Skip to content

Commit 02e6b7c

Browse files
committed
Make FileSystemWatcherTests more robust
Previously, several tests in FileSystemWatcherTests assumed that all of the changes detected by the watcher would be grouped into a single change set. This assumption breaks down when a test runs slowly (due to CPU or IO contention, for example), and making changes to the file system takes long then the watcher's polling interval. When this happens, the changes will be split across two (or more). This commit attempts to make the tests more robust. The tests now tolerate multiple changes sets by combining them and asserting that across the n change sets, only the expected changes were detected. Closes gh-25901
1 parent c5c0718 commit 02e6b7c

File tree

1 file changed

+21
-29
lines changed

1 file changed

+21
-29
lines changed

spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/filewatch/FileSystemWatcherTests.java

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,10 +23,10 @@
2323
import java.util.ArrayList;
2424
import java.util.Collections;
2525
import java.util.HashSet;
26-
import java.util.LinkedHashSet;
2726
import java.util.List;
2827
import java.util.Set;
2928
import java.util.UUID;
29+
import java.util.stream.Collectors;
3030

3131
import org.junit.jupiter.api.BeforeEach;
3232
import org.junit.jupiter.api.Test;
@@ -44,6 +44,7 @@
4444
* Tests for {@link FileSystemWatcher}.
4545
*
4646
* @author Phillip Webb
47+
* @author Andy Wilkinson
4748
*/
4849
class FileSystemWatcherTests {
4950

@@ -120,19 +121,17 @@ void addFile() throws Exception {
120121
File directory = startWithNewDirectory();
121122
File file = touch(new File(directory, "test.txt"));
122123
this.watcher.stopAfter(1);
123-
ChangedFiles changedFiles = getSingleChangedFiles();
124124
ChangedFile expected = new ChangedFile(directory, file, Type.ADD);
125-
assertThat(changedFiles.getFiles()).contains(expected);
125+
assertThat(getAllFileChanges()).containsExactly(expected);
126126
}
127127

128128
@Test
129129
void addNestedFile() throws Exception {
130130
File directory = startWithNewDirectory();
131131
File file = touch(new File(new File(directory, "sub"), "text.txt"));
132132
this.watcher.stopAfter(1);
133-
ChangedFiles changedFiles = getSingleChangedFiles();
134133
ChangedFile expected = new ChangedFile(directory, file, Type.ADD);
135-
assertThat(changedFiles.getFiles()).contains(expected);
134+
assertThat(getAllFileChanges()).containsExactly(expected);
136135
}
137136

138137
@Test
@@ -144,9 +143,8 @@ void createSourceDirectoryAndAddFile() throws IOException {
144143
directory.mkdirs();
145144
File file = touch(new File(directory, "text.txt"));
146145
this.watcher.stopAfter(1);
147-
ChangedFiles changedFiles = getSingleChangedFiles();
148146
ChangedFile expected = new ChangedFile(directory, file, Type.ADD);
149-
assertThat(changedFiles.getFiles()).contains(expected);
147+
assertThat(getAllFileChanges()).containsExactly(expected);
150148
}
151149

152150
@Test
@@ -171,8 +169,7 @@ void waitsForQuietPeriod() throws Exception {
171169
Thread.sleep(10);
172170
}
173171
this.watcher.stopAfter(1);
174-
ChangedFiles changedFiles = getSingleChangedFiles();
175-
assertThat(changedFiles.getFiles()).hasSize(100);
172+
assertThat(getAllFileChanges()).hasSize(100);
176173
}
177174

178175
@Test
@@ -184,9 +181,8 @@ void withExistingFiles() throws Exception {
184181
this.watcher.start();
185182
File file = touch(new File(directory, "test2.txt"));
186183
this.watcher.stopAfter(1);
187-
ChangedFiles changedFiles = getSingleChangedFiles();
188184
ChangedFile expected = new ChangedFile(directory, file, Type.ADD);
189-
assertThat(changedFiles.getFiles()).contains(expected);
185+
assertThat(getAllFileChanges()).contains(expected);
190186
}
191187

