View Javadoc

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