1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.internal.impl.synccontext;
20
21 import java.io.IOException;
22 import java.nio.file.Files;
23 import java.nio.file.Paths;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.concurrent.CountDownLatch;
27 import java.util.concurrent.TimeUnit;
28
29 import org.eclipse.aether.RepositorySystemSession;
30 import org.eclipse.aether.SyncContext;
31 import org.eclipse.aether.artifact.DefaultArtifact;
32 import org.eclipse.aether.internal.impl.synccontext.named.*;
33 import org.eclipse.aether.named.NamedLockFactory;
34 import org.eclipse.aether.repository.LocalRepository;
35 import org.eclipse.aether.spi.synccontext.SyncContextFactory;
36 import org.junit.AfterClass;
37 import org.junit.Assert;
38 import org.junit.Before;
39 import org.junit.Test;
40
41 import static java.util.Objects.requireNonNull;
42 import static org.hamcrest.MatcherAssert.assertThat;
43 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
44 import static org.mockito.Mockito.mock;
45 import static org.mockito.Mockito.when;
46
47
48
49
50 public abstract class NamedLockFactoryAdapterTestSupport {
51 private static final long ADAPTER_TIME = 1000L;
52
53 private static final TimeUnit ADAPTER_TIME_UNIT = TimeUnit.MILLISECONDS;
54
55
56
57
58 protected static NameMapper nameMapper = new DiscriminatingNameMapper(GAVNameMapper.gav());
59
60
61
62
63
64 protected static NamedLockFactory namedLockFactory;
65
66 private static NamedLockFactoryAdapter adapter;
67
68 private RepositorySystemSession session;
69
70 public static void createAdapter() {
71 requireNonNull(namedLockFactory, "NamedLockFactory not set");
72 adapter = new NamedLockFactoryAdapter(nameMapper, namedLockFactory);
73 }
74
75 @AfterClass
76 public static void cleanupAdapter() {
77 if (adapter != null) {
78 adapter.getNamedLockFactory().shutdown();
79 }
80 }
81
82 @Before
83 public void before() throws IOException {
84 Files.createDirectories(Paths.get(System.getProperty("java.io.tmpdir")));
85 LocalRepository localRepository =
86 new LocalRepository(Files.createTempDirectory("test").toFile());
87 session = mock(RepositorySystemSession.class);
88 when(session.getLocalRepository()).thenReturn(localRepository);
89 HashMap<String, Object> config = new HashMap<>();
90 config.put(NamedLockFactoryAdapter.TIME_KEY, String.valueOf(ADAPTER_TIME));
91 config.put(NamedLockFactoryAdapter.TIME_UNIT_KEY, ADAPTER_TIME_UNIT.name());
92 when(session.getConfigProperties()).thenReturn(config);
93 }
94
95 @Test
96 public void justCreateAndClose() {
97 adapter.newInstance(session, false).close();
98 }
99
100 @Test
101 public void justAcquire() {
102 try (SyncContext syncContext = adapter.newInstance(session, false)) {
103 syncContext.acquire(
104 Arrays.asList(
105 new DefaultArtifact("groupId:artifactId:1.0"),
106 new DefaultArtifact("groupId:artifactId:1.1")),
107 null);
108 }
109 }
110
111 @Test(timeout = 5000)
112 public void sharedAccess() throws InterruptedException {
113 CountDownLatch winners = new CountDownLatch(2);
114 CountDownLatch losers = new CountDownLatch(0);
115 Thread t1 = new Thread(new Access(true, winners, losers, adapter, session, null));
116 Thread t2 = new Thread(new Access(true, winners, losers, adapter, session, null));
117 t1.start();
118 t2.start();
119 t1.join();
120 t2.join();
121 winners.await();
122 losers.await();
123 }
124
125 @Test(timeout = 5000)
126 public void exclusiveAccess() throws InterruptedException {
127 CountDownLatch winners = new CountDownLatch(1);
128 CountDownLatch losers = new CountDownLatch(1);
129 Thread t1 = new Thread(new Access(false, winners, losers, adapter, session, null));
130 Thread t2 = new Thread(new Access(false, winners, losers, adapter, session, null));
131 t1.start();
132 t2.start();
133 t1.join();
134 t2.join();
135 winners.await();
136 losers.await();
137 }
138
139 @Test(timeout = 5000)
140 public void mixedAccess() throws InterruptedException {
141 CountDownLatch winners = new CountDownLatch(1);
142 CountDownLatch losers = new CountDownLatch(1);
143 Thread t1 = new Thread(new Access(true, winners, losers, adapter, session, null));
144 Thread t2 = new Thread(new Access(false, winners, losers, adapter, session, null));
145 t1.start();
146 t2.start();
147 t1.join();
148 t2.join();
149 winners.await();
150 losers.await();
151 }
152
153 @Test(timeout = 5000)
154 public void nestedSharedShared() throws InterruptedException {
155 CountDownLatch winners = new CountDownLatch(2);
156 CountDownLatch losers = new CountDownLatch(0);
157 Thread t1 = new Thread(new Access(
158 true, winners, losers, adapter, session, new Access(true, winners, losers, adapter, session, null)));
159 t1.start();
160 t1.join();
161 winners.await();
162 losers.await();
163 }
164
165 @Test(timeout = 5000)
166 public void nestedExclusiveShared() throws InterruptedException {
167 CountDownLatch winners = new CountDownLatch(2);
168 CountDownLatch losers = new CountDownLatch(0);
169 Thread t1 = new Thread(new Access(
170 false, winners, losers, adapter, session, new Access(true, winners, losers, adapter, session, null)));
171 t1.start();
172 t1.join();
173 winners.await();
174 losers.await();
175 }
176
177 @Test(timeout = 5000)
178 public void nestedExclusiveExclusive() throws InterruptedException {
179 CountDownLatch winners = new CountDownLatch(2);
180 CountDownLatch losers = new CountDownLatch(0);
181 Thread t1 = new Thread(new Access(
182 false, winners, losers, adapter, session, new Access(false, winners, losers, adapter, session, null)));
183 t1.start();
184 t1.join();
185 winners.await();
186 losers.await();
187 }
188
189 @Test(timeout = 5000)
190 public void nestedSharedExclusive() throws InterruptedException {
191 CountDownLatch winners = new CountDownLatch(1);
192 CountDownLatch losers = new CountDownLatch(1);
193 Thread t1 = new Thread(new Access(
194 true, winners, losers, adapter, session, new Access(false, winners, losers, adapter, session, null)));
195 t1.start();
196 t1.join();
197 winners.await();
198 losers.await();
199 }
200
201 @Test
202 public void fullyConsumeLockTime() throws InterruptedException {
203 long start = System.nanoTime();
204 CountDownLatch winners = new CountDownLatch(1);
205 CountDownLatch losers = new CountDownLatch(1);
206 Thread t1 = new Thread(new Access(false, winners, losers, adapter, session, null));
207 Thread t2 = new Thread(new Access(false, winners, losers, adapter, session, null));
208 t1.start();
209 t2.start();
210 t1.join();
211 t2.join();
212 winners.await();
213 losers.await();
214 long end = System.nanoTime();
215 long duration = end - start;
216 long expectedDuration = ADAPTER_TIME_UNIT.toNanos(ADAPTER_TIME);
217 assertThat(duration, greaterThanOrEqualTo(expectedDuration));
218 }
219
220 @Test
221 public void releasedExclusiveAllowAccess() throws InterruptedException {
222 CountDownLatch winners = new CountDownLatch(2);
223 CountDownLatch losers = new CountDownLatch(0);
224 Thread t1 = new Thread(new Access(false, winners, losers, adapter, session, null));
225 new Access(false, winners, losers, adapter, session, null).run();
226 t1.start();
227 t1.join();
228 winners.await();
229 losers.await();
230 }
231
232 private static class Access implements Runnable {
233 final boolean shared;
234 final CountDownLatch winner;
235 final CountDownLatch loser;
236 final NamedLockFactoryAdapter adapter;
237 final RepositorySystemSession session;
238 final Access chained;
239
240 public Access(
241 boolean shared,
242 CountDownLatch winner,
243 CountDownLatch loser,
244 NamedLockFactoryAdapter adapter,
245 RepositorySystemSession session,
246 Access chained) {
247 this.shared = shared;
248 this.winner = winner;
249 this.loser = loser;
250 this.adapter = adapter;
251 this.session = session;
252 this.chained = chained;
253 }
254
255 @Override
256 public void run() {
257 try {
258 try (SyncContext syncContext = adapter.newInstance(session, shared)) {
259 syncContext.acquire(
260 Arrays.asList(
261 new DefaultArtifact("groupId:artifactId:1.0"),
262 new DefaultArtifact("groupId:artifactId:1.1")),
263 null);
264 winner.countDown();
265 if (chained != null) {
266 chained.run();
267 }
268 loser.await();
269 } catch (IllegalStateException e) {
270 e.printStackTrace();
271 loser.countDown();
272 winner.await();
273 }
274 } catch (InterruptedException e) {
275 Assert.fail("interrupted");
276 }
277 }
278 }
279 }