View Javadoc

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