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 }