/* * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ /* @test * @bug 6907760 6929532 * @summary Tests WatchService behavior when lots of events are pending * @library .. * @run main/timeout=180 LotsOfEvents */ import java.nio.file.*; import static java.nio.file.StandardWatchEventKind.*; import java.io.IOException; import java.io.OutputStream; import java.util.*; import java.util.concurrent.TimeUnit; public class LotsOfEvents { static final Random rand = new Random(); public static void main(String[] args) throws Exception { Path dir = TestUtil.createTemporaryDirectory(); try { testOverflowEvent(dir); testModifyEventsQueuing(dir); } finally { TestUtil.removeAll(dir); } } /** * Tests that OVERFLOW events are not retreived with other events. */ static void testOverflowEvent(Path dir) throws IOException, InterruptedException { WatchService watcher = dir.getFileSystem().newWatchService(); try { dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE); // create a lot of files int n = 1024; Path[] files = new Path[n]; for (int i=0; i expectedKind, int count) throws IOException, InterruptedException { // wait for key to be signalled - the timeout is long to allow for // polling implementations WatchKey key = watcher.poll(15, TimeUnit.SECONDS); if (key != null && count == 0) throw new RuntimeException("Key was signalled (unexpected)"); if (key == null && count > 0) throw new RuntimeException("Key not signalled (unexpected)"); int nread = 0; boolean gotOverflow = false; while (key != null) { List> events = key.pollEvents(); for (WatchEvent event: events) { WatchEvent.Kind kind = event.kind(); if (kind == expectedKind) { // expected event kind if (++nread > count) throw new RuntimeException("More events than expected!!"); } else if (kind == OVERFLOW) { // overflow event should not be retrieved with other events if (events.size() > 1) throw new RuntimeException("Overflow retrieved with other events"); gotOverflow = true; } else { throw new RuntimeException("Unexpected event '" + kind + "'"); } } if (!key.reset()) throw new RuntimeException("Key is no longer valid"); key = watcher.poll(2, TimeUnit.SECONDS); } // check that all expected events were received or there was an overflow if (nread < count && !gotOverflow) throw new RuntimeException("Insufficient events"); } /** * Tests that check that ENTRY_MODIFY events are queued efficiently */ static void testModifyEventsQueuing(Path dir) throws IOException, InterruptedException { // this test uses a random number of files final int nfiles = 5 + rand.nextInt(10); DirectoryEntry[] entries = new DirectoryEntry[nfiles]; for (int i=0; i modified = new HashSet(); for (WatchEvent event: key.pollEvents()) { WatchEvent.Kind kind = event.kind(); Path file = (kind == OVERFLOW) ? null : (Path)event.context(); if (kind == ENTRY_MODIFY) { boolean added = modified.add(file); if (!added) { throw new RuntimeException( "ENTRY_MODIFY events not queued efficiently"); } } else { if (file != null) modified.remove(file); } } if (!key.reset()) throw new RuntimeException("Key is no longer valid"); key = watcher.poll(2, TimeUnit.SECONDS); } } } finally { watcher.close(); } } static class DirectoryEntry { private final Path file; DirectoryEntry(Path file) { this.file = file; } void create() throws IOException { if (file.notExists()) file.createFile(); } void deleteIfExists() throws IOException { file.deleteIfExists(); } void modifyIfExists() throws IOException { if (file.exists()) { OutputStream out = file.newOutputStream(StandardOpenOption.APPEND); try { out.write("message".getBytes()); } finally { out.close(); } } } } }