1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.transaction.locking;
18
19 import static junit.framework.Assert.assertEquals;
20 import static junit.framework.Assert.assertTrue;
21
22 import java.util.concurrent.TimeUnit;
23
24 import junit.framework.JUnit4TestAdapter;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.commons.transaction.util.RendezvousBarrier;
29 import org.junit.Test;
30
31 /**
32 * Tests for locking.
33 *
34 */
35 public class LockTest {
36
37 private Log log = LogFactory.getLog(getClass());
38
39 private static final int CONCURRENT_TESTS = 25;
40
41 protected static final long TIMEOUT = 1000000;
42
43 private static int deadlockCnt = 0;
44
45 private static String defaultResource = "resource";
46
47 public static junit.framework.Test suite() {
48 return new JUnit4TestAdapter(LockTest.class);
49 }
50
51 public static void main(java.lang.String[] args) {
52 junit.textui.TestRunner.run(suite());
53 }
54
55 @Test
56 public void deadlock() throws Throwable {
57
58 log.info("\n\nChecking deadlock detection\n\n");
59
60 final String res1 = "res1";
61 final String res2 = "res2";
62
63 final RWLockManager<Object, Object> manager = new RWLockManager<Object, Object>();
64
65 final RendezvousBarrier restart = new RendezvousBarrier("restart", TIMEOUT);
66
67 for (int i = 0; i < CONCURRENT_TESTS; i++) {
68
69 System.out.print(".");
70
71 final RendezvousBarrier deadlockBarrier1 = new RendezvousBarrier("deadlock1" + i,
72 TIMEOUT);
73
74 Thread deadlock = new Thread(new Runnable() {
75 public void run() {
76 try {
77 manager.startWork(10, TimeUnit.SECONDS);
78
79 manager.lock(defaultResource, res2, true);
80 synchronized (deadlockBarrier1) {
81 deadlockBarrier1.meet();
82 deadlockBarrier1.reset();
83 }
84
85
86 manager.lock(defaultResource, res1, true);
87 } catch (LockException le) {
88 assertEquals(le.getCode(), LockException.Code.WOULD_DEADLOCK);
89 deadlockCnt++;
90 } catch (InterruptedException ie) {
91 } finally {
92 manager.endWork();
93 try {
94 synchronized (restart) {
95 restart.meet();
96 restart.reset();
97 }
98 } catch (InterruptedException ie) {
99 }
100 }
101 }
102 }, "Deadlock Thread");
103
104 deadlock.start();
105
106 try {
107 manager.startWork(10, TimeUnit.SECONDS);
108
109 manager.lock(defaultResource, res1, false);
110 synchronized (deadlockBarrier1) {
111 deadlockBarrier1.meet();
112 deadlockBarrier1.reset();
113 }
114
115
116 manager.lock(defaultResource, res2, true);
117 } catch (LockException le) {
118 assertEquals(le.getCode(), LockException.Code.WOULD_DEADLOCK);
119 deadlockCnt++;
120 } finally {
121 manager.endWork();
122 synchronized (restart) {
123 restart.meet();
124 restart.reset();
125 }
126 }
127
128
129
130
131 if (deadlockCnt != 1) {
132 log.warn("More than one thread was deadlock victim!");
133 }
134 assertTrue(deadlockCnt >= 1);
135 deadlockCnt = 0;
136 }
137 }
138
139 @Test
140 public void stress() throws Throwable {
141
142 log.info("\n\nStress checking locks\n\n");
143
144 final String res1 = "res1";
145 final String res2 = "res2";
146 final String res3 = "res3";
147
148 final RWLockManager<Object, Object> manager = new RWLockManager<Object, Object>();
149
150 final RendezvousBarrier restart = new RendezvousBarrier("restart", 5, TIMEOUT);
151 final RendezvousBarrier start = new RendezvousBarrier("start", 5, TIMEOUT);
152
153 for (int i = 0; i < CONCURRENT_TESTS; i++) {
154
155 System.out.print(".");
156
157 Thread t1 = new Thread(new Runnable() {
158 public void run() {
159 try {
160 try {
161 synchronized (start) {
162 start.meet();
163 start.reset();
164 }
165 manager.startWork(10, TimeUnit.SECONDS);
166 manager.lock(defaultResource, res1, false);
167 manager.lock(defaultResource, res2, false);
168 manager.lock(defaultResource, res3, true);
169 } catch (LockException ie) {
170 } finally {
171 manager.endWork();
172 synchronized (restart) {
173 restart.meet();
174 restart.reset();
175 }
176 }
177 } catch (InterruptedException ie) {
178 }
179 }
180 }, "Thread #1");
181 t1.start();
182
183 Thread t2 = new Thread(new Runnable() {
184 public void run() {
185 try {
186 try {
187 synchronized (start) {
188 start.meet();
189 start.reset();
190 }
191 manager.startWork(10, TimeUnit.SECONDS);
192 manager.lock(defaultResource, res1, false);
193 manager.lock(defaultResource, res2, false);
194 manager.lock(defaultResource, res3, true);
195 } catch (LockException ie) {
196 } finally {
197 manager.endWork();
198 synchronized (restart) {
199 restart.meet();
200 restart.reset();
201 }
202 }
203 } catch (InterruptedException ie) {
204 }
205 }
206 }, "Thread #2");
207 t2.start();
208
209 Thread t3 = new Thread(new Runnable() {
210 public void run() {
211 try {
212 try {
213 synchronized (start) {
214 start.meet();
215 start.reset();
216 }
217 manager.startWork(10, TimeUnit.SECONDS);
218 manager.lock(defaultResource, res1, false);
219 manager.lock(defaultResource, res2, false);
220 manager.lock(defaultResource, res3, true);
221 } catch (LockException ie) {
222 } finally {
223 manager.endWork();
224 synchronized (restart) {
225 restart.meet();
226 restart.reset();
227 }
228 }
229 } catch (InterruptedException ie) {
230 }
231 }
232 }, "Thread #3");
233 t3.start();
234
235 Thread t4 = new Thread(new Runnable() {
236 public void run() {
237 try {
238 try {
239 synchronized (start) {
240 start.meet();
241 start.reset();
242 }
243 manager.startWork(10, TimeUnit.SECONDS);
244 manager.lock(defaultResource, res1, false);
245 manager.lock(defaultResource, res2, false);
246 manager.lock(defaultResource, res3, true);
247 } catch (LockException ie) {
248 } finally {
249 manager.endWork();
250 synchronized (restart) {
251 restart.meet();
252 restart.reset();
253 }
254 }
255 } catch (InterruptedException ie) {
256 }
257 }
258 }, "Thread #4");
259 t4.start();
260
261 try {
262 try {
263 synchronized (start) {
264 start.meet();
265 start.reset();
266 }
267 manager.startWork(10, TimeUnit.SECONDS);
268 manager.lock(defaultResource, res1, false);
269 manager.lock(defaultResource, res2, false);
270 manager.lock(defaultResource, res3, false);
271 } catch (LockException ie) {
272 } finally {
273 manager.endWork();
274 try {
275 synchronized (restart) {
276 restart.meet();
277 restart.reset();
278 }
279 } catch (InterruptedException ie) {
280 }
281 }
282 } catch (InterruptedException ie) {
283 }
284 }
285
286 }
287
288 @Test
289 public void choas() throws Throwable {
290
291 log.info("\n\nChaos testing locks for internal deadlocks resp. concurrent mods\n\n");
292
293 final String res1 = "res1";
294 final String res2 = "res2";
295 final String res3 = "res3";
296
297 final RWLockManager<Object, Object> manager = new RWLockManager<Object, Object>();
298
299 int concurrentThreads = 7;
300 int threads = CONCURRENT_TESTS * concurrentThreads;
301
302 final RendezvousBarrier end = new RendezvousBarrier("end", threads + 1, TIMEOUT);
303
304 log.info("\n\nStarting " + threads + " threads\n\n");
305
306 for (int i = 0; i < CONCURRENT_TESTS; i++) {
307
308 final int cnt = i;
309
310 System.out.print(".");
311
312 Thread t1 = new Thread(new Runnable() {
313 public void run() {
314 try {
315 manager.startWork(10, TimeUnit.SECONDS);
316 manager.lock(defaultResource, res1, false);
317 manager.lock(defaultResource, res2, false);
318 manager.lock(defaultResource, res3, true);
319 } catch (LockException ie) {
320 System.out.print("-");
321 } finally {
322 manager.endWork();
323 end.call();
324 }
325 }
326 }, "Thread #1");
327
328 Thread t2 = new Thread(new Runnable() {
329 public void run() {
330 try {
331 manager.startWork(10, TimeUnit.SECONDS);
332 manager.lock(defaultResource, res1, false);
333 manager.lock(defaultResource, res2, false);
334 manager.lock(defaultResource, res3, true);
335 } catch (LockException ie) {
336 System.out.print("-");
337 } finally {
338 manager.endWork();
339 end.call();
340 }
341 }
342 }, "Thread #2");
343
344 Thread t3 = new Thread(new Runnable() {
345 public void run() {
346 try {
347 manager.startWork(10 + cnt, TimeUnit.SECONDS);
348 manager.lock(defaultResource, res1, false);
349 manager.lock(defaultResource, res2, false);
350 manager.lock(defaultResource, res3, true);
351 } catch (LockException le) {
352 if (le.getCode() == LockException.Code.TIMED_OUT) {
353 System.out.print("*");
354 } else {
355 System.out.print("-");
356 }
357 } finally {
358 manager.endWork();
359 end.call();
360 }
361 }
362 }, "Thread #3");
363
364 Thread t4 = new Thread(new Runnable() {
365 public void run() {
366 try {
367 manager.startWork(10, TimeUnit.SECONDS);
368 manager.lock(defaultResource, res1, false);
369 manager.lock(defaultResource, res2, false);
370 manager.lock(defaultResource, res3, true);
371 } catch (LockException le) {
372 System.out.print("-");
373 } finally {
374 manager.endWork();
375 end.call();
376 }
377 }
378 }, "Thread #4");
379
380 Thread deadlock1 = new Thread(new Runnable() {
381 public void run() {
382 try {
383 manager.startWork(10, TimeUnit.SECONDS);
384 manager.lock(defaultResource, res2, true);
385 manager.lock(defaultResource, res1, true);
386 } catch (LockException le) {
387 assertEquals(le.getCode(), LockException.Code.WOULD_DEADLOCK);
388 System.out.print("-");
389 } finally {
390 manager.endWork();
391 end.call();
392 }
393 }
394 }, "Deadlock1 Thread");
395
396 Thread deadlock2 = new Thread(new Runnable() {
397 public void run() {
398 try {
399 manager.startWork(10, TimeUnit.SECONDS);
400 manager.lock(defaultResource, res1, false);
401 manager.lock(defaultResource, res2, false);
402 } catch (LockException le) {
403 assertEquals(le.getCode(), LockException.Code.WOULD_DEADLOCK);
404 System.out.print("-");
405 } finally {
406 manager.endWork();
407 end.call();
408 }
409 }
410 }, "Deadlock1 Thread");
411
412 Thread reader = new Thread(new Runnable() {
413 public void run() {
414 try {
415 manager.startWork(10, TimeUnit.SECONDS);
416 manager.lock(defaultResource, res1, false);
417 manager.lock(defaultResource, res2, false);
418 manager.lock(defaultResource, res3, false);
419 } catch (LockException ie) {
420 System.out.print("-");
421 } finally {
422 manager.endWork();
423 end.call();
424 }
425 }
426 }, "Reader Thread");
427
428 t4.start();
429 t3.start();
430 reader.start();
431 t1.start();
432 deadlock2.start();
433 t2.start();
434 deadlock1.start();
435 }
436
437 end.meet();
438
439 }
440 }