From 806e366a72638e8f26e92bba82a91c1eaad99a39 Mon Sep 17 00:00:00 2001 From: Markus Kreusch Date: Wed, 30 Dec 2015 20:53:27 +0100 Subject: [PATCH] Added test for Copier * Created Test covering all lines and mutations * Added HierachicalContextRunner dependency to allow more structured tests --- main/commons-test/pom.xml | 4 + .../org/cryptomator/filesystem/Copier.java | 14 +- .../cryptomator/filesystem/CopierTest.java | 173 ++++++++++++++++++ main/pom.xml | 6 + 4 files changed, 190 insertions(+), 7 deletions(-) create mode 100644 main/filesystem-api/src/test/java/org/cryptomator/filesystem/CopierTest.java diff --git a/main/commons-test/pom.xml b/main/commons-test/pom.xml index c8ff86ead..bba69fa84 100644 --- a/main/commons-test/pom.xml +++ b/main/commons-test/pom.xml @@ -18,6 +18,10 @@ junit junit + + de.bechte.junit + junit-hierarchicalcontextrunner + org.hamcrest hamcrest-all diff --git a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Copier.java b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Copier.java index 442124889..ff790d73d 100644 --- a/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Copier.java +++ b/main/filesystem-api/src/main/java/org/cryptomator/filesystem/Copier.java @@ -18,7 +18,7 @@ class Copier { source.files().forEach(sourceFile -> { File destinationFile = destination.file(sourceFile.name()); - copy(sourceFile, destinationFile); + sourceFile.copyTo(destinationFile); }); source.folders().forEach(sourceFolder -> { @@ -27,6 +27,12 @@ class Copier { }); } + public static void copy(File source, File destination) { + try (OpenFiles openFiles = DeadlockSafeFileOpener.withReadable(source).andWritable(destination).open()) { + openFiles.readable(source).copyTo(openFiles.writable(destination)); + } + } + private static void assertFoldersAreNotNested(Folder source, Folder destination) { if (source.isAncestorOf(destination)) { throw new IllegalArgumentException("Can not copy parent to child directory (src: " + source + ", dst: " + destination + ")"); @@ -36,10 +42,4 @@ class Copier { } } - public static void copy(File source, File destination) { - try (OpenFiles openFiles = DeadlockSafeFileOpener.withReadable(source).andWritable(destination).open()) { - openFiles.readable(source).copyTo(openFiles.writable(destination)); - } - } - } diff --git a/main/filesystem-api/src/test/java/org/cryptomator/filesystem/CopierTest.java b/main/filesystem-api/src/test/java/org/cryptomator/filesystem/CopierTest.java new file mode 100644 index 000000000..d32d1d231 --- /dev/null +++ b/main/filesystem-api/src/test/java/org/cryptomator/filesystem/CopierTest.java @@ -0,0 +1,173 @@ +package org.cryptomator.filesystem; + +import static java.util.Arrays.asList; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.stream.Stream; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import de.bechte.junit.runners.context.HierarchicalContextRunner; + +@RunWith(HierarchicalContextRunner.class) +public class CopierTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + + public class CopyFiles { + + @Mock + private File source; + + @Mock + private File destination; + + @Test + public void testCopyFileOpensFilesInSortedOrderIfSourceIsSmallerDestination() { + mockCompareToWithOrder(source, destination); + when(source.openReadable()).thenReturn(mock(ReadableFile.class)); + when(destination.openWritable()).thenReturn(mock(WritableFile.class)); + + Copier.copy(source, destination); + + InOrder inOrder = inOrder(source, destination); + inOrder.verify(source).openReadable(); + inOrder.verify(destination).openWritable(); + } + + @Test + public void testCopyFileOpensFilesInSortedOrderIfDestinationIsSmallerSource() { + mockCompareToWithOrder(destination, source); + when(source.openReadable()).thenReturn(mock(ReadableFile.class)); + when(destination.openWritable()).thenReturn(mock(WritableFile.class)); + + Copier.copy(source, destination); + + InOrder inOrder = inOrder(source, destination); + inOrder.verify(destination).openWritable(); + inOrder.verify(source).openReadable(); + } + + @Test + public void testCopyFileInvokesCopyToOnReadableSourceWithWritableDestintation() { + ReadableFile readableSource = mock(ReadableFile.class); + WritableFile writableDestination = mock(WritableFile.class); + mockCompareToWithOrder(source, destination); + when(source.openReadable()).thenReturn(readableSource); + when(destination.openWritable()).thenReturn(writableDestination); + + Copier.copy(source, destination); + + verify(readableSource).copyTo(writableDestination); + } + + private void mockCompareToWithOrder(File first, File last) { + when(first.compareTo(last)).thenReturn(-1); + when(last.compareTo(first)).thenReturn(1); + } + + } + + public class CopyFolders { + + @Mock + private Folder source; + + @Mock + private Folder destination; + + @Test + public void testCopyFolderDeletesAndCreatesDestinationBeforeIteratingOverTheFilesAndFoldersInSource() { + when(source.files()).thenReturn(Stream.empty()); + when(source.folders()).thenReturn(Stream.empty()); + + Copier.copy(source, destination); + + InOrder inOrder = inOrder(source, destination); + inOrder.verify(destination).delete(); + inOrder.verify(destination).create(); + inOrder.verify(source).files(); + inOrder.verify(source).folders(); + } + + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testCopyFolderInvokesCopyToOnAllFilesInSourceWithFileWithSameNameFromDestination() { + String filename1 = "nameOfFile1"; + String filename2 = "nameOfFile2"; + File file1 = mock(File.class); + File file2 = mock(File.class); + File destinationFile1 = mock(File.class); + File destinationFile2 = mock(File.class); + when(source.files()).thenReturn((Stream) asList(file1, file2).stream()); + when(source.folders()).thenReturn(Stream.empty()); + when(destination.file(filename1)).thenReturn(destinationFile1); + when(destination.file(filename2)).thenReturn(destinationFile2); + when(file1.name()).thenReturn(filename1); + when(file2.name()).thenReturn(filename2); + + Copier.copy(source, destination); + + verify(file1).copyTo(destinationFile1); + verify(file2).copyTo(destinationFile2); + } + + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testCopyFolderInvokesCopyToOnAllFoldersInSourceWithFolderWithSameNameFromDestination() { + String folderName1 = "nameOfFolder1"; + String folderName2 = "nameOfFolder2"; + Folder folder1 = mock(Folder.class); + Folder folder2 = mock(Folder.class); + Folder destinationfolder1 = mock(Folder.class); + Folder destinationfolder2 = mock(Folder.class); + when(source.folders()).thenReturn((Stream) asList(folder1, folder2).stream()); + when(source.files()).thenReturn(Stream.empty()); + when(destination.folder(folderName1)).thenReturn(destinationfolder1); + when(destination.folder(folderName2)).thenReturn(destinationfolder2); + when(folder1.name()).thenReturn(folderName1); + when(folder2.name()).thenReturn(folderName2); + + Copier.copy(source, destination); + + verify(folder1).copyTo(destinationfolder1); + verify(folder2).copyTo(destinationfolder2); + } + + @Test + public void testCopyFolderFailsWithIllegalArgumentExceptionIfSourceIsNestedInDestination() { + when(source.isAncestorOf(destination)).thenReturn(false); + when(destination.isAncestorOf(source)).thenReturn(true); + + thrown.expect(IllegalArgumentException.class); + + Copier.copy(source, destination); + } + + @Test + public void testCopyFolderFailsWithIllegalArgumentExceptionIfDestinationIsNestedInSource() { + when(source.isAncestorOf(destination)).thenReturn(true); + when(destination.isAncestorOf(source)).thenReturn(false); + + thrown.expect(IllegalArgumentException.class); + + Copier.copy(source, destination); + } + + } + +} diff --git a/main/pom.xml b/main/pom.xml index db046a3de..6b8ad2b48 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -31,6 +31,7 @@ 2.1 1.7.7 4.12 + 4.12.1 1.3 2.4 4.0 @@ -197,6 +198,11 @@ + + de.bechte.junit + junit-hierarchicalcontextrunner + ${junit.hierarchicalrunner.version} + org.mockito mockito-core