test/jdk/java/awt/event/SequencedEvent/MultipleContextsUnitTest.java
changeset 52558 08a0bf1592bd
equal deleted inserted replaced
52557:2f6f97629aa7 52558:08a0bf1592bd
       
     1 /*
       
     2  * Copyright (c) 2018, 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 import java.awt.AWTEvent;
       
    25 import java.awt.event.InvocationEvent;
       
    26 import java.lang.reflect.Constructor;
       
    27 import java.util.concurrent.CountDownLatch;
       
    28 import java.util.concurrent.atomic.AtomicReference;
       
    29 
       
    30 import sun.awt.AppContext;
       
    31 import sun.awt.SunToolkit;
       
    32 
       
    33 /**
       
    34  * @test
       
    35  * @bug 8204142
       
    36  * @author Sergey Bylokhov
       
    37  * @key headful
       
    38  * @modules java.desktop/sun.awt
       
    39  * @run main/othervm/timeout=30 MultipleContextsUnitTest
       
    40  */
       
    41 public final class MultipleContextsUnitTest {
       
    42 
       
    43     private static final int COUNT = 20;
       
    44     private static final AppContext[] apps = new AppContext[COUNT];
       
    45     private static final CountDownLatch go = new CountDownLatch(1);
       
    46     private static final CountDownLatch end = new CountDownLatch(COUNT);
       
    47 
       
    48     private static volatile int createSENumber = 0;
       
    49     private static volatile int dispatchSENumber = 0;
       
    50 
       
    51     public static void main(final String[] args) throws Exception {
       
    52         for (int i = 0; i < COUNT; i++) {
       
    53             Thread t = testThread(i);
       
    54             t.start();
       
    55             t.join();
       
    56         }
       
    57 
       
    58         for (AppContext app : apps) {
       
    59             SunToolkit.postEvent(app, new InvocationEvent(new Object(), () -> {
       
    60                 try {
       
    61                     go.await();
       
    62                 } catch (InterruptedException e) {
       
    63                     throw new RuntimeException(e);
       
    64                 }
       
    65             }));
       
    66         }
       
    67 
       
    68         // eventOne - created first, but posted last
       
    69         AWTEvent eventOne = getSequencedEvent();
       
    70         {
       
    71             // eventTwo and eventThree - posted in the reverse order
       
    72             AppContext app = apps[1];
       
    73             AWTEvent eventTwo = getSequencedEvent();
       
    74             AWTEvent eventThree = getSequencedEvent();
       
    75             SunToolkit.postEvent(app, eventThree);
       
    76             SunToolkit.postEvent(app, eventTwo);
       
    77             SunToolkit.postEvent(app, new InvocationEvent(new Object(), () -> {
       
    78                 System.err.println(AppContext.getAppContext());
       
    79                 end.countDown();
       
    80             }));
       
    81         }
       
    82 
       
    83         for (int i = 2; i < apps.length; i++) {
       
    84             // eventTwo and eventThree - posted in the correct order
       
    85             AppContext app = apps[i];
       
    86 
       
    87             AWTEvent eventTwo = getSequencedEvent();
       
    88             SunToolkit.postEvent(app, eventTwo);
       
    89 
       
    90             AtomicReference<Boolean> called1 = new AtomicReference(false);
       
    91             AtomicReference<Boolean> called2 = new AtomicReference(false);
       
    92             int num1 = createSENumber;
       
    93             SunToolkit.postEvent(app, new InvocationEvent(new Object(), () -> {
       
    94                 if (dispatchSENumber < num1) {
       
    95                     throw new RuntimeException("Dispatched too early");
       
    96                 }
       
    97                 called1.set(true);
       
    98                 if (called2.get()) {
       
    99                     throw new RuntimeException("Second event is called before first");
       
   100                 }
       
   101             }));
       
   102             AWTEvent eventThree = getSequencedEvent();
       
   103             SunToolkit.postEvent(app, eventThree);
       
   104             int num2 = createSENumber;
       
   105             SunToolkit.postEvent(app, new InvocationEvent(new Object(), () -> {
       
   106                 if (dispatchSENumber < num2) {
       
   107                     throw new RuntimeException("Dispatched too early");
       
   108                 }
       
   109                 called2.set(true);
       
   110                 if (!called1.get()) {
       
   111                     throw new RuntimeException("First event is not called before second");
       
   112                 }
       
   113                 System.err.println(AppContext.getAppContext());
       
   114                 end.countDown();
       
   115             }));
       
   116         }
       
   117 
       
   118 
       
   119 
       
   120         // eventOne should flush all EDT
       
   121         SunToolkit.postEvent(apps[0], eventOne);
       
   122         SunToolkit.postEvent(apps[0], new InvocationEvent(new Object(), () -> {
       
   123             System.err.println(AppContext.getAppContext());
       
   124             end.countDown();
       
   125         }));
       
   126 
       
   127         go.countDown();
       
   128 
       
   129         System.err.println("Start to wait");
       
   130         end.await();
       
   131         System.err.println("End to wait");
       
   132     }
       
   133 
       
   134     private static Thread testThread(int index) {
       
   135         final ThreadGroup group = new ThreadGroup("TG " + index);
       
   136         return new Thread(group, () -> {
       
   137             apps[index] = SunToolkit.createNewAppContext();
       
   138         });
       
   139     }
       
   140 
       
   141     private static AWTEvent getSequencedEvent()
       
   142     {
       
   143         int num = createSENumber++;
       
   144 
       
   145         InvocationEvent wrapMe = new InvocationEvent(new Object(), () -> {
       
   146             if (num != dispatchSENumber++) {
       
   147                 System.err.println("num: " + num);
       
   148                 System.err.println("dispatchSENumber: " + dispatchSENumber);
       
   149                 throw new RuntimeException("Wrong order");
       
   150             }
       
   151         });
       
   152 
       
   153         try {
       
   154             /*
       
   155              * SequencedEvent is a package private class, which cannot be instantiated
       
   156              * by importing. So use reflection to create an instance.
       
   157              */
       
   158             Class<? extends AWTEvent> seqClass = (Class<? extends AWTEvent>) Class.forName("java.awt.SequencedEvent");
       
   159             Constructor<? extends AWTEvent>
       
   160                     seqConst = seqClass.getConstructor(AWTEvent.class);
       
   161             seqConst.setAccessible(true);
       
   162             return seqConst.newInstance(wrapMe);
       
   163         } catch (Throwable err) {
       
   164             throw new RuntimeException("Unable to instantiate SequencedEvent",err);
       
   165         }
       
   166     }
       
   167 }