Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/nio/file/WatchService/LotsOfEvents.java
38828 views
/*1* Copyright (c) 2010, 2011, 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 6907760 692953225* @summary Tests WatchService behavior when lots of events are pending26* @library ..27* @run main/timeout=180 LotsOfEvents28* @key randomness29*/3031import java.nio.file.*;32import static java.nio.file.StandardWatchEventKinds.*;33import java.io.IOException;34import java.io.OutputStream;35import java.util.*;36import java.util.concurrent.TimeUnit;3738public class LotsOfEvents {3940static final Random rand = new Random();4142public static void main(String[] args) throws Exception {43Path dir = TestUtil.createTemporaryDirectory();44try {45testOverflowEvent(dir);46testModifyEventsQueuing(dir);47} finally {48TestUtil.removeAll(dir);49}50}5152/**53* Tests that OVERFLOW events are not retreived with other events.54*/55static void testOverflowEvent(Path dir)56throws IOException, InterruptedException57{58try (WatchService watcher = dir.getFileSystem().newWatchService()) {59dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE);6061// create a lot of files62int n = 1024;63Path[] files = new Path[n];64for (int i=0; i<n; i++) {65files[i] = Files.createFile(dir.resolve("foo" + i));66}6768// give time for events to accumulate (improve chance of overflow)69Thread.sleep(1000);7071// check that we see the create events (or overflow)72drainAndCheckOverflowEvents(watcher, ENTRY_CREATE, n);7374// delete the files75for (int i=0; i<n; i++) {76Files.delete(files[i]);77}7879// give time for events to accumulate (improve chance of overflow)80Thread.sleep(1000);8182// check that we see the delete events (or overflow)83drainAndCheckOverflowEvents(watcher, ENTRY_DELETE, n);84}85}8687static void drainAndCheckOverflowEvents(WatchService watcher,88WatchEvent.Kind<?> expectedKind,89int count)90throws IOException, InterruptedException91{92// wait for key to be signalled - the timeout is long to allow for93// polling implementations94WatchKey key = watcher.poll(15, TimeUnit.SECONDS);95if (key != null && count == 0)96throw new RuntimeException("Key was signalled (unexpected)");97if (key == null && count > 0)98throw new RuntimeException("Key not signalled (unexpected)");99100int nread = 0;101boolean gotOverflow = false;102while (key != null) {103List<WatchEvent<?>> events = key.pollEvents();104for (WatchEvent<?> event: events) {105WatchEvent.Kind<?> kind = event.kind();106if (kind == expectedKind) {107// expected event kind108if (++nread > count)109throw new RuntimeException("More events than expected!!");110} else if (kind == OVERFLOW) {111// overflow event should not be retrieved with other events112if (events.size() > 1)113throw new RuntimeException("Overflow retrieved with other events");114gotOverflow = true;115} else {116throw new RuntimeException("Unexpected event '" + kind + "'");117}118}119if (!key.reset())120throw new RuntimeException("Key is no longer valid");121key = watcher.poll(2, TimeUnit.SECONDS);122}123124// check that all expected events were received or there was an overflow125if (nread < count && !gotOverflow)126throw new RuntimeException("Insufficient events");127}128129/**130* Tests that check that ENTRY_MODIFY events are queued efficiently131*/132static void testModifyEventsQueuing(Path dir)133throws IOException, InterruptedException134{135// this test uses a random number of files136final int nfiles = 5 + rand.nextInt(10);137DirectoryEntry[] entries = new DirectoryEntry[nfiles];138for (int i=0; i<nfiles; i++) {139entries[i] = new DirectoryEntry(dir.resolve("foo" + i));140141// "some" of the files exist, some do not.142entries[i].deleteIfExists();143if (rand.nextBoolean())144entries[i].create();145}146147try (WatchService watcher = dir.getFileSystem().newWatchService()) {148dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);149150// do several rounds of noise and test151for (int round=0; round<10; round++) {152153// make some noise!!!154for (int i=0; i<100; i++) {155DirectoryEntry entry = entries[rand.nextInt(nfiles)];156int action = rand.nextInt(10);157switch (action) {158case 0 : entry.create(); break;159case 1 : entry.deleteIfExists(); break;160default: entry.modifyIfExists();161}162}163164// process events and ensure that we don't get repeated modify165// events for the same file.166WatchKey key = watcher.poll(15, TimeUnit.SECONDS);167while (key != null) {168Set<Path> modified = new HashSet<>();169for (WatchEvent<?> event: key.pollEvents()) {170WatchEvent.Kind<?> kind = event.kind();171Path file = (kind == OVERFLOW) ? null : (Path)event.context();172if (kind == ENTRY_MODIFY) {173boolean added = modified.add(file);174if (!added) {175throw new RuntimeException(176"ENTRY_MODIFY events not queued efficiently");177}178} else {179if (file != null) modified.remove(file);180}181}182if (!key.reset())183throw new RuntimeException("Key is no longer valid");184key = watcher.poll(2, TimeUnit.SECONDS);185}186}187}188}189190static class DirectoryEntry {191private final Path file;192DirectoryEntry(Path file) {193this.file = file;194}195void create() throws IOException {196if (Files.notExists(file))197Files.createFile(file);198199}200void deleteIfExists() throws IOException {201Files.deleteIfExists(file);202}203void modifyIfExists() throws IOException {204if (Files.exists(file)) {205try (OutputStream out = Files.newOutputStream(file, StandardOpenOption.APPEND)) {206out.write("message".getBytes());207}208}209}210}211212}213214215