View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.tck.concurrency;
8   
9   import org.mule.util.concurrent.Latch;
10  
11  import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
12  
13  /**
14   * This class is very useful for test cases which need to make assertions 
15   * concurrently in different threads.  Usage is as follows:
16   * <code>
17   *   public void testConcurrency() 
18   *   {                
19   *       TestingThread thread = new TestingThread()
20   *       {
21   *           protected void doRun() throws Throwable
22   *           {
23   *               // Wait a few seconds for somethingElse to begin
24   *               Thread.sleep(3000);
25   *               assertTrue(somethingElse.isRunning());
26   *               assertEquals(3, somethingElse.counter);
27   *           }
28   *       };
29   *       thread.start();
30   *
31   *       // This will block the main test thread
32   *       runSomething("big long task");
33   *       assertEquals("peachy", something.getResult());
34   *       assertFalse(something.isOutOfControl());
35   *       
36   *       // Verify that no exceptions occurred meanwhile in the TestingThread
37   *       thread.await();
38   *       if (thread.getException() != null)
39   *       {
40   *           fail(thread.getException().getMessage());
41   *       }
42   *   }
43   * </code>
44   *   Both the TestingThread and the main thread will run in parallel, 
45   *   therefore assertions can be made on "somethingElse" while the call 
46   *   to runSomething() is blocking the main thread of the TestCase.
47   */
48  public abstract class TestingThread extends Thread implements Runnable
49  {
50      public static final long AWAIT_TIMEOUT = 10000;
51      private static final long awaitTimeout = Long.getLong("mule.test.timeoutSecs", AWAIT_TIMEOUT/1000L) * 1000L;
52      private final Latch done = new Latch();
53      private volatile Throwable exception = null;        
54  
55      /**
56       * Executes the doRun() method and stores any exception which occurred to be 
57       * returned at a later time.
58       */
59      @Override
60      public final void run() 
61      {
62          try
63          {
64              doRun();
65          }
66          catch (Throwable e)
67          {
68              exception = e;
69          }
70          finally
71          {
72              done.countDown();
73          }
74      }
75      
76      abstract protected void doRun() throws Throwable;
77  
78      /**
79       * Block until the thread completes its doRun() method.
80       * @throws InterruptedException
81       */
82      public void await() throws InterruptedException
83      {
84          done.await(awaitTimeout, TimeUnit.MILLISECONDS);
85      }
86  
87      /**
88       * @return any exception thrown by the doRun() method, including failed assertions
89       */
90      public Throwable getException()
91      {
92          return exception;
93      }
94  }