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