1 /* 2 * Copyright (c) 2014, 2015, 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 import java.awt.*; 25 import java.awt.event.*; 26 import java.awt.peer.ComponentPeer; 27 import java.lang.reflect.Constructor; 28 import java.lang.reflect.Field; 29 import java.lang.reflect.InvocationTargetException; 30 import java.lang.reflect.Method; 31 import java.util.ArrayList; 32 import javax.swing.*; 33 34 import sun.awt.EmbeddedFrame; 35 import java.io.*; 36 import test.java.awt.regtesthelpers.Util; 37 38 /** 39 * <p>This class provides basis for AWT Mixing testing. 40 * <p>It provides all standard test machinery and should be used by 41 * extending and overriding next methods: 42 * <li> {@link OverlappingTestBase#prepareControls()} - setup UI components 43 * <li> {@link OverlappingTestBase#performTest()} - run particular test 44 * Those methods would be run in the loop for each AWT component. 45 * <p>Current AWT component should be added to the tested UI by {@link OverlappingTestBase#propagateAWTControls(java.awt.Container) ()}. 46 * There AWT components are prepared to be tested as being overlayed by other (e.g. Swing) components - they are colored to 47 * {@link OverlappingTestBase#AWT_BACKGROUND_COLOR} and throws failure on catching mouse event. 48 * <p> Validation of component being overlayed should be tested by {@link OverlappingTestBase#clickAndBlink(java.awt.Robot, java.awt.Point) } 49 * See each method javadoc for more details. 50 * 51 * <p>Due to test machinery limitations all test should be run from their own main() by calling next coe 52 * <code> 53 * public static void main(String args[]) throws InterruptedException { 54 * instance = new YourTestInstance(); 55 * OverlappingTestBase.doMain(args); 56 * } 57 * </code> 58 * 59 * @author Sergey Grinev 60 */ 61 public abstract class OverlappingTestBase { 62 // working variables 63 private static volatile boolean wasHWClicked = false; 64 private static volatile boolean passed = true; 65 // constants 66 /** 67 * Default color for AWT component used for validate correct drawing of overlapping. <b>Never</b> use it for lightweight components. 68 */ 69 protected static final Color AWT_BACKGROUND_COLOR = new Color(21, 244, 54); 70 protected static Color AWT_VERIFY_COLOR = AWT_BACKGROUND_COLOR; 71 protected static final int ROBOT_DELAY = 500; 72 private static final String[] simpleAwtControls = {"Button", "Checkbox", "Label", "TextArea"}; 73 /** 74 * Generic strings array. To be used for population of List based controls. 75 */ 76 protected static final String[] petStrings = {"Bird", "Cat", "Dog", "Rabbit", "Rhynocephalia Granda", "Bear", "Tiger", "Mustang"}; 77 static Field peerField; 78 // "properties" 79 /** 80 * Tests customization. Set this variable to test only control from java.awt 81 * <p>Usage of this variable should be marked with CR being the reason. 82 * <p>Do not use this variable simultaneously with {@link OverlappingTestBase#skipClassNames} 83 */ 84 protected String onlyClassName = null; 85 /** 86 * For customizing tests. List classes' simple names to skip them from testings. 87 * <p>Usage of this variable should be marked with CR being the reason. 88 */ 89 protected String[] skipClassNames = null; 90 /** 91 * Set to false to avoid event delivery validation 92 * @see OverlappingTestBase#clickAndBlink(java.awt.Robot, java.awt.Point, boolean) 93 */ 94 protected boolean useClickValidation = true; 95 /** 96 * Set to false if test doesn't supposed to verify EmbeddedFrame 97 */ 98 protected boolean testEmbeddedFrame = false; 99 /** 100 * Set this variable to true if testing embedded frame is impossible (on Mac, for instance, for now). 101 * The testEmbeddedFrame is explicitly set to true in dozen places. 102 */ 103 protected boolean skipTestingEmbeddedFrame = false; 104 105 public static final boolean isMac = System.getProperty("os.name").toLowerCase().contains("os x"); 106 private boolean isFrameBorderCalculated; 107 private int borderShift; 108 109 { if (Toolkit.getDefaultToolkit().getClass().getName().matches(".*L.*Toolkit")) { 110 // No EmbeddedFrame in LWToolkit/LWCToolkit, yet 111 // And it should be programmed some other way, too, in any case 112 System.err.println("skipTestingEmbeddedFrame"); 113 skipTestingEmbeddedFrame = true; 114 }else { 115 System.err.println("do not skipTestingEmbeddedFrame"); 116 } 117 } 118 119 protected int frameBorderCounter() { 120 if (!isFrameBorderCalculated) { 121 try { 122 new FrameBorderCounter(); // force compilation by jtreg 123 String JAVA_HOME = System.getProperty("java.home"); 124 Process p = Runtime.getRuntime().exec(JAVA_HOME + "/bin/java FrameBorderCounter"); 125 try { 126 p.waitFor(); 127 } catch (InterruptedException e) { 128 e.printStackTrace(); 129 throw new RuntimeException(e); 130 } 131 if (p.exitValue() != 0) { 132 throw new RuntimeException("FrameBorderCounter exited with not null code!\n" + readInputStream(p.getErrorStream())); 133 } 134 borderShift = Integer.parseInt(readInputStream(p.getInputStream()).trim()); 135 isFrameBorderCalculated = true; 136 } catch (IOException e) { 137 e.printStackTrace(); 138 throw new RuntimeException("Problem calculating a native border size"); 139 } 140 } 141 return borderShift; 142 } 143 144 public void getVerifyColor() { 145 try { 146 final int size = 200; 147 final Point[] p = new Point[1]; 148 SwingUtilities.invokeAndWait(new Runnable() { 149 public void run(){ 150 JFrame frame = new JFrame("set back"); 151 frame.getContentPane().setBackground(AWT_BACKGROUND_COLOR); 152 frame.setSize(size, size); 153 frame.setUndecorated(true); 154 frame.setVisible(true); 155 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 156 p[0] = frame.getLocation(); 157 } 158 }); 159 Robot robot = new Robot(); 160 robot.waitForIdle(); 161 Thread.sleep(ROBOT_DELAY); 162 AWT_VERIFY_COLOR = robot.getPixelColor(p[0].x+size/2, p[0].y+size/2); 163 System.out.println("Color will be compared with " + AWT_VERIFY_COLOR + " instead of " + AWT_BACKGROUND_COLOR); 164 } catch (Exception e) { 165 System.err.println("Cannot get verify color: "+e.getMessage()); 166 } 167 } 168 169 private String readInputStream(InputStream is) throws IOException { 170 byte[] buffer = new byte[4096]; 171 int len = 0; 172 StringBuilder sb = new StringBuilder(); 173 try (InputStreamReader isr = new InputStreamReader(is)) { 174 while ((len = is.read(buffer)) > 0) { 175 sb.append(new String(buffer, 0, len)); 176 } 177 } 178 return sb.toString(); 179 } 180 181 private void setupControl(final Component control) { 182 if (useClickValidation) { 183 control.addMouseListener(new MouseAdapter() { 184 @Override 185 public void mouseClicked(MouseEvent e) { 186 System.err.println("ERROR: " + control.getClass() + " received mouse click."); 187 wasHWClicked = true; 188 } 189 }); 190 } 191 control.setBackground(AWT_BACKGROUND_COLOR); 192 control.setForeground(AWT_BACKGROUND_COLOR); 193 control.setPreferredSize(new Dimension(150, 150)); 194 control.setFocusable(false); 195 } 196 197 private void addAwtControl(java.util.List<Component> container, final Component control) { 198 String simpleName = control.getClass().getSimpleName(); 199 if (onlyClassName != null && !simpleName.equals(onlyClassName)) { 200 return; 201 } 202 if (skipClassNames != null) { 203 for (String skipMe : skipClassNames) { 204 if (simpleName.equals(skipMe)) { 205 return; 206 } 207 } 208 } 209 setupControl(control); 210 container.add(control); 211 } 212 213 private void addSimpleAwtControl(java.util.List<Component> container, String className) { 214 try { 215 Class definition = Class.forName("java.awt." + className); 216 Constructor constructor = definition.getConstructor(new Class[]{String.class}); 217 java.awt.Component component = (java.awt.Component) constructor.newInstance(new Object[]{"AWT Component " + className}); 218 addAwtControl(container, component); 219 } catch (Exception ex) { 220 System.err.println(ex.getMessage()); 221 fail("Setup error, this jdk doesn't have awt conrol " + className); 222 } 223 } 224 225 /** 226 * Adds current AWT control to container 227 * <p>N.B.: if testEmbeddedFrame == true this method will also add EmbeddedFrame over Canvas 228 * and it should be called <b>after</b> Frame.setVisible(true) call 229 * @param container container to hold AWT component 230 */ 231 protected final void propagateAWTControls(Container container) { 232 if (currentAwtControl != null) { 233 container.add(currentAwtControl); 234 } else { // embedded frame 235 try { 236 237 //create embedder 238 Canvas embedder = new Canvas(); 239 embedder.setBackground(Color.RED); 240 embedder.setPreferredSize(new Dimension(150, 150)); 241 container.add(embedder); 242 container.setVisible(true); // create peer 243 244 long frameWindow = 0; 245 String getWindowMethodName = "getHWnd"; 246 if (Toolkit.getDefaultToolkit().getClass().getName().contains("XToolkit")) { 247 getWindowMethodName = "getWindow"; 248 } 249 ComponentPeer peer = (ComponentPeer) peerField.get(embedder); 250 // System.err.println("Peer: " + peer); 251 Method getWindowMethod = peer.getClass().getMethod(getWindowMethodName); 252 frameWindow = (Long) getWindowMethod.invoke(peer); 253 // System.err.println("frame peer ID: " + frameWindow); 254 255 String eframeClassName = "sun.awt.windows.WEmbeddedFrame"; 256 if (Toolkit.getDefaultToolkit().getClass().getName().contains("XToolkit")) { 257 eframeClassName = "sun.awt.X11.XEmbeddedFrame"; 258 } 259 Class eframeClass = Class.forName(eframeClassName); 260 Constructor eframeCtor = eframeClass.getConstructor(long.class); 261 EmbeddedFrame eframe = (EmbeddedFrame) eframeCtor.newInstance(frameWindow); 262 setupControl(eframe); 263 eframe.setSize(new Dimension(150, 150)); 264 eframe.setVisible(true); 265 // System.err.println(eframe.getSize()); 266 } catch (Exception ex) { 267 ex.printStackTrace(); 268 fail("Failed to instantiate EmbeddedFrame: " + ex.getMessage()); 269 } 270 } 271 } 272 private static final Font hugeFont = new Font("Arial", Font.BOLD, 70); 273 274 private java.util.List<Component> getAWTControls() { 275 java.util.List<Component> components = new ArrayList<Component>(); 276 277 for (String clazz : simpleAwtControls) { 278 addSimpleAwtControl(components, clazz); 279 } 280 281 TextField tf = new TextField(); 282 tf.setFont(hugeFont); 283 addAwtControl(components, tf); 284 285 // more complex controls 286 Choice c = new Choice(); 287 for (int i = 0; i < petStrings.length; i++) { 288 c.add(petStrings[i]); 289 } 290 addAwtControl(components, c); 291 c.setPreferredSize(null); 292 c.setFont(hugeFont); // to make control bigger as setPrefferedSize don't do his job here 293 294 List l = new List(petStrings.length); 295 for (int i = 0; i < petStrings.length; i++) { 296 l.add(petStrings[i]); 297 } 298 addAwtControl(components, l); 299 300 Canvas canvas = new Canvas(); 301 canvas.setSize(100, 200); 302 addAwtControl(components, canvas); 303 304 Scrollbar sb = new Scrollbar(Scrollbar.VERTICAL, 500, 1, 0, 500); 305 addAwtControl(components, sb); 306 307 Scrollbar sb2 = new Scrollbar(Scrollbar.HORIZONTAL, 500, 1, 0, 500); 308 addAwtControl(components, sb2); 309 310 return components; 311 } 312 /** 313 * Default shift for {@link OverlappingTestBase#clickAndBlink(java.awt.Robot, java.awt.Point) } 314 */ 315 protected static Point shift = new Point(16, 16); 316 317 /** 318 * Verifies point using specified AWT Robot. Supposes <code>defaultShift == true</code> for {@link OverlappingTestBase#clickAndBlink(java.awt.Robot, java.awt.Point, boolean) }. 319 * This method is used to verify controls by providing just their plain screen coordinates. 320 * @param robot AWT Robot. Usually created by {@link Util#createRobot() } 321 * @param lLoc point to verify 322 * @see OverlappingTestBase#clickAndBlink(java.awt.Robot, java.awt.Point, boolean) 323 */ 324 protected void clickAndBlink(Robot robot, Point lLoc) { 325 clickAndBlink(robot, lLoc, true); 326 } 327 /** 328 * Default failure message for color check 329 * @see OverlappingTestBase#performTest() 330 */ 331 protected String failMessageColorCheck = "The LW component did not pass pixel color check and is overlapped"; 332 /** 333 * Default failure message event check 334 * @see OverlappingTestBase#performTest() 335 */ 336 protected String failMessage = "The LW component did not received the click."; 337 338 private static boolean isValidForPixelCheck(Component component) { 339 if ((component instanceof java.awt.Scrollbar) || isMac && (component instanceof java.awt.Button)) { 340 return false; 341 } 342 return true; 343 } 344 345 /** 346 * Preliminary validation - should be run <b>before</b> overlapping happens to ensure test is correct. 347 * @param robot AWT Robot. Usually created by {@link Util#createRobot() } 348 * @param lLoc point to validate to be <b>of</b> {@link OverlappingTestBase#AWT_BACKGROUND_COLOR} 349 * @param component tested component, should be pointed out as not all components are valid for pixel check. 350 */ 351 protected void pixelPreCheck(Robot robot, Point lLoc, Component component) { 352 if (isValidForPixelCheck(component)) { 353 int tries = 10; 354 Color c = null; 355 while (tries-- > 0) { 356 c = robot.getPixelColor(lLoc.x, lLoc.y); 357 System.out.println("Precheck. color: "+c+" compare with "+AWT_VERIFY_COLOR); 358 if (c.equals(AWT_VERIFY_COLOR)) { 359 return; 360 } 361 try { 362 Thread.sleep(100); 363 } catch (InterruptedException e) { 364 } 365 } 366 System.err.println(lLoc + ": " + c); 367 fail("Dropdown test setup failure, colored part of AWT component is not located at click area"); 368 } 369 } 370 371 /** 372 * Verifies point using specified AWT Robot. 373 * <p>Firstly, verifies point by color pixel check 374 * <p>Secondly, verifies event delivery by mouse click 375 * @param robot AWT Robot. Usually created by {@link Util#createRobot() } 376 * @param lLoc point to verify 377 * @param defaultShift if true verified position will be shifted by {@link OverlappingTestBase#shift }. 378 */ 379 protected void clickAndBlink(Robot robot, Point lLoc, boolean defaultShift) { 380 Point loc = lLoc.getLocation(); 381 //check color 382 Util.waitForIdle(robot); 383 try{ 384 Thread.sleep(500); 385 }catch(Exception exx){ 386 exx.printStackTrace(); 387 } 388 389 if (defaultShift) { 390 loc.translate(shift.x, shift.y); 391 } 392 if (!(System.getProperty("os.name").toLowerCase().contains("os x"))) { 393 Color c = robot.getPixelColor(loc.x, loc.y); 394 System.out.println("C&B. color: "+c+" compare with "+AWT_VERIFY_COLOR); 395 if (c.equals(AWT_VERIFY_COLOR)) { 396 fail(failMessageColorCheck); 397 passed = false; 398 } 399 400 // perform click 401 Util.waitForIdle(robot); 402 } 403 404 robot.mouseMove(loc.x, loc.y); 405 406 robot.mousePress(InputEvent.BUTTON1_MASK); 407 robot.mouseRelease(InputEvent.BUTTON1_MASK); 408 Util.waitForIdle(robot); 409 } 410 411 /** 412 * This method should be overriden with code which setups UI for testing. 413 * Code in this method <b>will</b> be called only from AWT thread so Swing operations can be called directly. 414 * 415 * @see {@link OverlappingTestBase#propagateAWTControls(java.awt.Container) } for instructions about adding tested AWT control to UI 416 */ 417 protected abstract void prepareControls(); 418 419 /** 420 * This method should be overriden with test execution. It will <b>not</b> be called from AWT thread so all Swing operations should be treated accordingly. 421 * @return true if test passed. Otherwise fail with default fail message. 422 * @see {@link OverlappingTestBase#failMessage} default fail message 423 */ 424 protected abstract boolean performTest(); 425 /** 426 * This method can be overriden with cleanup routines. It will be called from AWT thread so all Swing operations should be treated accordingly. 427 */ 428 protected void cleanup() { 429 // intentionally do nothing 430 } 431 /** 432 * Currect tested AWT Control. Usually shouldn't be accessed directly. 433 * 434 * @see {@link OverlappingTestBase#propagateAWTControls(java.awt.Container) } for instructions about adding tested AWT control to UI 435 */ 436 protected Component currentAwtControl; 437 438 private void testComponent(Component component) throws InterruptedException, InvocationTargetException { 439 Robot robot = null; 440 try { 441 robot = new Robot(); 442 }catch(Exception ignorex) { 443 } 444 currentAwtControl = component; 445 System.out.println("Testing " + currentAwtControl.getClass().getSimpleName()); 446 SwingUtilities.invokeAndWait(new Runnable() { 447 public void run() { 448 prepareControls(); 449 } 450 }); 451 if (component != null) { 452 Util.waitTillShown(component); 453 } 454 Util.waitForIdle(robot); 455 try { 456 Thread.sleep(500); // wait for graphic effects on systems like Win7 457 } catch (InterruptedException ex) { 458 } 459 if (!instance.performTest()) { 460 fail(failMessage); 461 passed = false; 462 } 463 SwingUtilities.invokeAndWait(new Runnable() { 464 public void run() { 465 cleanup(); 466 } 467 }); 468 } 469 470 private void testEmbeddedFrame() throws InvocationTargetException, InterruptedException { 471 Robot robot = null; 472 try { 473 robot = new Robot(); 474 }catch(Exception ignorex) { 475 } 476 System.out.println("Testing EmbeddedFrame"); 477 currentAwtControl = null; 478 SwingUtilities.invokeAndWait(new Runnable() { 479 public void run() { 480 prepareControls(); 481 } 482 }); 483 Util.waitForIdle(robot); 484 try { 485 Thread.sleep(500); // wait for graphic effects on systems like Win7 486 } catch (InterruptedException ex) { 487 } 488 if (!instance.performTest()) { 489 fail(failMessage); 490 passed = false; 491 } 492 SwingUtilities.invokeAndWait(new Runnable() { 493 public void run() { 494 cleanup(); 495 } 496 }); 497 } 498 499 private void testAwtControls() throws InterruptedException { 500 try { 501 for (Component component : getAWTControls()) { 502 testComponent(component); 503 } 504 if (testEmbeddedFrame && !skipTestingEmbeddedFrame) { 505 testEmbeddedFrame(); 506 } 507 } catch (InvocationTargetException ex) { 508 ex.printStackTrace(); 509 fail(ex.getMessage()); 510 } 511 } 512 /** 513 * Used by standard test machinery. See usage at {@link OverlappingTestBase } 514 */ 515 protected static OverlappingTestBase instance; 516 517 protected OverlappingTestBase() { 518 getVerifyColor(); 519 } 520 521 /***************************************************** 522 * Standard Test Machinery Section 523 * DO NOT modify anything in this section -- it's a 524 * standard chunk of code which has all of the 525 * synchronisation necessary for the test harness. 526 * By keeping it the same in all tests, it is easier 527 * to read and understand someone else's test, as 528 * well as insuring that all tests behave correctly 529 * with the test harness. 530 * There is a section following this for test- 531 * classes 532 ******************************************************/ 533 private static void init() throws InterruptedException { 534 //*** Create instructions for the user here *** 535 //System.setProperty("sun.awt.disableMixing", "true"); 536 537 String[] instructions = { 538 "This is an AUTOMATIC test, simply wait until it is done.", 539 "The result (passed or failed) will be shown in the", 540 "message window below." 541 }; 542 Sysout.createDialog(); 543 Sysout.printInstructions(instructions); 544 545 instance.testAwtControls(); 546 547 if (wasHWClicked) { 548 fail("HW component received the click."); 549 passed = false; 550 } 551 if (passed) { 552 pass(); 553 } 554 }//End init() 555 private static boolean theTestPassed = false; 556 private static boolean testGeneratedInterrupt = false; 557 private static String failureMessage = ""; 558 private static Thread mainThread = null; 559 private static int sleepTime = 300000; 560 561 // Not sure about what happens if multiple of this test are 562 // instantiated in the same VM. Being static (and using 563 // static vars), it aint gonna work. Not worrying about 564 // it for now. 565 /** 566 * Starting point for test runs. See usage at {@link OverlappingTestBase } 567 * @param args regular main args, not used. 568 * @throws InterruptedException 569 */ 570 public static void doMain(String args[]) throws InterruptedException { 571 try { 572 peerField = Component.class.getDeclaredField("peer"); 573 } catch (NoSuchFieldException e) { 574 throw new RuntimeException("peer field is not available"); 575 } 576 peerField.setAccessible(true); 577 mainThread = Thread.currentThread(); 578 try { 579 init(); 580 } catch (TestPassedException e) { 581 //The test passed, so just return from main and harness will 582 // interepret this return as a pass 583 return; 584 } 585 //At this point, neither test pass nor test fail has been 586 // called -- either would have thrown an exception and ended the 587 // test, so we know we have multiple threads. 588 589 //Test involves other threads, so sleep and wait for them to 590 // called pass() or fail() 591 try { 592 Thread.sleep(sleepTime); 593 //Timed out, so fail the test 594 throw new RuntimeException("Timed out after " + sleepTime / 1000 + " seconds"); 595 } catch (InterruptedException e) { 596 //The test harness may have interrupted the test. If so, rethrow the exception 597 // so that the harness gets it and deals with it. 598 if (!testGeneratedInterrupt) { 599 throw e; 600 } 601 602 //reset flag in case hit this code more than once for some reason (just safety) 603 testGeneratedInterrupt = false; 604 605 if (theTestPassed == false) { 606 throw new RuntimeException(failureMessage); 607 } 608 } 609 610 }//main 611 612 /** 613 * Test will fail if not passed after this timeout. Default timeout is 300 seconds. 614 * @param seconds timeout in seconds 615 */ 616 public static synchronized void setTimeoutTo(int seconds) { 617 sleepTime = seconds * 1000; 618 } 619 620 /** 621 * Set test as passed. Usually shoudn't be called directly. 622 */ 623 public static synchronized void pass() { 624 Sysout.println("The test passed."); 625 Sysout.println("The test is over, hit Ctl-C to stop Java VM"); 626 //first check if this is executing in main thread 627 if (mainThread == Thread.currentThread()) { 628 //Still in the main thread, so set the flag just for kicks, 629 // and throw a test passed exception which will be caught 630 // and end the test. 631 theTestPassed = true; 632 throw new TestPassedException(); 633 } 634 theTestPassed = true; 635 testGeneratedInterrupt = true; 636 mainThread.interrupt(); 637 }//pass() 638 639 /** 640 * Fail test generic message. 641 */ 642 public static synchronized void fail() { 643 //test writer didn't specify why test failed, so give generic 644 fail("it just plain failed! :-)"); 645 } 646 647 /** 648 * Fail test providing specific reason. 649 * @param whyFailed reason 650 */ 651 public static synchronized void fail(String whyFailed) { 652 Sysout.println("The test failed: " + whyFailed); 653 Sysout.println("The test is over, hit Ctl-C to stop Java VM"); 654 //check if this called from main thread 655 if (mainThread == Thread.currentThread()) { 656 //If main thread, fail now 'cause not sleeping 657 throw new RuntimeException(whyFailed); 658 } 659 theTestPassed = false; 660 testGeneratedInterrupt = true; 661 failureMessage = whyFailed; 662 mainThread.interrupt(); 663 }//fail() 664 }// class LWComboBox 665 class TestPassedException extends RuntimeException { 666 } 667 668 //*********** End Standard Test Machinery Section ********** 669 //************ Begin classes defined for the test **************** 670 // if want to make listeners, here is the recommended place for them, then instantiate 671 // them in init() 672 673 /* Example of a class which may be written as part of a test 674 class NewClass implements anInterface 675 { 676 static int newVar = 0; 677 678 public void eventDispatched(AWTEvent e) 679 { 680 //Counting events to see if we get enough 681 eventCount++; 682 683 if( eventCount == 20 ) 684 { 685 //got enough events, so pass 686 687 LWComboBox.pass(); 688 } 689 else if( tries == 20 ) 690 { 691 //tried too many times without getting enough events so fail 692 693 LWComboBox.fail(); 694 } 695 696 }// eventDispatched() 697 698 }// NewClass class 699 700 */ 701 //************** End classes defined for the test ******************* 702 /**************************************************** 703 Standard Test Machinery 704 DO NOT modify anything below -- it's a standard 705 chunk of code whose purpose is to make user 706 interaction uniform, and thereby make it simpler 707 to read and understand someone else's test. 708 ****************************************************/ 709 /** 710 This is part of the standard test machinery. 711 It creates a dialog (with the instructions), and is the interface 712 for sending text messages to the user. 713 To print the instructions, send an array of strings to Sysout.createDialog 714 WithInstructions method. Put one line of instructions per array entry. 715 To display a message for the tester to see, simply call Sysout.println 716 with the string to be displayed. 717 This mimics System.out.println but works within the test harness as well 718 as standalone. 719 */ 720 class Sysout { 721 private static TestDialog dialog; 722 723 public static void createDialogWithInstructions(String[] instructions) { 724 dialog = new TestDialog(new Frame(), "Instructions"); 725 dialog.printInstructions(instructions); 726 //dialog.setVisible(true); 727 println("Any messages for the tester will display here."); 728 } 729 730 public static void createDialog() { 731 dialog = new TestDialog(new Frame(), "Instructions"); 732 String[] defInstr = {"Instructions will appear here. ", ""}; 733 dialog.printInstructions(defInstr); 734 //dialog.setVisible(true); 735 println("Any messages for the tester will display here."); 736 } 737 738 public static void printInstructions(String[] instructions) { 739 dialog.printInstructions(instructions); 740 } 741 742 public static void println(String messageIn) { 743 dialog.displayMessage(messageIn); 744 System.out.println(messageIn); 745 } 746 }// Sysout class 747 748 /** 749 This is part of the standard test machinery. It provides a place for the 750 test instructions to be displayed, and a place for interactive messages 751 to the user to be displayed. 752 To have the test instructions displayed, see Sysout. 753 To have a message to the user be displayed, see Sysout. 754 Do not call anything in this dialog directly. 755 */ 756 class TestDialog extends Dialog { 757 TextArea instructionsText; 758 TextArea messageText; 759 int maxStringLength = 80; 760 761 //DO NOT call this directly, go through Sysout 762 public TestDialog(Frame frame, String name) { 763 super(frame, name); 764 int scrollBoth = TextArea.SCROLLBARS_BOTH; 765 instructionsText = new TextArea("", 15, maxStringLength, scrollBoth); 766 add("North", instructionsText); 767 768 messageText = new TextArea("", 5, maxStringLength, scrollBoth); 769 add("Center", messageText); 770 771 pack(); 772 773 //setVisible(true); 774 }// TestDialog() 775 776 //DO NOT call this directly, go through Sysout 777 public void printInstructions(String[] instructions) { 778 //Clear out any current instructions 779 instructionsText.setText(""); 780 781 //Go down array of instruction strings 782 783 String printStr, remainingStr; 784 for (int i = 0; i < instructions.length; i++) { 785 //chop up each into pieces maxSringLength long 786 remainingStr = instructions[i]; 787 while (remainingStr.length() > 0) { 788 //if longer than max then chop off first max chars to print 789 if (remainingStr.length() >= maxStringLength) { 790 //Try to chop on a word boundary 791 int posOfSpace = remainingStr.lastIndexOf(' ', maxStringLength - 1); 792 793 if (posOfSpace <= 0) { 794 posOfSpace = maxStringLength - 1; 795 } 796 797 printStr = remainingStr.substring(0, posOfSpace + 1); 798 remainingStr = remainingStr.substring(posOfSpace + 1); 799 } //else just print 800 else { 801 printStr = remainingStr; 802 remainingStr = ""; 803 } 804 805 instructionsText.append(printStr + "\n"); 806 807 }// while 808 809 }// for 810 811 }//printInstructions() 812 813 //DO NOT call this directly, go through Sysout 814 public void displayMessage(String messageIn) { 815 messageText.append(messageIn + "\n"); 816 System.out.println(messageIn); 817 } 818 }// TestDialog class 819