package org.geotoolkit.nio; import org.junit.After; import org.junit.Assume; import org.junit.Before; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; /** * Initialisation for the tests over {@link DirectoryWatcher} component, which is an use of {@link java.nio.file.WatchService} API * for recursive file-system change survey. See {@link DirectWatchTest} and {@link RecursiveWatchTest} * for the real test cases. * * @author Alexis Manin (Geomatys) */ public class DirectoryWatcherTest { protected static final String ROOT_PREFIX = "DirectoryWatcherTest"; protected DirectoryWatcher watcher; protected Path rootDir; protected final ArrayList<PathChangedEvent> results = new ArrayList<>(); public DirectoryWatcherTest() { Assume.assumeTrue(System.getProperty("os.name").toLowerCase().contains("linux")); } @Before public void initTestDirectory() throws IOException { rootDir = Files.createTempDirectory(ROOT_PREFIX); } @After public void deleteTestDirectory() throws IOException { // Recursively delete all content of test root. Files.walkFileTree(rootDir, new SimpleFileVisitor<Path>() { @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Files.delete(dir); return super.postVisitDirectory(dir, exc); } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); return super.visitFile(file, attrs); } }); } /** * Create a directory (its parent must exist) and check the event propagation. * @param toCreate The path to create a folder from. * @throws IOException If a problem happened at directory creation * @throws InterruptedException If we cannot wait for event propagation. */ public void assertDirectoryCreated(Path toCreate) throws IOException, InterruptedException { synchronized (results) { Files.createDirectory(toCreate); results.wait(); } assertFalse("Event stack should not be empty", results.isEmpty()); assertEquals("Event path should denote the created folder.", toCreate, results.get(0).target); assertEquals("Event type should be \"entry created\"", StandardWatchEventKinds.ENTRY_CREATE, results.get(0).kind); results.clear(); } /** * Delete a directory (it must be empty) and check the event propagation. * @param toDelete The folder to remove. * @throws IOException If a problem happened at directory deletion * @throws InterruptedException If we cannot wait for event propagation. */ public void assertDirectoryDeleted(Path toDelete) throws IOException, InterruptedException { synchronized (results) { Files.delete(toDelete); results.wait(); } assertFalse("Event stack should not be empty", results.isEmpty()); assertEquals("Event path should denote the deleted folder.", toDelete, results.get(0).target); assertEquals("Event type should be \"entry deleted\"", StandardWatchEventKinds.ENTRY_DELETE, results.get(0).kind); results.clear(); } /** * Create a file (its parent must exist) and check the event propagation. * @param toCreate The path to create a file from. * @throws IOException If a problem happened at file creation * @throws InterruptedException If we cannot wait for event propagation. */ public void assertFileCreated(Path toCreate) throws IOException, InterruptedException { synchronized (results) { Files.createFile(toCreate); results.wait(); } assertFalse("Event stack should not be empty", results.isEmpty()); assertEquals("Event path should denote the created file.", toCreate, results.get(0).target); assertEquals("Event type should be \"entry created\"", StandardWatchEventKinds.ENTRY_CREATE, results.get(0).kind); results.clear(); } /** * Delete a file and check the event propagation. * @param toDelete The file to remove. * @throws IOException If a problem happened at file deletion * @throws InterruptedException If we cannot wait for event propagation. */ public void assertFileDeleted(Path toDelete) throws IOException, InterruptedException { synchronized (results) { Files.delete(toDelete); results.wait(); } assertFalse("Event stack should not be empty", results.isEmpty()); assertEquals("Event path should denote the deleted file.", toDelete, results.get(0).target); assertEquals("Event type should be \"entry deleted\"", StandardWatchEventKinds.ENTRY_DELETE, results.get(0).kind); results.clear(); } protected static class MockListener implements PathChangeListener { final ArrayList<PathChangedEvent> events; public MockListener(final ArrayList<PathChangedEvent> list) { events = list; } @Override public void pathChanged(PathChangedEvent event) { synchronized(events) { events.add(event); events.notify(); } } } }