1 package com.atlassian.cache.impl;
2
3 import java.util.concurrent.CountDownLatch;
4 import java.util.concurrent.atomic.AtomicReference;
5
6 import com.atlassian.utt.concurrency.Barrier;
7 import com.atlassian.utt.concurrency.TestThread;
8
9 import org.junit.Test;
10
11 import static com.atlassian.utt.concurrency.TestThread.runTest;
12 import static java.util.concurrent.TimeUnit.MILLISECONDS;
13 import static java.util.concurrent.TimeUnit.NANOSECONDS;
14 import static java.util.concurrent.TimeUnit.SECONDS;
15 import static org.hamcrest.Matchers.is;
16 import static org.hamcrest.Matchers.lessThan;
17 import static org.junit.Assert.assertThat;
18 import static org.junit.Assert.fail;
19
20
21
22
23 public class OneShotLatchTest
24 {
25
26 @Test
27 public void testIsHeldByCurrentThread() throws Exception
28 {
29 final OneShotLatch latch = new OneShotLatch();
30 assertThat("initially held by thread that created it", latch.isHeldByCurrentThread(), is(true));
31
32 runTest(new TestThread("Not the owner")
33 {
34
35 @Override
36 protected void go() throws Exception
37 {
38 assertThat("not held by somebody else", latch.isHeldByCurrentThread(), is(false));
39 }
40 });
41
42 latch.release();
43 assertThat("no longer held once released", latch.isHeldByCurrentThread(), is(false));
44 }
45
46 @Test
47 public void testAwaitAndRelease() throws Exception
48 {
49 final AtomicReference<OneShotLatch> latchRef = new AtomicReference<OneShotLatch>();
50 final Barrier latchCreated = new Barrier();
51 final CountDownLatch releaseReady = new CountDownLatch(2);
52 final Barrier releaseDone = new Barrier();
53
54 final TestThread latchOwner = new TestThread("latchOwner")
55 {
56 @Override
57 protected void go() throws Exception
58 {
59 final OneShotLatch latch = new OneShotLatch();
60 latchRef.set(latch);
61 latchCreated.signal();
62 assertThat(releaseReady.await(1L, SECONDS), is(true));
63 latch.release();
64 releaseDone.signal();
65 }
66 };
67
68 final TestThread latchWait1 = new TestThread("latchWait1")
69 {
70 @Override
71 protected void go() throws Exception
72 {
73 latchCreated.await();
74 final OneShotLatch latch = latchRef.get();
75 releaseReady.countDown();
76 latch.await();
77 }
78 };
79
80 final TestThread latchWait2 = new TestThread("latchWait2")
81 {
82 @Override
83 protected void go() throws Exception
84 {
85 latchCreated.await();
86 final OneShotLatch latch = latchRef.get();
87 assertThat("Should not release early", latch.await(100L, MILLISECONDS), is(false));
88 releaseReady.countDown();
89 assertThat("Release should unblock us", latch.await(1L, SECONDS), is(true));
90 }
91 };
92
93 final TestThread latchWait3 = new TestThread("latchWait3")
94 {
95 @Override
96 protected void go() throws Exception
97 {
98 releaseDone.await();
99 final OneShotLatch latch = latchRef.get();
100 final long startNanos = System.nanoTime();
101 assertThat("await after released", latch.await(100L, MILLISECONDS), is(true));
102 latch.await();
103 final long durationMillis = NANOSECONDS.toMillis(System.nanoTime() - startNanos);
104 assertThat("took way too long?!", durationMillis, lessThan(500L));
105 }
106 };
107
108 runTest(latchOwner, latchWait1, latchWait2, latchWait3);
109 }
110
111 @Test
112 public void testReleaseWhenNotOwner() throws Exception
113 {
114 final OneShotLatch latch = new OneShotLatch();
115 try
116 {
117 runTest(new TestThread("Not the owner")
118 {
119 @Override
120 protected void go() throws Exception
121 {
122 try
123 {
124 latch.release();
125 fail("Did not get expected IllegalMonitorStateException");
126 }
127 catch (IllegalMonitorStateException imse)
128 {
129
130 }
131 }
132 });
133 }
134 finally
135 {
136 latch.release();
137 }
138 }
139 }