1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/samples/deadlock/test/org/apidesign/javamonitorflaws/CacheTest.java Tue Feb 10 18:36:21 2009 +0100
1.3 @@ -0,0 +1,131 @@
1.4 +package org.apidesign.javamonitorflaws;
1.5 +
1.6 +import java.beans.PropertyChangeEvent;
1.7 +import java.beans.PropertyChangeListener;
1.8 +import org.netbeans.junit.NbTestCase;
1.9 +
1.10 +public class CacheTest extends NbTestCase {
1.11 + private MultiplyCache cache = new MultiplyCache();
1.12 +
1.13 + public CacheTest(String n) {
1.14 + super(n);
1.15 + }
1.16 +
1.17 + @Override
1.18 + protected int timeOut() {
1.19 + return 2000;
1.20 + }
1.21 +
1.22 + /**
1.23 + * To simulate deadlock between the cache's setMultiply method and
1.24 + * ToDeadlock's own lock. The root cause is that setMultiply is calling
1.25 + * foreign code while holding the caches's <code>this</code> lock:
1.26 +
1.27 +Thread Test Watch Dog: testDeadlockWithSetter
1.28 + org.apidesign.javamonitorflaws.MultiplyCache.setMultiply:19
1.29 + org.apidesign.javamonitorflaws.CacheTest$1ToDeadlock.assertMultiplyByTen:40
1.30 + org.apidesign.javamonitorflaws.CacheTest.testDeadlockWithSetter:50
1.31 + sun.reflect.NativeMethodAccessorImpl.invoke0:-2
1.32 + sun.reflect.NativeMethodAccessorImpl.invoke:39
1.33 + sun.reflect.DelegatingMethodAccessorImpl.invoke:25
1.34 + java.lang.reflect.Method.invoke:597
1.35 + junit.framework.TestCase.runTest:168
1.36 + org.netbeans.junit.NbTestCase.access$200:84
1.37 + org.netbeans.junit.NbTestCase$2.doSomething:328
1.38 + org.netbeans.junit.NbTestCase$1Guard.run:265
1.39 + java.lang.Thread.run:619
1.40 +Thread to deadlock
1.41 + org.apidesign.javamonitorflaws.CacheTest$1ToDeadlock.assertMultiplyByTen:40
1.42 + org.apidesign.javamonitorflaws.CacheTest$1ToDeadlock.propertyChange:36
1.43 + java.beans.PropertyChangeSupport.firePropertyChange:339
1.44 + java.beans.PropertyChangeSupport.firePropertyChange:276
1.45 + java.beans.PropertyChangeSupport.firePropertyChange:297
1.46 + org.apidesign.javamonitorflaws.MultiplyCache.setMultiply:21
1.47 + org.apidesign.javamonitorflaws.CacheTest$1ToDeadlock.run:28
1.48 + java.lang.Thread.run:619
1.49 +
1.50 + */
1.51 + public void testDeadlockWithSetter() throws Exception {
1.52 + if (Boolean.getBoolean("no.failures")) return;
1.53 +
1.54 + class ToDeadlock implements Runnable, PropertyChangeListener {
1.55 + int value;
1.56 +
1.57 + public void run() {
1.58 + cache.setMultiply(10);
1.59 + }
1.60 + public void propertyChange(PropertyChangeEvent evt) {
1.61 + try {
1.62 + Thread.sleep(500);
1.63 + } catch (InterruptedException ex) {
1.64 + // ok
1.65 + }
1.66 + changeMultiplyToSeven();
1.67 + }
1.68 +
1.69 + public synchronized void changeMultiplyToSeven() {
1.70 + cache.setMultiply(7);
1.71 + }
1.72 + }
1.73 + ToDeadlock toDeadlock = new ToDeadlock();
1.74 + cache.addPropertyChangeListener(toDeadlock);
1.75 + Thread t = new Thread(toDeadlock, "to deadlock");
1.76 + t.start();
1.77 +
1.78 + Thread.sleep(100);
1.79 +
1.80 + toDeadlock.changeMultiplyToSeven();
1.81 + }
1.82 +
1.83 + /** Shows that one can deadlock with the cache's API even the API
1.84 + * is locally correctly synchronized.
1.85 +Thread Test Watch Dog: testDeadlockWithTheAPICacheItself
1.86 + org.apidesign.javamonitorflaws.Cache.get:16
1.87 + org.apidesign.javamonitorflaws.CacheTest$2ToDeadlock.assertMultiplyByTen
1.88 + org.apidesign.javamonitorflaws.CacheTest.testDeadlockViaAPI:112
1.89 + java.lang.reflect.Method.invoke:597
1.90 + org.netbeans.junit.NbTestCase.access$200:84
1.91 + org.netbeans.junit.NbTestCase$2.doSomething:328
1.92 + org.netbeans.junit.NbTestCase$1Guard.run:265
1.93 + java.lang.Thread.run:619
1.94 +Thread Deadlock using API
1.95 + org.apidesign.javamonitorflaws.CacheTest$2ToDeadlock.assertMultiplyByTen
1.96 + org.apidesign.javamonitorflaws.CacheTest$2ToDeadlock.propertyChange:98
1.97 + java.beans.PropertyChangeSupport.firePropertyChange:339
1.98 + java.beans.PropertyChangeSupport.firePropertyChange:276
1.99 + java.beans.PropertyChangeSupport.firePropertyChange:297
1.100 + org.apidesign.javamonitorflaws.MultiplyCache.setMultiply:21
1.101 + org.apidesign.javamonitorflaws.CacheTest$2ToDeadlock.run:90
1.102 + java.lang.Thread.run:619
1.103 + */
1.104 + public void testDeadlockViaAPI() throws Exception {
1.105 + if (Boolean.getBoolean("no.failures")) return;
1.106 +
1.107 + class ToDeadlock implements Runnable, PropertyChangeListener {
1.108 + public void run() {
1.109 + cache.setMultiply(10);
1.110 + }
1.111 + public void propertyChange(PropertyChangeEvent evt) {
1.112 + try {
1.113 + Thread.sleep(500);
1.114 + } catch (InterruptedException ex) {
1.115 + // ok
1.116 + }
1.117 + assertMultiplyByTen();
1.118 + }
1.119 +
1.120 + public synchronized void assertMultiplyByTen() {
1.121 + int value = cache.get("123");
1.122 + assertEquals("3*10=30", 30, value);
1.123 + }
1.124 + }
1.125 + ToDeadlock toDeadlock = new ToDeadlock();
1.126 + cache.addPropertyChangeListener(toDeadlock);
1.127 + Thread t = new Thread(toDeadlock, "Deadlock using API");
1.128 + t.start();
1.129 +
1.130 + Thread.sleep(100);
1.131 +
1.132 + toDeadlock.assertMultiplyByTen();
1.133 + }
1.134 +}
1.135 \ No newline at end of file