1 /*
2  * Written by Doug Lea with assistance from members of JCP JSR-166
3  * Expert Group and released to the public domain, as explained at
4  * http://creativecommons.org/publicdomain/zero/1.0/
5  * Other contributors include Andrew Wright, Jeffrey Hayes,
6  * Pat Fisher, Mike Judd.
7  */
8 
9 package jsr166;
10 
11 import static java.util.concurrent.TimeUnit.MILLISECONDS;
12 
13 import java.util.concurrent.CountDownLatch;
14 import java.util.concurrent.Exchanger;
15 import java.util.concurrent.TimeoutException;
16 
17 import junit.framework.Test;
18 import junit.framework.TestSuite;
19 
20 public class ExchangerTest extends JSR166TestCase {
21 
22     // android-note: Removed because the CTS runner does a bad job of
23     // retrying tests that have suite() declarations.
24     //
25     // public static void main(String[] args) {
26     //     main(suite(), args);
27     // }
28     // public static Test suite() {
29     //     return new TestSuite(ExchangerTest.class);
30     // }
31 
32     /**
33      * exchange exchanges objects across two threads
34      */
testExchange()35     public void testExchange() {
36         final Exchanger e = new Exchanger();
37         Thread t1 = newStartedThread(new CheckedRunnable() {
38             public void realRun() throws InterruptedException {
39                 assertSame(one, e.exchange(two));
40                 assertSame(two, e.exchange(one));
41             }});
42         Thread t2 = newStartedThread(new CheckedRunnable() {
43             public void realRun() throws InterruptedException {
44                 assertSame(two, e.exchange(one));
45                 assertSame(one, e.exchange(two));
46             }});
47 
48         awaitTermination(t1);
49         awaitTermination(t2);
50     }
51 
52     /**
53      * timed exchange exchanges objects across two threads
54      */
testTimedExchange()55     public void testTimedExchange() {
56         final Exchanger e = new Exchanger();
57         Thread t1 = newStartedThread(new CheckedRunnable() {
58             public void realRun() throws Exception {
59                 assertSame(one, e.exchange(two, LONG_DELAY_MS, MILLISECONDS));
60                 assertSame(two, e.exchange(one, LONG_DELAY_MS, MILLISECONDS));
61             }});
62         Thread t2 = newStartedThread(new CheckedRunnable() {
63             public void realRun() throws Exception {
64                 assertSame(two, e.exchange(one, LONG_DELAY_MS, MILLISECONDS));
65                 assertSame(one, e.exchange(two, LONG_DELAY_MS, MILLISECONDS));
66             }});
67 
68         awaitTermination(t1);
69         awaitTermination(t2);
70     }
71 
72     /**
73      * interrupt during wait for exchange throws IE
74      */
testExchange_InterruptedException()75     public void testExchange_InterruptedException() {
76         final Exchanger e = new Exchanger();
77         final CountDownLatch threadStarted = new CountDownLatch(1);
78         Thread t = newStartedThread(new CheckedInterruptedRunnable() {
79             public void realRun() throws InterruptedException {
80                 threadStarted.countDown();
81                 e.exchange(one);
82             }});
83 
84         await(threadStarted);
85         t.interrupt();
86         awaitTermination(t);
87     }
88 
89     /**
90      * interrupt during wait for timed exchange throws IE
91      */
testTimedExchange_InterruptedException()92     public void testTimedExchange_InterruptedException() {
93         final Exchanger e = new Exchanger();
94         final CountDownLatch threadStarted = new CountDownLatch(1);
95         Thread t = newStartedThread(new CheckedInterruptedRunnable() {
96             public void realRun() throws Exception {
97                 threadStarted.countDown();
98                 e.exchange(null, LONG_DELAY_MS, MILLISECONDS);
99             }});
100 
101         await(threadStarted);
102         t.interrupt();
103         awaitTermination(t);
104     }
105 
106     /**
107      * timeout during wait for timed exchange throws TimeoutException
108      */
testExchange_TimeoutException()109     public void testExchange_TimeoutException() {
110         final Exchanger e = new Exchanger();
111         Thread t = newStartedThread(new CheckedRunnable() {
112             public void realRun() throws Exception {
113                 long startTime = System.nanoTime();
114                 try {
115                     e.exchange(null, timeoutMillis(), MILLISECONDS);
116                     shouldThrow();
117                 } catch (TimeoutException success) {}
118                 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
119             }});
120 
121         awaitTermination(t);
122     }
123 
124     /**
125      * If one exchanging thread is interrupted, another succeeds.
126      */
testReplacementAfterExchange()127     public void testReplacementAfterExchange() {
128         final Exchanger e = new Exchanger();
129         final CountDownLatch exchanged = new CountDownLatch(2);
130         final CountDownLatch interrupted = new CountDownLatch(1);
131         Thread t1 = newStartedThread(new CheckedInterruptedRunnable() {
132             public void realRun() throws InterruptedException {
133                 assertSame(two, e.exchange(one));
134                 exchanged.countDown();
135                 e.exchange(two);
136             }});
137         Thread t2 = newStartedThread(new CheckedRunnable() {
138             public void realRun() throws InterruptedException {
139                 assertSame(one, e.exchange(two));
140                 exchanged.countDown();
141                 interrupted.await();
142                 assertSame(three, e.exchange(one));
143             }});
144         Thread t3 = newStartedThread(new CheckedRunnable() {
145             public void realRun() throws InterruptedException {
146                 interrupted.await();
147                 assertSame(one, e.exchange(three));
148             }});
149 
150         await(exchanged);
151         t1.interrupt();
152         awaitTermination(t1);
153         interrupted.countDown();
154         awaitTermination(t2);
155         awaitTermination(t3);
156     }
157 
158 }
159