8225790: Two NestedDialogs tests fail on Ubuntu

Reviewed-by: serb
This commit is contained in:
Pankaj Bansal 2020-10-20 09:05:51 +00:00
parent 017d151e11
commit 21e67e5460
4 changed files with 177 additions and 706 deletions
test/jdk/java/awt

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,15 +23,10 @@
/**
* @test
* @bug 8155740
* @bug 8160266 8225790
* @key headful
* @summary See <rdar://problem/3429130>: Events: actionPerformed() method not
* called when it is button is clicked (system load related)
* @summary com.apple.junit.java.awt.Frame
* @library ../../../regtesthelpers
* @build VisibilityValidator
* @build Util
* @build Waypoint
* @run main NestedModalDialogTest
*/
@ -44,140 +39,103 @@
//////////////////////////////////////////////////////////////////////////////
// classes necessary for this test
import java.awt.*;
import java.awt.event.*;
import java.util.Enumeration;
import test.java.awt.regtesthelpers.Waypoint;
import test.java.awt.regtesthelpers.VisibilityValidator;
import test.java.awt.regtesthelpers.Util;
import java.awt.Button;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.GridBagLayout;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
public class NestedModalDialogTest {
Waypoint[] event_checkpoint = new Waypoint[3];
VisibilityValidator[] win_checkpoint = new VisibilityValidator[2];
IntermediateDialog interDiag;
TextDialog txtDiag;
private static Frame frame;
private static IntermediateDialog interDiag;
private static TextDialog txtDiag;
// Global variables so the robot thread can locate things.
Button[] robot_button = new Button[2];
TextField robot_text = null;
static Robot _robot = null;
private static Button[] robot_button = new Button[2];
private static TextField robot_text = null;
private static Robot robot = null;
/*
* @throws InterruptedException
* @throws WaypointException
*/
public void testModalDialogs() throws Exception {
Frame frame = null;
String result = "";
Robot robot = getRobot();
event_checkpoint[0] = new Waypoint(); // "-Launch 1-"
event_checkpoint[1] = new Waypoint(); // "-Launch 2-"
// Thread.currentThread().setName("NestedModalDialogTest Thread");
// launch first frame with firstButton
frame = new StartFrame();
VisibilityValidator.setVisibleAndConfirm(frame);
Util.clickOnComp(robot_button[0], robot);
// Dialog must be created and onscreen before we proceed.
// The event_checkpoint waits for the Dialog to be created.
// The win_checkpoint waits for the Dialog to be visible.
event_checkpoint[0].requireClear("TestFrame actionPerformed() never "
+ "called, see <rdar://problem/3429130>");
win_checkpoint[0].requireVisible();
Util.clickOnComp(robot_button[1], robot);
// Again, the Dialog must be created and onscreen before we proceed.
// The event_checkpoint waits for the Dialog to be created.
// The win_checkpoint waits for the Dialog to be visible.
event_checkpoint[1].requireClear("IntermediateDialog actionPerformed() "
+ "never called, see <rdar://problem/3429130>");
win_checkpoint[1].requireVisible();
Util.clickOnComp(robot_text, robot);
// I'm really not sure whether the click is needed for focus
// but since it's asynchronous, as is the actually gaining of focus
// we might as well do our best
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
}
});
} catch (Exception e) {
}
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_H);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_H);
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_E);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_E);
robot.keyPress(KeyEvent.VK_L);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_L);
robot.keyPress(KeyEvent.VK_L);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_L);
robot.keyPress(KeyEvent.VK_O);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_O);
//
// NOTE THAT WE MAY HAVE MORE SYNCHRONIZATION WORK TO DO HERE.
// CURRENTLY THERE IS NO GUARANTEE THAT THE KEYEVENT THAT THAT
// TYPES THE 'O' HAS BEEN PROCESSED BEFORE WE GET THE RESULT
//
// This is a (lame) attempt at waiting for the last typeKey events to
// propagate. It's not quite right because robot uses
// CGRemoteOperations, which are asynchronous. But that's why I put in
// the pause
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
}
});
} catch (Exception e) {
}
// Need to call this before the dialog that robot_text is in is disposed
result = robot_text.getText();
Thread.sleep(50); // shouldn't need this, but pause adds stability
// Click Close box of modal dialog with textField
Util.clickOnComp(txtDiag, robot);
Thread.sleep(50); // shouldn't need this, but pause adds stability
// Click Close box of intermediate modal dialog
Util.clickOnComp(interDiag, robot);
Thread.sleep(50); // shouldn't need this, but pause adds stability
// Click Close box of intermediate modal dialog
Util.clickOnComp(frame, robot);
String expected = "Hello";
}
private static Robot getRobot() {
if (_robot == null) {
private static void blockTillDisplayed(Component comp) {
Point p = null;
while (p == null) {
try {
_robot = new Robot();
} catch (AWTException e) {
throw new RuntimeException("Robot creation failed");
p = comp.getLocationOnScreen();
} catch (IllegalStateException e) {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
private static void clickOnComp(Component comp) {
Rectangle bounds = new Rectangle(comp.getLocationOnScreen(), comp.getSize());
robot.mouseMove(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
robot.waitForIdle();
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.waitForIdle();
}
public void testModalDialogs() throws Exception {
try {
robot = new Robot();
robot.setAutoDelay(100);
// launch first frame with firstButton
frame = new StartFrame();
blockTillDisplayed(frame);
clickOnComp(robot_button[0]);
// Dialog must be created and onscreen before we proceed.
blockTillDisplayed(interDiag);
clickOnComp(robot_button[1]);
// Again, the Dialog must be created and onscreen before we proceed.
blockTillDisplayed(robot_text);
clickOnComp(robot_text);
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_H);
robot.keyRelease(KeyEvent.VK_H);
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_E);
robot.keyRelease(KeyEvent.VK_E);
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_L);
robot.keyRelease(KeyEvent.VK_L);
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_L);
robot.keyRelease(KeyEvent.VK_L);
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_O);
robot.keyRelease(KeyEvent.VK_O);
robot.waitForIdle();
} finally {
if (frame != null) {
frame.dispose();
}
if (interDiag != null) {
interDiag.dispose();
}
if (txtDiag != null) {
txtDiag.dispose();
}
}
return _robot;
}
//////////////////// Start Frame ///////////////////
@ -198,26 +156,19 @@ public class NestedModalDialogTest {
but.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
interDiag = new IntermediateDialog(StartFrame.this);
win_checkpoint[0] = new VisibilityValidator(interDiag);
interDiag.setSize(300, 200);
// may need listener to watch this move.
interDiag.setLocation(getLocationOnScreen());
interDiag.pack();
event_checkpoint[0].clear();
interDiag.setVisible(true);
}
});
Panel pan = new Panel();
pan.add(but);
add(pan);
setVisible(true);
robot_button[0] = but;
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
}
});
}
}
@ -234,9 +185,7 @@ public class NestedModalDialogTest {
but.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtDiag = new TextDialog(m_parent);
win_checkpoint[1] = new VisibilityValidator(txtDiag);
txtDiag.setSize(300, 100);
event_checkpoint[1].clear();
txtDiag.setVisible(true);
}
});
@ -244,12 +193,6 @@ public class NestedModalDialogTest {
pan.add(but);
add(pan);
pack();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
}
});
// The robot needs to know about us, so set global
robot_button[1] = but;
@ -266,12 +209,6 @@ public class NestedModalDialogTest {
pan.add(txt);
add(pan);
pack();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
}
});
// The robot needs to know about us, so set global
robot_text = txt;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,16 +23,11 @@
/**
* @test
* @bug 8155740
* @bug 8160266 8225790
* @key headful
* @summary See <rdar://problem/3429130>: Events: actionPerformed() method not
* called when it is button is clicked (system load related)
* @summary com.apple.junit.java.awt.Frame
* @library ../../../regtesthelpers
* @build VisibilityValidator
* @build Util
* @build Waypoint
* @run main NestedModelessDialogTest -Xlog:exception
* @run main NestedModelessDialogTest
*/
/////////////////////////////////////////////////////////////////////////////
@ -43,26 +38,53 @@
// are successfully able to write into this Nested Modeless Dialog
/////////////////////////////////////////////////////////////////////////////
// classes necessary for this test
import java.awt.*;
import java.awt.event.*;
import java.util.Enumeration;
import test.java.awt.regtesthelpers.Util;
import test.java.awt.regtesthelpers.VisibilityValidator;
import test.java.awt.regtesthelpers.Waypoint;
import java.awt.Button;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.GridBagLayout;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
public class NestedModelessDialogTest {
Waypoint[] event_checkpoint = new Waypoint[3];
VisibilityValidator[] win_checkpoint = new VisibilityValidator[2];
IntermediateDialog interDiag;
TextDialog txtDiag;
private static Frame frame;
private static IntermediateDialog interDiag;
private static TextDialog txtDiag;
// Global variables so the robot thread can locate things.
Button[] robot_button = new Button[2];
TextField robot_text = null;
static Robot _robot = null;
private static Button[] robot_button = new Button[2];
private static TextField robot_text = null;
private static Robot robot;
private static void blockTillDisplayed(Component comp) {
Point p = null;
while (p == null) {
try {
p = comp.getLocationOnScreen();
} catch (IllegalStateException e) {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
private static void clickOnComp(Component comp) {
Rectangle bounds = new Rectangle(comp.getLocationOnScreen(), comp.getSize());
robot.mouseMove(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
robot.waitForIdle();
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.waitForIdle();
}
/**
* Get called by test harness
@ -70,111 +92,56 @@ public class NestedModelessDialogTest {
* @throws Exception
*/
public void testModelessDialogs() throws Exception {
Frame frame = null;
String result = "";
Robot robot = getRobot();
event_checkpoint[0] = new Waypoint(); // "-Launch 1-"
event_checkpoint[1] = new Waypoint(); // "-Launch 2-"
// launch first frame with fistButton
frame = new StartFrame();
VisibilityValidator.setVisibleAndConfirm(frame);
Util.clickOnComp(robot_button[0], robot);
// Dialog must be created and onscreen before we proceed.
// The event_checkpoint waits for the Dialog to be created.
// The win_checkpoint waits for the Dialog to be visible.
event_checkpoint[0].requireClear();
win_checkpoint[0].requireVisible();
Util.clickOnComp(robot_button[1], robot);
// Again, the Dialog must be created and onscreen before we proceed.
// The event_checkpoint waits for the Dialog to be created.
// The win_checkpoint waits for the Dialog to be visible.
event_checkpoint[1].requireClear();
win_checkpoint[1].requireVisible();
Util.clickOnComp(robot_text, robot);
// I'm really not sure whether the click is needed for focus
// but since it's asynchronous, as is the actually gaining of focus
// we might as well do our best
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
}
});
} catch (Exception e) {
}
robot = new Robot();
robot.setAutoDelay(100);
robot.keyPress(KeyEvent.VK_SHIFT);
// launch first frame with fistButton
frame = new StartFrame();
robot.waitForIdle();
blockTillDisplayed(frame);
clickOnComp(robot_button[0]);
robot.keyPress(KeyEvent.VK_H);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_H);
// Dialog must be created and onscreen before we proceed.
blockTillDisplayed(interDiag);
clickOnComp(robot_button[1]);
robot.keyRelease(KeyEvent.VK_SHIFT);
// Again, the Dialog must be created and onscreen before we proceed.
blockTillDisplayed(robot_text);
clickOnComp(robot_text);
robot.keyPress(KeyEvent.VK_E);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_E);
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_H);
robot.keyRelease(KeyEvent.VK_H);
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_L);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_L);
robot.keyPress(KeyEvent.VK_E);
robot.keyRelease(KeyEvent.VK_E);
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_L);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_L);
robot.keyPress(KeyEvent.VK_L);
robot.keyRelease(KeyEvent.VK_L);
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_O);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_O);
robot.keyPress(KeyEvent.VK_L);
robot.keyRelease(KeyEvent.VK_L);
robot.waitForIdle();
//
// NOTE THAT WE MAY HAVE MORE SYNCHRONIZATION WORK TO DO HERE.
// CURRENTLY THERE IS NO GUARANTEE THAT THE KEYEVENT THAT THAT
// TYPES THE 'O' HAS BEEN PROCESSED BEFORE WE GET THE RESULT
//
// This is a (lame) attempt at waiting for the last typeKey events to
// propagate. It's not quite right because robot uses
// CGRemoteOperations, which are asynchronous. But that's why I put in
// the Thread.sleep
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
}
});
} catch (Exception e) {
}
// Need to call this before the dialog that robot_text is in is disposed
result = robot_text.getText();
Thread.sleep(50); // Thread.sleep adds stability
// Click Close box of modeless dialog with textField
Util.clickOnComp(txtDiag, robot);
Thread.sleep(50); // Thread.sleep adds stability
// Click Close box of intermediate modal dialog
Util.clickOnComp(interDiag, robot);
Thread.sleep(50); // Thread.sleep adds stability
// Click Close box of intermediate modal dialog
Util.clickOnComp(frame, robot);
String expected = "Hello";
}
private static Robot getRobot() {
if (_robot == null) {
try {
_robot = new Robot();
} catch (AWTException e) {
throw new RuntimeException("Robot creation failed");
robot.keyPress(KeyEvent.VK_O);
robot.keyRelease(KeyEvent.VK_O);
robot.waitForIdle();
} finally {
if (frame != null) {
frame.dispose();
}
if (interDiag != null) {
interDiag.dispose();
}
if (txtDiag != null) {
txtDiag.dispose();
}
}
return _robot;
}
//////////////////// Start Frame ///////////////////
@ -195,26 +162,19 @@ public class NestedModelessDialogTest {
but.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
interDiag = new IntermediateDialog(StartFrame.this);
win_checkpoint[0] = new VisibilityValidator(interDiag);
interDiag.setSize(300, 200);
// may need listener to watch this move.
interDiag.setLocation(getLocationOnScreen());
interDiag.pack();
event_checkpoint[0].clear();
interDiag.setVisible(true);
}
});
Panel pan = new Panel();
pan.add(but);
add(pan);
setVisible(true);
robot_button[0] = but;
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
}
});
}
}
@ -231,9 +191,7 @@ public class NestedModelessDialogTest {
but.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtDiag = new TextDialog(m_parent);
win_checkpoint[1] = new VisibilityValidator(txtDiag);
txtDiag.setSize(300, 100);
event_checkpoint[1].clear();
txtDiag.setVisible(true);
}
});
@ -241,12 +199,6 @@ public class NestedModelessDialogTest {
pan.add(but);
add(pan);
pack();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
}
});
// The robot needs to know about us, so set global
robot_button[1] = but;
@ -263,12 +215,6 @@ public class NestedModelessDialogTest {
pan.add(txt);
add(pan);
pack();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
}
});
// The robot needs to know about us, so set global
robot_text = txt;

