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 8173409 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 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 light.setMixingCutoutShape(new Rectangle()); 127 } 128 if (i == 6) { 129 light.setMixingCutoutShape(null); 130 } 131 132 robot.mousePress(InputEvent.BUTTON1_MASK); 133 robot.mouseRelease(InputEvent.BUTTON1_MASK); 134 Util.waitForIdle(robot); 135 } 136 137 Util.waitForIdle(robot); 138 139 // If the buttons are correctly mixed, the test sequence 140 // is equal to the check sequence. 141 if (testSeq.equals(checkSeq)) { 142 OpaqueTest.pass(); 143 } else { 144 OpaqueTest.fail("The components changed their visible Z-order in a wrong sequence: '" + testSeq + "' instead of '" + checkSeq + "'"); 145 } 146 }//End init() 147 148 149 150 /***************************************************** 151 * Standard Test Machinery Section 152 * DO NOT modify anything in this section -- it's a 153 * standard chunk of code which has all of the 154 * synchronisation necessary for the test harness. 155 * By keeping it the same in all tests, it is easier 156 * to read and understand someone else's test, as 157 * well as insuring that all tests behave correctly 158 * with the test harness. 159 * There is a section following this for test- 160 * classes 161 ******************************************************/ 162 private static boolean theTestPassed = false; 163 private static boolean testGeneratedInterrupt = false; 164 private static String failureMessage = ""; 165 166 private static Thread mainThread = null; 167 168 private static int sleepTime = 300000; 169 170 // Not sure about what happens if multiple of this test are 171 // instantiated in the same VM. Being static (and using 172 // static vars), it aint gonna work. Not worrying about 173 // it for now. 174 public static void main( String args[] ) throws InterruptedException 175 { 176 mainThread = Thread.currentThread(); 177 try 178 { 179 init(); 180 } 181 catch( TestPassedException e ) 182 { 183 //The test passed, so just return from main and harness will 184 // interepret this return as a pass 185 return; 186 } 187 //At this point, neither test pass nor test fail has been 188 // called -- either would have thrown an exception and ended the 189 // test, so we know we have multiple threads. 190 191 //Test involves other threads, so sleep and wait for them to 192 // called pass() or fail() 193 try 194 { 195 Thread.sleep( sleepTime ); 196 //Timed out, so fail the test 197 throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); 198 } 199 catch (InterruptedException e) 200 { 201 //The test harness may have interrupted the test. If so, rethrow the exception 202 // so that the harness gets it and deals with it. 203 if( ! testGeneratedInterrupt ) throw e; 204 205 //reset flag in case hit this code more than once for some reason (just safety) 206 testGeneratedInterrupt = false; 207 208 if ( theTestPassed == false ) 209 { 210 throw new RuntimeException( failureMessage ); 211 } 212 } 213 214 }//main 215 216 public static synchronized void setTimeoutTo( int seconds ) 217 { 218 sleepTime = seconds * 1000; 219 } 220 221 public static synchronized void pass() 222 { 223 Sysout.println( "The test passed." ); 224 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 225 //first check if this is executing in main thread 226 if ( mainThread == Thread.currentThread() ) 227 { 228 //Still in the main thread, so set the flag just for kicks, 229 // and throw a test passed exception which will be caught 230 // and end the test. 231 theTestPassed = true; 232 throw new TestPassedException(); 233 } 234 theTestPassed = true; 235 testGeneratedInterrupt = true; 236 mainThread.interrupt(); 237 }//pass() 238 239 public static synchronized void fail() 240 { 241 //test writer didn't specify why test failed, so give generic 242 fail( "it just plain failed! :-)" ); 243 } 244 245 public static synchronized void fail( String whyFailed ) 246 { 247 Sysout.println( "The test failed: " + whyFailed ); 248 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 249 //check if this called from main thread 250 if ( mainThread == Thread.currentThread() ) 251 { 252 //If main thread, fail now 'cause not sleeping 253 throw new RuntimeException( whyFailed ); 254 } 255 theTestPassed = false; 256 testGeneratedInterrupt = true; 257 failureMessage = whyFailed; 258 mainThread.interrupt(); 259 }//fail() 260 261 }// class OpaqueTest 262 263 //This exception is used to exit from any level of call nesting 264 // when it's determined that the test has passed, and immediately 265 // end the test. 266 class TestPassedException extends RuntimeException 267 { 268 } 269 270 //*********** End Standard Test Machinery Section ********** 271 272 273 //************ Begin classes defined for the test **************** 274 275 // if want to make listeners, here is the recommended place for them, then instantiate 276 // them in init() 277 278 /* Example of a class which may be written as part of a test 279 class NewClass implements anInterface 280 { 281 static int newVar = 0; 282 283 public void eventDispatched(AWTEvent e) 284 { 285 //Counting events to see if we get enough 286 eventCount++; 287 288 if( eventCount == 20 ) 289 { 290 //got enough events, so pass 291 292 OpaqueTest.pass(); 293 } 294 else if( tries == 20 ) 295 { 296 //tried too many times without getting enough events so fail 297 298 OpaqueTest.fail(); 299 } 300 301 }// eventDispatched() 302 303 }// NewClass class 304 305 */ 306 307 308 //************** End classes defined for the test ******************* 309 310 311 312 313 /**************************************************** 314 Standard Test Machinery 315 DO NOT modify anything below -- it's a standard 316 chunk of code whose purpose is to make user 317 interaction uniform, and thereby make it simpler 318 to read and understand someone else's test. 319 ****************************************************/ 320 321 /** 322 This is part of the standard test machinery. 323 It creates a dialog (with the instructions), and is the interface 324 for sending text messages to the user. 325 To print the instructions, send an array of strings to Sysout.createDialog 326 WithInstructions method. Put one line of instructions per array entry. 327 To display a message for the tester to see, simply call Sysout.println 328 with the string to be displayed. 329 This mimics System.out.println but works within the test harness as well 330 as standalone. 331 */ 332 333 class Sysout 334 { 335 private static TestDialog dialog; 336 337 public static void createDialogWithInstructions( String[] instructions ) 338 { 339 dialog = new TestDialog( new Frame(), "Instructions" ); 340 dialog.printInstructions( instructions ); 341 dialog.setVisible(true); 342 println( "Any messages for the tester will display here." ); 343 } 344 345 public static void createDialog( ) 346 { 347 dialog = new TestDialog( new Frame(), "Instructions" ); 348 String[] defInstr = { "Instructions will appear here. ", "" } ; 349 dialog.printInstructions( defInstr ); 350 dialog.setVisible(true); 351 println( "Any messages for the tester will display here." ); 352 } 353 354 355 public static void printInstructions( String[] instructions ) 356 { 357 dialog.printInstructions( instructions ); 358 } 359 360 361 public static void println( String messageIn ) 362 { 363 dialog.displayMessage( messageIn ); 364 System.out.println(messageIn); 365 } 366 367 }// Sysout class 368 369 /** 370 This is part of the standard test machinery. It provides a place for the 371 test instructions to be displayed, and a place for interactive messages 372 to the user to be displayed. 373 To have the test instructions displayed, see Sysout. 374 To have a message to the user be displayed, see Sysout. 375 Do not call anything in this dialog directly. 376 */ 377 class TestDialog extends Dialog 378 { 379 380 TextArea instructionsText; 381 TextArea messageText; 382 int maxStringLength = 80; 383 384 //DO NOT call this directly, go through Sysout 385 public TestDialog( Frame frame, String name ) 386 { 387 super( frame, name ); 388 int scrollBoth = TextArea.SCROLLBARS_BOTH; 389 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 390 add( "North", instructionsText ); 391 392 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 393 add("Center", messageText); 394 395 pack(); 396 397 setVisible(true); 398 }// TestDialog() 399 400 //DO NOT call this directly, go through Sysout 401 public void printInstructions( String[] instructions ) 402 { 403 //Clear out any current instructions 404 instructionsText.setText( "" ); 405 406 //Go down array of instruction strings 407 408 String printStr, remainingStr; 409 for( int i=0; i < instructions.length; i++ ) 410 { 411 //chop up each into pieces maxSringLength long 412 remainingStr = instructions[ i ]; 413 while( remainingStr.length() > 0 ) 414 { 415 //if longer than max then chop off first max chars to print 416 if( remainingStr.length() >= maxStringLength ) 417 { 418 //Try to chop on a word boundary 419 int posOfSpace = remainingStr. 420 lastIndexOf( ' ', maxStringLength - 1 ); 421 422 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 423 424 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 425 remainingStr = remainingStr.substring( posOfSpace + 1 ); 426 } 427 //else just print 428 else 429 { 430 printStr = remainingStr; 431 remainingStr = ""; 432 } 433 434 instructionsText.append( printStr + "\n" ); 435 436 }// while 437 438 }// for 439 440 }//printInstructions() 441 442 //DO NOT call this directly, go through Sysout 443 public void displayMessage( String messageIn ) 444 { 445 messageText.append( messageIn + "\n" ); 446 System.out.println(messageIn); 447 } 448 449 }// TestDialog class