Path: blob/master/test/jdk/java/nio/file/WatchService/Basic.java
41153 views
/*1* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24* @bug 4313887 6838333 7017446 8011537 804247025* @summary Unit test for java.nio.file.WatchService26* @library ..27* @run main Basic28*/2930import java.nio.file.*;31import static java.nio.file.StandardWatchEventKinds.*;32import java.nio.file.attribute.*;33import java.io.*;34import java.util.*;35import java.util.concurrent.TimeUnit;3637/**38* Unit test for WatchService that exercises all methods in various scenarios.39*/4041public class Basic {4243static void checkKey(WatchKey key, Path dir) {44if (!key.isValid())45throw new RuntimeException("Key is not valid");46if (key.watchable() != dir)47throw new RuntimeException("Unexpected watchable");48}4950static void takeExpectedKey(WatchService watcher, WatchKey expected) {51System.out.println("take events...");52WatchKey key;53try {54key = watcher.take();55} catch (InterruptedException x) {56// not expected57throw new RuntimeException(x);58}59if (key != expected)60throw new RuntimeException("removed unexpected key");61}6263static void checkExpectedEvent(Iterable<WatchEvent<?>> events,64WatchEvent.Kind<?> expectedKind,65Object expectedContext)66{67WatchEvent<?> event = events.iterator().next();68System.out.format("got event: type=%s, count=%d, context=%s\n",69event.kind(), event.count(), event.context());70if (event.kind() != expectedKind)71throw new RuntimeException("unexpected event");72if (!expectedContext.equals(event.context()))73throw new RuntimeException("unexpected context");74}7576/**77* Simple test of each of the standard events78*/79static void testEvents(Path dir) throws IOException {80System.out.println("-- Standard Events --");8182FileSystem fs = FileSystems.getDefault();83Path name = fs.getPath("foo");8485try (WatchService watcher = fs.newWatchService()) {86// --- ENTRY_CREATE ---8788// register for event89System.out.format("register %s for ENTRY_CREATE\n", dir);90WatchKey myKey = dir.register(watcher,91new WatchEvent.Kind<?>[]{ ENTRY_CREATE });92checkKey(myKey, dir);9394// create file95Path file = dir.resolve("foo");96System.out.format("create %s\n", file);97Files.createFile(file);9899// remove key and check that we got the ENTRY_CREATE event100takeExpectedKey(watcher, myKey);101checkExpectedEvent(myKey.pollEvents(),102StandardWatchEventKinds.ENTRY_CREATE, name);103104System.out.println("reset key");105if (!myKey.reset())106throw new RuntimeException("key has been cancalled");107108System.out.println("OKAY");109110// --- ENTRY_DELETE ---111112System.out.format("register %s for ENTRY_DELETE\n", dir);113WatchKey deleteKey = dir.register(watcher,114new WatchEvent.Kind<?>[]{ ENTRY_DELETE });115if (deleteKey != myKey)116throw new RuntimeException("register did not return existing key");117checkKey(deleteKey, dir);118119System.out.format("delete %s\n", file);120Files.delete(file);121takeExpectedKey(watcher, myKey);122checkExpectedEvent(myKey.pollEvents(),123StandardWatchEventKinds.ENTRY_DELETE, name);124125System.out.println("reset key");126if (!myKey.reset())127throw new RuntimeException("key has been cancalled");128129System.out.println("OKAY");130131// create the file for the next test132Files.createFile(file);133134// --- ENTRY_MODIFY ---135136System.out.format("register %s for ENTRY_MODIFY\n", dir);137WatchKey newKey = dir.register(watcher,138new WatchEvent.Kind<?>[]{ ENTRY_MODIFY });139if (newKey != myKey)140throw new RuntimeException("register did not return existing key");141checkKey(newKey, dir);142143System.out.format("update: %s\n", file);144try (OutputStream out = Files.newOutputStream(file, StandardOpenOption.APPEND)) {145out.write("I am a small file".getBytes("UTF-8"));146}147148// remove key and check that we got the ENTRY_MODIFY event149takeExpectedKey(watcher, myKey);150checkExpectedEvent(myKey.pollEvents(),151StandardWatchEventKinds.ENTRY_MODIFY, name);152System.out.println("OKAY");153154// done155Files.delete(file);156}157}158159/**160* Check that a cancelled key will never be queued161*/162static void testCancel(Path dir) throws IOException {163System.out.println("-- Cancel --");164165try (WatchService watcher = FileSystems.getDefault().newWatchService()) {166167System.out.format("register %s for events\n", dir);168WatchKey myKey = dir.register(watcher,169new WatchEvent.Kind<?>[]{ ENTRY_CREATE });170checkKey(myKey, dir);171172System.out.println("cancel key");173myKey.cancel();174175// create a file in the directory176Path file = dir.resolve("mars");177System.out.format("create: %s\n", file);178Files.createFile(file);179180// poll for keys - there will be none181System.out.println("poll...");182try {183WatchKey key = watcher.poll(3000, TimeUnit.MILLISECONDS);184if (key != null)185throw new RuntimeException("key should not be queued");186} catch (InterruptedException x) {187throw new RuntimeException(x);188}189190// done191Files.delete(file);192193System.out.println("OKAY");194}195}196197/**198* Check that deleting a registered directory causes the key to be199* cancelled and queued.200*/201static void testAutomaticCancel(Path dir) throws IOException {202System.out.println("-- Automatic Cancel --");203204Path subdir = Files.createDirectory(dir.resolve("bar"));205206try (WatchService watcher = FileSystems.getDefault().newWatchService()) {207208System.out.format("register %s for events\n", subdir);209WatchKey myKey = subdir.register(watcher,210new WatchEvent.Kind<?>[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY });211212System.out.format("delete: %s\n", subdir);213Files.delete(subdir);214takeExpectedKey(watcher, myKey);215216System.out.println("reset key");217if (myKey.reset())218throw new RuntimeException("Key was not cancelled");219if (myKey.isValid())220throw new RuntimeException("Key is still valid");221222System.out.println("OKAY");223224}225}226227/**228* Asynchronous close of watcher causes blocked threads to wakeup229*/230static void testWakeup(Path dir) throws IOException {231System.out.println("-- Wakeup Tests --");232final WatchService watcher = FileSystems.getDefault().newWatchService();233Runnable r = new Runnable() {234public void run() {235try {236Thread.sleep(5000);237System.out.println("close WatchService...");238watcher.close();239} catch (InterruptedException x) {240x.printStackTrace();241} catch (IOException x) {242x.printStackTrace();243}244}245};246247// start thread to close watch service after delay248new Thread(r).start();249250try {251System.out.println("take...");252watcher.take();253throw new RuntimeException("ClosedWatchServiceException not thrown");254} catch (InterruptedException x) {255throw new RuntimeException(x);256} catch (ClosedWatchServiceException x) {257System.out.println("ClosedWatchServiceException thrown");258}259260System.out.println("OKAY");261}262263/**264* Simple test to check exceptions and other cases265*/266@SuppressWarnings("unchecked")267static void testExceptions(Path dir) throws IOException {268System.out.println("-- Exceptions and other simple tests --");269270WatchService watcher = FileSystems.getDefault().newWatchService();271try {272273// Poll tests274275WatchKey key;276System.out.println("poll...");277key = watcher.poll();278if (key != null)279throw new RuntimeException("no keys registered");280281System.out.println("poll with timeout...");282try {283long start = System.nanoTime();284key = watcher.poll(3000, TimeUnit.MILLISECONDS);285if (key != null)286throw new RuntimeException("no keys registered");287long waited = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);288if (waited < 2900)289throw new RuntimeException("poll was too short");290} catch (InterruptedException x) {291throw new RuntimeException(x);292}293294// IllegalArgumentException295System.out.println("IllegalArgumentException tests...");296try {297dir.register(watcher /*empty event list*/);298throw new RuntimeException("IllegalArgumentException not thrown");299} catch (IllegalArgumentException x) {300}301try {302// OVERFLOW is ignored so this is equivalent to the empty set303dir.register(watcher, OVERFLOW);304throw new RuntimeException("IllegalArgumentException not thrown");305} catch (IllegalArgumentException x) {306}307try {308// OVERFLOW is ignored even if specified multiple times309dir.register(watcher, OVERFLOW, OVERFLOW);310throw new RuntimeException("IllegalArgumentException not thrown");311} catch (IllegalArgumentException x) {312}313314// UnsupportedOperationException315try {316dir.register(watcher,317new WatchEvent.Kind<Object>() {318@Override public String name() { return "custom"; }319@Override public Class<Object> type() { return Object.class; }320});321throw new RuntimeException("UnsupportedOperationException not thrown");322} catch (UnsupportedOperationException x) {323}324try {325dir.register(watcher,326new WatchEvent.Kind<?>[]{ ENTRY_CREATE },327new WatchEvent.Modifier() {328@Override public String name() { return "custom"; }329});330throw new RuntimeException("UnsupportedOperationException not thrown");331} catch (UnsupportedOperationException x) {332}333334// NullPointerException335System.out.println("NullPointerException tests...");336try {337dir.register(null, ENTRY_CREATE);338throw new RuntimeException("NullPointerException not thrown");339} catch (NullPointerException x) {340}341try {342dir.register(watcher, new WatchEvent.Kind<?>[]{ null });343throw new RuntimeException("NullPointerException not thrown");344} catch (NullPointerException x) {345}346try {347dir.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_CREATE },348(WatchEvent.Modifier)null);349throw new RuntimeException("NullPointerException not thrown");350} catch (NullPointerException x) {351}352} finally {353watcher.close();354}355356// -- ClosedWatchServiceException --357358System.out.println("ClosedWatchServiceException tests...");359360try {361watcher.poll();362throw new RuntimeException("ClosedWatchServiceException not thrown");363} catch (ClosedWatchServiceException x) {364}365366// assume that poll throws exception immediately367long start = System.nanoTime();368try {369watcher.poll(10000, TimeUnit.MILLISECONDS);370throw new RuntimeException("ClosedWatchServiceException not thrown");371} catch (InterruptedException x) {372throw new RuntimeException(x);373} catch (ClosedWatchServiceException x) {374long waited = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);375if (waited > 5000)376throw new RuntimeException("poll was too long");377}378379try {380watcher.take();381throw new RuntimeException("ClosedWatchServiceException not thrown");382} catch (InterruptedException x) {383throw new RuntimeException(x);384} catch (ClosedWatchServiceException x) {385}386387try {388dir.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_CREATE });389throw new RuntimeException("ClosedWatchServiceException not thrown");390} catch (ClosedWatchServiceException x) {391}392393System.out.println("OKAY");394}395396/**397* Test that directory can be registered with more than one watch service398* and that events don't interfere with each other399*/400static void testTwoWatchers(Path dir) throws IOException {401System.out.println("-- Two watchers test --");402403FileSystem fs = FileSystems.getDefault();404WatchService watcher1 = fs.newWatchService();405WatchService watcher2 = fs.newWatchService();406try {407Path name1 = fs.getPath("gus1");408Path name2 = fs.getPath("gus2");409410// create gus1411Path file1 = dir.resolve(name1);412System.out.format("create %s\n", file1);413Files.createFile(file1);414415// register with both watch services (different events)416System.out.println("register for different events");417WatchKey key1 = dir.register(watcher1,418new WatchEvent.Kind<?>[]{ ENTRY_CREATE });419WatchKey key2 = dir.register(watcher2,420new WatchEvent.Kind<?>[]{ ENTRY_DELETE });421422if (key1 == key2)423throw new RuntimeException("keys should be different");424425// create gus2426Path file2 = dir.resolve(name2);427System.out.format("create %s\n", file2);428Files.createFile(file2);429430// check that key1 got ENTRY_CREATE431takeExpectedKey(watcher1, key1);432checkExpectedEvent(key1.pollEvents(),433StandardWatchEventKinds.ENTRY_CREATE, name2);434435// check that key2 got zero events436WatchKey key = watcher2.poll();437if (key != null)438throw new RuntimeException("key not expected");439440// delete gus1441Files.delete(file1);442443// check that key2 got ENTRY_DELETE444takeExpectedKey(watcher2, key2);445checkExpectedEvent(key2.pollEvents(),446StandardWatchEventKinds.ENTRY_DELETE, name1);447448// check that key1 got zero events449key = watcher1.poll();450if (key != null)451throw new RuntimeException("key not expected");452453// reset for next test454key1.reset();455key2.reset();456457// change registration with watcher2 so that they are both458// registered for the same event459System.out.println("register for same event");460key2 = dir.register(watcher2, new WatchEvent.Kind<?>[]{ ENTRY_CREATE });461462// create file and key2 should be queued463System.out.format("create %s\n", file1);464Files.createFile(file1);465takeExpectedKey(watcher2, key2);466checkExpectedEvent(key2.pollEvents(),467StandardWatchEventKinds.ENTRY_CREATE, name1);468469System.out.println("OKAY");470471} finally {472watcher2.close();473watcher1.close();474}475}476477/**478* Test that thread interruped status is preserved upon a call479* to register()480*/481static void testThreadInterrupt(Path dir) throws IOException {482System.out.println("-- Thread interrupted status test --");483484FileSystem fs = FileSystems.getDefault();485Thread curr = Thread.currentThread();486try (WatchService watcher = fs.newWatchService()) {487System.out.println("interrupting current thread");488curr.interrupt();489dir.register(watcher, ENTRY_CREATE);490if (!curr.isInterrupted())491throw new RuntimeException("thread should remain interrupted");492System.out.println("current thread is still interrupted");493System.out.println("OKAY");494} finally {495curr.interrupted();496}497}498499public static void main(String[] args) throws IOException {500Path dir = TestUtil.createTemporaryDirectory();501try {502503testEvents(dir);504testCancel(dir);505testAutomaticCancel(dir);506testWakeup(dir);507testExceptions(dir);508testTwoWatchers(dir);509testThreadInterrupt(dir);510511} finally {512TestUtil.removeAll(dir);513}514}515}516517518