package org.peerbox.watchservice; import java.io.File; import java.io.FileWriter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.io.FileUtils; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.peerbox.app.manager.file.IFileManager; import org.peerbox.testutils.WatchServiceTestHelpers; import org.peerbox.watchservice.filetree.FileTree; import org.peerbox.watchservice.integration.TestPeerWaspConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class NativeFolderWatchServiceTest { private static final Logger logger = LoggerFactory.getLogger(NativeFolderWatchServiceTest.class); private FolderWatchService watchService; private FileEventManager eventManager; private ActionExecutor actionExecutor; private FileTree fileTree; @Mock private IFileManager fileManager; private static Path basePath; private static final int NUM_CHARS_SMALL_FILE = 50*1024; private static final int NUM_CHARS_BIG_FILE = 50*1024*1024; // private static final int SLEEP_TIME = 4000; @BeforeClass public static void setup() throws Exception { basePath = Paths.get(FileUtils.getTempDirectoryPath(), "PeerWasp_FolderWatchServiceTest"); basePath.toFile().mkdir(); logger.info("Path: {}", basePath); } @AfterClass public static void teardown() { } @Before public void initialization() throws Exception { FileUtils.cleanDirectory(basePath.toFile()); MockitoAnnotations.initMocks(this); watchService = new FolderWatchService(); fileTree = new FileTree(basePath, true); eventManager = new FileEventManager(fileTree, null); actionExecutor = new ActionExecutor(eventManager, fileManager, new TestPeerWaspConfig()); actionExecutor.setWaitForActionCompletion(false); actionExecutor.start(); watchService.addFileEventListener(eventManager); logger.info("Running"); } @After public void cleanFolder() throws Exception { watchService.stop(); Thread.sleep(500); FileUtils.cleanDirectory(basePath.toFile()); } private void sleep() throws InterruptedException { Thread.sleep(actionExecutor.getPeerWaspConfig().getAggregationIntervalInMillis() * 2); } /** * Create a file and test whether it gets handled by the * handleCreateEvent and eventually send over to H2H.add * * @throws Exception */ @Test public void testFileCreate() throws Exception { watchService.start(basePath); // create new file File add = Paths.get(basePath.toString(), "add_empty.txt").toFile(); add.createNewFile(); sleep(); Mockito.verify(fileManager, Mockito.times(1)).add(add.toPath()); } /** * Create a file with some data in it and test whether * it gets handled by the handleCreateEvent * * @throws Exception */ @Test public void testSmallFileCreate() throws Exception { watchService.start(basePath); // create new small file File add = Paths.get(basePath.toString(), "add_small.txt").toFile(); FileWriter out = new FileWriter(add); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); sleep(); Mockito.verify(fileManager, Mockito.times(1)).add(add.toPath()); } /** * Create a file which contains a large portion of data and test * whether it gets handled by the handleCreateEvent * * @throws Exception */ @Test public void testBigFileCreate() throws Exception { watchService.start(basePath); // create new big file File add = Paths.get(basePath.toString(), "add_big.txt").toFile(); FileWriter out = new FileWriter(add); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_BIG_FILE); out.close(); sleep(); Mockito.verify(fileManager, Mockito.times(1)).add(add.toPath()); } /** * Test whether a file which already was added to H2H does not * lead to a hard-delete when it is desynchronized. * * @throws Exception */ @Test public void testFileSoftDelete() throws Exception { // create new file File delete = Paths.get(basePath.toString(), "delete_empty.txt").toFile(); delete.createNewFile(); sleep(); watchService.start(basePath); //delete newly created file FileUtils.forceDelete(delete); sleep(); Mockito.verifyNoMoreInteractions(fileManager); } /** * Test whether a modify event will be detected when a file * gets altered * * @throws Exception */ @Test public void testFileModify() throws Exception { watchService.start(basePath); // create new small file File modify = Paths.get(basePath.toString(), "modify_small.txt").toFile(); FileWriter out = new FileWriter(modify); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); sleep(); Mockito.verify(fileManager, Mockito.times(1)).add(modify.toPath()); // modify newly created file out = new FileWriter(modify); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); sleep(); Mockito.verify(fileManager, Mockito.times(1)).update(modify.toPath()); } /** * Test whether a modify event of a big file gets detected when a file * gets altered * * @throws Exception */ @Test public void testBigFileModify() throws Exception { watchService.start(basePath); // create new small file File modify = Paths.get(basePath.toString(), "modify_big.txt").toFile(); FileWriter out = new FileWriter(modify); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_BIG_FILE); out.close(); sleep(); Mockito.verify(fileManager, Mockito.times(1)).add(modify.toPath()); // modify newly created file out = new FileWriter(modify); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_BIG_FILE); out.close(); sleep(); Mockito.verify(fileManager).update(modify.toPath()); } /** * Test whether renaming a file gets recognized as an move event * @throws Exception */ @Test public void testFileRename() throws Exception { watchService.start(basePath); File rename = Paths.get(basePath.toString(), "rename.txt").toFile(); File newName = Paths.get(basePath.toString(), "rename_rename.txt").toFile(); FileWriter out = new FileWriter(rename); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); sleep(); Mockito.verify(fileManager, Mockito.times(1)).add(rename.toPath()); rename.renameTo(newName); sleep(); Mockito.verify(fileManager, Mockito.times(1)).move(rename.toPath(), newName.toPath()); } /** * Test whether the movement of a file to an existing sub directory gets recognized * as an move event * * @throws Exception */ @Test public void testFileMove() throws Exception { watchService.start(basePath); // create new sub directory String subDirString = "subDir"; File subDir = Paths.get(basePath.toString(), subDirString).toFile(); FileUtils.forceMkdir(subDir); // create new file File file = Paths.get(basePath.toString(), "move.txt").toFile(); // target file path File newFile = Paths.get(basePath.toString(), subDirString, "move.txt").toFile(); FileWriter out = new FileWriter(file); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); sleep(); Mockito.verify(fileManager, Mockito.times(1)).add(file.toPath()); // move file to new target path FileUtils.moveFile(file, newFile); sleep(); Mockito.verify(fileManager, Mockito.times(1)).move(file.toPath(), newFile.toPath()); } /** * Copy an existing file to another location and check whether * the appropriate event gets triggered * * @throws Exception */ @Test public void testSmallFileCopy() throws Exception { File file = Paths.get(basePath.toString(), "original.txt").toFile(); File newFile = Paths.get(basePath.toString(), "copy.txt").toFile(); FileWriter out = new FileWriter(file); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); watchService.start(basePath); FileUtils.copyFile(file, newFile); sleep(); Mockito.verify(fileManager, Mockito.times(1)).add(newFile.toPath()); Mockito.verify(fileManager, Mockito.never()).delete(file.toPath()); Mockito.verify(fileManager, Mockito.never()).move(file.toPath(), newFile.toPath()); } @Test public void testBigFileCopy() throws Exception { File file = Paths.get(basePath.toString(), "original_big.txt").toFile(); File newFile = Paths.get(basePath.toString(), "copy_big.txt").toFile(); FileWriter out = new FileWriter(file); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_BIG_FILE); out.close(); watchService.start(basePath); FileUtils.copyFile(file, newFile); sleep(); Mockito.verify(fileManager, Mockito.times(1)).add(newFile.toPath()); Mockito.verify(fileManager, Mockito.never()).delete(file.toPath()); Mockito.verify(fileManager, Mockito.never()).move(file.toPath(), newFile.toPath()); } @Test public void testManySimultaneousEvents() throws Exception { watchService.start(basePath); List<File> folderList = new ArrayList<File>(); List<File> fileList = new ArrayList<File>(); int numberOfFolders = WatchServiceTestHelpers.randomInt(5, 50); int numberOfFiles = WatchServiceTestHelpers.randomInt(200, 1000); // create random folders & save files(paths) in list String folderName = null; for (int i = 1; i <= numberOfFolders; i++){ folderName = WatchServiceTestHelpers.getRandomString(15, "abcdefghijklmnopqrstuvwxyz123456789"); String subDirString = "\\" + folderName +"\\"; File subDir = Paths.get(basePath.toString(), subDirString).toFile(); FileUtils.forceMkdir(subDir); folderList.add(subDir); } // create random files in base path & save files(paths) in list File randomFile; for (int i = 1; i <= numberOfFiles; i++){ String randomFileName = WatchServiceTestHelpers.getRandomString(15, "abcdefghijklmnopqrstuvwxyz123456789"); randomFile = Paths.get(basePath.toString(), randomFileName + ".txt").toFile(); FileWriter out = new FileWriter(randomFile); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); fileList.add(randomFile); } // pick a random number of files and move them randomly to folders int randomNumberOfMovements = WatchServiceTestHelpers.randomInt(1, numberOfFiles); for (int i = 1; i <= randomNumberOfMovements; i++){ // randomly pick a file from the fileList int randomFilePick = WatchServiceTestHelpers.randomInt(0, fileList.size()-1); File randomFileToMove = fileList.get(randomFilePick); // randomly pick a target sub directory int randomFolderPick = WatchServiceTestHelpers.randomInt(0, folderList.size()-1); File randomTargetFolder = folderList.get(randomFolderPick); FileUtils.moveFileToDirectory(randomFileToMove, randomTargetFolder, false); // remove moved file from file list fileList.remove(randomFileToMove); } sleep(); // Mockito.verify(fileManager, Mockito.times(randomNumberOfMovements)).move(Matchers.anyObject(), Matchers.anyObject()); } @Test public void createManyFiles() throws Exception{ int numFiles = 1000; watchService.start(basePath); List<Path> files = new ArrayList<Path>(); while(numFiles > 0) { String randomFileName = WatchServiceTestHelpers.getRandomString(5, "abcdfg1234"); Path file = Paths.get(basePath.toString(), randomFileName + ".txt"); FileWriter out = new FileWriter(file.toFile()); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); files.add(file); --numFiles; } sleep(); Iterator<Path> it = files.iterator(); while(it.hasNext()) { Mockito.verify(fileManager, Mockito.times(1)).add(it.next()); } } @Test @Ignore public void testCopyFolder() throws Exception { // create folder with files int numFiles = 100; Path original = Paths.get(basePath.toString(), "original_folder"); Files.createDirectory(original); List<Path> files = new ArrayList<Path>(); Path copy = Paths.get(basePath.toString(), "copy_folder"); files.add(original); for(int i = 0; i < numFiles; ++i) { Path f = Paths.get(original.toString(), String.format("file_%s.txt", i)); FileWriter out = new FileWriter(f.toFile()); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); files.add(Paths.get(copy.toString(), f.getFileName().toString())); } watchService.start(basePath); // copy folder FileUtils.copyDirectory(original.toFile(), copy.toFile()); Thread.sleep(actionExecutor.getPeerWaspConfig().getAggregationIntervalInMillis() * 2); Mockito.verify(fileManager, Mockito.times(1)).add(copy); // Iterator<Path> it = files.iterator(); // while(it.hasNext()) { // Path newFile = it.next(); //// Path newFile = Paths.get(copy.toString(), oldFile.getFileName().toString()); // assertTrue(Files.exists(newFile)); // Object obj = Mockito.when(fileManager.add(newFile)).thenReturn(null); // // Mockito.verify(fileManager, Mockito.times(1)).add(newFile); // Mockito.verify(fileManager, Mockito.never()).delete(oldFile); // Mockito.verify(fileManager, Mockito.never()).move(oldFile, newFile); //} // TODO: test not implemented correctly yet //fail(); // final int nrElements = files.size(); final ArgumentCaptor<Path> captor = ArgumentCaptor.forClass(Path.class); // Mockito.verify(fileManager).add(captor.capture()); // // // This is using assertJ // // assertThat(captor.getAllValues()).isEqualTo(myObjects); } @Test public void testCreateManyFiles() throws Exception{ watchService.start(basePath); File file = null; int fileNumbers = 1000; for (int i = 1; i <= fileNumbers; i++){ String randomFileName = WatchServiceTestHelpers.getRandomString(9, "abcdefg123456789"); file = Paths.get(basePath.toString(), randomFileName + ".txt").toFile(); FileWriter out = new FileWriter(file); WatchServiceTestHelpers.writeRandomData(out, NUM_CHARS_SMALL_FILE); out.close(); // System.out.println("File added: Itemnr.: " + i); } sleep(); Mockito.verify(fileManager, Mockito.times(fileNumbers)).add(Matchers.anyObject()); } }