1 package org.apidesign.javamonitorflaws;
3 import java.beans.PropertyChangeEvent;
4 import java.beans.PropertyChangeListener;
5 import org.netbeans.junit.NbTestCase;
7 public class CacheTest extends NbTestCase {
8 private MultiplyCache cache = new MultiplyCache();
10 public CacheTest(String n) {
15 protected int timeOut() {
20 * To simulate deadlock between the cache's setMultiply method and
21 * ToDeadlock's own lock. The root cause is that setMultiply is calling
22 * foreign code while holding the caches's <code>this</code> lock:
24 Thread Test Watch Dog: testDeadlockWithSetter
25 org.apidesign.javamonitorflaws.MultiplyCache.setMultiply:19
26 org.apidesign.javamonitorflaws.CacheTest$1ToDeadlock.assertMultiplyByTen:40
27 org.apidesign.javamonitorflaws.CacheTest.testDeadlockWithSetter:50
28 sun.reflect.NativeMethodAccessorImpl.invoke0:-2
29 sun.reflect.NativeMethodAccessorImpl.invoke:39
30 sun.reflect.DelegatingMethodAccessorImpl.invoke:25
31 java.lang.reflect.Method.invoke:597
32 junit.framework.TestCase.runTest:168
33 org.netbeans.junit.NbTestCase.access$200:84
34 org.netbeans.junit.NbTestCase$2.doSomething:328
35 org.netbeans.junit.NbTestCase$1Guard.run:265
36 java.lang.Thread.run:619
38 org.apidesign.javamonitorflaws.CacheTest$1ToDeadlock.assertMultiplyByTen:40
39 org.apidesign.javamonitorflaws.CacheTest$1ToDeadlock.propertyChange:36
40 java.beans.PropertyChangeSupport.firePropertyChange:339
41 java.beans.PropertyChangeSupport.firePropertyChange:276
42 java.beans.PropertyChangeSupport.firePropertyChange:297
43 org.apidesign.javamonitorflaws.MultiplyCache.setMultiply:21
44 org.apidesign.javamonitorflaws.CacheTest$1ToDeadlock.run:28
45 java.lang.Thread.run:619
48 public void testDeadlockWithSetter() throws Exception {
49 if (Boolean.getBoolean("no.failures")) return;
51 class ToDeadlock implements Runnable, PropertyChangeListener {
55 cache.setMultiply(10);
57 public void propertyChange(PropertyChangeEvent evt) {
60 } catch (InterruptedException ex) {
63 changeMultiplyToSeven();
66 public synchronized void changeMultiplyToSeven() {
70 ToDeadlock toDeadlock = new ToDeadlock();
71 cache.addPropertyChangeListener(toDeadlock);
72 Thread t = new Thread(toDeadlock, "to deadlock");
77 toDeadlock.changeMultiplyToSeven();
80 /** Shows that one can deadlock with the cache's API even the API
81 * is locally correctly synchronized.
82 Thread Test Watch Dog: testDeadlockWithTheAPICacheItself
83 org.apidesign.javamonitorflaws.Cache.get:16
84 org.apidesign.javamonitorflaws.CacheTest$2ToDeadlock.assertMultiplyByTen
85 org.apidesign.javamonitorflaws.CacheTest.testDeadlockViaAPI:112
86 java.lang.reflect.Method.invoke:597
87 org.netbeans.junit.NbTestCase.access$200:84
88 org.netbeans.junit.NbTestCase$2.doSomething:328
89 org.netbeans.junit.NbTestCase$1Guard.run:265
90 java.lang.Thread.run:619
91 Thread Deadlock using API
92 org.apidesign.javamonitorflaws.CacheTest$2ToDeadlock.assertMultiplyByTen
93 org.apidesign.javamonitorflaws.CacheTest$2ToDeadlock.propertyChange:98
94 java.beans.PropertyChangeSupport.firePropertyChange:339
95 java.beans.PropertyChangeSupport.firePropertyChange:276
96 java.beans.PropertyChangeSupport.firePropertyChange:297
97 org.apidesign.javamonitorflaws.MultiplyCache.setMultiply:21
98 org.apidesign.javamonitorflaws.CacheTest$2ToDeadlock.run:90
99 java.lang.Thread.run:619
101 public void testDeadlockViaAPI() throws Exception {
102 if (Boolean.getBoolean("no.failures")) return;
104 class ToDeadlock implements Runnable, PropertyChangeListener {
106 cache.setMultiply(10);
108 public void propertyChange(PropertyChangeEvent evt) {
111 } catch (InterruptedException ex) {
114 assertMultiplyByTen();
117 public synchronized void assertMultiplyByTen() {
118 int value = cache.get("123");
119 assertEquals("3*10=30", 30, value);
122 ToDeadlock toDeadlock = new ToDeadlock();
123 cache.addPropertyChangeListener(toDeadlock);
124 Thread t = new Thread(toDeadlock, "Deadlock using API");
129 toDeadlock.assertMultiplyByTen();