aboutsummaryrefslogtreecommitdiff
path: root/jimfs/src/test/java/com/google/common/jimfs/PollingWatchServiceTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'jimfs/src/test/java/com/google/common/jimfs/PollingWatchServiceTest.java')
-rw-r--r--jimfs/src/test/java/com/google/common/jimfs/PollingWatchServiceTest.java247
1 files changed, 247 insertions, 0 deletions
diff --git a/jimfs/src/test/java/com/google/common/jimfs/PollingWatchServiceTest.java b/jimfs/src/test/java/com/google/common/jimfs/PollingWatchServiceTest.java
new file mode 100644
index 0000000..86f9832
--- /dev/null
+++ b/jimfs/src/test/java/com/google/common/jimfs/PollingWatchServiceTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.jimfs;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.jimfs.AbstractWatchService.Event;
+import com.google.common.jimfs.AbstractWatchService.Key;
+import com.google.common.util.concurrent.Runnables;
+import com.google.common.util.concurrent.Uninterruptibles;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.NotDirectoryException;
+import java.nio.file.Path;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link PollingWatchService}.
+ *
+ * @author Colin Decker
+ */
+@RunWith(JUnit4.class)
+public class PollingWatchServiceTest {
+
+ private JimfsFileSystem fs;
+ private PollingWatchService watcher;
+
+ @Before
+ public void setUp() {
+ fs = (JimfsFileSystem) Jimfs.newFileSystem(Configuration.unix());
+ watcher =
+ new PollingWatchService(
+ fs.getDefaultView(),
+ fs.getPathService(),
+ new FileSystemState(Runnables.doNothing()),
+ 4,
+ MILLISECONDS);
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ watcher.close();
+ fs.close();
+ watcher = null;
+ fs = null;
+ }
+
+ @Test
+ public void testNewWatcher() {
+ assertThat(watcher.isOpen()).isTrue();
+ assertThat(watcher.isPolling()).isFalse();
+ }
+
+ @Test
+ public void testRegister() throws IOException {
+ Key key = watcher.register(createDirectory(), ImmutableList.of(ENTRY_CREATE));
+ assertThat(key.isValid()).isTrue();
+
+ assertThat(watcher.isPolling()).isTrue();
+ }
+
+ @Test
+ public void testRegister_fileDoesNotExist() throws IOException {
+ try {
+ watcher.register(fs.getPath("/a/b/c"), ImmutableList.of(ENTRY_CREATE));
+ fail();
+ } catch (NoSuchFileException expected) {
+ }
+ }
+
+ @Test
+ public void testRegister_fileIsNotDirectory() throws IOException {
+ Path path = fs.getPath("/a.txt");
+ Files.createFile(path);
+ try {
+ watcher.register(path, ImmutableList.of(ENTRY_CREATE));
+ fail();
+ } catch (NotDirectoryException expected) {
+ }
+ }
+
+ @Test
+ public void testCancellingLastKeyStopsPolling() throws IOException {
+ Key key = watcher.register(createDirectory(), ImmutableList.of(ENTRY_CREATE));
+ key.cancel();
+ assertThat(key.isValid()).isFalse();
+
+ assertThat(watcher.isPolling()).isFalse();
+
+ Key key2 = watcher.register(createDirectory(), ImmutableList.of(ENTRY_CREATE));
+ Key key3 = watcher.register(createDirectory(), ImmutableList.of(ENTRY_DELETE));
+
+ assertThat(watcher.isPolling()).isTrue();
+
+ key2.cancel();
+
+ assertThat(watcher.isPolling()).isTrue();
+
+ key3.cancel();
+
+ assertThat(watcher.isPolling()).isFalse();
+ }
+
+ @Test
+ public void testCloseCancelsAllKeysAndStopsPolling() throws IOException {
+ Key key1 = watcher.register(createDirectory(), ImmutableList.of(ENTRY_CREATE));
+ Key key2 = watcher.register(createDirectory(), ImmutableList.of(ENTRY_DELETE));
+
+ assertThat(key1.isValid()).isTrue();
+ assertThat(key2.isValid()).isTrue();
+ assertThat(watcher.isPolling()).isTrue();
+
+ watcher.close();
+
+ assertThat(key1.isValid()).isFalse();
+ assertThat(key2.isValid()).isFalse();
+ assertThat(watcher.isPolling()).isFalse();
+ }
+
+ @Test(timeout = 2000)
+ public void testWatchForOneEventType() throws IOException, InterruptedException {
+ JimfsPath path = createDirectory();
+ watcher.register(path, ImmutableList.of(ENTRY_CREATE));
+
+ Files.createFile(path.resolve("foo"));
+
+ assertWatcherHasEvents(new Event<>(ENTRY_CREATE, 1, fs.getPath("foo")));
+
+ Files.createFile(path.resolve("bar"));
+ Files.createFile(path.resolve("baz"));
+
+ assertWatcherHasEvents(
+ new Event<>(ENTRY_CREATE, 1, fs.getPath("bar")),
+ new Event<>(ENTRY_CREATE, 1, fs.getPath("baz")));
+ }
+
+ @Test(timeout = 2000)
+ public void testWatchForMultipleEventTypes() throws IOException, InterruptedException {
+ JimfsPath path = createDirectory();
+ watcher.register(path, ImmutableList.of(ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY));
+
+ Files.createDirectory(path.resolve("foo"));
+ Files.createFile(path.resolve("bar"));
+
+ assertWatcherHasEvents(
+ new Event<>(ENTRY_CREATE, 1, fs.getPath("bar")),
+ new Event<>(ENTRY_CREATE, 1, fs.getPath("foo")));
+
+ Files.createFile(path.resolve("baz"));
+ Files.delete(path.resolve("bar"));
+ Files.createFile(path.resolve("foo/bar"));
+
+ assertWatcherHasEvents(
+ new Event<>(ENTRY_CREATE, 1, fs.getPath("baz")),
+ new Event<>(ENTRY_DELETE, 1, fs.getPath("bar")),
+ new Event<>(ENTRY_MODIFY, 1, fs.getPath("foo")));
+
+ Files.delete(path.resolve("foo/bar"));
+ ensureTimeToPoll(); // watcher polls, seeing modification, then polls again, seeing delete
+ Files.delete(path.resolve("foo"));
+
+ assertWatcherHasEvents(
+ new Event<>(ENTRY_MODIFY, 1, fs.getPath("foo")),
+ new Event<>(ENTRY_DELETE, 1, fs.getPath("foo")));
+
+ Files.createDirectories(path.resolve("foo/bar"));
+
+ // polling here may either see just the creation of foo, or may first see the creation of foo
+ // and then the creation of foo/bar (modification of foo) since those don't happen atomically
+ assertWatcherHasEvents(
+ ImmutableList.<WatchEvent<?>>of(new Event<>(ENTRY_CREATE, 1, fs.getPath("foo"))),
+ // or
+ ImmutableList.<WatchEvent<?>>of(
+ new Event<>(ENTRY_CREATE, 1, fs.getPath("foo")),
+ new Event<>(ENTRY_MODIFY, 1, fs.getPath("foo"))));
+
+ Files.delete(path.resolve("foo/bar"));
+ Files.delete(path.resolve("foo"));
+
+ // polling here may either just see the deletion of foo, or may first see the deletion of bar
+ // (modification of foo) and then the deletion of foo
+ assertWatcherHasEvents(
+ ImmutableList.<WatchEvent<?>>of(new Event<>(ENTRY_DELETE, 1, fs.getPath("foo"))),
+ // or
+ ImmutableList.<WatchEvent<?>>of(
+ new Event<>(ENTRY_MODIFY, 1, fs.getPath("foo")),
+ new Event<>(ENTRY_DELETE, 1, fs.getPath("foo"))));
+ }
+
+ private void assertWatcherHasEvents(WatchEvent<?>... events) throws InterruptedException {
+ assertWatcherHasEvents(Arrays.asList(events), ImmutableList.<WatchEvent<?>>of());
+ }
+
+ private void assertWatcherHasEvents(List<WatchEvent<?>> expected, List<WatchEvent<?>> alternate)
+ throws InterruptedException {
+ ensureTimeToPoll(); // otherwise we could read 1 event but not all the events we're expecting
+ WatchKey key = watcher.take();
+ List<WatchEvent<?>> keyEvents = key.pollEvents();
+
+ if (keyEvents.size() == expected.size() || alternate.isEmpty()) {
+ assertThat(keyEvents).containsExactlyElementsIn(expected);
+ } else {
+ assertThat(keyEvents).containsExactlyElementsIn(alternate);
+ }
+ key.reset();
+ }
+
+ private static void ensureTimeToPoll() {
+ Uninterruptibles.sleepUninterruptibly(40, MILLISECONDS);
+ }
+
+ private JimfsPath createDirectory() throws IOException {
+ JimfsPath path = fs.getPath("/" + UUID.randomUUID().toString());
+ Files.createDirectory(path);
+ return path;
+ }
+}