@ -1,307 +0,0 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @summary Utility routines that wait for a window to be displayed or for
colors to be visible
* @summary com.apple.junit.utils
*/
package test.java.awt.regtesthelpers;
import java.awt.*;
import java.awt.event.*;
//import junit.framework.Assert;
public class VisibilityValidator {
// Wait up to five seconds for our window events
static final int SETUP_PERIOD = 5000;
static final boolean DEBUG = false;
volatile Window win = null;
boolean activated = false;
boolean opened = false;
boolean focused = false;
volatile boolean valid = false;
//
// Utility functions that encapsulates normal usage patterns
//
public static void setVisibleAndConfirm(Frame testframe) throws Exception {
setVisibleAndConfirm(testframe, "Could not confirm test frame was "
+ "visible");
}
public static void setVisibleAndConfirm(Frame testframe, String msg)
throws Exception {
if (testframe.isVisible()) {
throw new RuntimeException("Frame is already visible");
}
VisibilityValidator checkpoint = new VisibilityValidator(testframe);
testframe.setVisible(true);
checkpoint.requireVisible();
if (!checkpoint.isValid()) {
//System.err.println(msg);
throw new Exception("Frame not visible after " + SETUP_PERIOD
+ " milliseconds");
}
}
//
// Add listeners to the window
//
public VisibilityValidator(Window win) {
this.win = win;
WindowAdapter watcher = new WindowAdapter() {
public void windowOpened(WindowEvent e) {
doOpen();
}
public void windowActivated(WindowEvent e) {
doActivate();
}
public void windowGainedFocus(WindowEvent e) {
doGainedFocus();
}
};
win.addWindowListener(watcher);
win.addWindowFocusListener(watcher);
}
// Make the window visible
//
// The only way to make it through this routine is for the window to
// generate BOTH a windowOpened, a windowActivated event and a
// windowGainedFocus, or to timeout.
//
synchronized public void requireVisible() {
int tries = 0;
// wait for windowOpened and windowActivated events
try {
while ((opened == false)
|| (activated == false)
|| (focused == false)) {
if (tries < 4) {
tries += 1;
wait(SETUP_PERIOD);
} else {
break;
}
}
if (opened && activated) {
valid = true;
} else {
valid = false;
}
} catch (InterruptedException ix) {
valid = false;
}
// Extra-super paranoid checks
if (win.isVisible() == false) {
valid = false;
}
if (win.isShowing() == false) {
valid = false;
}
if (win.isFocused() == false) {
valid = false;
}
if (DEBUG) {
if (!isValid()) {
System.out.println("\tactivated:" + new Boolean(activated));
System.out.println("\topened:" + new Boolean(opened));
System.out.println("\tfocused:" + new Boolean(focused));
System.out.println("\tvalid:" + new Boolean(valid));
System.out.println("\tisVisible():"
+ new Boolean(win.isVisible()));
System.out.println("\tisShowing():"
+ new Boolean(win.isShowing()));
System.out.println("\tisFocused():"
+ new Boolean(win.isFocused()));
}
}
}
synchronized void doOpen() {
opened = true;
notify();
}
synchronized void doActivate() {
activated = true;
notify();
}
synchronized void doGainedFocus() {
focused = true;
notify();
}
public boolean isValid() {
return valid;
}
public boolean isClear() {
return valid;
}
volatile static Robot robot = null;
// utility function that waits until a Component is shown with the
// appropriate color
public static boolean waitForColor(Component c,
Color expected) throws AWTException,
InterruptedException {
Dimension dim = c.getSize();
int xOff = dim.width / 2;
int yOff = dim.height / 2;
return waitForColor(c, xOff, yOff, expected);
}
// utility function that waits for 5 seconds for Component to be shown with
// the appropriate color
public static boolean waitForColor(Component c,
int xOff,
int yOff,
Color expected) throws AWTException, InterruptedException {
return waitForColor(c, xOff, yOff, expected, 5000L);
}
// utility function that waits until a Component is up with the appropriate
// color
public static boolean waitForColor(Component c,
int xOff,
int yOff,
Color expected,
long timeout) throws AWTException, InterruptedException {
Point p = c.getLocationOnScreen();
int x = (int) p.getX() + xOff;
int y = (int) p.getY() + yOff;
return waitForColor(x, y, expected, timeout);
}
// utility function that waits until specific screen coords have the
// appropriate color
public static boolean waitForColor(int locX,
int locY,
Color expected,
long timeout) throws AWTException, InterruptedException {
if (robot == null) {
robot = new Robot();
}
long endtime = System.currentTimeMillis() + timeout;
while (endtime > System.currentTimeMillis()) {
if (colorMatch(robot.getPixelColor(locX, locY), expected)) {
return true;
}
Thread.sleep(50);
}
return false;
}
// utility function that asserts that two colors are similar to each other
public static void assertColorEquals(final String message,
final Color actual,
final Color expected) {
System.out.println("actual color: " + actual);
System.out.println("expect color: " + expected);
//Assert.assertTrue(message, colorMatch(actual, expected));
}
// determines if two colors are close in hue and brightness
public static boolean colorMatch(final Color actual, final Color expected) {
final float[] actualHSB = getHSB(actual);
final float[] expectedHSB = getHSB(expected);
final float actualHue = actualHSB[0];
final float expectedHue = expectedHSB[0];
final boolean hueMatched = closeMatchHue(actualHue, expectedHue, 0.17f);
//System.out.println("hueMatched? " + hueMatched);
final float actualBrightness = actualHSB[2];
final float expectedBrightness = expectedHSB[2];
final boolean brightnessMatched = closeMatch(actualBrightness,
expectedBrightness, 0.15f);
//System.out.println("brightnessMatched? " + brightnessMatched);
// check to see if the brightness was so low or so high that the hue
// got clamped to red
if (brightnessMatched && !hueMatched) {
return (expectedBrightness < 0.15f);
}
return brightnessMatched && hueMatched;
}
static float[] getHSB(final Color color) {
final float[] hsb = new float[3];
Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsb);
return hsb;
}
// matches hues from 0.0 to 1.0, accounting for wrap-around at the 1.0/0.0
// boundry
static boolean closeMatchHue(final float actual,
final float expected,
final float tolerance) {
if (closeMatch(actual, expected, tolerance)) {
return true;
}
// all that remains is the overflow and underflow cases
final float expectedHigh = expected + tolerance;
final float expectedLow = expected - tolerance;
if (expectedHigh > 1.0f) {
// expected is too high, and actual was too low
//System.out.println("\thue expected too high, actual too low");
return closeMatch(actual + 0.5f, expected - 0.5f, tolerance);
}
if (expectedLow < 0.0f) {
// expected is too low, and actual was too high
//System.out.println("\thue expected too low, actual too high");
return closeMatch(actual - 0.5f, expected + 0.5f, tolerance);
}
//System.out.println("\tcloseMatchHue? " + false);
return false;
}
static boolean closeMatch(final float actual,
final float expected,
final float tolerance) {
return (expected + tolerance) > actual && (expected - tolerance) < actual;
}
}

