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