diff --git a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt index ab540fd1..de8f7d7d 100644 --- a/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/AbstractNavigation.kt @@ -635,6 +635,16 @@ abstract class AbstractNavigation( return ref } + @Throws(QblStorageException::class) + override fun rename(boxFile: BoxFile, name: String): BoxFile { + TODO() + } + + @Throws(QblStorageException::class) + override fun rename(boxFolder: BoxFolder, name: String): BoxFolder { + TODO() + } + @Throws(QblStorageException::class) override fun getSharesOf(boxObject: BoxObject): List { return indexNavigation.listShares().filter({ share -> share.ref == boxObject.ref }).toList() diff --git a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt index bf638c23..ab3556e4 100644 --- a/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt +++ b/box/src/main/java/de/qabel/box/storage/BoxNavigation.kt @@ -175,6 +175,12 @@ interface BoxNavigation : ReadableBoxNavigation { @Throws(QblStorageException::class) fun delete(folder: BoxFolder) + @Throws(QblStorageException::class) + fun rename(boxFile: BoxFile, name: String): BoxFile + + @Throws(QblStorageException::class) + fun rename(boxFolder: BoxFolder, name: String): BoxFolder + /** * Remove a share mount from the current folder */ diff --git a/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt b/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt index e2252785..2494b0d9 100644 --- a/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt +++ b/box/src/test/java/de/qabel/box/storage/AbstractNavigationTest.kt @@ -3,17 +3,16 @@ package de.qabel.box.storage import com.natpryce.hamkrest.assertion.assertThat import com.natpryce.hamkrest.equalTo import com.natpryce.hamkrest.hasSize -import de.qabel.box.storage.command.DeleteFileChange -import de.qabel.box.storage.command.ShareChange -import de.qabel.box.storage.command.UnshareChange -import de.qabel.box.storage.command.UpdateFileChange +import de.qabel.box.storage.command.* import de.qabel.box.storage.dto.DMChangeEvent +import de.qabel.box.storage.exceptions.QblStorageNameConflict import de.qabel.box.storage.hash.QabelBoxDigestProvider import de.qabel.box.storage.jdbc.JdbcDirectoryMetadataFactory import de.qabel.core.config.Prefix import de.qabel.core.crypto.CryptoUtils import de.qabel.core.crypto.QblECKeyPair import de.qabel.core.extensions.letApply +import org.amshove.kluent.shouldThrow import org.junit.Assert.* import org.junit.Before import org.junit.Test @@ -23,6 +22,7 @@ import java.io.* import java.security.Security import java.util.* + abstract class AbstractNavigationTest { init { Security.addProvider(QabelBoxDigestProvider()) @@ -48,6 +48,9 @@ abstract class AbstractNavigationTest { abstract val nav: AbstractNavigation var subscriber = TestSubscriber() + val filename = "testfile" + val folderName = "testfolder" + @Before open fun setUp() { nav.changes.subscribe(subscriber) @@ -108,22 +111,24 @@ abstract class AbstractNavigationTest { nav.changes.subscribe(subscriber) } - fun assertChange(clazz: Class, block: T.() -> Unit) : T { + inline fun > assertChange(clazz: Class, block: T.() -> Unit) : DMChange<*> { val changes = subscriber.onNextEvents assertThat("no event happend, but expecting one", changes, hasSize(equalTo(1))) val change = changes.first().change - if (!clazz.isInstance(change)) { + val castedChange = change as? T + if (castedChange == null) { fail(change.toString() + " is not of type " + clazz.name) + } else { + block(castedChange) } - block(change as T) return change } @Test fun catchesDMConflictsWhileUploadingDm() { nav.setAutocommit(false) - nav.upload("testfile", "content".byteInputStream(), 7L) + upload(filename) val cPath = setupConflictingDM() { it.insertFile(someFile("anotherFile")) } var dmWasUploaded = false @@ -144,11 +149,49 @@ abstract class AbstractNavigationTest { nav.commit() - assertTrue(nav.hasFile("testfile")) + assertTrue(nav.hasFile(filename)) assertTrue(nav.hasFile("anotherFile")) assertTrue(dmWasUploaded) } + @Test fun `can rename a file without a conflict`() { + val newName = "newName" + upload(filename).let { + nav.rename(it, newName) + assertTrue(nav.hasFile(newName)) + assertFalse(nav.hasFile(filename)) + } + } + + @Test fun `can rename a folder without a conflict`() { + val newName = "newName" + nav.createFolder(folderName).let { + nav.rename(it, newName) + assertTrue(nav.hasFolder(newName)) + assertFalse(nav.hasFolder(folderName)) + } + } + + @Test fun `can't rename a folder to an existing name`() { + val newName = "newName" + nav.createFolder(newName) + upload(filename) + nav.createFolder(folderName).let { + { nav.rename(it, newName) } shouldThrow QblStorageNameConflict::class + { nav.rename(it, filename) } shouldThrow QblStorageNameConflict::class + } + } + + @Test fun `can't rename a file to an existing folder name`() { + val newName = "testfile2" + nav.createFolder(folderName) + upload(newName) + upload(filename).let { + { nav.rename(it, folderName) } shouldThrow QblStorageNameConflict::class + { nav.rename(it, newName) } shouldThrow QblStorageNameConflict::class + } + } + private fun setupConflictingDM(action: ((DirectoryMetadata) -> Unit)? = null): File { val conflictingDM = dmFactory.create() action?.invoke(conflictingDM) diff --git a/build.gradle b/build.gradle index 8dd2f29c..645c0521 100644 --- a/build.gradle +++ b/build.gradle @@ -46,6 +46,7 @@ subprojects { testCompile 'org.meanbean:meanbean:2.+' testCompile 'org.mockito:mockito-core:2.0.52-beta' testCompile 'com.nhaarman:mockito-kotlin:0.6.0' + testCompile 'org.amshove.kluent:kluent:1.13' compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" }