@ -1,105 +0,0 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @summary This is a utility for coordinating the flow of events on different
threads.
* @summary com.apple.junit.utils
*/
package test.java.awt.regtesthelpers;
public class Waypoint {
static final String MSG = "Waypoint timed out";
// Wait up to five seconds for our clear() to be called
static final int TIMEOUT = 5000;
boolean clear = false;
public Waypoint() {
}
//
// Pause for either TIMEOUT millis or until clear() is called
//
synchronized public void requireClear() throws RuntimeException {
requireClear(MSG, TIMEOUT);
}
synchronized public void requireClear(long timeout)
throws RuntimeException {
requireClear(MSG, timeout);
}
synchronized public void requireClear(String timeOutMsg)
throws RuntimeException {
requireClear(timeOutMsg, TIMEOUT);
}
synchronized public void requireClear(String timeOutMsg, long timeout)
throws RuntimeException {
long endtime = System.currentTimeMillis() + timeout;
try {
while (isClear() == false) {
if (System.currentTimeMillis() < endtime) {
wait(200);
} else {
break;
}
}
if (!isClear()) {
throw new RuntimeException(timeOutMsg);
}
} catch (InterruptedException ix) {
}
}
//
// Called when it is valid to procede past the waypoint
//
synchronized public void clear() {
clear = true;
notify();
}
//
// Should be checked after a call to requireClear() to make
// sure that we did not time out.
//
synchronized public boolean isClear() {
return clear;
}
synchronized public boolean isValid() {
return clear;
}
//
// For re-use of a waypoint. Be careful.
//
synchronized public void reset() {
clear = false;
}
}