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 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); }