diff --git a/app/src/androidTest/java/com/orgzly/android/repos/DocumentRepoTest.kt b/app/src/androidTest/java/com/orgzly/android/repos/DocumentRepoTest.kt index 31c62e669..94c936d3a 100644 --- a/app/src/androidTest/java/com/orgzly/android/repos/DocumentRepoTest.kt +++ b/app/src/androidTest/java/com/orgzly/android/repos/DocumentRepoTest.kt @@ -16,20 +16,26 @@ import com.orgzly.R import com.orgzly.android.OrgzlyTest import com.orgzly.android.db.entity.Repo import com.orgzly.android.espresso.util.EspressoUtils +import com.orgzly.android.repos.SyncRepoTest.Companion.repoDirName +import com.orgzly.android.repos.SyncRepoTest.Companion.treeDocumentFileExtraSegment import com.orgzly.android.ui.repos.ReposActivity +import com.orgzly.android.util.MiscUtils import org.hamcrest.core.AllOf import org.junit.After import org.junit.Assert import org.junit.Before -import org.junit.Test -import java.io.IOException +import kotlin.io.path.Path class DocumentRepoTest : SyncRepoTest, OrgzlyTest() { - private lateinit var documentTreeSegment: String private lateinit var repo: Repo - private lateinit var syncRepo: SyncRepo private lateinit var repoDirectory: DocumentFile + private lateinit var mSyncRepo: SyncRepo + private var treeDocumentFileUrl = if (Build.VERSION.SDK_INT < 30) { + "content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2F$repoDirName" + } else { + "content://com.android.externalstorage.documents/tree/primary%3A$repoDirName" + } @Before override fun setUp() { @@ -45,138 +51,33 @@ class DocumentRepoTest : SyncRepoTest, OrgzlyTest() { } } - @Test - override fun testGetBooks_singleOrgFile() { - SyncRepoTest.testGetBooks_singleOrgFile(repoDirectory, syncRepo) - } - - @Test - override fun testGetBooks_singleFileInSubfolderWhenEnabled() { - SyncRepoTest.testGetBooks_singleFileInSubfolderWhenEnabled(repoDirectory, syncRepo) - } - - @Test - override fun testGetBooks_singleFileInSubfolderWhenDisabled() { - SyncRepoTest.testGetBooks_singleFileInSubfolderWhenDisabled(repoDirectory, syncRepo) - } - - @Test - override fun testGetBooks_allFilesAreIgnored() { - SyncRepoTest.testGetBooks_allFilesAreIgnored(repoDirectory, syncRepo) - } - - @Test - override fun testGetBooks_specificFileInSubfolderIsIgnored() { - SyncRepoTest.testGetBooks_specificFileInSubfolderIsIgnored(repoDirectory, syncRepo) - } - - @Test - override fun testGetBooks_specificFileIsUnignored() { - SyncRepoTest.testGetBooks_specificFileIsUnignored(repoDirectory, syncRepo) - } - - @Test - override fun testGetBooks_ignoredExtensions() { - SyncRepoTest.testGetBooks_ignoredExtensions(repoDirectory, syncRepo) - } - - @Test - override fun testStoreBook_expectedUri() { - SyncRepoTest.testStoreBook_expectedUri(syncRepo) - } - - @Test - override fun testStoreBook_producesSameUriAsRetrieveBookWithSubfolder() { - SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithSubfolder(syncRepo) - } - - @Test - override fun testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder() { - SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder(syncRepo) - } - - @Test - override fun testStoreBook_producesSameUriAsGetBooks() { - SyncRepoTest.testStoreBook_producesSameUriAsGetBooks(repoDirectory, syncRepo) - } - - @Test - override fun testStoreBook_inSubfolder() { - SyncRepoTest.testStoreBook_inSubfolder(repoDirectory, syncRepo) - } - - @Test(expected = IOException::class) - override fun testStoreBook_inSubfolderWhenDisabled() { - SyncRepoTest.testStoreBook_inSubfolderWhenDisabled(syncRepo) - } - - @Test - override fun testRenameBook_expectedUri() { - SyncRepoTest.testRenameBook_expectedUri(syncRepo) - } - - @Test(expected = IOException::class) - override fun testRenameBook_repoFileAlreadyExists() { - SyncRepoTest.testRenameBook_repoFileAlreadyExists(repoDirectory, syncRepo) - } - - @Test - override fun testRenameBook_fromRootToSubfolderWhenEnabled() { - SyncRepoTest.testRenameBook_fromRootToSubfolderWhenEnabled(syncRepo) - } - - @Test(expected = IOException::class) - override fun testRenameBook_fromRootToSubfolderWhenDisabled() { - SyncRepoTest.testRenameBook_fromRootToSubfolderWhenDisabled(syncRepo) - } - - @Test - override fun testRenameBook_fromSubfolderToRoot() { - SyncRepoTest.testRenameBook_fromSubfolderToRoot(syncRepo) - } - - @Test - override fun testRenameBook_newSubfolderSameLeafName() { - SyncRepoTest.testRenameBook_newSubfolderSameLeafName(syncRepo) - } - - @Test - override fun testRenameBook_newSubfolderAndLeafName() { - SyncRepoTest.testRenameBook_newSubfolderAndLeafName(syncRepo) - } + override var syncRepo: SyncRepo + get() = mSyncRepo + set(value) {} + override val repoManipulationPoint: Any + get() = repoDirectory - @Test - override fun testRenameBook_sameSubfolderNewLeafName() { - SyncRepoTest.testRenameBook_sameSubfolderNewLeafName(syncRepo) + override fun writeFileToRepo(content: String, repoRelativePath: String): String { + val targetPath = Path(repoRelativePath) + var expectedRookUri = mSyncRepo.uri.toString() + treeDocumentFileExtraSegment + Uri.encode(repoRelativePath) + var targetDir = repoDirectory + if (repoRelativePath.contains("/")) { + targetDir = targetDir.createDirectory(targetPath.parent.toString())!! + expectedRookUri = mSyncRepo.uri.toString() + treeDocumentFileExtraSegment + Uri.encode(repoRelativePath) + } + MiscUtils.writeStringToDocumentFile(content, targetPath.fileName.toString(), targetDir.uri) + return expectedRookUri } - private fun setupDocumentRepo(extraDir: String? = null) { - val repoDirName = SyncRepoTest.repoDirName - documentTreeSegment = if (Build.VERSION.SDK_INT < 30) { - "/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2F$repoDirName%2F" - } else { - "/document/primary%3A$repoDirName%2F" - } - var treeDocumentFileUrl = if (Build.VERSION.SDK_INT < 30) { - "content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2F$repoDirName" - } else { - "content://com.android.externalstorage.documents/tree/primary%3A$repoDirName" - } - if (extraDir != null) { - treeDocumentFileUrl = "$treeDocumentFileUrl%2F" + Uri.encode(extraDir) - } + private fun setupDocumentRepo() { repoDirectory = DocumentFile.fromTreeUri(context, treeDocumentFileUrl.toUri())!! repo = if (!repoDirectory.exists()) { - if (extraDir != null) { - setupDocumentRepoInUi(extraDir) - } else { - setupDocumentRepoInUi(repoDirName) - } + setupDocumentRepoInUi() dataRepository.getRepos()[0] } else { testUtils.setupRepo(RepoType.DOCUMENT, treeDocumentFileUrl) } - syncRepo = testUtils.repoInstance(RepoType.DOCUMENT, repo.url, repo.id) + mSyncRepo = testUtils.repoInstance(RepoType.DOCUMENT, repo.url, repo.id) Assert.assertEquals(treeDocumentFileUrl, repo.url) } @@ -186,7 +87,7 @@ class DocumentRepoTest : SyncRepoTest, OrgzlyTest() { * a different repo URL, making some tests fail. If you are running locally, you must work * around this by wiping the device's data between test suite runs. */ - private fun setupDocumentRepoInUi(repoDirName: String) { + private fun setupDocumentRepoInUi() { ActivityScenario.launch(ReposActivity::class.java).use { Espresso.onView(ViewMatchers.withId(R.id.activity_repos_directory)) .perform(ViewActions.click()) @@ -220,4 +121,4 @@ class DocumentRepoTest : SyncRepoTest, OrgzlyTest() { .perform(ViewActions.click()) } } -} \ No newline at end of file +} diff --git a/app/src/test/java/com/orgzly/android/repos/DropboxRepoTest.kt b/app/src/test/java/com/orgzly/android/repos/DropboxRepoTest.kt index f88f89495..ed7212d52 100644 --- a/app/src/test/java/com/orgzly/android/repos/DropboxRepoTest.kt +++ b/app/src/test/java/com/orgzly/android/repos/DropboxRepoTest.kt @@ -1,24 +1,41 @@ package com.orgzly.android.repos +import android.net.Uri import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.orgzly.BuildConfig import com.orgzly.android.db.entity.Repo import com.orgzly.android.prefs.AppPreferences +import com.orgzly.android.repos.SyncRepoTest.Companion.repoDirName +import com.orgzly.android.util.MiscUtils import org.json.JSONObject import org.junit.After import org.junit.Assume.assumeTrue import org.junit.Before -import org.junit.Test import org.junit.runner.RunWith -import java.io.IOException import java.util.UUID @RunWith(AndroidJUnit4::class) class DropboxRepoTest : SyncRepoTest { - private lateinit var syncRepo: SyncRepo private lateinit var client: DropboxClient + private lateinit var mSyncRepo: SyncRepo + + override var syncRepo: SyncRepo + get() = mSyncRepo + set(value) {} + + override val repoManipulationPoint: Any + get() = client + + override fun writeFileToRepo(content: String, repoRelativePath: String): String { + val tmpFile = kotlin.io.path.createTempFile().toFile() + MiscUtils.writeStringToFile(content, tmpFile) + val expectedRookUri = mSyncRepo.uri.toString() + "/" + Uri.encode(repoRelativePath, "/") + client.upload(tmpFile, mSyncRepo.uri, repoRelativePath) + tmpFile.delete() + return expectedRookUri + } @Before fun setup() { @@ -33,123 +50,18 @@ class DropboxRepoTest : SyncRepoTest { ApplicationProvider.getApplicationContext(), mockSerializedDbxCredential.toString() ) - val repo = Repo(0, RepoType.DROPBOX, "dropbox:/${SyncRepoTest.repoDirName}/" + UUID.randomUUID().toString()) + val repo = Repo(0, RepoType.DROPBOX, "dropbox:/$repoDirName/" + UUID.randomUUID().toString()) val repoPropsMap = HashMap() val repoWithProps = RepoWithProps(repo, repoPropsMap) - syncRepo = DropboxRepo(repoWithProps, ApplicationProvider.getApplicationContext()) + mSyncRepo = DropboxRepo(repoWithProps, ApplicationProvider.getApplicationContext()) client = DropboxClient(ApplicationProvider.getApplicationContext(), repo.id) } @After fun tearDown() { - if (this::syncRepo.isInitialized) { - val dropboxRepo = syncRepo as DropboxRepo - dropboxRepo.deleteDirectory(syncRepo.uri) + if (this::mSyncRepo.isInitialized) { + val dropboxRepo = mSyncRepo as DropboxRepo + dropboxRepo.deleteDirectory(mSyncRepo.uri) } } - - @Test - override fun testGetBooks_singleOrgFile() { - SyncRepoTest.testGetBooks_singleOrgFile(client, syncRepo) - } - - @Test - override fun testGetBooks_singleFileInSubfolderWhenEnabled() { - SyncRepoTest.testGetBooks_singleFileInSubfolderWhenEnabled(client, syncRepo) - } - - @Test - override fun testGetBooks_singleFileInSubfolderWhenDisabled() { - SyncRepoTest.testGetBooks_singleFileInSubfolderWhenDisabled(client, syncRepo) - } - - @Test - override fun testGetBooks_allFilesAreIgnored() { - SyncRepoTest.testGetBooks_allFilesAreIgnored(client, syncRepo) - } - - @Test - override fun testGetBooks_specificFileInSubfolderIsIgnored() { - SyncRepoTest.testGetBooks_specificFileInSubfolderIsIgnored(client, syncRepo) - } - - @Test - override fun testGetBooks_specificFileIsUnignored() { - SyncRepoTest.testGetBooks_specificFileIsUnignored(client, syncRepo) - } - - @Test - override fun testGetBooks_ignoredExtensions() { - SyncRepoTest.testGetBooks_ignoredExtensions(client, syncRepo) - } - - @Test - override fun testStoreBook_expectedUri() { - SyncRepoTest.testStoreBook_expectedUri(syncRepo) - } - - @Test - override fun testStoreBook_producesSameUriAsRetrieveBookWithSubfolder() { - SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithSubfolder(syncRepo) - } - - @Test - override fun testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder() { - SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder(syncRepo) - } - - @Test - override fun testStoreBook_producesSameUriAsGetBooks() { - SyncRepoTest.testStoreBook_producesSameUriAsGetBooks(client, syncRepo) - } - - @Test - override fun testStoreBook_inSubfolder() { - SyncRepoTest.testStoreBook_inSubfolder(client, syncRepo) - } - - @Test(expected = IOException::class) - override fun testStoreBook_inSubfolderWhenDisabled() { - SyncRepoTest.testStoreBook_inSubfolderWhenDisabled(syncRepo) - } - - @Test - override fun testRenameBook_expectedUri() { - SyncRepoTest.testRenameBook_expectedUri(syncRepo) - } - - @Test(expected = IOException::class) - override fun testRenameBook_repoFileAlreadyExists() { - SyncRepoTest.testRenameBook_repoFileAlreadyExists(client, syncRepo) - } - - @Test - override fun testRenameBook_fromRootToSubfolderWhenEnabled() { - SyncRepoTest.testRenameBook_fromRootToSubfolderWhenEnabled(syncRepo) - } - - @Test(expected = IOException::class) - override fun testRenameBook_fromRootToSubfolderWhenDisabled() { - SyncRepoTest.testRenameBook_fromRootToSubfolderWhenDisabled(syncRepo) - } - - @Test - override fun testRenameBook_fromSubfolderToRoot() { - SyncRepoTest.testRenameBook_fromSubfolderToRoot(syncRepo) - } - - @Test - override fun testRenameBook_newSubfolderSameLeafName() { - SyncRepoTest.testRenameBook_newSubfolderSameLeafName(syncRepo) - } - - @Test - override fun testRenameBook_newSubfolderAndLeafName() { - SyncRepoTest.testRenameBook_newSubfolderAndLeafName(syncRepo) - } - - @Test - override fun testRenameBook_sameSubfolderNewLeafName() { - SyncRepoTest.testRenameBook_sameSubfolderNewLeafName(syncRepo) - } } diff --git a/app/src/test/java/com/orgzly/android/repos/GitRepoTest.kt b/app/src/test/java/com/orgzly/android/repos/GitRepoTest.kt index ac286a299..207aee9e0 100644 --- a/app/src/test/java/com/orgzly/android/repos/GitRepoTest.kt +++ b/app/src/test/java/com/orgzly/android/repos/GitRepoTest.kt @@ -1,157 +1,136 @@ package com.orgzly.android.repos import android.content.Context +import android.net.Uri import androidx.core.net.toUri import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.orgzly.android.db.entity.Repo +import com.orgzly.android.LocalStorage +import com.orgzly.android.TestUtils +import com.orgzly.android.data.DataRepository +import com.orgzly.android.data.DbRepoBookRepository +import com.orgzly.android.db.OrgzlyDatabase +import com.orgzly.android.db.entity.BookAction import com.orgzly.android.git.GitFileSynchronizer import com.orgzly.android.git.GitPreferencesFromRepoPrefs import com.orgzly.android.prefs.AppPreferences import com.orgzly.android.prefs.RepoPreferences +import com.orgzly.android.util.MiscUtils +import org.eclipse.jgit.api.CloneCommand import org.eclipse.jgit.api.Git import org.junit.After +import org.junit.Assert import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import java.io.File -import java.io.IOException +import java.nio.file.Files import kotlin.io.path.createTempDirectory @RunWith(AndroidJUnit4::class) class GitRepoTest : SyncRepoTest { - private lateinit var gitWorkingTree: File + private lateinit var workingCloneDir: File + private lateinit var workingClone: Git private lateinit var bareRepoDir: File private lateinit var gitFileSynchronizer: GitFileSynchronizer - private lateinit var syncRepo: SyncRepo - private val context: Context = ApplicationProvider.getApplicationContext() + private lateinit var dataRepository: DataRepository + private lateinit var testUtils: TestUtils + private lateinit var gitPreferences: GitPreferencesFromRepoPrefs + private lateinit var mSyncRepo: SyncRepo @Before fun setup() { + // Setup TestUtils + val context: Context = ApplicationProvider.getApplicationContext() + val database = OrgzlyDatabase.forFile(context, OrgzlyDatabase.NAME_FOR_TESTS) + val dbRepoBookRepository = DbRepoBookRepository(database) + val localStorage = LocalStorage(context) + val repoFactory = RepoFactory(context, dbRepoBookRepository) + dataRepository = DataRepository( + context, database, repoFactory, context.resources, localStorage + ) + testUtils = TestUtils(dataRepository, dbRepoBookRepository) + dataRepository.clearDatabase() + // Setup repo bareRepoDir = createTempDirectory().toFile() Git.init().setBare(true).setDirectory(bareRepoDir).call() AppPreferences.gitIsEnabled(context, true) - val repo = Repo(0, RepoType.GIT, "file://$bareRepoDir") + val repo = testUtils.setupRepo(RepoType.GIT, "file://$bareRepoDir") val repoPreferences = RepoPreferences(context, repo.id, repo.url.toUri()) - val gitPreferences = GitPreferencesFromRepoPrefs(repoPreferences) - gitWorkingTree = File(gitPreferences.repositoryFilepath()) - gitWorkingTree.mkdirs() - val git = GitRepo.ensureRepositoryExists(gitPreferences, true, null) - gitFileSynchronizer = GitFileSynchronizer(git, gitPreferences) + gitPreferences = GitPreferencesFromRepoPrefs(repoPreferences) + val orgzlyCloneDir = File(gitPreferences.repositoryFilepath()) + orgzlyCloneDir.mkdirs() + val orgzlyRepoClone = GitRepo.ensureRepositoryExists(gitPreferences, true, null) + gitFileSynchronizer = GitFileSynchronizer(orgzlyRepoClone, gitPreferences) val repoPropsMap = HashMap() val repoWithProps = RepoWithProps(repo, repoPropsMap) - syncRepo = GitRepo.getInstance(repoWithProps, context) + mSyncRepo = GitRepo.getInstance(repoWithProps, context) + // Setup working clone + workingCloneDir = Files.createTempDirectory("orgzlytest").toFile() + workingClone = CloneCommand().setURI(syncRepo.uri.toString()).setDirectory(workingCloneDir).call() } @After fun tearDown() { - gitWorkingTree.deleteRecursively() + if (this::workingCloneDir.isInitialized) + workingCloneDir.deleteRecursively() bareRepoDir.deleteRecursively() } - @Test - override fun testGetBooks_singleOrgFile() { - SyncRepoTest.testGetBooks_singleOrgFile(gitWorkingTree, syncRepo) - } - - @Test - override fun testGetBooks_singleFileInSubfolderWhenEnabled() { - SyncRepoTest.testGetBooks_singleFileInSubfolderWhenEnabled(gitWorkingTree, syncRepo) - } - - @Test - override fun testGetBooks_singleFileInSubfolderWhenDisabled() { - SyncRepoTest.testGetBooks_singleFileInSubfolderWhenDisabled(gitWorkingTree, syncRepo) - } - - @Test - override fun testGetBooks_allFilesAreIgnored() { - SyncRepoTest.testGetBooks_allFilesAreIgnored(gitWorkingTree, syncRepo) - } - - @Test - override fun testGetBooks_specificFileInSubfolderIsIgnored() { - SyncRepoTest.testGetBooks_specificFileInSubfolderIsIgnored(gitWorkingTree, syncRepo) - } - - @Test - override fun testGetBooks_specificFileIsUnignored() { - SyncRepoTest.testGetBooks_specificFileIsUnignored(gitWorkingTree, syncRepo) - } - - @Test - override fun testGetBooks_ignoredExtensions() { - SyncRepoTest.testGetBooks_ignoredExtensions(gitWorkingTree, syncRepo) - } + override var syncRepo: SyncRepo + get() = mSyncRepo + set(value) {} + override val repoManipulationPoint: Any + get() = workingCloneDir - @Test - override fun testStoreBook_expectedUri() { - SyncRepoTest.testStoreBook_expectedUri(syncRepo) + override fun writeFileToRepo(content: String, repoRelativePath: String): String { + val expectedRookUri = Uri.parse(Uri.encode(repoRelativePath, "/")) + val targetFile = File(workingCloneDir, repoRelativePath) + targetFile.parentFile!!.mkdirs() + MiscUtils.writeStringToFile(content, targetFile) + workingClone.add().addFilepattern(".").call() + workingClone.commit().setMessage("").call() + workingClone.push().call() + // Ensure Orgzly's working tree is updated. This is needed for testing getBooks(), which + // does not update the worktree on its own. + gitFileSynchronizer.mergeWithRemote() + return expectedRookUri.toString() } + /** + * Ensure we support syncing to a new, empty Git repo. + * Also tests that a book without a link is linked and synced, if possible. + */ @Test - override fun testStoreBook_producesSameUriAsRetrieveBookWithSubfolder() { - SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithSubfolder(syncRepo) + fun testSyncRepo_repoHasNoCommits() { + testUtils.setupBook("A Book", "...") + syncRepo.syncRepo(dataRepository) + val bookView = dataRepository.getBooks()[0] + Assert.assertEquals(syncRepo.uri.toString(), bookView.linkRepo!!.url) + Assert.assertNotNull(bookView.syncedTo?.revision) + Assert.assertTrue(bookView.book.lastAction!!.message.contains("Saved to ")) } @Test - override fun testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder() { - SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder(syncRepo) - } + fun testSyncRepo_bookWithoutLinkAndMultipleRepos() { + // Add a second repo + testUtils.setupRepo(RepoType.MOCK, "mock://repo") + testUtils.setupBook("A Book", "...") - @Test - override fun testStoreBook_producesSameUriAsGetBooks() { - SyncRepoTest.testStoreBook_producesSameUriAsGetBooks(gitWorkingTree, syncRepo) - } + syncRepo.syncRepo(dataRepository) - @Test - override fun testStoreBook_inSubfolder() { - SyncRepoTest.testStoreBook_inSubfolder(gitWorkingTree, syncRepo) - } - - @Test - override fun testStoreBook_inSubfolderWhenDisabled() { - SyncRepoTest.testStoreBook_inSubfolderWhenDisabled(syncRepo) - } - - @Test - override fun testRenameBook_expectedUri() { - SyncRepoTest.testRenameBook_expectedUri(syncRepo) - } - - @Test(expected = IOException::class) - override fun testRenameBook_repoFileAlreadyExists() { - SyncRepoTest.testRenameBook_repoFileAlreadyExists(gitWorkingTree, syncRepo) - } - - @Test - override fun testRenameBook_fromRootToSubfolderWhenEnabled() { - SyncRepoTest.testRenameBook_fromRootToSubfolderWhenEnabled(syncRepo) - } - - @Test(expected = IOException::class) - override fun testRenameBook_fromRootToSubfolderWhenDisabled() { - SyncRepoTest.testRenameBook_fromRootToSubfolderWhenDisabled(syncRepo) - } - - @Test - override fun testRenameBook_fromSubfolderToRoot() { - SyncRepoTest.testRenameBook_fromSubfolderToRoot(syncRepo) - } - - @Test - override fun testRenameBook_newSubfolderSameLeafName() { - SyncRepoTest.testRenameBook_newSubfolderSameLeafName(syncRepo) - } - - @Test - override fun testRenameBook_newSubfolderAndLeafName() { - SyncRepoTest.testRenameBook_newSubfolderAndLeafName(syncRepo) + val bookView = dataRepository.getBooks()[0] + Assert.assertEquals(BookAction.Type.ERROR, bookView.book.lastAction!!.type) + Assert.assertTrue(bookView.book.lastAction!!.message.contains("multiple repositories")) } + /** + * The very first sync is special, since the remote head has not changed since cloning, but + * we want to be sure that all books are loaded. + */ @Test - override fun testRenameBook_sameSubfolderNewLeafName() { - SyncRepoTest.testRenameBook_sameSubfolderNewLeafName(syncRepo) + fun testSyncRepo_firstSyncAfterCloning() { + return // TODO } -} \ No newline at end of file +} diff --git a/app/src/test/java/com/orgzly/android/repos/WebdavRepoTest.kt b/app/src/test/java/com/orgzly/android/repos/WebdavRepoTest.kt index d62fe20d6..a38cd37db 100644 --- a/app/src/test/java/com/orgzly/android/repos/WebdavRepoTest.kt +++ b/app/src/test/java/com/orgzly/android/repos/WebdavRepoTest.kt @@ -1,17 +1,18 @@ package com.orgzly.android.repos +import android.net.Uri import androidx.test.ext.junit.runners.AndroidJUnit4 import com.orgzly.android.db.entity.Repo import com.orgzly.android.repos.WebdavRepo.Companion.PASSWORD_PREF_KEY import com.orgzly.android.repos.WebdavRepo.Companion.USERNAME_PREF_KEY +import com.orgzly.android.util.MiscUtils import io.github.atetzner.webdav.server.MiltonWebDAVFileServer import org.junit.After import org.junit.Assert.assertEquals import org.junit.Before -import org.junit.Test import org.junit.runner.RunWith import java.io.File -import java.io.IOException +import kotlin.io.path.Path @RunWith(AndroidJUnit4::class) @@ -21,7 +22,23 @@ class WebdavRepoTest : SyncRepoTest { private lateinit var serverRootDir: File private lateinit var localServer: MiltonWebDAVFileServer - private lateinit var syncRepo: SyncRepo + private lateinit var mSyncRepo: SyncRepo + override var syncRepo: SyncRepo + get() = mSyncRepo + set(value) {} + override val repoManipulationPoint: Any + get() = serverRootDir + + override fun writeFileToRepo(content: String, repoRelativePath: String): String { + val targetFile = File(serverRootDir.absolutePath + "/" + Path(repoRelativePath)) + val targetDir = File(targetFile.parent!!) + targetDir.mkdirs() + val expectedRookUri = mSyncRepo.uri.toString() + "/" + Uri.encode(repoRelativePath, "/") + val remoteBookFile = File(targetDir.absolutePath + "/" + targetFile.name) + MiscUtils.writeStringToFile(content, remoteBookFile) + return expectedRookUri + } + private lateinit var tmpFile: File @Before @@ -35,7 +52,7 @@ class WebdavRepoTest : SyncRepoTest { repoPropsMap[USERNAME_PREF_KEY] = "user" repoPropsMap[PASSWORD_PREF_KEY] = "secret" val repoWithProps = RepoWithProps(repo, repoPropsMap) - syncRepo = WebdavRepo.getInstance(repoWithProps) + mSyncRepo = WebdavRepo.getInstance(repoWithProps) assertEquals(serverUrl, repo.url) tmpFile = kotlin.io.path.createTempFile().toFile() } @@ -50,109 +67,4 @@ class WebdavRepoTest : SyncRepoTest { serverRootDir.deleteRecursively() } } - - @Test - override fun testGetBooks_singleOrgFile() { - SyncRepoTest.testGetBooks_singleOrgFile(serverRootDir, syncRepo) - } - - @Test - override fun testGetBooks_singleFileInSubfolderWhenEnabled() { - SyncRepoTest.testGetBooks_singleFileInSubfolderWhenEnabled(serverRootDir, syncRepo) - } - - @Test - override fun testGetBooks_singleFileInSubfolderWhenDisabled() { - SyncRepoTest.testGetBooks_singleFileInSubfolderWhenDisabled(serverRootDir, syncRepo) - } - - @Test - override fun testGetBooks_allFilesAreIgnored() { - SyncRepoTest.testGetBooks_allFilesAreIgnored(serverRootDir, syncRepo) - } - - @Test - override fun testGetBooks_specificFileInSubfolderIsIgnored() { - SyncRepoTest.testGetBooks_specificFileInSubfolderIsIgnored(serverRootDir, syncRepo) - } - - @Test - override fun testGetBooks_specificFileIsUnignored() { - SyncRepoTest.testGetBooks_specificFileIsUnignored(serverRootDir, syncRepo) - } - - @Test - override fun testGetBooks_ignoredExtensions() { - SyncRepoTest.testGetBooks_ignoredExtensions(serverRootDir, syncRepo) - } - - @Test - override fun testStoreBook_expectedUri() { - SyncRepoTest.testStoreBook_expectedUri(syncRepo) - } - - @Test - override fun testStoreBook_producesSameUriAsRetrieveBookWithSubfolder() { - SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithSubfolder(syncRepo) - } - - @Test - override fun testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder() { - SyncRepoTest.testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder(syncRepo) - } - - @Test - override fun testStoreBook_producesSameUriAsGetBooks() { - SyncRepoTest.testStoreBook_producesSameUriAsGetBooks(serverRootDir, syncRepo) - } - - @Test - override fun testStoreBook_inSubfolder() { - SyncRepoTest.testStoreBook_inSubfolder(serverRootDir, syncRepo) - } - - @Test(expected = IOException::class) - override fun testStoreBook_inSubfolderWhenDisabled() { - SyncRepoTest.testStoreBook_inSubfolderWhenDisabled(syncRepo) - } - - @Test - override fun testRenameBook_expectedUri() { - SyncRepoTest.testRenameBook_expectedUri(syncRepo) - } - - @Test(expected = IOException::class) - override fun testRenameBook_repoFileAlreadyExists() { - SyncRepoTest.testRenameBook_repoFileAlreadyExists(serverRootDir, syncRepo) - } - - @Test - override fun testRenameBook_fromRootToSubfolderWhenEnabled() { - SyncRepoTest.testRenameBook_fromRootToSubfolderWhenEnabled(syncRepo) - } - - @Test(expected = IOException::class) - override fun testRenameBook_fromRootToSubfolderWhenDisabled() { - SyncRepoTest.testRenameBook_fromRootToSubfolderWhenDisabled(syncRepo) - } - - @Test - override fun testRenameBook_fromSubfolderToRoot() { - SyncRepoTest.testRenameBook_fromSubfolderToRoot(syncRepo) - } - - @Test - override fun testRenameBook_newSubfolderSameLeafName() { - SyncRepoTest.testRenameBook_newSubfolderSameLeafName(syncRepo) - } - - @Test - override fun testRenameBook_newSubfolderAndLeafName() { - SyncRepoTest.testRenameBook_newSubfolderAndLeafName(syncRepo) - } - - @Test - override fun testRenameBook_sameSubfolderNewLeafName() { - SyncRepoTest.testRenameBook_sameSubfolderNewLeafName(syncRepo) - } -} \ No newline at end of file +} diff --git a/app/src/androidTest/java/com/orgzly/android/TestUtils.java b/shared-test/src/main/java/com/orgzly/android/TestUtils.java similarity index 98% rename from app/src/androidTest/java/com/orgzly/android/TestUtils.java rename to shared-test/src/main/java/com/orgzly/android/TestUtils.java index 0da43deb3..63863dca4 100644 --- a/app/src/androidTest/java/com/orgzly/android/TestUtils.java +++ b/shared-test/src/main/java/com/orgzly/android/TestUtils.java @@ -36,7 +36,7 @@ public class TestUtils { private DataRepository dataRepository; private DbRepoBookRepository dbRepoBookRepository; - TestUtils(DataRepository dataRepository, DbRepoBookRepository dbRepoBookRepository) { + public TestUtils(DataRepository dataRepository, DbRepoBookRepository dbRepoBookRepository) { this.dataRepository = dataRepository; this.dbRepoBookRepository = dbRepoBookRepository; } diff --git a/shared-test/src/main/java/com/orgzly/android/repos/SyncRepoTest.kt b/shared-test/src/main/java/com/orgzly/android/repos/SyncRepoTest.kt index baf903482..e596ad241 100644 --- a/shared-test/src/main/java/com/orgzly/android/repos/SyncRepoTest.kt +++ b/shared-test/src/main/java/com/orgzly/android/repos/SyncRepoTest.kt @@ -10,491 +10,346 @@ import com.orgzly.android.prefs.AppPreferences import com.orgzly.android.util.MiscUtils import org.eclipse.jgit.api.Git import org.eclipse.jgit.storage.file.FileRepositoryBuilder +import org.junit.Assert import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue +import org.junit.Assert.assertThrows +import org.junit.Test import java.io.File import java.io.IOException @SuppressLint("NewApi") interface SyncRepoTest { - fun testGetBooks_singleOrgFile() - fun testGetBooks_singleFileInSubfolderWhenEnabled() - fun testGetBooks_singleFileInSubfolderWhenDisabled() - fun testGetBooks_allFilesAreIgnored() - fun testGetBooks_specificFileInSubfolderIsIgnored() - fun testGetBooks_specificFileIsUnignored() - fun testGetBooks_ignoredExtensions() - fun testStoreBook_expectedUri() - fun testStoreBook_producesSameUriAsRetrieveBookWithSubfolder() - fun testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder() - fun testStoreBook_producesSameUriAsGetBooks() - fun testStoreBook_inSubfolder() - fun testStoreBook_inSubfolderWhenDisabled() - fun testRenameBook_expectedUri() - fun testRenameBook_repoFileAlreadyExists() - fun testRenameBook_fromRootToSubfolderWhenEnabled() - fun testRenameBook_fromRootToSubfolderWhenDisabled() - fun testRenameBook_fromSubfolderToRoot() - fun testRenameBook_newSubfolderSameLeafName() - fun testRenameBook_newSubfolderAndLeafName() - fun testRenameBook_sameSubfolderNewLeafName() + var syncRepo: SyncRepo + val repoManipulationPoint: Any - companion object { - - const val repoDirName = "orgzly-android-test" - private var treeDocumentFileExtraSegment = if (Build.VERSION.SDK_INT < 30) { - "/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2F$repoDirName%2F" - } else { - "/document/primary%3A$repoDirName%2F" - } + fun writeFileToRepo(content: String, repoRelativePath: String): String - fun testGetBooks_singleOrgFile(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - val fileContent = "\n\n...\n\n" - val fileName = "Book one.org" - val expectedRookUri = writeFileToRepo(fileContent, syncRepo, repoManipulationPoint, fileName) + @Test + fun testGetBooks_singleOrgFile() { + // Given + val fileContent = "\n\n...\n\n" + val fileName = "Book one.org" + val expectedRookUri = writeFileToRepo(fileContent, fileName) - // When - val books = syncRepo.books - val retrieveBookDestinationFile = kotlin.io.path.createTempFile().toFile() - syncRepo.retrieveBook(fileName, retrieveBookDestinationFile) + // When + val retrieveBookDestinationFile = kotlin.io.path.createTempFile().toFile() + syncRepo.retrieveBook(fileName, retrieveBookDestinationFile) + val books = syncRepo.books - // Then - assertEquals(1, books.size) - assertEquals(expectedRookUri, books[0].uri.toString()) - assertEquals(fileContent, retrieveBookDestinationFile.readText()) - assertEquals(fileName, BookName.getRepoRelativePath(syncRepo.uri, books[0].uri)) - } - - fun testGetBooks_singleFileInSubfolderWhenEnabled(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val repoFilePath = "Folder/Book one.org" - val fileContent = "\n\n...\n\n" - val expectedRookUri = writeFileToRepo(fileContent, syncRepo, repoManipulationPoint, "Book one.org", "Folder") + // Then + assertEquals(1, books.size) + assertEquals(expectedRookUri, books[0].uri.toString()) + assertEquals(fileContent, retrieveBookDestinationFile.readText()) + assertEquals(fileName, BookName.getRepoRelativePath(syncRepo.uri, books[0].uri)) + } - // When - val books = syncRepo.books - val retrieveBookDestinationFile = kotlin.io.path.createTempFile().toFile() - syncRepo.retrieveBook(repoFilePath, retrieveBookDestinationFile) + @Test + fun testGetBooks_singleFileInSubfolder() { + // Given + val repoFilePath = "Folder/Book one.org" + val fileContent = "\n\n...\n\n" + val expectedRookUri = writeFileToRepo(fileContent, "Folder/Book one.org") + + // When + val retrieveBookDestinationFile = kotlin.io.path.createTempFile().toFile() + syncRepo.retrieveBook(repoFilePath, retrieveBookDestinationFile) + val books = syncRepo.books + + // Then + assertEquals(1, books.size) + assertEquals(expectedRookUri, books[0].uri.toString()) + assertEquals(repoFilePath, BookName.getRepoRelativePath(syncRepo.uri, books[0].uri)) + assertEquals(fileContent, retrieveBookDestinationFile.readText()) + } - // Then - assertEquals(1, books.size) - assertEquals(expectedRookUri, books[0].uri.toString()) - assertEquals(repoFilePath, BookName.getRepoRelativePath(syncRepo.uri, books[0].uri)) - assertEquals(fileContent, retrieveBookDestinationFile.readText()) - } + @Test + fun testGetBooks_allFilesAreIgnored() { + // Given + val ignoreFileContent = "*\n" + writeFileToRepo("...", "folder/book one.org") + writeFileToRepo(ignoreFileContent, RepoIgnoreNode.IGNORE_FILE) + // When + val books = syncRepo.books + // Then + assertEquals(0, books.size) + } - fun testGetBooks_singleFileInSubfolderWhenDisabled(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), false) - val fileContent = "\n\n...\n\n" - writeFileToRepo(fileContent, syncRepo, repoManipulationPoint, "Book one.org", "Folder") + @Test + fun testGetBooks_specificFileInSubfolderIsIgnored() { + // Given + val ignoreFileContent = "folder/book one.org\n" + writeFileToRepo("...", "folder/book one.org") + writeFileToRepo(ignoreFileContent, RepoIgnoreNode.IGNORE_FILE) + // When + val books = syncRepo.books + // Then + assertEquals(0, books.size) + } - // When - val books = syncRepo.books + @Test + fun testGetBooks_specificFileIsUnignored() { + // Given + val folderName = "My Folder" + val fileName = "My file.org" + val ignoreFileContent = "folder/**\n!$folderName/$fileName\n" + writeFileToRepo("...", "$folderName/$fileName") + writeFileToRepo(ignoreFileContent, RepoIgnoreNode.IGNORE_FILE) + // When + val books = syncRepo.books + // Then + assertEquals(1, books.size) + } - // Then - assertEquals(0, books.size) + @Test + fun testGetBooks_ignoredExtensions() { + // Given + val testBookContent = "\n\n...\n\n" + for (fileName in arrayOf("file one.txt", "file two.o", "file three.org")) { + writeFileToRepo(testBookContent, fileName) } + // When + val books = syncRepo.books + // Then + assertEquals(1, books.size.toLong()) + assertEquals("file three", BookName.fromRepoRelativePath(BookName.getRepoRelativePath(syncRepo.uri, books[0].uri)).name) + } - fun testGetBooks_allFilesAreIgnored(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - val ignoreFileContent = "*\n" - writeFileToRepo("...", syncRepo, repoManipulationPoint, "book one.org", "folder") - writeFileToRepo(ignoreFileContent, syncRepo, repoManipulationPoint, RepoIgnoreNode.IGNORE_FILE) - // When - val books = syncRepo.books - // Then - assertEquals(0, books.size) + @Test + fun testStoreBook_expectedUri() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + MiscUtils.writeStringToFile("...", tmpFile) + // When + val vrook = syncRepo.storeBook(tmpFile, "Book one.org") + tmpFile.delete() + // Then + val expectedRookUri = when (syncRepo) { + is GitRepo -> "Book%20one.org" + is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "Book%20one.org" + else -> syncRepo.uri.toString() + "/Book%20one.org" } + assertEquals(expectedRookUri, vrook.uri.toString()) + } - fun testGetBooks_specificFileInSubfolderIsIgnored(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val ignoreFileContent = "folder/book one.org\n" - writeFileToRepo("...", syncRepo, repoManipulationPoint, "book one.org", "folder") - writeFileToRepo(ignoreFileContent, syncRepo, repoManipulationPoint, RepoIgnoreNode.IGNORE_FILE) - // When - val books = syncRepo.books - // Then - assertEquals(0, books.size) - } + @Test + fun testStoreBook_producesSameUriAsRetrieveBook() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + val repositoryPath = "a folder/a book.org" + MiscUtils.writeStringToFile("...", tmpFile) + // When + val storedRook = syncRepo.storeBook(tmpFile, repositoryPath) + val retrievedBook = syncRepo.retrieveBook(repositoryPath, tmpFile) + tmpFile.delete() + // Then + assertEquals(retrievedBook.uri, storedRook.uri) + } - fun testGetBooks_specificFileIsUnignored(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val folderName = "My Folder" - val fileName = "My file.org" - val ignoreFileContent = "$folderName/**\n!$folderName/$fileName\n" - writeFileToRepo("...", syncRepo, repoManipulationPoint, fileName, folderName) - writeFileToRepo(ignoreFileContent, syncRepo, repoManipulationPoint, RepoIgnoreNode.IGNORE_FILE) - // When - val books = syncRepo.books - // Then - assertEquals(1, books.size) - } + @Test + fun testStoreBook_producesSameUriAsGetBooks() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + val folderName = "A folder" + val fileName = "A book.org" + writeFileToRepo("...", "$folderName/$fileName") + // When + val gottenBook = syncRepo.books[0] + MiscUtils.writeStringToFile("......", tmpFile) // N.B. Different content to ensure the repo file is actually changed + val storedRook = syncRepo.storeBook(tmpFile, "$folderName/$fileName") + tmpFile.delete() + // Then + assertEquals(gottenBook.uri, storedRook.uri) + } - fun testGetBooks_ignoredExtensions(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - val testBookContent = "\n\n...\n\n" - for (fileName in arrayOf("file one.txt", "file two.o", "file three.org")) { - writeFileToRepo(testBookContent, syncRepo, repoManipulationPoint, fileName) + @Test + fun testStoreBook_inSubfolder() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + val repositoryPath = "A folder/A book.org" + val testBookContent = "\n\n...\n\n" + MiscUtils.writeStringToFile(testBookContent, tmpFile) + // When + syncRepo.storeBook(tmpFile, repositoryPath) + tmpFile.delete() + // Then + when (syncRepo) { + is WebdavRepo -> { + val serverRepoDir = repoManipulationPoint as File + val subFolder = File(serverRepoDir, "A folder") + Assert.assertTrue(subFolder.exists()) + val bookFile = File(subFolder, "A book.org") + Assert.assertTrue(bookFile.exists()) + assertEquals(testBookContent, bookFile.readText()) } - // When - val books = syncRepo.books - // Then - assertEquals(1, books.size.toLong()) - assertEquals("file three", BookName.fromRepoRelativePath(BookName.getRepoRelativePath(syncRepo.uri, books[0].uri)).name) - } - - fun testStoreBook_expectedUri(syncRepo: SyncRepo) { - // Given - val tmpFile = kotlin.io.path.createTempFile().toFile() - MiscUtils.writeStringToFile("...", tmpFile) - // When - val vrook = syncRepo.storeBook(tmpFile, "Book one.org") - tmpFile.delete() - // Then - val expectedRookUri = when (syncRepo) { - is GitRepo -> "/Book one.org" - is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "Book%20one.org" - else -> syncRepo.uri.toString() + "/Book%20one.org" + is GitRepo -> { + val workingClone = repoManipulationPoint as File + val git = Git( + FileRepositoryBuilder() + .addCeilingDirectory(workingClone) + .findGitDir(workingClone) + .build() + ) + git.pull().call() + val subFolder = File(workingClone, "A folder") + Assert.assertTrue(subFolder.exists()) + val bookFile = File(subFolder, "A book.org") + Assert.assertTrue(bookFile.exists()) + assertEquals(testBookContent, bookFile.readText()) } - assertEquals(expectedRookUri, vrook.uri.toString()) - } - - fun testStoreBook_producesSameUriAsRetrieveBookWithSubfolder(syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val tmpFile = kotlin.io.path.createTempFile().toFile() - val repositoryPath = "a folder/a book.org" - MiscUtils.writeStringToFile("...", tmpFile) - // When - val storedRook = syncRepo.storeBook(tmpFile, repositoryPath) - val retrievedBook = syncRepo.retrieveBook(repositoryPath, tmpFile) - tmpFile.delete() - // Then - assertEquals(retrievedBook.uri, storedRook.uri) - } - - fun testStoreBook_producesSameUriAsRetrieveBookWithoutSubfolder(syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), false) - val tmpFile = kotlin.io.path.createTempFile().toFile() - val repositoryPath = "A book.org" - MiscUtils.writeStringToFile("...", tmpFile) - // When - val storedRook = syncRepo.storeBook(tmpFile, repositoryPath) - val retrievedBook = syncRepo.retrieveBook(repositoryPath, tmpFile) - tmpFile.delete() - // Then - assertEquals(retrievedBook.uri, storedRook.uri) - } - - fun testStoreBook_producesSameUriAsGetBooks(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val tmpFile = kotlin.io.path.createTempFile().toFile() - val folderName = "A folder" - val fileName = "A book.org" - writeFileToRepo("...", syncRepo, repoManipulationPoint, fileName, folderName) - // When - val gottenBook = syncRepo.books[0] - MiscUtils.writeStringToFile("......", tmpFile) // N.B. Different content to ensure the repo file is actually changed - val storedRook = syncRepo.storeBook(tmpFile, "$folderName/$fileName") - tmpFile.delete() - // Then - assertEquals(gottenBook.uri, storedRook.uri) - } - - fun testStoreBook_inSubfolder(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val tmpFile = kotlin.io.path.createTempFile().toFile() - val repositoryPath = "A folder/A book.org" - val testBookContent = "\n\n...\n\n" - MiscUtils.writeStringToFile(testBookContent, tmpFile) - // When - syncRepo.storeBook(tmpFile, repositoryPath) - tmpFile.delete() - // Then - when (syncRepo) { - is WebdavRepo -> { - repoManipulationPoint as File - val subFolder = File(repoManipulationPoint, "A folder") - assertTrue(subFolder.exists()) - val bookFile = File(subFolder, "A book.org") - assertTrue(bookFile.exists()) - assertEquals(testBookContent, bookFile.readText()) - } - is GitRepo -> { - repoManipulationPoint as File - val git = Git( - FileRepositoryBuilder() - .addCeilingDirectory(repoManipulationPoint) - .findGitDir(repoManipulationPoint) - .build() - ) - git.pull().call() - val subFolder = File(repoManipulationPoint, "A folder") - assertTrue(subFolder.exists()) - val bookFile = File(subFolder, "A book.org") - assertTrue(bookFile.exists()) - assertEquals(testBookContent, bookFile.readText()) - } - is DocumentRepo -> { - repoManipulationPoint as DocumentFile - val subFolder = repoManipulationPoint.findFile("A folder") - assertTrue(subFolder!!.exists()) - assertTrue(subFolder.isDirectory) - val bookFile = subFolder.findFile("A book.org") - assertTrue(bookFile!!.exists()) - assertEquals(testBookContent, MiscUtils.readStringFromDocumentFile(bookFile)) - } - is DropboxRepo -> { - // Not really much to assert here; we don't really care how Dropbox implements things, - // as long as URLs work as expected. - repoManipulationPoint as DropboxClient - val retrievedFile = kotlin.io.path.createTempFile().toFile() - repoManipulationPoint.download(syncRepo.uri, repositoryPath, retrievedFile) - assertEquals(testBookContent, retrievedFile.readText()) - } + is DocumentRepo -> { + val repoDocFile = repoManipulationPoint as DocumentFile + val subFolder = repoDocFile.findFile("A folder") + Assert.assertTrue(subFolder!!.exists()) + Assert.assertTrue(subFolder.isDirectory) + val bookFile = subFolder.findFile("A book.org") + Assert.assertTrue(bookFile!!.exists()) + assertEquals(testBookContent, MiscUtils.readStringFromDocumentFile(bookFile)) } - } - - fun testStoreBook_inSubfolderWhenDisabled(syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), false) - val tmpFile = kotlin.io.path.createTempFile().toFile() - val repositoryPath = "A folder/A book.org" - val testBookContent = "\n\n...\n\n" - MiscUtils.writeStringToFile(testBookContent, tmpFile) - // Then - try { - syncRepo.storeBook(tmpFile, repositoryPath) - } catch (e: IOException) { - assertTrue(e.message!!.contains("Support for subfolders is disabled")) - throw e + is DropboxRepo -> { + // Not really much to assert here; we don't really care how Dropbox implements things, + // as long as URLs work as expected. + val client = repoManipulationPoint as DropboxClient + val retrievedFile = kotlin.io.path.createTempFile().toFile() + client.download(syncRepo.uri, repositoryPath, retrievedFile) + assertEquals(testBookContent, retrievedFile.readText()) } } + } - fun testRenameBook_expectedUri(syncRepo: SyncRepo) { - // Given - val tmpFile = kotlin.io.path.createTempFile().toFile() - val oldFileName = "Original book.org" - val newBookName = "Renamed book" - val testBookContent = "\n\n...\n\n" - MiscUtils.writeStringToFile(testBookContent, tmpFile) - // When - val originalVrook = syncRepo.storeBook(tmpFile, oldFileName) - tmpFile.delete() - syncRepo.renameBook(originalVrook.uri, newBookName) - // Then - val renamedVrook = syncRepo.books[0] - val expectedRookUri = when (syncRepo) { - is GitRepo -> "/Renamed book.org" - is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "Renamed%20book.org" - else -> syncRepo.uri.toString() + "/Renamed%20book.org" - } - assertEquals(expectedRookUri, renamedVrook.uri.toString()) - } - - fun testRenameBook_repoFileAlreadyExists(repoManipulationPoint: Any, syncRepo: SyncRepo) { - // Given - for (fileName in arrayOf("Original.org", "Renamed.org")) { - writeFileToRepo("...", syncRepo, repoManipulationPoint, fileName) - } - val retrievedBookFile = kotlin.io.path.createTempFile().toFile() - // When - val originalRook = syncRepo.retrieveBook("Original.org", retrievedBookFile) - try { - syncRepo.renameBook(originalRook.uri, "Renamed") - } catch (e: IOException) { - // Then - assertTrue(e.message!!.contains("Renamed.org already exists")) - throw e - } finally { - retrievedBookFile.delete() - } + @Test + fun testRenameBook_expectedUri() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + val oldFileName = "Original book.org" + val newBookName = "Renamed book" + val testBookContent = "\n\n...\n\n" + MiscUtils.writeStringToFile(testBookContent, tmpFile) + // When + val originalVrook = syncRepo.storeBook(tmpFile, oldFileName) + tmpFile.delete() + syncRepo.renameBook(originalVrook.uri, newBookName) + // Then + val renamedVrook = syncRepo.books[0] + val expectedRookUri = when (syncRepo) { + is GitRepo -> "Renamed%20book.org" + is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "Renamed%20book.org" + else -> syncRepo.uri.toString() + "/Renamed%20book.org" } + assertEquals(expectedRookUri, renamedVrook.uri.toString()) + } - fun testRenameBook_fromRootToSubfolderWhenEnabled(syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val tmpFile = kotlin.io.path.createTempFile().toFile() - MiscUtils.writeStringToFile("...", tmpFile) - // When - val originalRook = syncRepo.storeBook(tmpFile, "Original book.org") - tmpFile.delete() - val renamedRook = syncRepo.renameBook(originalRook.uri, "A folder/Renamed book") - // Then - val expectedRookUri = when (syncRepo) { - is GitRepo -> "/A folder/Renamed book.org" - is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "A%20folder%2FRenamed%20book.org" - else -> syncRepo.uri.toString() + "/A%20folder/Renamed%20book.org" - } - assertEquals(expectedRookUri, renamedRook.uri.toString()) + @Test + @Throws(IOException::class) + fun testRenameBook_repoFileAlreadyExists() { + // Given + for (fileName in arrayOf("Original.org", "Renamed.org")) { + writeFileToRepo("...", fileName) } + val retrievedBookFile = kotlin.io.path.createTempFile().toFile() + // When + val originalRook = syncRepo.retrieveBook("Original.org", retrievedBookFile) + assertThrows(IOException::class.java) { syncRepo.renameBook(originalRook.uri, "Renamed") } + retrievedBookFile.delete() + } - fun testRenameBook_fromRootToSubfolderWhenDisabled(syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), false) - val tmpFile = kotlin.io.path.createTempFile().toFile() - MiscUtils.writeStringToFile("...", tmpFile) - // When - val originalRook = syncRepo.storeBook(tmpFile, "Original book.org") - tmpFile.delete() - // Then - try { - syncRepo.renameBook(originalRook.uri, "A folder/Renamed book") - } catch (e: IOException) { - assertTrue(e.message!!.contains("Support for subfolders is disabled")) - throw e - } + @Test + fun testRenameBook_fromRootToSubfolder() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + MiscUtils.writeStringToFile("...", tmpFile) + // When + val originalRook = syncRepo.storeBook(tmpFile, "Original book.org") + tmpFile.delete() + val renamedRook = syncRepo.renameBook(originalRook.uri, "A folder/Renamed book") + // Then + val expectedRookUri = when (syncRepo) { + is GitRepo -> "A%20folder/Renamed%20book.org" + is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "A%20folder%2FRenamed%20book.org" + else -> syncRepo.uri.toString() + "/A%20folder/Renamed%20book.org" } + assertEquals(expectedRookUri, renamedRook.uri.toString()) + } - fun testRenameBook_fromSubfolderToRoot(syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val tmpFile = kotlin.io.path.createTempFile().toFile() - MiscUtils.writeStringToFile("...", tmpFile) - // When - val originalRook = syncRepo.storeBook(tmpFile, "A folder/Original book.org") - tmpFile.delete() - val renamedRook = syncRepo.renameBook(originalRook.uri, "Renamed book") - // Then - val expectedRookUri = when (syncRepo) { - is GitRepo -> "/Renamed book.org" - is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "Renamed%20book.org" - else -> syncRepo.uri.toString() + "/Renamed%20book.org" - } - assertEquals(expectedRookUri, renamedRook.uri.toString()) + @Test + fun testRenameBook_fromSubfolderToRoot() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + MiscUtils.writeStringToFile("...", tmpFile) + // When + val originalRook = syncRepo.storeBook(tmpFile, "A folder/Original book.org") + tmpFile.delete() + val renamedRook = syncRepo.renameBook(originalRook.uri, "Renamed book") + // Then + val expectedRookUri = when (syncRepo) { + is GitRepo -> "Renamed%20book.org" + is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "Renamed%20book.org" + else -> syncRepo.uri.toString() + "/Renamed%20book.org" } + assertEquals(expectedRookUri, renamedRook.uri.toString()) + } - fun testRenameBook_newSubfolderSameLeafName(syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val tmpFile = kotlin.io.path.createTempFile().toFile() - MiscUtils.writeStringToFile("...", tmpFile) - // When - val originalRook = syncRepo.storeBook(tmpFile, "Old folder/Original book.org") - tmpFile.delete() - val renamedRook = syncRepo.renameBook(originalRook.uri, "New folder/Original book") - // Then - val expectedRookUri = when (syncRepo) { - is GitRepo -> "/New folder/Original book.org" - is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "New%20folder%2FOriginal%20book.org" - else -> syncRepo.uri.toString() + "/New%20folder/Original%20book.org" - } - assertEquals(expectedRookUri, renamedRook.uri.toString()) + @Test + fun testRenameBook_newSubfolderSameLeafName() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + MiscUtils.writeStringToFile("...", tmpFile) + // When + val originalRook = syncRepo.storeBook(tmpFile, "Old folder/Original book.org") + tmpFile.delete() + val renamedRook = syncRepo.renameBook(originalRook.uri, "New folder/Original book") + // Then + val expectedRookUri = when (syncRepo) { + is GitRepo -> "New%20folder/Original%20book.org" + is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "New%20folder%2FOriginal%20book.org" + else -> syncRepo.uri.toString() + "/New%20folder/Original%20book.org" } + assertEquals(expectedRookUri, renamedRook.uri.toString()) + } - fun testRenameBook_newSubfolderAndLeafName(syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val tmpFile = kotlin.io.path.createTempFile().toFile() - MiscUtils.writeStringToFile("...", tmpFile) - // When - val originalRook = syncRepo.storeBook(tmpFile, "old folder/Original book.org") - tmpFile.delete() - val renamedRook = syncRepo.renameBook(originalRook.uri, "new folder/New book") - // Then - val expectedRookUri = when (syncRepo) { - is GitRepo -> "/new folder/New book.org" - is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "new%20folder%2FNew%20book.org" - else -> syncRepo.uri.toString() + "/new%20folder/New%20book.org" - } - assertEquals(expectedRookUri, renamedRook.uri.toString()) + @Test + fun testRenameBook_newSubfolderAndLeafName() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + MiscUtils.writeStringToFile("...", tmpFile) + // When + val originalRook = syncRepo.storeBook(tmpFile, "old folder/Original book.org") + tmpFile.delete() + val renamedRook = syncRepo.renameBook(originalRook.uri, "new folder/New book") + // Then + val expectedRookUri = when (syncRepo) { + is GitRepo -> "new%20folder/New%20book.org" + is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "new%20folder%2FNew%20book.org" + else -> syncRepo.uri.toString() + "/new%20folder/New%20book.org" } + assertEquals(expectedRookUri, renamedRook.uri.toString()) + } - fun testRenameBook_sameSubfolderNewLeafName(syncRepo: SyncRepo) { - // Given - AppPreferences.subfolderSupport(App.getAppContext(), true) - val tmpFile = kotlin.io.path.createTempFile().toFile() - MiscUtils.writeStringToFile("...", tmpFile) - // When - val originalRook = syncRepo.storeBook(tmpFile, "old folder/Original book.org") - tmpFile.delete() - val renamedRook = syncRepo.renameBook(originalRook.uri, "old folder/New book") - // Then - val expectedRookUri = when (syncRepo) { - is GitRepo -> "/old folder/New book.org" - is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "old%20folder%2FNew%20book.org" - else -> syncRepo.uri.toString() + "/old%20folder/New%20book.org" - } - assertEquals(expectedRookUri, renamedRook.uri.toString()) + @Test + fun testRenameBook_sameSubfolderNewLeafName() { + // Given + val tmpFile = kotlin.io.path.createTempFile().toFile() + MiscUtils.writeStringToFile("...", tmpFile) + // When + val originalRook = syncRepo.storeBook(tmpFile, "old folder/Original book.org") + tmpFile.delete() + val renamedRook = syncRepo.renameBook(originalRook.uri, "old folder/New book") + // Then + val expectedRookUri = when (syncRepo) { + is GitRepo -> "old%20folder/New%20book.org" + is DocumentRepo -> syncRepo.uri.toString() + treeDocumentFileExtraSegment + "old%20folder%2FNew%20book.org" + else -> syncRepo.uri.toString() + "/old%20folder/New%20book.org" } + assertEquals(expectedRookUri, renamedRook.uri.toString()) + } - private fun writeFileToRepo( - content: String, - repo: SyncRepo, - repoManipulationPoint: Any, - fileName: String, - folderName: String? = null - ): String { - var expectedRookUri = repo.uri.toString() + "/" + Uri.encode(fileName) - when (repo) { - is WebdavRepo -> { - var targetDir = repoManipulationPoint as File - if (folderName != null) { - targetDir = File(targetDir.absolutePath + "/$folderName") - targetDir.mkdir() - expectedRookUri = repo.uri.toString() + "/" + Uri.encode("$folderName/$fileName", "/") - } - val remoteBookFile = File(targetDir.absolutePath + "/$fileName") - MiscUtils.writeStringToFile(content, remoteBookFile) - } - is GitRepo -> { - expectedRookUri = "/$fileName" - var targetDir = repoManipulationPoint as File - if (folderName != null) { - expectedRookUri = "/$folderName/$fileName" - targetDir = File(targetDir.absolutePath + "/$folderName") - targetDir.mkdir() - } - MiscUtils.writeStringToFile( - content, - File(targetDir.absolutePath + "/$fileName") - ) - updateGitRepo(repoManipulationPoint) - } - is DocumentRepo -> { - expectedRookUri = repo.uri.toString() + treeDocumentFileExtraSegment + Uri.encode(fileName) - var targetDir = repoManipulationPoint as DocumentFile - if (folderName != null) { - targetDir = targetDir.createDirectory(folderName)!! - expectedRookUri = repo.uri.toString() + treeDocumentFileExtraSegment + Uri.encode("$folderName/$fileName") - } - MiscUtils.writeStringToDocumentFile(content, fileName, targetDir.uri) - } - is DropboxRepo -> { - repoManipulationPoint as DropboxClient - val tmpFile = kotlin.io.path.createTempFile().toFile() - MiscUtils.writeStringToFile(content, tmpFile) - var targetPath = fileName - if (folderName != null) { - targetPath = "$folderName/$fileName" - expectedRookUri = repo.uri.toString() + "/" + Uri.encode("$folderName/$fileName", "/") - } - repoManipulationPoint.upload(tmpFile, repo.uri, targetPath) - tmpFile.delete() - } - } - return expectedRookUri - } + companion object { - private fun updateGitRepo(workdir: File) { - val git = Git( - FileRepositoryBuilder() - .addCeilingDirectory(workdir) - .findGitDir(workdir) - .build() - ) - git.add().addFilepattern(".").call() - git.commit().setMessage("").call() - git.push().call() + const val repoDirName = "orgzly-android-test" + var treeDocumentFileExtraSegment = if (Build.VERSION.SDK_INT < 30) { + "/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2F$repoDirName%2F" + } else { + "/document/primary%3A$repoDirName%2F" } } -} \ No newline at end of file +}