1 /* 2 * Copyright (c) 2006, 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 6418028 28 @summary java/awt/Focus/RequestOnCompWithNullParent/RequestOnCompWithNullParent_Barrier.java fails 29 @author oleg.sukhodolsky: area=awt.focus 30 @library ../../regtesthelpers 31 @build Util 32 @run main RequestOnCompWithNullParent1 33 */ 34 35 /** 36 * RequestOnCompWithNullParent1.java 37 * 38 * summary: java/awt/Focus/RequestOnCompWithNullParent/RequestOnCompWithNullParent_Barrier.java fails 39 */ 40 41 import java.awt.*; 42 import java.awt.event.*; 43 import java.awt.peer.ButtonPeer; 44 import java.awt.peer.ComponentPeer; 45 import java.lang.reflect.Field; 46 import java.lang.reflect.InvocationHandler; 47 import java.lang.reflect.InvocationTargetException; 48 import java.lang.reflect.Method; 49 import java.lang.reflect.Proxy; 50 import test.java.awt.regtesthelpers.Util; 51 52 //*** global search and replace RequestOnCompWithNullParent1 with name of the test *** 53 54 public class RequestOnCompWithNullParent1 55 { 56 57 private static void init() { 58 //*** Create instructions for the user here *** 59 String[] instructions = 60 { 61 "This is an AUTOMATIC test, simply wait until it is done.", 62 "The result (passed or failed) will be shown in the", 63 "message window below." 64 }; 65 Sysout.createDialog( ); 66 Sysout.printInstructions( instructions ); 67 68 69 Frame frame = new Frame("test for 6418028"); 70 frame.setLayout(new FlowLayout()); 71 Button btn1 = new Button("Button1"); 72 frame.add(btn1); 73 TestButton btn2 = new TestButton("Button2"); 74 frame.add(btn2); 75 frame.pack(); 76 frame.addWindowListener(new WindowAdapter() { 77 @Override 78 public void windowClosing(WindowEvent we) { 79 we.getWindow().dispose(); 80 } 81 }); 82 frame.setVisible(true); 83 84 Util.waitForIdle(null); 85 86 btn2.instrumentPeer(); 87 btn2.requestFocusInWindow(); 88 btn2.restorePeer(); 89 frame.dispose(); 90 RequestOnCompWithNullParent1.pass(); 91 }//End init() 92 93 94 95 /***************************************************** 96 * Standard Test Machinery Section 97 * DO NOT modify anything in this section -- it's a 98 * standard chunk of code which has all of the 99 * synchronisation necessary for the test harness. 100 * By keeping it the same in all tests, it is easier 101 * to read and understand someone else's test, as 102 * well as insuring that all tests behave correctly 103 * with the test harness. 104 * There is a section following this for test- 105 * classes 106 ******************************************************/ 107 private static boolean theTestPassed = false; 108 private static boolean testGeneratedInterrupt = false; 109 private static String failureMessage = ""; 110 111 private static Thread mainThread = null; 112 113 private static int sleepTime = 300000; 114 115 // Not sure about what happens if multiple of this test are 116 // instantiated in the same VM. Being static (and using 117 // static vars), it aint gonna work. Not worrying about 118 // it for now. 119 public static void main( String args[] ) throws InterruptedException 120 { 121 mainThread = Thread.currentThread(); 122 try 123 { 124 init(); 125 } 126 catch( TestPassedException e ) 127 { 128 //The test passed, so just return from main and harness will 129 // interepret this return as a pass 130 return; 131 } 132 //At this point, neither test pass nor test fail has been 133 // called -- either would have thrown an exception and ended the 134 // test, so we know we have multiple threads. 135 136 //Test involves other threads, so sleep and wait for them to 137 // called pass() or fail() 138 try 139 { 140 Thread.sleep( sleepTime ); 141 //Timed out, so fail the test 142 throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); 143 } 144 catch (InterruptedException e) 145 { 146 //The test harness may have interrupted the test. If so, rethrow the exception 147 // so that the harness gets it and deals with it. 148 if( ! testGeneratedInterrupt ) throw e; 149 150 //reset flag in case hit this code more than once for some reason (just safety) 151 testGeneratedInterrupt = false; 152 153 if ( theTestPassed == false ) 154 { 155 throw new RuntimeException( failureMessage ); 156 } 157 } 158 159 }//main 160 161 public static synchronized void setTimeoutTo( int seconds ) 162 { 163 sleepTime = seconds * 1000; 164 } 165 166 public static synchronized void pass() 167 { 168 Sysout.println( "The test passed." ); 169 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 170 //first check if this is executing in main thread 171 if ( mainThread == Thread.currentThread() ) 172 { 173 //Still in the main thread, so set the flag just for kicks, 174 // and throw a test passed exception which will be caught 175 // and end the test. 176 theTestPassed = true; 177 throw new TestPassedException(); 178 } 179 theTestPassed = true; 180 testGeneratedInterrupt = true; 181 mainThread.interrupt(); 182 }//pass() 183 184 public static synchronized void fail() 185 { 186 //test writer didn't specify why test failed, so give generic 187 fail( "it just plain failed! :-)" ); 188 } 189 190 public static synchronized void fail( String whyFailed ) 191 { 192 Sysout.println( "The test failed: " + whyFailed ); 193 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 194 //check if this called from main thread 195 if ( mainThread == Thread.currentThread() ) 196 { 197 //If main thread, fail now 'cause not sleeping 198 throw new RuntimeException( whyFailed ); 199 } 200 theTestPassed = false; 201 testGeneratedInterrupt = true; 202 failureMessage = whyFailed; 203 mainThread.interrupt(); 204 }//fail() 205 206 }// class RequestOnCompWithNullParent1 207 208 //This exception is used to exit from any level of call nesting 209 // when it's determined that the test has passed, and immediately 210 // end the test. 211 class TestPassedException extends RuntimeException 212 { 213 } 214 215 //*********** End Standard Test Machinery Section ********** 216 217 218 //************ Begin classes defined for the test **************** 219 220 class TestButton extends Button { 221 ButtonPeer origPeer; 222 ButtonPeer proxiedPeer; 223 224 /** Creates a new instance of TestButton */ 225 public TestButton(String text) { 226 super(text); 227 } 228 229 public void instrumentPeer() { 230 origPeer = (ButtonPeer) getPeer(); 231 InvocationHandler handler = new InvocationHandler() { 232 public Object invoke(Object proxy, Method method, Object[] args) { 233 if (method.getName().equals("requestFocus")) { 234 Container parent = getParent(); 235 parent.remove(TestButton.this); 236 System.err.println("parent = " + parent); 237 System.err.println("target = " + TestButton.this); 238 System.err.println("new parent = " + TestButton.this.getParent()); 239 } 240 Object ret = null; 241 try { 242 ret = method.invoke(origPeer, args); 243 } catch (IllegalAccessException iae) { 244 throw new Error("Test error.", iae); 245 } catch (InvocationTargetException ita) { 246 throw new Error("Test error.", ita); 247 } 248 return ret; 249 } 250 }; 251 252 proxiedPeer = (ButtonPeer) Proxy.newProxyInstance(ButtonPeer.class.getClassLoader(), new Class[] {ButtonPeer.class}, handler); 253 setPeer(proxiedPeer); 254 } 255 256 private void setPeer(final ComponentPeer newPeer) { 257 try { 258 Field peer_field = Component.class.getDeclaredField("peer"); 259 peer_field.setAccessible(true); 260 peer_field.set(this, newPeer); 261 } catch (IllegalArgumentException ex) { 262 throw new Error("Test error.", ex); 263 } catch (SecurityException ex) { 264 throw new Error("Test error.", ex); 265 } catch (IllegalAccessException ex) { 266 throw new Error("Test error.", ex); 267 } catch (NoSuchFieldException ex) { 268 throw new Error("Test error.", ex); 269 } 270 } 271 272 public void restorePeer() { 273 if (origPeer != null) { 274 setPeer(origPeer); 275 proxiedPeer = null; 276 } 277 } 278 } 279 //************** End classes defined for the test ******************* 280 281 282 283 284 /**************************************************** 285 Standard Test Machinery 286 DO NOT modify anything below -- it's a standard 287 chunk of code whose purpose is to make user 288 interaction uniform, and thereby make it simpler 289 to read and understand someone else's test. 290 ****************************************************/ 291 292 /** 293 This is part of the standard test machinery. 294 It creates a dialog (with the instructions), and is the interface 295 for sending text messages to the user. 296 To print the instructions, send an array of strings to Sysout.createDialog 297 WithInstructions method. Put one line of instructions per array entry. 298 To display a message for the tester to see, simply call Sysout.println 299 with the string to be displayed. 300 This mimics System.out.println but works within the test harness as well 301 as standalone. 302 */ 303 304 class Sysout 305 { 306 private static TestDialog dialog; 307 308 public static void createDialogWithInstructions( String[] instructions ) 309 { 310 dialog = new TestDialog( new Frame(), "Instructions" ); 311 dialog.printInstructions( instructions ); 312 dialog.setVisible(true); 313 println( "Any messages for the tester will display here." ); 314 } 315 316 public static void createDialog( ) 317 { 318 dialog = new TestDialog( new Frame(), "Instructions" ); 319 String[] defInstr = { "Instructions will appear here. ", "" } ; 320 dialog.printInstructions( defInstr ); 321 dialog.setVisible(true); 322 println( "Any messages for the tester will display here." ); 323 } 324 325 326 public static void printInstructions( String[] instructions ) 327 { 328 dialog.printInstructions( instructions ); 329 } 330 331 332 public static void println( String messageIn ) 333 { 334 dialog.displayMessage( messageIn ); 335 System.out.println(messageIn); 336 } 337 338 }// Sysout class 339 340 /** 341 This is part of the standard test machinery. It provides a place for the 342 test instructions to be displayed, and a place for interactive messages 343 to the user to be displayed. 344 To have the test instructions displayed, see Sysout. 345 To have a message to the user be displayed, see Sysout. 346 Do not call anything in this dialog directly. 347 */ 348 class TestDialog extends Dialog 349 { 350 351 TextArea instructionsText; 352 TextArea messageText; 353 int maxStringLength = 80; 354 355 //DO NOT call this directly, go through Sysout 356 public TestDialog( Frame frame, String name ) 357 { 358 super( frame, name ); 359 int scrollBoth = TextArea.SCROLLBARS_BOTH; 360 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 361 add( "North", instructionsText ); 362 363 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 364 add("Center", messageText); 365 366 pack(); 367 368 setVisible(true); 369 }// TestDialog() 370 371 //DO NOT call this directly, go through Sysout 372 public void printInstructions( String[] instructions ) 373 { 374 //Clear out any current instructions 375 instructionsText.setText( "" ); 376 377 //Go down array of instruction strings 378 379 String printStr, remainingStr; 380 for( int i=0; i < instructions.length; i++ ) 381 { 382 //chop up each into pieces maxSringLength long 383 remainingStr = instructions[ i ]; 384 while( remainingStr.length() > 0 ) 385 { 386 //if longer than max then chop off first max chars to print 387 if( remainingStr.length() >= maxStringLength ) 388 { 389 //Try to chop on a word boundary 390 int posOfSpace = remainingStr. 391 lastIndexOf( ' ', maxStringLength - 1 ); 392 393 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 394 395 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 396 remainingStr = remainingStr.substring( posOfSpace + 1 ); 397 } 398 //else just print 399 else 400 { 401 printStr = remainingStr; 402 remainingStr = ""; 403 } 404 405 instructionsText.append( printStr + "\n" ); 406 407 }// while 408 409 }// for 410 411 }//printInstructions() 412 413 //DO NOT call this directly, go through Sysout 414 public void displayMessage( String messageIn ) 415 { 416 messageText.append( messageIn + "\n" ); 417 System.out.println(messageIn); 418 } 419 420 }// TestDialog class