1 |
/* |
2 |
* Written by members of JCP JSR-166 Expert Group and released to the |
3 |
* public domain. Use, modify, and redistribute this code in any way |
4 |
* without acknowledgement. Other contributors include Andrew Wright, |
5 |
* Jeffrey Hayes, Pat Fischer, Mike Judd. |
6 |
*/ |
7 |
|
8 |
import junit.framework.*; |
9 |
import java.util.*; |
10 |
import java.util.concurrent.*; |
11 |
import java.io.*; |
12 |
|
13 |
public class FairSemaphoreTest extends JSR166TestCase{ |
14 |
|
15 |
public static void main(String[] args) { |
16 |
junit.textui.TestRunner.run (suite()); |
17 |
} |
18 |
|
19 |
public static Test suite() { |
20 |
return new TestSuite(FairSemaphoreTest.class); |
21 |
} |
22 |
|
23 |
/** |
24 |
* Zero, negative, and positive initial values are allowed in constructor |
25 |
*/ |
26 |
public void testConstructor() { |
27 |
FairSemaphore s0 = new FairSemaphore(0); |
28 |
assertEquals(0, s0.availablePermits()); |
29 |
FairSemaphore s1 = new FairSemaphore(-1); |
30 |
assertEquals(-1, s1.availablePermits()); |
31 |
FairSemaphore s2 = new FairSemaphore(-1); |
32 |
assertEquals(-1, s2.availablePermits()); |
33 |
} |
34 |
|
35 |
/** |
36 |
* tryAcquire succeeds when sufficent permits, else fails |
37 |
*/ |
38 |
public void testTryAcquireInSameThread() { |
39 |
FairSemaphore s = new FairSemaphore(2); |
40 |
assertEquals(2, s.availablePermits()); |
41 |
assertTrue(s.tryAcquire()); |
42 |
assertTrue(s.tryAcquire()); |
43 |
assertEquals(0, s.availablePermits()); |
44 |
assertFalse(s.tryAcquire()); |
45 |
} |
46 |
|
47 |
/** |
48 |
* tryAcquire(n) succeeds when sufficent permits, else fails |
49 |
*/ |
50 |
public void testTryAcquireNInSameThread() { |
51 |
FairSemaphore s = new FairSemaphore(2); |
52 |
assertEquals(2, s.availablePermits()); |
53 |
assertTrue(s.tryAcquire(2)); |
54 |
assertEquals(0, s.availablePermits()); |
55 |
assertFalse(s.tryAcquire()); |
56 |
} |
57 |
|
58 |
/** |
59 |
* Acquire and release of semaphore succeed if initially available |
60 |
*/ |
61 |
public void testAcquireReleaseInSameThread() { |
62 |
FairSemaphore s = new FairSemaphore(1); |
63 |
try { |
64 |
s.acquire(); |
65 |
s.release(); |
66 |
s.acquire(); |
67 |
s.release(); |
68 |
s.acquire(); |
69 |
s.release(); |
70 |
s.acquire(); |
71 |
s.release(); |
72 |
s.acquire(); |
73 |
s.release(); |
74 |
assertEquals(1, s.availablePermits()); |
75 |
} catch( InterruptedException e){ |
76 |
unexpectedException(); |
77 |
} |
78 |
} |
79 |
|
80 |
/** |
81 |
* Acquire(n) and release(n) of semaphore succeed if initially available |
82 |
*/ |
83 |
public void testAcquireReleaseNInSameThread() { |
84 |
FairSemaphore s = new FairSemaphore(1); |
85 |
try { |
86 |
s.release(1); |
87 |
s.acquire(1); |
88 |
s.release(2); |
89 |
s.acquire(2); |
90 |
s.release(3); |
91 |
s.acquire(3); |
92 |
s.release(4); |
93 |
s.acquire(4); |
94 |
s.release(5); |
95 |
s.acquire(5); |
96 |
assertEquals(1, s.availablePermits()); |
97 |
} catch( InterruptedException e){ |
98 |
unexpectedException(); |
99 |
} |
100 |
} |
101 |
|
102 |
/** |
103 |
* Acquire(n) and release(n) of semaphore succeed if initially available |
104 |
*/ |
105 |
public void testAcquireUninterruptiblyReleaseNInSameThread() { |
106 |
FairSemaphore s = new FairSemaphore(1); |
107 |
try { |
108 |
s.release(1); |
109 |
s.acquireUninterruptibly(1); |
110 |
s.release(2); |
111 |
s.acquireUninterruptibly(2); |
112 |
s.release(3); |
113 |
s.acquireUninterruptibly(3); |
114 |
s.release(4); |
115 |
s.acquireUninterruptibly(4); |
116 |
s.release(5); |
117 |
s.acquireUninterruptibly(5); |
118 |
assertEquals(1, s.availablePermits()); |
119 |
} finally { |
120 |
} |
121 |
} |
122 |
|
123 |
/** |
124 |
* release(n) in one thread enables timed acquire(n) in another thread |
125 |
*/ |
126 |
public void testTimedAcquireReleaseNInSameThread() { |
127 |
FairSemaphore s = new FairSemaphore(1); |
128 |
try { |
129 |
s.release(1); |
130 |
assertTrue(s.tryAcquire(1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
131 |
s.release(2); |
132 |
assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
133 |
s.release(3); |
134 |
assertTrue(s.tryAcquire(3, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
135 |
s.release(4); |
136 |
assertTrue(s.tryAcquire(4, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
137 |
s.release(5); |
138 |
assertTrue(s.tryAcquire(5, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
139 |
assertEquals(1, s.availablePermits()); |
140 |
} catch( InterruptedException e){ |
141 |
unexpectedException(); |
142 |
} |
143 |
} |
144 |
|
145 |
/** |
146 |
* release in one thread enables timed acquire in another thread |
147 |
*/ |
148 |
public void testTimedAcquireReleaseInSameThread() { |
149 |
FairSemaphore s = new FairSemaphore(1); |
150 |
try { |
151 |
assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
152 |
s.release(); |
153 |
assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
154 |
s.release(); |
155 |
assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
156 |
s.release(); |
157 |
assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
158 |
s.release(); |
159 |
assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
160 |
s.release(); |
161 |
assertEquals(1, s.availablePermits()); |
162 |
} catch( InterruptedException e){ |
163 |
unexpectedException(); |
164 |
} |
165 |
} |
166 |
|
167 |
/** |
168 |
* A release in one thread enables an acquire in another thread |
169 |
*/ |
170 |
public void testAcquireReleaseInDifferentThreads() { |
171 |
final FairSemaphore s = new FairSemaphore(0); |
172 |
Thread t = new Thread(new Runnable() { |
173 |
public void run() { |
174 |
try { |
175 |
s.acquire(); |
176 |
s.acquire(); |
177 |
s.acquire(); |
178 |
s.acquire(); |
179 |
} catch(InterruptedException ie){ |
180 |
threadUnexpectedException(); |
181 |
} |
182 |
} |
183 |
}); |
184 |
try { |
185 |
t.start(); |
186 |
Thread.sleep(SHORT_DELAY_MS); |
187 |
s.release(); |
188 |
s.release(); |
189 |
s.release(); |
190 |
s.release(); |
191 |
s.release(); |
192 |
s.release(); |
193 |
t.join(); |
194 |
assertEquals(2, s.availablePermits()); |
195 |
} catch( InterruptedException e){ |
196 |
unexpectedException(); |
197 |
} |
198 |
} |
199 |
|
200 |
/** |
201 |
* release(n) in one thread enables acquire(n) in another thread |
202 |
*/ |
203 |
public void testAcquireReleaseNInDifferentThreads() { |
204 |
final FairSemaphore s = new FairSemaphore(0); |
205 |
Thread t = new Thread(new Runnable() { |
206 |
public void run() { |
207 |
try { |
208 |
s.acquire(2); |
209 |
s.acquire(2); |
210 |
s.release(4); |
211 |
} catch(InterruptedException ie){ |
212 |
threadUnexpectedException(); |
213 |
} |
214 |
} |
215 |
}); |
216 |
try { |
217 |
t.start(); |
218 |
Thread.sleep(SHORT_DELAY_MS); |
219 |
s.release(6); |
220 |
s.acquire(2); |
221 |
s.acquire(2); |
222 |
s.release(2); |
223 |
t.join(); |
224 |
} catch( InterruptedException e){ |
225 |
unexpectedException(); |
226 |
} |
227 |
} |
228 |
|
229 |
|
230 |
|
231 |
/** |
232 |
* release in one thread enables timed acquire in another thread |
233 |
*/ |
234 |
public void testTimedAcquireReleaseInDifferentThreads() { |
235 |
final FairSemaphore s = new FairSemaphore(1); |
236 |
Thread t = new Thread(new Runnable() { |
237 |
public void run() { |
238 |
try { |
239 |
threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
240 |
threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
241 |
threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
242 |
threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
243 |
threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
244 |
|
245 |
} catch(InterruptedException ie){ |
246 |
threadUnexpectedException(); |
247 |
} |
248 |
} |
249 |
}); |
250 |
t.start(); |
251 |
try { |
252 |
s.release(); |
253 |
s.release(); |
254 |
s.release(); |
255 |
s.release(); |
256 |
s.release(); |
257 |
t.join(); |
258 |
} catch( InterruptedException e){ |
259 |
unexpectedException(); |
260 |
} |
261 |
} |
262 |
|
263 |
/** |
264 |
* release(n) in one thread enables timed acquire(n) in another thread |
265 |
*/ |
266 |
public void testTimedAcquireReleaseNInDifferentThreads() { |
267 |
final FairSemaphore s = new FairSemaphore(2); |
268 |
Thread t = new Thread(new Runnable() { |
269 |
public void run() { |
270 |
try { |
271 |
threadAssertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
272 |
s.release(2); |
273 |
threadAssertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
274 |
s.release(2); |
275 |
} catch(InterruptedException ie){ |
276 |
threadUnexpectedException(); |
277 |
} |
278 |
} |
279 |
}); |
280 |
t.start(); |
281 |
try { |
282 |
assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
283 |
s.release(2); |
284 |
assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
285 |
s.release(2); |
286 |
t.join(); |
287 |
} catch( InterruptedException e){ |
288 |
unexpectedException(); |
289 |
} |
290 |
} |
291 |
|
292 |
/** |
293 |
* A waiting acquire blocks interruptibly |
294 |
*/ |
295 |
public void testAcquire_InterruptedException() { |
296 |
final FairSemaphore s = new FairSemaphore(0); |
297 |
Thread t = new Thread(new Runnable() { |
298 |
public void run() { |
299 |
try { |
300 |
s.acquire(); |
301 |
threadShouldThrow(); |
302 |
} catch(InterruptedException success){} |
303 |
} |
304 |
}); |
305 |
t.start(); |
306 |
try { |
307 |
Thread.sleep(SHORT_DELAY_MS); |
308 |
t.interrupt(); |
309 |
t.join(); |
310 |
} catch(InterruptedException e){ |
311 |
unexpectedException(); |
312 |
} |
313 |
} |
314 |
|
315 |
/** |
316 |
* A waiting acquire(n) blocks interruptibly |
317 |
*/ |
318 |
public void testAcquireN_InterruptedException() { |
319 |
final FairSemaphore s = new FairSemaphore(2); |
320 |
Thread t = new Thread(new Runnable() { |
321 |
public void run() { |
322 |
try { |
323 |
s.acquire(3); |
324 |
threadShouldThrow(); |
325 |
} catch(InterruptedException success){} |
326 |
} |
327 |
}); |
328 |
t.start(); |
329 |
try { |
330 |
Thread.sleep(SHORT_DELAY_MS); |
331 |
t.interrupt(); |
332 |
t.join(); |
333 |
} catch(InterruptedException e){ |
334 |
unexpectedException(); |
335 |
} |
336 |
} |
337 |
|
338 |
/** |
339 |
* A waiting tryAcquire blocks interruptibly |
340 |
*/ |
341 |
public void testTryAcquire_InterruptedException() { |
342 |
final FairSemaphore s = new FairSemaphore(0); |
343 |
Thread t = new Thread(new Runnable() { |
344 |
public void run() { |
345 |
try { |
346 |
s.tryAcquire(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); |
347 |
threadShouldThrow(); |
348 |
} catch(InterruptedException success){ |
349 |
} |
350 |
} |
351 |
}); |
352 |
t.start(); |
353 |
try { |
354 |
Thread.sleep(SHORT_DELAY_MS); |
355 |
t.interrupt(); |
356 |
t.join(); |
357 |
} catch(InterruptedException e){ |
358 |
unexpectedException(); |
359 |
} |
360 |
} |
361 |
|
362 |
/** |
363 |
* A waiting tryAcquire(n) blocks interruptibly |
364 |
*/ |
365 |
public void testTryAcquireN_InterruptedException() { |
366 |
final FairSemaphore s = new FairSemaphore(1); |
367 |
Thread t = new Thread(new Runnable() { |
368 |
public void run() { |
369 |
try { |
370 |
s.tryAcquire(4, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); |
371 |
threadShouldThrow(); |
372 |
} catch(InterruptedException success){ |
373 |
} |
374 |
} |
375 |
}); |
376 |
t.start(); |
377 |
try { |
378 |
Thread.sleep(SHORT_DELAY_MS); |
379 |
t.interrupt(); |
380 |
t.join(); |
381 |
} catch(InterruptedException e){ |
382 |
unexpectedException(); |
383 |
} |
384 |
} |
385 |
|
386 |
/** |
387 |
* a deserialized serialized semaphore has same number of permits |
388 |
*/ |
389 |
public void testSerialization() { |
390 |
FairSemaphore l = new FairSemaphore(3); |
391 |
|
392 |
try { |
393 |
l.acquire(); |
394 |
l.release(); |
395 |
ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); |
396 |
ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); |
397 |
out.writeObject(l); |
398 |
out.close(); |
399 |
|
400 |
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); |
401 |
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); |
402 |
FairSemaphore r = (FairSemaphore) in.readObject(); |
403 |
assertEquals(3, r.availablePermits()); |
404 |
r.acquire(); |
405 |
r.release(); |
406 |
} catch(Exception e){ |
407 |
unexpectedException(); |
408 |
} |
409 |
} |
410 |
|
411 |
} |