diff --git a/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java b/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java index 35484f2fec8befb4903dc35660eb229af26d3300..4764565303d0be1f91f0c5a28357aeb5928bbfbc 100644 --- a/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java @@ -23,6 +23,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.resources.files.ChunkedFileUploadRemoteOperation; import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation; +import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; import com.owncloud.android.lib.resources.files.FileUtils; import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation; @@ -44,14 +45,14 @@ import timber.log.Timber; * @author Vincent Bourgmayer * High level Operation which upload a local file to a remote cloud storage */ +@SuppressWarnings("rawtypes") public class UploadFileOperation extends RemoteOperation { public final static int FILE_SIZE_FLOOR_FOR_CHUNKED = 3072000; //3MB - private static final Set handledFailureCodes = getHandledFailureCodes(); private final Context context; private final SyncedFileState syncedState; - private final Account account; // TODO Remove as soon as nextcloud library move all Operation to NextcloudClient instead of OwncloudClient + private final Account account; //TODO Remove as soon as nextcloud library move all Operation to NextcloudClient instead of OwncloudClient /** * Construct an upload operation with an already known syncedFileState @@ -90,7 +91,8 @@ public class UploadFileOperation extends RemoteOperation { Timber.d("Upload %s as chunked file", file.getName()); uploadResult = uploadChunkedFile(file, client); } else { - uploadResult = uploadFile(file, client); + final boolean checkEtag = ifMatchETagRequired(client); + uploadResult = uploadFile(file, client, checkEtag); } final ResultCode resultCode; @@ -169,7 +171,6 @@ public class UploadFileOperation extends RemoteOperation { return ResultCode.OK; } - /** * Update syncedFileState (etag & last modified) in case of successful upload * @param uploadResult The Upload's result instance @@ -178,7 +179,7 @@ public class UploadFileOperation extends RemoteOperation { */ private void updateSyncedFileState(final RemoteOperationResult uploadResult, final long fileLastModified, final OwnCloudClient client) { //The below if statement should only be called for chunked upload. But - //for some unknown reason, the simple file upload doesn't give the etag in the result + //for some unknown reason, the simple file upload doesn't give the eTag in the result // so, I moved the code here as a security if (uploadResult.getResultData() == null) { final RemoteOperationResult result = readRemoteFile(syncedState.getRemotePath(), client); @@ -259,23 +260,59 @@ public class UploadFileOperation extends RemoteOperation { return uploadOperation.execute(client); } + /** + * Check that the remote file exists + * @param remotePath path of remote file + * @param client OwncloudClient instance to perform the request + * @return true if the remote file exist, false otherwise + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + public boolean remoteFileExist(@NonNull String remotePath, @NonNull OwnCloudClient client) { + final ExistenceCheckRemoteOperation operation = new ExistenceCheckRemoteOperation(remotePath, false); + final RemoteOperationResult result = operation.execute(client); + return result.isSuccess(); + } + + /** + * define if upload request should embed a "if-match" header + * with eTag. + * + * - Only check for etag if the file can be downloaded, aka media files + * (pictures, music, etc.) + * - Only check for etag, if a previous eTag was already known + * which means that the file has already been on the cloud + * - Only check for eTag if the file is still on the cloud or we will get http 412 + * + * @param client OwnCloudClient instance used to check if remote file exists + * @return true if the if-match header should be added + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + public boolean ifMatchETagRequired(@NonNull OwnCloudClient client) { + return syncedState.isMediaType() + && !syncedState.getLastETAG().isEmpty() + && remoteFileExist(syncedState.getRemotePath(), client); + } /** * Upload a file * note: this has been extracted from run(...) for * testing purpose + * @param file File instance representing the file to upload * @param client client to run the method. TODO will be replaced by NextcloudClient in future. + * @param checkEtag indicate if upload request must have a if-match header with eTag value * @return RemoteOperationResult the instance must contains etag in resultData if successful. */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) @NonNull - public RemoteOperationResult uploadFile(@NonNull final File file, @NonNull final OwnCloudClient client) { - final String timeStamp = ((Long) (file.lastModified() / 1000) ).toString() ; + public RemoteOperationResult uploadFile(@NonNull final File file, @NonNull final OwnCloudClient client, boolean checkEtag) { + final String timeStamp = ((Long) (file.lastModified() / 1000) ).toString(); + final String eTag = checkEtag ? syncedState.getLastETAG() : null; + final UploadFileRemoteOperation uploadOperation = new UploadFileRemoteOperation(syncedState.getLocalPath(), syncedState.getRemotePath(), CommonUtils.getMimeType(file), - (!this.syncedState.isMediaType() || syncedState.getLastETAG().isEmpty())? null : syncedState.getLastETAG(), //If not null, This can cause error 412; that means remote file has change - timeStamp ); + eTag, //If not null, This can cause error 412; that means remote file has change + timeStamp); return uploadOperation.execute(client); } @@ -297,4 +334,4 @@ public class UploadFileOperation extends RemoteOperation { public SyncedFileState getSyncedState() { return syncedState; } -} +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/services/InitializerService.java b/app/src/main/java/foundation/e/drive/services/InitializerService.java index b8d875353c2304b3013d400bd46654183c8ee7c3..ecf74702552c742a754d5dc6fd5a529e726389ee 100644 --- a/app/src/main/java/foundation/e/drive/services/InitializerService.java +++ b/app/src/main/java/foundation/e/drive/services/InitializerService.java @@ -28,6 +28,7 @@ import timber.log.Timber; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import androidx.work.WorkManager; /** @@ -78,7 +79,8 @@ public class InitializerService extends Service { * - Account available * @return true if condition are met */ - private boolean checkStartConditions(@NonNull final SharedPreferences prefs, + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + public boolean checkStartConditions(@NonNull final SharedPreferences prefs, @NonNull final String accountName, @NonNull final String accountType) { if (prefs.getBoolean(AppConstants.INITIALIZATION_HAS_BEEN_DONE, false)) { Timber.w("Initialization has already been done"); diff --git a/app/src/test/java/foundation/e/drive/TestUtils.java b/app/src/test/java/foundation/e/drive/TestUtils.java index 19861db817c02ccc0b891b8837efdc16433f2a7d..3ff562f96459d58ae8ffaeddbdc0d468fe159e21 100644 --- a/app/src/test/java/foundation/e/drive/TestUtils.java +++ b/app/src/test/java/foundation/e/drive/TestUtils.java @@ -50,7 +50,6 @@ public abstract class TestUtils { TEST_SERVER_URI = properties.getProperty("test.account.url"); } - /** * Get the valid Account object. Create it if it isn't already instanciated * @return Account @@ -63,7 +62,6 @@ public abstract class TestUtils { return validAccount; } - public static NextcloudClient getNcClient(Context context) { final Uri serverUri = Uri.parse(TEST_SERVER_URI); return new NextcloudClient(serverUri, TEST_ACCOUNT_NAME, TEST_ACCOUNT_PASSWORD, context); @@ -126,9 +124,8 @@ public abstract class TestUtils { } } - /** - * Method adapted from https://github.com/nextcloud/android/blob/master/src/androidTest/java/com/owncloud/android/AbstractIT.java + * Method adapted from ... * @param filePath path of the file to create * @param iteration number of time to write dummy content * @return the File instance @@ -144,7 +141,6 @@ public abstract class TestUtils { file.createNewFile(); final FileWriter writer = new FileWriter(file); - for (int i = 0; i < iteration; i++) { writer.write("123123123123123123123123123\n"); } @@ -154,16 +150,14 @@ public abstract class TestUtils { return file; } - /** * Delete a local directory with all its content. - * Adapted from https://www.geeksforgeeks.org/java-program-to-delete-a-directory/ + * Adapted from ... * @param file */ public static void deleteDirectory(File file) { for (File subfile : file.listFiles()) { - if (subfile.isDirectory()) { deleteDirectory(subfile); } @@ -172,7 +166,6 @@ public abstract class TestUtils { file.delete(); } - public static void initializeWorkmanager(Context context) { final Configuration config = new Configuration.Builder() .setMinimumLoggingLevel(Log.DEBUG) @@ -181,4 +174,4 @@ public abstract class TestUtils { WorkManagerTestInitHelper.initializeTestWorkManager( context, config); } -} +} \ No newline at end of file diff --git a/app/src/test/java/foundation/e/drive/operations/UploadFileOperationTest.java b/app/src/test/java/foundation/e/drive/operations/UploadFileOperationTest.java index 2ba3e269162d81417df1d3c48c747eee32e78e38..2e2eaf48fd115b10bf4df22e242c05b00f051d8b 100644 --- a/app/src/test/java/foundation/e/drive/operations/UploadFileOperationTest.java +++ b/app/src/test/java/foundation/e/drive/operations/UploadFileOperationTest.java @@ -21,7 +21,6 @@ import com.owncloud.android.lib.common.UserInfo; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; @@ -38,23 +37,18 @@ import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.SyncedFileState; import foundation.e.drive.models.SyncedFolder; import foundation.e.drive.TestUtils; -import foundation.e.drive.utils.CommonUtils; import foundation.e.drive.utils.DavClientProvider; - +@SuppressWarnings("rawtypes") @RunWith(RobolectricTestRunner.class) @Config(sdk = Build.VERSION_CODES.O, manifest = Config.NONE) public class UploadFileOperationTest { - private List syncedFileStates= new ArrayList<>(); private final OwnCloudClient ocClient; private final NextcloudClient ncClient; private final AccountManager accountManager; private final Context context; - private long userFreeQuota; - private long userTotalQuota; - private long userUsedQuota; - private double userRelativeQuota; + private final long userFreeQuota = 50; private final Account account; public UploadFileOperationTest() { @@ -66,15 +60,11 @@ public class UploadFileOperationTest { account = TestUtils.getValidAccount(); ocClient = DavClientProvider.getInstance().getClientInstance(account, context); ncClient = TestUtils.getNcClient(context); - userFreeQuota = 50; - userTotalQuota = 100; - userUsedQuota = 50; - userRelativeQuota = 50.0; } @Before public void setUp() { - prepareDB(); //Create DB + prepareDB(); assertNotNull("Client is null. unexpected!", ocClient); } @@ -87,7 +77,6 @@ public class UploadFileOperationTest { DbHelper.insertSyncedFolder(createSyncedFolder("medium"), context); DbHelper.insertSyncedFolder(createSyncedFolder("large"), context); - //assertion for debug purpose assertEquals("There isn't three folder in DB as expected", 3, DbHelper.getSyncedFolderList(context, true).size()); } @@ -98,8 +87,8 @@ public class UploadFileOperationTest { */ private SyncedFolder createSyncedFolder(String name) { return new SyncedFolder(name, - TestUtils.TEST_LOCAL_ROOT_FOLDER_PATH+name+"/", - TestUtils.TEST_REMOTE_ROOT_FOLDER_PATH+name+"/", + TestUtils.TEST_LOCAL_ROOT_FOLDER_PATH + name + "/", + TestUtils.TEST_REMOTE_ROOT_FOLDER_PATH + name + "/", true, true, true, true); } @@ -107,7 +96,7 @@ public class UploadFileOperationTest { * Create a local small file to use for upload test */ private File createSmallFile() { - final String smallDummyFilePath = TestUtils.TEST_LOCAL_ROOT_FOLDER_PATH+"small/dummy.txt"; + final String smallDummyFilePath = TestUtils.TEST_LOCAL_ROOT_FOLDER_PATH + "small/dummy.txt"; File file = null; try { file = TestUtils.createFile(smallDummyFilePath, 2); @@ -115,7 +104,11 @@ public class UploadFileOperationTest { fail(e.getMessage()); } - final SyncedFileState sfs = new SyncedFileState(-1, "dummy.txt", TestUtils.TEST_LOCAL_ROOT_FOLDER_PATH+"small/dummy.txt", TestUtils.TEST_REMOTE_ROOT_FOLDER_PATH+"small/dummy.txt", "", 0l, 0, true, 3); + final SyncedFileState sfs = new SyncedFileState(-1, + "dummy.txt", + TestUtils.TEST_LOCAL_ROOT_FOLDER_PATH + "small/dummy.txt", + TestUtils.TEST_REMOTE_ROOT_FOLDER_PATH + "small/dummy.txt", + "", 0L, 0, true, 3); sfs.setId(DbHelper.manageSyncedFileStateDB(sfs, "INSERT", context)); syncedFileStates.add(sfs); @@ -123,22 +116,20 @@ public class UploadFileOperationTest { } /** - * Remove SmallFile locally and remotly if it exist + * Remove SmallFile locally if it exist * This method has just been made to make basic test to work - * It should be refactored for next state, and test improvement + * todo: refactor for next state, and test improvement * @return true if file deleted or if it doesn't exist */ private boolean removeSmallFile() { if (!syncedFileStates.isEmpty()) { final SyncedFileState sfs = syncedFileStates.get(0); if (sfs != null) { - //final RemoveFileOperation removeRemoteFileOp = new RemoveFileOperation(sfs); - //removeRemoteFileOp.execute(ocClient); syncedFileStates.remove(sfs); } } - final String smallDummyFilePath = TestUtils.TEST_LOCAL_ROOT_FOLDER_PATH+"small/dummy.txt"; + final String smallDummyFilePath = TestUtils.TEST_LOCAL_ROOT_FOLDER_PATH + "small/dummy.txt"; final File smallFile = new File(smallDummyFilePath); if (smallFile.exists()) { return smallFile.delete(); @@ -149,26 +140,25 @@ public class UploadFileOperationTest { * test upload of a file and check that it's ok */ @Test - //@Ignore("Mocking file uploading doesn't work, and I don't find why; But this isn't related to method under test") public void uploadNewSmallFile_shouldwork() { - //tearDown removeSmallFile(); //clean the environnement final File file = createSmallFile(); //preparation final SyncedFileState sfs_fromDB = DbHelper.loadSyncedFile(context, syncedFileStates.get(0).getLocalPath(), true); - assertTrue("SyncedFileState loaded from DB must have an empty Etag", sfs_fromDB.getLastETAG().isEmpty()); - boolean checkEtag = false; + assertTrue("SyncedFileState loaded from DB must have an empty ETag", sfs_fromDB.getLastETAG().isEmpty()); final UploadFileOperation operation = Mockito.spy(new UploadFileOperation(syncedFileStates.get(0), account, context)); + mockCreateRemoteDir(true, operation, sfs_fromDB.getRemotePath()); mockUserInfoReading(operation); - mockSuccessfulFileUpload(operation, file); + mockFileHeadOperation(true, operation, sfs_fromDB.getRemotePath()); + mockSuccessfulFileUpload(operation, file, false); final RemoteOperationResult result = operation.execute(ocClient); - String errorMsg = "The upload failed:\n http code: "+result.getHttpCode() - +"\n, is success ?"+result.isSuccess() - +"\n, log msg: "+result.getLogMessage() - +"\n, is server fail ? "+result.isServerFail(); + String errorMsg = "The upload failed:\n http code: " + result.getHttpCode() + + "\n, is success ?" + result.isSuccess() + + "\n, log msg: " + result.getLogMessage() + + "\n, is server fail ? " + result.isServerFail(); if (result.getException() != null) { - errorMsg += "\n, exception msg: "+result.getException().getMessage(); + errorMsg += "\n, exception msg: " + result.getException().getMessage(); } assertTrue( errorMsg, result.isSuccess()); @@ -176,27 +166,6 @@ public class UploadFileOperationTest { assertFalse("After upload, the database must store the etag of the syncedFileState. But here it is empty", sfs_fromDBAfterUpload.getLastETAG().isEmpty()); } - - - - /** - * Try to upload a file with a null SyncedFileState instance - * Must return a "Forbidden" result code - */ - @Ignore("Ignored until UploadFileOperation has fixed the NPE") - @Test - public void nullSyncedFileState_shouldFail() { - - SyncedFileState syncedFileState = null; - //Test fails at the moment because of UploadFileOperation's constructor not checking for syncedFileState is null) - // check https://gitlab.e.foundation/e/apps/eDrive/-/issues/120 - final UploadFileOperation testOperation = new UploadFileOperation(syncedFileState, account, context); - - RemoteOperationResult result = testOperation.execute(ocClient); - assertEquals("Expected result code was FORBIDDEN but got: "+result.getCode().name(), RemoteOperationResult.ResultCode.FORBIDDEN, result.getCode()); - } - - /** * Try to upload local file that has been removed between uploadOperation's creation and * ploadOperation execution @@ -216,22 +185,20 @@ public class UploadFileOperationTest { assertTrue("Local file deletion return false instead of true", smallFile.delete()); final RemoteOperationResult result = testOperation.execute(ocClient); - assertEquals("Expected result code was FORBIDDEN but got: "+result.getCode().name(), RemoteOperationResult.ResultCode.FORBIDDEN, result.getCode()); + assertEquals("Expected result code was FORBIDDEN but got: " + result.getCode().name(), RemoteOperationResult.ResultCode.FORBIDDEN, result.getCode()); } - /** * Assert that uploading a file that is bigger than free quotas isn't allowed */ @Test public void fileSizeBiggerThanFreeQuota_shouldnotBeAllowed() { - //long freeQuota = getUserRemoteFreeQuota(); - assertFalse("Reading remote free quota fails"+userFreeQuota, -1 == userFreeQuota); - //We don't care of parameter of UploadFileOperation's constructor + assertNotEquals("Reading remote free quota fails" + userFreeQuota, -1, userFreeQuota); + final UploadFileOperation operation = Mockito.spy(new UploadFileOperation(Mockito.mock(SyncedFileState.class), account, context)); mockUserInfoReading(operation); final RemoteOperationResult actualResult = operation.checkAvailableSpace(ncClient, (userFreeQuota+1)); - assertEquals("Quota check ("+ userFreeQuota+"vs"+(userFreeQuota+1)+") failed", RemoteOperationResult.ResultCode.QUOTA_EXCEEDED, actualResult.getCode()); + assertEquals("Quota check (" + userFreeQuota + "vs" + (userFreeQuota+1) + ") failed", RemoteOperationResult.ResultCode.QUOTA_EXCEEDED, actualResult.getCode()); } /** @@ -239,15 +206,13 @@ public class UploadFileOperationTest { */ @Test public void fileSizeEqualToFreeQuota_shouldBeAllowed() { - //I don't know why but it always fail for this test. - //long freeQuota = getUserRemoteFreeQuota(); - assertFalse("Reading remote free quota fails"+userFreeQuota, -1 == userFreeQuota); + assertNotEquals("Reading remote free quota fails" + userFreeQuota, -1, userFreeQuota); final UploadFileOperation operation = Mockito.spy(new UploadFileOperation(Mockito.mock(SyncedFileState.class), account, context)); mockUserInfoReading(operation); final RemoteOperationResult actualResult = operation.checkAvailableSpace(ncClient, userFreeQuota); - assertNotEquals("Quota check is Quota Exceeded ("+ userFreeQuota+" vs "+userFreeQuota+")", + assertNotEquals("Quota check is Quota Exceeded (" + userFreeQuota + " vs " + userFreeQuota + ")", RemoteOperationResult.ResultCode.QUOTA_EXCEEDED, actualResult.getCode()); assertEquals("Quota Check is not OK", @@ -255,37 +220,125 @@ public class UploadFileOperationTest { actualResult.getCode()); } - /** * Assert that uploading a file which size is lower than the amount of free quota is allowed * */ @Test public void fileSizeSmallerThanFreeQuota_shouldBeAllowed() { - //long freeQuota = getUserRemoteFreeQuota(); - assertFalse("Reading remote free quota fails "+userFreeQuota, -1 == userFreeQuota); + assertNotEquals("Reading remote free quota fails " + userFreeQuota, -1, userFreeQuota); final UploadFileOperation operation = Mockito.spy(new UploadFileOperation(Mockito.mock(SyncedFileState.class), account, context)); mockUserInfoReading(operation); final RemoteOperationResult actualResult = operation.checkAvailableSpace(ncClient, (userFreeQuota-1)); - assertEquals("Quota check ("+ userFreeQuota+" vs "+(userFreeQuota-1)+") failed", + assertEquals("Quota check (" + userFreeQuota + " vs " + (userFreeQuota-1) + ") failed", RemoteOperationResult.ResultCode.OK, actualResult.getCode()); } + @Test + public void ifMatchEtagRequired_notMediaType_expectedFalse() { + final SyncedFileState testSyncedState = new SyncedFileState(1, + "test.jpg", + "pictures/toto.jpg", + "pictures/test.jpg", + "123456", + 11111220, + 1, + false, + 3); + + assertFalse("SyncedFileState should not have a media type but it has", testSyncedState.isMediaType()); + + final UploadFileOperation operationUnderTest = new UploadFileOperation(testSyncedState, account, context); + final boolean addIfMatchHeader =operationUnderTest.ifMatchETagRequired(ocClient); + assertFalse("Expected result for ifMatchETagRequired(client) was false but got: true", addIfMatchHeader); + } + + @Test + public void ifMatchETagRequired_empyEtag_expectedFalse() { + final SyncedFileState testSyncedState = new SyncedFileState(1, + "test.jpg", + "pictures/toto.jpg", + "pictures/test.jpg", + "", + 11111220, + 1, + true, + 3); + + assertTrue("SyncedFileState's ETag should be empty but isn't", testSyncedState.getLastETAG().isEmpty()); + assertTrue("SyncedFileState is not a media type but it should", testSyncedState.isMediaType()); + final UploadFileOperation operationUnderTest = new UploadFileOperation(testSyncedState, account, context); + final boolean addIfMatchHeader =operationUnderTest.ifMatchETagRequired(ocClient); + assertFalse("Expected result for ifMatchETagRequired(client) was false but got: true", addIfMatchHeader); + } + + @Test + public void ifMatchETagRequired_missingRemoteFile_expectedFalse() { + final SyncedFileState testSyncedState = new SyncedFileState(1, + "test.jpg", + "pictures/toto.jpg", + "pictures/test.jpg", + "123456", + 11111220, + 1, + true, + 3); + + assertFalse("SyncedFileState's ETag should not be empty but isn't", testSyncedState.getLastETAG().isEmpty()); + assertTrue("SyncedFileState is not a media type but it should", testSyncedState.isMediaType()); + final UploadFileOperation operationUnderTest = Mockito.spy(new UploadFileOperation(testSyncedState, account, context)); + mockFileHeadOperation(false, operationUnderTest, testSyncedState.getRemotePath()); + final boolean addIfMatchHeader =operationUnderTest.ifMatchETagRequired(ocClient); + assertFalse("Expected result for ifMatchETagRequired(client) is false but got: true", addIfMatchHeader); + } + + @Test + public void ifMatchETagRequired_expectedTrue() { + final SyncedFileState testSyncedState = new SyncedFileState(1, + "test.jpg", + "pictures/toto.jpg", + "pictures/test.jpg", + "123456", + 11111220, + 1, + true, + 3); + + assertFalse("SyncedFileState's ETag should not be empty but isn't", testSyncedState.getLastETAG().isEmpty()); + assertTrue("SyncedFileState is not a media type but it should", testSyncedState.isMediaType()); + final UploadFileOperation operationUnderTest = Mockito.spy(new UploadFileOperation(testSyncedState, account, context)); + mockFileHeadOperation(true, operationUnderTest, testSyncedState.getRemotePath()); + final boolean addIfMatchHeader =operationUnderTest.ifMatchETagRequired(ocClient); + assertTrue("Expected result for ifMatchETagRequired(client) is true but got: false", addIfMatchHeader); + } private void mockUserInfoReading(UploadFileOperation instanceUnderTest) { + final long userTotalQuota = 100; + final long userUsedQuota = 50; + final double userRelativeQuota = 50; final Quota quota = new Quota(userFreeQuota, userUsedQuota, userTotalQuota, userRelativeQuota, 100); final UserInfo uInfo = new UserInfo("id", true, "toto", "toto@toto.com", "+123456789", "adress", "", "", quota, null); - final RemoteOperationResult mockResponse = new RemoteOperationResult(RemoteOperationResult.ResultCode.OK); + final RemoteOperationResult mockResponse = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK); mockResponse.setResultData(uInfo); Mockito.doReturn(mockResponse).when(instanceUnderTest).readUserInfo(ncClient); } - private void mockSuccessfulFileUpload(final UploadFileOperation instanceUnderTest, final File file) { + @SuppressWarnings("SameParameterValue") + private void mockSuccessfulFileUpload(final UploadFileOperation instanceUnderTest, final File file, final boolean checkETag) { final String eTag = "123456789"; - final RemoteOperationResult mockResponse = new RemoteOperationResult(RemoteOperationResult.ResultCode.OK); + final RemoteOperationResult mockResponse = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK); mockResponse.setResultData(eTag); - Mockito.doReturn(mockResponse).when(instanceUnderTest).uploadFile(file, ocClient); + Mockito.doReturn(mockResponse).when(instanceUnderTest).uploadFile(file, ocClient, checkETag); + } + + private void mockFileHeadOperation(boolean expectedResult, final UploadFileOperation instanceUdnerTest, final String remotePath) { + Mockito.doReturn(expectedResult).when(instanceUdnerTest).remoteFileExist(remotePath, ocClient); + } + + @SuppressWarnings("SameParameterValue") + private void mockCreateRemoteDir(boolean successExpected, final UploadFileOperation instanceUnderTest, final String remotePath) { + Mockito.doReturn(successExpected).when(instanceUnderTest).createRemoteFolder(remotePath, ocClient); } } \ No newline at end of file diff --git a/app/src/test/java/foundation/e/drive/services/AbstractServiceIT.java b/app/src/test/java/foundation/e/drive/services/AbstractServiceIT.java index 314e1141c4b982e3a25cec894c5b3608cf1e10c3..6d82245a0670453fa0fc91a32656ab1f9f22b093 100644 --- a/app/src/test/java/foundation/e/drive/services/AbstractServiceIT.java +++ b/app/src/test/java/foundation/e/drive/services/AbstractServiceIT.java @@ -116,6 +116,6 @@ public abstract class AbstractServiceIT { .putString(AccountManager.KEY_ACCOUNT_TYPE, TEST_ACCOUNT_TYPE) .putInt(AppConstants.INITIALFOLDERS_NUMBER, initial_folder_number) .putLong(AppConstants.KEY_LAST_SYNC_TIME, last_sync_time) - .commit(); + .apply(); } } diff --git a/app/src/test/java/foundation/e/drive/services/InitializerServiceTest.java b/app/src/test/java/foundation/e/drive/services/InitializerServiceTest.java index 725d8bd8d080d4297568813adaecf2db5dd36099..ca5febde32ca4d45688701e970af2035ffb5371b 100644 --- a/app/src/test/java/foundation/e/drive/services/InitializerServiceTest.java +++ b/app/src/test/java/foundation/e/drive/services/InitializerServiceTest.java @@ -1,6 +1,6 @@ package foundation.e.drive.services; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.accounts.AccountManager; @@ -8,14 +8,9 @@ import android.app.job.JobScheduler; import android.content.Context; import android.net.ConnectivityManager; - import androidx.test.core.app.ApplicationProvider; -import androidx.work.WorkManager; - import org.junit.Test; import org.robolectric.Robolectric; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.shadows.ShadowLog; import foundation.e.drive.TestUtils; import foundation.e.drive.database.DbHelper; @@ -24,7 +19,6 @@ import foundation.e.drive.utils.AppConstants; public class InitializerServiceTest extends AbstractServiceIT{ public InitializerServiceTest(){ - mServiceController = Robolectric.buildService(InitializerService.class); mService = mServiceController.get(); context = ApplicationProvider.getApplicationContext(); @@ -36,52 +30,36 @@ public class InitializerServiceTest extends AbstractServiceIT