1/*
2 * Copyright (c) 2014, 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
25import java.awt.*;
26import java.awt.event.InputEvent;
27import javax.swing.*;
28import java.io.*;
29import test.java.awt.regtesthelpers.Util;
30
31/**
32 * AWT/Swing overlapping test for Panel and JPanel behavior during resizing.
33 * <p>See <a href="https://bugs.openjdk.java.net/browse/JDK-6786219">JDK-6786219</a> for details
34 */
35/*
36 * @test
37 * @key headful
38 * @bug 6786219
39 * @summary Issues when resizing the frame after mixing of heavy weight & light weight components
40 * @author sergey.grinev@oracle.com: area=awt.mixing
41 * @library ../../regtesthelpers
42 * @build Util
43 * @build FrameBorderCounter
44 * @run main MixingPanelsResizing
45 */
46public class MixingPanelsResizing {
47
48    static volatile boolean failed = false;
49
50    private static JFrame frame;
51    private static JButton jbutton;
52    private static Button awtButton;
53    private static JButton jbutton2;
54    private static Button awtButton2;
55    private static final Color jbColor = Color.RED;
56    private static final Color awtColor = Color.ORANGE;
57    private static final Color jb2Color = Color.BLUE;
58    private static final Color awt2Color = Color.CYAN;
59    private static final int ROBOT_DELAY = 500;
60
61    private static Point lLoc;
62    private static int borderShift;
63
64    private static int frameBorderCounter() {
65        String JAVA_HOME = System.getProperty("java.home");
66        try {
67            Process p = Runtime.getRuntime().exec(JAVA_HOME + "/bin/java FrameBorderCounter");
68            try {
69                p.waitFor();
70            } catch (InterruptedException e) {
71                e.printStackTrace();
72                throw new RuntimeException(e);
73            }
74            if (p.exitValue() != 0) {
75                throw new RuntimeException("FrameBorderCounter exited with not null code!\n" + readInputStream(p.getErrorStream()));
76            }
77            return Integer.parseInt(readInputStream(p.getInputStream()).trim());
78        } catch (IOException e) {
79            e.printStackTrace();
80            throw new RuntimeException(e);
81        }
82    }
83
84    private static String readInputStream(InputStream is) throws IOException {
85        byte[] buffer = new byte[4096];
86        int len = 0;
87        StringBuilder sb = new StringBuilder();
88        try (InputStreamReader isr = new InputStreamReader(is)) {
89            while ((len = is.read(buffer)) > 0) {
90                sb.append(new String(buffer, 0, len));
91            }
92        }
93        return sb.toString();
94    }
95
96    private static void init() throws Exception {
97        //*** Create instructions for the user here ***
98
99        borderShift = frameBorderCounter();
100        borderShift = Math.abs(borderShift) == 1 ? borderShift : (borderShift / 2);
101        String[] instructions = {
102            "This is an AUTOMATIC test, simply wait until it is done.",
103            "The result (passed or failed) will be shown in the",
104            "message window below."
105        };
106        SwingUtilities.invokeAndWait(new Runnable() {
107            public void run() {
108                Sysout.createDialog();
109                Sysout.printInstructions(instructions);
110
111                // prepare controls
112
113                frame = new JFrame();
114
115                Panel awtPanel = new Panel();
116                awtPanel.setBackground(Color.GREEN);
117                awtButton = new Button("AWTButton");
118                awtPanel.add(awtButton);
119                awtButton.setForeground(awtColor);
120                awtButton.setBackground(awtColor);
121                jbutton = new JButton("SwingButton");
122                awtPanel.add(jbutton);
123                jbutton.setForeground(jbColor);
124                jbutton.setBackground(jbColor);
125
126                JPanel jPanel = new JPanel();
127                jbutton2 = new JButton("SwingButton2");
128                jPanel.add(jbutton2);
129                jbutton2.setForeground(jb2Color);
130                jbutton2.setBackground(jb2Color);
131                awtButton2 = new Button("AWT Button2");
132                jPanel.add(awtButton2);
133                awtButton2.setForeground(awt2Color);
134                awtButton2.setBackground(awt2Color);
135                jPanel.setBackground(Color.YELLOW);
136
137                frame.add(awtPanel, BorderLayout.SOUTH);
138                frame.add(jPanel, BorderLayout.NORTH);
139
140                frame.pack();
141                frame.setVisible(true);
142            }
143        });
144
145        /////////////////////////
146
147        final Robot robot = Util.createRobot();
148        robot.setAutoDelay(ROBOT_DELAY);
149
150        Util.waitForIdle(robot);
151
152        SwingUtilities.invokeAndWait(new Runnable() {
153            public void run() {
154                lLoc = frame.getLocationOnScreen();
155                lLoc.translate(frame.getWidth() + borderShift, frame.getHeight() + borderShift);
156            }
157        });
158
159        //grow
160        robot.mouseMove(lLoc.x, lLoc.y);
161        robot.mousePress(InputEvent.BUTTON1_MASK);
162
163        Runnable test = new Runnable() {
164
165            public void run() {
166                Point btnLoc = jbutton.getLocationOnScreen();
167                Color c = robot.getPixelColor(btnLoc.x + 5, btnLoc.y + 5);
168                if (!c.equals(jbColor)) {
169                    fail("JButton was not redrawn properly on AWT Panel during move");
170                }
171
172                btnLoc = awtButton.getLocationOnScreen();
173                c = robot.getPixelColor(btnLoc.x + 5, btnLoc.y + 5);
174                if (!c.equals(awtColor)) {
175                    fail("AWT Button was not redrawn properly on AWT Panel during move");
176                }
177
178                btnLoc = jbutton2.getLocationOnScreen();
179                c = robot.getPixelColor(btnLoc.x + 5, btnLoc.y + 5);
180                if (!c.equals(jb2Color)) {
181                    fail("JButton was not redrawn properly on JPanel during move");
182                }
183
184                btnLoc = awtButton2.getLocationOnScreen();
185                c = robot.getPixelColor(btnLoc.x + 5, btnLoc.y + 5);
186                if (!c.equals(awt2Color)) {
187                    fail("ATW Button was not redrawn properly on JPanel during move");
188                }
189            }
190        };
191
192        for (int i = 0; i < 30; i++) {
193            test.run();
194            robot.mouseMove(lLoc.x + 20 * i, lLoc.y + 10 * i);
195        }
196        robot.mouseRelease(InputEvent.BUTTON1_MASK);
197
198        //back
199        System.out.println("fast back");
200        robot.mousePress(InputEvent.BUTTON1_MASK);
201        for (int i = 5; i >= 0; i--) {
202            test.run();
203            robot.mouseMove(lLoc.x + 120 * i, lLoc.y + 60 * i);
204        }
205        robot.mouseRelease(InputEvent.BUTTON1_MASK);
206
207        pass();
208    }//End  init()
209    /*****************************************************
210     * Standard Test Machinery Section
211     * DO NOT modify anything in this section -- it's a
212     * standard chunk of code which has all of the
213     * synchronisation necessary for the test harness.
214     * By keeping it the same in all tests, it is easier
215     * to read and understand someone else's test, as
216     * well as insuring that all tests behave correctly
217     * with the test harness.
218     * There is a section following this for test-
219     * classes
220     ******************************************************/
221    private static boolean theTestPassed = false;
222    private static boolean testGeneratedInterrupt = false;
223    private static String failureMessage = "";
224    private static Thread mainThread = null;
225    private static int sleepTime = 300000;
226
227    // Not sure about what happens if multiple of this test are
228    //  instantiated in the same VM.  Being static (and using
229    //  static vars), it aint gonna work.  Not worrying about
230    //  it for now.
231    public static void main(String args[]) throws Exception {
232        if (!Toolkit.getDefaultToolkit().isDynamicLayoutActive()) {
233            System.out.println("Dynamic layout is not active. Test passes.");
234            return;
235        }
236        mainThread = Thread.currentThread();
237        try {
238            init();
239        } catch (TestPassedException e) {
240            //The test passed, so just return from main and harness will
241            // interepret this return as a pass
242            return;
243        }
244        //At this point, neither test pass nor test fail has been
245        // called -- either would have thrown an exception and ended the
246        // test, so we know we have multiple threads.
247
248        //Test involves other threads, so sleep and wait for them to
249        // called pass() or fail()
250        try {
251            Thread.sleep(sleepTime);
252            //Timed out, so fail the test
253            throw new RuntimeException("Timed out after " + sleepTime / 1000 + " seconds");
254        } catch (InterruptedException e) {
255            //The test harness may have interrupted the test.  If so, rethrow the exception
256            // so that the harness gets it and deals with it.
257            if (!testGeneratedInterrupt) {
258                throw e;
259            }
260
261            //reset flag in case hit this code more than once for some reason (just safety)
262            testGeneratedInterrupt = false;
263
264            if (theTestPassed == false) {
265                throw new RuntimeException(failureMessage);
266            }
267        }
268
269    }//main
270
271    public static synchronized void setTimeoutTo(int seconds) {
272        sleepTime = seconds * 1000;
273    }
274
275    public static synchronized void pass() {
276        Sysout.println("The test passed.");
277        Sysout.println("The test is over, hit  Ctl-C to stop Java VM");
278        //first check if this is executing in main thread
279        if (mainThread == Thread.currentThread()) {
280            //Still in the main thread, so set the flag just for kicks,
281            // and throw a test passed exception which will be caught
282            // and end the test.
283            theTestPassed = true;
284            throw new TestPassedException();
285        }
286        theTestPassed = true;
287        testGeneratedInterrupt = true;
288        mainThread.interrupt();
289    }//pass()
290
291    public static synchronized void fail() {
292        //test writer didn't specify why test failed, so give generic
293        fail("it just plain failed! :-)");
294    }
295
296    public static synchronized void fail(String whyFailed) {
297        Sysout.println("The test failed: " + whyFailed);
298        Sysout.println("The test is over, hit  Ctl-C to stop Java VM");
299        //check if this called from main thread
300        if (mainThread == Thread.currentThread()) {
301            //If main thread, fail now 'cause not sleeping
302            throw new RuntimeException(whyFailed);
303        }
304        theTestPassed = false;
305        testGeneratedInterrupt = true;
306        failureMessage = whyFailed;
307        mainThread.interrupt();
308    }//fail()
309}// class JButtonInGlassPane
310class TestPassedException extends RuntimeException {
311}
312
313//*********** End Standard Test Machinery Section **********
314//************ Begin classes defined for the test ****************
315// if want to make listeners, here is the recommended place for them, then instantiate
316//  them in init()
317
318/* Example of a class which may be written as part of a test
319class NewClass implements anInterface
320{
321static int newVar = 0;
322
323public void eventDispatched(AWTEvent e)
324{
325//Counting events to see if we get enough
326eventCount++;
327
328if( eventCount == 20 )
329{
330//got enough events, so pass
331
332JButtonInGlassPane.pass();
333}
334else if( tries == 20 )
335{
336//tried too many times without getting enough events so fail
337
338JButtonInGlassPane.fail();
339}
340
341}// eventDispatched()
342
343}// NewClass class
344
345 */
346//************** End classes defined for the test *******************
347/****************************************************
348Standard Test Machinery
349DO NOT modify anything below -- it's a standard
350chunk of code whose purpose is to make user
351interaction uniform, and thereby make it simpler
352to read and understand someone else's test.
353 ****************************************************/
354/**
355This is part of the standard test machinery.
356It creates a dialog (with the instructions), and is the interface
357for sending text messages to the user.
358To print the instructions, send an array of strings to Sysout.createDialog
359WithInstructions method.  Put one line of instructions per array entry.
360To display a message for the tester to see, simply call Sysout.println
361with the string to be displayed.
362This mimics System.out.println but works within the test harness as well
363as standalone.
364 */
365class Sysout {
366
367    private static TestDialog dialog;
368
369    public static void createDialogWithInstructions(String[] instructions) {
370        dialog = new TestDialog(new Frame(), "Instructions");
371        dialog.printInstructions(instructions);
372        //dialog.setVisible(true);
373        println("Any messages for the tester will display here.");
374    }
375
376    public static void createDialog() {
377        dialog = new TestDialog(new Frame(), "Instructions");
378        String[] defInstr = {"Instructions will appear here. ", ""};
379        dialog.printInstructions(defInstr);
380        //dialog.setVisible(true);
381        println("Any messages for the tester will display here.");
382    }
383
384    public static void printInstructions(String[] instructions) {
385        dialog.printInstructions(instructions);
386    }
387
388    public static void println(String messageIn) {
389        dialog.displayMessage(messageIn);
390        System.out.println(messageIn);
391    }
392}// Sysout  class
393
394/**
395This is part of the standard test machinery.  It provides a place for the
396test instructions to be displayed, and a place for interactive messages
397to the user to be displayed.
398To have the test instructions displayed, see Sysout.
399To have a message to the user be displayed, see Sysout.
400Do not call anything in this dialog directly.
401 */
402class TestDialog extends Dialog {
403
404    TextArea instructionsText;
405    TextArea messageText;
406    int maxStringLength = 80;
407
408    //DO NOT call this directly, go through Sysout
409    public TestDialog(Frame frame, String name) {
410        super(frame, name);
411        int scrollBoth = TextArea.SCROLLBARS_BOTH;
412        instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
413        add("North", instructionsText);
414
415        messageText = new TextArea("", 5, maxStringLength, scrollBoth);
416        add("Center", messageText);
417
418        pack();
419
420        //setVisible(true);
421    }// TestDialog()
422
423    //DO NOT call this directly, go through Sysout
424    public void printInstructions(String[] instructions) {
425        //Clear out any current instructions
426        instructionsText.setText("");
427
428        //Go down array of instruction strings
429
430        String printStr, remainingStr;
431        for (int i = 0; i < instructions.length; i++) {
432            //chop up each into pieces maxSringLength long
433            remainingStr = instructions[i];
434            while (remainingStr.length() > 0) {
435                //if longer than max then chop off first max chars to print
436                if (remainingStr.length() >= maxStringLength) {
437                    //Try to chop on a word boundary
438                    int posOfSpace = remainingStr.lastIndexOf(' ', maxStringLength - 1);
439
440                    if (posOfSpace <= 0) {
441                        posOfSpace = maxStringLength - 1;
442                    }
443
444                    printStr = remainingStr.substring(0, posOfSpace + 1);
445                    remainingStr = remainingStr.substring(posOfSpace + 1);
446                } //else just print
447                else {
448                    printStr = remainingStr;
449                    remainingStr = "";
450                }
451
452                instructionsText.append(printStr + "\n");
453
454            }// while
455
456        }// for
457
458    }//printInstructions()
459
460    //DO NOT call this directly, go through Sysout
461    public void displayMessage(String messageIn) {
462        messageText.append(messageIn + "\n");
463        System.out.println(messageIn);
464    }
465}// TestDialog  class
466
467