From 4766da6def17eb8c567fe6924ed299bb307b4996 Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Mon, 9 Dec 2024 15:48:24 +0100 Subject: [PATCH 1/7] Rewrite onEvent to on --- README.md | 2 +- src/main/java/engineering/swat/watch/Watcher.java | 6 +++--- src/test/java/engineering/swat/watch/DeleteLockTests.java | 2 +- .../java/engineering/swat/watch/RecursiveWatchTests.java | 6 +++--- .../java/engineering/swat/watch/SingleDirectoryTests.java | 2 +- src/test/java/engineering/swat/watch/SingleFileTests.java | 4 ++-- src/test/java/engineering/swat/watch/SmokeTests.java | 6 +++--- src/test/java/engineering/swat/watch/TortureTests.java | 8 ++++---- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index a2145a2c..f8dd168b 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Start using java-watch: var directory = Path.of("tmp", "test-dir"); var watcherSetup = Watcher.watch(directory, WatchScope.PATH_AND_CHILDREN) .withExecutor(Executors.newCachedThreadPool()) // optionally configure a custom thread pool - .onEvent(watchEvent -> { + .on(watchEvent -> { System.err.println(watchEvent); }); diff --git a/src/main/java/engineering/swat/watch/Watcher.java b/src/main/java/engineering/swat/watch/Watcher.java index ab762711..6cf2f63d 100644 --- a/src/main/java/engineering/swat/watch/Watcher.java +++ b/src/main/java/engineering/swat/watch/Watcher.java @@ -99,13 +99,13 @@ public static Watcher watch(Path path, WatchScope scope) { * @param eventHandler a callback that handles the watch event, will be called once per event. * @return this for optional method chaining */ - public Watcher onEvent(Consumer eventHandler) { + public Watcher on(Consumer eventHandler) { this.eventHandler = eventHandler; return this; } /** - * Optionally configure the executor in which the {@link #onEvent(Consumer)} callbacks are scheduled. + * Optionally configure the executor in which the {@link #on(Consumer)} callbacks are scheduled. * If not defined, every task will be scheduled on the {@link java.util.concurrent.ForkJoinPool#commonPool()}. * @param callbackHandler worker pool to use * @return this for optional method chaining @@ -119,7 +119,7 @@ public Watcher withExecutor(Executor callbackHandler) { * Start watch the path for events. * @return a subscription for the watch, when closed, new events will stop being registered to the worker pool. * @throws IOException in case the starting of the watcher caused an underlying IO exception - * @throws IllegalStateException the watchers is not configured correctly (for example, missing {@link #onEvent(Consumer)}, or a watcher is started twice) + * @throws IllegalStateException the watchers is not configured correctly (for example, missing {@link #on(Consumer)}, or a watcher is started twice) */ public ActiveWatch start() throws IOException { if (this.eventHandler == NULL_HANDLER) { diff --git a/src/test/java/engineering/swat/watch/DeleteLockTests.java b/src/test/java/engineering/swat/watch/DeleteLockTests.java index 08ed96f6..1996515c 100644 --- a/src/test/java/engineering/swat/watch/DeleteLockTests.java +++ b/src/test/java/engineering/swat/watch/DeleteLockTests.java @@ -77,7 +77,7 @@ private static void recursiveDelete(Path target) throws IOException { } private void deleteAndVerify(Path target, WatchScope scope) throws IOException { - try (var watch = Watcher.watch(target, scope).onEvent(ev -> {}).start()) { + try (var watch = Watcher.watch(target, scope).on(ev -> {}).start()) { recursiveDelete(target); assertFalse(Files.exists(target), "The file/directory shouldn't exist anymore"); } diff --git a/src/test/java/engineering/swat/watch/RecursiveWatchTests.java b/src/test/java/engineering/swat/watch/RecursiveWatchTests.java index bcc2a465..655a2b8d 100644 --- a/src/test/java/engineering/swat/watch/RecursiveWatchTests.java +++ b/src/test/java/engineering/swat/watch/RecursiveWatchTests.java @@ -74,7 +74,7 @@ void newDirectoryWithFilesChangesDetected() throws IOException { var created = new AtomicBoolean(false); var changed = new AtomicBoolean(false); var watchConfig = Watcher.watch(testDir.getTestDirectory(), WatchScope.PATH_AND_ALL_DESCENDANTS) - .onEvent(ev -> { + .on(ev -> { logger.debug("Event received: {}", ev); if (ev.calculateFullPath().equals(target.get())) { switch (ev.getKind()) { @@ -106,7 +106,7 @@ void correctRelativePathIsReported() throws IOException { Path relative = Path.of("a","b", "c", "d.txt"); var seen = new AtomicBoolean(false); var watcher = Watcher.watch(testDir.getTestDirectory(), WatchScope.PATH_AND_ALL_DESCENDANTS) - .onEvent(ev -> { + .on(ev -> { logger.debug("Seen event: {}", ev); if (ev.getRelativePath().equals(relative)) { seen.set(true); @@ -131,7 +131,7 @@ void deleteOfFileInDirectoryShouldBeVisible() throws IOException, InterruptedExc .orElseThrow(); var seen = new AtomicBoolean(false); var watchConfig = Watcher.watch(target.getParent(), WatchScope.PATH_AND_CHILDREN) - .onEvent(ev -> { + .on(ev -> { if (ev.getKind() == Kind.DELETED && ev.calculateFullPath().equals(target)) { seen.set(true); } diff --git a/src/test/java/engineering/swat/watch/SingleDirectoryTests.java b/src/test/java/engineering/swat/watch/SingleDirectoryTests.java index 4337c47d..f50a5ebd 100644 --- a/src/test/java/engineering/swat/watch/SingleDirectoryTests.java +++ b/src/test/java/engineering/swat/watch/SingleDirectoryTests.java @@ -68,7 +68,7 @@ void deleteOfFileInDirectoryShouldBeVisible() throws IOException, InterruptedExc var seenDelete = new AtomicBoolean(false); var seenCreate = new AtomicBoolean(false); var watchConfig = Watcher.watch(target.getParent(), WatchScope.PATH_AND_CHILDREN) - .onEvent(ev -> { + .on(ev -> { if (ev.getKind() == Kind.DELETED && ev.calculateFullPath().equals(target)) { seenDelete.set(true); } diff --git a/src/test/java/engineering/swat/watch/SingleFileTests.java b/src/test/java/engineering/swat/watch/SingleFileTests.java index f176df09..71a2ab93 100644 --- a/src/test/java/engineering/swat/watch/SingleFileTests.java +++ b/src/test/java/engineering/swat/watch/SingleFileTests.java @@ -66,7 +66,7 @@ void singleFileShouldNotTriggerOnOtherFilesInSameDir() throws IOException, Inter var seen = new AtomicBoolean(false); var others = new AtomicBoolean(false); var watchConfig = Watcher.watch(target, WatchScope.PATH_ONLY) - .onEvent(ev -> { + .on(ev -> { if (ev.calculateFullPath().equals(target)) { seen.set(true); } @@ -95,7 +95,7 @@ void singleFileThatMonitorsOnlyADirectory() throws IOException, InterruptedExcep var seen = new AtomicBoolean(false); var others = new AtomicBoolean(false); var watchConfig = Watcher.watch(target, WatchScope.PATH_ONLY) - .onEvent(ev -> { + .on(ev -> { if (ev.calculateFullPath().equals(target)) { seen.set(true); } diff --git a/src/test/java/engineering/swat/watch/SmokeTests.java b/src/test/java/engineering/swat/watch/SmokeTests.java index 2325e416..29cfe506 100644 --- a/src/test/java/engineering/swat/watch/SmokeTests.java +++ b/src/test/java/engineering/swat/watch/SmokeTests.java @@ -67,7 +67,7 @@ void watchDirectory() throws IOException, InterruptedException { var changed = new AtomicBoolean(false); var target = testDir.getTestFiles().get(0); var watchConfig = Watcher.watch(testDir.getTestDirectory(), WatchScope.PATH_AND_CHILDREN) - .onEvent(ev -> {if (ev.getKind() == MODIFIED && ev.calculateFullPath().equals(target)) { changed.set(true); }}) + .on(ev -> {if (ev.getKind() == MODIFIED && ev.calculateFullPath().equals(target)) { changed.set(true); }}) ; try (var activeWatch = watchConfig.start() ) { @@ -84,7 +84,7 @@ void watchRecursiveDirectory() throws IOException, InterruptedException { .findFirst() .orElseThrow(); var watchConfig = Watcher.watch(testDir.getTestDirectory(), WatchScope.PATH_AND_ALL_DESCENDANTS) - .onEvent(ev -> { if (ev.getKind() == MODIFIED && ev.calculateFullPath().equals(target)) { changed.set(true);}}) + .on(ev -> { if (ev.getKind() == MODIFIED && ev.calculateFullPath().equals(target)) { changed.set(true);}}) ; try (var activeWatch = watchConfig.start() ) { @@ -102,7 +102,7 @@ void watchSingleFile() throws IOException { .orElseThrow(); var watchConfig = Watcher.watch(target, WatchScope.PATH_ONLY) - .onEvent(ev -> { + .on(ev -> { if (ev.calculateFullPath().equals(target)) { changed.set(true); } diff --git a/src/test/java/engineering/swat/watch/TortureTests.java b/src/test/java/engineering/swat/watch/TortureTests.java index 2a87b930..5704d864 100644 --- a/src/test/java/engineering/swat/watch/TortureTests.java +++ b/src/test/java/engineering/swat/watch/TortureTests.java @@ -148,7 +148,7 @@ void pressureOnFSShouldNotMissNewFilesAnything() throws InterruptedException, IO var seenCreates = ConcurrentHashMap.newKeySet(); var watchConfig = Watcher.watch(testDir.getTestDirectory(), WatchScope.PATH_AND_ALL_DESCENDANTS) .withExecutor(pool) - .onEvent(ev -> { + .on(ev -> { var fullPath = ev.calculateFullPath(); switch (ev.getKind()) { case CREATED: @@ -212,7 +212,7 @@ void manyRegistrationsForSamePath() throws InterruptedException, IOException { try { var watcher = Watcher .watch(testDir.getTestDirectory(), WatchScope.PATH_AND_CHILDREN) - .onEvent(e -> seen.add(e.calculateFullPath())); + .on(e -> seen.add(e.calculateFullPath())); startRegistering.acquire(); try (var c = watcher.start()) { startedWatching.release(); @@ -279,7 +279,7 @@ void manyRegisterAndUnregisterSameTime() throws InterruptedException, IOExceptio for (int k = 0; k < 1000; k++) { var watcher = Watcher .watch(testDir.getTestDirectory(), WatchScope.PATH_AND_CHILDREN) - .onEvent(e -> { + .on(e -> { if (e.calculateFullPath().equals(target)) { seen.add(id); } @@ -345,7 +345,7 @@ void pressureOnFSShouldNotMissDeletes() throws InterruptedException, IOException final var happened = new Semaphore(0); var watchConfig = Watcher.watch(testDir.getTestDirectory(), WatchScope.PATH_AND_ALL_DESCENDANTS) .withExecutor(pool) - .onEvent(ev -> { + .on(ev -> { events.getAndIncrement(); happened.release(); var fullPath = ev.calculateFullPath(); From c33f9156fd9201265ccd28312a1ff4be7d075665 Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Mon, 9 Dec 2024 15:56:41 +0100 Subject: [PATCH 2/7] Added convenience overload --- .../swat/watch/WatchEventListener.java | 37 +++++++++++++++++++ .../java/engineering/swat/watch/Watcher.java | 31 ++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/main/java/engineering/swat/watch/WatchEventListener.java diff --git a/src/main/java/engineering/swat/watch/WatchEventListener.java b/src/main/java/engineering/swat/watch/WatchEventListener.java new file mode 100644 index 00000000..5fa897d0 --- /dev/null +++ b/src/main/java/engineering/swat/watch/WatchEventListener.java @@ -0,0 +1,37 @@ +/* + * BSD 2-Clause License + * + * Copyright (c) 2023, Swat.engineering + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package engineering.swat.watch; + +/** + * A visit like interface that allows you to only override the functions you are interested in + */ +public interface WatchEventListener { + default void onCreated(WatchEvent ev) { } + default void onModified(WatchEvent ev) { } + default void onDeleted(WatchEvent ev) { } + default void onOverflow(WatchEvent ev) { } +} diff --git a/src/main/java/engineering/swat/watch/Watcher.java b/src/main/java/engineering/swat/watch/Watcher.java index 6cf2f63d..7926574c 100644 --- a/src/main/java/engineering/swat/watch/Watcher.java +++ b/src/main/java/engineering/swat/watch/Watcher.java @@ -100,10 +100,41 @@ public static Watcher watch(Path path, WatchScope scope) { * @return this for optional method chaining */ public Watcher on(Consumer eventHandler) { + if (this.eventHandler != NULL_HANDLER) { + throw new IllegalArgumentException("on handler cannot be set more than once"); + } this.eventHandler = eventHandler; return this; } + /** + * Convenience variant of {@link #on(Consumer)}, which allows you to only respond to certain events + */ + public Watcher on(WatchEventListener listener) { + if (this.eventHandler != NULL_HANDLER) { + throw new IllegalArgumentException("on handler cannot be set more than once"); + } + this.eventHandler = ev -> { + switch (ev.getKind()) { + case CREATED: + listener.onCreated(ev); + break; + case DELETED: + listener.onDeleted(ev); + break; + case MODIFIED: + listener.onModified(ev); + break; + case OVERFLOW: + listener.onOverflow(ev); + break; + default: + throw new IllegalArgumentException("Unexpected kind: " + ev.getKind()); + } + }; + return this; + } + /** * Optionally configure the executor in which the {@link #on(Consumer)} callbacks are scheduled. * If not defined, every task will be scheduled on the {@link java.util.concurrent.ForkJoinPool#commonPool()}. From faae1e7695790b535ad3e5fa0b02a9458147452a Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Mon, 9 Dec 2024 16:29:35 +0100 Subject: [PATCH 3/7] Added extra tests for API --- .../swat/watch/APIErrorsTests.java | 109 ++++++++++++++++++ .../swat/watch/SingleDirectoryTests.java | 31 +++++ 2 files changed, 140 insertions(+) create mode 100644 src/test/java/engineering/swat/watch/APIErrorsTests.java diff --git a/src/test/java/engineering/swat/watch/APIErrorsTests.java b/src/test/java/engineering/swat/watch/APIErrorsTests.java new file mode 100644 index 00000000..bc370050 --- /dev/null +++ b/src/test/java/engineering/swat/watch/APIErrorsTests.java @@ -0,0 +1,109 @@ +/* + * BSD 2-Clause License + * + * Copyright (c) 2023, Swat.engineering + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package engineering.swat.watch; + +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +import java.io.IOException; +import java.nio.file.Files; + +import org.awaitility.Awaitility; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class APIErrorsTests { + + private TestDirectory testDir; + + @BeforeEach + void setup() throws IOException { + testDir = new TestDirectory(); + } + + @AfterEach + void cleanup() { + if (testDir != null) { + testDir.close(); + } + } + + @BeforeAll + static void setupEverything() { + Awaitility.setDefaultTimeout(TestHelper.NORMAL_WAIT); + } + + @Test + void noDuplicateEvents() { + assertThrowsExactly(IllegalArgumentException.class, () -> + Watcher + .watch(testDir.getTestDirectory(), WatchScope.PATH_AND_CHILDREN) + .on(System.out::println) + .on(System.err::println) + ); + } + + @Test + void OnlyDirectoryWatchingOnDirectories() { + assertThrowsExactly(IllegalArgumentException.class, () -> + Watcher + .watch(testDir.getTestFiles().get(0), WatchScope.PATH_AND_CHILDREN) + ); + } + + @Test + void doNotStartWithoutEventHandler() { + assertThrowsExactly(IllegalStateException.class, () -> + Watcher + .watch(testDir.getTestDirectory(), WatchScope.PATH_AND_CHILDREN) + .start() + ); + } + + @Test + void noRelativePaths() { + var relativePath = testDir.getTestDirectory().resolve("d1").relativize(testDir.getTestDirectory()); + + assertThrowsExactly(IllegalArgumentException.class, () -> + Watcher + .watch(relativePath, WatchScope.PATH_AND_CHILDREN) + .start() + ); + } + + @Test + void nonExistingDirectory() throws IOException { + var nonExistingDir = testDir.getTestDirectory().resolve("testd1"); + Files.createDirectory(nonExistingDir); + var w = Watcher.watch(nonExistingDir, WatchScope.PATH_AND_CHILDREN); + Files.delete(nonExistingDir); + assertThrowsExactly(IllegalStateException.class, w::start); + } + + +} diff --git a/src/test/java/engineering/swat/watch/SingleDirectoryTests.java b/src/test/java/engineering/swat/watch/SingleDirectoryTests.java index f50a5ebd..63ec141b 100644 --- a/src/test/java/engineering/swat/watch/SingleDirectoryTests.java +++ b/src/test/java/engineering/swat/watch/SingleDirectoryTests.java @@ -89,4 +89,35 @@ void deleteOfFileInDirectoryShouldBeVisible() throws IOException, InterruptedExc .untilTrue(seenCreate); } } + + @Test + void alternativeAPITest() throws IOException, InterruptedException { + var target = testDir.getTestFiles().get(0); + var seenDelete = new AtomicBoolean(false); + var seenCreate = new AtomicBoolean(false); + var watchConfig = Watcher.watch(target.getParent(), WatchScope.PATH_AND_CHILDREN) + .on(new WatchEventListener() { + @Override + public void onCreated(WatchEvent ev) { + seenCreate.set(true); + } + + @Override + public void onDeleted(WatchEvent ev) { + seenDelete.set(true); + } + }); + try (var watch = watchConfig.start()) { + + // Delete the file + Files.delete(target); + await("File deletion should generate delete event") + .untilTrue(seenDelete); + + // Re-create it again + Files.writeString(target, "Hello World"); + await("File creation should generate create event") + .untilTrue(seenCreate); + } + } } From 8f5c5f4b5693e334f699091cc7f4986529976e20 Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Tue, 10 Dec 2024 13:09:11 +0100 Subject: [PATCH 4/7] Update src/test/java/engineering/swat/watch/APIErrorsTests.java Co-authored-by: sungshik <16154899+sungshik@users.noreply.github.com> --- src/test/java/engineering/swat/watch/APIErrorsTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/engineering/swat/watch/APIErrorsTests.java b/src/test/java/engineering/swat/watch/APIErrorsTests.java index bc370050..ffa5b44c 100644 --- a/src/test/java/engineering/swat/watch/APIErrorsTests.java +++ b/src/test/java/engineering/swat/watch/APIErrorsTests.java @@ -69,7 +69,7 @@ void noDuplicateEvents() { } @Test - void OnlyDirectoryWatchingOnDirectories() { + void onlyDirectoryWatchingOnDirectories() { assertThrowsExactly(IllegalArgumentException.class, () -> Watcher .watch(testDir.getTestFiles().get(0), WatchScope.PATH_AND_CHILDREN) From bdcb8f0675276b47ef4f819f45590e67d6a3f87e Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Tue, 10 Dec 2024 13:19:33 +0100 Subject: [PATCH 5/7] Configure how picky codecov is --- .codecov.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .codecov.yml diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 00000000..3ad6ab6b --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,13 @@ +coverage: + range: "80..100" + precision: 1 + status: + project: + default: + target: auto #default + threshold: 5% + base: auto + patch: + default: + target: auto + threshold: 10% From df2912d414ae611324158793a96790d859e46528 Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Tue, 10 Dec 2024 13:20:30 +0100 Subject: [PATCH 6/7] Improved name of empty handler --- src/main/java/engineering/swat/watch/Watcher.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/engineering/swat/watch/Watcher.java b/src/main/java/engineering/swat/watch/Watcher.java index 7926574c..303bfefc 100644 --- a/src/main/java/engineering/swat/watch/Watcher.java +++ b/src/main/java/engineering/swat/watch/Watcher.java @@ -54,8 +54,8 @@ public class Watcher { private final Path path; private volatile Executor executor = CompletableFuture::runAsync; - private static final Consumer NULL_HANDLER = p -> {}; - private volatile Consumer eventHandler = NULL_HANDLER; + private static final Consumer EMPTY_HANDLER = p -> {}; + private volatile Consumer eventHandler = EMPTY_HANDLER; private Watcher(WatchScope scope, Path path) { @@ -100,7 +100,7 @@ public static Watcher watch(Path path, WatchScope scope) { * @return this for optional method chaining */ public Watcher on(Consumer eventHandler) { - if (this.eventHandler != NULL_HANDLER) { + if (this.eventHandler != EMPTY_HANDLER) { throw new IllegalArgumentException("on handler cannot be set more than once"); } this.eventHandler = eventHandler; @@ -111,7 +111,7 @@ public Watcher on(Consumer eventHandler) { * Convenience variant of {@link #on(Consumer)}, which allows you to only respond to certain events */ public Watcher on(WatchEventListener listener) { - if (this.eventHandler != NULL_HANDLER) { + if (this.eventHandler != EMPTY_HANDLER) { throw new IllegalArgumentException("on handler cannot be set more than once"); } this.eventHandler = ev -> { @@ -153,7 +153,7 @@ public Watcher withExecutor(Executor callbackHandler) { * @throws IllegalStateException the watchers is not configured correctly (for example, missing {@link #on(Consumer)}, or a watcher is started twice) */ public ActiveWatch start() throws IOException { - if (this.eventHandler == NULL_HANDLER) { + if (this.eventHandler == EMPTY_HANDLER) { throw new IllegalStateException("There is no onEvent handler defined"); } switch (scope) { From 211181d7c9172412e3042388f429b4d6a72d70ff Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Tue, 10 Dec 2024 13:42:31 +0100 Subject: [PATCH 7/7] Tuning of coverage criterea --- .codecov.yml | 6 +++--- pom.xml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.codecov.yml b/.codecov.yml index 3ad6ab6b..ce294a3a 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -4,10 +4,10 @@ coverage: status: project: default: - target: auto #default - threshold: 5% + target: auto + threshold: 5% # allow a bit of coverage drop base: auto patch: default: - target: auto + target: 50% # have at least 50% of test coverage threshold: 10% diff --git a/pom.xml b/pom.xml index 9c935e0b..1d1df8fd 100644 --- a/pom.xml +++ b/pom.xml @@ -129,6 +129,7 @@ target/** .vscode/** .editorconfig + .codecov.yml