From 76dd4e2cbdca0e6f07b6ccf36b4132264ca71540 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Thu, 14 Feb 2019 14:22:02 +0100 Subject: [PATCH] test CreateFolderOperation without server Signed-off-by: tobiasKaminsky --- build.gradle | 2 +- .../datamodel/FileDataStorageManager.java | 2 +- .../FileDataStorageManagerInterface.java | 58 +++++++ .../owncloud/android/datamodel/OCFile.java | 2 +- .../datamodel/ThumbnailsCacheManager.java | 4 +- .../operations/CreateFolderOperation.java | 16 +- .../SynchronizeFolderOperation.java | 6 +- .../operations/common/SyncOperation.java | 53 +++---- .../android/utils/FileStorageUtils.java | 3 +- .../android/FileDataStorageManagerLocal.java | 149 ++++++++++++++++++ .../operations/CreateFolderOperationTest.java | 73 +++++++++ 11 files changed, 328 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerInterface.java create mode 100644 src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java create mode 100644 src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java diff --git a/build.gradle b/build.gradle index 6ddf3e47efde..145eea547651 100644 --- a/build.gradle +++ b/build.gradle @@ -253,7 +253,7 @@ dependencies { // JUnit4 Rules androidTestImplementation 'androidx.test:rules:1.1.1' // Android JUnit Runner - androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.ext:junit:1.1.0' // Espresso core androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index be03b333c882..481c203bd0ed 100644 --- a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -67,7 +67,7 @@ import lombok.Setter; @Getter -public class FileDataStorageManager { +public class FileDataStorageManager implements FileDataStorageManagerInterface { private static final String TAG = FileDataStorageManager.class.getSimpleName(); private static final String AND = "=? AND "; diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerInterface.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerInterface.java new file mode 100644 index 000000000000..bc1952da0b0f --- /dev/null +++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerInterface.java @@ -0,0 +1,58 @@ +package com.owncloud.android.datamodel; + +import android.accounts.Account; + +import com.owncloud.android.lib.resources.shares.OCShare; +import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.lib.resources.status.OCCapability; + +import java.util.Collection; +import java.util.List; + +import androidx.annotation.Nullable; + +public interface FileDataStorageManagerInterface { + + OCFile getFileByPath(String path); + + Account getAccount(); + + @Nullable + OCFile getFileById(long id); + + void saveConflict(OCFile file, String etagInConflict); + + void deleteFileInMediaScan(String path); + + boolean saveFile(OCFile file); + + boolean fileExists(long id); + + List getFolderContent(OCFile f, boolean onlyOnDevice); + + void saveFolder(OCFile folder, Collection updatedFiles, Collection filesToRemove); + + boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy); + + boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent); + + void moveLocalFile(OCFile file, String targetPath, String targetParentPath); + + boolean saveShare(OCShare share); + + List getSharesWithForAFile(String filePath, String accountName); + + void removeShare(OCShare share); + + void copyLocalFile(OCFile file, String targetPath); + + OCShare getFirstShareByPathAndType(String path, ShareType type, String shareWith); + + OCCapability saveCapabilities(OCCapability capability); + + void saveSharesDB(List shares); + + void removeSharesForFile(String remotePath); + + OCShare getShareById(long id); +} diff --git a/src/main/java/com/owncloud/android/datamodel/OCFile.java b/src/main/java/com/owncloud/android/datamodel/OCFile.java index 512fe5350e59..6a4a725e1090 100644 --- a/src/main/java/com/owncloud/android/datamodel/OCFile.java +++ b/src/main/java/com/owncloud/android/datamodel/OCFile.java @@ -54,7 +54,7 @@ public class OCFile implements Parcelable, Comparable, ServerFileInterfa private static final String TAG = OCFile.class.getSimpleName(); - @Getter @Setter private long fileId; // android internal ID of the file + @Getter @Setter private long fileId; // android internal ID of the file @Getter @Setter private long parentId; @Getter @Setter private long fileLength; @Getter @Setter private long creationTimestamp; // UNIX timestamp of the time the file was created diff --git a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index f76b6208edde..a94a26ab9da0 100644 --- a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@ -399,7 +399,7 @@ public static class ThumbnailGenerationTask extends AsyncTask mAsyncTasks; private Object mFile; private String mImageKey; - private FileDataStorageManager mStorageManager; + private FileDataStorageManagerInterface mStorageManager; private GetMethod getMethod; public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) @@ -424,7 +424,7 @@ public GetMethod getGetMethod() { return getMethod; } - public ThumbnailGenerationTask(FileDataStorageManager storageManager, Account account){ + public ThumbnailGenerationTask(FileDataStorageManagerInterface storageManager, Account account) { if (storageManager == null) { throw new IllegalArgumentException("storageManager must not be NULL"); } diff --git a/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java b/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java index 1c78c60a2d0b..05983637fa1a 100644 --- a/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java +++ b/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java @@ -60,11 +60,11 @@ public CreateFolderOperation(String remotePath, boolean createFullPath) { @Override - protected RemoteOperationResult run(OwnCloudClient client) { - RemoteOperationResult result = new CreateFolderRemoteOperation(mRemotePath, mCreateFullPath).execute(client); + public RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result = createCreateFolderRemoteOperation(mRemotePath, mCreateFullPath).execute(client); if (result.isSuccess()) { - RemoteOperationResult remoteFolderOperationResult = new ReadFolderRemoteOperation(mRemotePath) + RemoteOperationResult remoteFolderOperationResult = createReadFolderRemoteOperation(mRemotePath) .execute(client, true); createdRemoteFolder = (RemoteFile) remoteFolderOperationResult.getData().get(0); @@ -76,6 +76,14 @@ protected RemoteOperationResult run(OwnCloudClient client) { return result; } + public CreateFolderRemoteOperation createCreateFolderRemoteOperation(String mRemotePath, boolean mCreateFullPath) { + return new CreateFolderRemoteOperation(mRemotePath, mCreateFullPath); + } + + public ReadFolderRemoteOperation createReadFolderRemoteOperation(String mRemotePath) { + return new ReadFolderRemoteOperation(mRemotePath); + } + @Override public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { if (operation instanceof CreateFolderRemoteOperation) { @@ -120,7 +128,7 @@ private void saveFolderInDB() { newDir.setEncrypted(FileStorageUtils.checkEncryptionStatus(newDir, getStorageManager())); getStorageManager().saveFile(newDir); - Log_OC.d(TAG, "Create directory " + mRemotePath + " in Database"); + // Log_OC.d(TAG, "Create directory " + mRemotePath + " in Database"); } } diff --git a/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java index 32cf1605873c..77655026fd50 100644 --- a/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -25,7 +25,7 @@ import android.content.Intent; import android.util.Log; -import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerInterface; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.lib.common.OwnCloudClient; @@ -225,7 +225,7 @@ private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) th private void removeLocalFolder() { - FileDataStorageManager storageManager = getStorageManager(); + FileDataStorageManagerInterface storageManager = getStorageManager(); if (storageManager.fileExists(mLocalFolder.getFileId())) { String currentSavePath = FileStorageUtils.getSavePath(mAccount.name); storageManager.removeFolder( @@ -260,7 +260,7 @@ private void synchronizeData(List folderAndFiles) throws OperationCancel throw new OperationCancelledException(); } - FileDataStorageManager storageManager = getStorageManager(); + FileDataStorageManagerInterface storageManager = getStorageManager(); List updatedFiles = new Vector<>(folderAndFiles.size() - 1); // get current data about local contents of the folder to synchronize diff --git a/src/main/java/com/owncloud/android/operations/common/SyncOperation.java b/src/main/java/com/owncloud/android/operations/common/SyncOperation.java index a09f17eaf904..b2c806c6b7fe 100644 --- a/src/main/java/com/owncloud/android/operations/common/SyncOperation.java +++ b/src/main/java/com/owncloud/android/operations/common/SyncOperation.java @@ -24,6 +24,7 @@ import android.os.Handler; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerInterface; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -33,33 +34,33 @@ /** * Operation which execution involves both interactions with an ownCloud server and * with local data in the device. - * + * * Provides methods to execute the operation both synchronously or asynchronously. */ public abstract class SyncOperation extends RemoteOperation { - + //private static final String TAG = SyncOperation.class.getSimpleName(); - private FileDataStorageManager mStorageManager; - - public FileDataStorageManager getStorageManager() { + private FileDataStorageManagerInterface mStorageManager; + + public FileDataStorageManagerInterface getStorageManager() { return mStorageManager; } - + /** * Synchronously executes the operation on the received ownCloud account. - * + * * Do not call this method from the main thread. - * + * * This method should be used whenever an ownCloud account is available, instead of - * {@link #execute(OwnCloudClient, com.owncloud.android.datamodel.FileDataStorageManager)}. - * + * {@link #execute(OwnCloudClient, com.owncloud.android.datamodel.FileDataStorageManagerInterface)}. + * * @param storageManager * @param context Android context for the component calling the method. * @return Result of the operation. */ - public RemoteOperationResult execute(FileDataStorageManager storageManager, Context context) { + public RemoteOperationResult execute(FileDataStorageManagerInterface storageManager, Context context) { if (storageManager == null) { throw new IllegalArgumentException("Trying to execute a sync operation with a " + "NULL storage manager"); @@ -71,35 +72,33 @@ public RemoteOperationResult execute(FileDataStorageManager storageManager, Cont mStorageManager = storageManager; return super.execute(mStorageManager.getAccount(), context); } - - - /** + + + /** * Synchronously executes the remote operation - * + * * Do not call this method from the main thread. - * + * * @param client Client object to reach an ownCloud server during the execution of the o * peration. * @param storageManager * @return Result of the operation. */ - public RemoteOperationResult execute(OwnCloudClient client, - FileDataStorageManager storageManager) { + public RemoteOperationResult execute(OwnCloudClient client, FileDataStorageManagerInterface storageManager) { if (storageManager == null) { - throw new IllegalArgumentException("Trying to execute a sync operation with a " + - "NULL storage manager"); + throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); } mStorageManager = storageManager; return super.execute(client); } - + /** * Asynchronously executes the remote operation - * + * * This method should be used whenever an ownCloud account is available, instead of * {@link #execute(OwnCloudClient)}. - * + * * @param account ownCloud account in remote ownCloud server to reach during the * execution of the operation. * @param context Android context for the component calling the method. @@ -125,10 +124,10 @@ public Thread execute(FileDataStorageManager storageManager, } */ - - /** + + /** * Asynchronously executes the remote operation - * + * * @param client Client object to reach an ownCloud server during the * execution of the operation. * @param listener Listener to be notified about the execution of the operation. @@ -146,5 +145,5 @@ public Thread execute(OwnCloudClient client, FileDataStorageManager storageManag return super.execute(client, listener, listenerHandler); } - + } diff --git a/src/main/java/com/owncloud/android/utils/FileStorageUtils.java b/src/main/java/com/owncloud/android/utils/FileStorageUtils.java index 415f305ea9d2..021883b0118e 100644 --- a/src/main/java/com/owncloud/android/utils/FileStorageUtils.java +++ b/src/main/java/com/owncloud/android/utils/FileStorageUtils.java @@ -27,6 +27,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerInterface; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.files.model.RemoteFile; @@ -409,7 +410,7 @@ public static void checkIfFileFinishedSaving(OCFile file) { * @param storageManager up to date reference to storage manager * @return true if file itself or ancestor is encrypted */ - public static boolean checkEncryptionStatus(OCFile file, FileDataStorageManager storageManager) { + public static boolean checkEncryptionStatus(OCFile file, FileDataStorageManagerInterface storageManager) { if (file.isEncrypted()) { return true; } diff --git a/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java b/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java new file mode 100644 index 000000000000..5a06acd56a71 --- /dev/null +++ b/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java @@ -0,0 +1,149 @@ +package com.owncloud.android; + +import android.accounts.Account; + +import com.owncloud.android.datamodel.FileDataStorageManagerInterface; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.lib.resources.shares.OCShare; +import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.lib.resources.status.OCCapability; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import androidx.annotation.Nullable; + +public class FileDataStorageManagerLocal implements FileDataStorageManagerInterface { + private Map pathToFile = new HashMap<>(); + private long currentMaxId = 0; + + public FileDataStorageManagerLocal() { + // always have root file + pathToFile.put("/", createOCFile("/")); + } + + @Override + public OCFile getFileByPath(String path) { + return pathToFile.get(path); + } + + @Override + public Account getAccount() { + throw new IllegalArgumentException("to implement"); + } + + @Nullable + @Override + public OCFile getFileById(long id) { + for (Map.Entry entry : pathToFile.entrySet()) { + if (entry.getValue().getFileId() == id) { + return entry.getValue(); + } + } + + return null; + } + + @Override + public void saveConflict(OCFile file, String etagInConflict) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public void deleteFileInMediaScan(String path) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public boolean saveFile(OCFile file) { + pathToFile.put(file.getRemotePath(), file); + + return true; + } + + @Override + public boolean fileExists(long id) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public List getFolderContent(OCFile f, boolean onlyOnDevice) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public void saveFolder(OCFile folder, Collection updatedFiles, Collection filesToRemove) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public boolean saveShare(OCShare share) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public List getSharesWithForAFile(String filePath, String accountName) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public void removeShare(OCShare share) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public void copyLocalFile(OCFile file, String targetPath) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public OCShare getFirstShareByPathAndType(String path, ShareType type, String shareWith) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public OCCapability saveCapabilities(OCCapability capability) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public void saveSharesDB(List shares) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public void removeSharesForFile(String remotePath) { + throw new IllegalArgumentException("to implement"); + } + + @Override + public OCShare getShareById(long id) { + throw new IllegalArgumentException("to implement"); + } + + public OCFile createOCFile(String path) { + OCFile file = new OCFile(path); + + file.setFileId(currentMaxId); + currentMaxId++; + + return file; + } +} diff --git a/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java b/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java new file mode 100644 index 000000000000..cce1f6fc4dc6 --- /dev/null +++ b/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java @@ -0,0 +1,73 @@ +package com.owncloud.android.operations; + +import com.owncloud.android.FileDataStorageManagerLocal; +import com.owncloud.android.datamodel.FileDataStorageManagerInterface; +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation; +import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation; +import com.owncloud.android.lib.resources.files.model.RemoteFile; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class CreateFolderOperationTest { + private FileDataStorageManagerInterface fileDataStorageManager = new FileDataStorageManagerLocal(); + + @Mock OwnCloudClient client; + + @Mock CreateFolderRemoteOperation createFolderRemoteOperation; + @Mock ReadFolderRemoteOperation readFolderRemoteOperation; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testCreateFolder() { + // setup + String path = "/testFolder/"; + CreateFolderOperation sut = spy(new CreateFolderOperation(path, true)); + + when(createFolderRemoteOperation.execute(any())) + .thenReturn(new RemoteOperationResult(RemoteOperationResult.ResultCode.OK)); + + RemoteOperationResult result = new RemoteOperationResult(RemoteOperationResult.ResultCode.OK); + ArrayList list = new ArrayList<>(); + list.add(new RemoteFile("/testFolder")); + + result.setData(list); + + when(readFolderRemoteOperation.execute(any(OwnCloudClient.class), any(Boolean.class))) + .thenReturn(result); + doReturn(createFolderRemoteOperation). + when(sut).createCreateFolderRemoteOperation(any(String.class), any(Boolean.class)); + doReturn(readFolderRemoteOperation) + .when(sut).createReadFolderRemoteOperation(any(String.class)); + + // tests + // folder does not exist yet + assertNull(fileDataStorageManager.getFileByPath(path)); + + // run + RemoteOperationResult syncResult = sut.execute(client, fileDataStorageManager); + + // verify + assertTrue(syncResult.isSuccess()); + + // folder exists + assertTrue(fileDataStorageManager.getFileByPath(path).isFolder()); + } +}