|
@@ -14,13 +14,17 @@ import org.elasticsearch.test.ESTestCase;
|
|
|
import java.io.BufferedWriter;
|
|
|
import java.io.IOException;
|
|
|
import java.nio.charset.Charset;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
import java.nio.file.Files;
|
|
|
import java.nio.file.Path;
|
|
|
import java.nio.file.StandardOpenOption;
|
|
|
+import java.nio.file.attribute.FileTime;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
|
import static org.hamcrest.Matchers.contains;
|
|
|
+import static org.hamcrest.Matchers.containsInAnyOrder;
|
|
|
+import static org.hamcrest.Matchers.empty;
|
|
|
import static org.hamcrest.Matchers.equalTo;
|
|
|
import static org.hamcrest.Matchers.hasSize;
|
|
|
|
|
@@ -101,10 +105,62 @@ public class FileWatcherTests extends ESTestCase {
|
|
|
fileWatcher.checkAndNotify();
|
|
|
assertThat(changes.notifications(), hasSize(0));
|
|
|
|
|
|
+ // change modification date, but not contents [we set the time in the future to guarantee a change]
|
|
|
+ Files.setLastModifiedTime(testFile, FileTime.fromMillis(System.currentTimeMillis() + 1));
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), contains(equalTo("onFileChanged: test.txt")));
|
|
|
+
|
|
|
+ changes.notifications().clear();
|
|
|
Files.delete(testFile);
|
|
|
fileWatcher.checkAndNotify();
|
|
|
assertThat(changes.notifications(), contains(equalTo("onFileDeleted: test.txt")));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testSimpleFileOperationsWithContentChecking() throws IOException {
|
|
|
+ Path tempDir = createTempDir();
|
|
|
+ RecordingChangeListener changes = new RecordingChangeListener(tempDir);
|
|
|
+ Path testFile = tempDir.resolve("test.txt");
|
|
|
+ touch(testFile);
|
|
|
+ FileWatcher fileWatcher = new FileWatcher(testFile, true);
|
|
|
+ fileWatcher.addListener(changes);
|
|
|
+ fileWatcher.init();
|
|
|
+ assertThat(changes.notifications(), contains(equalTo("onFileInit: test.txt")));
|
|
|
+
|
|
|
+ changes.notifications().clear();
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), empty());
|
|
|
+
|
|
|
+ append("Test", testFile, Charset.defaultCharset());
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), contains(equalTo("onFileChanged: test.txt")));
|
|
|
+
|
|
|
+ changes.notifications().clear();
|
|
|
+
|
|
|
+ // change modification date, but not contents
|
|
|
+ Files.setLastModifiedTime(testFile, FileTime.fromMillis(System.currentTimeMillis() + 1));
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), empty());
|
|
|
+
|
|
|
+ changes.notifications().clear();
|
|
|
+
|
|
|
+ // change modification date again, but not contents
|
|
|
+ Files.setLastModifiedTime(testFile, FileTime.fromMillis(System.currentTimeMillis() + 2));
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ // This will not trigger a notification because the hash was calculated last time
|
|
|
+ assertThat(changes.notifications(), empty());
|
|
|
+
|
|
|
+ // Change file length without changing modification time
|
|
|
+ final FileTime modifiedTime = Files.getLastModifiedTime(testFile);
|
|
|
+ append("Modified", testFile, Charset.defaultCharset());
|
|
|
+ Files.setLastModifiedTime(testFile, modifiedTime);
|
|
|
+
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), contains(equalTo("onFileChanged: test.txt")));
|
|
|
|
|
|
+ changes.notifications().clear();
|
|
|
+ Files.delete(testFile);
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), contains(equalTo("onFileDeleted: test.txt")));
|
|
|
}
|
|
|
|
|
|
public void testSimpleDirectoryOperations() throws IOException {
|
|
@@ -196,6 +252,97 @@ public class FileWatcherTests extends ESTestCase {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ public void testSimpleDirectoryOperationsWithContentChecking() throws IOException {
|
|
|
+ final long startTime = System.currentTimeMillis();
|
|
|
+
|
|
|
+ Path tempDir = createTempDir();
|
|
|
+ RecordingChangeListener changes = new RecordingChangeListener(tempDir);
|
|
|
+ Path testDir = tempDir.resolve("test-dir");
|
|
|
+ Files.createDirectories(testDir);
|
|
|
+ for (String fileName : List.of("test1.txt", "test2.txt", "test3.txt", "test4.txt")) {
|
|
|
+ Files.writeString(testDir.resolve(fileName), "initial", StandardCharsets.UTF_8);
|
|
|
+ }
|
|
|
+
|
|
|
+ FileWatcher fileWatcher = new FileWatcher(testDir, true);
|
|
|
+ fileWatcher.addListener(changes);
|
|
|
+ fileWatcher.init();
|
|
|
+ assertThat(changes.notifications(), contains(
|
|
|
+ equalTo("onDirectoryInit: test-dir/"),
|
|
|
+ equalTo("onFileInit: test-dir/test1.txt"),
|
|
|
+ equalTo("onFileInit: test-dir/test2.txt"),
|
|
|
+ equalTo("onFileInit: test-dir/test3.txt"),
|
|
|
+ equalTo("onFileInit: test-dir/test4.txt")
|
|
|
+ ));
|
|
|
+
|
|
|
+ changes.notifications().clear();
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), hasSize(0));
|
|
|
+
|
|
|
+ // Modify the length of file #1
|
|
|
+ append("Test-1", testDir.resolve("test1.txt"), Charset.defaultCharset());
|
|
|
+
|
|
|
+ // Change lastModified on file #2 (set it to before this test started so there's no chance of accidental matching)
|
|
|
+ // However the contents haven't changed, so it won't be notified
|
|
|
+ Files.setLastModifiedTime(testDir.resolve("test2.txt"), FileTime.fromMillis(startTime - 100));
|
|
|
+
|
|
|
+ // Add a new file
|
|
|
+ Files.writeString(testDir.resolve("test5.txt"), "abc", StandardCharsets.UTF_8);
|
|
|
+
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(
|
|
|
+ changes.notifications(),
|
|
|
+ containsInAnyOrder(
|
|
|
+ "onFileChanged: test-dir/test1.txt",
|
|
|
+ "onFileCreated: test-dir/test5.txt"
|
|
|
+ )
|
|
|
+ );
|
|
|
+
|
|
|
+ // Change file #2 but don't change the size
|
|
|
+ Files.writeString(testDir.resolve("test2.txt"), "changed", StandardCharsets.UTF_8);
|
|
|
+ // Change lastModified on file #3 (newer than the last update, but still before the test started)
|
|
|
+ // But no change to contents, so no notification
|
|
|
+ Files.setLastModifiedTime(testDir.resolve("test3.txt"), FileTime.fromMillis(startTime - 50));
|
|
|
+
|
|
|
+ changes.notifications().clear();
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), containsInAnyOrder(
|
|
|
+ equalTo("onFileChanged: test-dir/test2.txt")
|
|
|
+ ));
|
|
|
+
|
|
|
+ // change the contents of files #2 (change in size) and #3 (same size)
|
|
|
+ Files.writeString(testDir.resolve("test2.txt"), "new contents", StandardCharsets.UTF_8);
|
|
|
+ Files.writeString(testDir.resolve("test3.txt"), "updated", StandardCharsets.UTF_8);
|
|
|
+
|
|
|
+ changes.notifications().clear();
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), containsInAnyOrder(
|
|
|
+ equalTo("onFileChanged: test-dir/test2.txt"),
|
|
|
+ equalTo("onFileChanged: test-dir/test3.txt")
|
|
|
+ ));
|
|
|
+
|
|
|
+ // Change lastModified on files #2 & #3, but not the contents
|
|
|
+ Files.setLastModifiedTime(testDir.resolve("test2.txt"), FileTime.fromMillis(System.currentTimeMillis() + 3));
|
|
|
+ Files.setLastModifiedTime(testDir.resolve("test3.txt"), FileTime.fromMillis(System.currentTimeMillis() + 3));
|
|
|
+
|
|
|
+ changes.notifications().clear();
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), hasSize(0));
|
|
|
+
|
|
|
+ // Do nothing
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), hasSize(0));
|
|
|
+
|
|
|
+ // Delete files
|
|
|
+ Files.delete(testDir.resolve("test1.txt"));
|
|
|
+ Files.delete(testDir.resolve("test2.txt"));
|
|
|
+
|
|
|
+ fileWatcher.checkAndNotify();
|
|
|
+ assertThat(changes.notifications(), contains(
|
|
|
+ equalTo("onFileDeleted: test-dir/test1.txt"),
|
|
|
+ equalTo("onFileDeleted: test-dir/test2.txt")
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
public void testNestedDirectoryOperations() throws IOException {
|
|
|
Path tempDir = createTempDir();
|
|
|
RecordingChangeListener changes = new RecordingChangeListener(tempDir);
|