1 /*
   2  * Copyright (c) 2014, 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 import java.awt.*;
  26 import java.awt.event.*;
  27 
  28 /*
  29  * @test
  30  * @summary  To Test the following assertions in InvovationEvent.
  31  * 1.InvocationEvent when dispatched, should invoke the
  32  *   run() method of the Runnable Interface.
  33  * 2.If catchExceptions is false, Exception should be
  34  *   propagated up to the EventDispatchThread's dispatch loop.
  35  * 3.If catchExceptions is true, InvocationEvent.getExceptions()
  36  *   should return the exception thrown inside thr run() method.
  37  * 4.When InvocationEvent object is posted on to the EventQueue,
  38  *   InvocationEvent.dispatch() method should be invoked by the
  39  *   EventQueue.
  40  * 5.If the notifier object is not null, notifyAll() of the
  41  *   notifier object should be invoked when the run() method returns.
  42  * 6.To test whether the threads are invoked in the right order
  43  *   When InvocationEvents are nested.
  44  * 7.The getWhen method should return timestamp which is less than
  45  *   current System time and greater than the time before it has
  46  *   actually happened
  47  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
  48  * @run main InvocationEventTest
  49  */
  50 
  51 public class InvocationEventTest {
  52     EventQueue eventQ1 = new EventQueue();
  53 
  54     Object lock = new Object();
  55 
  56     static final int delay = 5000;
  57 
  58     public volatile boolean notifierStatus = false;
  59     public Object notifierLock = new Object();
  60 
  61     public volatile boolean threadStatus = false;
  62     public volatile boolean childInvoked = false;
  63 
  64     public synchronized void doTest() throws Exception {
  65         // Testing assertions 1, 2 and 7:
  66         // 1.InvocationEvent when dispatched, should invoke the
  67         //   run() method of the Runnable Interface.
  68         // 2.If catchExceptions is false, Exception should be
  69         //   propagated up to the EventDispatchThread's dispatch loop.
  70         // 7.The getWhen method should return timestamp which is less than
  71         //   current System time and greater than the time before it has
  72         //   actually happened
  73 
  74         long timeBeforeInvoking = System.currentTimeMillis();
  75 
  76         Thread.sleep(10);
  77 
  78         InvocationEvent invoc = new InvocationEvent(this, () -> { threadStatus = true; }, lock, false);
  79         invoc.dispatch();
  80 
  81         Thread.sleep(10);
  82 
  83         if (!threadStatus) {
  84             synchronized (lock) {
  85                 lock.wait(delay);
  86             }
  87         }
  88 
  89         // testing getException() when no exception is thrown
  90         if (invoc.getWhen() <= timeBeforeInvoking ||
  91                 invoc.getWhen() >= System.currentTimeMillis()) {
  92             throw new RuntimeException("getWhen method is not getting the time at which event occured");
  93         }
  94 
  95         if (invoc.getException() != null) {
  96             throw new RuntimeException("InvocationEvent.getException() does not return null " +
  97                     "when catchException is false");
  98         }
  99 
 100         // testing the normal behaviour of InvocationEvent
 101         if (!threadStatus) {
 102             throw new RuntimeException("InvocationEvent when dispatched, did not" +
 103                     " invoke the run() of the Runnable interface  ");
 104         }
 105         threadStatus = false;
 106 
 107         // Testing assertion 3:
 108         // 3.If catchExceptions is true, InvocationEvent.getExceptions()
 109         //   should return the exception thrown inside the run() method.
 110         RuntimeException sampleExn = new RuntimeException(" test exception");
 111 
 112         invoc = new InvocationEvent(this, () -> { threadStatus = true; throw sampleExn; }, lock, true);
 113         invoc.dispatch();
 114         if (!threadStatus) {
 115             synchronized (lock) {
 116                 lock.wait(delay);
 117             }
 118         }
 119         // testing getException() when exception is thrown
 120         // Should return the same exception thrown inside the run() method
 121         if (!invoc.getException().equals(sampleExn)) {
 122             throw new RuntimeException("getException() does not return " +
 123                     "the same Exception thrown inside the run() method ");
 124         }
 125         threadStatus = false;
 126 
 127         // Testing assertions 4 and 5:
 128         // 4.When InvocationEvent object is posted on to the EventQueue,
 129         //   InvocationEvent.dispatch() method should be invoked by the
 130         //   EventQueue.
 131         // 5.If the notifier object is not null, notifyAll() of the
 132         //   notifier object should be invoked when the run() method returns.
 133 
 134         Thread notify = new Thread(){
 135             public void run() {
 136                 synchronized (this) {
 137                     try { wait(); } catch (InterruptedException e) { throw new RuntimeException(e); }
 138                 }
 139                 notifierStatus = true;
 140                 synchronized (notifierLock) {
 141                     notifierLock.notifyAll();
 142                 }
 143             }
 144         };
 145         notify.start();
 146 
 147         while (notify.getState() != Thread.State.WAITING)
 148             Thread.sleep(delay/5);
 149 
 150         InvocationEvent invocation = new InvocationEvent(this, () -> { }, (Object) notify, false);
 151         eventQ1.postEvent(invocation);
 152 
 153         while(!invocation.isDispatched())
 154             synchronized (notifierLock) {
 155                 notifierLock.wait(delay);
 156             }
 157 
 158         while (notify.getState() != Thread.State.TERMINATED)
 159             Thread.sleep(delay/5);
 160 
 161         if (!notifierStatus) {
 162             throw new RuntimeException("Notifier object did not get notified" +
 163                     " When the run method of the Runnable returns ");
 164         }
 165 
 166         // Testing assertion 6:
 167         // 6.To test whether the threads are invoked in the right order
 168         //   When InvocationEvents are nested.
 169         Thread thread = new Thread(){
 170             public void run() {
 171                 InvocationEvent evt = new InvocationEvent(this, () -> { childInvoked = true; }, (Object) this, false);
 172                 new EventQueue().postEvent(evt);
 173                 synchronized (this) {
 174                     try {
 175                         wait(delay);
 176                     } catch (InterruptedException e) {
 177                         throw new RuntimeException(e);
 178                     }
 179                 }
 180                 threadStatus = true;
 181             }
 182         };
 183 
 184         invocation = new InvocationEvent(this, thread, lock, false);
 185 
 186         eventQ1.postEvent(invocation);
 187 
 188         while (!invocation.isDispatched())
 189             synchronized (lock) {
 190                 lock.wait(delay);
 191             }
 192 
 193         if (!threadStatus || !childInvoked) {
 194             throw new RuntimeException("Nesting of InvocationEvents when dispatched," +
 195                     " did not invoke the run() of the Runnables properly ");
 196         }
 197     }
 198 
 199     public static void main(String[] args) throws Exception {
 200         new InvocationEventTest().doTest();
 201     }
 202 }
 203