Skip to content

Commit 760e5b6

Browse files
committed
refactor(test): move lock specific tests to it's own file
Signed-off-by: Caleb Hulbert <cmhulbert@gmail.com>
1 parent 164c13b commit 760e5b6

2 files changed

Lines changed: 207 additions & 174 deletions

File tree

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
package org.janelia.saalfeldlab.n5;
2+
3+
import org.junit.Test;
4+
5+
import java.io.File;
6+
import java.io.IOException;
7+
import java.nio.file.Files;
8+
import java.nio.file.Path;
9+
import java.nio.file.Paths;
10+
import java.util.concurrent.*;
11+
import java.util.concurrent.atomic.AtomicBoolean;
12+
13+
import static org.junit.Assert.assertTrue;
14+
import static org.junit.Assert.fail;
15+
16+
public class FsLockTest {
17+
18+
private static final FileKeyLockManager LOCK_MANAGER = FileKeyLockManager.FILE_LOCK_MANAGER;
19+
20+
private static String tempPathName() {
21+
22+
try {
23+
final File tmpFile = Files.createTempDirectory("fs-key-lock-test-").toFile();
24+
tmpFile.delete();
25+
tmpFile.mkdir();
26+
tmpFile.deleteOnExit();
27+
return tmpFile.getCanonicalPath();
28+
} catch (final Exception e) {
29+
throw new RuntimeException(e);
30+
}
31+
}
32+
33+
@Test
34+
public void testReadLock() throws IOException {
35+
36+
final Path path = Paths.get(tempPathName(), "lock");
37+
path.toFile().createNewFile();
38+
assertTrue("File Created", path.toFile().exists());
39+
LockedChannel lock = LOCK_MANAGER.lockForReading(path);
40+
lock.close();
41+
lock = LOCK_MANAGER.lockForReading(path);
42+
43+
final ExecutorService exec = Executors.newSingleThreadExecutor();
44+
final Future<Void> future = exec.submit(() -> {
45+
LOCK_MANAGER.lockForWriting(path).close();
46+
return null;
47+
});
48+
49+
try {
50+
System.out.println("Trying to acquire locked readable channel...");
51+
System.out.println(future.get(3, TimeUnit.SECONDS));
52+
fail("Lock broken!");
53+
} catch (final TimeoutException e) {
54+
System.out.println("Lock held!");
55+
future.cancel(true);
56+
} catch (final InterruptedException | ExecutionException e) {
57+
future.cancel(true);
58+
System.out.println("Test was interrupted!");
59+
} finally {
60+
lock.close();
61+
Files.delete(path);
62+
}
63+
64+
exec.shutdownNow();
65+
}
66+
67+
@Test
68+
public void testWriteLock() throws IOException {
69+
70+
final Path path = Paths.get(tempPathName(), "lock");
71+
final LockedChannel lock = LOCK_MANAGER.lockForWriting(path);
72+
System.out.println("locked");
73+
74+
final ExecutorService exec = Executors.newSingleThreadExecutor();
75+
final Future<Void> future = exec.submit(() -> {
76+
LOCK_MANAGER.lockForReading(path).close();
77+
return null;
78+
});
79+
80+
try {
81+
System.out.println("Trying to acquire locked writable channel...");
82+
System.out.println(future.get(3, TimeUnit.SECONDS));
83+
fail("Lock broken!");
84+
} catch (final TimeoutException e) {
85+
System.out.println("Lock held!");
86+
future.cancel(true);
87+
} catch (final InterruptedException | ExecutionException e) {
88+
future.cancel(true);
89+
System.out.println("Test was interrupted!");
90+
} finally {
91+
lock.close();
92+
Files.delete(path);
93+
}
94+
95+
exec.shutdownNow();
96+
}
97+
98+
@Test
99+
public void testFSLockRelease() throws IOException, ExecutionException, InterruptedException, TimeoutException {
100+
101+
102+
final Path path = Paths.get(tempPathName(), "lock");
103+
final ExecutorService exec = Executors.newFixedThreadPool(2);
104+
105+
// first thread acquires the lock, waits for 200ms then should release it
106+
exec.submit(() -> {
107+
try {
108+
try(final LockedChannel lock = LOCK_MANAGER.lockForWriting(path)) {
109+
lock.newReader();
110+
Thread.sleep(200);
111+
}
112+
} catch (IOException e) {
113+
e.printStackTrace();
114+
} catch (InterruptedException e) {
115+
e.printStackTrace();
116+
}
117+
});
118+
119+
// second thread waits for the lock.
120+
// it should get it within a few seconds.
121+
final Future<Void> future = exec.submit(() -> {
122+
LOCK_MANAGER.lockForWriting(path).close();
123+
return null;
124+
});
125+
126+
future.get(3, TimeUnit.SECONDS);
127+
Files.delete(path);
128+
exec.shutdownNow();
129+
}
130+
131+
@Test
132+
public void testReadLockBehavior() throws IOException, InterruptedException, ExecutionException, TimeoutException {
133+
134+
final Path path = Paths.get(tempPathName(), "read-lock");
135+
path.toFile().createNewFile();
136+
137+
final ExecutorService exec = Executors.newFixedThreadPool(3);
138+
139+
final AtomicBoolean v = new AtomicBoolean(false);
140+
141+
// first thread acquires a read lock, waits for 200ms
142+
Future<?> f = exec.submit(() -> {
143+
try {
144+
try(final LockedChannel lock = LOCK_MANAGER.lockForReading(path)) {
145+
lock.newReader();
146+
Thread.sleep(200);
147+
148+
// ensure that the other thread updated the value
149+
assertTrue(v.get());
150+
151+
}
152+
} catch (IOException e) {
153+
e.printStackTrace();
154+
} catch (InterruptedException e) {
155+
e.printStackTrace();
156+
}
157+
});
158+
159+
// second thread gets a read lock
160+
// and should not be blocked
161+
// this thread updates the boolean
162+
exec.submit(() -> {
163+
try( final LockedChannel lock = LOCK_MANAGER.lockForReading(path)) {
164+
lock.newReader();
165+
v.set(true);
166+
}
167+
return null;
168+
});
169+
170+
f.get(3, TimeUnit.SECONDS);
171+
exec.shutdownNow();
172+
Files.delete(path);
173+
}
174+
175+
@Test
176+
public void testWriteLockBehavior() throws IOException, ExecutionException, InterruptedException, TimeoutException {
177+
178+
179+
final Path path = Paths.get(tempPathName(), "lock");
180+
final ExecutorService exec = Executors.newFixedThreadPool(2);
181+
182+
// first thread acquires the lock, waits for 200ms then should release it
183+
exec.submit(() -> {
184+
try {
185+
try(final LockedChannel lock = LOCK_MANAGER.lockForWriting(path)) {
186+
lock.newReader();
187+
Thread.sleep(200);
188+
}
189+
} catch (IOException e) {
190+
e.printStackTrace();
191+
} catch (InterruptedException e) {
192+
e.printStackTrace();
193+
}
194+
});
195+
196+
// second thread waits for the lock.
197+
// it should get it within a few seconds.
198+
final Future<Void> future = exec.submit(() -> {
199+
LOCK_MANAGER.lockForWriting(path).close();
200+
return null;
201+
});
202+
203+
future.get(3, TimeUnit.SECONDS);
204+
Files.delete(path);
205+
exec.shutdownNow();
206+
}
207+
}

0 commit comments

Comments
 (0)