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