test.name.pachler.jpathwatch.JDK7Test Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jpathwatch Show documentation
Show all versions of jpathwatch Show documentation
jpathwatch is a Java library for monitoring directories for changes. It
uses the host platform's native OS functions to achive this to avoid
polling.
The newest version!
/*
* Copyright 2008-2011 Uwe Pachler
*
* 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 particular file is
* subject to the "Classpath" exception as provided in the LICENSE file
* that accompanied this code.
*
* 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.
*
*/
package name.pachler.jpathwatch;
import java.util.logging.Level;
import java.util.logging.Logger;
import name.pachler.nio.file.WatchEvent;
import name.pachler.nio.file.WatchKey;
import name.pachler.nio.file.WatchService;
import name.pachler.nio.file.StandardWatchEventKind;
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import name.pachler.nio.file.ClosedWatchServiceException;
import name.pachler.nio.file.FileSystems;
import name.pachler.nio.file.Path;
import name.pachler.nio.file.Paths;
import name.pachler.nio.file.ext.Bootstrapper;
import name.pachler.nio.file.ext.ExtendedWatchEventModifier;
import name.pachler.nio.file.impl.PollingPathWatchService;
import org.junit.Assert;
import org.junit.Test;
import static org.junit.Assert.*;
import static name.pachler.nio.file.StandardWatchEventKind.*;
import static name.pachler.nio.file.ext.ExtendedWatchEventKind.*;
public class JDK7Test {
// enable this to test the PollingPathWatchService on platforms that would
// otherwise use their native implementation
/*
static
{
Bootstrapper.setForcePollingEnabled(true);
Bootstrapper.setDefaultPollingInterval(500);
}
*/
static class SingleWatchKeyTaker extends Thread{
WatchService watcher;
WatchKey watchKey;
List> events;
boolean noExceptions = false;
boolean closedException = false;
public SingleWatchKeyTaker(WatchService watcher) {
this.watcher = watcher;
}
public SingleWatchKeyTaker(WatchService watcher, String threadName) {
super(threadName);
this.watcher = watcher;
}
@Override
public void run() {
try {
watchKey = watcher.take();
Assert.assertNotNull(watchKey);
events = watchKey.pollEvents();
Assert.assertTrue(watchKey.reset());
noExceptions = true;
} catch (InterruptedException ex) {
Logger.getLogger(JDK7Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClosedWatchServiceException ex) {
closedException = true;
}
}
}
static File createTempDir(String prefix) throws IOException{
File file = File.createTempFile(prefix, "");
file.deleteOnExit();
File dir = new File(file.getParentFile(), file.getName()+".dir");
dir.mkdir();
dir.deleteOnExit();
return dir;
}
static void appendBytesToFile(File file, byte[] bytes) throws IOException {
FileOutputStream fos = new FileOutputStream(file, true);
fos.write(bytes, 0, bytes.length);
fos.close();
}
boolean listContainsEvent(List> list, WatchEvent.Kind kind, String fileName)
{
Path context = null;
if(fileName !=null)
context = Bootstrapper.newPath(new File(fileName));
for(WatchEvent> key : list){
boolean sameKind = key.kind() == kind;
boolean sameContext = key.context()== null && context==null || key.context().equals(context);
if(sameKind && sameContext)
return true;
}
return false;
}
@Test
public void testTwoTakerThreads() throws IOException, InterruptedException{
// WatchKeys for two distinct directories are created. Two threads
// are created, each calling take() once. In each observed directory,
// a single file is created.
// The expected result is that each thread receives one of the WatchKeys
// as a return value from take().
WatchService w = Bootstrapper.newWatchService();
SingleWatchKeyTaker swkt1 = new SingleWatchKeyTaker(w, "swkt1");
SingleWatchKeyTaker swkt2 = new SingleWatchKeyTaker(w, "swkt2");
File dir1 = createTempDir("dir1");
Path path1 = Bootstrapper.newPath(dir1);
WatchKey wk1 = path1.register(w, StandardWatchEventKind.ENTRY_CREATE);
File dir2 = createTempDir("dir2");
Path path2 = Bootstrapper.newPath(dir2);
WatchKey wk2 = path2.register(w, StandardWatchEventKind.ENTRY_CREATE);
swkt1.start();
swkt2.start();
File file1 = new File(dir1, "file1");
file1.createNewFile();
file1.deleteOnExit();
File file2 = new File(dir2, "file2");
file2.createNewFile();
file2.deleteOnExit();
synchronized(this){
wait(1000); // wait a second to give threads time to process events
}
// because threads each take a single watch key and terminate straight
// after, they should all be dead by now
Assert.assertFalse(swkt1.isAlive());
Assert.assertFalse(swkt2.isAlive());
// put all received watch keys into a set
Set paths = new HashSet();
paths.add(swkt1.watchKey);
paths.add(swkt2.watchKey);
// check that the watch keys the threads received are distinct, and
// that they were the keys that we used
Assert.assertTrue(swkt1.watchKey != swkt2.watchKey);
Assert.assertTrue(paths.contains(wk1));
Assert.assertTrue(paths.contains(wk2));
w.close();
}
@Test
public synchronized void testOneTaker() throws IOException, InterruptedException{
WatchService watcher = Bootstrapper.newWatchService();
File dir = createTempDir("dir1");
Path path = Bootstrapper.newPath(dir);
WatchKey wk = path.register(watcher, StandardWatchEventKind.ENTRY_CREATE);
// wait for 200ms - should return no key
WatchKey key = watcher.poll(200, TimeUnit.MILLISECONDS);
assertNull(key);
File file1 = new File(dir, "file1");
file1.createNewFile();
wait(200);
key = watcher.take();
assertNotNull(key);
List> eventList = key.pollEvents();
assertTrue(eventList.size() == 1);
WatchEvent event = eventList.get(0);
assertEquals(event.context(), Bootstrapper.newPath(new File("file1")));
assertEquals(event.kind(), ENTRY_CREATE);
key.reset();
File file2 = new File(dir, "file2");
file2.createNewFile();
wait(200);
key = watcher.take();
assertNotNull(key);
eventList = key.pollEvents();
assertTrue(eventList.size() == 1);
event = eventList.get(0);
assertEquals(event.context(), Bootstrapper.newPath(new File("file2")));
assertEquals(event.kind(), ENTRY_CREATE);
key.reset();
// test file with single-character file name
File file3 = new File(dir, "3");
file3.createNewFile();
wait(200);
key = watcher.take();
assertNotNull(key);
eventList = key.pollEvents();
assertTrue(eventList.size() == 1);
event = eventList.get(0);
assertEquals(event.context(), Bootstrapper.newPath(new File("3")));
assertEquals(event.kind(), ENTRY_CREATE);
watcher.close();
}
@Test
public synchronized void testOneTakerThreaded() throws IOException, InterruptedException{
// WatchKeys for two distinct directories are created. Two threads
// are created, each calling take() once. In each observed directory,
// a single file is created.
// The expected result is that each thread receives one of the WatchKeys
// as a return value from take().
WatchService watcher = Bootstrapper.newWatchService();
SingleWatchKeyTaker swkt = new SingleWatchKeyTaker(watcher);
File dir = createTempDir("dir1");
Path path = Bootstrapper.newPath(dir);
WatchKey wk = path.register(watcher, StandardWatchEventKind.ENTRY_CREATE);
File file = new File(dir, "file1");
file.createNewFile();
file.deleteOnExit();
WatchKey key = watcher.take();
assertTrue(key != null);
boolean resetSuccessful = key.reset();
assertTrue(resetSuccessful);
swkt.start();
File file2 = new File(dir, "file2");
file2.createNewFile();
file2.deleteOnExit();
wait(200); // wait a second to give threads time to process events
// because threads each take a single watch key and terminate straight
// after, they should all be dead by now
Assert.assertFalse(swkt.isAlive());
// check that the watch keys the threads received are distinct, and
// that they were the keys that we used
Assert.assertTrue(swkt.watchKey == wk);
watcher.close();
}
@Test
public void testPollTimeout() throws IOException, ClosedWatchServiceException, InterruptedException{
// test to check if the polling timeout works properly.
// The timeouts don't need to be exact (they can't be), but
// they should at least be reasonably close (we assume 10% delta here)
// to the specified timeout value.
WatchService watcher = null;
try {
watcher = Bootstrapper.newWatchService();
File dir = createTempDir("testPollTimeout");
Path path = Paths.get(dir.getPath());
WatchKey key = path.register(watcher, ENTRY_CREATE);
long timeout = 2500;
long startTime = System.currentTimeMillis();
watcher.poll(timeout, TimeUnit.MILLISECONDS);
long endTime = System.currentTimeMillis();
long elapsed = endTime - startTime;
assertEquals(timeout, elapsed, timeout*.1);
timeout = 2000;
startTime = System.currentTimeMillis();
watcher.poll(timeout/1000, TimeUnit.SECONDS);
endTime = System.currentTimeMillis();
elapsed = endTime - startTime;
assertEquals(timeout, elapsed, timeout*.1);
} finally {
if(watcher != null)
watcher.close();
}
}
@Test
public synchronized void testOneTakerClosing() throws IOException, InterruptedException{
// test that closing a WatchService makes it raise a
// ClosedWatchServiceException from a take() call
WatchService watcher = Bootstrapper.newWatchService();
SingleWatchKeyTaker swkt = new SingleWatchKeyTaker(watcher);
swkt.start();
// this should make sure that swkt is actually running and waiting in WatchService.take().
wait(200);
watcher.close();
swkt.join(1000);
Assert.assertFalse(swkt.isAlive());
Assert.assertTrue(swkt.closedException);
}
@Test
public synchronized void testTakeFirstThenRegister() throws IOException, InterruptedException{
// Tests the following case:
// * A thread calls take on a WatchService that has no paths registered
// yet. take() will block.
// * Another thread registers a path afterwards, and then creates
// a file in the watched path.
// * The first thread should return a watch key now
WatchService watcher = Bootstrapper.newWatchService();
SingleWatchKeyTaker swkt = new SingleWatchKeyTaker(watcher);
swkt.start();
wait(200); // give the swkt thread time to call take()...
File dir = createTempDir("testTakeFirstThenRegister");
Path path = Bootstrapper.newPath(dir);
WatchKey key = path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
File file = new File(dir, "test");
file.createNewFile();
file.deleteOnExit();
// the take() call in the swkt thread should have returned by now
// and returned the key
long joinTimeout = 1000;
if(watcher instanceof PollingPathWatchService)
joinTimeout = (long)(1.5f * ((PollingPathWatchService)watcher).getPollInterval()); // longer timeout if we have a polling service
swkt.join(joinTimeout);
Assert.assertFalse(swkt.isAlive());
Assert.assertTrue(swkt.watchKey == key);
watcher.close();
}
@Test
public synchronized void testRename() throws IOException, InterruptedException{
// Tests watching a directory within which a file is renamed.
// Only standard event kinds are to be used.
WatchService watcher = Bootstrapper.newWatchService();
File dir = createTempDir("testRename");
Path path = Bootstrapper.newPath(dir);
File file = new File(dir, "test1");
file.createNewFile();
file.deleteOnExit();
WatchKey key1 = path.register(watcher, ENTRY_CREATE, ENTRY_DELETE);
boolean couldRename;
{
File f = new File(dir, "test2");
couldRename = file.renameTo(f);
file = f;
}
assertTrue(couldRename);
wait(200);
SingleWatchKeyTaker swkt1 = new SingleWatchKeyTaker(watcher);
swkt1.start();
swkt1.join(200);
Assert.assertFalse(swkt1.isAlive());
Assert.assertTrue(swkt1.watchKey == key1);
Assert.assertTrue(listContainsEvent(swkt1.events, ENTRY_DELETE, "test1"));
Assert.assertTrue(listContainsEvent(swkt1.events, ENTRY_CREATE, "test2"));
key1.cancel();
boolean platformSupportsRenameEvents =
System.getProperty("os.name").contains("Windows")
|| System.getProperty("os.name").contains("Linux");
if(platformSupportsRenameEvents && !Bootstrapper.isForcePollingEnabled())
{
WatchKey key2 = path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_RENAME_FROM, ENTRY_RENAME_TO);
{
File f = new File(dir, "test3");
couldRename = file.renameTo(f);
file = f;
}
assertTrue(couldRename);
wait(200);
SingleWatchKeyTaker swkt2 = new SingleWatchKeyTaker(watcher);
swkt2.start();
wait(200);
Assert.assertFalse(swkt2.isAlive());
Assert.assertTrue(listContainsEvent(swkt2.events, ENTRY_RENAME_FROM, "test2"));
Assert.assertTrue(listContainsEvent(swkt2.events, ENTRY_RENAME_TO, "test3"));
}
watcher.close();
}
@Test
public void testForeignRename() throws IOException, InterruptedException{
// This test checks if files that are moved into and out of a watched
// directory are correctly recognized as ENTRY_CREATE / ENTRY_DELETE
// (and not as ENTRY_RENAME_TO / ENTRY_RENAME_FROM that don't have a
// corresponding _FROM / _TO event, as in bug #3309509
// (http://sourceforge.net/tracker/?func=detail&aid=3309509&group_id=245450&atid=1419016)
WatchService watcher = Bootstrapper.newWatchService();
File watchedDir = createTempDir("testForeignRename-watched");
Path path = Bootstrapper.newPath(watchedDir);
File unwatchedDir = createTempDir("testForeignRename-not-watched");
File file1 = new File(watchedDir, "test1-watched");
file1.createNewFile();
file1.deleteOnExit();
File file2 = new File(unwatchedDir, "test2-unwatched");
file2.createNewFile();
file2.deleteOnExit();
boolean platformSupportsRenameEvents =
System.getProperty("os.name").contains("Windows")
|| System.getProperty("os.name").contains("Linux");
WatchKey key1;
if(platformSupportsRenameEvents)
key1 = path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_RENAME_FROM, ENTRY_RENAME_TO);
else
key1 = path.register(watcher, ENTRY_CREATE, ENTRY_DELETE);
boolean couldRename;
{
File f = new File(unwatchedDir, "test1-unwatched");
couldRename = file1.renameTo(f);
f.deleteOnExit();
file1 = f;
}
assertTrue(couldRename);
{
File f = new File(watchedDir, "test2-watched");
couldRename = file1.renameTo(f);
f.deleteOnExit();
file2 = f;
}
assertTrue(couldRename);
Thread.sleep(200);
SingleWatchKeyTaker swkt1 = new SingleWatchKeyTaker(watcher);
swkt1.start();
swkt1.join(200);
Assert.assertFalse(swkt1.isAlive());
Assert.assertTrue(swkt1.watchKey == key1);
Assert.assertTrue(listContainsEvent(swkt1.events, ENTRY_DELETE, "test1-watched"));
Assert.assertTrue(listContainsEvent(swkt1.events, ENTRY_CREATE, "test2-watched"));
key1.cancel();
watcher.close();
}
@Test
public void testRecursiveWatch() throws IOException, InterruptedException{
WatchService service = Bootstrapper.newWatchService();
// test non-recursive watch first: make sure that changes
// to files in a child directory are ignored
File dir = createTempDir("watched-dir");
Path path = Bootstrapper.newPath(dir);
File subdir = new File(dir, "subdir");
subdir.mkdir();
WatchKey key1 = path.register(service, StandardWatchEventKind.ENTRY_CREATE);
File file1 = new File(subdir, "file1");
file1.deleteOnExit();
file1.createNewFile();
// the file that has just been created must be ignored.
WatchKey result1 = service.poll(200, TimeUnit.MILLISECONDS);
assertNull(result1);
WatchKey key2;
try {
WatchEvent.Kind[] eventKinds = { StandardWatchEventKind.ENTRY_CREATE };
key2 = path.register(service, eventKinds, ExtendedWatchEventModifier.FILE_TREE);
} catch (UnsupportedOperationException uox){
// on platforms other than Windows, we expect an illegal argument
// exception, because only Windows currently implements the
// FILE_TREE modifier.
if(!System.getProperty("os.name").contains("Windows") || Bootstrapper.isForcePollingEnabled())
return;
throw uox;
}
File file2 = new File(subdir, "file2");
file2.deleteOnExit();
file2.createNewFile();
WatchKey result2 = service.poll(200, TimeUnit.MILLISECONDS);
assertTrue(result2 == key2);
service.close();
}
@Test
public synchronized void testRegister() throws InterruptedException, IOException{
WatchService service = Bootstrapper.newWatchService();
File dir = createTempDir("watched-dir");
Path path = Bootstrapper.newPath(dir);
WatchKey key1 = path.register(service, StandardWatchEventKind.ENTRY_CREATE);
File file = new File(dir, "file");
file.createNewFile();
wait(200);
WatchKey resultKey1 = service.poll(200, TimeUnit.MILLISECONDS);
assertTrue(resultKey1 == key1);
List> list1 = resultKey1.pollEvents();
assertTrue(listContainsEvent(list1, ENTRY_CREATE, "file"));
assertTrue(resultKey1.reset());
WatchKey key2 = path.register(service, ENTRY_CREATE, ENTRY_DELETE);
assertTrue(key1 == key2);
file.delete();
WatchKey resultKey2 = service.poll(200, TimeUnit.MILLISECONDS);
assertTrue(resultKey2 == key2);
List> list2 = resultKey2.pollEvents();
assertTrue(listContainsEvent(list2, ENTRY_DELETE, "file"));
assertTrue(resultKey2.reset());
service.close();
}
@Test
public synchronized void testACCURATE() throws InterruptedException, IOException{
WatchService service = Bootstrapper.newWatchService();
File dir = createTempDir("watched-dir");
Path path = Bootstrapper.newPath(dir);
// ensure that selected platforms support ACCURATE
boolean platformSupportsACCURATE =
System.getProperty("os.name").contains("Windows")
|| System.getProperty("os.name").contains("Linux");
WatchKey key1;
try {
key1 = path.register(service, new WatchEvent.Kind[]{StandardWatchEventKind.ENTRY_CREATE}, ExtendedWatchEventModifier.ACCURATE);
}catch(UnsupportedOperationException uox){
// implementation reports that ACCURATE is not supported,
// so ensure that that's true:
assertFalse(platformSupportsACCURATE);
return;
}
File file = new File(dir, "file");
file.createNewFile();
file.delete();
wait(200);
WatchKey resultKey1 = service.poll(200, TimeUnit.MILLISECONDS);
List> list1 = resultKey1.pollEvents();
assertTrue(resultKey1 == key1);
assertTrue(listContainsEvent(list1, ENTRY_CREATE, "file"));
assertFalse(listContainsEvent(list1, ENTRY_DELETE, "file"));
assertTrue(resultKey1.reset());
service.close();
}
@Test
public synchronized void testReset() throws IOException, InterruptedException{
WatchService service = FileSystems.getDefault().newWatchService();
File dir = createTempDir("testReset");
Path path = Paths.get(dir.toString());
WatchKey key = path.register(service, ENTRY_CREATE);
// this event should now be picked up by the WatchService
File file1 = new File(dir, "file1");
file1.createNewFile();
WatchKey k = service.poll(200, TimeUnit.MILLISECONDS);
assertTrue(k == key);
List> list = k.pollEvents();
assertTrue(listContainsEvent(list, ENTRY_CREATE, "file1"));
// THIS IS THE IMPORTANT PART:
// before we call reset, we wait a wee bit. Then we create another file,
// wait a wee bit more so that the event can be delivered to the key,
// and then call reset. poll() should now return the key immediately
// (because it has events queued up)
wait(200);
File file2 = new File(dir, "file2");
file2.createNewFile();
wait(200);
boolean resetResult = k.reset();
assertTrue(resetResult);
// poll should return the key now
k = service.poll();
assertTrue(k == key);
list = k.pollEvents();
assertTrue(listContainsEvent(list, ENTRY_CREATE, "file2"));
service.close();
}
@Test
public synchronized void testInvalidationByCancel() throws IOException, InterruptedException{
// test for KEY_INVALID events in case the user manually cancels
// the watch key by calling WatchKey.cancel().
WatchService service = FileSystems.getDefault().newWatchService();
File dir = createTempDir("testInvalidationByCancel");
Path path = Paths.get(dir.toString());
WatchKey key = path.register(service, ENTRY_CREATE, KEY_INVALID);
// invalidation by user
key.cancel();
assertFalse(key.isValid());
// Because we're listening for KEY_INVALID events, the key still
// needs to be queued
WatchKey k = service.poll();
assertSame(key, k);
List> events = k.pollEvents();
assertTrue(events.size()==1);
assertTrue(listContainsEvent(events, KEY_INVALID, null));
service.close();
}
@Test
public synchronized void testInvalidationByDelete() throws IOException, InterruptedException{
// test for KEY_INVALID events in case the Path for which they
// key was registered is removed
WatchService service = FileSystems.getDefault().newWatchService();
File dir = createTempDir("testInvalidationByDelete");
Path path = Paths.get(dir.toString());
WatchKey key = path.register(service, ENTRY_CREATE, KEY_INVALID);
// invalidation by deleting the watched path
boolean deleted = dir.delete();
assertTrue(deleted); // if delete fails, we can't test
wait(500); // wait a bit so that the deletion can propagate
// (Windows appears to be specifically slow here...)
// Because we're listening for KEY_INVALID events, the key still
// should still be queued
WatchKey k = service.poll();
assertSame(key, k);
// key should now be invalid
assertFalse(key.isValid());
List> events = k.pollEvents();
assertTrue(events.size()==1);
assertTrue(listContainsEvent(events, KEY_INVALID, null));
service.close();
}
@Test
public synchronized void testMODIFY() throws IOException, InterruptedException{
// test for ENTRY_MODIFY events.
// The test is taylored for kernel event driven WatchServices as well
// as for poll driven ones (like all other tests).
//
// We test two things:
// * changes that affect the file size
// * changes that affect the modtime
// * file creation and modification right after register()
//
// Polling implementations have a couple of challenges to face here:
// Often systems store modtime as seconds from the epoch,
// which means that there can be a case where a write occurs that does
// not change modtime:
// Assume you write to a file, call register() and then write again.
// The first write sets modtime to 12:00:01, but register and the
// second write follow so quickly that they still happen in the same
// second - so the modtime is still 12:00:01. If the file size does
// not change as well, the change is undetectable by a polling
// implementation.
// Another case is when you create a file AFTER calling register and then
// modify it:
// Assume you call register on a directory, then create a file and
// write to it straight after: Creating the file sets it's modtime to
// 10:00:01, and the write happens so quick it's still set to 10:00:01.
// But because we know that the file has been created and therefore its
// initial size can only be 0, if it's different from that we can assume
// it has been written to as well, and therefore expect a modification
// event to be detected by a polling implementation.
WatchService service = FileSystems.getDefault().newWatchService();
File dir = createTempDir("testMODIFY");
Path path = Paths.get(dir.toString());
// first, we create a new file (size: 0 bytes)
File file1 = new File(dir, "file1");
file1.createNewFile();
// then, register() the key. Polling implementations will take a
// snapshot here, non-pollers will receive modification events
// hereafter - so we can expect modifications to be detected that happen
// after calling register().
WatchKey key = path.register(service, ENTRY_MODIFY);
// modify file - here: write one byte to it.
FileOutputStream fos = new FileOutputStream(file1);
fos.write(1);
fos.close();
wait(100); // wait a bit here, as for event driven WatchService
// implementations it might take a bit for the event to propagate
// through the kernel (100ms is very generous here)
// get key with events
WatchKey k = service.poll();
// we expect an event to be reported by poll().
assertNotNull(k);
List> elist = k.pollEvents();
assertTrue(listContainsEvent(elist, ENTRY_MODIFY, "file1"));
k.reset();
// wait more than a second here, to allow for the modtime to be
// different when writing to the file again (for pollers)
wait(1100);
// write one byte to the file; this will not change the file size, but
// should change the modification date, so pollers can pick it up too.
fos = new FileOutputStream(file1);
fos.write(1);
fos.close();
// wait a bit for event driven WatchService implementations
// to allow events trickling through the kernel
k = service.poll(100, TimeUnit.MILLISECONDS);
// again, we expect an event to be reported by poll().
assertNotNull(k);
elist = k.pollEvents();
assertTrue(listContainsEvent(elist, ENTRY_MODIFY, "file1"));
k.reset();
// now create an entirely new file and write to it straight away.
// pollers should pick this up too.
File file2 = new File(dir, "file2");
file2.createNewFile();
fos = new FileOutputStream(file2);
fos.write(1);
fos.close();
// wait a bit for event driven WatchService implementations
// to allow events trickling through the kernel
k = service.poll(100, TimeUnit.MILLISECONDS);
// we expect this modification to be picked up too. Pollers need to
// take special care here, because the creation event may not shadow
// the modification that has taken place too.
assertNotNull(k);
elist = k.pollEvents();
assertTrue(listContainsEvent(elist, ENTRY_MODIFY, "file2"));
k.reset();
// try again with writing to the file, this time reading from the
// service with take()
fos = new FileOutputStream(file2);
fos.write(new byte[]{1,3,4});
fos.close();
k = service.take();
assertNotNull(k);
elist = k.pollEvents();
assertTrue(listContainsEvent(elist, ENTRY_MODIFY, "file2"));
k.reset();
service.close();
}
@Test(timeout=15000)
public synchronized void testManyDirectories() throws IOException, InterruptedException{
// this is a basic test which attempts to create a large number of
// monitored directories. In each directory, a file is created, and
// the tests ensures that this creation event is picked up by all
// registered watch keys.
// Note that the main reason to implement this test is to make sure
// that the Windows implementation can handle more than 63 directories
// (which is a limit imposed by the WaitForMultipleObjects() win32
// kernel function). The Windows implementation must find a way around
// this limit.
// Note that there will be limits like this on every platform; we won't
// test for them here at this stage.
int numDirectories = 200;
File parent = createTempDir("testManyDirectories");
WatchService ws = FileSystems.getDefault().newWatchService();
Map createdFiles = new HashMap();
for(int n=0; n> elist = k.pollEvents();
assert(listContainsEvent(elist, ENTRY_CREATE, "file"));
assert(createdFiles.containsKey(k));
createdFiles.remove(k);
k = ws.poll();
}
assert(createdFiles.isEmpty());
// shut down
ws.close();
for(int n=0; n files = new ArrayList(numFiles);
try{
currentThread.setPriority(Thread.MAX_PRIORITY);
for(int i=0; i> list = resultKey.pollEvents();
numEvents += list.size();
if(!overflowDetected)
overflowDetected = listContainsEvent(list, OVERFLOW, null);
resultKey.reset();
}
}while(!overflowDetected && resultKey != null);
assertTrue(overflowDetected);
} finally {
// reset priority
currentThread.setPriority(initialPriority);
// clean up files
for(File f : files)
f.delete();
}
}
@Test
public void testCancel() throws IOException, InterruptedException{
// NOTE: this test case was written specifically with the BSDPathWatchService
// in mind, which is why it might do things that aren't too straight-forward.
// However, it must hold for all platforms.
// WatchKey.cancel() is supposed to invalidate the key. Therefore,
// the following conditions must hold:
// * (1)prior to calling WatchKey.cancel()
// - (1.1)WatchKey.isValid()==true
// - (1.2)a second call to Path.register() for the same path should
// return the same key
// * (2)after calling to calling WatchKey.cancel()
// - (2.1)WatchKey.isValid()==false
// - (2.2)a second call to Path.register() for the same path returns a
// DIFFERENT key
// Note that these conditions must also hold if there are other keys
// registered
File parent = createTempDir("testCancel");
File modifiedFile = new File(parent, "modifiedFile");
//NOTE: instead of using the line below (calling File.createNewFile),
// we use a new FileOutputStream that we immediately close to create
// the file. The Reason: When debugging, File.createNewFile() apparently
// didn't create the file, even though it claimed it did. JDK bug?
// The whole episode only seems to happen in debug..
//
//assert(modifiedFile.createNewFile());
new FileOutputStream(modifiedFile).close();
assert(modifiedFile.exists());
File otherWatchedDir = createTempDir("testCancel_background");
WatchService ws = FileSystems.getDefault().newWatchService();
Path p = Paths.get(parent.getAbsolutePath());
// register background key, which is only there so that the watch service
// doesn't run completely empty if we cancel the main key we use for
// testing. Otherwise, we ignore the key (this is why we don't store it)
Paths.get(otherWatchedDir.getAbsolutePath()).register(ws, ENTRY_CREATE, ENTRY_MODIFY);
WatchKey k1 = p.register(ws, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
// check for (1.1)assert
assert(k1.isValid());
{
Path p2 = Paths.get(parent.getAbsolutePath());
WatchKey k0 = p2.register(ws, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
assert(k0 == k1); // check for (1.2)
}
appendBytesToFile(modifiedFile, new byte[1]);
WatchKey k = ws.poll(200, TimeUnit.MILLISECONDS);
assert(k == k1);
// poll events and discard them
List> events = k.pollEvents();
assertTrue(events.size()==1);
assertTrue(listContainsEvent(events, ENTRY_MODIFY, modifiedFile.getName()));
k.reset();
// CANCELLING KEY
k.cancel();
// check for (2.1)
assert(!k.isValid());
appendBytesToFile(modifiedFile, new byte[1]);
k = ws.poll(200, TimeUnit.MILLISECONDS);
assert(k == null);
// check for (2.2)
WatchKey k2 = p.register(ws, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
assert(k1 != k2);
appendBytesToFile(modifiedFile, new byte[1]);
k = ws.poll(200, TimeUnit.MILLISECONDS);
assert(k == k2);
k.reset();
ws.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy