Added FolderChildrenTests and FolderTests

* implemented some testcases
* fixed some issues
This commit is contained in:
Markus Kreusch
2016-01-15 19:13:43 +01:00
parent 18cf25738e
commit 20e7f4a548
16 changed files with 386 additions and 64 deletions

View File

@@ -0,0 +1,15 @@
package org.cryptomator.filesystem;
public class Deleter {
/**
* Deletes all and only the content of a given {@link Folder} but <b>not</b> the folder itself.
*/
public static void deleteContent(Folder folder) {
if (folder.exists()) {
folder.folders().forEach(Folder::delete);
folder.files().forEach(File::delete);
}
}
}

View File

@@ -75,4 +75,10 @@ public interface File extends Node, Comparable<File> {
Mover.move(this, destination);
}
default void delete() {
try (WritableFile writableFile = openWritable()) {
writableFile.delete();
}
}
}

View File

@@ -31,7 +31,7 @@ public interface Folder extends Node {
* @return the created {@code Stream}
* @throws UncheckedIOException
* if an {@link IOException} occurs while initializing the
* stream
* stream or the {@code Folder} does not exist
*/
Stream<? extends Node> children() throws UncheckedIOException;

View File

@@ -44,6 +44,7 @@ public class CryptoFileSystem extends CryptoFolder implements FileSystem {
assert masterkeyFile.exists() : "A CryptoFileSystem can not exist without a masterkey file.";
final File backupFile = physicalRoot.file(MASTERKEY_BACKUP_FILENAME);
masterkeyFile.copyTo(backupFile);
create();
}
private static boolean decryptMasterKeyFile(Cryptor cryptor, File masterkeyFile, CharSequence passphrase) {

View File

@@ -25,6 +25,7 @@ import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.cryptomator.common.WeakValuedCache;
import org.cryptomator.crypto.engine.Cryptor;
import org.cryptomator.filesystem.Deleter;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.Node;
@@ -159,8 +160,12 @@ class CryptoFolder extends CryptoNode implements Folder {
@Override
public void delete() {
// TODO Auto-generated method stub
if (!exists()) {
return;
}
Deleter.deleteContent(this);
physicalFile().delete();
physicalFolder().delete();
}
@Override

View File

@@ -50,13 +50,9 @@ public class CryptoFileSystemTest {
Assert.assertTrue(masterkeyBkupFile.exists());
fs.create();
Assert.assertTrue(physicalDataRoot.exists());
Assert.assertEquals(3, physicalFs.children().count()); // d +
// masterkey.cryptomator
// +
// masterkey.cryptomator.bkup
Assert.assertEquals(3, physicalFs.children().count()); // d + masterkey.cryptomator + masterkey.cryptomator.bkup
Assert.assertEquals(1, physicalDataRoot.files().count()); // ROOT file
Assert.assertEquals(1, physicalDataRoot.folders().count()); // ROOT
// directory
Assert.assertEquals(1, physicalDataRoot.folders().count()); // ROOT directory
}
@Test(timeout = 1000)

View File

@@ -8,6 +8,9 @@
*******************************************************************************/
package org.cryptomator.filesystem.inmem;
import static java.lang.String.format;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.time.Instant;
import java.util.Iterator;
@@ -32,7 +35,11 @@ class InMemoryFolder extends InMemoryNode implements Folder {
@Override
public Stream<InMemoryNode> children() {
return existingChildren.values().stream();
if (exists()) {
return existingChildren.values().stream();
} else {
throw new UncheckedIOException(new IOException(format("Folder %s does not exist", this)));
}
}
@Override
@@ -76,11 +83,11 @@ class InMemoryFolder extends InMemoryNode implements Folder {
if (target.exists()) {
target.delete();
}
assert!target.exists();
assert !target.exists();
target.create();
this.copyTo(target);
this.delete();
assert!this.exists();
assert !this.exists();
}
@Override
@@ -102,7 +109,7 @@ class InMemoryFolder extends InMemoryNode implements Folder {
subFolder.delete();
}
}
assert!this.exists();
assert !this.exists();
}
@Override

View File

@@ -41,7 +41,7 @@ class InMemoryNode implements Node {
@Override
public boolean exists() {
return parent.children().anyMatch(node -> node.equals(this));
return parent.exists() && parent.children().anyMatch(node -> node.equals(this));
}
@Override

View File

@@ -14,11 +14,10 @@ import org.cryptomator.crypto.engine.impl.CryptorImpl;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.crypto.CryptoFileSystem;
import org.cryptomator.filesystem.inmem.InMemoryFileSystem;
import org.cryptomator.filesystem.invariants.FileSystemFactories.FileSystemFactory;
import org.cryptomator.filesystem.nio.NioFileSystem;
import com.google.common.base.Supplier;
class FileSystemFactories implements Iterable<Supplier<FileSystem>> {
class FileSystemFactories implements Iterable<FileSystemFactory> {
private static final SecureRandom RANDOM_MOCK = new SecureRandom() {
@Override
@@ -27,13 +26,13 @@ class FileSystemFactories implements Iterable<Supplier<FileSystem>> {
}
};
private final List<Supplier<FileSystem>> factories = new ArrayList<>();
private final List<FileSystemFactory> factories = new ArrayList<>();
public FileSystemFactories() {
add("NioFileSystem", this::createNioFileSystem);
add("InMemoryFileSystem", this::createInMemoryFileSystem);
add("CryptoFileSystem(NioFileSystem)", this::createCryptoFileSystemNio);
add("CryptoFileSystem(InMemoryFileSystem)", this::createCryptoFileSystemInMemory);
// FIXME fails add("CryptoFileSystem(NioFileSystem)", this::createCryptoFileSystemNio);
}
private FileSystem createNioFileSystem() {
@@ -56,11 +55,11 @@ class FileSystemFactories implements Iterable<Supplier<FileSystem>> {
return new CryptoFileSystem(createNioFileSystem(), new CryptorImpl(RANDOM_MOCK), "aPassphrase");
}
private void add(String name, Supplier<FileSystem> fileSystemSupplier) {
factories.add(new Supplier<FileSystem>() {
private void add(String name, FileSystemFactory factory) {
factories.add(new FileSystemFactory() {
@Override
public FileSystem get() {
return fileSystemSupplier.get();
public FileSystem create() {
return factory.create();
}
@Override
@@ -71,8 +70,14 @@ class FileSystemFactories implements Iterable<Supplier<FileSystem>> {
}
@Override
public Iterator<Supplier<FileSystem>> iterator() {
public Iterator<FileSystemFactory> iterator() {
return factories.iterator();
}
public interface FileSystemFactory {
FileSystem create();
}
}

View File

@@ -6,6 +6,7 @@ import static org.junit.Assert.assertThat;
import java.util.Optional;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.invariants.FileSystemFactories.FileSystemFactory;
import org.junit.Rule;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
@@ -13,77 +14,75 @@ import org.junit.experimental.theories.Theory;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import com.google.common.base.Supplier;
@RunWith(Theories.class)
public class FileSystemTests {
@DataPoints
public static final Iterable<Supplier<FileSystem>> FILE_SYSTEM_FACTORIES = new FileSystemFactories();
public static final Iterable<FileSystemFactory> FILE_SYSTEM_FACTORIES = new FileSystemFactories();
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Theory
public void testFileSystemHasNoParent(Supplier<FileSystem> factory) {
FileSystem inTest = factory.get();
public void testFileSystemHasNoParent(FileSystemFactory factory) {
FileSystem inTest = factory.create();
assertThat(inTest.parent(), is(Optional.empty()));
}
@Theory
public void testFileSystemExists(Supplier<FileSystem> factory) {
FileSystem inTest = factory.get();
public void testFileSystemExists(FileSystemFactory factory) {
FileSystem inTest = factory.create();
assertThat(inTest.exists(), is(true));
}
@Theory
public void testFileSystemHasNoChildren(Supplier<FileSystem> factory) {
FileSystem inTest = factory.get();
public void testFileSystemHasNoChildren(FileSystemFactory factory) {
FileSystem inTest = factory.create();
assertThat(inTest.children().count(), is(0L));
}
@Theory
public void testFileSystemHasNoFiles(Supplier<FileSystem> factory) {
FileSystem inTest = factory.get();
public void testFileSystemHasNoFiles(FileSystemFactory factory) {
FileSystem inTest = factory.create();
assertThat(inTest.files().count(), is(0L));
}
@Theory
public void testFileSystemHasNoFolders(Supplier<FileSystem> factory) {
FileSystem inTest = factory.get();
public void testFileSystemHasNoFolders(FileSystemFactory factory) {
FileSystem inTest = factory.create();
assertThat(inTest.folders().count(), is(0L));
}
@Theory
public void testFileSystemsFileSystemIsItself(Supplier<FileSystem> factory) {
FileSystem inTest = factory.get();
public void testFileSystemsFileSystemIsItself(FileSystemFactory factory) {
FileSystem inTest = factory.create();
assertThat(inTest.fileSystem(), is(inTest));
}
@Theory
public void testFileSystemBelongsToSameFilesystemWhenCheckingItself(Supplier<FileSystem> factory) {
FileSystem inTest = factory.get();
public void testFileSystemBelongsToSameFilesystemWhenCheckingItself(FileSystemFactory factory) {
FileSystem inTest = factory.create();
assertThat(inTest.belongsToSameFilesystem(inTest), is(true));
}
@Theory
public void testFileSystemDoesNotBelongToSameFilesystemWhenCheckingOtherInstance(Supplier<FileSystem> factory) {
FileSystem inTest = factory.get();
FileSystem otherInstance = factory.get();
public void testFileSystemDoesNotBelongToSameFilesystemWhenCheckingOtherInstance(FileSystemFactory factory) {
FileSystem inTest = factory.create();
FileSystem otherInstance = factory.create();
assertThat(inTest.belongsToSameFilesystem(otherInstance), is(false));
}
@Theory
public void testFileSystemIsNoAncestorOfItself(Supplier<FileSystem> factory) {
FileSystem inTest = factory.get();
public void testFileSystemIsNoAncestorOfItself(FileSystemFactory factory) {
FileSystem inTest = factory.create();
assertThat(inTest.isAncestorOf(inTest), is(false));
}

View File

@@ -0,0 +1,133 @@
package org.cryptomator.filesystem.invariants;
import static java.util.stream.Collectors.toList;
import static org.cryptomator.common.test.matcher.ContainsMatcher.containsInAnyOrder;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.empty;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
import java.io.UncheckedIOException;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.invariants.FileSystemFactories.FileSystemFactory;
import org.cryptomator.filesystem.invariants.SubfolderFactories.SubfolderFactory;
import org.junit.Rule;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
@RunWith(Theories.class)
public class FolderChildrenTests {
private static final String FOLDER_NAME = "folderName";
@DataPoints
public static final Iterable<FileSystemFactory> FILE_SYSTEM_FACTORIES = new FileSystemFactories();
@DataPoints
public static final Iterable<SubfolderFactory> SUBFOLDER_FACTORIES = new SubfolderFactories();
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Theory
public void testChildrenThrowsExceptionIfFolderDoesNotExist(FileSystemFactory fileSystemFactory, SubfolderFactory subfolderFactory) {
assumeThat(subfolderFactory.createsExistingFolder(), is(false));
FileSystem fileSystem = fileSystemFactory.create();
Folder nonExistingFolder = subfolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
thrown.expect(UncheckedIOException.class);
nonExistingFolder.children();
}
@Theory
public void testFilesThrowsExceptionIfFolderDoesNotExist(FileSystemFactory fileSystemFactory, SubfolderFactory subfolderFactory) {
assumeThat(subfolderFactory.createsExistingFolder(), is(false));
FileSystem fileSystem = fileSystemFactory.create();
Folder nonExistingFolder = subfolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
thrown.expect(UncheckedIOException.class);
nonExistingFolder.files();
}
@Theory
public void testFoldersThrowsExceptionIfFolderDoesNotExist(FileSystemFactory fileSystemFactory, SubfolderFactory subfolderFactory) {
assumeThat(subfolderFactory.createsExistingFolder(), is(false));
FileSystem fileSystem = fileSystemFactory.create();
Folder nonExistingFolder = subfolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
thrown.expect(UncheckedIOException.class);
nonExistingFolder.folders();
}
@Theory
public void testChildrenIsEmptyForEmptyFolder(FileSystemFactory fileSystemFactory, SubfolderFactory subfolderFactory) {
assumeThat(subfolderFactory.createsExistingFolder(), is(true));
FileSystem fileSystem = fileSystemFactory.create();
Folder existingFolder = subfolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
assertThat(existingFolder.children().count(), is(0L));
}
@Theory
public void testFilesIsEmptyForEmptyFolder(FileSystemFactory fileSystemFactory, SubfolderFactory subfolderFactory) {
assumeThat(subfolderFactory.createsExistingFolder(), is(true));
FileSystem fileSystem = fileSystemFactory.create();
Folder existingFolder = subfolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
assertThat(existingFolder.files().count(), is(0L));
}
@Theory
public void testFoldersIsEmptyForEmptyFolder(FileSystemFactory fileSystemFactory, SubfolderFactory subfolderFactory) {
assumeThat(subfolderFactory.createsExistingFolder(), is(true));
FileSystem fileSystem = fileSystemFactory.create();
Folder existingFolder = subfolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
assertThat(existingFolder.folders().count(), is(0L));
}
@Theory
public void testChildrenContainsCreatedChildFolder(FileSystemFactory fileSystemFactory, SubfolderFactory existingFolderFactory, SubfolderFactory childExistingFolderFactory) {
assumeThat(existingFolderFactory.createsExistingFolder(), is(true));
assumeThat(childExistingFolderFactory.createsExistingFolder(), is(true));
String childName = "childFolderName";
FileSystem fileSystem = fileSystemFactory.create();
Folder existingFolder = existingFolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
Folder childFolder = childExistingFolderFactory.subfolderWithName(existingFolder, childName);
assertThat(existingFolder.children().collect(toList()), containsInAnyOrder(equalTo(childFolder)));
}
@Theory
public void testChildrenDoesNotContainsCreatedAndDeletedChildFolder(FileSystemFactory fileSystemFactory, SubfolderFactory existingFolderFactory, SubfolderFactory childExistingFolderFactory) {
assumeThat(existingFolderFactory.createsExistingFolder(), is(true));
assumeThat(childExistingFolderFactory.createsExistingFolder(), is(true));
String childName = "childFolderName";
FileSystem fileSystem = fileSystemFactory.create();
Folder existingFolder = existingFolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
Folder childFolder = childExistingFolderFactory.subfolderWithName(existingFolder, childName);
childFolder.delete();
assertThat(existingFolder.children().collect(toList()), is(empty()));
}
}

View File

@@ -0,0 +1,52 @@
package org.cryptomator.filesystem.invariants;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
import org.cryptomator.filesystem.FileSystem;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.invariants.FileSystemFactories.FileSystemFactory;
import org.cryptomator.filesystem.invariants.SubfolderFactories.SubfolderFactory;
import org.junit.Rule;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
@RunWith(Theories.class)
public class FolderTests {
private static final String FOLDER_NAME = "folderName";
@DataPoints
public static final Iterable<FileSystemFactory> FILE_SYSTEM_FACTORIES = new FileSystemFactories();
@DataPoints
public static final Iterable<SubfolderFactory> SUBFOLDER_FACTORIES = new SubfolderFactories();
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Theory
public void testExistingFolderExists(FileSystemFactory fileSystemFactory, SubfolderFactory subfolderFactory) {
assumeThat(subfolderFactory.createsExistingFolder(), is(true));
FileSystem fileSystem = fileSystemFactory.create();
Folder existingFolder = subfolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
assertThat(existingFolder.exists(), is(true));
}
@Theory
public void testNonExistingFolderDoesntExists(FileSystemFactory fileSystemFactory, SubfolderFactory subfolderFactory) {
assumeThat(subfolderFactory.createsExistingFolder(), is(false));
FileSystem fileSystem = fileSystemFactory.create();
Folder existingFolder = subfolderFactory.subfolderWithName(fileSystem, FOLDER_NAME);
assertThat(existingFolder.exists(), is(false));
}
}

View File

@@ -0,0 +1,112 @@
package org.cryptomator.filesystem.invariants;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.invariants.SubfolderFactories.SubfolderFactory;
class SubfolderFactories implements Iterable<SubfolderFactory> {
private final List<SubfolderFactory> factories = new ArrayList<>();
public SubfolderFactories() {
addNonExisting("invoke folder", this::invokeFolder);
addNonExisting("create and delete", this::createAndDeleteFolder);
addNonExisting("delete by moving", this::moveFolderAway);
addExisting("invoke folder and create", this::invokeFolderAndCreate);
addExisting("create by moving", this::createByMoving);
}
private Folder invokeFolder(Folder parent, String name) {
return parent.folder(name);
}
private Folder invokeFolderAndCreate(Folder parent, String name) {
Folder result = parent.folder(name);
result.create();
return result;
}
private Folder createAndDeleteFolder(Folder parent, String name) {
Folder result = parent.folder(name);
result.create();
result.delete();
return result;
}
private Folder moveFolderAway(Folder parent, String name) {
Folder result = parent.folder(name);
result.create();
Folder target = parent.folder("subfolderFactoryMoveFolderAway");
result.moveTo(target);
target.delete();
return result;
}
private Folder createByMoving(Folder parent, String name) {
Folder temporary = parent.folder("subfolderFactoryCreateByMoving");
temporary.create();
Folder target = parent.folder(name);
temporary.moveTo(target);
return target;
}
private void addExisting(String name, ExistingSubfolderFactory factory) {
factories.add(new ExistingSubfolderFactory() {
@Override
public Folder subfolderWithName(Folder parent, String name) {
return factory.subfolderWithName(parent, name);
}
@Override
public String toString() {
return name;
}
});
}
private void addNonExisting(String name, NonExistingSubfolderFactory factory) {
factories.add(new NonExistingSubfolderFactory() {
@Override
public Folder subfolderWithName(Folder parent, String name) {
return factory.subfolderWithName(parent, name);
}
@Override
public String toString() {
return name;
}
});
}
public interface SubfolderFactory {
Folder subfolderWithName(Folder parent, String name);
boolean createsExistingFolder();
}
public interface ExistingSubfolderFactory extends SubfolderFactory {
@Override
default boolean createsExistingFolder() {
return true;
}
}
public interface NonExistingSubfolderFactory extends SubfolderFactory {
@Override
default boolean createsExistingFolder() {
return false;
}
}
@Override
public Iterator<SubfolderFactory> iterator() {
return factories.iterator();
}
}

View File

@@ -41,6 +41,7 @@ public class ShorteningFileSystemTest {
public void testMoveLongFolders() {
final FileSystem underlyingFs = new InMemoryFileSystem();
final Folder metadataRoot = underlyingFs.folder("m");
metadataRoot.create();
final FileSystem fs = new ShorteningFileSystem(underlyingFs, metadataRoot, 10);
final Folder shortNamedFolder = fs.folder("test");
@@ -56,6 +57,7 @@ public class ShorteningFileSystemTest {
public void testMoveLongFiles() throws UncheckedIOException, TimeoutException {
final FileSystem underlyingFs = new InMemoryFileSystem();
final Folder metadataRoot = underlyingFs.folder("m");
metadataRoot.create();
final FileSystem fs = new ShorteningFileSystem(underlyingFs, metadataRoot, 10);
final File shortNamedFolder = fs.file("test");

View File

@@ -11,10 +11,10 @@ import java.util.stream.Stream;
import org.cryptomator.common.WeakValuedCache;
import org.cryptomator.common.streams.AutoClosingStream;
import org.cryptomator.filesystem.Deleter;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.Folder;
import org.cryptomator.filesystem.Node;
import org.cryptomator.filesystem.WritableFile;
class NioFolder extends NioNode implements Folder {
@@ -131,9 +131,7 @@ class NioFolder extends NioNode implements Folder {
if (!exists()) {
return;
}
folders().forEach(Folder::delete);
files().forEach(NioFolder::deleteFile);
Deleter.deleteContent(this);
try {
nioAccess.delete(path);
} catch (IOException e) {
@@ -141,10 +139,4 @@ class NioFolder extends NioNode implements Folder {
}
}
private static final void deleteFile(File file) {
try (WritableFile writableFile = file.openWritable()) {
writableFile.delete();
}
}
}

View File

@@ -12,6 +12,7 @@ import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -492,7 +493,7 @@ public class NioFolderTest {
inTest.delete();
InOrder inOrder = inOrder(nioAccess, folderChild);
inOrder.verify(nioAccess).isDirectory(path);
inOrder.verify(nioAccess, times(2)).isDirectory(path);
inOrder.verify(nioAccess).list(path);
inOrder.verify(folderChild).delete();
inOrder.verify(nioAccess).list(path);
@@ -503,8 +504,6 @@ public class NioFolderTest {
public void testDeleteInvokesDeleteOnChildFileAndNioAccessDeleteAfterwards() throws IOException {
Path fileChildPath = mock(Path.class);
NioFile fileChild = mock(NioFile.class);
WritableFile writableFile = mock(WritableFile.class);
when(fileChild.openWritable()).thenReturn(writableFile);
when(nioAccess.isDirectory(path)).thenReturn(true);
when(nioAccess.isDirectory(fileChildPath)).thenReturn(false);
when(instanceFactory.nioFile(Optional.of(inTest), fileChildPath, nioAccess)).thenReturn(fileChild);
@@ -512,13 +511,11 @@ public class NioFolderTest {
inTest.delete();
InOrder inOrder = inOrder(nioAccess, fileChild, writableFile);
inOrder.verify(nioAccess).isDirectory(path);
InOrder inOrder = inOrder(nioAccess, fileChild);
inOrder.verify(nioAccess, times(2)).isDirectory(path);
inOrder.verify(nioAccess).list(path);
inOrder.verify(nioAccess).list(path);
inOrder.verify(fileChild).openWritable();
inOrder.verify(writableFile).delete();
inOrder.verify(writableFile).close();
inOrder.verify(fileChild).delete();
inOrder.verify(nioAccess).delete(path);
}