1 /* 2 * Copyright (c) 2007, 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 @test 26 @bug 4811096 27 @summary Tests whether opaque and non-opaque components mix correctly 28 @author anthony.petrov@...: area=awt.mixing 29 @library ../regtesthelpers 30 @build Util 31 @run main OpaqueTest 32 */ 33 34 35 /** 36 * OpaqueTest.java 37 * 38 * summary: OpaqueTest 39 */ 40 41 import java.awt.*; 42 import java.awt.event.*; 43 import javax.swing.*; 44 import test.java.awt.regtesthelpers.Util; 45 import com.sun.awt.AWTUtilities; 46 47 48 49 public class OpaqueTest 50 { 51 52 //*** test-writer defined static variables go here *** 53 54 static String testSeq = new String(""); 55 final static String checkSeq = new String("010000101"); 56 57 private static void init() 58 { 59 //*** Create instructions for the user here *** 60 61 String[] instructions = 62 { 63 "This is an AUTOMATIC test, simply wait until it is done.", 64 "The result (passed or failed) will be shown in the", 65 "message window below." 66 }; 67 Sysout.createDialog( ); 68 Sysout.printInstructions( instructions ); 69 70 71 // Create components 72 final Frame f = new Frame("Button-JButton mix test"); 73 final Panel p = new Panel(); 74 final Button heavy = new Button(" Heavyweight Button "); 75 final JButton light = new JButton(" LW Button "); 76 77 // Actions for the buttons add appropriate number to the test sequence 78 heavy.addActionListener(new java.awt.event.ActionListener() 79 { 80 public void actionPerformed(java.awt.event.ActionEvent e) { 81 p.setComponentZOrder(light, 0); 82 f.validate(); 83 testSeq = testSeq + "0"; 84 } 85 } 86 ); 87 88 light.addActionListener(new java.awt.event.ActionListener() 89 { 90 public void actionPerformed(java.awt.event.ActionEvent e) { 91 p.setComponentZOrder(heavy, 0); 92 f.validate(); 93 testSeq = testSeq + "1"; 94 } 95 } 96 ); 97 98 // Overlap the buttons 99 heavy.setBounds(30, 30, 200, 200); 100 light.setBounds(10, 10, 50, 50); 101 102 // Put the components into the frame 103 p.setLayout(null); 104 p.add(heavy); 105 p.add(light); 106 f.add(p); 107 f.setBounds(50, 50, 400, 400); 108 f.show(); 109 110 111 Robot robot = Util.createRobot(); 112 robot.setAutoDelay(20); 113 114 Util.waitForIdle(robot); 115 116 // Move the mouse pointer to the position where both 117 // buttons overlap 118 Point heavyLoc = heavy.getLocationOnScreen(); 119 robot.mouseMove(heavyLoc.x + 5, heavyLoc.y + 5); 120 121 // Now perform the click at this point for 9 times 122 // In the middle of the process toggle the opaque 123 // flag value. 124 for (int i = 0; i < 9; ++i) { 125 if (i == 3) { 126 AWTUtilities.setComponentMixingCutoutShape(light, 127 new Rectangle()); 128 } 129 if (i == 6) { 130 AWTUtilities.setComponentMixingCutoutShape(light, 131 null); 132 } 133 134 robot.mousePress(InputEvent.BUTTON1_MASK); 135 robot.mouseRelease(InputEvent.BUTTON1_MASK); 136 Util.waitForIdle(robot); 137 } 138 139 Util.waitForIdle(robot); 140 141 // If the buttons are correctly mixed, the test sequence 142 // is equal to the check sequence. 143 if (testSeq.equals(checkSeq)) { 144 OpaqueTest.pass(); 145 } else { 146 OpaqueTest.fail("The components changed their visible Z-order in a wrong sequence: '" + testSeq + "' instead of '" + checkSeq + "'"); 147 } 148 }//End init() 149 150 151 152 /***************************************************** 153 * Standard Test Machinery Section 154 * DO NOT modify anything in this section -- it's a 155 * standard chunk of code which has all of the 156 * synchronisation necessary for the test harness. 157 * By keeping it the same in all tests, it is easier 158 * to read and understand someone else's test, as 159 * well as insuring that all tests behave correctly 160 * with the test harness. 161 * There is a section following this for test- 162 * classes 163 ******************************************************/ 164 private static boolean theTestPassed = false; 165 private static boolean testGeneratedInterrupt = false; 166 private static String failureMessage = ""; 167 168 private static Thread mainThread = null; 169 170 private static int sleepTime = 300000; 171 172 // Not sure about what happens if multiple of this test are 173 // instantiated in the same VM. Being static (and using 174 // static vars), it aint gonna work. Not worrying about 175 // it for now. 176 public static void main( String args[] ) throws InterruptedException 177 { 178 mainThread = Thread.currentThread(); 179 try 180 { 181 init(); 182 } 183 catch( TestPassedException e ) 184 { 185 //The test passed, so just return from main and harness will 186 // interepret this return as a pass 187 return; 188 } 189 //At this point, neither test pass nor test fail has been 190 // called -- either would have thrown an exception and ended the 191 // test, so we know we have multiple threads. 192 193 //Test involves other threads, so sleep and wait for them to 194 // called pass() or fail() 195 try 196 { 197 Thread.sleep( sleepTime ); 198 //Timed out, so fail the test 199 throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); 200 } 201 catch (InterruptedException e) 202 { 203 //The test harness may have interrupted the test. If so, rethrow the exception 204 // so that the harness gets it and deals with it. 205 if( ! testGeneratedInterrupt ) throw e; 206 207 //reset flag in case hit this code more than once for some reason (just safety) 208 testGeneratedInterrupt = false; 209 210 if ( theTestPassed == false ) 211 { 212 throw new RuntimeException( failureMessage ); 213 } 214 } 215 216 }//main 217 218 public static synchronized void setTimeoutTo( int seconds ) 219 { 220 sleepTime = seconds * 1000; 221 } 222 223 public static synchronized void pass() 224 { 225 Sysout.println( "The test passed." ); 226 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 227 //first check if this is executing in main thread 228 if ( mainThread == Thread.currentThread() ) 229 { 230 //Still in the main thread, so set the flag just for kicks, 231 // and throw a test passed exception which will be caught 232 // and end the test. 233 theTestPassed = true; 234 throw new TestPassedException(); 235 } 236 theTestPassed = true; 237 testGeneratedInterrupt = true; 238 mainThread.interrupt(); 239 }//pass() 240 241 public static synchronized void fail() 242 { 243 //test writer didn't specify why test failed, so give generic 244 fail( "it just plain failed! :-)" ); 245 } 246 247 public static synchronized void fail( String whyFailed ) 248 { 249 Sysout.println( "The test failed: " + whyFailed ); 250 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 251 //check if this called from main thread 252 if ( mainThread == Thread.currentThread() ) 253 { 254 //If main thread, fail now 'cause not sleeping 255 throw new RuntimeException( whyFailed ); 256 } 257 theTestPassed = false; 258 testGeneratedInterrupt = true; 259 failureMessage = whyFailed; 260 mainThread.interrupt(); 261 }//fail() 262 263 }// class OpaqueTest 264 265 //This exception is used to exit from any level of call nesting 266 // when it's determined that the test has passed, and immediately 267 // end the test. 268 class TestPassedException extends RuntimeException 269 { 270 } 271 272 //*********** End Standard Test Machinery Section ********** 273 274 275 //************ Begin classes defined for the test **************** 276 277 // if want to make listeners, here is the recommended place for them, then instantiate 278 // them in init() 279 280 /* Example of a class which may be written as part of a test 281 class NewClass implements anInterface 282 { 283 static int newVar = 0; 284 285 public void eventDispatched(AWTEvent e) 286 { 287 //Counting events to see if we get enough 288 eventCount++; 289 290 if( eventCount == 20 ) 291 { 292 //got enough events, so pass 293 294 OpaqueTest.pass(); 295 } 296 else if( tries == 20 ) 297 { 298 //tried too many times without getting enough events so fail 299 300 OpaqueTest.fail(); 301 } 302 303 }// eventDispatched() 304 305 }// NewClass class 306 307 */ 308 309 310 //************** End classes defined for the test ******************* 311 312 313 314 315 /**************************************************** 316 Standard Test Machinery 317 DO NOT modify anything below -- it's a standard 318 chunk of code whose purpose is to make user 319 interaction uniform, and thereby make it simpler 320 to read and understand someone else's test. 321 ****************************************************/ 322 323 /** 324 This is part of the standard test machinery. 325 It creates a dialog (with the instructions), and is the interface 326 for sending text messages to the user. 327 To print the instructions, send an array of strings to Sysout.createDialog 328 WithInstructions method. Put one line of instructions per array entry. 329 To display a message for the tester to see, simply call Sysout.println 330 with the string to be displayed. 331 This mimics System.out.println but works within the test harness as well 332 as standalone. 333 */ 334 335 class Sysout 336 { 337 private static TestDialog dialog; 338 339 public static void createDialogWithInstructions( String[] instructions ) 340 { 341 dialog = new TestDialog( new Frame(), "Instructions" ); 342 dialog.printInstructions( instructions ); 343 dialog.setVisible(true); 344 println( "Any messages for the tester will display here." ); 345 } 346 347 public static void createDialog( ) 348 { 349 dialog = new TestDialog( new Frame(), "Instructions" ); 350 String[] defInstr = { "Instructions will appear here. ", "" } ; 351 dialog.printInstructions( defInstr ); 352 dialog.setVisible(true); 353 println( "Any messages for the tester will display here." ); 354 } 355 356 357 public static void printInstructions( String[] instructions ) 358 { 359 dialog.printInstructions( instructions ); 360 } 361 362 363 public static void println( String messageIn ) 364 { 365 dialog.displayMessage( messageIn ); 366 System.out.println(messageIn); 367 } 368 369 }// Sysout class 370 371 /** 372 This is part of the standard test machinery. It provides a place for the 373 test instructions to be displayed, and a place for interactive messages 374 to the user to be displayed. 375 To have the test instructions displayed, see Sysout. 376 To have a message to the user be displayed, see Sysout. 377 Do not call anything in this dialog directly. 378 */ 379 class TestDialog extends Dialog 380 { 381 382 TextArea instructionsText; 383 TextArea messageText; 384 int maxStringLength = 80; 385 386 //DO NOT call this directly, go through Sysout 387 public TestDialog( Frame frame, String name ) 388 { 389 super( frame, name ); 390 int scrollBoth = TextArea.SCROLLBARS_BOTH; 391 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 392 add( "North", instructionsText ); 393 394 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 395 add("Center", messageText); 396 397 pack(); 398 399 setVisible(true); 400 }// TestDialog() 401 402 //DO NOT call this directly, go through Sysout 403 public void printInstructions( String[] instructions ) 404 { 405 //Clear out any current instructions 406 instructionsText.setText( "" ); 407 408 //Go down array of instruction strings 409 410 String printStr, remainingStr; 411 for( int i=0; i < instructions.length; i++ ) 412 { 413 //chop up each into pieces maxSringLength long 414 remainingStr = instructions[ i ]; 415 while( remainingStr.length() > 0 ) 416 { 417 //if longer than max then chop off first max chars to print 418 if( remainingStr.length() >= maxStringLength ) 419 { 420 //Try to chop on a word boundary 421 int posOfSpace = remainingStr. 422 lastIndexOf( ' ', maxStringLength - 1 ); 423 424 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 425 426 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 427 remainingStr = remainingStr.substring( posOfSpace + 1 ); 428 } 429 //else just print 430 else 431 { 432 printStr = remainingStr; 433 remainingStr = ""; 434 } 435 436 instructionsText.append( printStr + "\n" ); 437 438 }// while 439 440 }// for 441 442 }//printInstructions() 443 444 //DO NOT call this directly, go through Sysout 445 public void displayMessage( String messageIn ) 446 { 447 messageText.append( messageIn + "\n" ); 448 System.out.println(messageIn); 449 } 450 451 }// TestDialog class