1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.named;
20
21 import java.util.concurrent.CountDownLatch;
22 import java.util.concurrent.TimeUnit;
23
24 import org.junit.Assert;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.junit.rules.TestName;
28
29 import static org.hamcrest.MatcherAssert.assertThat;
30 import static org.hamcrest.Matchers.*;
31
32
33
34
35 public abstract class NamedLockFactoryTestSupport {
36
37 protected static NamedLockFactory namedLockFactory;
38
39 @Rule
40 public TestName testName = new TestName();
41
42 protected String lockName() {
43 return testName.getMethodName();
44 }
45
46 @Test
47 public void refCounting() {
48 final String name = lockName();
49 try (NamedLock one = namedLockFactory.getLock(name);
50 NamedLock two = namedLockFactory.getLock(name)) {
51 assertThat(one, sameInstance(two));
52 one.close();
53 two.close();
54
55 try (NamedLock three = namedLockFactory.getLock(name)) {
56 assertThat(three, not(sameInstance(two)));
57 }
58 }
59 }
60
61 @Test(expected = IllegalStateException.class)
62 public void unlockWoLock() {
63 final String name = lockName();
64 try (NamedLock one = namedLockFactory.getLock(name)) {
65 one.unlock();
66 }
67 }
68
69 @Test
70 public void wwBoxing() throws InterruptedException {
71 final String name = lockName();
72 try (NamedLock one = namedLockFactory.getLock(name)) {
73 assertThat(one.lockExclusively(1L, TimeUnit.MILLISECONDS), is(true));
74 assertThat(one.lockExclusively(1L, TimeUnit.MILLISECONDS), is(true));
75 one.unlock();
76 one.unlock();
77 }
78 }
79
80 @Test
81 public void rrBoxing() throws InterruptedException {
82 final String name = lockName();
83 try (NamedLock one = namedLockFactory.getLock(name)) {
84 assertThat(one.lockShared(1L, TimeUnit.MILLISECONDS), is(true));
85 assertThat(one.lockShared(1L, TimeUnit.MILLISECONDS), is(true));
86 one.unlock();
87 one.unlock();
88 }
89 }
90
91 @Test
92 public void wrBoxing() throws InterruptedException {
93 final String name = lockName();
94 try (NamedLock one = namedLockFactory.getLock(name)) {
95 assertThat(one.lockExclusively(1L, TimeUnit.MILLISECONDS), is(true));
96 assertThat(one.lockShared(1L, TimeUnit.MILLISECONDS), is(true));
97 one.unlock();
98 one.unlock();
99 }
100 }
101
102 @Test
103 public void rwBoxing() throws InterruptedException {
104 final String name = lockName();
105 try (NamedLock one = namedLockFactory.getLock(name)) {
106 assertThat(one.lockShared(1L, TimeUnit.MILLISECONDS), is(true));
107 assertThat(one.lockExclusively(1L, TimeUnit.MILLISECONDS), is(false));
108 one.unlock();
109 }
110 }
111
112 @Test(timeout = 5000)
113 public void sharedAccess() throws InterruptedException {
114 final String name = lockName();
115 CountDownLatch winners = new CountDownLatch(2);
116 CountDownLatch losers = new CountDownLatch(0);
117 Thread t1 = new Thread(new Access(namedLockFactory, name, true, winners, losers));
118 Thread t2 = new Thread(new Access(namedLockFactory, name, true, winners, losers));
119 t1.start();
120 t2.start();
121 t1.join();
122 t2.join();
123 winners.await();
124 losers.await();
125 }
126
127 @Test(timeout = 5000)
128 public void exclusiveAccess() throws InterruptedException {
129 final String name = lockName();
130 CountDownLatch winners = new CountDownLatch(1);
131 CountDownLatch losers = new CountDownLatch(1);
132 Thread t1 = new Thread(new Access(namedLockFactory, name, false, winners, losers));
133 Thread t2 = new Thread(new Access(namedLockFactory, name, false, winners, losers));
134 t1.start();
135 t2.start();
136 t1.join();
137 t2.join();
138 winners.await();
139 losers.await();
140 }
141
142 @Test(timeout = 5000)
143 public void mixedAccess() throws InterruptedException {
144 final String name = lockName();
145 CountDownLatch winners = new CountDownLatch(1);
146 CountDownLatch losers = new CountDownLatch(1);
147 Thread t1 = new Thread(new Access(namedLockFactory, name, true, winners, losers));
148 Thread t2 = new Thread(new Access(namedLockFactory, name, false, winners, losers));
149 t1.start();
150 t2.start();
151 t1.join();
152 t2.join();
153 winners.await();
154 losers.await();
155 }
156
157 @Test(timeout = 5000)
158 public void fullyConsumeLockTime() throws InterruptedException {
159 long start = System.nanoTime();
160 final String name = lockName();
161 CountDownLatch winners = new CountDownLatch(1);
162 CountDownLatch losers = new CountDownLatch(1);
163 Thread t1 = new Thread(new Access(namedLockFactory, name, true, winners, losers));
164 Thread t2 = new Thread(new Access(namedLockFactory, name, false, winners, losers));
165 t1.start();
166 t2.start();
167 t1.join();
168 t2.join();
169 winners.await();
170 losers.await();
171 long end = System.nanoTime();
172 long duration = end - start;
173 long expectedDuration = TimeUnit.MILLISECONDS.toNanos(ACCESS_WAIT_MILLIS);
174 assertThat(duration, greaterThanOrEqualTo(expectedDuration));
175 }
176
177 @Test(timeout = 5000)
178 public void releasedExclusiveAllowAccess() throws InterruptedException {
179 final String name = lockName();
180 CountDownLatch winners = new CountDownLatch(1);
181 CountDownLatch losers = new CountDownLatch(0);
182 Thread t1 = new Thread(new Access(namedLockFactory, name, true, winners, losers));
183 try (NamedLock namedLock = namedLockFactory.getLock(name)) {
184 assertThat(namedLock.lockExclusively(50L, TimeUnit.MILLISECONDS), is(true));
185 try {
186 t1.start();
187 Thread.sleep(50L);
188 } finally {
189 namedLock.unlock();
190 }
191 }
192 t1.join();
193 winners.await();
194 losers.await();
195 }
196
197 private static final long ACCESS_WAIT_MILLIS = 1000L;
198
199 private static class Access implements Runnable {
200 final NamedLockFactory namedLockFactory;
201 final String name;
202 final boolean shared;
203 final CountDownLatch winner;
204 final CountDownLatch loser;
205
206 public Access(
207 NamedLockFactory namedLockFactory,
208 String name,
209 boolean shared,
210 CountDownLatch winner,
211 CountDownLatch loser) {
212 this.namedLockFactory = namedLockFactory;
213 this.name = name;
214 this.shared = shared;
215 this.winner = winner;
216 this.loser = loser;
217 }
218
219 @Override
220 public void run() {
221 try (NamedLock lock = namedLockFactory.getLock(name)) {
222 if (shared
223 ? lock.lockShared(ACCESS_WAIT_MILLIS, TimeUnit.MILLISECONDS)
224 : lock.lockExclusively(ACCESS_WAIT_MILLIS, TimeUnit.MILLISECONDS)) {
225 try {
226 winner.countDown();
227 loser.await();
228 } finally {
229 lock.unlock();
230 }
231 } else {
232 loser.countDown();
233 winner.await();
234 }
235 } catch (InterruptedException e) {
236 Assert.fail(e.getMessage());
237 }
238 }
239 }
240 }