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 
init()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.
main( String args[] )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 
setTimeoutTo( int seconds )218     public static synchronized void setTimeoutTo( int seconds )
219     {
220         sleepTime = seconds * 1000;
221     }
222 
pass()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 
fail()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 
fail( String whyFailed )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 
createDialogWithInstructions( String[] instructions )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 
createDialog( )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 
printInstructions( String[] instructions )357     public static void printInstructions( String[] instructions )
358     {
359         dialog.printInstructions( instructions );
360     }
361 
362 
println( String messageIn )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
TestDialog( Frame frame, String name )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
printInstructions( String[] instructions )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
displayMessage( String messageIn )445     public void displayMessage( String messageIn )
446     {
447         messageText.append( messageIn + "\n" );
448         System.out.println(messageIn);
449     }
450 
451 }// TestDialog  class
452