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 }