1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.named.hazelcast;
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.DiscriminatingNameMapper;
33 import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
34 import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapter;
35 import org.eclipse.aether.named.NamedLockFactory;
36 import org.eclipse.aether.named.support.LockUpgradeNotSupportedException;
37 import org.eclipse.aether.repository.LocalRepository;
38 import org.eclipse.aether.spi.synccontext.SyncContextFactory;
39 import org.junit.jupiter.api.AfterAll;
40 import org.junit.jupiter.api.BeforeEach;
41 import org.junit.jupiter.api.Test;
42 import org.junit.jupiter.api.Timeout;
43
44 import static org.junit.jupiter.api.Assertions.*;
45 import static org.mockito.Mockito.mock;
46 import static org.mockito.Mockito.when;
47
48
49
50
51 public abstract class NamedLockFactoryAdapterTestSupport {
52 protected static final HazelcastClientUtils utils = new HazelcastClientUtils();
53
54 private static final long ADAPTER_TIME = 100L;
55
56 private static final TimeUnit ADAPTER_TIME_UNIT = TimeUnit.MILLISECONDS;
57
58
59
60
61
62 private static NamedLockFactoryAdapter adapter;
63
64 private RepositorySystemSession session;
65
66 protected static void setNamedLockFactory(final NamedLockFactory namedLockFactory) {
67 adapter = new NamedLockFactoryAdapter(new DiscriminatingNameMapper(GAVNameMapper.gav()), namedLockFactory);
68 }
69
70 @AfterAll
71 static void cleanup() {
72 if (adapter != null) {
73 adapter.getNamedLockFactory().shutdown();
74 }
75
76 utils.cleanup();
77 }
78
79 @BeforeEach
80 void before() throws IOException {
81 Files.createDirectories(Paths.get(System.getProperty("java.io.tmpdir")));
82 LocalRepository localRepository =
83 new LocalRepository(Files.createTempDirectory("test").toFile());
84 session = mock(RepositorySystemSession.class);
85 when(session.getLocalRepository()).thenReturn(localRepository);
86 HashMap<String, Object> config = new HashMap<>();
87 config.put(NamedLockFactoryAdapter.TIME_KEY, String.valueOf(ADAPTER_TIME));
88 config.put(NamedLockFactoryAdapter.TIME_UNIT_KEY, ADAPTER_TIME_UNIT.name());
89 when(session.getConfigProperties()).thenReturn(config);
90 }
91
92 @Test
93 void justCreateAndClose() {
94 adapter.newInstance(session, false).close();
95 }
96
97 @Test
98 void justAcquire() {
99 try (SyncContext syncContext = adapter.newInstance(session, false)) {
100 syncContext.acquire(
101 Arrays.asList(
102 new DefaultArtifact("groupId:artifactId:1.0"),
103 new DefaultArtifact("groupId:artifactId:1.1")),
104 null);
105 }
106 }
107
108 @Test
109 @Timeout(5)
110 public void sharedAccess() throws InterruptedException {
111 CountDownLatch winners = new CountDownLatch(2);
112 CountDownLatch losers = new CountDownLatch(0);
113 Thread t1 = new Thread(new Access(true, winners, losers, adapter, session, null));
114 Thread t2 = new Thread(new Access(true, winners, losers, adapter, session, null));
115 t1.start();
116 t2.start();
117 t1.join();
118 t2.join();
119 winners.await();
120 losers.await();
121 }
122
123 @Test
124 @Timeout(5)
125 public void exclusiveAccess() throws InterruptedException {
126 CountDownLatch winners = new CountDownLatch(1);
127 CountDownLatch losers = new CountDownLatch(1);
128 Thread t1 = new Thread(new Access(false, winners, losers, adapter, session, null));
129 Thread t2 = new Thread(new Access(false, winners, losers, adapter, session, null));
130 t1.start();
131 t2.start();
132 t1.join();
133 t2.join();
134 winners.await();
135 losers.await();
136 }
137
138 @Test
139 @Timeout(5)
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
154 @Timeout(5)
155 public void nestedSharedShared() throws InterruptedException {
156 CountDownLatch winners = new CountDownLatch(2);
157 CountDownLatch losers = new CountDownLatch(0);
158 Thread t1 = new Thread(new Access(
159 true, winners, losers, adapter, session, new Access(true, winners, losers, adapter, session, null)));
160 t1.start();
161 t1.join();
162 winners.await();
163 losers.await();
164 }
165
166 @Test
167 @Timeout(5)
168 public void nestedExclusiveShared() throws InterruptedException {
169 CountDownLatch winners = new CountDownLatch(2);
170 CountDownLatch losers = new CountDownLatch(0);
171 Thread t1 = new Thread(new Access(
172 false, winners, losers, adapter, session, new Access(true, winners, losers, adapter, session, null)));
173 t1.start();
174 t1.join();
175 winners.await();
176 losers.await();
177 }
178
179 @Test
180 @Timeout(5)
181 public void nestedExclusiveExclusive() throws InterruptedException {
182 CountDownLatch winners = new CountDownLatch(2);
183 CountDownLatch losers = new CountDownLatch(0);
184 Thread t1 = new Thread(new Access(
185 false, winners, losers, adapter, session, new Access(false, winners, losers, adapter, session, null)));
186 t1.start();
187 t1.join();
188 winners.await();
189 losers.await();
190 }
191
192 @Test
193 @Timeout(5)
194 public void nestedSharedExclusive() throws InterruptedException {
195 CountDownLatch winners = new CountDownLatch(1);
196 CountDownLatch losers = new CountDownLatch(1);
197 Thread t1 = new Thread(new Access(
198 true, winners, losers, adapter, session, new Access(false, winners, losers, adapter, session, null)));
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(
214 boolean shared,
215 CountDownLatch winner,
216 CountDownLatch loser,
217 NamedLockFactoryAdapter adapter,
218 RepositorySystemSession session,
219 Access chained) {
220 this.shared = shared;
221 this.winner = winner;
222 this.loser = loser;
223 this.adapter = adapter;
224 this.session = session;
225 this.chained = chained;
226 }
227
228 @Override
229 public void run() {
230 try {
231 try (SyncContext syncContext = adapter.newInstance(session, shared)) {
232 syncContext.acquire(
233 Arrays.asList(
234 new DefaultArtifact("groupId:artifactId:1.0"),
235 new DefaultArtifact("groupId:artifactId:1.1")),
236 null);
237 winner.countDown();
238 if (chained != null) {
239 chained.run();
240 }
241 loser.await();
242 } catch (IllegalStateException | LockUpgradeNotSupportedException e) {
243 loser.countDown();
244 winner.await();
245 }
246 } catch (InterruptedException e) {
247 fail("interrupted");
248 }
249 }
250 }
251 }