192188
@Test
@@ -201,7 +197,7 @@ void multipleSources() throws Exception {
201197
File file1 = touch(new File(directory1, "test.txt"));
202198
File file2 = touch(new File(directory2, "test.txt"));
203199
this.watcher.stopAfter(1);
204-
Set<ChangedFiles> change = getSingleOnChange();
200+
Set<ChangedFiles> change = this.changes.stream().flatMap(Set<ChangedFiles>::stream).collect(Collectors.toSet());
205201
assertThat(change.size()).isEqualTo(2);
206202
for (ChangedFiles changedFiles : change) {
207203
if (changedFiles.getSourceDirectory().equals(directory1)) {
@@ -219,16 +215,16 @@ void multipleSources() throws Exception {
219215
void multipleListeners() throws Exception {
220216
File directory = new File(this.tempDir, UUID.randomUUID().toString());
221217
directory.mkdir();
222-
final Set<ChangedFiles> listener2Changes = new LinkedHashSet<>();
218+
final List<Set<ChangedFiles>> listener2Changes = new ArrayList<>();
223219
this.watcher.addSourceDirectory(directory);
224-
this.watcher.addListener(listener2Changes::addAll);
220+
this.watcher.addListener(listener2Changes::add);
225221
this.watcher.start();
226222
File file = touch(new File(directory, "test.txt"));
227223
this.watcher.stopAfter(1);
228-
ChangedFiles changedFiles = getSingleChangedFiles();
229224
ChangedFile expected = new ChangedFile(directory, file, Type.ADD);
230-
assertThat(changedFiles.getFiles()).contains(expected);
231-
assertThat(listener2Changes).isEqualTo(this.changes.get(0));
225+
Set<ChangedFile> changeSet = getAllFileChanges();
226+
assertThat(changeSet).contains(expected);
227+
assertThat(getAllFileChanges(listener2Changes)).isEqualTo(changeSet);
232228
}
233229

234230
@Test
@@ -243,8 +239,7 @@ void modifyDeleteAndAdd() throws Exception {
243239
delete.delete();
244240
File add = touch(new File(directory, "add.txt"));
245241
this.watcher.stopAfter(1);
246-
ChangedFiles changedFiles = getSingleChangedFiles();
247-
Set<ChangedFile> actual = changedFiles.getFiles();
242+
Set<ChangedFile> actual = getAllFileChanges();
248243
Set<ChangedFile> expected = new HashSet<>();
249244
expected.add(new ChangedFile(directory, modify, Type.MODIFY));
250245
expected.add(new ChangedFile(directory, delete, Type.DELETE));
@@ -266,8 +261,7 @@ void withTriggerFilter() throws Exception {
266261
assertThat(this.changes).isEmpty();
267262
FileCopyUtils.copy("abc".getBytes(), trigger);
268263
this.watcher.stopAfter(1);
269-
ChangedFiles changedFiles = getSingleChangedFiles();
270-
Set<ChangedFile> actual = changedFiles.getFiles();
264+
Set<ChangedFile> actual = getAllFileChanges();
271265
Set<ChangedFile> expected = new HashSet<>();
272266
expected.add(new ChangedFile(directory, file, Type.MODIFY));
273267
assertThat(actual).isEqualTo(expected);
@@ -286,15 +280,13 @@ private File startWithNewDirectory() throws IOException {
286280
return directory;
287281
}
288282

289-
private ChangedFiles getSingleChangedFiles() {
290-
Set<ChangedFiles> singleChange = getSingleOnChange();
291-
assertThat(singleChange).hasSize(1);
292-
return singleChange.iterator().next();
283+
private Set<ChangedFile> getAllFileChanges() {
284+
return getAllFileChanges(this.changes);
293285
}
294286

295-
private Set<ChangedFiles> getSingleOnChange() {
296-
assertThat(this.changes).hasSize(1);
297-
return this.changes.get(0);
287+
private Set<ChangedFile> getAllFileChanges(List<Set<ChangedFiles>> changes) {
288+
return changes.stream().flatMap(Set<ChangedFiles>::stream)
289+
.flatMap((changedFiles) -> changedFiles.getFiles().stream()).collect(Collectors.toSet());
298290
}
299291

300292
private File touch(File file) throws IOException {

0 commit comments

Comments
 (0)