Explorar el Código

New base class for filesystem decorators, which basically just delegate work to the underlying file system

Sebastian Stenzel hace 9 años
padre
commit
c466c7e3ba
Se han modificado 18 ficheros con 932 adiciones y 0 borrados
  1. 8 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/Copier.java
  2. 8 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/DeadlockSafeFileOpener.java
  3. 8 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystemVisitor.java
  4. 8 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/Mover.java
  5. 8 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/OpenFiles.java
  6. 61 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFile.java
  7. 20 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFileSystem.java
  8. 86 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFolder.java
  9. 70 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingNode.java
  10. 55 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingReadableFile.java
  11. 70 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingWritableFile.java
  12. 8 0
      main/filesystem-api/src/main/java/org/cryptomator/filesystem/package-info.java
  13. 8 0
      main/filesystem-api/src/main/java/org/cryptomator/io/ByteBuffers.java
  14. 136 0
      main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingFileTest.java
  15. 163 0
      main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingFolderTest.java
  16. 88 0
      main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingReadableFileTest.java
  17. 119 0
      main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingWritableFileTest.java
  18. 8 0
      main/filesystem-api/src/test/java/org/cryptomator/io/ByteBuffersTest.java

+ 8 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/Copier.java

@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
 package org.cryptomator.filesystem;
 
 class Copier {

+ 8 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/DeadlockSafeFileOpener.java

@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
 package org.cryptomator.filesystem;
 
 import static java.lang.String.format;

+ 8 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystemVisitor.java

@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
 package org.cryptomator.filesystem;
 
 import static java.lang.String.format;

+ 8 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/Mover.java

@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
 package org.cryptomator.filesystem;
 
 class Mover {

+ 8 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/OpenFiles.java

@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
 package org.cryptomator.filesystem;
 
 import java.io.UncheckedIOException;

+ 61 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFile.java

@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import java.io.UncheckedIOException;
+
+import org.cryptomator.filesystem.File;
+
+public class DelegatingFile extends DelegatingNode<File>implements File {
+
+	public DelegatingFile(DelegatingFolder parent, File delegate) {
+		super(parent, delegate);
+	}
+
+	@Override
+	public DelegatingReadableFile openReadable() throws UncheckedIOException {
+		return new DelegatingReadableFile(delegate.openReadable());
+	}
+
+	@Override
+	public DelegatingWritableFile openWritable() throws UncheckedIOException {
+		return new DelegatingWritableFile(delegate.openWritable());
+	}
+
+	@Override
+	public void copyTo(File destination) {
+		if (getClass().equals(destination.getClass())) {
+			final File delegateDest = ((DelegatingFile) destination).delegate;
+			delegate.copyTo(delegateDest);
+		} else {
+			delegate.copyTo(destination);
+		}
+	}
+
+	@Override
+	public void moveTo(File destination) {
+		if (getClass().equals(destination.getClass())) {
+			final File delegateDest = ((DelegatingFile) destination).delegate;
+			delegate.moveTo(delegateDest);
+		} else {
+			throw new IllegalArgumentException("Can only move DelegatingFile to other DelegatingFile.");
+		}
+	}
+
+	@Override
+	public int compareTo(File o) {
+		if (getClass().equals(o.getClass())) {
+			final File delegateOther = ((DelegatingFile) o).delegate;
+			return delegate.compareTo(delegateOther);
+		} else {
+			return delegate.compareTo(o);
+		}
+	}
+
+}

+ 20 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFileSystem.java

@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import org.cryptomator.filesystem.FileSystem;
+import org.cryptomator.filesystem.Folder;
+
+public class DelegatingFileSystem extends DelegatingFolder implements FileSystem {
+
+	public DelegatingFileSystem(Folder delegate) {
+		super(null, delegate);
+	}
+
+}

+ 86 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingFolder.java

@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import java.io.UncheckedIOException;
+import java.util.stream.Stream;
+
+import org.cryptomator.filesystem.File;
+import org.cryptomator.filesystem.Folder;
+
+public class DelegatingFolder extends DelegatingNode<Folder>implements Folder {
+
+	public DelegatingFolder(DelegatingFolder parent, Folder delegate) {
+		super(parent, delegate);
+	}
+
+	@Override
+	public Stream<? extends DelegatingNode<?>> children() throws UncheckedIOException {
+		return Stream.concat(folders(), files());
+	}
+
+	@Override
+	public Stream<DelegatingFolder> folders() {
+		return delegate.folders().map(this::folder);
+	}
+
+	@Override
+	public Stream<DelegatingFile> files() throws UncheckedIOException {
+		return delegate.files().map(this::file);
+	}
+
+	@Override
+	public DelegatingFile file(String name) throws UncheckedIOException {
+		return file(delegate.file(name));
+	}
+
+	private DelegatingFile file(File delegate) {
+		return new DelegatingFile(this, delegate);
+	}
+
+	@Override
+	public DelegatingFolder folder(String name) throws UncheckedIOException {
+		return folder(delegate.folder(name));
+	}
+
+	private DelegatingFolder folder(Folder delegate) {
+		return new DelegatingFolder(this, delegate);
+	}
+
+	@Override
+	public void create() throws UncheckedIOException {
+		delegate.create();
+	}
+
+	@Override
+	public void delete() {
+		delegate.delete();
+	}
+
+	@Override
+	public void copyTo(Folder destination) throws UncheckedIOException {
+		if (destination instanceof DelegatingFolder) {
+			final Folder delegateDest = ((DelegatingFolder) destination).delegate;
+			delegate.copyTo(delegateDest);
+		} else {
+			delegate.copyTo(destination);
+		}
+	}
+
+	@Override
+	public void moveTo(Folder destination) {
+		if (getClass().equals(destination.getClass())) {
+			final Folder delegateDest = ((DelegatingFolder) destination).delegate;
+			delegate.moveTo(delegateDest);
+		} else {
+			throw new IllegalArgumentException("Can only move DelegatingFolder to other DelegatingFolder.");
+		}
+	}
+
+}

+ 70 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingNode.java

@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import java.io.UncheckedIOException;
+import java.time.Instant;
+import java.util.Optional;
+
+import org.cryptomator.filesystem.Node;
+
+class DelegatingNode<T extends Node> implements Node {
+
+	protected final DelegatingFolder parent;
+	protected final T delegate;
+
+	public DelegatingNode(DelegatingFolder parent, T delegate) {
+		if (delegate == null) {
+			throw new IllegalArgumentException("Delegate must not be null");
+		}
+		this.parent = parent;
+		this.delegate = delegate;
+	}
+
+	@Override
+	public String name() throws UncheckedIOException {
+		return delegate.name();
+	}
+
+	@Override
+	public Optional<DelegatingFolder> parent() throws UncheckedIOException {
+		return Optional.ofNullable(parent);
+	}
+
+	@Override
+	public boolean exists() throws UncheckedIOException {
+		return delegate.exists();
+	}
+
+	@Override
+	public Instant lastModified() throws UncheckedIOException {
+		return delegate.lastModified();
+	}
+
+	@Override
+	public int hashCode() {
+		return delegate.hashCode();
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj instanceof DelegatingNode) {
+			DelegatingNode<?> other = (DelegatingNode<?>) obj;
+			return this.delegate.equals(other.delegate);
+		} else {
+			return false;
+		}
+	}
+
+	@Override
+	public String toString() {
+		return "Delegate[" + delegate + "]";
+	}
+
+}

+ 55 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingReadableFile.java

@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import java.io.UncheckedIOException;
+import java.nio.ByteBuffer;
+
+import org.cryptomator.filesystem.ReadableFile;
+import org.cryptomator.filesystem.WritableFile;
+
+public class DelegatingReadableFile implements ReadableFile {
+
+	private final ReadableFile delegate;
+
+	public DelegatingReadableFile(ReadableFile delegate) {
+		this.delegate = delegate;
+	}
+
+	@Override
+	public boolean isOpen() {
+		return delegate.isOpen();
+	}
+
+	@Override
+	public void copyTo(WritableFile destination) throws UncheckedIOException {
+		if (destination instanceof DelegatingWritableFile) {
+			final WritableFile delegateDest = ((DelegatingWritableFile) destination).delegate;
+			delegate.copyTo(delegateDest);
+		} else {
+			delegate.copyTo(destination);
+		}
+	}
+
+	@Override
+	public int read(ByteBuffer target) throws UncheckedIOException {
+		return delegate.read(target);
+	}
+
+	@Override
+	public void position(long position) throws UncheckedIOException {
+		delegate.position(position);
+	}
+
+	@Override
+	public void close() throws UncheckedIOException {
+		delegate.close();
+	}
+
+}

+ 70 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/delegating/DelegatingWritableFile.java

@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import java.io.UncheckedIOException;
+import java.nio.ByteBuffer;
+import java.time.Instant;
+
+import org.cryptomator.filesystem.WritableFile;
+
+public class DelegatingWritableFile implements WritableFile {
+
+	final WritableFile delegate;
+
+	public DelegatingWritableFile(WritableFile delegate) {
+		this.delegate = delegate;
+	}
+
+	@Override
+	public boolean isOpen() {
+		return delegate.isOpen();
+	}
+
+	@Override
+	public void moveTo(WritableFile destination) throws UncheckedIOException {
+		if (getClass().equals(destination.getClass())) {
+			final WritableFile delegateDest = ((DelegatingWritableFile) destination).delegate;
+			delegate.moveTo(delegateDest);
+		} else {
+			throw new IllegalArgumentException("Can only move DelegatingWritableFile to a DelegatingWritableFile.");
+		}
+	}
+
+	@Override
+	public void setLastModified(Instant instant) throws UncheckedIOException {
+		delegate.setLastModified(instant);
+	}
+
+	@Override
+	public void delete() throws UncheckedIOException {
+		delegate.delete();
+	}
+
+	@Override
+	public void truncate() throws UncheckedIOException {
+		delegate.truncate();
+	}
+
+	@Override
+	public int write(ByteBuffer source) throws UncheckedIOException {
+		return delegate.write(source);
+	}
+
+	@Override
+	public void position(long position) throws UncheckedIOException {
+		delegate.position(position);
+	}
+
+	@Override
+	public void close() throws UncheckedIOException {
+		delegate.close();
+	}
+
+}

+ 8 - 0
main/filesystem-api/src/main/java/org/cryptomator/filesystem/package-info.java

@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
 /**
  * Defines a file system abstraction to allow access to real and virtual file
  * systems through a common API.

+ 8 - 0
main/filesystem-api/src/main/java/org/cryptomator/io/ByteBuffers.java

@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
 package org.cryptomator.io;
 
 import java.nio.ByteBuffer;

+ 136 - 0
main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingFileTest.java

@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import java.time.Instant;
+
+import org.cryptomator.filesystem.File;
+import org.cryptomator.filesystem.Folder;
+import org.cryptomator.filesystem.ReadableFile;
+import org.cryptomator.filesystem.WritableFile;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class DelegatingFileTest {
+
+	@Test
+	public void testName() {
+		File mockFile = Mockito.mock(File.class);
+		DelegatingFile delegatingFile = new DelegatingFile(null, mockFile);
+
+		Mockito.when(mockFile.name()).thenReturn("Test");
+		Assert.assertEquals(mockFile.name(), delegatingFile.name());
+	}
+
+	@Test
+	public void testParent() {
+		Folder mockFolder = Mockito.mock(Folder.class);
+		File mockFile = Mockito.mock(File.class);
+
+		DelegatingFolder delegatingParent = new DelegatingFileSystem(mockFolder);
+		DelegatingFile delegatingFile = new DelegatingFile(delegatingParent, mockFile);
+		Assert.assertEquals(delegatingParent, delegatingFile.parent().get());
+	}
+
+	@Test
+	public void testExists() {
+		File mockFile = Mockito.mock(File.class);
+		DelegatingFile delegatingFile = new DelegatingFile(null, mockFile);
+
+		Mockito.when(mockFile.exists()).thenReturn(true);
+		Assert.assertTrue(delegatingFile.exists());
+
+		Mockito.when(mockFile.exists()).thenReturn(false);
+		Assert.assertFalse(delegatingFile.exists());
+	}
+
+	@Test
+	public void testLastModified() {
+		File mockFile = Mockito.mock(File.class);
+		Instant now = Instant.now();
+
+		Mockito.when(mockFile.lastModified()).thenReturn(now);
+		DelegatingFile delegatingFile = new DelegatingFile(null, mockFile);
+		Assert.assertEquals(now, delegatingFile.lastModified());
+	}
+
+	@Test
+	public void testOpenReadable() {
+		File mockFile = Mockito.mock(File.class);
+		ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
+
+		Mockito.when(mockFile.openReadable()).thenReturn(mockReadableFile);
+		DelegatingFile delegatingFile = new DelegatingFile(null, mockFile);
+		Assert.assertNotNull(delegatingFile.openReadable());
+	}
+
+	@Test
+	public void testOpenWritable() {
+		File mockFile = Mockito.mock(File.class);
+		WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
+
+		Mockito.when(mockFile.openWritable()).thenReturn(mockWritableFile);
+		DelegatingFile delegatingFile = new DelegatingFile(null, mockFile);
+		Assert.assertNotNull(delegatingFile.openWritable());
+	}
+
+	@Test
+	public void testMoveTo() {
+		File mockFile1 = Mockito.mock(File.class);
+		File mockFile2 = Mockito.mock(File.class);
+		DelegatingFile delegatingFile1 = new DelegatingFile(null, mockFile1);
+		DelegatingFile delegatingFile2 = new DelegatingFile(null, mockFile2);
+
+		delegatingFile1.moveTo(delegatingFile2);
+		Mockito.verify(mockFile1).moveTo(mockFile2);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testMoveToDestinationFromDifferentLayer() {
+		File mockFile1 = Mockito.mock(File.class);
+		File mockFile2 = Mockito.mock(File.class);
+		DelegatingFile delegatingFile1 = new DelegatingFile(null, mockFile1);
+
+		delegatingFile1.moveTo(mockFile2);
+	}
+
+	@Test
+	public void testCopyTo() {
+		File mockFile1 = Mockito.mock(File.class);
+		File mockFile2 = Mockito.mock(File.class);
+		DelegatingFile delegatingFile1 = new DelegatingFile(null, mockFile1);
+		DelegatingFile delegatingFile2 = new DelegatingFile(null, mockFile2);
+
+		delegatingFile1.copyTo(delegatingFile2);
+		Mockito.verify(mockFile1).copyTo(mockFile2);
+	}
+
+	@Test
+	public void testCopyToDestinationFromDifferentLayer() {
+		File mockFile1 = Mockito.mock(File.class);
+		File mockFile2 = Mockito.mock(File.class);
+		DelegatingFile delegatingFile1 = new DelegatingFile(null, mockFile1);
+
+		delegatingFile1.copyTo(mockFile2);
+		Mockito.verify(mockFile1).copyTo(mockFile2);
+	}
+
+	@Test
+	public void testCompareTo() {
+		File mockFile1 = Mockito.mock(File.class);
+		File mockFile2 = Mockito.mock(File.class);
+
+		Mockito.when(mockFile1.compareTo(mockFile2)).thenReturn(-1);
+		DelegatingFile delegatingFile1 = new DelegatingFile(null, mockFile1);
+		DelegatingFile delegatingFile2 = new DelegatingFile(null, mockFile2);
+		Assert.assertEquals(-1, delegatingFile1.compareTo(delegatingFile2));
+	}
+
+}

+ 163 - 0
main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingFolderTest.java

@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.cryptomator.filesystem.File;
+import org.cryptomator.filesystem.Folder;
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class DelegatingFolderTest {
+
+	@Test
+	public void testName() {
+		Folder mockFolder = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingFolder = new DelegatingFolder(null, mockFolder);
+
+		Mockito.when(mockFolder.name()).thenReturn("Test");
+		Assert.assertEquals(mockFolder.name(), delegatingFolder.name());
+	}
+
+	@Test
+	public void testParent() {
+		Folder mockFolder1 = Mockito.mock(Folder.class);
+		Folder mockFolder2 = Mockito.mock(Folder.class);
+
+		DelegatingFolder delegatingParent = new DelegatingFileSystem(mockFolder1);
+		DelegatingFolder delegatingFolder = new DelegatingFolder(delegatingParent, mockFolder2);
+		Assert.assertEquals(delegatingParent, delegatingFolder.parent().get());
+	}
+
+	@Test
+	public void testExists() {
+		Folder mockFolder = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingFolder = new DelegatingFolder(null, mockFolder);
+
+		Mockito.when(mockFolder.exists()).thenReturn(true);
+		Assert.assertTrue(delegatingFolder.exists());
+
+		Mockito.when(mockFolder.exists()).thenReturn(false);
+		Assert.assertFalse(delegatingFolder.exists());
+	}
+
+	@Test
+	public void testLastModified() {
+		Folder mockFolder = Mockito.mock(Folder.class);
+		Instant now = Instant.now();
+
+		Mockito.when(mockFolder.lastModified()).thenReturn(now);
+		DelegatingFolder delegatingFolder = new DelegatingFolder(null, mockFolder);
+		Assert.assertEquals(now, delegatingFolder.lastModified());
+	}
+
+	@Test
+	public void testChildren() {
+		Folder mockFolder = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingFolder = new DelegatingFolder(null, mockFolder);
+
+		Folder subFolder1 = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingSubFolder1 = new DelegatingFolder(delegatingFolder, subFolder1);
+		File subFile1 = Mockito.mock(File.class);
+		DelegatingFile delegatingSubFile1 = new DelegatingFile(delegatingFolder, subFile1);
+
+		/* folders */
+		Mockito.when(mockFolder.folder("subFolder1")).thenReturn(subFolder1);
+		Assert.assertEquals(delegatingSubFolder1, delegatingFolder.folder("subFolder1"));
+
+		Mockito.<Stream<? extends Folder>>when(mockFolder.folders()).thenAnswer((invocation) -> {
+			return Arrays.stream(new Folder[] {subFolder1});
+		});
+		List<DelegatingFolder> subFolders = delegatingFolder.folders().collect(Collectors.toList());
+		Assert.assertThat(subFolders, Matchers.containsInAnyOrder(delegatingSubFolder1));
+
+		/* files */
+		Mockito.when(mockFolder.file("subFile1")).thenReturn(subFile1);
+		Assert.assertEquals(delegatingSubFile1, delegatingFolder.file("subFile1"));
+
+		Mockito.<Stream<? extends File>>when(mockFolder.files()).thenAnswer((invocation) -> {
+			return Arrays.stream(new File[] {subFile1});
+		});
+		List<DelegatingFile> subFiles = delegatingFolder.files().collect(Collectors.toList());
+		Assert.assertThat(subFiles, Matchers.containsInAnyOrder(delegatingSubFile1));
+
+		/* files and folders */
+		List<DelegatingNode<?>> children = delegatingFolder.children().collect(Collectors.toList());
+		DelegatingNode<?>[] expectedChildren = new DelegatingNode[] {delegatingSubFolder1, delegatingSubFile1};
+		Assert.assertThat(children, Matchers.containsInAnyOrder(expectedChildren));
+
+	}
+
+	@Test
+	public void testMoveTo() {
+		Folder mockFolder1 = Mockito.mock(Folder.class);
+		Folder mockFolder2 = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingFolder1 = new DelegatingFolder(null, mockFolder1);
+		DelegatingFolder delegatingFolder2 = new DelegatingFolder(null, mockFolder2);
+
+		delegatingFolder1.moveTo(delegatingFolder2);
+		Mockito.verify(mockFolder1).moveTo(mockFolder2);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testMoveToDestinationFromDifferentLayer() {
+		Folder mockFolder1 = Mockito.mock(Folder.class);
+		Folder mockFolder2 = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingFolder1 = new DelegatingFolder(null, mockFolder1);
+
+		delegatingFolder1.moveTo(mockFolder2);
+	}
+
+	@Test
+	public void testCopyTo() {
+		Folder mockFolder1 = Mockito.mock(Folder.class);
+		Folder mockFolder2 = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingFolder1 = new DelegatingFolder(null, mockFolder1);
+		DelegatingFolder delegatingFolder2 = new DelegatingFolder(null, mockFolder2);
+
+		delegatingFolder1.copyTo(delegatingFolder2);
+		Mockito.verify(mockFolder1).copyTo(mockFolder2);
+	}
+
+	@Test
+	public void testCopyToDestinationFromDifferentLayer() {
+		Folder mockFolder1 = Mockito.mock(Folder.class);
+		Folder mockFolder2 = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingFolder1 = new DelegatingFolder(null, mockFolder1);
+
+		delegatingFolder1.copyTo(mockFolder2);
+		Mockito.verify(mockFolder1).copyTo(mockFolder2);
+	}
+
+	@Test
+	public void testCreate() {
+		Folder mockFolder = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingFolder = new DelegatingFolder(null, mockFolder);
+
+		delegatingFolder.create();
+		Mockito.verify(mockFolder).create();
+	}
+
+	@Test
+	public void testDelete() {
+		Folder mockFolder = Mockito.mock(Folder.class);
+		DelegatingFolder delegatingFolder = new DelegatingFolder(null, mockFolder);
+
+		delegatingFolder.delete();
+		Mockito.verify(mockFolder).delete();
+	}
+
+}

