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/licenses/publicdomain
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9package tests.api.java.util.concurrent;
10
11import junit.framework.*;
12import java.util.*;
13import java.util.concurrent.*;
14import java.util.concurrent.locks.*;
15import java.io.*;
16
17public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
18    public static void main(String[] args) {
19        junit.textui.TestRunner.run (suite());
20    }
21    public static Test suite() {
22        return new TestSuite(AbstractQueuedSynchronizerTest.class);
23    }
24
25    /**
26     * A simple mutex class, adapted from the
27     * AbstractQueuedSynchronizer javadoc.  Exclusive acquire tests
28     * exercise this as a sample user extension.  Other
29     * methods/features of AbstractQueuedSynchronizerTest are tested
30     * via other test classes, including those for ReentrantLock,
31     * ReentrantReadWriteLock, and Semaphore
32     */
33    static class Mutex extends AbstractQueuedSynchronizer {
34        public boolean isHeldExclusively() { return getState() == 1; }
35
36        public boolean tryAcquire(int acquires) {
37            assertTrue(acquires == 1);
38            return compareAndSetState(0, 1);
39        }
40
41        public boolean tryRelease(int releases) {
42            if (getState() == 0) throw new IllegalMonitorStateException();
43            setState(0);
44            return true;
45        }
46
47        public AbstractQueuedSynchronizer.ConditionObject newCondition() { return new AbstractQueuedSynchronizer.ConditionObject(); }
48
49    }
50
51
52    /**
53     * A simple latch class, to test shared mode.
54     */
55    static class BooleanLatch extends AbstractQueuedSynchronizer {
56        public boolean isSignalled() { return getState() != 0; }
57
58        public int tryAcquireShared(int ignore) {
59            return isSignalled()? 1 : -1;
60        }
61
62        public boolean tryReleaseShared(int ignore) {
63            setState(1);
64            return true;
65        }
66    }
67
68    /**
69     * A runnable calling acquireInterruptibly
70     */
71    class InterruptibleSyncRunnable implements Runnable {
72        final Mutex sync;
73        InterruptibleSyncRunnable(Mutex l) { sync = l; }
74        public void run() {
75            try {
76                sync.acquireInterruptibly(1);
77            } catch(InterruptedException success){}
78        }
79    }
80
81
82    /**
83     * A runnable calling acquireInterruptibly that expects to be
84     * interrupted
85     */
86    class InterruptedSyncRunnable implements Runnable {
87        final Mutex sync;
88        InterruptedSyncRunnable(Mutex l) { sync = l; }
89        public void run() {
90            try {
91                sync.acquireInterruptibly(1);
92                threadShouldThrow();
93            } catch(InterruptedException success){}
94        }
95    }
96
97    /**
98     * isHeldExclusively is false upon construction
99     */
100    public void testIsHeldExclusively() {
101        Mutex rl = new Mutex();
102        assertFalse(rl.isHeldExclusively());
103    }
104
105    /**
106     * acquiring released sync succeeds
107     */
108    public void testAcquire() {
109        Mutex rl = new Mutex();
110        rl.acquire(1);
111        assertTrue(rl.isHeldExclusively());
112        rl.release(1);
113        assertFalse(rl.isHeldExclusively());
114    }
115
116    /**
117     * tryAcquire on an released sync succeeds
118     */
119    public void testTryAcquire() {
120        Mutex rl = new Mutex();
121        assertTrue(rl.tryAcquire(1));
122        assertTrue(rl.isHeldExclusively());
123        rl.release(1);
124    }
125
126    /**
127     * hasQueuedThreads reports whether there are waiting threads
128     */
129    public void testhasQueuedThreads() {
130        final Mutex sync = new Mutex();
131        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
132        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
133        try {
134            assertFalse(sync.hasQueuedThreads());
135            sync.acquire(1);
136            t1.start();
137            Thread.sleep(SHORT_DELAY_MS);
138            assertTrue(sync.hasQueuedThreads());
139            t2.start();
140            Thread.sleep(SHORT_DELAY_MS);
141            assertTrue(sync.hasQueuedThreads());
142            t1.interrupt();
143            Thread.sleep(SHORT_DELAY_MS);
144            assertTrue(sync.hasQueuedThreads());
145            sync.release(1);
146            Thread.sleep(SHORT_DELAY_MS);
147            assertFalse(sync.hasQueuedThreads());
148            t1.join();
149            t2.join();
150        } catch(Exception e){
151            unexpectedException();
152        }
153    }
154
155    /**
156     * isQueued(null) throws NPE
157     */
158    public void testIsQueuedNPE() {
159        final Mutex sync = new Mutex();
160        try {
161            sync.isQueued(null);
162            shouldThrow();
163        } catch (NullPointerException success) {
164        }
165    }
166
167    /**
168     * isQueued reports whether a thread is queued.
169     */
170    public void testIsQueued() {
171        final Mutex sync = new Mutex();
172        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
173        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
174        try {
175            assertFalse(sync.isQueued(t1));
176            assertFalse(sync.isQueued(t2));
177            sync.acquire(1);
178            t1.start();
179            Thread.sleep(SHORT_DELAY_MS);
180            assertTrue(sync.isQueued(t1));
181            t2.start();
182            Thread.sleep(SHORT_DELAY_MS);
183            assertTrue(sync.isQueued(t1));
184            assertTrue(sync.isQueued(t2));
185            t1.interrupt();
186            Thread.sleep(SHORT_DELAY_MS);
187            assertFalse(sync.isQueued(t1));
188            assertTrue(sync.isQueued(t2));
189            sync.release(1);
190            Thread.sleep(SHORT_DELAY_MS);
191            assertFalse(sync.isQueued(t1));
192            Thread.sleep(SHORT_DELAY_MS);
193            assertFalse(sync.isQueued(t2));
194            t1.join();
195            t2.join();
196        } catch(Exception e){
197            unexpectedException();
198        }
199    }
200
201    /**
202     * getFirstQueuedThread returns first waiting thread or null if none
203     */
204    public void testGetFirstQueuedThread() {
205        final Mutex sync = new Mutex();
206        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
207        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
208        try {
209            assertNull(sync.getFirstQueuedThread());
210            sync.acquire(1);
211            t1.start();
212            Thread.sleep(SHORT_DELAY_MS);
213            assertEquals(t1, sync.getFirstQueuedThread());
214            t2.start();
215            Thread.sleep(SHORT_DELAY_MS);
216            assertEquals(t1, sync.getFirstQueuedThread());
217            t1.interrupt();
218            Thread.sleep(SHORT_DELAY_MS);
219            Thread.sleep(SHORT_DELAY_MS);
220            assertEquals(t2, sync.getFirstQueuedThread());
221            sync.release(1);
222            Thread.sleep(SHORT_DELAY_MS);
223            assertNull(sync.getFirstQueuedThread());
224            t1.join();
225            t2.join();
226        } catch(Exception e){
227            unexpectedException();
228        }
229    }
230
231
232    /**
233     * hasContended reports false if no thread has ever blocked, else true
234     */
235    public void testHasContended() {
236        final Mutex sync = new Mutex();
237        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
238        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
239        try {
240            assertFalse(sync.hasContended());
241            sync.acquire(1);
242            t1.start();
243            Thread.sleep(SHORT_DELAY_MS);
244            assertTrue(sync.hasContended());
245            t2.start();
246            Thread.sleep(SHORT_DELAY_MS);
247            assertTrue(sync.hasContended());
248            t1.interrupt();
249            Thread.sleep(SHORT_DELAY_MS);
250            assertTrue(sync.hasContended());
251            sync.release(1);
252            Thread.sleep(SHORT_DELAY_MS);
253            assertTrue(sync.hasContended());
254            t1.join();
255            t2.join();
256        } catch(Exception e){
257            unexpectedException();
258        }
259    }
260
261    /**
262     * getQueuedThreads includes waiting threads
263     */
264    public void testGetQueuedThreads() {
265        final Mutex sync = new Mutex();
266        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
267        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
268        try {
269            assertTrue(sync.getQueuedThreads().isEmpty());
270            sync.acquire(1);
271            assertTrue(sync.getQueuedThreads().isEmpty());
272            t1.start();
273            Thread.sleep(SHORT_DELAY_MS);
274            assertTrue(sync.getQueuedThreads().contains(t1));
275            t2.start();
276            Thread.sleep(SHORT_DELAY_MS);
277            assertTrue(sync.getQueuedThreads().contains(t1));
278            assertTrue(sync.getQueuedThreads().contains(t2));
279            t1.interrupt();
280            Thread.sleep(SHORT_DELAY_MS);
281            assertFalse(sync.getQueuedThreads().contains(t1));
282            assertTrue(sync.getQueuedThreads().contains(t2));
283            sync.release(1);
284            Thread.sleep(SHORT_DELAY_MS);
285            assertTrue(sync.getQueuedThreads().isEmpty());
286            t1.join();
287            t2.join();
288        } catch(Exception e){
289            unexpectedException();
290        }
291    }
292
293    /**
294     * getExclusiveQueuedThreads includes waiting threads
295     */
296    public void testGetExclusiveQueuedThreads() {
297        final Mutex sync = new Mutex();
298        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
299        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
300        try {
301            assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
302            sync.acquire(1);
303            assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
304            t1.start();
305            Thread.sleep(SHORT_DELAY_MS);
306            assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
307            t2.start();
308            Thread.sleep(SHORT_DELAY_MS);
309            assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
310            assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
311            t1.interrupt();
312            Thread.sleep(SHORT_DELAY_MS);
313            assertFalse(sync.getExclusiveQueuedThreads().contains(t1));
314            assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
315            sync.release(1);
316            Thread.sleep(SHORT_DELAY_MS);
317            assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
318            t1.join();
319            t2.join();
320        } catch(Exception e){
321            unexpectedException();
322        }
323    }
324
325    /**
326     * getSharedQueuedThreads does not include exclusively waiting threads
327     */
328    public void testGetSharedQueuedThreads() {
329        final Mutex sync = new Mutex();
330        Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
331        Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
332        try {
333            assertTrue(sync.getSharedQueuedThreads().isEmpty());
334            sync.acquire(1);
335            assertTrue(sync.getSharedQueuedThreads().isEmpty());
336            t1.start();
337            Thread.sleep(SHORT_DELAY_MS);
338            assertTrue(sync.getSharedQueuedThreads().isEmpty());
339            t2.start();
340            Thread.sleep(SHORT_DELAY_MS);
341            assertTrue(sync.getSharedQueuedThreads().isEmpty());
342            t1.interrupt();
343            Thread.sleep(SHORT_DELAY_MS);
344            assertTrue(sync.getSharedQueuedThreads().isEmpty());
345            sync.release(1);
346            Thread.sleep(SHORT_DELAY_MS);
347            assertTrue(sync.getSharedQueuedThreads().isEmpty());
348            t1.join();
349            t2.join();
350        } catch(Exception e){
351            unexpectedException();
352        }
353    }
354
355    /**
356     * tryAcquireNanos is interruptible.
357     */
358    public void testInterruptedException2() {
359        final Mutex sync = new Mutex();
360        sync.acquire(1);
361        Thread t = new Thread(new Runnable() {
362                public void run() {
363                    try {
364                        sync.tryAcquireNanos(1, MEDIUM_DELAY_MS * 1000 * 1000);
365                        threadShouldThrow();
366                    } catch(InterruptedException success){}
367                }
368            });
369        try {
370            t.start();
371            t.interrupt();
372        } catch(Exception e){
373            unexpectedException();
374        }
375    }
376
377
378    /**
379     * TryAcquire on exclusively held sync fails
380     */
381    public void testTryAcquireWhenSynced() {
382        final Mutex sync = new Mutex();
383        sync.acquire(1);
384        Thread t = new Thread(new Runnable() {
385                public void run() {
386                    threadAssertFalse(sync.tryAcquire(1));
387                }
388            });
389        try {
390            t.start();
391            t.join();
392            sync.release(1);
393        } catch(Exception e){
394            unexpectedException();
395        }
396    }
397
398    /**
399     * tryAcquireNanos on an exclusively held sync times out
400     */
401    public void testAcquireNanos_Timeout() {
402        final Mutex sync = new Mutex();
403        sync.acquire(1);
404        Thread t = new Thread(new Runnable() {
405                public void run() {
406                    try {
407                        threadAssertFalse(sync.tryAcquireNanos(1, 1000 * 1000));
408                    } catch (Exception ex) {
409                        threadUnexpectedException();
410                    }
411                }
412            });
413        try {
414            t.start();
415            t.join();
416            sync.release(1);
417        } catch(Exception e){
418            unexpectedException();
419        }
420    }
421
422
423    /**
424     * getState is true when acquired and false when not
425     */
426    public void testGetState() {
427        final Mutex sync = new Mutex();
428        sync.acquire(1);
429        assertTrue(sync.isHeldExclusively());
430        sync.release(1);
431        assertFalse(sync.isHeldExclusively());
432        Thread t = new Thread(new Runnable() {
433                public void run() {
434                    sync.acquire(1);
435                    try {
436                        Thread.sleep(SMALL_DELAY_MS);
437                    }
438                    catch(Exception e) {
439                        threadUnexpectedException();
440                    }
441                    sync.release(1);
442                }
443            });
444        try {
445            t.start();
446            Thread.sleep(SHORT_DELAY_MS);
447            assertTrue(sync.isHeldExclusively());
448            t.join();
449            assertFalse(sync.isHeldExclusively());
450        } catch(Exception e){
451            unexpectedException();
452        }
453    }
454
455
456    /**
457     * acquireInterruptibly is interruptible.
458     */
459    public void testAcquireInterruptibly1() {
460        final Mutex sync = new Mutex();
461        sync.acquire(1);
462        Thread t = new Thread(new InterruptedSyncRunnable(sync));
463        try {
464            t.start();
465            Thread.sleep(SHORT_DELAY_MS);
466            t.interrupt();
467            Thread.sleep(SHORT_DELAY_MS);
468            sync.release(1);
469            t.join();
470        } catch(Exception e){
471            unexpectedException();
472        }
473    }
474
475    /**
476     * acquireInterruptibly succeeds when released, else is interruptible
477     */
478    public void testAcquireInterruptibly2() {
479        final Mutex sync = new Mutex();
480        try {
481            sync.acquireInterruptibly(1);
482        } catch(Exception e) {
483            unexpectedException();
484        }
485        Thread t = new Thread(new InterruptedSyncRunnable(sync));
486        try {
487            t.start();
488            t.interrupt();
489            assertTrue(sync.isHeldExclusively());
490            t.join();
491        } catch(Exception e){
492            unexpectedException();
493        }
494    }
495
496    /**
497     * owns is true for a condition created by sync else false
498     */
499    public void testOwns() {
500        final Mutex sync = new Mutex();
501        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
502        final Mutex sync2 = new Mutex();
503        assertTrue(sync.owns(c));
504        assertFalse(sync2.owns(c));
505    }
506
507    /**
508     * Calling await without holding sync throws IllegalMonitorStateException
509     */
510    public void testAwait_IllegalMonitor() {
511        final Mutex sync = new Mutex();
512        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
513        try {
514            c.await();
515            shouldThrow();
516        }
517        catch (IllegalMonitorStateException success) {
518        }
519        catch (Exception ex) {
520            unexpectedException();
521        }
522    }
523
524    /**
525     * Calling signal without holding sync throws IllegalMonitorStateException
526     */
527    public void testSignal_IllegalMonitor() {
528        final Mutex sync = new Mutex();
529        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
530        try {
531            c.signal();
532            shouldThrow();
533        }
534        catch (IllegalMonitorStateException success) {
535        }
536        catch (Exception ex) {
537            unexpectedException();
538        }
539    }
540
541    /**
542     * awaitNanos without a signal times out
543     */
544    public void testAwaitNanos_Timeout() {
545        final Mutex sync = new Mutex();
546        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
547        try {
548            sync.acquire(1);
549            long t = c.awaitNanos(100);
550            assertTrue(t <= 0);
551            sync.release(1);
552        }
553        catch (Exception ex) {
554            unexpectedException();
555        }
556    }
557
558    /**
559     *  Timed await without a signal times out
560     */
561    public void testAwait_Timeout() {
562        final Mutex sync = new Mutex();
563        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
564        try {
565            sync.acquire(1);
566            assertFalse(c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
567            sync.release(1);
568        }
569        catch (Exception ex) {
570            unexpectedException();
571        }
572    }
573
574    /**
575     * awaitUntil without a signal times out
576     */
577    public void testAwaitUntil_Timeout() {
578        final Mutex sync = new Mutex();
579        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
580        try {
581            sync.acquire(1);
582            java.util.Date d = new java.util.Date();
583            assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
584            sync.release(1);
585        }
586        catch (Exception ex) {
587            unexpectedException();
588        }
589    }
590
591    /**
592     * await returns when signalled
593     */
594    public void testAwait() {
595        final Mutex sync = new Mutex();
596        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
597        Thread t = new Thread(new Runnable() {
598                public void run() {
599                    try {
600                        sync.acquire(1);
601                        c.await();
602                        sync.release(1);
603                    }
604                    catch(InterruptedException e) {
605                        threadUnexpectedException();
606                    }
607                }
608            });
609
610        try {
611            t.start();
612            Thread.sleep(SHORT_DELAY_MS);
613            sync.acquire(1);
614            c.signal();
615            sync.release(1);
616            t.join(SHORT_DELAY_MS);
617            assertFalse(t.isAlive());
618        }
619        catch (Exception ex) {
620            unexpectedException();
621        }
622    }
623
624
625
626    /**
627     * hasWaiters throws NPE if null
628     */
629    public void testHasWaitersNPE() {
630        final Mutex sync = new Mutex();
631        try {
632            sync.hasWaiters(null);
633            shouldThrow();
634        } catch (NullPointerException success) {
635        } catch (Exception ex) {
636            unexpectedException();
637        }
638    }
639
640    /**
641     * getWaitQueueLength throws NPE if null
642     */
643    public void testGetWaitQueueLengthNPE() {
644        final Mutex sync = new Mutex();
645        try {
646            sync.getWaitQueueLength(null);
647            shouldThrow();
648        } catch (NullPointerException success) {
649        } catch (Exception ex) {
650            unexpectedException();
651        }
652    }
653
654
655    /**
656     * getWaitingThreads throws NPE if null
657     */
658    public void testGetWaitingThreadsNPE() {
659        final Mutex sync = new Mutex();
660        try {
661            sync.getWaitingThreads(null);
662            shouldThrow();
663        } catch (NullPointerException success) {
664        } catch (Exception ex) {
665            unexpectedException();
666        }
667    }
668
669
670    /**
671     * hasWaiters throws IAE if not owned
672     */
673    public void testHasWaitersIAE() {
674        final Mutex sync = new Mutex();
675        final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
676        final Mutex sync2 = new Mutex();
677        try {
678            sync2.hasWaiters(c);
679            shouldThrow();
680        } catch (IllegalArgumentException success) {
681        } catch (Exception ex) {
682            unexpectedException();
683        }
684    }
685
686    /**
687     * hasWaiters throws IMSE if not synced
688     */
689    public void testHasWaitersIMSE() {
690        final Mutex sync = new Mutex();
691        final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
692        try {
693            sync.hasWaiters(c);
694            shouldThrow();
695        } catch (IllegalMonitorStateException success) {
696        } catch (Exception ex) {
697            unexpectedException();
698        }
699    }
700
701
702    /**
703     * getWaitQueueLength throws IAE if not owned
704     */
705    public void testGetWaitQueueLengthIAE() {
706        final Mutex sync = new Mutex();
707        final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
708        final Mutex sync2 = new Mutex();
709        try {
710            sync2.getWaitQueueLength(c);
711            shouldThrow();
712        } catch (IllegalArgumentException success) {
713        } catch (Exception ex) {
714            unexpectedException();
715        }
716    }
717
718    /**
719     * getWaitQueueLength throws IMSE if not synced
720     */
721    public void testGetWaitQueueLengthIMSE() {
722        final Mutex sync = new Mutex();
723        final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
724        try {
725            sync.getWaitQueueLength(c);
726            shouldThrow();
727        } catch (IllegalMonitorStateException success) {
728        } catch (Exception ex) {
729            unexpectedException();
730        }
731    }
732
733
734    /**
735     * getWaitingThreads throws IAE if not owned
736     */
737    public void testGetWaitingThreadsIAE() {
738        final Mutex sync = new Mutex();
739        final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
740        final Mutex sync2 = new Mutex();
741        try {
742            sync2.getWaitingThreads(c);
743            shouldThrow();
744        } catch (IllegalArgumentException success) {
745        } catch (Exception ex) {
746            unexpectedException();
747        }
748    }
749
750    /**
751     * getWaitingThreads throws IMSE if not synced
752     */
753    public void testGetWaitingThreadsIMSE() {
754        final Mutex sync = new Mutex();
755        final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
756        try {
757            sync.getWaitingThreads(c);
758            shouldThrow();
759        } catch (IllegalMonitorStateException success) {
760        } catch (Exception ex) {
761            unexpectedException();
762        }
763    }
764
765
766
767    /**
768     * hasWaiters returns true when a thread is waiting, else false
769     */
770    public void testHasWaiters() {
771        final Mutex sync = new Mutex();
772        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
773        Thread t = new Thread(new Runnable() {
774                public void run() {
775                    try {
776                        sync.acquire(1);
777                        threadAssertFalse(sync.hasWaiters(c));
778                        threadAssertEquals(0, sync.getWaitQueueLength(c));
779                        c.await();
780                        sync.release(1);
781                    }
782                    catch(InterruptedException e) {
783                        threadUnexpectedException();
784                    }
785                }
786            });
787
788        try {
789            t.start();
790            Thread.sleep(SHORT_DELAY_MS);
791            sync.acquire(1);
792            assertTrue(sync.hasWaiters(c));
793            assertEquals(1, sync.getWaitQueueLength(c));
794            c.signal();
795            sync.release(1);
796            Thread.sleep(SHORT_DELAY_MS);
797            sync.acquire(1);
798            assertFalse(sync.hasWaiters(c));
799            assertEquals(0, sync.getWaitQueueLength(c));
800            sync.release(1);
801            t.join(SHORT_DELAY_MS);
802            assertFalse(t.isAlive());
803        }
804        catch (Exception ex) {
805            unexpectedException();
806        }
807    }
808
809    /**
810     * getWaitQueueLength returns number of waiting threads
811     */
812    public void testGetWaitQueueLength() {
813        final Mutex sync = new Mutex();
814        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
815        Thread t1 = new Thread(new Runnable() {
816                public void run() {
817                    try {
818                        sync.acquire(1);
819                        threadAssertFalse(sync.hasWaiters(c));
820                        threadAssertEquals(0, sync.getWaitQueueLength(c));
821                        c.await();
822                        sync.release(1);
823                    }
824                    catch(InterruptedException e) {
825                        threadUnexpectedException();
826                    }
827                }
828            });
829
830        Thread t2 = new Thread(new Runnable() {
831                public void run() {
832                    try {
833                        sync.acquire(1);
834                        threadAssertTrue(sync.hasWaiters(c));
835                        threadAssertEquals(1, sync.getWaitQueueLength(c));
836                        c.await();
837                        sync.release(1);
838                    }
839                    catch(InterruptedException e) {
840                        threadUnexpectedException();
841                    }
842                }
843            });
844
845        try {
846            t1.start();
847            Thread.sleep(SHORT_DELAY_MS);
848            t2.start();
849            Thread.sleep(SHORT_DELAY_MS);
850            sync.acquire(1);
851            assertTrue(sync.hasWaiters(c));
852            assertEquals(2, sync.getWaitQueueLength(c));
853            c.signalAll();
854            sync.release(1);
855            Thread.sleep(SHORT_DELAY_MS);
856            sync.acquire(1);
857            assertFalse(sync.hasWaiters(c));
858            assertEquals(0, sync.getWaitQueueLength(c));
859            sync.release(1);
860            t1.join(SHORT_DELAY_MS);
861            t2.join(SHORT_DELAY_MS);
862            assertFalse(t1.isAlive());
863            assertFalse(t2.isAlive());
864        }
865        catch (Exception ex) {
866            unexpectedException();
867        }
868    }
869
870    /**
871     * getWaitingThreads returns only and all waiting threads
872     */
873    public void testGetWaitingThreads() {
874        final Mutex sync = new Mutex();
875        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
876        Thread t1 = new Thread(new Runnable() {
877                public void run() {
878                    try {
879                        sync.acquire(1);
880                        threadAssertTrue(sync.getWaitingThreads(c).isEmpty());
881                        c.await();
882                        sync.release(1);
883                    }
884                    catch(InterruptedException e) {
885                        threadUnexpectedException();
886                    }
887                }
888            });
889
890        Thread t2 = new Thread(new Runnable() {
891                public void run() {
892                    try {
893                        sync.acquire(1);
894                        threadAssertFalse(sync.getWaitingThreads(c).isEmpty());
895                        c.await();
896                        sync.release(1);
897                    }
898                    catch(InterruptedException e) {
899                        threadUnexpectedException();
900                    }
901                }
902            });
903
904        try {
905            sync.acquire(1);
906            assertTrue(sync.getWaitingThreads(c).isEmpty());
907            sync.release(1);
908            t1.start();
909            Thread.sleep(SHORT_DELAY_MS);
910            t2.start();
911            Thread.sleep(SHORT_DELAY_MS);
912            sync.acquire(1);
913            assertTrue(sync.hasWaiters(c));
914            assertTrue(sync.getWaitingThreads(c).contains(t1));
915            assertTrue(sync.getWaitingThreads(c).contains(t2));
916            c.signalAll();
917            sync.release(1);
918            Thread.sleep(SHORT_DELAY_MS);
919            sync.acquire(1);
920            assertFalse(sync.hasWaiters(c));
921            assertTrue(sync.getWaitingThreads(c).isEmpty());
922            sync.release(1);
923            t1.join(SHORT_DELAY_MS);
924            t2.join(SHORT_DELAY_MS);
925            assertFalse(t1.isAlive());
926            assertFalse(t2.isAlive());
927        }
928        catch (Exception ex) {
929            unexpectedException();
930        }
931    }
932
933
934
935    /**
936     * awaitUninterruptibly doesn't abort on interrupt
937     */
938    public void testAwaitUninterruptibly() {
939        final Mutex sync = new Mutex();
940        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
941        Thread t = new Thread(new Runnable() {
942                public void run() {
943                    sync.acquire(1);
944                    c.awaitUninterruptibly();
945                    sync.release(1);
946                }
947            });
948
949        try {
950            t.start();
951            Thread.sleep(SHORT_DELAY_MS);
952            t.interrupt();
953            sync.acquire(1);
954            c.signal();
955            sync.release(1);
956            t.join(SHORT_DELAY_MS);
957            assertFalse(t.isAlive());
958        }
959        catch (Exception ex) {
960            unexpectedException();
961        }
962    }
963
964    /**
965     * await is interruptible
966     */
967    public void testAwait_Interrupt() {
968        final Mutex sync = new Mutex();
969        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
970        Thread t = new Thread(new Runnable() {
971                public void run() {
972                    try {
973                        sync.acquire(1);
974                        c.await();
975                        sync.release(1);
976                        threadShouldThrow();
977                    }
978                    catch(InterruptedException success) {
979                    }
980                }
981            });
982
983        try {
984            t.start();
985            Thread.sleep(SHORT_DELAY_MS);
986            t.interrupt();
987            t.join(SHORT_DELAY_MS);
988            assertFalse(t.isAlive());
989        }
990        catch (Exception ex) {
991            unexpectedException();
992        }
993    }
994
995    /**
996     * awaitNanos is interruptible
997     */
998    public void testAwaitNanos_Interrupt() {
999        final Mutex sync = new Mutex();
1000        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
1001        Thread t = new Thread(new Runnable() {
1002                public void run() {
1003                    try {
1004                        sync.acquire(1);
1005                        c.awaitNanos(1000 * 1000 * 1000); // 1 sec
1006                        sync.release(1);
1007                        threadShouldThrow();
1008                    }
1009                    catch(InterruptedException success) {
1010                    }
1011                }
1012            });
1013
1014        try {
1015            t.start();
1016            Thread.sleep(SHORT_DELAY_MS);
1017            t.interrupt();
1018            t.join(SHORT_DELAY_MS);
1019            assertFalse(t.isAlive());
1020        }
1021        catch (Exception ex) {
1022            unexpectedException();
1023        }
1024    }
1025
1026    /**
1027     * awaitUntil is interruptible
1028     */
1029    public void testAwaitUntil_Interrupt() {
1030        final Mutex sync = new Mutex();
1031        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
1032        Thread t = new Thread(new Runnable() {
1033                public void run() {
1034                    try {
1035                        sync.acquire(1);
1036                        java.util.Date d = new java.util.Date();
1037                        c.awaitUntil(new java.util.Date(d.getTime() + 10000));
1038                        sync.release(1);
1039                        threadShouldThrow();
1040                    }
1041                    catch(InterruptedException success) {
1042                    }
1043                }
1044            });
1045
1046        try {
1047            t.start();
1048            // BEGIN android-changed
1049            Thread.sleep(SMALL_DELAY_MS); // SHORT_DELAY_MS was flaky on Android
1050            t.interrupt();
1051            t.join(SMALL_DELAY_MS);       // SHORT_DELAY_MS was flaky on Android
1052            // END android-changed
1053            assertFalse(t.isAlive());
1054        }
1055        catch (Exception ex) {
1056            unexpectedException();
1057        }
1058    }
1059
1060    /**
1061     * signalAll wakes up all threads
1062     */
1063    public void testSignalAll() {
1064        final Mutex sync = new Mutex();
1065        final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
1066        Thread t1 = new Thread(new Runnable() {
1067                public void run() {
1068                    try {
1069                        sync.acquire(1);
1070                        c.await();
1071                        sync.release(1);
1072                    }
1073                    catch(InterruptedException e) {
1074                        threadUnexpectedException();
1075                    }
1076                }
1077            });
1078
1079        Thread t2 = new Thread(new Runnable() {
1080                public void run() {
1081                    try {
1082                        sync.acquire(1);
1083                        c.await();
1084                        sync.release(1);
1085                    }
1086                    catch(InterruptedException e) {
1087                        threadUnexpectedException();
1088                    }
1089                }
1090            });
1091
1092        try {
1093            t1.start();
1094            t2.start();
1095            Thread.sleep(SHORT_DELAY_MS);
1096            sync.acquire(1);
1097            c.signalAll();
1098            sync.release(1);
1099            t1.join(SHORT_DELAY_MS);
1100            t2.join(SHORT_DELAY_MS);
1101            assertFalse(t1.isAlive());
1102            assertFalse(t2.isAlive());
1103        }
1104        catch (Exception ex) {
1105            unexpectedException();
1106        }
1107    }
1108
1109
1110    /**
1111     * toString indicates current state
1112     */
1113    public void testToString() {
1114        Mutex sync = new Mutex();
1115        String us = sync.toString();
1116        assertTrue(us.indexOf("State = 0") >= 0);
1117        sync.acquire(1);
1118        String ls = sync.toString();
1119        assertTrue(ls.indexOf("State = 1") >= 0);
1120    }
1121
1122    /**
1123     * A serialized AQS deserializes with current state
1124     */
1125    public void testSerialization() {
1126        Mutex l = new Mutex();
1127        l.acquire(1);
1128        assertTrue(l.isHeldExclusively());
1129
1130        try {
1131            ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
1132            ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
1133            out.writeObject(l);
1134            out.close();
1135
1136            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
1137            ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
1138            Mutex r = (Mutex) in.readObject();
1139            assertTrue(r.isHeldExclusively());
1140        } catch(Exception e){
1141            e.printStackTrace();
1142            unexpectedException();
1143        }
1144    }
1145
1146
1147    /**
1148     * tryReleaseShared setting state changes getState
1149     */
1150    public void testGetStateWithReleaseShared() {
1151        final BooleanLatch l = new BooleanLatch();
1152        assertFalse(l.isSignalled());
1153        l.releaseShared(0);
1154        assertTrue(l.isSignalled());
1155    }
1156
1157    /**
1158     * releaseShared has no effect when already signalled
1159     */
1160    public void testReleaseShared() {
1161        final BooleanLatch l = new BooleanLatch();
1162        assertFalse(l.isSignalled());
1163        l.releaseShared(0);
1164        assertTrue(l.isSignalled());
1165        l.releaseShared(0);
1166        assertTrue(l.isSignalled());
1167    }
1168
1169    /**
1170     * acquireSharedInterruptibly returns after release, but not before
1171     */
1172    public void testAcquireSharedInterruptibly() {
1173        final BooleanLatch l = new BooleanLatch();
1174
1175        Thread t = new Thread(new Runnable() {
1176                public void run() {
1177                    try {
1178                        threadAssertFalse(l.isSignalled());
1179                        l.acquireSharedInterruptibly(0);
1180                        threadAssertTrue(l.isSignalled());
1181                    } catch(InterruptedException e){
1182                        threadUnexpectedException();
1183                    }
1184                }
1185            });
1186        try {
1187            t.start();
1188            assertFalse(l.isSignalled());
1189            Thread.sleep(SHORT_DELAY_MS);
1190            l.releaseShared(0);
1191            assertTrue(l.isSignalled());
1192            t.join();
1193        } catch (InterruptedException e){
1194            unexpectedException();
1195        }
1196    }
1197
1198
1199    /**
1200     * acquireSharedTimed returns after release
1201     */
1202    public void testAsquireSharedTimed() {
1203        final BooleanLatch l = new BooleanLatch();
1204
1205        Thread t = new Thread(new Runnable() {
1206                public void run() {
1207                    try {
1208                        threadAssertFalse(l.isSignalled());
1209                        threadAssertTrue(l.tryAcquireSharedNanos(0, MEDIUM_DELAY_MS* 1000 * 1000));
1210                        threadAssertTrue(l.isSignalled());
1211
1212                    } catch(InterruptedException e){
1213                        threadUnexpectedException();
1214                    }
1215                }
1216            });
1217        try {
1218            t.start();
1219            assertFalse(l.isSignalled());
1220            Thread.sleep(SHORT_DELAY_MS);
1221            l.releaseShared(0);
1222            assertTrue(l.isSignalled());
1223            t.join();
1224        } catch (InterruptedException e){
1225            unexpectedException();
1226        }
1227    }
1228
1229    /**
1230     * acquireSharedInterruptibly throws IE if interrupted before released
1231     */
1232    public void testAcquireSharedInterruptibly_InterruptedException() {
1233        final BooleanLatch l = new BooleanLatch();
1234        Thread t = new Thread(new Runnable() {
1235                public void run() {
1236                    try {
1237                        threadAssertFalse(l.isSignalled());
1238                        l.acquireSharedInterruptibly(0);
1239                        threadShouldThrow();
1240                    } catch(InterruptedException success){}
1241                }
1242            });
1243        t.start();
1244        try {
1245            assertFalse(l.isSignalled());
1246            t.interrupt();
1247            t.join();
1248        } catch (InterruptedException e){
1249            unexpectedException();
1250        }
1251    }
1252
1253    /**
1254     * acquireSharedTimed throws IE if interrupted before released
1255     */
1256    public void testAcquireSharedNanos_InterruptedException() {
1257        final BooleanLatch l = new BooleanLatch();
1258        Thread t = new Thread(new Runnable() {
1259                public void run() {
1260                    try {
1261                        threadAssertFalse(l.isSignalled());
1262                        l.tryAcquireSharedNanos(0, SMALL_DELAY_MS* 1000 * 1000);
1263                        threadShouldThrow();
1264                    } catch(InterruptedException success){}
1265                }
1266            });
1267        t.start();
1268        try {
1269            Thread.sleep(SHORT_DELAY_MS);
1270            assertFalse(l.isSignalled());
1271            t.interrupt();
1272            t.join();
1273        } catch (InterruptedException e){
1274            unexpectedException();
1275        }
1276    }
1277
1278    /**
1279     * acquireSharedTimed times out if not released before timeout
1280     */
1281    public void testAcquireSharedNanos_Timeout() {
1282        final BooleanLatch l = new BooleanLatch();
1283        Thread t = new Thread(new Runnable() {
1284                public void run() {
1285                    try {
1286                        threadAssertFalse(l.isSignalled());
1287                        threadAssertFalse(l.tryAcquireSharedNanos(0, SMALL_DELAY_MS* 1000 * 1000));
1288                    } catch(InterruptedException ie){
1289                        threadUnexpectedException();
1290                    }
1291                }
1292            });
1293        t.start();
1294        try {
1295            Thread.sleep(SHORT_DELAY_MS);
1296            assertFalse(l.isSignalled());
1297            t.join();
1298        } catch (InterruptedException e){
1299            unexpectedException();
1300        }
1301    }
1302
1303
1304}
1305