diff options
author | Stefan Niedermann <info@niedermann.it> | 2021-05-18 15:28:44 +0300 |
---|---|---|
committer | Stefan Niedermann <info@niedermann.it> | 2021-05-18 15:28:44 +0300 |
commit | 0b84a25c24b013719e812b5724228ecbcff0e7ae (patch) | |
tree | 02bd2a8f5fbd67a1d21b4201ff0866e957593e61 | |
parent | 6b3bcdfb575abba8a7d29398e830ce3e5adeab12 (diff) |
Harden ApiProvider for concurrent modifications and add unit tests
-rw-r--r-- | app/src/main/java/it/niedermann/owncloud/notes/persistence/ApiProvider.java | 8 | ||||
-rw-r--r-- | app/src/test/java/it/niedermann/owncloud/notes/persistence/ApiProviderTest.java | 96 |
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 |