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 6533330
  28   @summary ANCESTOR_RESIZED is not sent while resizing a frame. Regression caused by 6500477.
  29   @author anthony.petrov: area=awt.toplevel
  30   @library ../../../regtesthelpers
  31   @build Util
  32   @run main AncestorResized
  33 */
  34 
  35 
  36 /**
  37  * AncestorResized.java
  38  *
  39  * summary:  After fixing the 6500477, the ANCESTOR_RESIZED event stoped
  40  *           firing while resizing a frame. This was a regression.
  41  *           The test checks whether the event starts dispatching as it
  42  *           was before fixing the 6500477.
  43  */
  44 
  45 import java.awt.*;
  46 import java.awt.event.*;
  47 import test.java.awt.regtesthelpers.Util;
  48 
  49 
  50 public class AncestorResized
  51 {
  52     public static volatile int ancestorResizedCounter = 0;
  53 
  54 
  55     static class HierarchyBoundsListenerImpl implements HierarchyBoundsListener {
  56         public void ancestorMoved(HierarchyEvent ce) {
  57             // ANCESTOR_MOVED seems to work OK.
  58         }
  59         public void ancestorResized(HierarchyEvent ce) {
  60             ancestorResizedCounter++;
  61         }
  62     }
  63 
  64     private static void init()
  65     {
  66         Frame frame;
  67         Panel panel;
  68         Button button;
  69         Label label;
  70         Component[] components;
  71 
  72         String[] instructions =
  73         {
  74             "This is an AUTOMATIC test, simply wait until it is done.",
  75             "The result (passed or failed) will be shown in the",
  76             "message window below."
  77         };
  78         Sysout.createDialog( );
  79         Sysout.printInstructions( instructions );
  80 
  81         frame = new Frame("Test Frame");
  82         frame.setLayout(new FlowLayout());
  83 
  84         panel = new Panel();
  85         button = new Button("Button");
  86         label = new Label("Label");
  87 
  88         components = new Component[] {
  89             panel, button, label
  90         };
  91 
  92         frame.setSize(300, 300);
  93         frame.setVisible(true);
  94 
  95         Robot robot = Util.createRobot();
  96         robot.setAutoDelay(20);
  97 
  98         // To ensure the window is shown and packed
  99         Util.waitForIdle(robot);
 100 
 101         Insets insets = frame.getInsets();
 102         if (insets.right == 0 || insets.bottom == 0) {
 103             // Because we want to catch the "size-grip" of the frame.
 104             System.out.println("The test environment must have non-zero right & bottom insets! The current insets are: " + insets);
 105             pass();
 106             return;
 107         }
 108 
 109         // Let's move the mouse pointer to the bottom-right coner of the frame (the "size-grip")
 110         Rectangle bounds = frame.getBounds();
 111 
 112         robot.mouseMove(bounds.x + bounds.width - 1, bounds.y + bounds.height - 1);
 113 
 114         // From now on the ANCESTOR_RESIZED events get counted.
 115         HierarchyBoundsListener listener = new HierarchyBoundsListenerImpl();
 116         for (int i = 0; i < components.length; i++) {
 117             components[i].addHierarchyBoundsListener(listener);
 118             frame.add(components[i]);
 119         }
 120 
 121         // ... and start resizing
 122         robot.mousePress( InputEvent.BUTTON1_MASK );
 123         robot.mouseMove(bounds.x + bounds.width + 20, bounds.y + bounds.height + 15);
 124         Util.waitForIdle(robot);
 125 
 126         if (ancestorResizedCounter == 0) {
 127             robot.mouseRelease( InputEvent.BUTTON1_MASK );
 128             AncestorResized.fail("No ANCESTOR_RESIZED events received.");
 129             return;
 130         }
 131 
 132         robot.mouseRelease( InputEvent.BUTTON1_MASK );
 133 
 134         AncestorResized.pass();
 135     }//End  init()
 136 
 137 
 138 
 139     /*****************************************************
 140      * Standard Test Machinery Section
 141      * DO NOT modify anything in this section -- it's a
 142      * standard chunk of code which has all of the
 143      * synchronisation necessary for the test harness.
 144      * By keeping it the same in all tests, it is easier
 145      * to read and understand someone else's test, as
 146      * well as insuring that all tests behave correctly
 147      * with the test harness.
 148      * There is a section following this for test-
 149      * classes
 150      ******************************************************/
 151     private static boolean theTestPassed = false;
 152     private static boolean testGeneratedInterrupt = false;
 153     private static String failureMessage = "";
 154 
 155     private static Thread mainThread = null;
 156 
 157     private static int sleepTime = 300000;
 158 
 159     // Not sure about what happens if multiple of this test are
 160     //  instantiated in the same VM.  Being static (and using
 161     //  static vars), it aint gonna work.  Not worrying about
 162     //  it for now.
 163     public static void main( String args[] ) throws InterruptedException
 164     {
 165         mainThread = Thread.currentThread();
 166         try
 167         {
 168             init();
 169         }
 170         catch( TestPassedException e )
 171         {
 172             //The test passed, so just return from main and harness will
 173             // interepret this return as a pass
 174             return;
 175         }
 176         //At this point, neither test pass nor test fail has been
 177         // called -- either would have thrown an exception and ended the
 178         // test, so we know we have multiple threads.
 179 
 180         //Test involves other threads, so sleep and wait for them to
 181         // called pass() or fail()
 182         try
 183         {
 184             Thread.sleep( sleepTime );
 185             //Timed out, so fail the test
 186             throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
 187         }
 188         catch (InterruptedException e)
 189         {
 190             //The test harness may have interrupted the test.  If so, rethrow the exception
 191             // so that the harness gets it and deals with it.
 192             if( ! testGeneratedInterrupt ) throw e;
 193 
 194             //reset flag in case hit this code more than once for some reason (just safety)
 195             testGeneratedInterrupt = false;
 196 
 197             if ( theTestPassed == false )
 198             {
 199                 throw new RuntimeException( failureMessage );
 200             }
 201         }
 202 
 203     }//main
 204 
 205     public static synchronized void setTimeoutTo( int seconds )
 206     {
 207         sleepTime = seconds * 1000;
 208     }
 209 
 210     public static synchronized void pass()
 211     {
 212         Sysout.println( "The test passed." );
 213         Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
 214         //first check if this is executing in main thread
 215         if ( mainThread == Thread.currentThread() )
 216         {
 217             //Still in the main thread, so set the flag just for kicks,
 218             // and throw a test passed exception which will be caught
 219             // and end the test.
 220             theTestPassed = true;
 221             throw new TestPassedException();
 222         }
 223         theTestPassed = true;
 224         testGeneratedInterrupt = true;
 225         mainThread.interrupt();
 226     }//pass()
 227 
 228     public static synchronized void fail()
 229     {
 230         //test writer didn't specify why test failed, so give generic
 231         fail( "it just plain failed! :-)" );
 232     }
 233 
 234     public static synchronized void fail( String whyFailed )
 235     {
 236         Sysout.println( "The test failed: " + whyFailed );
 237         Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
 238         //check if this called from main thread
 239         if ( mainThread == Thread.currentThread() )
 240         {
 241             //If main thread, fail now 'cause not sleeping
 242             throw new RuntimeException( whyFailed );
 243         }
 244         theTestPassed = false;
 245         testGeneratedInterrupt = true;
 246         failureMessage = whyFailed;
 247         mainThread.interrupt();
 248     }//fail()
 249 
 250 }// class AncestorResized
 251 
 252 //This exception is used to exit from any level of call nesting
 253 // when it's determined that the test has passed, and immediately
 254 // end the test.
 255 class TestPassedException extends RuntimeException
 256 {
 257 }
 258 
 259 //*********** End Standard Test Machinery Section **********
 260 
 261 
 262 //************ Begin classes defined for the test ****************
 263 
 264 // if want to make listeners, here is the recommended place for them, then instantiate
 265 //  them in init()
 266 
 267 /* Example of a class which may be written as part of a test
 268 class NewClass implements anInterface
 269  {
 270    static int newVar = 0;
 271 
 272    public void eventDispatched(AWTEvent e)
 273     {
 274       //Counting events to see if we get enough
 275       eventCount++;
 276 
 277       if( eventCount == 20 )
 278        {
 279          //got enough events, so pass
 280 
 281          AncestorResized.pass();
 282        }
 283       else if( tries == 20 )
 284        {
 285          //tried too many times without getting enough events so fail
 286 
 287          AncestorResized.fail();
 288        }
 289 
 290     }// eventDispatched()
 291 
 292  }// NewClass class
 293 
 294 */
 295 
 296 
 297 //************** End classes defined for the test *******************
 298 
 299 
 300 
 301 
 302 /****************************************************
 303  Standard Test Machinery
 304  DO NOT modify anything below -- it's a standard
 305   chunk of code whose purpose is to make user
 306   interaction uniform, and thereby make it simpler
 307   to read and understand someone else's test.
 308  ****************************************************/
 309 
 310 /**
 311  This is part of the standard test machinery.
 312  It creates a dialog (with the instructions), and is the interface
 313   for sending text messages to the user.
 314  To print the instructions, send an array of strings to Sysout.createDialog
 315   WithInstructions method.  Put one line of instructions per array entry.
 316  To display a message for the tester to see, simply call Sysout.println
 317   with the string to be displayed.
 318  This mimics System.out.println but works within the test harness as well
 319   as standalone.
 320  */
 321 
 322 class Sysout
 323 {
 324     private static TestDialog dialog;
 325 
 326     public static void createDialogWithInstructions( String[] instructions )
 327     {
 328         dialog = new TestDialog( new Frame(), "Instructions" );
 329         dialog.printInstructions( instructions );
 330         dialog.setVisible(true);
 331         println( "Any messages for the tester will display here." );
 332     }
 333 
 334     public static void createDialog( )
 335     {
 336         dialog = new TestDialog( new Frame(), "Instructions" );
 337         String[] defInstr = { "Instructions will appear here. ", "" } ;
 338         dialog.printInstructions( defInstr );
 339         dialog.setVisible(true);
 340         println( "Any messages for the tester will display here." );
 341     }
 342 
 343 
 344     public static void printInstructions( String[] instructions )
 345     {
 346         dialog.printInstructions( instructions );
 347     }
 348 
 349 
 350     public static void println( String messageIn )
 351     {
 352         dialog.displayMessage( messageIn );
 353         System.out.println(messageIn);
 354     }
 355 
 356 }// Sysout  class
 357 
 358 /**
 359   This is part of the standard test machinery.  It provides a place for the
 360    test instructions to be displayed, and a place for interactive messages
 361    to the user to be displayed.
 362   To have the test instructions displayed, see Sysout.
 363   To have a message to the user be displayed, see Sysout.
 364   Do not call anything in this dialog directly.
 365   */
 366 class TestDialog extends Dialog
 367 {
 368 
 369     TextArea instructionsText;
 370     TextArea messageText;
 371     int maxStringLength = 80;
 372 
 373     //DO NOT call this directly, go through Sysout
 374     public TestDialog( Frame frame, String name )
 375     {
 376         super( frame, name );
 377         int scrollBoth = TextArea.SCROLLBARS_BOTH;
 378         instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
 379         add( "North", instructionsText );
 380 
 381         messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
 382         add("Center", messageText);
 383 
 384         pack();
 385 
 386         setVisible(true);
 387     }// TestDialog()
 388 
 389     //DO NOT call this directly, go through Sysout
 390     public void printInstructions( String[] instructions )
 391     {
 392         //Clear out any current instructions
 393         instructionsText.setText( "" );
 394 
 395         //Go down array of instruction strings
 396 
 397         String printStr, remainingStr;
 398         for( int i=0; i < instructions.length; i++ )
 399         {
 400             //chop up each into pieces maxSringLength long
 401             remainingStr = instructions[ i ];
 402             while( remainingStr.length() > 0 )
 403             {
 404                 //if longer than max then chop off first max chars to print
 405                 if( remainingStr.length() >= maxStringLength )
 406                 {
 407                     //Try to chop on a word boundary
 408                     int posOfSpace = remainingStr.
 409                         lastIndexOf( ' ', maxStringLength - 1 );
 410 
 411                     if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
 412 
 413                     printStr = remainingStr.substring( 0, posOfSpace + 1 );
 414                     remainingStr = remainingStr.substring( posOfSpace + 1 );
 415                 }
 416                 //else just print
 417                 else
 418                 {
 419                     printStr = remainingStr;
 420                     remainingStr = "";
 421                 }
 422 
 423                 instructionsText.append( printStr + "\n" );
 424 
 425             }// while
 426 
 427         }// for
 428 
 429     }//printInstructions()
 430 
 431     //DO NOT call this directly, go through Sysout
 432     public void displayMessage( String messageIn )
 433     {
 434         messageText.append( messageIn + "\n" );
 435         System.out.println(messageIn);
 436     }
 437 
 438 }// TestDialog  class