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