+ 88 - 0
main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingReadableFileTest.java

@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import java.nio.ByteBuffer;
+
+import org.cryptomator.filesystem.ReadableFile;
+import org.cryptomator.filesystem.WritableFile;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class DelegatingReadableFileTest {
+
+	@Test
+	public void testIsOpen() {
+		ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
+
+		Mockito.when(mockReadableFile.isOpen()).thenReturn(true);
+		Assert.assertTrue(delegatingReadableFile.isOpen());
+
+		Mockito.when(mockReadableFile.isOpen()).thenReturn(false);
+		Assert.assertFalse(delegatingReadableFile.isOpen());
+	}
+
+	@Test
+	public void testCopyTo() {
+		ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
+		WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
+		DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
+
+		delegatingReadableFile.copyTo(delegatingWritableFile);
+		Mockito.verify(mockReadableFile).copyTo(mockWritableFile);
+	}
+
+	@Test
+	public void testCopyToDestinationFromDifferentLayer() {
+		ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
+		WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
+
+		delegatingReadableFile.copyTo(mockWritableFile);
+		Mockito.verify(mockReadableFile).copyTo(mockWritableFile);
+	}
+
+	@Test
+	public void testRead() {
+		ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
+
+		ByteBuffer buf = ByteBuffer.allocate(4);
+		Mockito.when(mockReadableFile.read(buf)).thenReturn(4);
+		Assert.assertEquals(4, delegatingReadableFile.read(buf));
+		Mockito.verify(mockReadableFile).read(buf);
+	}
+
+	@Test
+	public void testPosition() {
+		ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
+
+		delegatingReadableFile.position(42);
+		Mockito.verify(mockReadableFile).position(42);
+	}
+
+	@Test
+	public void testClose() {
+		ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
+		DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
+
+		delegatingReadableFile.close();
+		Mockito.verify(mockReadableFile).close();
+	}
+
+}

