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
105 }
106 }
107 });
108 } finally {
109 latch.release();
110 }
111 }
112 }