1 /*
   2  * Copyright (c) 2009, 2017, 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 6799345
  27  * @key headful
  28  * @summary Tests that no exceptions are thrown from TimerQueue and
  29  * SwingWorker on AppContext shutdown
  30  * @author art
  31  * @modules java.desktop/sun.awt
  32  * @run main TestShutdown
  33  */
  34 
  35 import java.awt.*;
  36 import java.awt.event.*;
  37 
  38 import java.util.*;
  39 
  40 import javax.swing.*;
  41 
  42 import sun.awt.*;
  43 
  44 public class TestShutdown
  45 {
  46     private static AppContext targetAppContext;
  47 
  48     private static JFrame f;
  49     private static JTextField tf;
  50 
  51     private static volatile boolean exceptionsOccurred = false;
  52     private static volatile boolean appcontextInitDone = false;
  53 
  54     private static int timerValue = 0;
  55 
  56     public static void main(String[] args)
  57         throws Exception
  58     {
  59         ThreadGroup tg = new TestThreadGroup("TTG");
  60         Thread t = new Thread(tg, new TestRunnable(), "InitThread");
  61         t.start();
  62 
  63         while (!appcontextInitDone)
  64         {
  65             Thread.sleep(1000);
  66         }
  67 
  68         targetAppContext.dispose();
  69 
  70         if (exceptionsOccurred)
  71         {
  72             throw new RuntimeException("Test FAILED: some exceptions occurred");
  73         }
  74     }
  75 
  76     static void initGUI()
  77     {
  78         f = new JFrame("F");
  79         f.setBounds(100, 100, 200, 100);
  80         tf = new JTextField("Test");
  81         f.add(tf);
  82         f.setVisible(true);
  83     }
  84 
  85     static void startGUI()
  86     {
  87         // caret blink Timer
  88         tf.requestFocusInWindow();
  89 
  90         // misc Timer
  91         ActionListener al = new ActionListener()
  92         {
  93             @Override
  94             public void actionPerformed(ActionEvent ae)
  95             {
  96                 System.out.println("Timer tick: " + timerValue++);
  97             }
  98         };
  99         new javax.swing.Timer(30, al).start();
 100     }
 101 
 102     static class TestThreadGroup extends ThreadGroup
 103     {
 104         public TestThreadGroup(String name)
 105         {
 106             super(name);
 107         }
 108 
 109         @Override
 110         public synchronized void uncaughtException(Thread thread, Throwable t)
 111         {
 112             if (t instanceof ThreadDeath)
 113             {
 114                 // this one is expected, rethrow
 115                 throw (ThreadDeath)t;
 116             }
 117             System.err.println("Test FAILED: an exception is caught in the " +
 118                                "target thread group on thread " + thread.getName());
 119             t.printStackTrace(System.err);
 120             exceptionsOccurred = true;
 121         }
 122     }
 123 
 124     static class TestRunnable implements Runnable
 125     {
 126         @Override
 127         public void run()
 128         {
 129             SunToolkit stk = (SunToolkit)Toolkit.getDefaultToolkit();
 130             targetAppContext = stk.createNewAppContext();
 131 
 132             // create and show frame and text field
 133             SwingUtilities.invokeLater(new Runnable()
 134             {
 135                 @Override
 136                 public void run()
 137                 {
 138                     initGUI();
 139                 }
 140             });
 141             stk.realSync();
 142 
 143             // start some Timers
 144             SwingUtilities.invokeLater(new Runnable()
 145             {
 146                 @Override
 147                 public void run()
 148                 {
 149                     startGUI();
 150                 }
 151             });
 152 
 153             // start multiple SwingWorkers
 154             while (!Thread.interrupted())
 155             {
 156                 try
 157                 {
 158                     new TestSwingWorker().execute();
 159                     Thread.sleep(40);
 160                 }
 161                 catch (Exception e)
 162                 {
 163                     // exception here is expected, skip
 164                     break;
 165                 }
 166             }
 167         }
 168     }
 169 
 170     static class TestSwingWorker extends SwingWorker<String, Integer>
 171     {
 172         @Override
 173         public String doInBackground()
 174         {
 175             Random r = new Random();
 176             for (int i = 0; i < 10; i++)
 177             {
 178                 try
 179                 {
 180                     int delay = r.nextInt() % 50;
 181                     Thread.sleep(delay);
 182                     publish(delay);
 183                 }
 184                 catch (Exception z)
 185                 {
 186                     break;
 187                 }
 188             }
 189             if (!appcontextInitDone)
 190             {
 191                 appcontextInitDone = true;
 192             }
 193             return "Done";
 194         }
 195 
 196         @Override
 197         public void process(java.util.List<Integer> chunks)
 198         {
 199             for (Integer i : chunks)
 200             {
 201                 System.err.println("Processed: " + i);
 202             }
 203         }
 204     }
 205 }