Skip to content

Commit 091744c

Browse files
committed
Created own await framework to get faster tests and better messages
1 parent 9ecc427 commit 091744c

File tree

3 files changed

+256
-33
lines changed

3 files changed

+256
-33
lines changed

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

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,22 @@
2727
package engineering.swat.watch;
2828

2929
import static engineering.swat.watch.WatchEvent.Kind.CREATED;
30-
import static org.awaitility.Awaitility.await;
30+
import static engineering.swat.watch.util.WaitFor.await;
31+
import static org.junit.jupiter.api.Assertions.assertEquals;
3132

3233
import java.io.IOException;
3334
import java.nio.file.Files;
3435
import java.nio.file.Path;
36+
import java.util.ArrayList;
37+
import java.util.Arrays;
38+
import java.util.Collection;
39+
import java.util.Collections;
40+
import java.util.List;
3541
import java.util.concurrent.ForkJoinPool;
3642
import java.util.concurrent.atomic.AtomicBoolean;
3743
import java.util.concurrent.atomic.AtomicReference;
3844
import java.util.function.Consumer;
45+
import java.util.stream.Collectors;
3946

4047
import org.apache.logging.log4j.LogManager;
4148
import org.apache.logging.log4j.Logger;
@@ -49,6 +56,7 @@
4956

5057
import engineering.swat.watch.WatchEvent.Kind;
5158
import engineering.swat.watch.impl.EventHandlingWatch;
59+
import engineering.swat.watch.util.WaitFor;
5260

5361
class RecursiveWatchTests {
5462
private final Logger logger = LogManager.getLogger();
@@ -69,7 +77,7 @@ void cleanup() {
6977

7078
@BeforeAll
7179
static void setupEverything() {
72-
Awaitility.setDefaultTimeout(TestHelper.NORMAL_WAIT);
80+
WaitFor.setDefaultTimeout(TestHelper.NORMAL_WAIT);
7381
}
7482

7583
@Test
@@ -99,9 +107,9 @@ void newDirectoryWithFilesChangesDetected() throws IOException {
99107
target.set(freshFile);
100108
logger.debug("Interested in: {}", freshFile);
101109
Files.writeString(freshFile, "Hello world");
102-
await("New files should have been seen").untilTrue(created);
110+
await("New files should have been seen").until(created);
103111
Files.writeString(freshFile, "Hello world 2");
104-
await("Fresh file change have been detected").untilTrue(changed);
112+
await("Fresh file change have been detected").until(changed);
105113
}
106114
}
107115

@@ -121,7 +129,7 @@ void correctRelativePathIsReported() throws IOException {
121129
var targetFile = testDir.getTestDirectory().resolve(relative);
122130
Files.createDirectories(targetFile.getParent());
123131
Files.writeString(targetFile, "Hello World");
124-
await("Nested path is seen").untilTrue(seen);
132+
await("Nested path is seen").until(seen);
125133
}
126134

127135
}
@@ -143,19 +151,19 @@ void deleteOfFileInDirectoryShouldBeVisible() throws IOException {
143151
try (var watch = watchConfig.start()) {
144152
Files.delete(target);
145153
await("File deletion should generate delete event")
146-
.untilTrue(seen);
154+
.until(seen);
147155
}
148156
}
149157

