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