Skip to content

Commit f81df21

Browse files
committed
Add test to expose bug that IndexingRescanner generates events outside the watch scope
1 parent d569c50 commit f81df21

File tree

2 files changed

+79
-3
lines changed

2 files changed

+79
-3
lines changed

src/test/java/engineering/swat/watch/TestDirectory.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,11 @@
3737
import java.util.Comparator;
3838
import java.util.List;
3939

40-
class TestDirectory implements Closeable {
40+
public class TestDirectory implements Closeable {
4141
private final Path testDirectory;
4242
private final List<Path> testFiles;
4343

44-
45-
TestDirectory() throws IOException {
44+
public TestDirectory() throws IOException {
4645
testDirectory = Files.createTempDirectory("java-watch-test");
4746
List<Path> testFiles = new ArrayList<>();
4847
add3Files(testFiles, testDirectory);
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package engineering.swat.watch.impl.overflows;
2+
3+
import static org.awaitility.Awaitility.await;
4+
5+
import java.io.IOException;
6+
import java.util.concurrent.ForkJoinPool;
7+
import java.util.concurrent.atomic.AtomicBoolean;
8+
9+
import org.awaitility.Awaitility;
10+
import org.junit.jupiter.api.AfterEach;
11+
import org.junit.jupiter.api.BeforeAll;
12+
import org.junit.jupiter.api.BeforeEach;
13+
import org.junit.jupiter.api.Test;
14+
15+
import engineering.swat.watch.OnOverflow;
16+
import engineering.swat.watch.TestDirectory;
17+
import engineering.swat.watch.TestHelper;
18+
import engineering.swat.watch.WatchEvent;
19+
import engineering.swat.watch.WatchScope;
20+
import engineering.swat.watch.Watcher;
21+
import engineering.swat.watch.impl.EventHandlingWatch;
22+
23+
class IndexingRescannerTests {
24+
25+
private TestDirectory testDir;
26+
27+
@BeforeEach
28+
void setup() throws IOException {
29+
testDir = new TestDirectory();
30+
}
31+
32+
@AfterEach
33+
void cleanup() {
34+
if (testDir != null) {
35+
testDir.close();
36+
}
37+
}
38+
39+
@BeforeAll
40+
static void setupEverything() {
41+
Awaitility.setDefaultTimeout(TestHelper.NORMAL_WAIT);
42+
}
43+
44+
@Test
45+
void onlyEventsForFilesInScopeAreIssued() throws IOException, InterruptedException {
46+
var path = testDir.getTestDirectory();
47+
48+
// Prepare a watch that monitors only the children (not all descendants)
49+
// of `path`
50+
var eventsOnlyForChildren = new AtomicBoolean(true);
51+
var watchConfig = Watcher.watch(path, WatchScope.PATH_AND_CHILDREN)
52+
.approximate(OnOverflow.NONE) // Disable the auto-handler here; we'll have an explicit one below
53+
.on(e -> {
54+
if (e.getRelativePath().getNameCount() > 1) {
55+
eventsOnlyForChildren.set(false);
56+
}
57+
});
58+
59+
try (var watch = (EventHandlingWatch) watchConfig.start()) {
60+
// Create a rescanner that initially indexes all descendants (not
61+
// only the children) of `path`
62+
var rescanner = new IndexingRescanner(
63+
ForkJoinPool.commonPool(), path,
64+
WatchScope.PATH_AND_ALL_DESCENDANTS);
65+
66+
// Trigger a rescan. As only the children (not all descendants) of
67+
// `path` are watched, the rescan should issue events only for those
68+
// children.
69+
var overflow = new WatchEvent(WatchEvent.Kind.OVERFLOW, path);
70+
rescanner.accept(watch, overflow);
71+
Thread.sleep(TestHelper.SHORT_WAIT.toMillis());
72+
73+
await("No events for non-children descendants should have been issued")
74+
.until(eventsOnlyForChildren::get);
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)