1 /*
2  * Copyright (c) 1998, 2013, 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  *
26  * @bug 4023283
27  * @key headful
28  * @summary Checks that an Error which propogates up to the EventDispatch
29  * loop does not crash AWT.
30  * @author Andrei Dmitriev: area=awt.event
31  * @library ../../regtesthelpers
32  * @build Util
33  * @run main LoopRobustness
34  */
35 
36 import java.awt.*;
37 import java.awt.event.*;
38 
39 import sun.awt.SunToolkit;
40 
41 import test.java.awt.regtesthelpers.Util;
42 
43 public class LoopRobustness {
44 
45     final static long TIMEOUT = 5000;
46     final static Object LOCK = new Object();
47 
48     public static int clicks = 0;
49     public static volatile boolean notifyOccured = false;
50     public static volatile boolean otherExceptionsCaught = false;
51 
main(String [] args)52     public static void main(String [] args) throws Exception {
53         SunToolkit.createNewAppContext();
54 
55         ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
56 
57         long at;
58         //wait for a TIMEOUT giving a chance to a new Thread above to accomplish its stuff.
59         synchronized (LoopRobustness.LOCK) {
60             new Thread(new TestThreadGroup(mainThreadGroup, "TestGroup"), new Impl()).start();
61             at = System.currentTimeMillis();
62             try {
63                 while (!notifyOccured && (System.currentTimeMillis() - at < TIMEOUT)) {
64                     LoopRobustness.LOCK.wait(1000);
65                 }
66             } catch (InterruptedException e) {
67                 throw new RuntimeException("Test interrupted.", e);
68             }
69         }
70 
71         if (!notifyOccured) {
72             //notify doesn't occur after a reasonable time.
73             throw new RuntimeException("Test FAILED: second thread hasn't notified MainThread");
74         }
75 
76         //now wait for two clicks
77         at = System.currentTimeMillis();
78         while(System.currentTimeMillis() - at < TIMEOUT && clicks < 2) {
79             try {
80                 Thread.sleep(100);
81             } catch(InterruptedException e) {
82                 throw new RuntimeException("Test interrupted.", e);
83             }
84         }
85         if (clicks != 2) {
86             throw new RuntimeException("Test FAILED: robot should press button twice");
87         }
88         if (otherExceptionsCaught) {
89             throw new RuntimeException("Test FAILED: unexpected exceptions caught");
90         }
91     }
92 }
93 
94 class Impl implements Runnable{
95     static Robot robot;
run()96     public void run() {
97         SunToolkit.createNewAppContext();
98 
99         Button b = new Button("Press me to test the AWT-Event Queue thread");
100         Frame lr = new Frame("ROBUST FRAME");
101         lr.setBounds(100, 100, 300, 100);
102         b.addActionListener(new ActionListener() {
103                 public void actionPerformed(ActionEvent e) {
104                     LoopRobustness.clicks++;
105                     //throwing an exception in Static Initializer
106                     System.out.println(HostileCrasher.aStaticMethod());
107                 }
108             });
109         lr.add(b);
110         lr.setVisible(true);
111 
112         try {
113             robot = new Robot();
114         } catch (AWTException e) {
115             throw new RuntimeException("Test interrupted.", e);
116         }
117         Util.waitForIdle(robot);
118 
119         synchronized (LoopRobustness.LOCK){
120             LoopRobustness.LOCK.notify();
121             LoopRobustness.notifyOccured = true;
122         }
123 
124         int i = 0;
125         while (i < 2) {
126             robot.mouseMove(b.getLocationOnScreen().x + b.getWidth()/2,
127                             b.getLocationOnScreen().y + b.getHeight()/2);
128             Util.waitForIdle(robot);
129             robot.mousePress(InputEvent.BUTTON1_MASK);
130             Util.waitForIdle(robot);
131             robot.mouseRelease(InputEvent.BUTTON1_MASK);
132             Util.waitForIdle(robot);
133             i++;
134         }
135     }
136 }
137 
138 class TestThreadGroup extends ThreadGroup {
TestThreadGroup(ThreadGroup threadGroup, String name)139     TestThreadGroup(ThreadGroup threadGroup, String name) {
140         super(threadGroup, name);
141     }
142 
uncaughtException(Thread thread, Throwable e)143     public void uncaughtException(Thread thread, Throwable e) {
144         System.out.println("Exception caught: " + e);
145         e.printStackTrace(System.out);
146         System.out.flush();
147         if ((e instanceof ExceptionInInitializerError) ||
148             (e instanceof NoClassDefFoundError))
149         {
150             // These two are expected
151             return;
152         }
153         LoopRobustness.otherExceptionsCaught = true;
154     }
155 }
156 
157 class HostileCrasher {
158     static {
159         if (Math.random() >= 0.0) {
160             throw new RuntimeException("Die, AWT-Event Queue thread!");
161         }
162     }
aStaticMethod()163     public static String aStaticMethod() {
164         return "hello, world";
165     }
166 }
167