diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Deleter.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Deleter.java
new file mode 100644
index 000000000..2ae71d3f5
--- /dev/null
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Deleter.java
@@ -0,0 +1,15 @@
+package org.cryptomator.filesystem;
+
+public class Deleter {
+
+ /**
+ * Deletes all and only the content of a given {@link Folder} but not the folder itself.
+ */
+ public static void deleteContent(Folder folder) {
+ if (folder.exists()) {
+ folder.folders().forEach(Folder::delete);
+ folder.files().forEach(File::delete);
+ }
+ }
+
+}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/File.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/File.java
index 82889bc1d..4cb6665aa 100644
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/File.java
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/File.java
@@ -75,4 +75,10 @@ public interface File extends Node, Comparable {
Mover.move(this, destination);
}
+ default void delete() {
+ try (WritableFile writableFile = openWritable()) {
+ writableFile.delete();
+ }
+ }
+
}
diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Folder.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Folder.java
index 674dd71a0..af9718ce6 100644
--- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Folder.java
+++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Folder.java
@@ -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;
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java
index d1a69a809..f6b99033f 100644
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java
+++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFileSystem.java
@@ -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) {
diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java
index 6c05e87c3..bff548745 100644
--- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java
+++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java
@@ -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
diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemTest.java b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemTest.java
index 7c5162238..c23c60680 100644
--- a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemTest.java
+++ b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemTest.java
@@ -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)
diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFolder.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFolder.java
index c9020596a..95f62fe80 100644
--- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFolder.java
+++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFolder.java
@@ -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 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
diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryNode.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryNode.java
index 71b799c25..dc85711b8 100644
--- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryNode.java
+++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryNode.java
@@ -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
diff --git a/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemFactories.java b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemFactories.java
index 6963bd784..f4a3db6bd 100644
--- a/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemFactories.java
+++ b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemFactories.java
@@ -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> {
+class FileSystemFactories implements Iterable {
private static final SecureRandom RANDOM_MOCK = new SecureRandom() {
@Override
@@ -27,13 +26,13 @@ class FileSystemFactories implements Iterable> {
}
};
- private final List> factories = new ArrayList<>();
+ private final List 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> {
return new CryptoFileSystem(createNioFileSystem(), new CryptorImpl(RANDOM_MOCK), "aPassphrase");
}
- private void add(String name, Supplier fileSystemSupplier) {
- factories.add(new Supplier() {
+ 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> {
}
@Override
- public Iterator> iterator() {
+ public Iterator iterator() {
return factories.iterator();
}
+ public interface FileSystemFactory {
+
+ FileSystem create();
+
+ }
+
}
diff --git a/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemTests.java b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemTests.java
index 9a39f2ec4..b2ccd1c5c 100644
--- a/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemTests.java
+++ b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FileSystemTests.java
@@ -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> FILE_SYSTEM_FACTORIES = new FileSystemFactories();
+ public static final Iterable FILE_SYSTEM_FACTORIES = new FileSystemFactories();
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Theory
- public void testFileSystemHasNoParent(Supplier 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 factory) {
- FileSystem inTest = factory.get();
+ public void testFileSystemExists(FileSystemFactory factory) {
+ FileSystem inTest = factory.create();
assertThat(inTest.exists(), is(true));
}
@Theory
- public void testFileSystemHasNoChildren(Supplier 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 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 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 factory) {
- FileSystem inTest = factory.get();
+ public void testFileSystemsFileSystemIsItself(FileSystemFactory factory) {
+ FileSystem inTest = factory.create();
assertThat(inTest.fileSystem(), is(inTest));
}
@Theory
- public void testFileSystemBelongsToSameFilesystemWhenCheckingItself(Supplier 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 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 factory) {
- FileSystem inTest = factory.get();
+ public void testFileSystemIsNoAncestorOfItself(FileSystemFactory factory) {
+ FileSystem inTest = factory.create();
assertThat(inTest.isAncestorOf(inTest), is(false));
}
diff --git a/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FolderChildrenTests.java b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FolderChildrenTests.java
new file mode 100644
index 000000000..463976e52
--- /dev/null
+++ b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FolderChildrenTests.java
@@ -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 FILE_SYSTEM_FACTORIES = new FileSystemFactories();
+
+ @DataPoints
+ public static final Iterable 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()));
+ }
+
+}
diff --git a/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FolderTests.java b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FolderTests.java
new file mode 100644
index 000000000..0a748e362
--- /dev/null
+++ b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/FolderTests.java
@@ -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 FILE_SYSTEM_FACTORIES = new FileSystemFactories();
+
+ @DataPoints
+ public static final Iterable 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));
+ }
+
+}
diff --git a/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/SubfolderFactories.java b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/SubfolderFactories.java
new file mode 100644
index 000000000..00bff41df
--- /dev/null
+++ b/main/filesystem-invariants-tests/src/test/java/org/cryptomator/filesystem/invariants/SubfolderFactories.java
@@ -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 {
+
+ private final List 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 iterator() {
+ return factories.iterator();
+ }
+
+}
diff --git a/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemTest.java b/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemTest.java
index 6a6b65d65..c91485744 100644
--- a/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemTest.java
+++ b/main/filesystem-nameshortening/src/test/java/org/cryptomator/filesystem/shortening/ShorteningFileSystemTest.java
@@ -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");
diff --git a/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFolder.java b/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFolder.java
index 472ea3712..cbc4c563d 100644
--- a/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFolder.java
+++ b/main/filesystem-nio/src/main/java/org/cryptomator/filesystem/nio/NioFolder.java
@@ -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();
- }
- }
-
}
diff --git a/main/filesystem-nio/src/test/java/org/cryptomator/filesystem/nio/NioFolderTest.java b/main/filesystem-nio/src/test/java/org/cryptomator/filesystem/nio/NioFolderTest.java
index 615813dc0..ddc47e3fc 100644
--- a/main/filesystem-nio/src/test/java/org/cryptomator/filesystem/nio/NioFolderTest.java
+++ b/main/filesystem-nio/src/test/java/org/cryptomator/filesystem/nio/NioFolderTest.java
@@ -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);
}