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