1 /*
   2  * Copyright (c) 2010, 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 6424157
  27   @author Artem Ananiev: area=eventqueue
  28   @run main PreserveDispatchThread
  29 */
  30 
  31 import java.awt.*;
  32 import java.awt.event.*;
  33 
  34 public class PreserveDispatchThread {
  35 
  36     private static volatile Frame f;
  37     private static volatile Dialog d;
  38 
  39     private static volatile boolean isEDT = true;
  40 
  41     public static void main(String[] args) throws Exception {
  42         f = new Frame("F");
  43         f.setSize(320, 340);
  44         f.setLocationRelativeTo(null);
  45         f.setVisible(true);
  46 
  47         try {
  48             test1();
  49             if (!isEDT) {
  50                 throw new RuntimeException("Test FAILED (test1): event dispatch thread is changed");
  51             }
  52 
  53             test2();
  54             if (!isEDT) {
  55                 throw new RuntimeException("Test FAILED (test2): event dispatch thread is changed");
  56             }
  57 
  58             test3();
  59             if (!isEDT) {
  60                 throw new RuntimeException("Test FAILED (test3): event dispatch thread is changed");
  61             }
  62         } finally {
  63             if (d != null) {
  64                 d.dispose();
  65             }
  66             f.dispose();
  67         }
  68     }
  69 
  70     /*
  71      * Tests that push/pop doesn't change the dispatch thread if
  72      * called on EDT.
  73      */
  74     private static void test1() throws Exception {
  75         EventQueue.invokeAndWait(new Runnable() {
  76             @Override
  77             public void run() {
  78                 TestEventQueue teq = new TestEventQueue();
  79                 EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
  80                 try {
  81                     seq.push(teq);
  82                     d = new TestDialog();
  83                     d.setVisible(true);
  84                     checkEDT();
  85                 } finally {
  86                     teq.pop();
  87                 }
  88                 checkEDT();
  89             }
  90         });
  91     }
  92 
  93     /*
  94      * Tests that push/pop doesn't change the dispatch thread if
  95      * called on the main thread.
  96      */
  97     private static void test2() throws Exception {
  98         TestEventQueue teq = new TestEventQueue();
  99         EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
 100         try {
 101             seq.push(teq);
 102             EventQueue.invokeAndWait(new Runnable() {
 103                 @Override
 104                 public void run() {
 105                     checkEDT();
 106                     d = new TestDialog();
 107                     d.setVisible(true);
 108                     checkEDT();
 109                 }
 110             });
 111         } finally {
 112             teq.pop();
 113         }
 114     }
 115 
 116     private static final Object test3Lock = new Object();
 117     private static boolean test3Sync = false;
 118 
 119     /*
 120      * A complex test: several nested invokeLater() are called and
 121      * in every runnable a check for EDT is performed. At the ent
 122      * of the test we wait for all the runnables to be processed
 123      * and the dialog is disposed; otherwise the last EDT check can
 124      * be later than this method returns and the whole test is passed.
 125      */
 126     private static void test3() throws Exception {
 127         EventQueue.invokeLater(new Runnable() {
 128             @Override
 129             public void run() {
 130                 d = new Dialog(f, true);
 131                 d.setSize(240, 180);
 132                 d.setLocationRelativeTo(f);
 133                 EventQueue.invokeLater(new Runnable() {
 134                     @Override
 135                     public void run() {
 136                         d.setVisible(true);
 137                         checkEDT();
 138                     }
 139                 });
 140                 EventQueue.invokeLater(new Runnable() {
 141                     @Override
 142                     public void run() {
 143                         TestEventQueue teq = new TestEventQueue();
 144                         EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
 145                         try {
 146                             seq.push(teq);
 147                             checkEDT();
 148                             EventQueue.invokeLater(new Runnable() {
 149                                 @Override
 150                                 public void run() {
 151                                     d.dispose();
 152                                     checkEDT();
 153                                     synchronized (test3Lock) {
 154                                         test3Sync = true;
 155                                         test3Lock.notify();
 156                                     }
 157                                 }
 158                             });
 159                         } finally {
 160                             teq.pop();
 161                         }
 162                         checkEDT();
 163                     }
 164                 });
 165                 checkEDT();
 166             }
 167         });
 168         synchronized (test3Lock) {
 169             while (!test3Sync) {
 170                 try {
 171                     test3Lock.wait();
 172                 } catch (InterruptedException ie) {
 173                     break;
 174                 }
 175             }
 176         }
 177         // Make sure all the nested invokeLater/invokeAndWait are processed
 178         EventQueue.invokeAndWait(new Runnable() {
 179             @Override
 180             public void run() {
 181             }
 182         });
 183     }
 184 
 185     private static void checkEDT() {
 186         isEDT = isEDT && EventQueue.isDispatchThread();
 187     }
 188 
 189     private static class TestEventQueue extends EventQueue {
 190         public TestEventQueue() {
 191             super();
 192         }
 193         public void pop() {
 194             super.pop();
 195         }
 196     }
 197 
 198     private static class TestDialog extends Dialog {
 199         private volatile boolean dialogShown = false;
 200         private volatile boolean paintCalled = false;
 201         public TestDialog() {
 202             super(f, true);
 203             setSize(240, 180);
 204             setLocationRelativeTo(f);
 205             addComponentListener(new ComponentAdapter() {
 206                 @Override
 207                 public void componentShown(ComponentEvent e) {
 208                     if (paintCalled) {
 209                         dispose();
 210                     }
 211                     dialogShown = true;
 212                 }
 213             });
 214         }
 215         @Override
 216         public void paint(Graphics g) {
 217             if (dialogShown) {
 218                 dispose();
 219             }
 220             paintCalled = true;
 221         }
 222     }
 223 
 224 }