+ 119 - 0
main/filesystem-api/src/test/java/org/cryptomator/filesystem/delegating/DelegatingWritableFileTest.java

@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
+package org.cryptomator.filesystem.delegating;
+
+import java.nio.ByteBuffer;
+import java.time.Instant;
+
+import org.cryptomator.filesystem.ReadableFile;
+import org.cryptomator.filesystem.WritableFile;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class DelegatingWritableFileTest {
+
+	@Test
+	public void testIsOpen() {
+		WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
+
+		Mockito.when(mockWritableFile.isOpen()).thenReturn(true);
+		Assert.assertTrue(delegatingWritableFile.isOpen());
+
+		Mockito.when(mockWritableFile.isOpen()).thenReturn(false);
+		Assert.assertFalse(delegatingWritableFile.isOpen());
+	}
+
+	@Test
+	public void testMoveTo() {
+		WritableFile mockWritableFile1 = Mockito.mock(WritableFile.class);
+		WritableFile mockWritableFile2 = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingWritableFile delegatingWritableFile1 = new DelegatingWritableFile(mockWritableFile1);
+		DelegatingWritableFile delegatingWritableFile2 = new DelegatingWritableFile(mockWritableFile2);
+
+		delegatingWritableFile1.moveTo(delegatingWritableFile2);
+		Mockito.verify(mockWritableFile1).moveTo(mockWritableFile2);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testMoveToDestinationFromDifferentLayer() {
+		WritableFile mockWritableFile1 = Mockito.mock(WritableFile.class);
+		WritableFile mockWritableFile2 = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingWritableFile delegatingWritableFile1 = new DelegatingWritableFile(mockWritableFile1);
+
+		delegatingWritableFile1.moveTo(mockWritableFile2);
+	}
+
+	@Test
+	public void testSetLastModified() {
+		WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
+
+		Instant now = Instant.now();
+		delegatingWritableFile.setLastModified(now);
+		Mockito.verify(mockWritableFile).setLastModified(now);
+	}
+
+	@Test
+	public void testDelete() {
+		WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
+
+		delegatingWritableFile.delete();
+		Mockito.verify(mockWritableFile).delete();
+	}
+
+	@Test
+	public void testTruncate() {
+		WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
+
+		delegatingWritableFile.truncate();
+		Mockito.verify(mockWritableFile).truncate();
+	}
+
+	@Test
+	public void testWrite() {
+		WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
+
+		ByteBuffer buf = ByteBuffer.allocate(4);
+		Mockito.when(mockWritableFile.write(buf)).thenReturn(4);
+		Assert.assertEquals(4, delegatingWritableFile.write(buf));
+		Mockito.verify(mockWritableFile).write(buf);
+	}
+
+	@Test
+	public void testPosition() {
+		WritableFile mockWritableFile = Mockito.mock(WritableFile.class);
+		@SuppressWarnings("resource")
+		DelegatingWritableFile delegatingWritableFile = new DelegatingWritableFile(mockWritableFile);
+
+		delegatingWritableFile.position(42);
+		Mockito.verify(mockWritableFile).position(42);
+	}
+
+	@Test
+	public void testClose() {
+		ReadableFile mockReadableFile = Mockito.mock(ReadableFile.class);
+		DelegatingReadableFile delegatingReadableFile = new DelegatingReadableFile(mockReadableFile);
+
+		delegatingReadableFile.close();
+		Mockito.verify(mockReadableFile).close();
+	}
+
+}

+ 8 - 0
main/filesystem-api/src/test/java/org/cryptomator/io/ByteBuffersTest.java

@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Sebastian Stenzel and others.
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *******************************************************************************/
 package org.cryptomator.io;
 
 import java.nio.ByteBuffer;