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