package org.peerbox.watchservice.filetree;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.io.FileUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.peerbox.watchservice.filetree.composite.AbstractFileComponent;
import org.peerbox.watchservice.filetree.composite.FileComponent;
import org.peerbox.watchservice.filetree.composite.FileLeaf;
import org.peerbox.watchservice.filetree.composite.FolderComposite;
public class FileComponentTest {
private static Path parentPath = Paths.get(FileUtils.getTempDirectoryPath(), "PeerWasp_FolderCompositeTest");
private static Path fileOnRootPath = parentPath.resolve("file.txt");
private static Path dirOnRootPath = parentPath.resolve("dir");
private static Path dirInDirOnRootPath = parentPath.resolve("dir").resolve("dir2");
private static Path fileInNewDirPath = parentPath.resolve("dir").resolve("file.txt");
private static Path fileInDirInDirOnRootPath = dirInDirOnRootPath.resolve("file.txt");
@BeforeClass
public static void setup() throws IOException{
Files.createDirectory(parentPath);
Files.createFile(fileOnRootPath);
Files.createDirectories(dirInDirOnRootPath);
Files.createDirectories(dirOnRootPath);
Files.createFile(fileInNewDirPath);
}
@AfterClass
public static void rollBack() throws IOException{
FileUtils.deleteDirectory(parentPath.toFile());
}
/**
* This test checks if putComponent calls work by issuing getComponent calls on
* the added components. Furthermore, delete and updates are tested,
*
* - add a file to the root directory
* - add a file to a sub directory (such that the sub dir is created as well)
* - add a directory
*/
@Test
public void fileTreeOperationsTest(){
FolderComposite fileTree = new TestFolderComposite(parentPath, true, true);
FileLeaf fileOnRoot = new TestFileLeaf(fileOnRootPath, true);
FileLeaf fileInNewDir = new TestFileLeaf(fileInNewDirPath, true);
fileInNewDir.getAction().setFile(fileInNewDir);
fileOnRoot.getAction().setFile(fileOnRoot);
fileTree.putComponent(fileOnRootPath, fileOnRoot);
fileTree.putComponent(fileInNewDirPath, fileInNewDir);
FileComponent component = fileTree.getComponent(fileOnRootPath);
assertTrue(component instanceof FileLeaf);
assertTrue(component.getAction().getFile().getPath().equals(fileOnRootPath));
//check if it is possible to add a file into a new directory
component = fileTree.getComponent(fileInNewDirPath);
assertTrue(component instanceof FileLeaf);
assertTrue(component.getPath().equals(fileInNewDirPath));
component = fileTree.getComponent(dirOnRootPath);
assertTrue(component instanceof FolderComposite);
assertTrue(component.getPath().equals(dirOnRootPath));
component = fileTree.getComponent(dirInDirOnRootPath);
assertNull(component);
fileTree.putComponent(dirInDirOnRootPath, new TestFolderComposite(dirInDirOnRootPath, true));
component = fileTree.getComponent(dirInDirOnRootPath);
assertTrue(component instanceof FolderComposite);
assertTrue(component.getPath().equals(dirInDirOnRootPath));
bubbleContentHashUpdateTest(fileTree);
deleteComponentTest(fileTree);
}
private void bubbleContentHashUpdateTest(FolderComposite fileTree){
//put a new file in a lower directory
FileLeaf fileInDirInDirOnRoot = new TestFileLeaf(fileInDirInDirOnRootPath, true);
fileInDirInDirOnRoot.getAction().setFile(fileInDirInDirOnRoot);
fileTree.putComponent(fileInDirInDirOnRootPath, fileInDirInDirOnRoot);
FileComponent component = fileTree.getComponent(fileInDirInDirOnRootPath);
assertTrue(component instanceof FileLeaf);
assertTrue(component.getPath().equals(fileInDirInDirOnRootPath));
//get old hash of root and file, then modify the file
String oldHashRoot = fileTree.getContentHash();
String oldHashFile = component.getContentHash();
try {
PrintWriter writer = new PrintWriter(fileInDirInDirOnRootPath.toFile(), "UTF-8");
writer.println("HelloWorld");
writer.close();
} catch (FileNotFoundException | UnsupportedEncodingException e) {
e.printStackTrace();
}
fileInDirInDirOnRoot.updateContentHash();
String newHashRoot = fileTree.getContentHash();
String newHashFile = component.getContentHash();
assertFalse(newHashRoot.equals(oldHashRoot));
assertFalse(newHashFile.equals(oldHashFile));
}
private void deleteComponentTest(FolderComposite fileTree){
//ensure the file exists
FileComponent component = fileTree.deleteComponent(fileOnRootPath);
assertTrue(component instanceof FileLeaf);
//ensure it cannot be received anymore
component = fileTree.getComponent(fileOnRootPath);
assertNull(component);
//ensure new delete returns null
component = fileTree.deleteComponent(fileOnRootPath);
assertNull(component);
//ensure file in sub directory still exists
component = fileTree.getComponent(fileInNewDirPath);
assertTrue(component instanceof FileLeaf);
String oldStructureHashRoot = fileTree.getStructureHash();
//delete subdirectory, ensure contained files and directories are deleted as well
component = fileTree.deleteComponent(dirOnRootPath);
assertFalse(fileTree.getStructureHash().equals(oldStructureHashRoot));
oldStructureHashRoot = fileTree.getStructureHash();
assertTrue(component instanceof FolderComposite);
component = fileTree.deleteComponent(dirInDirOnRootPath);
assertNull(component);
assertTrue(fileTree.getStructureHash().equals(oldStructureHashRoot));
component = fileTree.deleteComponent(fileInNewDirPath);
assertNull(component);
assertTrue(fileTree.getStructureHash().equals(oldStructureHashRoot));
}
/**
* This test ensures that create/delete events of components trigger hierarchical updates of
* the structureHash value, which encodes the filenames of all recusively contained components
*/
public void bubbleStructureHashUpdateTest(){
}
public static void setContentHashByReflection(FileComponent f, String contentHash) {
try {
Method setContentHashMethod = AbstractFileComponent.class.getDeclaredMethod("setContentHash", String.class);
setContentHashMethod.setAccessible(true);
setContentHashMethod.invoke(f, contentHash);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}