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