1 /* 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @summary Utility routines that wait for a window to be displayed or for 26 colors to be visible 27 * @summary com.apple.junit.utils 28 */ 29 package test.java.awt.regtesthelpers; 30 31 import java.awt.*; 32 import java.awt.event.*; 33 34 //import junit.framework.Assert; 35 public class VisibilityValidator { 36 37 // Wait up to five seconds for our window events 38 static final int SETUP_PERIOD = 5000; 39 static final boolean DEBUG = false; 40 41 volatile Window win = null; 42 boolean activated = false; 43 boolean opened = false; 44 boolean focused = false; 45 volatile boolean valid = false; 46 47 // 48 // Utility functions that encapsulates normal usage patterns 49 // 50 public static void setVisibleAndConfirm(Frame testframe) throws Exception { 51 setVisibleAndConfirm(testframe, "Could not confirm test frame was " 52 + "visible"); 53 } 54 55 public static void setVisibleAndConfirm(Frame testframe, String msg) 56 throws Exception { 57 if (testframe.isVisible()) { 58 throw new RuntimeException("Frame is already visible"); 59 } 60 61 VisibilityValidator checkpoint = new VisibilityValidator(testframe); 62 testframe.setVisible(true); 63 checkpoint.requireVisible(); 64 if (!checkpoint.isValid()) { 65 //System.err.println(msg); 66 throw new Exception("Frame not visible after " + SETUP_PERIOD 67 + " milliseconds"); 68 } 69 } 70 71 // 72 // Add listeners to the window 73 // 74 public VisibilityValidator(Window win) { 75 this.win = win; 76 WindowAdapter watcher = new WindowAdapter() { 77 public void windowOpened(WindowEvent e) { 78 doOpen(); 79 } 80 81 public void windowActivated(WindowEvent e) { 82 doActivate(); 83 } 84 85 public void windowGainedFocus(WindowEvent e) { 86 doGainedFocus(); 87 } 88 }; 89 90 win.addWindowListener(watcher); 91 win.addWindowFocusListener(watcher); 92 } 93 94 // Make the window visible 95 // 96 // The only way to make it through this routine is for the window to 97 // generate BOTH a windowOpened, a windowActivated event and a 98 // windowGainedFocus, or to timeout. 99 // 100 synchronized public void requireVisible() { 101 int tries = 0; 102 103 // wait for windowOpened and windowActivated events 104 try { 105 while ((opened == false) 106 || (activated == false) 107 || (focused == false)) { 108 if (tries < 4) { 109 tries += 1; 110 wait(SETUP_PERIOD); 111 } else { 112 break; 113 } 114 } 115 116 if (opened && activated) { 117 valid = true; 118 } else { 119 valid = false; 120 } 121 } catch (InterruptedException ix) { 122 valid = false; 123 } 124 125 // Extra-super paranoid checks 126 if (win.isVisible() == false) { 127 valid = false; 128 } 129 130 if (win.isShowing() == false) { 131 valid = false; 132 } 133 134 if (win.isFocused() == false) { 135 valid = false; 136 } 137 138 if (DEBUG) { 139 if (!isValid()) { 140 System.out.println("\tactivated:" + new Boolean(activated)); 141 System.out.println("\topened:" + new Boolean(opened)); 142 System.out.println("\tfocused:" + new Boolean(focused)); 143 System.out.println("\tvalid:" + new Boolean(valid)); 144 System.out.println("\tisVisible():" 145 + new Boolean(win.isVisible())); 146 System.out.println("\tisShowing():" 147 + new Boolean(win.isShowing())); 148 System.out.println("\tisFocused():" 149 + new Boolean(win.isFocused())); 150 } 151 } 152 153 } 154 155 synchronized void doOpen() { 156 opened = true; 157 notify(); 158 } 159 160 synchronized void doActivate() { 161 activated = true; 162 notify(); 163 } 164 165 synchronized void doGainedFocus() { 166 focused = true; 167 notify(); 168 } 169 170 public boolean isValid() { 171 return valid; 172 } 173 174 public boolean isClear() { 175 return valid; 176 } 177 178 volatile static Robot robot = null; 179 180 // utility function that waits until a Component is shown with the 181 // appropriate color 182 public static boolean waitForColor(Component c, 183 Color expected) throws AWTException, 184 InterruptedException { 185 Dimension dim = c.getSize(); 186 int xOff = dim.width / 2; 187 int yOff = dim.height / 2; 188 return waitForColor(c, xOff, yOff, expected); 189 } 190 191 // utility function that waits for 5 seconds for Component to be shown with 192 // the appropriate color 193 public static boolean waitForColor(Component c, 194 int xOff, 195 int yOff, 196 Color expected) throws AWTException, InterruptedException { 197 return waitForColor(c, xOff, yOff, expected, 5000L); 198 } 199 200 // utility function that waits until a Component is up with the appropriate 201 // color 202 public static boolean waitForColor(Component c, 203 int xOff, 204 int yOff, 205 Color expected, 206 long timeout) throws AWTException, InterruptedException { 207 Point p = c.getLocationOnScreen(); 208 int x = (int) p.getX() + xOff; 209 int y = (int) p.getY() + yOff; 210 return waitForColor(x, y, expected, timeout); 211 } 212 213 // utility function that waits until specific screen coords have the 214 // appropriate color 215 public static boolean waitForColor(int locX, 216 int locY, 217 Color expected, 218 long timeout) throws AWTException, InterruptedException { 219 if (robot == null) { 220 robot = new Robot(); 221 } 222 223 long endtime = System.currentTimeMillis() + timeout; 224 while (endtime > System.currentTimeMillis()) { 225 if (colorMatch(robot.getPixelColor(locX, locY), expected)) { 226 return true; 227 } 228 Thread.sleep(50); 229 } 230 231 return false; 232 } 233 234 // utility function that asserts that two colors are similar to each other 235 public static void assertColorEquals(final String message, 236 final Color actual, 237 final Color expected) { 238 System.out.println("actual color: " + actual); 239 System.out.println("expect color: " + expected); 240 //Assert.assertTrue(message, colorMatch(actual, expected)); 241 } 242 243 // determines if two colors are close in hue and brightness 244 public static boolean colorMatch(final Color actual, final Color expected) { 245 final float[] actualHSB = getHSB(actual); 246 final float[] expectedHSB = getHSB(expected); 247 248 final float actualHue = actualHSB[0]; 249 final float expectedHue = expectedHSB[0]; 250 final boolean hueMatched = closeMatchHue(actualHue, expectedHue, 0.17f); 251 //System.out.println("hueMatched? " + hueMatched); 252 final float actualBrightness = actualHSB[2]; 253 final float expectedBrightness = expectedHSB[2]; 254 final boolean brightnessMatched = closeMatch(actualBrightness, 255 expectedBrightness, 0.15f); 256 //System.out.println("brightnessMatched? " + brightnessMatched); 257 258 // check to see if the brightness was so low or so high that the hue 259 // got clamped to red 260 if (brightnessMatched && !hueMatched) { 261 return (expectedBrightness < 0.15f); 262 } 263 264 return brightnessMatched && hueMatched; 265 } 266 267 static float[] getHSB(final Color color) { 268 final float[] hsb = new float[3]; 269 Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsb); 270 return hsb; 271 } 272 273 // matches hues from 0.0 to 1.0, accounting for wrap-around at the 1.0/0.0 274 // boundry 275 static boolean closeMatchHue(final float actual, 276 final float expected, 277 final float tolerance) { 278 if (closeMatch(actual, expected, tolerance)) { 279 return true; 280 } 281 282 // all that remains is the overflow and underflow cases 283 final float expectedHigh = expected + tolerance; 284 final float expectedLow = expected - tolerance; 285 286 if (expectedHigh > 1.0f) { 287 // expected is too high, and actual was too low 288 //System.out.println("\thue expected too high, actual too low"); 289 return closeMatch(actual + 0.5f, expected - 0.5f, tolerance); 290 } 291 292 if (expectedLow < 0.0f) { 293 // expected is too low, and actual was too high 294 //System.out.println("\thue expected too low, actual too high"); 295 return closeMatch(actual - 0.5f, expected + 0.5f, tolerance); 296 } 297 298 //System.out.println("\tcloseMatchHue? " + false); 299 return false; 300 } 301 302 static boolean closeMatch(final float actual, 303 final float expected, 304 final float tolerance) { 305 return (expected + tolerance) > actual && (expected - tolerance) < actual; 306 } 307 }