1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.util.concurrent;
18
19 import com.google.common.testing.NullPointerTester;
20 import com.google.common.testing.TearDownStack;
21
22 import junit.framework.TestCase;
23
24 import java.util.Random;
25 import java.util.concurrent.TimeUnit;
26
27
28
29
30
31
32
33 public abstract class MonitorTestCase extends TestCase {
34
35 public class TestGuard extends Monitor.Guard {
36 private volatile boolean satisfied;
37
38 public TestGuard(boolean satisfied) {
39 super(MonitorTestCase.this.monitor);
40 this.satisfied = satisfied;
41 }
42
43 @Override public boolean isSatisfied() {
44 return this.satisfied;
45 }
46
47 public void setSatisfied(boolean satisfied) {
48 this.satisfied = satisfied;
49 }
50 }
51
52 private final boolean interruptible;
53 private Monitor monitor;
54 private final TearDownStack tearDownStack = new TearDownStack(true);
55 private TestThread<Monitor> thread1;
56 private TestThread<Monitor> thread2;
57
58 protected MonitorTestCase(boolean interruptible) {
59 this.interruptible = interruptible;
60 }
61
62 @Override protected final void setUp() throws Exception {
63 boolean fair = new Random().nextBoolean();
64 monitor = new Monitor(fair);
65 tearDownStack.addTearDown(thread1 = new TestThread<Monitor>(monitor, "TestThread #1"));
66 tearDownStack.addTearDown(thread2 = new TestThread<Monitor>(monitor, "TestThread #2"));
67 }
68
69 @Override protected final void tearDown() {
70 tearDownStack.runTearDown();
71 }
72
73 private String enter() {
74 return interruptible ? "enterInterruptibly" : "enter";
75 }
76
77 private String tryEnter() {
78 return "tryEnter";
79 }
80
81 private String enterIf() {
82 return interruptible ? "enterIfInterruptibly" : "enterIf";
83 }
84
85 private String tryEnterIf() {
86 return "tryEnterIf";
87 }
88
89 private String enterWhen() {
90 return interruptible ? "enterWhen" : "enterWhenUninterruptibly";
91 }
92
93 private String waitFor() {
94 return interruptible ? "waitFor" : "waitForUninterruptibly";
95 }
96
97 private String leave() {
98 return "leave";
99 }
100
101 public final void testMutualExclusion() throws Exception {
102 thread1.callAndAssertReturns(enter());
103 thread2.callAndAssertBlocks(enter());
104 thread1.callAndAssertReturns(leave());
105 thread2.assertPriorCallReturns(enter());
106 }
107
108 public final void testTryEnter() throws Exception {
109 thread1.callAndAssertReturns(true, tryEnter());
110 thread2.callAndAssertReturns(false, tryEnter());
111 thread1.callAndAssertReturns(true, tryEnter());
112 thread2.callAndAssertReturns(false, tryEnter());
113 thread1.callAndAssertReturns(leave());
114 thread2.callAndAssertReturns(false, tryEnter());
115 thread1.callAndAssertReturns(leave());
116 thread2.callAndAssertReturns(true, tryEnter());
117 }
118
119 public final void testSystemStateMethods() throws Exception {
120 checkSystemStateMethods(0);
121 thread1.callAndAssertReturns(enter());
122 checkSystemStateMethods(1);
123 thread1.callAndAssertReturns(enter());
124 checkSystemStateMethods(2);
125 thread1.callAndAssertReturns(leave());
126 checkSystemStateMethods(1);
127 thread1.callAndAssertReturns(leave());
128 checkSystemStateMethods(0);
129 }
130
131 private void checkSystemStateMethods(int enterCount) throws Exception {
132 thread1.callAndAssertReturns(enterCount != 0, "isOccupied");
133 thread1.callAndAssertReturns(enterCount != 0, "isOccupiedByCurrentThread");
134 thread1.callAndAssertReturns(enterCount, "getOccupiedDepth");
135
136 thread2.callAndAssertReturns(enterCount != 0, "isOccupied");
137 thread2.callAndAssertReturns(false, "isOccupiedByCurrentThread");
138 thread2.callAndAssertReturns(0, "getOccupiedDepth");
139 }
140
141 public final void testEnterWhen_initiallyTrue() throws Exception {
142 TestGuard guard = new TestGuard(true);
143 thread1.callAndAssertReturns(enterWhen(), guard);
144 }
145
146 public final void testEnterWhen_initiallyFalse() throws Exception {
147 TestGuard guard = new TestGuard(false);
148 thread1.callAndAssertWaits(enterWhen(), guard);
149 monitor.enter();
150 guard.setSatisfied(true);
151 monitor.leave();
152 thread1.assertPriorCallReturns(enterWhen());
153 }
154
155 public final void testEnterWhen_alreadyOccupied() throws Exception {
156 TestGuard guard = new TestGuard(true);
157 thread2.callAndAssertReturns(enter());
158 thread1.callAndAssertBlocks(enterWhen(), guard);
159 thread2.callAndAssertReturns(leave());
160 thread1.assertPriorCallReturns(enterWhen());
161 }
162
163 public final void testEnterIf_initiallyTrue() throws Exception {
164 TestGuard guard = new TestGuard(true);
165 thread1.callAndAssertReturns(true, enterIf(), guard);
166 thread2.callAndAssertBlocks(enter());
167 }
168
169 public final void testEnterIf_initiallyFalse() throws Exception {
170 TestGuard guard = new TestGuard(false);
171 thread1.callAndAssertReturns(false, enterIf(), guard);
172 thread2.callAndAssertReturns(enter());
173 }
174
175 public final void testEnterIf_alreadyOccupied() throws Exception {
176 TestGuard guard = new TestGuard(true);
177 thread2.callAndAssertReturns(enter());
178 thread1.callAndAssertBlocks(enterIf(), guard);
179 thread2.callAndAssertReturns(leave());
180 thread1.assertPriorCallReturns(true, enterIf());
181 }
182
183 public final void testTryEnterIf_initiallyTrue() throws Exception {
184 TestGuard guard = new TestGuard(true);
185 thread1.callAndAssertReturns(true, tryEnterIf(), guard);
186 thread2.callAndAssertBlocks(enter());
187 }
188
189 public final void testTryEnterIf_initiallyFalse() throws Exception {
190 TestGuard guard = new TestGuard(false);
191 thread1.callAndAssertReturns(false, tryEnterIf(), guard);
192 thread2.callAndAssertReturns(enter());
193 }
194
195 public final void testTryEnterIf_alreadyOccupied() throws Exception {
196 TestGuard guard = new TestGuard(true);
197 thread2.callAndAssertReturns(enter());
198 thread1.callAndAssertReturns(false, tryEnterIf(), guard);
199 }
200
201 public final void testWaitFor_initiallyTrue() throws Exception {
202 TestGuard guard = new TestGuard(true);
203 thread1.callAndAssertReturns(enter());
204 thread1.callAndAssertReturns(waitFor(), guard);
205 }
206
207 public final void testWaitFor_initiallyFalse() throws Exception {
208 TestGuard guard = new TestGuard(false);
209 thread1.callAndAssertReturns(enter());
210 thread1.callAndAssertWaits(waitFor(), guard);
211 monitor.enter();
212 guard.setSatisfied(true);
213 monitor.leave();
214 thread1.assertPriorCallReturns(waitFor());
215 }
216
217 public final void testWaitFor_withoutEnter() throws Exception {
218 TestGuard guard = new TestGuard(true);
219 thread1.callAndAssertThrows(IllegalMonitorStateException.class, waitFor(), guard);
220 }
221
222 public void testNulls() {
223 monitor.enter();
224 new NullPointerTester()
225 .setDefault(TimeUnit.class, TimeUnit.SECONDS)
226 .setDefault(Monitor.Guard.class, new TestGuard(true))
227 .testAllPublicInstanceMethods(monitor);
228 }
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 }