Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-notes.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Niedermann <info@niedermann.it>2021-05-18 15:28:44 +0300
committerStefan Niedermann <info@niedermann.it>2021-05-18 15:28:44 +0300
commit0b84a25c24b013719e812b5724228ecbcff0e7ae (patch)
tree02bd2a8f5fbd67a1d21b4201ff0866e957593e61
parent6b3bcdfb575abba8a7d29398e830ce3e5adeab12 (diff)
Harden ApiProvider for concurrent modifications and add unit tests
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/ApiProvider.java8
-rw-r--r--app/src/test/java/it/niedermann/owncloud/notes/persistence/ApiProviderTest.java96
2 files changed, 100 insertions, 4 deletions
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/ApiProvider.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/ApiProvider.java
index 1afd8875..6b851ddb 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/ApiProvider.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/ApiProvider.java
@@ -16,8 +16,8 @@ import com.nextcloud.android.sso.api.NextcloudAPI;
import com.nextcloud.android.sso.model.SingleSignOnAccount;
import java.util.Calendar;
-import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import it.niedermann.owncloud.notes.persistence.sync.CapabilitiesDeserializer;
import it.niedermann.owncloud.notes.persistence.sync.NotesAPI;
@@ -40,10 +40,10 @@ public class ApiProvider {
private static final String API_ENDPOINT_OCS = "/ocs/v2.php/cloud/";
- private static final Map<String, NextcloudAPI> API_CACHE = new HashMap<>();
+ private static final Map<String, NextcloudAPI> API_CACHE = new ConcurrentHashMap<>();
- private static final Map<String, OcsAPI> API_CACHE_OCS = new HashMap<>();
- private static final Map<String, NotesAPI> API_CACHE_NOTES = new HashMap<>();
+ private static final Map<String, OcsAPI> API_CACHE_OCS = new ConcurrentHashMap<>();
+ private static final Map<String, NotesAPI> API_CACHE_NOTES = new ConcurrentHashMap<>();
public static ApiProvider getInstance() {
return INSTANCE;
diff --git a/app/src/test/java/it/niedermann/owncloud/notes/persistence/ApiProviderTest.java b/app/src/test/java/it/niedermann/owncloud/notes/persistence/ApiProviderTest.java
new file mode 100644
index 00000000..2bffda88
--- /dev/null
+++ b/app/src/test/java/it/niedermann/owncloud/notes/persistence/ApiProviderTest.java
@@ -0,0 +1,96 @@
+package it.niedermann.owncloud.notes.persistence;
+
+import android.os.Build;
+
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.nextcloud.android.sso.model.SingleSignOnAccount;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import it.niedermann.owncloud.notes.persistence.sync.NotesAPI;
+import it.niedermann.owncloud.notes.persistence.sync.OcsAPI;
+import it.niedermann.owncloud.notes.shared.model.ApiVersion;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(sdk = {Build.VERSION_CODES.P})
+public class ApiProviderTest {
+
+ @Rule
+ public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
+
+ private ApiProvider apiProvider;
+ private SingleSignOnAccount ssoAccount;
+ private SingleSignOnAccount secondSsoAccount;
+
+ @Before
+ public void setup() {
+ apiProvider = ApiProvider.getInstance();
+ ssoAccount = new SingleSignOnAccount("one", "eins", "1", "example.com", "");
+ secondSsoAccount = new SingleSignOnAccount("two", "zwei", "2", "example.org", "");
+ }
+
+ @Test
+ public void testGetOcsAPI() {
+ OcsAPI api = apiProvider.getOcsAPI(ApplicationProvider.getApplicationContext(), ssoAccount);
+
+ assertNotNull(api);
+ assertSame(api, apiProvider.getOcsAPI(ApplicationProvider.getApplicationContext(), ssoAccount));
+ assertNotSame(api, apiProvider.getOcsAPI(ApplicationProvider.getApplicationContext(), secondSsoAccount));
+
+ apiProvider.invalidateAPICache(ssoAccount);
+
+ final OcsAPI newApi = apiProvider.getOcsAPI(ApplicationProvider.getApplicationContext(), ssoAccount);
+
+ assertNotSame("After invalidating the cache, a new API instance is returned", api, newApi);
+
+ api = newApi;
+
+ assertSame(api, apiProvider.getOcsAPI(ApplicationProvider.getApplicationContext(), ssoAccount));
+ assertNotSame("A new instance should be returned when another SingleSignOn account is provided",
+ api, apiProvider.getOcsAPI(ApplicationProvider.getApplicationContext(), secondSsoAccount));
+
+ apiProvider.invalidateAPICache();
+
+ assertNotSame(api, apiProvider.getOcsAPI(ApplicationProvider.getApplicationContext(), ssoAccount));
+ assertNotSame(newApi, apiProvider.getOcsAPI(ApplicationProvider.getApplicationContext(), secondSsoAccount));
+ }
+
+ @Test
+ public void testGetNotesAPI() {
+ final NotesAPI notesAPI = apiProvider.getNotesAPI(ApplicationProvider.getApplicationContext(), ssoAccount, ApiVersion.API_VERSION_0_2);
+
+ assertNotNull(notesAPI);
+
+ assertSame("Before a manual invalidation, the returned Notes API will be the same instance",
+ notesAPI, apiProvider.getNotesAPI(ApplicationProvider.getApplicationContext(), ssoAccount, ApiVersion.API_VERSION_0_2));
+ assertSame("Before a manual invalidation, the returned Notes API will be the same instance, no matter which preferred version is passed",
+ notesAPI, apiProvider.getNotesAPI(ApplicationProvider.getApplicationContext(), ssoAccount, ApiVersion.API_VERSION_1_0));
+
+ apiProvider.invalidateAPICache();
+
+ final NotesAPI newNotesAPI = apiProvider.getNotesAPI(ApplicationProvider.getApplicationContext(), ssoAccount, ApiVersion.API_VERSION_1_0);
+
+ assertNotSame("After a manual invalidation, the returned Notes API will be a new instance",
+ notesAPI, newNotesAPI);
+ assertSame("Before a manual invalidation, the returned Notes API will be the same instance, no matter which preferred version is passed",
+ newNotesAPI, apiProvider.getNotesAPI(ApplicationProvider.getApplicationContext(), ssoAccount, ApiVersion.API_VERSION_0_2));
+ assertNotSame("Before a manual invalidation, the returned Notes API will be a different instance, even if the preferred version is the same, if the ssoAccount is different",
+ newNotesAPI, apiProvider.getNotesAPI(ApplicationProvider.getApplicationContext(), secondSsoAccount, ApiVersion.API_VERSION_0_2));
+
+ apiProvider.invalidateAPICache(ssoAccount);
+
+ assertNotSame("After a manual invalidation, the returned Notes API will be a new instance",
+ newNotesAPI, apiProvider.getNotesAPI(ApplicationProvider.getApplicationContext(), ssoAccount, ApiVersion.API_VERSION_0_2));
+ }
+} \ No newline at end of file