Basic.java revision 3909
893N/A/*
3909N/A * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
893N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
893N/A *
893N/A * This code is free software; you can redistribute it and/or modify it
893N/A * under the terms of the GNU General Public License version 2 only, as
893N/A * published by the Free Software Foundation.
893N/A *
893N/A * This code is distributed in the hope that it will be useful, but WITHOUT
893N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
893N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
893N/A * version 2 for more details (a copy is included in the LICENSE file that
893N/A * accompanied this code).
893N/A *
893N/A * You should have received a copy of the GNU General Public License version
893N/A * 2 along with this work; if not, write to the Free Software Foundation,
893N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
893N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
893N/A */
893N/A
893N/A/* @test
3779N/A * @bug 4313887 6838333 7017446
893N/A * @summary Unit test for java.nio.file.WatchService
893N/A * @library ..
893N/A * @run main/timeout=120 Basic
893N/A */
893N/A
893N/Aimport java.nio.file.*;
893N/Aimport static java.nio.file.StandardWatchEventKind.*;
893N/Aimport java.nio.file.attribute.*;
893N/Aimport java.io.*;
893N/Aimport java.util.*;
893N/Aimport java.util.concurrent.TimeUnit;
893N/A
893N/A/**
893N/A * Unit test for WatchService that exercises all methods in various scenarios.
893N/A */
893N/A
893N/Apublic class Basic {
893N/A
3471N/A static void checkKey(WatchKey key, Path dir) {
3471N/A if (!key.isValid())
3471N/A throw new RuntimeException("Key is not valid");
3779N/A if (key.watchable() != dir)
3779N/A throw new RuntimeException("Unexpected watchable");
893N/A }
893N/A
893N/A static void takeExpectedKey(WatchService watcher, WatchKey expected) {
893N/A System.out.println("take events...");
893N/A WatchKey key;
893N/A try {
893N/A key = watcher.take();
893N/A } catch (InterruptedException x) {
893N/A // not expected
893N/A throw new RuntimeException(x);
893N/A }
893N/A if (key != expected)
893N/A throw new RuntimeException("removed unexpected key");
893N/A }
893N/A
893N/A static void checkExpectedEvent(Iterable<WatchEvent<?>> events,
893N/A WatchEvent.Kind<?> expectedKind,
893N/A Object expectedContext)
893N/A {
893N/A WatchEvent<?> event = events.iterator().next();
893N/A System.out.format("got event: type=%s, count=%d, context=%s\n",
893N/A event.kind(), event.count(), event.context());
893N/A if (event.kind() != expectedKind)
893N/A throw new RuntimeException("unexpected event");
893N/A if (!expectedContext.equals(event.context()))
893N/A throw new RuntimeException("unexpected context");
893N/A }
893N/A
893N/A /**
893N/A * Simple test of each of the standard events
893N/A */
893N/A static void testEvents(Path dir) throws IOException {
893N/A System.out.println("-- Standard Events --");
893N/A
893N/A FileSystem fs = FileSystems.getDefault();
893N/A Path name = fs.getPath("foo");
893N/A
3471N/A try (WatchService watcher = fs.newWatchService()) {
893N/A // --- ENTRY_CREATE ---
893N/A
893N/A // register for event
893N/A System.out.format("register %s for ENTRY_CREATE\n", dir);
893N/A WatchKey myKey = dir.register(watcher,
893N/A new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
3471N/A checkKey(myKey, dir);
893N/A
893N/A // create file
893N/A Path file = dir.resolve("foo");
893N/A System.out.format("create %s\n", file);
3471N/A Files.createFile(file);
893N/A
893N/A // remove key and check that we got the ENTRY_CREATE event
893N/A takeExpectedKey(watcher, myKey);
893N/A checkExpectedEvent(myKey.pollEvents(),
893N/A StandardWatchEventKind.ENTRY_CREATE, name);
893N/A
893N/A System.out.println("reset key");
893N/A if (!myKey.reset())
893N/A throw new RuntimeException("key has been cancalled");
893N/A
893N/A System.out.println("OKAY");
893N/A
893N/A // --- ENTRY_DELETE ---
893N/A
893N/A System.out.format("register %s for ENTRY_DELETE\n", dir);
893N/A WatchKey deleteKey = dir.register(watcher,
893N/A new WatchEvent.Kind<?>[]{ ENTRY_DELETE });
893N/A if (deleteKey != myKey)
893N/A throw new RuntimeException("register did not return existing key");
3471N/A checkKey(deleteKey, dir);
893N/A
893N/A System.out.format("delete %s\n", file);
3471N/A Files.delete(file);
893N/A takeExpectedKey(watcher, myKey);
893N/A checkExpectedEvent(myKey.pollEvents(),
893N/A StandardWatchEventKind.ENTRY_DELETE, name);
893N/A
893N/A System.out.println("reset key");
893N/A if (!myKey.reset())
893N/A throw new RuntimeException("key has been cancalled");
893N/A
893N/A System.out.println("OKAY");
893N/A
893N/A // create the file for the next test
3471N/A Files.createFile(file);
893N/A
893N/A // --- ENTRY_MODIFY ---
893N/A
893N/A System.out.format("register %s for ENTRY_MODIFY\n", dir);
893N/A WatchKey newKey = dir.register(watcher,
893N/A new WatchEvent.Kind<?>[]{ ENTRY_MODIFY });
893N/A if (newKey != myKey)
893N/A throw new RuntimeException("register did not return existing key");
3471N/A checkKey(newKey, dir);
893N/A
893N/A System.out.format("update: %s\n", file);
3471N/A try (OutputStream out = Files.newOutputStream(file, StandardOpenOption.APPEND)) {
893N/A out.write("I am a small file".getBytes("UTF-8"));
893N/A }
893N/A
893N/A // remove key and check that we got the ENTRY_MODIFY event
893N/A takeExpectedKey(watcher, myKey);
893N/A checkExpectedEvent(myKey.pollEvents(),
893N/A StandardWatchEventKind.ENTRY_MODIFY, name);
893N/A System.out.println("OKAY");
893N/A
893N/A // done
3471N/A Files.delete(file);
893N/A }
893N/A }
893N/A
893N/A /**
893N/A * Check that a cancelled key will never be queued
893N/A */
893N/A static void testCancel(Path dir) throws IOException {
893N/A System.out.println("-- Cancel --");
893N/A
3471N/A try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
893N/A
893N/A System.out.format("register %s for events\n", dir);
893N/A WatchKey myKey = dir.register(watcher,
893N/A new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
3471N/A checkKey(myKey, dir);
893N/A
893N/A System.out.println("cancel key");
893N/A myKey.cancel();
893N/A
893N/A // create a file in the directory
893N/A Path file = dir.resolve("mars");
893N/A System.out.format("create: %s\n", file);
3471N/A Files.createFile(file);
893N/A
893N/A // poll for keys - there will be none
893N/A System.out.println("poll...");
893N/A try {
893N/A WatchKey key = watcher.poll(3000, TimeUnit.MILLISECONDS);
893N/A if (key != null)
893N/A throw new RuntimeException("key should not be queued");
893N/A } catch (InterruptedException x) {
893N/A throw new RuntimeException(x);
893N/A }
893N/A
893N/A // done
3471N/A Files.delete(file);
893N/A
893N/A System.out.println("OKAY");
893N/A }
893N/A }
893N/A
893N/A /**
893N/A * Check that deleting a registered directory causes the key to be
893N/A * cancelled and queued.
893N/A */
893N/A static void testAutomaticCancel(Path dir) throws IOException {
893N/A System.out.println("-- Automatic Cancel --");
893N/A
3471N/A Path subdir = Files.createDirectory(dir.resolve("bar"));
893N/A
3471N/A try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
893N/A
893N/A System.out.format("register %s for events\n", subdir);
893N/A WatchKey myKey = subdir.register(watcher,
893N/A new WatchEvent.Kind<?>[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY });
893N/A
893N/A System.out.format("delete: %s\n", subdir);
3471N/A Files.delete(subdir);
893N/A takeExpectedKey(watcher, myKey);
893N/A
893N/A System.out.println("reset key");
893N/A if (myKey.reset())
893N/A throw new RuntimeException("Key was not cancelled");
893N/A if (myKey.isValid())
893N/A throw new RuntimeException("Key is still valid");
893N/A
893N/A System.out.println("OKAY");
893N/A
893N/A }
893N/A }
893N/A
893N/A /**
893N/A * Asynchronous close of watcher causes blocked threads to wakeup
893N/A */
893N/A static void testWakeup(Path dir) throws IOException {
893N/A System.out.println("-- Wakeup Tests --");
893N/A final WatchService watcher = FileSystems.getDefault().newWatchService();
893N/A Runnable r = new Runnable() {
893N/A public void run() {
893N/A try {
893N/A Thread.sleep(5000);
893N/A System.out.println("close WatchService...");
893N/A watcher.close();
893N/A } catch (InterruptedException x) {
893N/A x.printStackTrace();
893N/A } catch (IOException x) {
893N/A x.printStackTrace();
893N/A }
893N/A }
893N/A };
893N/A
893N/A // start thread to close watch service after delay
893N/A new Thread(r).start();
893N/A
893N/A try {
893N/A System.out.println("take...");
893N/A watcher.take();
893N/A throw new RuntimeException("ClosedWatchServiceException not thrown");
893N/A } catch (InterruptedException x) {
893N/A throw new RuntimeException(x);
893N/A } catch (ClosedWatchServiceException x) {
893N/A System.out.println("ClosedWatchServiceException thrown");
893N/A }
893N/A
893N/A System.out.println("OKAY");
893N/A }
893N/A
893N/A /**
893N/A * Simple test to check exceptions and other cases
893N/A */
893N/A @SuppressWarnings("unchecked")
893N/A static void testExceptions(Path dir) throws IOException {
893N/A System.out.println("-- Exceptions and other simple tests --");
893N/A
893N/A WatchService watcher = FileSystems.getDefault().newWatchService();
893N/A try {
893N/A
893N/A // Poll tests
893N/A
893N/A WatchKey key;
893N/A System.out.println("poll...");
893N/A key = watcher.poll();
893N/A if (key != null)
893N/A throw new RuntimeException("no keys registered");
893N/A
893N/A System.out.println("poll with timeout...");
893N/A try {
893N/A long start = System.currentTimeMillis();
893N/A key = watcher.poll(3000, TimeUnit.MILLISECONDS);
893N/A if (key != null)
893N/A throw new RuntimeException("no keys registered");
893N/A long waited = System.currentTimeMillis() - start;
893N/A if (waited < 2900)
893N/A throw new RuntimeException("poll was too short");
893N/A } catch (InterruptedException x) {
893N/A throw new RuntimeException(x);
893N/A }
893N/A
893N/A // IllegalArgumentException
893N/A System.out.println("IllegalArgumentException tests...");
893N/A try {
893N/A dir.register(watcher, new WatchEvent.Kind<?>[]{ } );
893N/A throw new RuntimeException("IllegalArgumentException not thrown");
893N/A } catch (IllegalArgumentException x) {
893N/A }
893N/A try {
893N/A // OVERFLOW is ignored so this is equivalent to the empty set
893N/A dir.register(watcher, new WatchEvent.Kind<?>[]{ OVERFLOW });
893N/A throw new RuntimeException("IllegalArgumentException not thrown");
893N/A } catch (IllegalArgumentException x) {
893N/A }
893N/A
893N/A // UnsupportedOperationException
893N/A try {
893N/A dir.register(watcher, new WatchEvent.Kind<?>[]{
893N/A new WatchEvent.Kind<Object>() {
893N/A @Override public String name() { return "custom"; }
893N/A @Override public Class<Object> type() { return Object.class; }
893N/A }});
893N/A } catch (UnsupportedOperationException x) {
893N/A }
893N/A try {
893N/A dir.register(watcher,
893N/A new WatchEvent.Kind<?>[]{ ENTRY_CREATE },
893N/A new WatchEvent.Modifier() {
893N/A @Override public String name() { return "custom"; }
893N/A });
893N/A throw new RuntimeException("UnsupportedOperationException not thrown");
893N/A } catch (UnsupportedOperationException x) {
893N/A }
893N/A
893N/A // NullPointerException
893N/A System.out.println("NullPointerException tests...");
893N/A try {
893N/A dir.register(null, new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
893N/A throw new RuntimeException("NullPointerException not thrown");
893N/A } catch (NullPointerException x) {
893N/A }
893N/A try {
893N/A dir.register(watcher, new WatchEvent.Kind<?>[]{ null });
893N/A throw new RuntimeException("NullPointerException not thrown");
893N/A } catch (NullPointerException x) {
893N/A }
893N/A try {
893N/A dir.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_CREATE },
893N/A (WatchEvent.Modifier)null);
893N/A throw new RuntimeException("NullPointerException not thrown");
893N/A } catch (NullPointerException x) {
893N/A }
893N/A } finally {
893N/A watcher.close();
893N/A }
893N/A
893N/A // -- ClosedWatchServiceException --
893N/A
893N/A System.out.println("ClosedWatchServiceException tests...");
893N/A
893N/A try {
893N/A watcher.poll();
893N/A throw new RuntimeException("ClosedWatchServiceException not thrown");
893N/A } catch (ClosedWatchServiceException x) {
893N/A }
893N/A
893N/A // assume that poll throws exception immediately
893N/A long start = System.currentTimeMillis();
893N/A try {
893N/A watcher.poll(10000, TimeUnit.MILLISECONDS);
893N/A throw new RuntimeException("ClosedWatchServiceException not thrown");
893N/A } catch (InterruptedException x) {
893N/A throw new RuntimeException(x);
893N/A } catch (ClosedWatchServiceException x) {
893N/A long waited = System.currentTimeMillis() - start;
893N/A if (waited > 5000)
893N/A throw new RuntimeException("poll was too long");
893N/A }
893N/A
893N/A try {
893N/A watcher.take();
893N/A throw new RuntimeException("ClosedWatchServiceException not thrown");
893N/A } catch (InterruptedException x) {
893N/A throw new RuntimeException(x);
893N/A } catch (ClosedWatchServiceException x) {
893N/A }
893N/A
893N/A try {
893N/A dir.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
893N/A throw new RuntimeException("ClosedWatchServiceException not thrown");
893N/A } catch (ClosedWatchServiceException x) {
893N/A }
893N/A
893N/A System.out.println("OKAY");
893N/A }
893N/A
893N/A /**
893N/A * Test that directory can be registered with more than one watch service
893N/A * and that events don't interfere with each other
893N/A */
893N/A static void testTwoWatchers(Path dir) throws IOException {
893N/A System.out.println("-- Two watchers test --");
893N/A
893N/A FileSystem fs = FileSystems.getDefault();
893N/A WatchService watcher1 = fs.newWatchService();
893N/A WatchService watcher2 = fs.newWatchService();
893N/A try {
893N/A Path name1 = fs.getPath("gus1");
893N/A Path name2 = fs.getPath("gus2");
893N/A
893N/A // create gus1
893N/A Path file1 = dir.resolve(name1);
893N/A System.out.format("create %s\n", file1);
3471N/A Files.createFile(file1);
893N/A
893N/A // register with both watch services (different events)
893N/A System.out.println("register for different events");
893N/A WatchKey key1 = dir.register(watcher1,
893N/A new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
893N/A WatchKey key2 = dir.register(watcher2,
893N/A new WatchEvent.Kind<?>[]{ ENTRY_DELETE });
893N/A
893N/A if (key1 == key2)
893N/A throw new RuntimeException("keys should be different");
893N/A
893N/A // create gus2
893N/A Path file2 = dir.resolve(name2);
893N/A System.out.format("create %s\n", file2);
3471N/A Files.createFile(file2);
893N/A
893N/A // check that key1 got ENTRY_CREATE
893N/A takeExpectedKey(watcher1, key1);
893N/A checkExpectedEvent(key1.pollEvents(),
893N/A StandardWatchEventKind.ENTRY_CREATE, name2);
893N/A
893N/A // check that key2 got zero events
893N/A WatchKey key = watcher2.poll();
893N/A if (key != null)
893N/A throw new RuntimeException("key not expected");
893N/A
893N/A // delete gus1
3471N/A Files.delete(file1);
893N/A
893N/A // check that key2 got ENTRY_DELETE
893N/A takeExpectedKey(watcher2, key2);
893N/A checkExpectedEvent(key2.pollEvents(),
893N/A StandardWatchEventKind.ENTRY_DELETE, name1);
893N/A
893N/A // check that key1 got zero events
893N/A key = watcher1.poll();
893N/A if (key != null)
893N/A throw new RuntimeException("key not expected");
893N/A
893N/A // reset for next test
893N/A key1.reset();
893N/A key2.reset();
893N/A
893N/A // change registration with watcher2 so that they are both
893N/A // registered for the same event
893N/A System.out.println("register for same event");
893N/A key2 = dir.register(watcher2, new WatchEvent.Kind<?>[]{ ENTRY_CREATE });
893N/A
893N/A // create file and key2 should be queued
893N/A System.out.format("create %s\n", file1);
3471N/A Files.createFile(file1);
893N/A takeExpectedKey(watcher2, key2);
893N/A checkExpectedEvent(key2.pollEvents(),
893N/A StandardWatchEventKind.ENTRY_CREATE, name1);
893N/A
893N/A System.out.println("OKAY");
893N/A
893N/A } finally {
893N/A watcher2.close();
893N/A watcher1.close();
893N/A }
893N/A }
893N/A
893N/A public static void main(String[] args) throws IOException {
893N/A Path dir = TestUtil.createTemporaryDirectory();
893N/A try {
893N/A
893N/A testEvents(dir);
893N/A testCancel(dir);
893N/A testAutomaticCancel(dir);
893N/A testWakeup(dir);
893N/A testExceptions(dir);
893N/A testTwoWatchers(dir);
893N/A
893N/A } finally {
893N/A TestUtil.removeAll(dir);
893N/A }
893N/A }
893N/A}