1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.quexec.testutil;
20
21
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.concurrent.CountDownLatch;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.junit.After;
30 import org.junit.Before;
31 import org.junit.BeforeClass;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public abstract class AbstractMultithreadedTest {
53
54 public interface Task {
55 public void doIt() throws Throwable;
56 }
57
58 private static final Log log = LogFactory.getLog(AbstractMultithreadedTest.class);
59
60 private static final List<Throwable> thrownByTest =
61 Collections.synchronizedList(new ArrayList<Throwable>(10));
62
63 private final List<Thread> testThreads =
64 Collections.synchronizedList(new ArrayList<Thread>(10));
65
66 private final CountDownLatch testStartLatch = new CountDownLatch(1);
67
68
69
70
71
72
73 @BeforeClass
74 public static void setUpMultithreadingBeforeClass() throws Throwable {
75 Thread.setDefaultUncaughtExceptionHandler(
76 new Thread.UncaughtExceptionHandler() {
77 public void uncaughtException(Thread t, Throwable e) {
78 thrownByTest.add(e);
79 log.error("Exception in thread '" + t.getName(),
80 e.fillInStackTrace());
81 throw new IllegalStateException(
82 "Exception in thread '" + t.getName() + "'",
83 e);
84 }
85 });
86 }
87
88
89
90
91
92
93 @Before
94 public void setUpMultithreading() {
95 thrownByTest.clear();
96 testThreads.clear();
97 }
98
99
100
101
102
103
104 @After
105 public void tearDownMultithreading() throws Throwable {
106 if (!thrownByTest.isEmpty()) {
107 Throwable e = thrownByTest.get(0);
108 log.warn("exception by test thread detected: ", e.fillInStackTrace());
109 throw e;
110 }
111 }
112
113 protected final Thread scheduleTask(final Task task, String name) {
114 Thread t = new Thread(name) {
115 public void run() {
116 try {
117 testStartLatch.await();
118 task.doIt();
119 }
120 catch (Throwable e) {
121 rethrowAsUnchecked(e);
122 }
123 }
124 };
125 t.start();
126 testThreads.add(t);
127 return t;
128 }
129
130 protected final void startAll() {
131 testStartLatch.countDown();
132 }
133
134 protected final void joinAll() throws InterruptedException {
135 for (Thread t : testThreads) {
136 log.debug("Waiting for thread: " + t);
137 t.join();
138 }
139 }
140
141 protected final void runAll() throws InterruptedException {
142 startAll();
143 joinAll();
144 }
145
146 private void rethrowAsUnchecked(Throwable e) {
147 if (e instanceof RuntimeException) {
148 throw (RuntimeException) e;
149 }
150 else if (e instanceof Error) {
151 throw (Error) e;
152 }
153 else {
154 throw new IllegalStateException(
155 "wrapped checked exception", e);
156 }
157 }
158 }