From 66e5551653e8fa9226a0ace4c64a1a8e78254313 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 17 Sep 2026 16:21:05 +0200 Subject: [PATCH 1/2] ci(garm): fix launcher activity and file it Signed-off-by: alperozturk96 --- .../com/nmc/android/ui/LauncherActivityIT.kt | 26 ++- .../java/com/owncloud/android/FileIT.java | 151 ------------------ .../java/com/owncloud/android/FileIT.kt | 125 +++++++++++++++ 3 files changed, 148 insertions(+), 154 deletions(-) delete mode 100644 app/src/androidTest/java/com/owncloud/android/FileIT.java create mode 100644 app/src/androidTest/java/com/owncloud/android/FileIT.kt diff --git a/app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt b/app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt index abbf7bfc545e..8e7ef8efccfd 100644 --- a/app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt +++ b/app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt @@ -1,12 +1,14 @@ /* * Nextcloud - Android Client * + * SPDX-FileCopyrightText: 2026 Alper Ozturk * SPDX-FileCopyrightText: 2023 TSI-mc * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only */ package com.nmc.android.ui import android.content.Intent +import android.os.SystemClock import android.view.View import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry @@ -46,9 +48,7 @@ class LauncherActivityIT : AbstractIT() { fun testSplashScreenWithEmptyTitlesShouldNotDelayNextScreen() { val activity = launchLauncherActivity() - instrumentation.waitForIdleSync() - - assertTrue(activity.isFinishing) + assertTrue("Splash screen without titles did not open the next screen", activity.awaitFinishing()) } private fun launchLauncherActivity(): LauncherActivity { @@ -57,4 +57,24 @@ class LauncherActivityIT : AbstractIT() { return instrumentation.startActivitySync(intent) as LauncherActivity } + + private fun LauncherActivity.awaitFinishing(): Boolean { + val deadline = SystemClock.uptimeMillis() + FINISH_TIMEOUT_IN_MILLIS + var finishing = false + + while (!finishing && SystemClock.uptimeMillis() < deadline) { + instrumentation.runOnMainSync { finishing = isFinishing } + + if (!finishing) { + Thread.sleep(FINISH_POLL_INTERVAL_IN_MILLIS) + } + } + + return finishing + } + + companion object { + private const val FINISH_TIMEOUT_IN_MILLIS = 5000L + private const val FINISH_POLL_INTERVAL_IN_MILLIS = 50L + } } diff --git a/app/src/androidTest/java/com/owncloud/android/FileIT.java b/app/src/androidTest/java/com/owncloud/android/FileIT.java deleted file mode 100644 index 59d412477295..000000000000 --- a/app/src/androidTest/java/com/owncloud/android/FileIT.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2018 Tobias Kaminsky - * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only - */ -package com.owncloud.android; - -import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.operations.CreateFolderOperation; -import com.owncloud.android.operations.RemoveFileOperation; -import com.owncloud.android.operations.RenameFileOperation; -import com.owncloud.android.operations.SynchronizeFolderOperation; -import com.owncloud.android.operations.common.SyncOperation; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.File; -import java.io.IOException; - -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import static junit.framework.TestCase.assertTrue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; - -/** - * Tests related to file operations. - */ -@RunWith(AndroidJUnit4.class) -public class FileIT extends AbstractOnServerIT { - - @Test - public void testCreateFolder() { - String path = "/testFolder/"; - - // folder does not exist yet - assertNull(getStorageManager().getFileByPath(path)); - - SyncOperation syncOp = new CreateFolderOperation(path, user, targetContext, getStorageManager()); - RemoteOperationResult result = syncOp.execute(client); - - assertTrue(result.toString(), result.isSuccess()); - - // folder exists - OCFile file = getStorageManager().getFileByPath(path); - assertTrue(file.isFolder()); - - // cleanup - assertTrue(new RemoveFileOperation(file, false, user, false, targetContext, getStorageManager()) - .execute(client) - .isSuccess()); - } - - @Test - public void testCreateNonExistingSubFolder() { - String path = "/subFolder/1/2/3/4/5/"; - // folder does not exist yet - assertNull(getStorageManager().getFileByPath(path)); - - SyncOperation syncOp = new CreateFolderOperation(path, user, targetContext, getStorageManager()); - RemoteOperationResult result = syncOp.execute(client); - assertTrue(result.toString(), result.isSuccess()); - - // folder exists - OCFile file = getStorageManager().getFileByPath(path); - assertTrue(file.isFolder()); - - // cleanup - new RemoveFileOperation(file, - false, - user, - false, - targetContext, - getStorageManager()) - .execute(client); - } - - @Test - public void testRemoteIdNull() { - getStorageManager().deleteAllFiles(); - assertEquals(0, getStorageManager().getAllFiles().size()); - - OCFile test = new OCFile("/123.txt"); - getStorageManager().saveFile(test); - assertEquals(1, getStorageManager().getAllFiles().size()); - - getStorageManager().deleteAllFiles(); - assertEquals(0, getStorageManager().getAllFiles().size()); - } - - @Test - public void testRenameFolder() throws IOException { - String folderPath = "/testRenameFolder/"; - - // create folder - createFolder(folderPath); - - // upload file inside it - uploadFile(getDummyFile("nonEmpty.txt"), folderPath + "text.txt"); - - // sync folder - assertTrue(new SynchronizeFolderOperation(targetContext, - folderPath, - user, - fileDataStorageManager, - false, - false) - .execute(targetContext) - .isSuccess()); - - // check if file exists - String storagePath1 = fileDataStorageManager.getFileByDecryptedRemotePath(folderPath).getStoragePath(); - assertTrue(new File(storagePath1).exists()); - - String storagePath2 = fileDataStorageManager - .getFileByDecryptedRemotePath(folderPath + "text.txt") - .getStoragePath(); - assertTrue(new File(storagePath2).exists()); - - shortSleep(); - - // Rename - assertTrue( - new RenameFileOperation(folderPath, "test123", fileDataStorageManager) - .execute(targetContext) - .isSuccess() - ); - - // after rename check new location - assertTrue( - new File(fileDataStorageManager.getFileByDecryptedRemotePath("/test123/").getStoragePath()) - .exists() - ); - assertTrue( - new File(fileDataStorageManager.getFileByDecryptedRemotePath("/test123/text.txt").getStoragePath()) - .exists() - ); - - // old files do no exist - assertNull(fileDataStorageManager.getFileByDecryptedRemotePath(folderPath)); - assertNull(fileDataStorageManager.getFileByDecryptedRemotePath(folderPath + "text.txt")); - - // local files also do not exist - assertFalse(new File(storagePath1).exists()); - assertFalse(new File(storagePath2).exists()); - } -} diff --git a/app/src/androidTest/java/com/owncloud/android/FileIT.kt b/app/src/androidTest/java/com/owncloud/android/FileIT.kt new file mode 100644 index 000000000000..7f7d79599886 --- /dev/null +++ b/app/src/androidTest/java/com/owncloud/android/FileIT.kt @@ -0,0 +1,125 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2018 Tobias Kaminsky + * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only + */ +package com.owncloud.android + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.operations.CreateFolderOperation +import com.owncloud.android.operations.RenameFileOperation +import com.owncloud.android.operations.SynchronizeFolderOperation +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import java.io.File + +/** + * Tests related to file operations. + * + * Every test starts with an empty server and an empty local database, and [AbstractOnServerIT.after] wipes both again + * afterwards, so no test needs to clean up after itself. + */ +@RunWith(AndroidJUnit4::class) +class FileIT : AbstractOnServerIT() { + + @Test + fun testCreateFolder() { + val path = "/testFolder/" + assertNull(storageManager.getFileByDecryptedRemotePath(path)) + createFolderOrFail(path) + assertTrue(localFile(path).isFolder) + } + + @Test + fun testCreateNonExistingSubFolder() { + val path = "/subFolder/1/2/3/4/5/" + assertNull(storageManager.getFileByDecryptedRemotePath(path)) + createFolderOrFail(path) + assertTrue(localFile(path).isFolder) + } + + @Test + fun testRemoteIdNull() { + storageManager.deleteAllFiles() + assertEquals(0, storageManager.allFiles.size) + + storageManager.saveFile(OCFile("/123.txt")) + assertEquals(1, storageManager.allFiles.size) + + storageManager.deleteAllFiles() + assertEquals(0, storageManager.allFiles.size) + } + + @Test + fun testRenameFolder() { + val folderPath = "/testRenameFolder/" + val filePath = folderPath + UPLOADED_FILE_NAME + val renamedFolderPath = "/$NEW_FOLDER_NAME/" + val renamedFilePath = renamedFolderPath + UPLOADED_FILE_NAME + + // the upload creates the parent folder on the server and in the local database + uploadFile(getDummyFile(DUMMY_FILE_NAME), filePath) + synchronizeFolder(folderPath) + + val folderCopy = localCopyOf(folderPath) + val fileCopy = localCopyOf(filePath) + assertTrue("$folderPath was not downloaded", folderCopy.exists()) + assertTrue("$filePath was not downloaded", fileCopy.exists()) + + val result = RenameFileOperation(folderPath, NEW_FOLDER_NAME, storageManager).execute(targetContext) + assertTrue("Rename of $folderPath failed: ${result.logMessage}", result.isSuccess) + + assertTrue("$renamedFolderPath has no local copy", localCopyOf(renamedFolderPath).exists()) + assertTrue("$renamedFilePath has no local copy", localCopyOf(renamedFilePath).exists()) + + assertNull(storageManager.getFileByDecryptedRemotePath(folderPath)) + assertNull(storageManager.getFileByDecryptedRemotePath(filePath)) + + assertFalse("$folderPath was not moved locally", folderCopy.exists()) + assertFalse("$filePath was not moved locally", fileCopy.exists()) + } + + private fun createFolderOrFail(remotePath: String) { + val result = CreateFolderOperation(remotePath, user, targetContext, storageManager).execute(client) + assertTrue("Creation of $remotePath failed: ${result.logMessage}", result.isSuccess) + } + + private fun synchronizeFolder(remotePath: String) { + val result = SynchronizeFolderOperation( + targetContext, + remotePath, + user, + storageManager, + false, + false + ).execute(targetContext) + + assertTrue("Sync of $remotePath failed: ${result.logMessage}", result.isSuccess) + } + + private fun localFile(remotePath: String): OCFile { + val file = storageManager.getFileByDecryptedRemotePath(remotePath) + assertNotNull("$remotePath is missing from the local database", file) + return file!! + } + + private fun localCopyOf(remotePath: String): File { + val storagePath = localFile(remotePath).storagePath + assertFalse("$remotePath has no storage path", storagePath.isNullOrEmpty()) + return File(storagePath) + } + + companion object { + private const val DUMMY_FILE_NAME = "nonEmpty.txt" + private const val UPLOADED_FILE_NAME = "text.txt" + private const val NEW_FOLDER_NAME = "test123" + } +} From e92afec910b03c68b0e42b9973db7c03d1c0f8e4 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 17 Sep 2026 16:58:43 +0200 Subject: [PATCH 2/2] wip Signed-off-by: alperozturk96 --- app/src/androidTest/java/com/owncloud/android/FileIT.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/androidTest/java/com/owncloud/android/FileIT.kt b/app/src/androidTest/java/com/owncloud/android/FileIT.kt index 7f7d79599886..a77a3af72530 100644 --- a/app/src/androidTest/java/com/owncloud/android/FileIT.kt +++ b/app/src/androidTest/java/com/owncloud/android/FileIT.kt @@ -1,7 +1,7 @@ /* * Nextcloud - Android Client * - * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2026 Alper Ozturk * SPDX-FileCopyrightText: 2018 Tobias Kaminsky * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only */ @@ -74,7 +74,7 @@ class FileIT : AbstractOnServerIT() { assertTrue("$folderPath was not downloaded", folderCopy.exists()) assertTrue("$filePath was not downloaded", fileCopy.exists()) - val result = RenameFileOperation(folderPath, NEW_FOLDER_NAME, storageManager).execute(targetContext) + val result = RenameFileOperation(folderPath, NEW_FOLDER_NAME, storageManager).execute(client) assertTrue("Rename of $folderPath failed: ${result.logMessage}", result.isSuccess) assertTrue("$renamedFolderPath has no local copy", localCopyOf(renamedFolderPath).exists()) @@ -100,7 +100,7 @@ class FileIT : AbstractOnServerIT() { storageManager, false, false - ).execute(targetContext) + ).execute(client) assertTrue("Sync of $remotePath failed: ${result.logMessage}", result.isSuccess) }