150158
@ParameterizedTest
151159
@EnumSource // Repeat test for each `Approximation` value
152160
void overflowsAreRecoveredFrom(Approximation whichFiles) throws IOException, InterruptedException {
153161
var parent = testDir.getTestDirectory();
154-
var descendants = new Path[] {
162+
var descendants = List.of(
155163
Path.of("foo"),
156164
Path.of("bar"),
157165
Path.of("bar", "x", "y", "z")
158-
};
166+
);
159167

160168
// Configure and start watch
161169
var dropEvents = new AtomicBoolean(false); // Toggles overflow simulation
@@ -169,28 +177,38 @@ void overflowsAreRecoveredFrom(Approximation whichFiles) throws IOException, Int
169177
try (var watch = (EventHandlingWatch) watchConfig.start()) {
170178

171179
// Define helper functions to test which events have happened
172-
Consumer<Path> awaitCreation = p ->
173-
await("Creation of `" + p + "` should be observed")
174-
.until(() -> bookkeeper.events().kind(CREATED).rootPath(parent).relativePath(p).any());
175-
176-
Consumer<Path> awaitNotCreation = p ->
177-
await("Creation of `" + p + "` shouldn't be observed: " + bookkeeper)
178-
.pollDelay(TestHelper.TINY_WAIT)
179-
.until(() -> bookkeeper.events().kind(CREATED).rootPath(parent).relativePath(p).none());
180+
Consumer<Collection<Path>> awaitCreation = paths ->
181+
WaitFor.await("Creation should be observed")
182+
.untilContainsAll(() ->
183+
bookkeeper.events()
184+
.kind(CREATED)
185+
.rootPath(parent)
186+
.relativePath(paths)
187+
.events()
188+
.map(WatchEvent::getRelativePath)
189+
, paths);
180190

181191
// Begin overflow simulation
182192
dropEvents.set(true);
183193

184194
// Create descendants and files. They *shouldn't* be observed yet.
195+
var missedCreates = new ArrayList<Path>();
185196
var file1 = Path.of("file1.txt");
186197
for (var descendant : descendants) {
187-
Files.createDirectories(parent.resolve(descendant));
188-
Files.createFile(parent.resolve(descendant).resolve(file1));
189-
}
190-
for (var descendant : descendants) {
191-
awaitNotCreation.accept(descendant);
192-
awaitNotCreation.accept(descendant.resolve(file1));
198+
var d = parent.resolve(descendant);
199+
var f = d.resolve(file1);
200+
Files.createDirectories(d);
201+
Files.createFile(f);
202+
missedCreates.add(descendant);
203+
missedCreates.add(descendant.resolve(file1));
193204
}
205+
WaitFor.await(() -> "We should not have seen any events")
206+
.time(TestHelper.TINY_WAIT)
207+
.holdsEmpty(() -> bookkeeper.events()
208+
.kind(CREATED)
209+
.rootPath(parent)
210+
.relativePath(missedCreates)
211+
.events());
194212

195213
// End overflow simulation, and generate the `OVERFLOW` event. The
196214
// previous creation of descendants and files *should* now be
@@ -201,10 +219,7 @@ void overflowsAreRecoveredFrom(Approximation whichFiles) throws IOException, Int
201219
watch.handleEvent(overflow);
202220

203221
if (whichFiles != Approximation.NONE) { // Auto-handler is configured
204-
for (var descendant : descendants) {
205-
awaitCreation.accept(descendant);
206-
awaitCreation.accept(descendant.resolve(file1));
207-
}
222+
awaitCreation.accept(missedCreates);
208223
} else {
209224
// Give the watch some time to process the `OVERFLOW` event and
210225
// do internal bookkeeping
@@ -213,13 +228,14 @@ void overflowsAreRecoveredFrom(Approximation whichFiles) throws IOException, Int
213228

214229
// Create more files. They *should* be observed (regardless of
215230
// whether an auto-handler for `OVERFLOW` events is configured).
216-
var file2 = Path.of("file2.txt");
217-
for (var descendant : descendants) {
218-
Files.createFile(parent.resolve(descendant).resolve(file2));
219-
}
220-
for (var descendant : descendants) {
221-
awaitCreation.accept(descendant.resolve(file2));
231+
var moreFiles = descendants.stream()
232+
.map(d -> d.resolve(Path.of("file2.txt")))
233+
.collect(Collectors.toList());
234+
235+
for (var f : moreFiles) {
236+
Files.createFile(parent.resolve(f));
222237
}
238+
awaitCreation.accept(moreFiles);
223239
}
224240
}
225241
}

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.nio.file.Path;
3030
import java.time.Duration;
3131
import java.util.Arrays;
32+
import java.util.Collection;
33+
import java.util.Collections;
3234
import java.util.Queue;
3335
import java.util.concurrent.ConcurrentLinkedQueue;
3436
import java.util.function.Consumer;
@@ -113,35 +115,59 @@ public boolean none() {
113115
return !any();
114116
}
115117

118+
public Stream<WatchEvent> events() {
119+
return stream;
120+
}
121+
116122
public boolean none(WatchEvent event) {
117123
return !any(event);
118124
}
119125

120126
public Events kind(WatchEvent.Kind... kinds) {
127+
return kind(Arrays.asList(kinds));
128+
}
129+
public Events kind(Collection<WatchEvent.Kind> kinds) {
121130
return new Events(stream.filter(e -> contains(kinds, e.getKind())));
122131
}
123132

124133
public Events kindNot(WatchEvent.Kind... kinds) {
134+
return kindNot(Arrays.asList(kinds));
135+
}
136+
public Events kindNot(Collection<WatchEvent.Kind> kinds) {
125137
return new Events(stream.filter(e -> !contains(kinds, e.getKind())));
126138
}
127139

128140
public Events rootPath(Path... rootPaths) {
141+
return rootPath(Arrays.asList(rootPaths));
142+
}
143+
public Events rootPath(Collection<Path> rootPaths) {
129144
return new Events(stream.filter(e -> contains(rootPaths, e.getRootPath())));
130145
}
131146

132147
public Events rootPathNot(Path... rootPaths) {
148+
return rootPathNot(Arrays.asList(rootPaths));
149+
}
150+
public Events rootPathNot(Collection<Path> rootPaths) {
133151
return new Events(stream.filter(e -> !contains(rootPaths, e.getRootPath())));
134152
}
135153

136154
public Events relativePath(Path... relativePaths) {
155+
return relativePath(Arrays.asList(relativePaths));
156+
}
157+
158+
public Events relativePath(Collection<Path> relativePaths) {
137159
return new Events(stream.filter(e -> contains(relativePaths, e.getRelativePath())));
138160
}
139161

140162
public Events relativePathNot(Path... relativePaths) {
163+
return relativePathNot(Arrays.asList(relativePaths));
164+
}
165+
166+
public Events relativePathNot(Collection<Path> relativePaths) {
141167
return new Events(stream.filter(e -> !contains(relativePaths, e.getRelativePath())));
142168
}
143169

144-
private boolean contains(Object[] a, Object key) {
170+
private <T> boolean contains(Collection<T> a, T key) {
145171
for (var elem : a) {
146172
if (elem.equals(key)) {
147173
return true;

0 commit comments

Comments
 (0)