View Javadoc

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   * @since 2.4.5
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                         // expected
130                     }
131                 }
132             });
133         }
134         finally
135         {
136             latch.release();
137         }
138     }
139 }