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