From af416a7897119f02c82335a6e9b4bfee93466edb Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Thu, 1 Dec 2022 17:17:04 -0800 Subject: [PATCH 01/13] Remove Powermock and fix unit and functional tests --- code/build.gradle | 2 +- code/edgeidentity/build.gradle | 13 +- .../marketing/mobile/MobileCoreHelper.java | 26 + .../edge/identity/IdentityAdIdTest.java | 85 +- .../identity/IdentityAndroidTestUtil.java | 303 +++++ .../edge/identity/IdentityBootUpTest.java | 21 +- .../identity/IdentityECIDHandlingTest.java | 19 +- .../identity/IdentityFunctionalTestUtil.java | 73 +- .../edge/identity/IdentityPublicAPITest.java | 64 +- .../identity/IdentityResetHandlingTest.java | 12 +- .../identity/util}/ADBCountDownLatch.java | 13 +- .../identity/util/IdentityTestConstants.java | 42 + .../identity/util}/MockNetworkService.java | 11 +- .../identity/util}/MonitorExtension.java | 124 +- .../identity/util}/TestConstants.java | 2 +- .../{ => edge/identity/util}/TestHelper.java | 101 +- .../identity/util}/TestPersistenceHelper.java | 3 +- .../edge/identity/IdentityExtension.java | 13 +- .../mobile/edge/identity/IdentityState.java | 11 +- .../edge/identity/IdentityTestUtil.java | 197 +-- .../mobile/edge/identity/ECIDTests.java | 17 +- .../mobile/edge/identity/EventUtilsTests.java | 92 ++ .../edge/identity/IdentityExtensionTests.java | 1057 +++++++++-------- .../edge/identity/IdentityMapTests.java | 9 +- .../identity/IdentityPropertiesTests.java | 154 ++- .../edge/identity/IdentityStateTests.java | 723 +++++------ .../identity/IdentityStorageManagerTests.java | 208 ++++ .../identity/IdentityStorageServiceTests.java | 206 ---- .../mobile/edge/identity/IdentityTests.java | 934 +++++++++------ ...stenerEdgeIdentityRemoveIdentityTests.java | 105 -- ...tenerEdgeIdentityRequestIdentityTests.java | 132 -- ...stenerEdgeIdentityUpdateIdentityTests.java | 105 -- .../identity/ListenerEventHubBootTest.java | 84 -- .../identity/ListenerHubSharedStateTests.java | 105 -- .../ListenerIdentityRequestContentTests.java | 105 -- .../ListenerIdentityRequestResetTests.java | 105 -- .../edge/identity/MockIdentityState.java | 50 - .../org.mockito.plugins.MockMaker | 1 + 38 files changed, 2586 insertions(+), 2741 deletions(-) create mode 100644 code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MobileCoreHelper.java create mode 100644 code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAndroidTestUtil.java rename code/edgeidentity/src/{sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity => androidTest/java/com/adobe/marketing/mobile/edge/identity/util}/ADBCountDownLatch.java (85%) create mode 100644 code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityTestConstants.java rename code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/{ => edge/identity/util}/MockNetworkService.java (80%) rename code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/{ => edge/identity/util}/MonitorExtension.java (69%) rename code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/{ => edge/identity/util}/TestConstants.java (96%) rename code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/{ => edge/identity/util}/TestHelper.java (91%) rename code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/{ => edge/identity/util}/TestPersistenceHelper.java (97%) create mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageManagerTests.java delete mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageServiceTests.java delete mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRemoveIdentityTests.java delete mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRequestIdentityTests.java delete mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityUpdateIdentityTests.java delete mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEventHubBootTest.java delete mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerHubSharedStateTests.java delete mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestContentTests.java delete mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestResetTests.java delete mode 100644 code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/MockIdentityState.java create mode 100644 code/edgeidentity/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/code/build.gradle b/code/build.gradle index 865739af..56c90130 100644 --- a/code/build.gradle +++ b/code/build.gradle @@ -24,7 +24,7 @@ ext { // test dependencies junitVersion = "1.1.3" - mockitoCoreVersion = "2.28.2" + mockitoCoreVersion = "4.5.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" // spotless diff --git a/code/edgeidentity/build.gradle b/code/edgeidentity/build.gradle index aef0c300..4e8529fc 100644 --- a/code/edgeidentity/build.gradle +++ b/code/edgeidentity/build.gradle @@ -229,18 +229,17 @@ dependencies { testImplementation "androidx.test.ext:junit:${rootProject.ext.junitVersion}" testImplementation "org.mockito:mockito-core:${rootProject.ext.mockitoCoreVersion}" testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.9.9' - testImplementation 'org.powermock:powermock-api-mockito2:2.0.0' - testImplementation 'org.powermock:powermock-module-junit4:2.0.0' testImplementation 'org.json:json:20180813' androidTestImplementation "androidx.test.ext:junit:${rootProject.ext.junitVersion}" androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - // Using older version of PowerMock as it supports minimum Android API < 26 - // the root issue appears to be a dependency with Objenesis in Mockito-Core - // where Objenesis 2 requires minimum Android API 26 - androidTestImplementation 'org.powermock:powermock-module-junit4:1+' androidTestImplementation 'com.fasterxml.jackson.core:jackson-databind:2.9.9' - androidTestImplementation "com.adobe.marketing.mobile:identity:1.+" + + // TODO: Uncomment next line when Identity 2.0 artifacts are published to maven + // implementation "com.adobe.marketing.mobile:identity:2.+" + androidTestImplementation ("com.github.adobe.aepsdk-core-android:identity:dev-v2.0.0-SNAPSHOT") { + transitive = false + } } tasks.withType(Test) { diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MobileCoreHelper.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MobileCoreHelper.java new file mode 100644 index 00000000..c34a117c --- /dev/null +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MobileCoreHelper.java @@ -0,0 +1,26 @@ +/* + Copyright 2022 Adobe. All rights reserved. + This file is licensed to you under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. You may obtain a copy + of the License at http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under + the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + OF ANY KIND, either express or implied. See the License for the specific language + governing permissions and limitations under the License. +*/ + +package com.adobe.marketing.mobile; + +/** + * Helper class that exists as a to access test helper methods provided in core + * within the package com.adobe.marketing.mobile + */ +public class MobileCoreHelper { + + /** + * Wrapper around {@link MobileCore#resetSDK()} + */ + public static void resetSDK() { + MobileCore.resetSDK(); + } +} diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java index 92fc643c..f7e080ee 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java @@ -11,23 +11,22 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.TestHelper.getDispatchedEventsWith; -import static com.adobe.marketing.mobile.TestHelper.getXDMSharedStateFor; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.createXDMIdentityMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.setEdgeIdentityPersistence; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.createXDMIdentityMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.flattenMap; +import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getDispatchedEventsWith; +import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; import static org.junit.Assert.assertEquals; -import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionError; -import com.adobe.marketing.mobile.ExtensionErrorCallback; import com.adobe.marketing.mobile.MobileCore; -import com.adobe.marketing.mobile.TestHelper; -import com.adobe.marketing.mobile.TestPersistenceHelper; +import com.adobe.marketing.mobile.edge.identity.util.TestHelper; +import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; +import com.adobe.marketing.mobile.util.JSONUtils; +import com.adobe.marketing.mobile.util.StringUtils; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -51,10 +50,11 @@ public void testGenericIdentityRequest_whenValidAdId_thenNewValidAdId() throws E String newAdId = "8d9ca5ff-7e74-44ac-bbcd-7aee7baf4f6c"; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityTestUtil.TestItem("ECID", "primaryECID"), - new IdentityTestUtil.TestItem("GAID", initialAdId) + new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), + new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) ) ); + registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); @@ -73,7 +73,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenNewValidAdId() throws E IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); verifyFlatIdentityMap(persistedMap, newAdId); } @@ -83,8 +83,8 @@ public void testGenericIdentityRequest_whenValidAdId_thenNonAdId() throws Except String initialAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityTestUtil.TestItem("ECID", "primaryECID"), - new IdentityTestUtil.TestItem("GAID", initialAdId) + new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), + new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) ) ); registerEdgeIdentityExtension(); @@ -105,7 +105,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenNonAdId() throws Except IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); verifyFlatIdentityMap(persistedMap, initialAdId); } @@ -116,8 +116,8 @@ public void testGenericIdentityRequest_whenValidAdId_thenSameValidAdId() throws String newAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityTestUtil.TestItem("ECID", "primaryECID"), - new IdentityTestUtil.TestItem("GAID", initialAdId) + new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), + new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) ) ); registerEdgeIdentityExtension(); @@ -137,7 +137,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenSameValidAdId() throws IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); verifyFlatIdentityMap(persistedMap, newAdId); } @@ -148,8 +148,8 @@ public void testGenericIdentityRequest_whenValidAdId_thenEmptyAdId() throws Exce String newAdId = ""; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityTestUtil.TestItem("ECID", "primaryECID"), - new IdentityTestUtil.TestItem("GAID", initialAdId) + new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), + new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) ) ); registerEdgeIdentityExtension(); @@ -169,7 +169,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenEmptyAdId() throws Exce IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); verifyFlatIdentityMap(persistedMap, null); } @@ -180,8 +180,8 @@ public void testGenericIdentityRequest_whenValidAdId_thenAllZerosAdId() throws E String newAdId = "00000000-0000-0000-0000-000000000000"; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityTestUtil.TestItem("ECID", "primaryECID"), - new IdentityTestUtil.TestItem("GAID", initialAdId) + new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), + new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) ) ); registerEdgeIdentityExtension(); @@ -201,7 +201,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenAllZerosAdId() throws E IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); verifyFlatIdentityMap(persistedMap, null); } @@ -209,7 +209,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenAllZerosAdId() throws E public void testGenericIdentityRequest_whenNoAdId_thenNewValidAdId() throws Exception { // Test String newAdId = "8d9ca5ff-7e74-44ac-bbcd-7aee7baf4f6c"; - setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityTestUtil.TestItem("ECID", "primaryECID"))); + setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"))); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); @@ -228,14 +228,14 @@ public void testGenericIdentityRequest_whenNoAdId_thenNewValidAdId() throws Exce IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); verifyFlatIdentityMap(persistedMap, newAdId); } @Test public void testGenericIdentityRequest_whenNoAdId_thenNonAdId() throws Exception { // Test - setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityTestUtil.TestItem("ECID", "primaryECID"))); + setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"))); registerEdgeIdentityExtension(); dispatchGenericIdentityNonAdIdEvent(); @@ -254,7 +254,7 @@ public void testGenericIdentityRequest_whenNoAdId_thenNonAdId() throws Exception IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); verifyFlatIdentityMap(persistedMap, null); } @@ -262,7 +262,7 @@ public void testGenericIdentityRequest_whenNoAdId_thenNonAdId() throws Exception public void testGenericIdentityRequest_whenNoAdId_thenEmptyAdId() throws Exception { // Test String newAdId = ""; - setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityTestUtil.TestItem("ECID", "primaryECID"))); + setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"))); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); @@ -280,7 +280,7 @@ public void testGenericIdentityRequest_whenNoAdId_thenEmptyAdId() throws Excepti IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); verifyFlatIdentityMap(persistedMap, null); } @@ -288,7 +288,7 @@ public void testGenericIdentityRequest_whenNoAdId_thenEmptyAdId() throws Excepti public void testGenericIdentityRequest_whenNoAdId_thenAllZerosAdIdTwice() throws Exception { // Test String newAdId = "00000000-0000-0000-0000-000000000000"; - setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityTestUtil.TestItem("ECID", "primaryECID"))); + setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"))); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); @@ -306,7 +306,7 @@ public void testGenericIdentityRequest_whenNoAdId_thenAllZerosAdIdTwice() throws IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); verifyFlatIdentityMap(persistedMap, null); // Reset wildcard listener @@ -327,12 +327,12 @@ public void testGenericIdentityRequest_whenNoAdId_thenAllZerosAdIdTwice() throws IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap2 = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson2))); + Map persistedMap2 = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson2))); verifyFlatIdentityMap(persistedMap2, null); } /** - * Verifies that the expected events from the {@link MobileCore#setAdvertisingIdentifier(String)} or {@link MobileCore#dispatchEvent(Event, ExtensionErrorCallback)} + * Verifies that the expected events from the {@link MobileCore#setAdvertisingIdentifier(String)} or {@link MobileCore#dispatchEvent(Event)} * APIs are properly dispatched. Verifies: * 1. Event type and source * 2. Event data/properties as required for proper ad ID functionality @@ -352,14 +352,14 @@ private void verifyDispatchedEvents(boolean isGenericIdentityEventAdIdEvent, Str // Verify Generic Identity event assertEquals(1, dispatchedGenericIdentityEvents.size()); Event genericIdentityEvent = dispatchedGenericIdentityEvents.get(0); - assertEquals(isGenericIdentityEventAdIdEvent ? true : false, EventUtils.isAdIdEvent(genericIdentityEvent)); + assertEquals(isGenericIdentityEventAdIdEvent, EventUtils.isAdIdEvent(genericIdentityEvent)); // Verify Edge Consent event List dispatchedConsentEvents = getDispatchedEventsWith( IdentityConstants.EventType.EDGE_CONSENT, IdentityConstants.EventSource.UPDATE_CONSENT ); - assertEquals(Utils.isNullOrEmpty(expectedConsentValue) ? 0 : 1, dispatchedConsentEvents.size()); - if (!Utils.isNullOrEmpty(expectedConsentValue)) { + assertEquals(StringUtils.isNullOrEmpty(expectedConsentValue) ? 0 : 1, dispatchedConsentEvents.size()); + if (!StringUtils.isNullOrEmpty(expectedConsentValue)) { Map consentDataMap = flattenMap(dispatchedConsentEvents.get(0).getEventData()); assertEquals("GAID", consentDataMap.get("consents.adID.idType")); assertEquals(expectedConsentValue, consentDataMap.get("consents.adID.val")); @@ -389,7 +389,6 @@ private void verifyFlatIdentityMap( assertEquals("false", flatIdentityMap.get("identityMap.ECID[0].primary")); assertEquals(expectedECID, flatIdentityMap.get("identityMap.ECID[0].id")); assertEquals("ambiguous", flatIdentityMap.get("identityMap.ECID[0].authenticatedState")); - return; } /** @@ -413,14 +412,6 @@ private void dispatchGenericIdentityNonAdIdEvent() { } ) .build(); - MobileCore.dispatchEvent( - genericIdentityNonAdIdEvent, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - Log.e("IdentityAdIdTest", "Failed to dispatch event." + extensionError.toString()); - } - } - ); + MobileCore.dispatchEvent(genericIdentityNonAdIdEvent); } } diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAndroidTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAndroidTestUtil.java new file mode 100644 index 00000000..9ef1bd82 --- /dev/null +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAndroidTestUtil.java @@ -0,0 +1,303 @@ +/* + Copyright 2021 Adobe. All rights reserved. + This file is licensed to you under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. You may obtain a copy + of the License at http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under + the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + OF ANY KIND, either express or implied. See the License for the specific language + governing permissions and limitations under the License. +*/ + +package com.adobe.marketing.mobile.edge.identity; + +import static com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants.LOG_TAG; + +import com.adobe.marketing.mobile.AdobeCallback; +import com.adobe.marketing.mobile.AdobeCallbackWithError; +import com.adobe.marketing.mobile.AdobeError; +import com.adobe.marketing.mobile.Event; +import com.adobe.marketing.mobile.edge.identity.util.ADBCountDownLatch; +import com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants; +import com.adobe.marketing.mobile.services.Log; +import com.adobe.marketing.mobile.util.JSONUtils; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.ValueNode; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Util class used by both Functional and Unit tests + */ +public class IdentityAndroidTestUtil { + + private static final String LOG_SOURCE = "IdentityAndroidTestUtil"; + + /** + * Helper method to create IdentityXDM Map using {@link TestItem}s + */ + static Map createXDMIdentityMap(TestItem... items) { + final Map>> allItems = new HashMap<>(); + + for (TestItem item : items) { + final Map itemMap = new HashMap<>(); + itemMap.put(IdentityConstants.XDMKeys.ID, item.id); + itemMap.put(IdentityConstants.XDMKeys.AUTHENTICATED_STATE, "ambiguous"); + itemMap.put(IdentityConstants.XDMKeys.PRIMARY, item.isPrimary); + List> nameSpaceItems = allItems.get(item.namespace); + + if (nameSpaceItems == null) { + nameSpaceItems = new ArrayList<>(); + } + + nameSpaceItems.add(itemMap); + allItems.put(item.namespace, nameSpaceItems); + } + + final Map identityMapDict = new HashMap<>(); + identityMapDict.put(IdentityConstants.XDMKeys.IDENTITY_MAP, allItems); + return identityMapDict; + } + + /** + * Helper method to build remove identity request event with XDM formatted Identity jsonString + */ + static Event buildRemoveIdentityRequestWithJSONString(final String jsonStr) throws Exception { + final JSONObject jsonObject = new JSONObject(jsonStr); + final Map xdmData = JSONUtils.toMap(jsonObject); + return buildRemoveIdentityRequest(xdmData); + } + + /** + * Helper method to build remove identity request event with XDM formatted Identity map + */ + static Event buildRemoveIdentityRequest(final Map map) { + return new Event.Builder( + "Remove Identity Event", + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.REMOVE_IDENTITY + ) + .setEventData(map) + .build(); + } + + /** + * Helper method to build update identity request event with XDM formatted Identity jsonString + */ + static Event buildUpdateIdentityRequestJSONString(final String jsonStr) throws Exception { + final JSONObject jsonObject = new JSONObject(jsonStr); + final Map xdmData = JSONUtils.toMap(jsonObject); + return buildUpdateIdentityRequest(xdmData); + } + + /** + * Helper method to build update identity request event with XDM formatted Identity map + */ + static Event buildUpdateIdentityRequest(final Map map) { + return new Event.Builder( + "Update Identity Event", + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.UPDATE_IDENTITY + ) + .setEventData(map) + .build(); + } + + /** + * Serialize the given {@code jsonString} to a JSON Object, then flattens to {@code Map}. + * If the provided string is not in JSON structure an {@link JSONException} is thrown. + * + * @param jsonString the string in JSON structure to flatten + * @return new map with flattened structure + */ + static Map flattenJSONString(final String jsonString) throws JSONException { + JSONObject jsonObject = new JSONObject(jsonString); + Map persistenceValueMap = JSONUtils.toMap(jsonObject); + return flattenMap(persistenceValueMap); + } + + /** + * Serialize the given {@code map} to a JSON Object, then flattens to {@code Map}. + * For example, a JSON such as "{xdm: {stitchId: myID, eventType: myType}}" is flattened + * to two map elements "xdm.stitchId" = "myID" and "xdm.eventType" = "myType". + * + * @param map map with JSON structure to flatten + * @return new map with flattened structure + */ + static Map flattenMap(final Map map) { + if (map == null || map.isEmpty()) { + return Collections.emptyMap(); + } + + try { + JSONObject jsonObject = new JSONObject(map); + Map payloadMap = new HashMap<>(); + addKeys("", new ObjectMapper().readTree(jsonObject.toString()), payloadMap); + return payloadMap; + } catch (IOException e) { + Log.error(LOG_TAG, LOG_SOURCE, "Failed to parse JSON object to tree structure."); + } + + return Collections.emptyMap(); + } + + /** + * Deserialize {@code JsonNode} and flatten to provided {@code map}. + * For example, a JSON such as "{xdm: {stitchId: myID, eventType: myType}}" is flattened + * to two map elements "xdm.stitchId" = "myID" and "xdm.eventType" = "myType". + *

+ * Method is called recursively. To use, call with an empty path such as + * {@code addKeys("", new ObjectMapper().readTree(JsonNodeAsString), map);} + * + * @param currentPath the path in {@code JsonNode} to process + * @param jsonNode {@link JsonNode} to deserialize + * @param map {@code Map} instance to store flattened JSON result + * @see Stack Overflow post + */ + static void addKeys(String currentPath, JsonNode jsonNode, Map map) { + if (jsonNode.isObject()) { + ObjectNode objectNode = (ObjectNode) jsonNode; + Iterator> iter = objectNode.fields(); + String pathPrefix = currentPath.isEmpty() ? "" : currentPath + "."; + + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + addKeys(pathPrefix + entry.getKey(), entry.getValue(), map); + } + } else if (jsonNode.isArray()) { + ArrayNode arrayNode = (ArrayNode) jsonNode; + + for (int i = 0; i < arrayNode.size(); i++) { + addKeys(currentPath + "[" + i + "]", arrayNode.get(i), map); + } + } else if (jsonNode.isValueNode()) { + ValueNode valueNode = (ValueNode) jsonNode; + map.put(currentPath, valueNode.asText()); + } + } + + /** + * Class similar to {@link IdentityItem} for a specific namespace used for easier testing. + * For simplicity this class does not involve authenticatedState and primary key + */ + static class TestItem { + + private final String namespace; + private final String id; + private final boolean isPrimary = false; + + public TestItem(String namespace, String id) { + this.namespace = namespace; + this.id = id; + } + } + + /** + * Retrieves identities from Identity extension synchronously + * @return a {@code Map} of identities if retrieved successfully; + * null in case of a failure to retrieve it within timeout. + */ + static Map getIdentitiesSync() { + try { + final HashMap getIdentityResponse = new HashMap<>(); + final ADBCountDownLatch latch = new ADBCountDownLatch(1); + Identity.getIdentities( + new AdobeCallbackWithError() { + @Override + public void call(final IdentityMap identities) { + getIdentityResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, identities); + latch.countDown(); + } + + @Override + public void fail(final AdobeError adobeError) { + getIdentityResponse.put(IdentityTestConstants.GetIdentitiesHelper.ERROR, adobeError); + latch.countDown(); + } + } + ); + latch.await(2000, TimeUnit.MILLISECONDS); + + return getIdentityResponse; + } catch (Exception exp) { + return null; + } + } + + /** + * Retrieves Experience Cloud Id from Identity extension synchronously + * @return an ECID if retrieved successfully; + * null in case of a failure to retrieve it within timeout. + */ + static String getExperienceCloudIdSync() { + try { + final HashMap getExperienceCloudIdResponse = new HashMap<>(); + final ADBCountDownLatch latch = new ADBCountDownLatch(1); + Identity.getExperienceCloudId( + new AdobeCallback() { + @Override + public void call(final String ecid) { + getExperienceCloudIdResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, ecid); + latch.countDown(); + } + } + ); + latch.await(2000, TimeUnit.MILLISECONDS); + return getExperienceCloudIdResponse.get(IdentityTestConstants.GetIdentitiesHelper.VALUE); + } catch (Exception exp) { + return null; + } + } + + /** + * Retrieves url variables from Identity extension synchronously + * @return a url variable string if retrieved successfully; + * null in case of a failure to retrieve it within timeout. + */ + static String getUrlVariablesSync() { + try { + final HashMap getUrlVariablesResponse = new HashMap<>(); + final ADBCountDownLatch latch = new ADBCountDownLatch(1); + Identity.getUrlVariables( + new AdobeCallback() { + @Override + public void call(final String urlVariables) { + getUrlVariablesResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, urlVariables); + latch.countDown(); + } + } + ); + latch.await(2000, TimeUnit.MILLISECONDS); + return getUrlVariablesResponse.get(IdentityTestConstants.GetIdentitiesHelper.VALUE); + } catch (Exception exp) { + return null; + } + } + + static IdentityMap createIdentityMap(final String namespace, final String id) { + return createIdentityMap(namespace, id, AuthenticatedState.AMBIGUOUS, false); + } + + static IdentityMap createIdentityMap( + final String namespace, + final String id, + final AuthenticatedState state, + final boolean isPrimary + ) { + IdentityMap map = new IdentityMap(); + IdentityItem item = new IdentityItem(id, state, isPrimary); + map.addItem(item, namespace); + return map; + } +} diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java index 3653c9d7..92261db0 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java @@ -11,14 +11,15 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.TestHelper.getXDMSharedStateFor; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.createXDMIdentityMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.*; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.createXDMIdentityMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.flattenMap; +import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; import static org.junit.Assert.assertEquals; -import com.adobe.marketing.mobile.TestHelper; -import com.adobe.marketing.mobile.TestPersistenceHelper; +import com.adobe.marketing.mobile.edge.identity.util.TestHelper; +import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; +import com.adobe.marketing.mobile.util.JSONUtils; import java.util.Map; import org.json.JSONObject; import org.junit.Rule; @@ -41,10 +42,10 @@ public void testOnBootUp_LoadsAllIdentitiesFromPreference() throws Exception { // test setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityTestUtil.TestItem("ECID", "primaryECID"), - new IdentityTestUtil.TestItem("ECID", "secondaryECID"), - new IdentityTestUtil.TestItem("Email", "example@email.com"), - new IdentityTestUtil.TestItem("UserId", "JohnDoe") + new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), + new IdentityAndroidTestUtil.TestItem("ECID", "secondaryECID"), + new IdentityAndroidTestUtil.TestItem("Email", "example@email.com"), + new IdentityAndroidTestUtil.TestItem("UserId", "JohnDoe") ) ); registerEdgeIdentityExtension(); @@ -62,7 +63,7 @@ public void testOnBootUp_LoadsAllIdentitiesFromPreference() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(12, persistedMap.size()); // 3 for ECID and 3 for secondaryECID + 6 } // -------------------------------------------------------------------------------------------- diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java index e20b7005..870e51ae 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java @@ -11,14 +11,15 @@ package com.adobe.marketing.mobile.edge.identity; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.createXDMIdentityMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getExperienceCloudIdSync; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.*; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.*; import static org.junit.Assert.*; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.adobe.marketing.mobile.MobileCore; import com.adobe.marketing.mobile.MobilePrivacyStatus; -import com.adobe.marketing.mobile.TestHelper; +import com.adobe.marketing.mobile.edge.identity.util.TestHelper; import org.junit.Rule; import org.junit.Test; import org.junit.rules.RuleChain; @@ -45,7 +46,10 @@ public void testECID_autoGeneratedWhenBooted() throws InterruptedException { public void testECID_loadedFromPersistence() throws Exception { // setup setEdgeIdentityPersistence( - createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("ECID", "secondaryECID")) + createXDMIdentityMap( + new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), + new IdentityAndroidTestUtil.TestItem("ECID", "secondaryECID") + ) ); registerEdgeIdentityExtension(); @@ -58,7 +62,7 @@ public void testECID_loadedFromPersistence() throws Exception { public void testECID_edgePersistenceTakesPreferenceOverDirectExtension() throws Exception { // setup setIdentityDirectPersistedECID("legacyECID"); - setEdgeIdentityPersistence(CreateIdentityMap("ECID", "edgeECID").asXDMMap()); + setEdgeIdentityPersistence(IdentityAndroidTestUtil.createIdentityMap("ECID", "edgeECID").asXDMMap()); registerEdgeIdentityExtension(); // verify @@ -112,7 +116,10 @@ public void testECID_whenBothExtensionRegistered_migrationPath() throws Exceptio public void testECID_onResetClearsOldECID() throws Exception { // setup setEdgeIdentityPersistence( - createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("ECID", "secondaryECID")) + createXDMIdentityMap( + new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), + new IdentityAndroidTestUtil.TestItem("ECID", "secondaryECID") + ) ); registerEdgeIdentityExtension(); @@ -179,7 +186,7 @@ public void testECID_AreDifferentAfterResetIdentitiesAndPrivacyChange() throws E public void testECID_DirectEcidIsRemovedOnPrivacyOptOut() throws Exception { // setup setIdentityDirectPersistedECID("legacyECID"); - setEdgeIdentityPersistence(CreateIdentityMap("ECID", "edgeECID").asXDMMap()); + setEdgeIdentityPersistence(IdentityAndroidTestUtil.createIdentityMap("ECID", "edgeECID").asXDMMap()); registerBothIdentityExtensions(); // verify ECID diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java index 40e8465f..29898f95 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java @@ -11,17 +11,21 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.TestHelper.getXDMSharedStateFor; -import static com.adobe.marketing.mobile.TestHelper.resetTestExpectations; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.flattenMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.getExperienceCloudIdSync; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getExperienceCloudIdSync; +import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; +import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.resetTestExpectations; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import com.adobe.marketing.mobile.AdobeCallback; import com.adobe.marketing.mobile.MobileCore; -import com.adobe.marketing.mobile.TestHelper; -import com.adobe.marketing.mobile.TestPersistenceHelper; +import com.adobe.marketing.mobile.edge.identity.util.ADBCountDownLatch; +import com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants; +import com.adobe.marketing.mobile.edge.identity.util.TestHelper; +import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; +import com.adobe.marketing.mobile.util.JSONUtils; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -33,46 +37,8 @@ public class IdentityFunctionalTestUtil { * Register's Edge Identity Extension and start the Core */ static void registerEdgeIdentityExtension() throws InterruptedException { - com.adobe.marketing.mobile.edge.identity.Identity.registerExtension(); - - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - MobileCore.start( - new AdobeCallback() { - @Override - public void call(Object o) { - latch.countDown(); - } - } - ); - - latch.await(1000, TimeUnit.MILLISECONDS); - TestHelper.waitForThreads(2000); - resetTestExpectations(); - } - - /** - * Register's Identity Direct Extension and start the Core - */ - static void registerIdentityDirectExtension() throws Exception { - HashMap config = new HashMap() { - { - put("global.privacy", "optedin"); - put("experienceCloud.org", "testOrg@AdobeOrg"); - put("experienceCloud.server", "notaserver"); - } - }; - MobileCore.updateConfiguration(config); - com.adobe.marketing.mobile.Identity.registerExtension(); - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - MobileCore.start( - new AdobeCallback() { - @Override - public void call(Object o) { - latch.countDown(); - } - } - ); + MobileCore.registerExtensions(Arrays.asList(Identity.EXTENSION), o -> latch.countDown()); latch.await(1000, TimeUnit.MILLISECONDS); TestHelper.waitForThreads(2000); @@ -92,17 +58,10 @@ static void registerBothIdentityExtensions() throws Exception { }; MobileCore.updateConfiguration(config); - com.adobe.marketing.mobile.edge.identity.Identity.registerExtension(); - com.adobe.marketing.mobile.Identity.registerExtension(); - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - MobileCore.start( - new AdobeCallback() { - @Override - public void call(Object o) { - latch.countDown(); - } - } + MobileCore.registerExtensions( + Arrays.asList(Identity.EXTENSION, com.adobe.marketing.mobile.Identity.EXTENSION), + o -> latch.countDown() ); latch.await(); @@ -206,7 +165,7 @@ static void verifyPrimaryECID(final String primaryECID) throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(primaryECID, persistedMap.get("identityMap.ECID[0].id")); } @@ -224,7 +183,7 @@ static void verifySecondaryECID(final String secondaryECID) throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(secondaryECID, persistedMap.get("identityMap.ECID[1].id")); } } diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java index bc187a84..27df8d6e 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java @@ -11,16 +11,22 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.TestHelper.*; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.createIdentityMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getExperienceCloudIdSync; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getIdentitiesSync; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getUrlVariablesSync; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.setupConfiguration; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.*; +import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.*; import static org.junit.Assert.*; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.TestHelper; -import com.adobe.marketing.mobile.TestPersistenceHelper; +import com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants; +import com.adobe.marketing.mobile.edge.identity.util.TestHelper; +import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; +import com.adobe.marketing.mobile.util.JSONUtils; import java.util.List; import java.util.Map; import org.json.JSONObject; @@ -63,11 +69,11 @@ public void testGetExtensionVersionAPI() { @Test public void testRegisterExtensionAPI() throws InterruptedException { // test - // Consent.registerExtension() is called in the setup method + // Identity.registerExtension() is called in the setup method // verify that the extension is registered with the correct version details Map sharedStateMap = flattenMap( - getSharedStateFor(IdentityTestConstants.SharedStateName.EVENT_HUB, 1000) + getSharedStateFor(IdentityTestConstants.SharedStateName.EVENT_HUB, 5000) ); assertEquals( IdentityConstants.EXTENSION_VERSION, @@ -83,7 +89,7 @@ public void testRegisterExtensionAPI() throws InterruptedException { public void testUpdateIdentitiesAPI() throws Exception { // test Identity.updateIdentities( - CreateIdentityMap("Email", "example@email.com", AuthenticatedState.AUTHENTICATED, true) + createIdentityMap("Email", "example@email.com", AuthenticatedState.AUTHENTICATED, true) ); TestHelper.waitForThreads(2000); @@ -99,7 +105,7 @@ public void testUpdateIdentitiesAPI() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(6, persistedMap.size()); // 3 for ECID and 3 for Email assertEquals("example@email.com", persistedMap.get("identityMap.Email[0].id")); assertEquals("true", persistedMap.get("identityMap.Email[0].primary")); @@ -147,12 +153,12 @@ public void testUpdateAPI_emptyData() throws Exception { @Test public void testUpdateAPI_shouldReplaceExistingIdentities() throws Exception { // test - Identity.updateIdentities(CreateIdentityMap("Email", "example@email.com")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("Email", "example@email.com")); Identity.updateIdentities( - CreateIdentityMap("Email", "example@email.com", AuthenticatedState.AUTHENTICATED, true) + createIdentityMap("Email", "example@email.com", AuthenticatedState.AUTHENTICATED, true) ); Identity.updateIdentities( - CreateIdentityMap("Email", "example@email.com", AuthenticatedState.LOGGED_OUT, false) + createIdentityMap("Email", "example@email.com", AuthenticatedState.LOGGED_OUT, false) ); TestHelper.waitForThreads(2000); @@ -168,7 +174,7 @@ public void testUpdateAPI_shouldReplaceExistingIdentities() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(6, persistedMap.size()); // 3 for ECID and 3 for Email assertEquals("example@email.com", persistedMap.get("identityMap.Email[0].id")); assertEquals("false", persistedMap.get("identityMap.Email[0].primary")); @@ -178,13 +184,13 @@ public void testUpdateAPI_shouldReplaceExistingIdentities() throws Exception { @Test public void testUpdateAPI_withReservedNamespaces() throws Exception { // test - Identity.updateIdentities(CreateIdentityMap("ECID", "newECID")); - Identity.updateIdentities(CreateIdentityMap("GAID", "")); - Identity.updateIdentities(CreateIdentityMap("IDFA", "")); - Identity.updateIdentities(CreateIdentityMap("IDFa", "")); - Identity.updateIdentities(CreateIdentityMap("gaid", "")); - Identity.updateIdentities(CreateIdentityMap("ecid", "")); - Identity.updateIdentities(CreateIdentityMap("idfa", "")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("ECID", "newECID")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("GAID", "")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("IDFA", "")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("IDFa", "")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("gaid", "")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("ecid", "")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("idfa", "")); TestHelper.waitForThreads(2000); // verify xdm shared state does not get updated @@ -197,7 +203,7 @@ public void testUpdateAPI_withReservedNamespaces() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(3, persistedMap.size()); // 3 for ECID assertNotEquals("newECID", persistedMap.get("identityMap.ECID[0].id")); // ECID doesn't get replaced by API } @@ -226,7 +232,7 @@ public void testUpdateAPI_multipleNamespaceMap() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(15, persistedMap.size()); // 3 for ECID + 12 for new identities assertEquals("primary@email.com", persistedMap.get("identityMap.Email[0].id")); assertEquals("secondary@email.com", persistedMap.get("identityMap.Email[1].id")); @@ -254,7 +260,7 @@ public void testUpdateAPI_caseSensitiveNamespacesForCustomIdentifiers() throws E IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(9, persistedMap.size()); // 3 for ECID + 6 for new identities assertEquals("primary@email.com", persistedMap.get("identityMap.Email[0].id")); assertEquals("secondary@email.com", persistedMap.get("identityMap.email[0].id")); @@ -381,7 +387,7 @@ public void testRemoveIdentity() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(3, persistedMap.size()); // 3 for ECID } @@ -401,7 +407,7 @@ public void testRemoveIdentity_nonExistentNamespace() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(3, persistedMap.size()); // 3 for ECID } @@ -409,7 +415,7 @@ public void testRemoveIdentity_nonExistentNamespace() throws Exception { public void testRemoveIdentity_nameSpaceCaseSensitive() throws Exception { // setup // update Identities through API - Identity.updateIdentities(CreateIdentityMap("Email", "example@email.com")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("Email", "example@email.com")); // test Identity.removeIdentity(new IdentityItem("example@email.com"), "email"); @@ -425,7 +431,7 @@ public void testRemoveIdentity_nameSpaceCaseSensitive() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(6, persistedMap.size()); // 3 for ECID + 3 for Email } @@ -433,7 +439,7 @@ public void testRemoveIdentity_nameSpaceCaseSensitive() throws Exception { public void testRemoveIdentity_nonExistentItem() throws Exception { // setup // update Identities through API - Identity.updateIdentities(CreateIdentityMap("Email", "example@email.com")); + Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("Email", "example@email.com")); // test Identity.removeIdentity(new IdentityItem("secondary@email.com"), "Email"); @@ -449,7 +455,7 @@ public void testRemoveIdentity_nonExistentItem() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(6, persistedMap.size()); // 3 for ECID + 3 for Email } @@ -472,7 +478,7 @@ public void testRemoveIdentity_doesNotRemoveECID() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(3, persistedMap.size()); // 3 for ECID that still exists } } diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java index 985ff51d..a1810a70 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java @@ -11,15 +11,17 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.TestHelper.*; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getExperienceCloudIdSync; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.*; +import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.*; import static org.junit.Assert.*; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.MobileCore; -import com.adobe.marketing.mobile.TestHelper; -import com.adobe.marketing.mobile.TestPersistenceHelper; +import com.adobe.marketing.mobile.edge.identity.util.TestHelper; +import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; +import com.adobe.marketing.mobile.util.JSONUtils; import java.util.List; import java.util.Map; import org.json.JSONObject; @@ -84,7 +86,7 @@ public void testReset_ClearsAllIDAndDispatchesResetComplete() throws Exception { IdentityConstants.DataStoreKey.DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES ); - Map persistedMap = flattenMap(IdentityTestUtil.toMap(new JSONObject(persistedJson))); + Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(3, persistedMap.size()); // 3 for ECID assertEquals(newECID, persistedMap.get("identityMap.ECID[0].id")); } diff --git a/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/ADBCountDownLatch.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/ADBCountDownLatch.java similarity index 85% rename from code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/ADBCountDownLatch.java rename to code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/ADBCountDownLatch.java index 4bf97273..3d36853c 100644 --- a/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/ADBCountDownLatch.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/ADBCountDownLatch.java @@ -1,5 +1,5 @@ /* - Copyright 2021 Adobe. All rights reserved. + Copyright 2022 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 @@ -9,12 +9,15 @@ governing permissions and limitations under the License. */ -package com.adobe.marketing.mobile.edge.identity; +package com.adobe.marketing.mobile.edge.identity.util; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +/** + * Test utility class that facilitates waiting. + */ public class ADBCountDownLatch { private final CountDownLatch latch; @@ -40,10 +43,6 @@ public void countDown() { latch.countDown(); } - public long getCount() { - return latch.getCount(); - } - public int getInitialCount() { return initialCount; } @@ -54,6 +53,6 @@ public int getCurrentCount() { @Override public String toString() { - return String.format("%s, initial: %d, current: %d", latch.toString(), initialCount, currentCount.get()); + return String.format("%s, initial: %d, current: %d", latch, initialCount, currentCount.get()); } } diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityTestConstants.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityTestConstants.java new file mode 100644 index 00000000..9e6cffc5 --- /dev/null +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityTestConstants.java @@ -0,0 +1,42 @@ +/* + Copyright 2021 Adobe. All rights reserved. + This file is licensed to you under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. You may obtain a copy + of the License at http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under + the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + OF ANY KIND, either express or implied. See the License for the specific language + governing permissions and limitations under the License. +*/ + +package com.adobe.marketing.mobile.edge.identity.util; + +public class IdentityTestConstants { + + public static final String LOG_TAG = "EdgeIdentity"; + + public static final class DataStoreKey { + + public static final String CONFIG_DATASTORE = "AdobeMobile_ConfigState"; + public static final String IDENTITY_DATASTORE = "com.adobe.edge.identity"; + public static final String IDENTITY_DIRECT_DATASTORE = "visitorIDServiceDataStore"; + + private DataStoreKey() {} + } + + public static final class SharedStateName { + + public static final String CONFIG = "com.adobe.module.configuration"; + public static final String EVENT_HUB = "com.adobe.module.eventhub"; + + private SharedStateName() {} + } + + public static final class GetIdentitiesHelper { + + public static final String VALUE = "getConsentValue"; + public static final String ERROR = "getConsentError"; + + private GetIdentitiesHelper() {} + } +} diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MockNetworkService.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MockNetworkService.java similarity index 80% rename from code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MockNetworkService.java rename to code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MockNetworkService.java index 537e14b1..56f96bc9 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MockNetworkService.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MockNetworkService.java @@ -9,9 +9,12 @@ governing permissions and limitations under the License. */ -package com.adobe.marketing.mobile; +package com.adobe.marketing.mobile.edge.identity.util; + +import static com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants.LOG_TAG; import com.adobe.marketing.mobile.services.HttpConnecting; +import com.adobe.marketing.mobile.services.Log; import com.adobe.marketing.mobile.services.NetworkCallback; import com.adobe.marketing.mobile.services.NetworkRequest; import com.adobe.marketing.mobile.services.Networking; @@ -24,9 +27,9 @@ */ class MockNetworkService implements Networking { - private static String TAG = "MockNetworkService"; + private static final String LOG_SOURCE = "MockNetworkService"; - private static HttpConnecting dummyConnection = new HttpConnecting() { + private static final HttpConnecting dummyConnection = new HttpConnecting() { @Override public InputStream getInputStream() { return new ByteArrayInputStream("{}".getBytes()); @@ -62,7 +65,7 @@ public void connectAsync(NetworkRequest networkRequest, NetworkCallback networkC return; } - MobileCore.log(LoggingMode.DEBUG, TAG, "Received async request '" + networkRequest.getUrl() + "', ignoring."); + Log.debug(LOG_TAG, LOG_SOURCE, "Received async request '" + networkRequest.getUrl() + "', ignoring."); if (networkCallback != null) { networkCallback.call(dummyConnection); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MonitorExtension.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java similarity index 69% rename from code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MonitorExtension.java rename to code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java index 4b7478ee..9a4d95e9 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MonitorExtension.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java @@ -9,9 +9,23 @@ governing permissions and limitations under the License. */ -package com.adobe.marketing.mobile; - -import com.adobe.marketing.mobile.edge.identity.ADBCountDownLatch; +package com.adobe.marketing.mobile.edge.identity.util; + +import static com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants.LOG_TAG; + +import androidx.annotation.NonNull; +import com.adobe.marketing.mobile.Event; +import com.adobe.marketing.mobile.EventSource; +import com.adobe.marketing.mobile.EventType; +import com.adobe.marketing.mobile.Extension; +import com.adobe.marketing.mobile.ExtensionApi; +import com.adobe.marketing.mobile.ExtensionError; +import com.adobe.marketing.mobile.ExtensionErrorCallback; +import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.SharedStateResolution; +import com.adobe.marketing.mobile.SharedStateResult; +import com.adobe.marketing.mobile.services.Log; +import com.adobe.marketing.mobile.util.DataReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -22,44 +36,40 @@ * A third party extension class aiding for assertion against dispatched events, shared state * and XDM shared state. */ -class MonitorExtension extends Extension { +public class MonitorExtension extends Extension { - private static final String LOG_TAG = "MonitorExtension"; + public static final Class EXTENSION = MonitorExtension.class; + private static final String LOG_SOURCE = "MonitorExtension"; private static final Map> receivedEvents = new HashMap<>(); private static final Map expectedEvents = new HashMap<>(); protected MonitorExtension(ExtensionApi extensionApi) { super(extensionApi); - extensionApi.registerWildcardListener( - MonitorListener.class, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.ERROR, - LOG_TAG, - "There was an error registering Extension Listener: " + extensionError.getErrorName() - ); - } - } - ); } + @NonNull @Override protected String getName() { return "MonitorExtension"; } + @Override + protected void onRegistered() { + super.onRegistered(); + + getApi().registerEventListener(EventType.WILDCARD, EventSource.WILDCARD, this::wildcardProcessor); + } + public static void registerExtension() { MobileCore.registerExtension( MonitorExtension.class, new ExtensionErrorCallback() { @Override public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.ERROR, + Log.error( LOG_TAG, + LOG_SOURCE, "There was an error registering the Monitor extension: " + extensionError.getErrorName() ); } @@ -77,15 +87,7 @@ public static void unregisterExtension() { TestConstants.EventSource.UNREGISTER ) .build(); - MobileCore.dispatchEvent( - event, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log(LoggingMode.ERROR, LOG_TAG, "Failed to unregister Monitor extension."); - } - } - ); + MobileCore.dispatchEvent(event); } /** @@ -111,7 +113,7 @@ public static Map> getReceivedEvents() { * Resets the map of received and expected events. */ public static void reset() { - MobileCore.log(LoggingMode.VERBOSE, LOG_TAG, "Reset expected and received events."); + Log.trace(LOG_TAG, LOG_SOURCE, "Reset expected and received events."); receivedEvents.clear(); expectedEvents.clear(); } @@ -123,7 +125,7 @@ public static void reset() { * All other events are added to the map of received events. If the event is in the map * of expected events, its latch is counted down. * - * @param event + * @param event the event to be processed */ public void wildcardProcessor(final Event event) { if (TestConstants.EventType.MONITOR.equalsIgnoreCase(event.getType())) { @@ -140,10 +142,10 @@ public void wildcardProcessor(final Event event) { EventSpec eventSpec = new EventSpec(event.getSource(), event.getType()); - MobileCore.log(LoggingMode.DEBUG, LOG_TAG, "Received and processing event " + eventSpec); + Log.debug(LOG_TAG, LOG_SOURCE, "Received and processing event " + eventSpec); if (!receivedEvents.containsKey(eventSpec)) { - receivedEvents.put(eventSpec, new ArrayList()); + receivedEvents.put(eventSpec, new ArrayList<>()); } receivedEvents.get(eventSpec).add(event); @@ -155,43 +157,44 @@ public void wildcardProcessor(final Event event) { /** * Processor which unregisters this extension. - * @param event + * @param event the event to be processed */ private void processUnregisterRequest(final Event event) { - MobileCore.log(LoggingMode.DEBUG, LOG_TAG, "Unregistering the Monitor Extension."); + Log.debug(LOG_TAG, LOG_SOURCE, "Unregistering the Monitor Extension."); getApi().unregisterExtension(); } /** * Processor which retrieves and dispatches the XDM shared state for the state owner specified * in the request. - * @param event + * @param event the event to be processed */ private void processXDMSharedStateRequest(final Event event) { - EventData eventData = event.getData(); + final Map eventData = event.getEventData(); if (eventData == null) { return; } - String stateOwner = eventData.optString(TestConstants.EventDataKey.STATE_OWNER, null); + final String stateOwner = DataReader.optString(eventData, TestConstants.EventDataKey.STATE_OWNER, null); if (stateOwner == null) { return; } - EventData sharedState = getApi().getXDMSharedEventState(stateOwner, event); + final SharedStateResult sharedStateResult = getApi() + .getXDMSharedState(stateOwner, event, false, SharedStateResolution.LAST_SET); Event responseEvent = new Event.Builder( "Get Shared State Response", TestConstants.EventType.MONITOR, TestConstants.EventSource.XDM_SHARED_STATE_RESPONSE ) - .setEventData(sharedState == null ? null : sharedState.toObjectMap()) - .setPairID(event.getResponsePairID()) + .setEventData(sharedStateResult == null ? null : sharedStateResult.getValue()) + .inResponseToEvent(event) .build(); - MobileCore.dispatchResponseEvent(responseEvent, event, null); + MobileCore.dispatchEvent(responseEvent); } /** @@ -200,54 +203,31 @@ private void processXDMSharedStateRequest(final Event event) { * @param event */ private void processSharedStateRequest(final Event event) { - EventData eventData = event.getData(); + final Map eventData = event.getEventData(); if (eventData == null) { return; } - String stateOwner = eventData.optString(TestConstants.EventDataKey.STATE_OWNER, null); + final String stateOwner = DataReader.optString(eventData, TestConstants.EventDataKey.STATE_OWNER, null); if (stateOwner == null) { return; } - EventData sharedState = getApi().getSharedEventState(stateOwner, event); + final SharedStateResult sharedStateResult = getApi() + .getSharedState(stateOwner, event, false, SharedStateResolution.LAST_SET); Event responseEvent = new Event.Builder( "Get Shared State Response", TestConstants.EventType.MONITOR, TestConstants.EventSource.SHARED_STATE_RESPONSE ) - .setEventData(sharedState == null ? null : sharedState.toObjectMap()) - .setPairID(event.getResponsePairID()) + .setEventData(sharedStateResult == null ? null : sharedStateResult.getValue()) + .inResponseToEvent(event) .build(); - MobileCore.dispatchResponseEvent(responseEvent, event, null); - } - - /** - * Listener class - */ - public static class MonitorListener extends ExtensionListener { - - protected MonitorListener(ExtensionApi extension, String type, String source) { - super(extension, type, source); - } - - @Override - public void hear(Event event) { - MonitorExtension extension = getParentExtension(); - - if (extension != null) { - extension.wildcardProcessor(event); - } - } - - @Override - protected MonitorExtension getParentExtension() { - return (MonitorExtension) super.getParentExtension(); - } + MobileCore.dispatchEvent(responseEvent); } /** diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/TestConstants.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestConstants.java similarity index 96% rename from code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/TestConstants.java rename to code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestConstants.java index 674fb1e4..69045499 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/TestConstants.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestConstants.java @@ -9,7 +9,7 @@ governing permissions and limitations under the License. */ -package com.adobe.marketing.mobile; +package com.adobe.marketing.mobile.edge.identity.util; /** * Class to maintain test constants. diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/TestHelper.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java similarity index 91% rename from code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/TestHelper.java rename to code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java index 387ef5da..1e8c5b5f 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/TestHelper.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java @@ -9,8 +9,9 @@ governing permissions and limitations under the License. */ -package com.adobe.marketing.mobile; +package com.adobe.marketing.mobile.edge.identity.util; +import static com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants.LOG_TAG; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -19,8 +20,14 @@ import android.app.Instrumentation; import android.content.Context; import androidx.test.platform.app.InstrumentationRegistry; -import com.adobe.marketing.mobile.MonitorExtension.EventSpec; -import com.adobe.marketing.mobile.edge.identity.ADBCountDownLatch; +import com.adobe.marketing.mobile.AdobeCallbackWithError; +import com.adobe.marketing.mobile.AdobeError; +import com.adobe.marketing.mobile.Event; +import com.adobe.marketing.mobile.LoggingMode; +import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.MobileCoreHelper; +import com.adobe.marketing.mobile.edge.identity.util.MonitorExtension.EventSpec; +import com.adobe.marketing.mobile.services.Log; import com.adobe.marketing.mobile.services.ServiceProvider; import java.util.ArrayList; import java.util.Collections; @@ -39,7 +46,7 @@ */ public class TestHelper { - private static final String TAG = "TestHelper"; + private static final String LOG_SOURCE = "TestHelper"; static final int WAIT_TIMEOUT_MS = 1000; static final int WAIT_EVENT_TIMEOUT_MS = 2000; static Application defaultApplication; @@ -81,24 +88,14 @@ public void evaluate() throws Throwable { try { base.evaluate(); } catch (Throwable e) { - MobileCore.log(LoggingMode.DEBUG, "SetupCoreRule", "Wait after test failure."); + Log.debug(LOG_TAG, "SetupCoreRule", "Wait after test failure."); throw e; // rethrow test failure } finally { // After test execution - MobileCore.log( - LoggingMode.DEBUG, - "SetupCoreRule", - "Finished '" + description.getMethodName() + "'" - ); + Log.debug(LOG_TAG, "SetupCoreRule", "Finished '" + description.getMethodName() + "'"); waitForThreads(5000); // wait to allow thread to run after test execution - Core core = MobileCore.getCore(); - if (core != null && core.eventHub != null) { - core.eventHub.shutdown(); - core.eventHub = null; - } - - MobileCore.setCore(null); + MobileCoreHelper.resetSDK(); TestPersistenceHelper.resetKnownPersistence(); resetTestExpectations(); } @@ -157,16 +154,12 @@ public static void waitForThreads(final int timeoutMillis) { Set threadSet = getEligibleThreads(); while (threadSet.size() > 0 && ((System.currentTimeMillis() - startTime) < timeoutTestMillis)) { - MobileCore.log( - LoggingMode.DEBUG, - TAG, - "waitForThreads - Still waiting for " + threadSet.size() + " thread(s)" - ); + Log.debug(LOG_TAG, LOG_SOURCE, "waitForThreads - Still waiting for " + threadSet.size() + " thread(s)"); for (Thread t : threadSet) { - MobileCore.log( - LoggingMode.DEBUG, - TAG, + Log.debug( + LOG_TAG, + LOG_SOURCE, "waitForThreads - Waiting for thread " + t.getName() + " (" + t.getId() + ")" ); boolean done = false; @@ -189,15 +182,15 @@ public static void waitForThreads(final int timeoutMillis) { } if (timedOut) { - MobileCore.log( - LoggingMode.DEBUG, - TAG, + Log.debug( + LOG_TAG, + LOG_SOURCE, "waitForThreads - Timeout out waiting for thread " + t.getName() + " (" + t.getId() + ")" ); } else { - MobileCore.log( - LoggingMode.DEBUG, - TAG, + Log.debug( + LOG_TAG, + LOG_SOURCE, "waitForThreads - Done waiting for thread " + t.getName() + " (" + t.getId() + ")" ); } @@ -206,7 +199,7 @@ public static void waitForThreads(final int timeoutMillis) { threadSet = getEligibleThreads(); } - MobileCore.log(LoggingMode.DEBUG, TAG, "waitForThreads - All known threads are terminated."); + Log.debug(LOG_TAG, LOG_SOURCE, "waitForThreads - All known threads are terminated."); } /** @@ -257,7 +250,7 @@ private static boolean isAppThread(final Thread t) { * Resets the network and event test expectations. */ public static void resetTestExpectations() { - MobileCore.log(LoggingMode.DEBUG, TAG, "Resetting functional test expectations for events"); + Log.debug(LOG_TAG, LOG_SOURCE, "Resetting functional test expectations for events"); MonitorExtension.reset(); } @@ -376,9 +369,9 @@ public static void assertUnexpectedEvents(final boolean shouldWait) throws Inter receivedEvent.getValue().size() ) ); - MobileCore.log( - LoggingMode.DEBUG, - TAG, + Log.debug( + LOG_TAG, + LOG_SOURCE, String.format( "Received unexpected event with type: %s source: %s", receivedEvent.getKey().type, @@ -477,7 +470,13 @@ public static Map getSharedStateFor(final String stateOwner, int final Map sharedState = new HashMap<>(); MobileCore.dispatchEventWithResponseCallback( event, - new AdobeCallback() { + 5000L, + new AdobeCallbackWithError() { + @Override + public void fail(AdobeError adobeError) { + Log.error(LOG_TAG, LOG_SOURCE, "Failed to get shared state for " + stateOwner + ": " + adobeError); + } + @Override public void call(Event event) { if (event.getEventData() != null) { @@ -486,16 +485,6 @@ public void call(Event event) { latch.countDown(); } - }, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.ERROR, - TAG, - "Failed to get shared state for " + stateOwner + ": " + extensionError - ); - } } ); @@ -532,7 +521,13 @@ public static Map getXDMSharedStateFor(final String stateOwner, final Map sharedState = new HashMap<>(); MobileCore.dispatchEventWithResponseCallback( event, - new AdobeCallback() { + 5000L, + new AdobeCallbackWithError() { + @Override + public void fail(AdobeError adobeError) { + Log.debug(LOG_TAG, LOG_SOURCE, "Failed to get shared state for " + stateOwner + ": " + adobeError); + } + @Override public void call(Event event) { if (event.getEventData() != null) { @@ -541,16 +536,6 @@ public void call(Event event) { latch.countDown(); } - }, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.ERROR, - TAG, - "Failed to get shared state for " + stateOwner + ": " + extensionError - ); - } } ); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/TestPersistenceHelper.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestPersistenceHelper.java similarity index 97% rename from code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/TestPersistenceHelper.java rename to code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestPersistenceHelper.java index 65f8fae9..84de4b78 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/TestPersistenceHelper.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestPersistenceHelper.java @@ -9,14 +9,13 @@ governing permissions and limitations under the License. */ -package com.adobe.marketing.mobile; +package com.adobe.marketing.mobile.edge.identity.util; import static org.junit.Assert.fail; import android.app.Application; import android.content.Context; import android.content.SharedPreferences; -import com.adobe.marketing.mobile.edge.identity.IdentityTestConstants; import java.util.ArrayList; /** diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityExtension.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityExtension.java index ac595451..ef6f2c77 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityExtension.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityExtension.java @@ -22,7 +22,6 @@ import com.adobe.marketing.mobile.SharedStateResult; import com.adobe.marketing.mobile.SharedStateStatus; import com.adobe.marketing.mobile.services.Log; -import com.adobe.marketing.mobile.services.ServiceProvider; import com.adobe.marketing.mobile.util.StringUtils; import com.adobe.marketing.mobile.util.TimeUtils; import java.util.HashMap; @@ -95,6 +94,8 @@ protected String getVersion() { */ @Override protected void onRegistered() { + super.onRegistered(); + // GENERIC_IDENTITY event listeners getApi() .registerEventListener( @@ -176,7 +177,7 @@ void handleRequestIdentity(@NonNull final Event event) { * * @param event the identity request {@link Event} */ - private void handleUrlVariablesRequest(@NonNull final Event event) { + void handleUrlVariablesRequest(@NonNull final Event event) { final SharedStateResult configSharedStateResult = sharedStateHandle.getSharedState( IdentityConstants.SharedState.Configuration.NAME, event @@ -224,7 +225,7 @@ private void handleUrlVariablesRequest(@NonNull final Event event) { * @param event the identity request {@link Event} * @param urlVariables {@link String} representing the urlVariables encoded string */ - void handleUrlVariableResponse(@NonNull final Event event, final String urlVariables) { + private void handleUrlVariableResponse(@NonNull final Event event, final String urlVariables) { handleUrlVariableResponse(event, urlVariables, null); } @@ -235,7 +236,11 @@ void handleUrlVariableResponse(@NonNull final Event event, final String urlVaria * @param urlVariables {@link String} representing the urlVariables encoded string * @param errorMsg {@link String} representing error encountered while generating the urlVariables string */ - void handleUrlVariableResponse(@NonNull final Event event, final String urlVariables, final String errorMsg) { + private void handleUrlVariableResponse( + @NonNull final Event event, + final String urlVariables, + final String errorMsg + ) { Event responseEvent = new Event.Builder( IdentityConstants.EventNames.IDENTITY_RESPONSE_URL_VARIABLES, IdentityConstants.EventType.EDGE_IDENTITY, diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityState.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityState.java index 2abf6c67..080d4302 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityState.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityState.java @@ -13,12 +13,12 @@ import static com.adobe.marketing.mobile.edge.identity.IdentityConstants.LOG_TAG; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.MobileCore; import com.adobe.marketing.mobile.SharedStateResult; import com.adobe.marketing.mobile.SharedStateStatus; -import com.adobe.marketing.mobile.services.DataStoring; import com.adobe.marketing.mobile.services.Log; import com.adobe.marketing.mobile.services.ServiceProvider; import com.adobe.marketing.mobile.util.DataReader; @@ -51,17 +51,10 @@ class IdentityState { this.identityProperties = (persistedProperties != null) ? persistedProperties : new IdentityProperties(); } - /** - * @return the current bootup status - */ - @VisibleForTesting - boolean hasBooted() { - return hasBooted; - } - /** * @return The current {@link IdentityProperties} for this identity state */ + @NonNull IdentityProperties getIdentityProperties() { return identityProperties; } diff --git a/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java b/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java index ee8f58e2..59a97a99 100644 --- a/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java +++ b/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java @@ -11,12 +11,10 @@ package com.adobe.marketing.mobile.edge.identity; -import com.adobe.marketing.mobile.AdobeCallback; -import com.adobe.marketing.mobile.AdobeCallbackWithError; -import com.adobe.marketing.mobile.AdobeError; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.JSONUtils; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -29,8 +27,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -39,102 +35,6 @@ */ class IdentityTestUtil { - /** - * Method to serialize jsonObject to Map. - * - * @param jsonObject the {@link JSONObject} to be serialized - * @return a {@link Map} representing the serialized JSONObject - */ - - static Map toMap(final JSONObject jsonObject) { - if (jsonObject == null) { - return null; - } - - Map jsonAsMap = new HashMap(); - Iterator keysIterator = jsonObject.keys(); - - while (keysIterator.hasNext()) { - String nextKey = keysIterator.next(); - Object value = null; - Object returnValue; - - try { - value = jsonObject.get(nextKey); - } catch (JSONException e) { - MobileCore.log( - LoggingMode.DEBUG, - "Functional Test", - "toMap - Unable to convert jsonObject to Map for key " + nextKey + ", skipping." - ); - } - - if (value == null) { - continue; - } - - if (value instanceof JSONObject) { - returnValue = toMap((JSONObject) value); - } else if (value instanceof JSONArray) { - returnValue = toList((JSONArray) value); - } else { - returnValue = value; - } - - jsonAsMap.put(nextKey, returnValue); - } - - return jsonAsMap; - } - - /** - * Converts provided {@link JSONArray} into {@link List} for any number of levels which can be used as event data - * This method is recursive. - * The elements for which the conversion fails will be skipped. - * - * @param jsonArray to be converted - * @return {@link List} containing the elements from the provided json, null if {@code jsonArray} is null - */ - static List toList(final JSONArray jsonArray) { - if (jsonArray == null) { - return null; - } - - List jsonArrayAsList = new ArrayList(); - int size = jsonArray.length(); - - for (int i = 0; i < size; i++) { - Object value = null; - Object returnValue; - - try { - value = jsonArray.get(i); - } catch (JSONException e) { - MobileCore.log( - LoggingMode.DEBUG, - "Functional Test", - "toList - Unable to convert jsonObject to List for index " + i + ", skipping." - ); - } - - if (value == null) { - continue; - } - - if (value instanceof JSONObject) { - returnValue = toMap((JSONObject) value); - } else if (value instanceof JSONArray) { - returnValue = toList((JSONArray) value); - } else { - returnValue = value; - } - - jsonArrayAsList.add(returnValue); - } - - return jsonArrayAsList; - } - /** * Helper method to create IdentityXDM Map using {@link TestItem}s */ @@ -166,7 +66,7 @@ static Map createXDMIdentityMap(TestItem... items) { */ static Event buildRemoveIdentityRequestWithJSONString(final String jsonStr) throws Exception { final JSONObject jsonObject = new JSONObject(jsonStr); - final Map xdmData = Utils.toMap(jsonObject); + final Map xdmData = JSONUtils.toMap(jsonObject); return buildRemoveIdentityRequest(xdmData); } @@ -188,7 +88,7 @@ static Event buildRemoveIdentityRequest(final Map map) { */ static Event buildUpdateIdentityRequestJSONString(final String jsonStr) throws Exception { final JSONObject jsonObject = new JSONObject(jsonStr); - final Map xdmData = Utils.toMap(jsonObject); + final Map xdmData = JSONUtils.toMap(jsonObject); return buildUpdateIdentityRequest(xdmData); } @@ -214,7 +114,7 @@ static Event buildUpdateIdentityRequest(final Map map) { */ static Map flattenJSONString(final String jsonString) throws JSONException { JSONObject jsonObject = new JSONObject(jsonString); - Map persistenceValueMap = Utils.toMap(jsonObject); + Map persistenceValueMap = JSONUtils.toMap(jsonObject); return flattenMap(persistenceValueMap); } @@ -284,9 +184,9 @@ private static void addKeys(String currentPath, JsonNode jsonNode, Map getIdentitiesSync() { - try { - final HashMap getIdentityResponse = new HashMap<>(); - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - Identity.getIdentities( - new AdobeCallbackWithError() { - @Override - public void call(final IdentityMap identities) { - getIdentityResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, identities); - latch.countDown(); - } - - @Override - public void fail(final AdobeError adobeError) { - getIdentityResponse.put(IdentityTestConstants.GetIdentitiesHelper.ERROR, adobeError); - latch.countDown(); - } - } - ); - latch.await(2000, TimeUnit.MILLISECONDS); - - return getIdentityResponse; - } catch (Exception exp) { - return null; - } - } - - static String getExperienceCloudIdSync() { - try { - final HashMap getExperienceCloudIdResponse = new HashMap<>(); - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - Identity.getExperienceCloudId( - new AdobeCallback() { - @Override - public void call(final String ecid) { - getExperienceCloudIdResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, ecid); - latch.countDown(); - } - } - ); - latch.await(2000, TimeUnit.MILLISECONDS); - return getExperienceCloudIdResponse.get(IdentityTestConstants.GetIdentitiesHelper.VALUE); - } catch (Exception exp) { - return null; - } - } - - static String getUrlVariablesSync() { - try { - final HashMap getUrlVariablesResponse = new HashMap<>(); - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - Identity.getUrlVariables( - new AdobeCallback() { - @Override - public void call(final String urlVariables) { - getUrlVariablesResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, urlVariables); - latch.countDown(); - } - } - ); - latch.await(2000, TimeUnit.MILLISECONDS); - return getUrlVariablesResponse.get(IdentityTestConstants.GetIdentitiesHelper.VALUE); - } catch (Exception exp) { - return null; - } - } - - static IdentityMap CreateIdentityMap(final String namespace, final String id) { - return CreateIdentityMap(namespace, id, AuthenticatedState.AMBIGUOUS, false); - } - - static IdentityMap CreateIdentityMap( - final String namespace, - final String id, - final AuthenticatedState state, - final boolean isPrimary - ) { - IdentityMap map = new IdentityMap(); - IdentityItem item = new IdentityItem(id, state, isPrimary); - map.addItem(item, namespace); - return map; - } } diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java index 6483db01..2dbee4f4 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java @@ -13,7 +13,6 @@ import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertNotNull; import static org.junit.Assert.assertNotEquals; @@ -21,9 +20,9 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.junit.Assert; import org.junit.Test; -@SuppressWarnings("unchecked") public class ECIDTests { @Test @@ -112,15 +111,15 @@ public void testECID_equals() { ECID a = new ECID(); ECID b = new ECID(a.toString()); - assertTrue(a.equals(b)); - assertTrue(b.equals(a)); - assertTrue(a.equals(a)); - assertTrue(b.equals(b)); + Assert.assertEquals(a, b); + Assert.assertEquals(b, a); + Assert.assertEquals(a, a); + Assert.assertEquals(b, b); - assertFalse(a.equals(null)); - assertFalse(a.equals(new ECID())); + Assert.assertNotNull(a); + assertNotEquals(a, new ECID()); - assertFalse(a.equals(new NotECID(a.toString()))); + assertNotEquals(a, new NotECID(a.toString())); } private class NotECID { diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/EventUtilsTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/EventUtilsTests.java index bd6203b0..95136a19 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/EventUtilsTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/EventUtilsTests.java @@ -17,7 +17,9 @@ import static org.junit.Assert.assertTrue; import com.adobe.marketing.mobile.Event; +import java.util.Collections; import java.util.HashMap; +import java.util.Map; import org.junit.Test; public class EventUtilsTests { @@ -289,6 +291,96 @@ public void test_getAdId_whenValid_thenValid() { assertEquals("adId", EventUtils.getAdId(event)); } + // ====================================================================================================================== + // Tests for method : isSharedStateUpdateFor(final String stateOwnerName, final Event event) + // ====================================================================================================================== + + @Test + public void test_isSharedStateUpdateFor_stateOwnerIsNull() { + final Event event = new Event.Builder( + "Shared state event", + IdentityConstants.EventType.GENERIC_IDENTITY, + IdentityConstants.EventSource.REQUEST_IDENTITY + ) + .setEventData(Collections.EMPTY_MAP) + .build(); + + assertFalse(EventUtils.isSharedStateUpdateFor(null, event)); + } + + @Test + public void test_isSharedStateUpdateFor_eventIsNull() { + assertFalse(EventUtils.isSharedStateUpdateFor(IdentityConstants.SharedState.Configuration.NAME, null)); + } + + @Test + public void test_isSharedStateUpdateFor_stateOwnerValueIsNull() { + final Event event = new Event.Builder( + "Shared state event", + IdentityConstants.EventType.GENERIC_IDENTITY, + IdentityConstants.EventSource.REQUEST_IDENTITY + ) + .setEventData(Collections.singletonMap(IdentityConstants.EventDataKeys.STATE_OWNER, null)) + .build(); + + assertFalse(EventUtils.isSharedStateUpdateFor(IdentityConstants.EventType.GENERIC_IDENTITY, event)); + } + + @Test + public void test_isSharedStateUpdateFor_stateOwnerValueIsEmpty() { + final Event event = new Event.Builder( + "Shared state event", + IdentityConstants.EventType.GENERIC_IDENTITY, + IdentityConstants.EventSource.REQUEST_IDENTITY + ) + .setEventData(Collections.singletonMap(IdentityConstants.EventDataKeys.STATE_OWNER, "")) + .build(); + + assertFalse(EventUtils.isSharedStateUpdateFor(IdentityConstants.EXTENSION_NAME, event)); + } + + @Test + public void test_isSharedStateUpdateFor_stateOwnerValueExists() { + final Event event = new Event.Builder( + "Shared state event", + IdentityConstants.EventType.GENERIC_IDENTITY, + IdentityConstants.EventSource.REQUEST_IDENTITY + ) + .setEventData( + Collections.singletonMap(IdentityConstants.EventDataKeys.STATE_OWNER, "com.adobe.module.configuration") + ) + .build(); + + assertTrue(EventUtils.isSharedStateUpdateFor("com.adobe.module.configuration", event)); + assertFalse(EventUtils.isSharedStateUpdateFor(IdentityConstants.EXTENSION_NAME, event)); + } + + // ====================================================================================================================== + // Tests for method : getECID(final Map identityDirectSharedState) + // ====================================================================================================================== + @Test + public void test_getECID_valueExists() { + final Map identityDirectState = Collections.singletonMap( + IdentityConstants.SharedState.IdentityDirect.ECID, + "SomeRandomECID" + ); + assertEquals("SomeRandomECID", EventUtils.getECID(identityDirectState).toString()); + } + + @Test + public void test_getECID_valueDoesNotExist() { + assertNull(EventUtils.getECID(Collections.EMPTY_MAP)); + } + + @Test + public void test_getECID_valueIsNull() { + final Map identityDirectState = Collections.singletonMap( + IdentityConstants.SharedState.IdentityDirect.ECID, + null + ); + assertNull(EventUtils.getECID(identityDirectState)); + } + // Test helpers /** diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityExtensionTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityExtensionTests.java index c156d2de..2e313f0b 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityExtensionTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityExtensionTests.java @@ -12,43 +12,36 @@ package com.adobe.marketing.mobile.edge.identity; import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.*; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.buildUpdateIdentityRequest; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.times; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.when; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; -import android.app.Application; -import android.content.Context; -import android.content.SharedPreferences; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionErrorCallback; -import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.SharedStateResolution; +import com.adobe.marketing.mobile.SharedStateResult; +import com.adobe.marketing.mobile.SharedStateStatus; +import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.json.JSONObject; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; -@RunWith(PowerMockRunner.class) -@PrepareForTest({ Event.class, MobileCore.class, ExtensionApi.class, IdentityState.class }) public class IdentityExtensionTests { private IdentityExtension extension; @@ -57,110 +50,61 @@ public class IdentityExtensionTests { ExtensionApi mockExtensionApi; @Mock - Application mockApplication; - - @Mock - Context mockContext; - - @Mock - SharedPreferences mockSharedPreference; - - @Mock - SharedPreferences.Editor mockSharedPreferenceEditor; + IdentityState mockIdentityState; @Before public void setup() { - PowerMockito.mockStatic(MobileCore.class); - - Mockito.when(MobileCore.getApplication()).thenReturn(mockApplication); - Mockito.when(mockApplication.getApplicationContext()).thenReturn(mockContext); - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito.when(mockSharedPreference.edit()).thenReturn(mockSharedPreferenceEditor); - - extension = new IdentityExtension(mockExtensionApi); - - // simulate bootup - extension.bootupIfReady(); - verify(mockExtensionApi, times(1)) - .setXDMSharedEventState(any(Map.class), nullable(Event.class), any(ExtensionErrorCallback.class)); - clearInvocations(mockExtensionApi); + MockitoAnnotations.openMocks(this); } // ======================================================================================== - // constructor + // onRegistered // ======================================================================================== @Test - public void test_ListenersRegistration() { - // setup - final ArgumentCaptor callbackCaptor = ArgumentCaptor.forClass( - ExtensionErrorCallback.class - ); - + public void test_onRegistered_registersListeners() { // test extension = new IdentityExtension(mockExtensionApi); + extension.onRegistered(); - // verify 2 listeners are registered - verify(mockExtensionApi, times(7)) - .registerEventListener(anyString(), anyString(), any(Class.class), any(ExtensionErrorCallback.class)); - - // verify listeners are registered with correct event source and type - verify(mockExtensionApi, times(1)) + // verify + verify(mockExtensionApi) .registerEventListener( eq(IdentityConstants.EventType.GENERIC_IDENTITY), eq(IdentityConstants.EventSource.REQUEST_CONTENT), - eq(ListenerIdentityRequestContent.class), - callbackCaptor.capture() + any() ); - verify(mockExtensionApi, times(1)) + verify(mockExtensionApi) + .registerEventListener( + eq(IdentityConstants.EventType.GENERIC_IDENTITY), + eq(IdentityConstants.EventSource.REQUEST_RESET), + any() + ); + verify(mockExtensionApi) .registerEventListener( eq(IdentityConstants.EventType.EDGE_IDENTITY), eq(IdentityConstants.EventSource.REQUEST_IDENTITY), - eq(ListenerEdgeIdentityRequestIdentity.class), - callbackCaptor.capture() + any() ); - verify(mockExtensionApi, times(1)) + verify(mockExtensionApi) .registerEventListener( eq(IdentityConstants.EventType.EDGE_IDENTITY), eq(IdentityConstants.EventSource.UPDATE_IDENTITY), - eq(ListenerEdgeIdentityUpdateIdentity.class), - callbackCaptor.capture() + any() ); - verify(mockExtensionApi, times(1)) + verify(mockExtensionApi) .registerEventListener( eq(IdentityConstants.EventType.EDGE_IDENTITY), eq(IdentityConstants.EventSource.REMOVE_IDENTITY), - eq(ListenerEdgeIdentityRemoveIdentity.class), - callbackCaptor.capture() - ); - verify(mockExtensionApi, times(1)) - .registerEventListener( - eq(IdentityConstants.EventType.GENERIC_IDENTITY), - eq(IdentityConstants.EventSource.REQUEST_RESET), - eq(ListenerIdentityRequestReset.class), - callbackCaptor.capture() + any() ); - verify(mockExtensionApi, times(1)) + verify(mockExtensionApi) .registerEventListener( eq(IdentityConstants.EventType.HUB), eq(IdentityConstants.EventSource.SHARED_STATE), - eq(ListenerHubSharedState.class), - callbackCaptor.capture() - ); - verify(mockExtensionApi, times(1)) - .registerEventListener( - eq(IdentityConstants.EventType.HUB), - eq(IdentityConstants.EventSource.BOOTED), - eq(ListenerEventHubBoot.class), - callbackCaptor.capture() + any() ); - // verify the callback - ExtensionErrorCallback extensionErrorCallback = callbackCaptor.getValue(); - Assert.assertNotNull("The extension callback should not be null", extensionErrorCallback); - // TODO - enable when ExtensionError creation is available - //extensionErrorCallback.error(ExtensionError.UNEXPECTED_ERROR); + verifyNoMoreInteractions(mockExtensionApi); } // ======================================================================================== @@ -169,7 +113,8 @@ public void test_ListenersRegistration() { @Test public void test_getName() { // test - String moduleName = extension.getName(); + extension = new IdentityExtension(mockExtensionApi); + final String moduleName = extension.getName(); assertEquals("getName should return the correct module name", IdentityConstants.EXTENSION_NAME, moduleName); } @@ -179,7 +124,8 @@ public void test_getName() { @Test public void test_getVersion() { // test - String moduleVersion = extension.getVersion(); + extension = new IdentityExtension(mockExtensionApi); + final String moduleVersion = extension.getVersion(); assertEquals( "getVersion should return the correct module version", IdentityConstants.EXTENSION_VERSION, @@ -188,246 +134,282 @@ public void test_getVersion() { } // ======================================================================================== - // handleIdentityRequest + // readyForEvent(Event event) // ======================================================================================== - @Test - public void test_handleIdentityRequest_nullEvent_shouldNotThrow() { - // test - extension.handleIdentityRequest(null); + public void test_readyForEvent_cannotBoot() { + // setup + when(mockIdentityState.bootupIfReady(any())).thenReturn(false); + + // test and verify + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + assertFalse(extension.readyForEvent(buildUpdateIdentityRequest(Collections.EMPTY_MAP))); } @Test - public void test_handleIdentityRequest_generatesNewECID() { + public void test_readyForEvent_GetUrlVariablesRequestButConfigurationStateUnavailable() { // setup + when(mockIdentityState.bootupIfReady(any())).thenReturn(true); Event event = new Event.Builder( "Test event", IdentityConstants.EventType.EDGE_IDENTITY, IdentityConstants.EventSource.REQUEST_IDENTITY ) + .setEventData( + new HashMap() { + { + put("urlvariables", true); + } + } + ) .build(); - final ArgumentCaptor responseEventCaptor = ArgumentCaptor.forClass(Event.class); - final ArgumentCaptor requestEventCaptor = ArgumentCaptor.forClass(Event.class); - - // test - extension.handleIdentityRequest(event); - - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchResponseEvent( - responseEventCaptor.capture(), - requestEventCaptor.capture(), - any(ExtensionErrorCallback.class) - ); - // verify response event containing ECID is dispatched - Event ecidResponseEvent = responseEventCaptor.getAllValues().get(0); - final IdentityMap identityMap = IdentityMap.fromXDMMap(ecidResponseEvent.getEventData()); - final String ecid = identityMap.getIdentityItemsForNamespace("ECID").get(0).getId(); + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.Configuration.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn(null); - assertNotNull(ecid); - assertTrue(ecid.length() > 0); + // test and verify + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + assertFalse(extension.readyForEvent(event)); } @Test - public void test_handleIdentityRequest_loadsPersistedECID() { + public void test_readyForEvent_GetUrlVariablesRequest_ConfigurationStatePending() { // setup - ECID existingECID = new ECID(); - IdentityProperties persistedProps = new IdentityProperties(); - persistedProps.setECID(existingECID); - PowerMockito.stub(PowerMockito.method(IdentityState.class, "getIdentityProperties")).toReturn(persistedProps); - + when(mockIdentityState.bootupIfReady(any())).thenReturn(true); Event event = new Event.Builder( "Test event", IdentityConstants.EventType.EDGE_IDENTITY, IdentityConstants.EventSource.REQUEST_IDENTITY ) + .setEventData( + new HashMap() { + { + put("urlvariables", true); + } + } + ) .build(); - final ArgumentCaptor responseEventCaptor = ArgumentCaptor.forClass(Event.class); - final ArgumentCaptor requestEventCaptor = ArgumentCaptor.forClass(Event.class); - // test - extension = new IdentityExtension(mockExtensionApi); - extension.handleIdentityRequest(event); - - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchResponseEvent( - responseEventCaptor.capture(), - requestEventCaptor.capture(), - any(ExtensionErrorCallback.class) - ); - - // verify response event containing ECID is dispatched - Event ecidResponseEvent = responseEventCaptor.getAllValues().get(0); - final IdentityMap identityMap = IdentityMap.fromXDMMap(ecidResponseEvent.getEventData()); - final String ecid = identityMap.getIdentityItemsForNamespace("ECID").get(0).getId(); + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.Configuration.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn(new SharedStateResult(SharedStateStatus.PENDING, null)); - assertEquals(existingECID.toString(), ecid); + // test and verify + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + assertFalse(extension.readyForEvent(event)); } @Test - public void test_handleIdentityRequest_noIdentifiers_emptyXDMIdentityMap() { - // Setup - IdentityProperties emptyProps = new IdentityProperties(); - PowerMockito.stub(PowerMockito.method(IdentityState.class, "getIdentityProperties")).toReturn(emptyProps); - + public void test_readyForEvent_GetUrlVariablesRequest_ConfigurationStateSet() { + // setup + when(mockIdentityState.bootupIfReady(any())).thenReturn(true); Event event = new Event.Builder( "Test event", IdentityConstants.EventType.EDGE_IDENTITY, IdentityConstants.EventSource.REQUEST_IDENTITY ) + .setEventData( + new HashMap() { + { + put("urlvariables", true); + } + } + ) .build(); - final ArgumentCaptor responseEventCaptor = ArgumentCaptor.forClass(Event.class); - final ArgumentCaptor requestEventCaptor = ArgumentCaptor.forClass(Event.class); + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.Configuration.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, Collections.EMPTY_MAP)); - // Test - extension.handleIdentityRequest(event); - - // Verify event dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchResponseEvent( - responseEventCaptor.capture(), - requestEventCaptor.capture(), - any(ExtensionErrorCallback.class) - ); + // test and verify + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + assertTrue(extension.readyForEvent(event)); + } - // Verify response event containing ECID is dispatched - Event ecidResponseEvent = responseEventCaptor.getAllValues().get(0); - final Map xdmData = ecidResponseEvent.getEventData(); - final Map identityMap = (Map) xdmData.get("identityMap"); + @Test + public void test_readyForEvent_OtherEvent_canBoot() { + // setup + when(mockIdentityState.bootupIfReady(any())).thenReturn(true); - assertTrue(identityMap.isEmpty()); + // test and verify + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + assertTrue(extension.readyForEvent(buildUpdateIdentityRequest(Collections.EMPTY_MAP))); } + // ======================================================================================== + // handleRequestIdentity + // ======================================================================================== + @Test - public void test_handleIdentityResetRequest() { + public void test_handleRequestIdentity_DispatchesResponseEvent_PersistedECIDExists() { // setup + final IdentityProperties properties = new IdentityProperties(); + properties.setECID(new ECID()); // simulate persisted ECID + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); + + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + Event event = new Event.Builder( "Test event", - IdentityConstants.EventType.GENERIC_IDENTITY, - IdentityConstants.EventSource.REQUEST_RESET + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.REQUEST_IDENTITY ) .build(); - final ArgumentCaptor sharedStateCaptor = ArgumentCaptor.forClass(Map.class); - final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); + final ArgumentCaptor responseEventCaptor = ArgumentCaptor.forClass(Event.class); // test - extension.handleRequestReset(event); + extension.handleRequestIdentity(event); - // verify - verify(mockExtensionApi, times(1)) - .setXDMSharedEventState(sharedStateCaptor.capture(), eq(event), any(ExtensionErrorCallback.class)); - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEvent(eventCaptor.capture(), any(ExtensionErrorCallback.class)); + // verify that an event is dispatched + verify(mockExtensionApi).dispatch(responseEventCaptor.capture()); - Map sharedState = flattenMap(sharedStateCaptor.getValue()); - assertTrue(sharedState.get("identityMap.ECID[0].id").length() > 0); + // verify that it is a response event to the incident event + final Event capturedResponseEvent = responseEventCaptor.getValue(); + assertEquals(capturedResponseEvent.getResponseID(), event.getUniqueIdentifier()); + + // verify that the data sent in the response event contains the ecid from properties + final Event ecidResponseEvent = responseEventCaptor.getAllValues().get(0); + final IdentityMap identityMap = IdentityMap.fromXDMMap(ecidResponseEvent.getEventData()); + assertNotNull(identityMap); + final String ecid = identityMap.getIdentityItemsForNamespace("ECID").get(0).getId(); + assertEquals(ecid, properties.getECID().toString()); } - @Test - public void test_handleHubSharedState_updateLegacyEcidOnDirectIdentityStateChange() { - final ECID existingECID = new ECID(); - setupExistingIdentityProps(existingECID); - setIdentityDirectSharedState("1234"); + // ======================================================================================== + // handleIdentityDirectECIDUpdate + // ======================================================================================== - Event event = new Event.Builder( - "Test event", + @Test + public void test_handleIdentityDirectECIDUpdate_notAnIdentityDirectStateUpdate() { + final Event event = new Event.Builder( + "Not an IdentityDirect State event", IdentityConstants.EventType.HUB, IdentityConstants.EventSource.SHARED_STATE ) .setEventData( new HashMap() { { - put( - IdentityConstants.EventDataKeys.STATE_OWNER, - IdentityConstants.SharedState.IdentityDirect.NAME - ); + put(IdentityConstants.EventDataKeys.STATE_OWNER, "Some.Other.Extension.Name"); } } ) .build(); - extension.handleHubSharedState(event); + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + extension.handleIdentityDirectECIDUpdate(event); - final ArgumentCaptor> sharedStateCaptor = ArgumentCaptor.forClass(Map.class); - verify(mockExtensionApi, times(1)) - .setXDMSharedEventState(sharedStateCaptor.capture(), eq(event), any(ExtensionErrorCallback.class)); - Map sharedState = sharedStateCaptor.getValue(); - assertEquals("1234", flattenMap(sharedState).get("identityMap.ECID[1].id")); // Legacy ECID is set as a secondary ECID - - final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); - // verify no event dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(0)); - MobileCore.dispatchEvent(eventCaptor.capture(), any(ExtensionErrorCallback.class)); - assertTrue(eventCaptor.getAllValues().isEmpty()); + verify(mockExtensionApi, never()).getSharedState(any(), any(), anyBoolean(), any()); + verify(mockIdentityState, never()).updateLegacyExperienceCloudId(any()); + verify(mockExtensionApi, never()).createXDMSharedState(any(), any()); } @Test - public void test_handleHubSharedState_noOpNullEvent() { - setIdentityDirectSharedState("1234"); - - extension.handleHubSharedState(null); - - verify(mockExtensionApi, times(0)) - .setXDMSharedEventState(any(Map.class), any(Event.class), any(ExtensionErrorCallback.class)); - } - - @Test - public void test_handleHubSharedState_noOpNullEventData() { - setIdentityDirectSharedState("1234"); - - Event event = new Event.Builder( - "Test event", + public void test_handleIdentityDirectECIDUpdate_identityDirectStateResultIsNull() { + final Event event = new Event.Builder( + "IdentityDirect State event", IdentityConstants.EventType.HUB, IdentityConstants.EventSource.SHARED_STATE ) + .setEventData( + new HashMap() { + { + put( + IdentityConstants.EventDataKeys.STATE_OWNER, + IdentityConstants.SharedState.IdentityDirect.NAME + ); + } + } + ) .build(); + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.IdentityDirect.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn(null); - extension.handleHubSharedState(event); + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + extension.handleIdentityDirectECIDUpdate(event); - verify(mockExtensionApi, times(0)) - .setXDMSharedEventState(any(Map.class), any(Event.class), any(ExtensionErrorCallback.class)); + verify(mockExtensionApi) + .getSharedState( + IdentityConstants.SharedState.IdentityDirect.NAME, + event, + false, + SharedStateResolution.LAST_SET + ); + verify(mockIdentityState, never()).updateLegacyExperienceCloudId(any()); + verify(mockExtensionApi, never()).createXDMSharedState(any(), any()); } @Test - public void test_handleHubSharedState_noOpNotDirectIdentityStateChange() { - setIdentityDirectSharedState("1234"); - - Event event = new Event.Builder( - "Test event", + public void test_handleIdentityDirectECIDUpdate_identityDirectStateIsNull() { + final Event event = new Event.Builder( + "IdentityDirect State event", IdentityConstants.EventType.HUB, IdentityConstants.EventSource.SHARED_STATE ) .setEventData( new HashMap() { { - put(IdentityConstants.EventDataKeys.STATE_OWNER, "com.adobe.module.configuration"); + put( + IdentityConstants.EventDataKeys.STATE_OWNER, + IdentityConstants.SharedState.IdentityDirect.NAME + ); } } ) .build(); + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.IdentityDirect.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, null)); - extension.handleHubSharedState(event); + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + extension.handleIdentityDirectECIDUpdate(event); - verify(mockExtensionApi, times(0)) - .setXDMSharedEventState(any(Map.class), any(Event.class), any(ExtensionErrorCallback.class)); + verify(mockExtensionApi) + .getSharedState( + IdentityConstants.SharedState.IdentityDirect.NAME, + event, + false, + SharedStateResolution.LAST_SET + ); + verify(mockIdentityState, never()).updateLegacyExperienceCloudId(any()); + verify(mockExtensionApi, never()).createXDMSharedState(any(), any()); } @Test - public void test_handleHubSharedState_noOpNoDirectIdentitySharedState() { - when( - mockExtensionApi.getSharedEventState( - eq(IdentityConstants.SharedState.IdentityDirect.NAME), - any(Event.class), - any(ExtensionErrorCallback.class) - ) - ) - .thenReturn(null); - - Event event = new Event.Builder( - "Test event", + public void test_handleIdentityDirectECIDUpdate_legacyEcidUpdateFailed() { + final Event event = new Event.Builder( + "IdentityDirect State event", IdentityConstants.EventType.HUB, IdentityConstants.EventSource.SHARED_STATE ) @@ -443,18 +425,40 @@ public void test_handleHubSharedState_noOpNoDirectIdentitySharedState() { ) .build(); - extension.handleHubSharedState(event); + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.IdentityDirect.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn( + new SharedStateResult( + SharedStateStatus.SET, + Collections.singletonMap(IdentityConstants.SharedState.IdentityDirect.ECID, null) + ) + ); + when(mockIdentityState.updateLegacyExperienceCloudId(any())).thenReturn(false); + + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + extension.handleIdentityDirectECIDUpdate(event); - verify(mockExtensionApi, times(0)) - .setXDMSharedEventState(any(Map.class), any(Event.class), any(ExtensionErrorCallback.class)); + verify(mockExtensionApi) + .getSharedState( + IdentityConstants.SharedState.IdentityDirect.NAME, + event, + false, + SharedStateResolution.LAST_SET + ); + verify(mockIdentityState).updateLegacyExperienceCloudId(null); + verify(mockExtensionApi, never()).createXDMSharedState(any(), any()); } @Test - public void test_handleHubSharedState_doesNotShareStateIfLegacyECIDDoesNotChange() { - setIdentityDirectSharedState("1234"); - - Event event = new Event.Builder( - "Test event", + public void test_handleIdentityDirectECIDUpdate_identityDirectStateValidECID() { + final Event event = new Event.Builder( + "IdentityDirect State event", IdentityConstants.EventType.HUB, IdentityConstants.EventSource.SHARED_STATE ) @@ -470,14 +474,45 @@ public void test_handleHubSharedState_doesNotShareStateIfLegacyECIDDoesNotChange ) .build(); - // IdentityState.updateLegacyExperienceCloudId returns false if Legacy ECID was not updated - PowerMockito.stub(PowerMockito.method(IdentityState.class, "updateLegacyExperienceCloudId")).toReturn(false); + final ECID legacyEcid = new ECID(); - extension.handleHubSharedState(event); + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.IdentityDirect.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn( + new SharedStateResult( + SharedStateStatus.SET, + new HashMap() { + { + { + put(IdentityConstants.SharedState.IdentityDirect.ECID, legacyEcid.toString()); + } + } + } + ) + ); + when(mockIdentityState.updateLegacyExperienceCloudId(any())).thenReturn(true); + + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + when(mockIdentityState.getIdentityProperties()).thenReturn(new IdentityProperties()); + + extension.handleIdentityDirectECIDUpdate(event); - final ArgumentCaptor> sharedStateCaptor = ArgumentCaptor.forClass(Map.class); - verify(mockExtensionApi, times(0)) - .setXDMSharedEventState(sharedStateCaptor.capture(), eq(event), any(ExtensionErrorCallback.class)); + verify(mockExtensionApi) + .getSharedState( + IdentityConstants.SharedState.IdentityDirect.NAME, + event, + false, + SharedStateResolution.LAST_SET + ); + verify(mockIdentityState).updateLegacyExperienceCloudId(legacyEcid); + verify(mockExtensionApi) + .createXDMSharedState(mockIdentityState.getIdentityProperties().toXDMData(false), event); } // ======================================================================================== @@ -485,13 +520,7 @@ public void test_handleHubSharedState_doesNotShareStateIfLegacyECIDDoesNotChange // ======================================================================================== @Test - public void test_handleUrlVariablesRequest_nullEvent_shouldNotThrow() { - // test - extension.handleUrlVariablesRequest(null); - } - - @Test - public void test_handleUrlVariablesRequest_whenConfigAndECIDNotPresent_returnsNull() { + public void test_handleUrlVariablesRequest_whenOrgIdAndECIDNotPresent_returnsNull() { // setup Event event = new Event.Builder( "Test event", @@ -506,34 +535,42 @@ public void test_handleUrlVariablesRequest_whenConfigAndECIDNotPresent_returnsNu } ) .build(); + // Simulate null config state + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.Configuration.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn(null); + + final IdentityProperties properties = new IdentityProperties(); + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + final ArgumentCaptor responseEventCaptor = ArgumentCaptor.forClass(Event.class); // test extension.handleUrlVariablesRequest(event); - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchResponseEvent( - responseEventCaptor.capture(), - any(Event.class), - any(ExtensionErrorCallback.class) - ); + // verify that response event is dispatched + verify(mockExtensionApi).dispatch(responseEventCaptor.capture()); - Event urlVariablesResponseEvent = responseEventCaptor.getAllValues().get(0); - final Map data = urlVariablesResponseEvent.getEventData(); + // verify that the response event contains "urlvariables" property + final Event capturedResponseEvent = responseEventCaptor.getValue(); + final Map data = capturedResponseEvent.getEventData(); assertTrue(data.containsKey("urlvariables")); - String urlvariables = (String) data.get("urlvariables"); + // verify that the response event data has no values for "urlvariables" key + final String urlvariables = (String) data.get("urlvariables"); assertNull(urlvariables); } @Test - public void test_handleUrlVariablesRequest_whenOrgIdAndECIDPresent_returnsValidUrlVariablesString() { + public void test_handleUrlVariablesRequest_whenOrgIdPresentAndECIDNotPresent_returnsNull() { // setup - ECID testECID = new ECID(); - extension.state.getIdentityProperties().setECID(testECID); - setConfigurationSharedState("test-org-id@AdobeOrg"); - Event event = new Event.Builder( "Test event", IdentityConstants.EventType.EDGE_IDENTITY, @@ -547,38 +584,53 @@ public void test_handleUrlVariablesRequest_whenOrgIdAndECIDPresent_returnsValidU } ) .build(); + + // Simulate valid config state + final SharedStateResult configSharedStateResult = new SharedStateResult( + SharedStateStatus.SET, + Collections.singletonMap( + IdentityConstants.SharedState.Configuration.EXPERIENCE_CLOUD_ORGID, + "SomeOrgId@AdobeOrg" + ) + ); + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.Configuration.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn(configSharedStateResult); + + final IdentityProperties properties = new IdentityProperties(); // Simulate Absent ECID + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + final ArgumentCaptor responseEventCaptor = ArgumentCaptor.forClass(Event.class); // test extension.handleUrlVariablesRequest(event); - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchResponseEvent( - responseEventCaptor.capture(), - any(Event.class), - any(ExtensionErrorCallback.class) - ); + // verify that response event is dispatched + verify(mockExtensionApi).dispatch(responseEventCaptor.capture()); + final Event capturedResponseEvent = responseEventCaptor.getValue(); - Event urlVariablesResponseEvent = responseEventCaptor.getAllValues().get(0); - final Map data = urlVariablesResponseEvent.getEventData(); - String urlvariables = (String) data.get("urlvariables"); + // verify that the response event is sent to the incident event + assertEquals(event.getUniqueIdentifier(), capturedResponseEvent.getResponseID()); - String expectedUrlVariableTSString = "adobe_mc=TS%3"; - String expectedUrlVariableIdentifiersString = "%7CMCMID%3D" + testECID + "%7CMCORGID%3Dtest-org-id%40AdobeOrg"; + // verify that the response event contains "urlvariables" property + final Map data = capturedResponseEvent.getEventData(); + assertTrue(data.containsKey("urlvariables")); - assertNotNull(urlvariables); - assertTrue(urlvariables.contains("adobe_mc=")); - assertTrue(urlvariables.contains(expectedUrlVariableTSString)); - assertTrue(urlvariables.contains(expectedUrlVariableIdentifiersString)); + // verify that the response event data has no values for "urlvariables" key + final String urlvariables = (String) data.get("urlvariables"); + assertNull(urlvariables); } @Test - public void test_handleUrlVariablesRequest_whenOrgIdMissing_returnsValidNull() { + public void test_handleUrlVariablesRequest_whenOrgIdAndECIDPresent_returnsValidUrlVariables() { // setup - ECID testECID = new ECID(); - extension.state.getIdentityProperties().setECID(testECID); - Event event = new Event.Builder( "Test event", IdentityConstants.EventType.EDGE_IDENTITY, @@ -592,63 +644,55 @@ public void test_handleUrlVariablesRequest_whenOrgIdMissing_returnsValidNull() { } ) .build(); - final ArgumentCaptor responseEventCaptor = ArgumentCaptor.forClass(Event.class); - // test - extension.handleUrlVariablesRequest(event); - - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchResponseEvent( - responseEventCaptor.capture(), - any(Event.class), - any(ExtensionErrorCallback.class) + // Simulate valid config state + final SharedStateResult configSharedStateResult = new SharedStateResult( + SharedStateStatus.SET, + Collections.singletonMap( + IdentityConstants.SharedState.Configuration.EXPERIENCE_CLOUD_ORGID, + "SomeOrgId@AdobeOrg" + ) ); + when( + mockExtensionApi.getSharedState( + IdentityConstants.SharedState.Configuration.NAME, + event, + false, + SharedStateResolution.LAST_SET + ) + ) + .thenReturn(configSharedStateResult); - Event urlVariablesResponseEvent = responseEventCaptor.getAllValues().get(0); - final Map data = urlVariablesResponseEvent.getEventData(); - String urlvariables = (String) data.get("urlvariables"); + final IdentityProperties properties = new IdentityProperties(); + properties.setECID(new ECID()); + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); - assertNull(urlvariables); - } + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); - @Test - public void test_handleUrlVariablesRequest_whenECIDMissing_returnsValidNull() { - // setup - extension.state.getIdentityProperties().setECID(null); - setConfigurationSharedState("test-org-id@AdobeOrg"); + // test + extension.handleUrlVariablesRequest(event); - Event event = new Event.Builder( - "Test event", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .setEventData( - new HashMap() { - { - put("urlvariables", true); - } - } - ) - .build(); + // verify that response event is dispatched final ArgumentCaptor responseEventCaptor = ArgumentCaptor.forClass(Event.class); + verify(mockExtensionApi).dispatch(responseEventCaptor.capture()); + final Event capturedResponseEvent = responseEventCaptor.getValue(); - // test - extension.handleUrlVariablesRequest(event); + // verify that the response event is sent to the incident event + assertEquals(event.getUniqueIdentifier(), capturedResponseEvent.getResponseID()); - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchResponseEvent( - responseEventCaptor.capture(), - any(Event.class), - any(ExtensionErrorCallback.class) - ); + // verify that the response event contains "urlvariables" property + final Map data = capturedResponseEvent.getEventData(); + assertTrue(data.containsKey("urlvariables")); - Event urlVariablesResponseEvent = responseEventCaptor.getAllValues().get(0); - final Map data = urlVariablesResponseEvent.getEventData(); - String urlvariables = (String) data.get("urlvariables"); + final String urlvariables = (String) data.get("urlvariables"); + final String expectedUrlVariableTSString = "adobe_mc=TS%3"; + final String expectedUrlVariableIdentifiersString = + "%7CMCMID%3D" + properties.getECID() + "%7CMCORGID%3DSomeOrgId%40AdobeOrg"; - assertNull(urlvariables); + assertNotNull(urlvariables); + assertTrue(urlvariables.contains("adobe_mc=")); + assertTrue(urlvariables.contains(expectedUrlVariableTSString)); + assertTrue(urlvariables.contains(expectedUrlVariableIdentifiersString)); } // ======================================================================================== @@ -658,42 +702,91 @@ public void test_handleUrlVariablesRequest_whenECIDMissing_returnsValidNull() { @Test public void test_handleUpdateIdentities_whenValidData_updatesCustomerIdentifiers_updatesSharedState() { // setup - MockIdentityState mockIdentityState = new MockIdentityState(new IdentityProperties()); - extension.state = mockIdentityState; + final IdentityProperties properties = new IdentityProperties(); + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); + + // simulate an update to the identity properties + doAnswer(invocation -> { + final IdentityMap arg = (IdentityMap) invocation.getArgument(0); + properties.updateCustomerIdentifiers(arg); + return null; + }) + .when(mockIdentityState) + .updateCustomerIdentifiers(any()); + + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); // test - Map identityXDM = createXDMIdentityMap( + final Map identityXDM = createXDMIdentityMap( new TestItem("id1", "somevalue"), new TestItem("id2", "othervalue") ); - Event updateIdentityEvent = buildUpdateIdentityRequest(identityXDM); + final Event updateIdentityEvent = new Event.Builder( + "Update Identity Event", + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.UPDATE_IDENTITY + ) + .setEventData(identityXDM) + .build(); extension.handleUpdateIdentities(updateIdentityEvent); // verify identifiers updated - assertEquals(1, mockIdentityState.updateCustomerIdentifiersCalledTimes); - assertEquals(identityXDM, mockIdentityState.updateCustomerIdentifiersParams.get(0).asXDMMap()); + final ArgumentCaptor identityMapCaptor = ArgumentCaptor.forClass(IdentityMap.class); + verify(mockIdentityState).updateCustomerIdentifiers(identityMapCaptor.capture()); + assertEquals(identityXDM, identityMapCaptor.getValue().asXDMMap()); - // verify no event dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(0)); - MobileCore.dispatchEvent(any(Event.class), any(ExtensionErrorCallback.class)); + verify(mockExtensionApi).createXDMSharedState(properties.toXDMData(false), updateIdentityEvent); + verify(mockExtensionApi, never()).dispatch(any()); } @Test public void test_handleUpdateIdentities_nullEventData_returns() { // setup - MockIdentityState mockIdentityState = new MockIdentityState(new IdentityProperties()); - extension.state = mockIdentityState; + final IdentityProperties properties = new IdentityProperties(); + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); + + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); // test - Event updateIdentityEvent = buildUpdateIdentityRequest(null); + final Event updateIdentityEvent = new Event.Builder( + "Update Identity Event", + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.UPDATE_IDENTITY + ) // no event data + .build(); extension.handleUpdateIdentities(updateIdentityEvent); - // verify identifiers not updated - assertEquals(0, mockIdentityState.updateCustomerIdentifiersCalledTimes); + // verify that identifiers are not updated + verify(mockIdentityState, never()).updateCustomerIdentifiers(any()); + // verify that no shared state is created + verify(mockExtensionApi, never()).createXDMSharedState(any(), any()); + // verify that no event is dispatched + verify(mockExtensionApi, never()).dispatch(any()); + } - // verify shared state - verify(mockExtensionApi, times(0)) - .setXDMSharedEventState(any(Map.class), any(Event.class), any(ExtensionErrorCallback.class)); + @Test + public void test_handleUpdateIdentities_EmptyEventData_returns() { + // setup + final IdentityProperties properties = new IdentityProperties(); + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + + // test + final Event updateIdentityEvent = new Event.Builder( + "Update Identity Event", + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.UPDATE_IDENTITY + ) + .setEventData(new HashMap<>()) + .build(); + extension.handleUpdateIdentities(updateIdentityEvent); + + // verify that identifiers are not updated + verify(mockIdentityState, never()).updateCustomerIdentifiers(any()); + // verify that no shared state is created + verify(mockExtensionApi, never()).createXDMSharedState(any(), any()); + // verify that no event is dispatched + verify(mockExtensionApi, never()).dispatch(any()); } // ======================================================================================== @@ -706,126 +799,79 @@ public void test_handleRemoveIdentity_whenValidData_removesCustomerIdentifiers_u new TestItem("UserId", "secretID"), new TestItem("PushId", "token") ); - MockIdentityState mockIdentityState = new MockIdentityState(new IdentityProperties(identityXDM)); - extension.state = mockIdentityState; + final IdentityProperties properties = new IdentityProperties(identityXDM); + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); + doAnswer( + new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + final IdentityMap args = (IdentityMap) invocation.getArgument(0); + properties.removeCustomerIdentifiers(args); + return null; + } + } + ) + .when(mockIdentityState) + .removeCustomerIdentifiers(any()); + + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); // test - Map removedIdentityXDM = createXDMIdentityMap(new TestItem("UserId", "secretID")); - Event removeIdentityEvent = buildRemoveIdentityRequest(removedIdentityXDM); + final Map removedIdentityXDM = createXDMIdentityMap(new TestItem("UserId", "secretID")); + final Event removeIdentityEvent = buildRemoveIdentityRequest(removedIdentityXDM); extension.handleRemoveIdentity(removeIdentityEvent); // verify identifiers removed - assertEquals(1, mockIdentityState.removeCustomerIdentifiersCalledTimes); - assertEquals(removedIdentityXDM, mockIdentityState.removeCustomerIdentifiersParams.get(0).asXDMMap()); + final ArgumentCaptor removedIdentityMapCaptor = ArgumentCaptor.forClass(IdentityMap.class); + verify(mockIdentityState).removeCustomerIdentifiers(removedIdentityMapCaptor.capture()); + assertEquals( + IdentityMap.fromXDMMap(removedIdentityXDM).toString(), + removedIdentityMapCaptor.getValue().toString() + ); // verify shared state - final ArgumentCaptor sharedStateCaptor = ArgumentCaptor.forClass(Map.class); - verify(mockExtensionApi, times(1)) - .setXDMSharedEventState( - sharedStateCaptor.capture(), - eq(removeIdentityEvent), - any(ExtensionErrorCallback.class) - ); - - // verify no event dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(0)); - MobileCore.dispatchEvent(any(Event.class), any(ExtensionErrorCallback.class)); + final Map expectedState = properties.toXDMData(false); + final ArgumentCaptor> stateCaptor = ArgumentCaptor.forClass(Map.class); + verify(mockExtensionApi).createXDMSharedState(stateCaptor.capture(), eq(removeIdentityEvent)); + assertEquals(expectedState, stateCaptor.getValue()); } @Test public void test_handleRemoveIdentity_whenNullData_returns() { // setup - Map identityXDM = createXDMIdentityMap(new TestItem("PushId", "token")); - MockIdentityState mockIdentityState = new MockIdentityState(new IdentityProperties(identityXDM)); - extension.state = mockIdentityState; + Map identityXDM = createXDMIdentityMap( + new TestItem("UserId", "secretID"), + new TestItem("PushId", "token") + ); + final IdentityProperties properties = new IdentityProperties(identityXDM); + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); // test - Event removeIdentityEvent = buildRemoveIdentityRequest(null); + final Event removeIdentityEvent = buildRemoveIdentityRequest(null); extension.handleRemoveIdentity(removeIdentityEvent); // verify identifiers not removed - assertEquals(0, mockIdentityState.removeCustomerIdentifiersCalledTimes); - - // verify shared state - verify(mockExtensionApi, times(0)) - .setXDMSharedEventState(any(Map.class), eq(removeIdentityEvent), any(ExtensionErrorCallback.class)); - } - - @Test - public void test_processCachedEvents_returnsWhenNotBooted() { - Map identityXDM = createXDMIdentityMap(new TestItem("space", "moon")); - MockIdentityState mockIdentityState = new MockIdentityState(new IdentityProperties(identityXDM)); - extension.state = mockIdentityState; - - // test - extension.processAddEvent(buildUpdateIdentityRequest(identityXDM)); - extension.processAddEvent(buildUpdateIdentityRequest(identityXDM)); + verify(mockIdentityState, never()).removeCustomerIdentifiers(any()); - // verify - verify(mockExtensionApi, times(0)) - .setXDMSharedEventState(any(Map.class), any(Event.class), any(ExtensionErrorCallback.class)); + // verify shared state is never created + verify(mockExtensionApi, never()).createXDMSharedState(any(), any()); } @Test - public void test_processAddEvent_nullEvent_returns() { - Map identityXDM = createXDMIdentityMap(new TestItem("space", "moon")); - MockIdentityState mockIdentityState = new MockIdentityState(new IdentityProperties(identityXDM)); - extension.state = mockIdentityState; - mockIdentityState.hasBooted = true; + public void test_handleRemoveIdentity_eventWithEmptyData_returns() { + // setup + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); // test - extension.processAddEvent(null); + final Event notARemoveIdentityEvent = buildRemoveIdentityRequest(Collections.EMPTY_MAP); + extension.handleRemoveIdentity(notARemoveIdentityEvent); - // verify - verify(mockExtensionApi, times(0)) - .setXDMSharedEventState(any(Map.class), any(Event.class), any(ExtensionErrorCallback.class)); - } - - @Test - public void test_processCachedEvents_processesWhenBooted() { - Map identityXDM = createXDMIdentityMap(new TestItem("space", "moon")); - MockIdentityState mockIdentityState = new MockIdentityState(new IdentityProperties(identityXDM)); - mockIdentityState.hasBooted = true; - extension.state = mockIdentityState; - - // test - extension.processAddEvent(buildUpdateIdentityRequest(identityXDM)); - extension.processAddEvent(buildRemoveIdentityRequest(identityXDM)); - extension.processAddEvent( - new Event.Builder( - "Test event", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .setEventData( - new HashMap() { - { - put("urlVariables", true); - } - } - ) - .build() - ); - extension.processAddEvent( - new Event.Builder( - "Test event", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .build() - ); - extension.processAddEvent( - new Event.Builder( - "Test event", - IdentityConstants.EventType.GENERIC_IDENTITY, - IdentityConstants.EventSource.REQUEST_RESET - ) - .build() - ); + // verify identifiers not removed + verify(mockIdentityState, never()).removeCustomerIdentifiers(any()); - // verify - verify(mockExtensionApi, times(3)) - .setXDMSharedEventState(any(Map.class), any(Event.class), any(ExtensionErrorCallback.class)); // request identity does not update shared state + // verify shared state is never created + verify(mockExtensionApi, never()).createXDMSharedState(any(), any()); } // ======================================================================================== @@ -833,7 +879,7 @@ public void test_processCachedEvents_processesWhenBooted() { // ======================================================================================== @Test - public void test_handleRequestContent_processesWhenBooted() { + public void test_handleRequestContent() { // Setup final Event event = new Event.Builder( "Test Ad ID event", @@ -849,77 +895,60 @@ public void test_handleRequestContent_processesWhenBooted() { ) .build(); - final ArgumentCaptor sharedStateCaptor = ArgumentCaptor.forClass(Map.class); - final ArgumentCaptor consentEventCaptor = ArgumentCaptor.forClass(Event.class); + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); // Test extension.handleRequestContent(event); - // Verify - consent event should be dispatched - verify(mockExtensionApi, times(1)) - .setXDMSharedEventState(sharedStateCaptor.capture(), eq(event), any(ExtensionErrorCallback.class)); - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEvent(consentEventCaptor.capture(), any(ExtensionErrorCallback.class)); - - // Verify shared state - Map sharedState = flattenMap(sharedStateCaptor.getValue()); - assertTrue(sharedState.get("identityMap.GAID[0].id").length() > 0); - assertEquals("adId", sharedState.get("identityMap.GAID[0].id")); - assertEquals("ambiguous", sharedState.get("identityMap.GAID[0].authenticatedState")); - assertEquals("false", sharedState.get("identityMap.GAID[0].primary")); - - // Verify consent event - Event consentEvent = consentEventCaptor.getAllValues().get(0); - Map consentEventData = flattenMap(consentEvent.getEventData()); - assertEquals("GAID", consentEventData.get("consents.adID.idType")); - assertEquals("y", consentEventData.get("consents.adID.val")); + verify(mockIdentityState).updateAdvertisingIdentifier(eq(event), any(SharedStateCallback.class)); } - // ======================================================================================== - // private helper methods - // ======================================================================================== - - private void setupExistingIdentityProps(final ECID ecid) { - IdentityProperties persistedProps = new IdentityProperties(); - persistedProps.setECID(ecid); - final JSONObject jsonObject = new JSONObject(persistedProps.toXDMData(false)); - final String propsJSON = jsonObject.toString(); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, null)) - .thenReturn(propsJSON); - } - - private void setIdentityDirectSharedState(final String ecid) { - when( - mockExtensionApi.getSharedEventState( - eq(IdentityConstants.SharedState.IdentityDirect.NAME), - any(Event.class), - any(ExtensionErrorCallback.class) - ) + @Test + public void test_handleRequestContent_EventIsNotAdIdEvent() { + // Setup + final Event event = new Event.Builder( + "Not an Ad ID event", + IdentityConstants.EventType.GENERIC_IDENTITY, + IdentityConstants.EventSource.REQUEST_CONTENT ) - .thenReturn( + .setEventData( new HashMap() { { - put(IdentityConstants.SharedState.IdentityDirect.ECID, ecid); + put(IdentityConstants.EventDataKeys.URL_VARIABLES, "adId"); } } - ); + ) + .build(); + + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + + // Test + extension.handleRequestContent(event); + + verify(mockIdentityState, never()).updateAdvertisingIdentifier(eq(event), any(SharedStateCallback.class)); } - private void setConfigurationSharedState(final String orgId) { - when( - mockExtensionApi.getSharedEventState( - eq("com.adobe.module.configuration"), - any(Event.class), - any(ExtensionErrorCallback.class) - ) + // ======================================================================================== + // handleRequestReset + // ======================================================================================== + + @Test + public void test_handleRequestReset() { + final IdentityProperties properties = new IdentityProperties(); + when(mockIdentityState.getIdentityProperties()).thenReturn(properties); + + extension = new IdentityExtension(mockExtensionApi, mockIdentityState); + + Event resetEvent = new Event.Builder( + "Test event", + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.REQUEST_IDENTITY ) - .thenReturn( - new HashMap() { - { - put("experienceCloud.org", orgId); - } - } - ); + .build(); + + extension.handleRequestReset(resetEvent); + + verify(mockIdentityState).resetIdentifiers(); + verify(mockExtensionApi).createXDMSharedState(properties.toXDMData(false), resetEvent); // will fail because of new ecid } } diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityMapTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityMapTests.java index 0f4efa24..331f48ad 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityMapTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityMapTests.java @@ -15,6 +15,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import com.adobe.marketing.mobile.util.JSONUtils; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -294,7 +295,7 @@ public void test_FromData() throws Exception { "}"; final JSONObject jsonObject = new JSONObject(jsonStr); - final Map xdmData = Utils.toMap(jsonObject); + final Map xdmData = JSONUtils.toMap(jsonObject); // test IdentityMap map = IdentityMap.fromXDMMap(xdmData); @@ -331,7 +332,7 @@ public void testFromXDMMap_InvalidNamespace() throws Exception { "}"; final JSONObject jsonObject = new JSONObject(invalidJsonStr); - final Map xdmData = Utils.toMap(jsonObject); + final Map xdmData = JSONUtils.toMap(jsonObject); // test IdentityMap map = IdentityMap.fromXDMMap(xdmData); @@ -359,7 +360,7 @@ public void testFromXDMMap_InvalidItemForNamespace() throws Exception { "}"; final JSONObject jsonObject = new JSONObject(invalidJsonStr); - final Map xdmData = Utils.toMap(jsonObject); + final Map xdmData = JSONUtils.toMap(jsonObject); // test IdentityMap map = IdentityMap.fromXDMMap(xdmData); @@ -376,7 +377,7 @@ public void testFromXDMMap_InvalidIdentityMap() throws Exception { final String invalidJsonStr = "{\"identityMap\": [\"not a map\"]}"; final JSONObject jsonObject = new JSONObject(invalidJsonStr); - final Map xdmData = Utils.toMap(jsonObject); + final Map xdmData = JSONUtils.toMap(jsonObject); // test IdentityMap map = IdentityMap.fromXDMMap(xdmData); diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityPropertiesTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityPropertiesTests.java index 7302a471..68339f26 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityPropertiesTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityPropertiesTests.java @@ -334,12 +334,162 @@ public void test_getsetAdId_whenEmpty_thenNull() { // Verify assertNull(advertisingIdentifier); } + // ====================================================================================================================== - // Tests for "updateCustomerIdentifiers" is already covered in "handleUpdateRequest" tests in IdentityExtensionTests + // Tests for updateCustomerIdentifiers() // ====================================================================================================================== + @Test + public void test_updateCustomerIdentifiers_validProperties() { + // Setup + IdentityProperties props = new IdentityProperties(); + props.setECID(new ECID("internalECID")); + + // Test + final Map customerIdentifierUpdate = createXDMIdentityMap( + new IdentityTestUtil.TestItem("UserId", "somevalue") + ); + props.updateCustomerIdentifiers(IdentityMap.fromXDMMap(customerIdentifierUpdate)); + + // Verify + final Map expectedProperties = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "internalECID"), + new IdentityTestUtil.TestItem("UserId", "somevalue") + ); + assertEquals(expectedProperties, props.toXDMData(false)); + } + + @Test + public void test_updateCustomerIdentifiers_doesNotUpdateReservedNamespace() { + // Setup + IdentityProperties props = new IdentityProperties(); + props.setECID(new ECID("internalECID")); + + // Test + final Map customerIdentifierUpdate = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "somevalue"), + new IdentityTestUtil.TestItem("GAID", "somevalue"), + new IdentityTestUtil.TestItem("IDFA", "somevalue"), + new IdentityTestUtil.TestItem("IdFA", "somevalue"), + new IdentityTestUtil.TestItem("gaid", "somevalue"), + new IdentityTestUtil.TestItem("UserId", "somevalue") + ); + props.updateCustomerIdentifiers(IdentityMap.fromXDMMap(customerIdentifierUpdate)); + + // Verify + final Map expectedProperties = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "internalECID"), + new IdentityTestUtil.TestItem("UserId", "somevalue") + ); + assertEquals(expectedProperties, props.toXDMData(false)); + } + + @Test + public void test_updateCustomerIdentifiers_storesAllIdentifiersCaseSensitively() { + // Setup + IdentityProperties props = new IdentityProperties(); + props.setECID(new ECID("internalECID")); + + // Test + final Map customerIdentifierUpdate = createXDMIdentityMap( + new IdentityTestUtil.TestItem("caseSensitive", "somevalue"), + new IdentityTestUtil.TestItem("CASESENSITIVE", "SOMEVALUE") + ); + props.updateCustomerIdentifiers(IdentityMap.fromXDMMap(customerIdentifierUpdate)); + + // Verify + final Map expectedProperties = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "internalECID"), + new IdentityTestUtil.TestItem("caseSensitive", "somevalue"), + new IdentityTestUtil.TestItem("CASESENSITIVE", "SOMEVALUE") + ); + assertEquals(expectedProperties, props.toXDMData(false)); + } + // ====================================================================================================================== - // Tests for "removeCustomerIdentifiers" is already covered in handleRemoveRequest tests in IdentityExtensionTests + // Tests for removeCustomerIdentifiers() // ====================================================================================================================== + @Test + public void test_removeCustomerIdentifiers_removesIdentifiers() { + // Setup + IdentityProperties props = new IdentityProperties(); + props.setECID(new ECID("internalECID")); + final Map customerIdentifierUpdate = createXDMIdentityMap( + new IdentityTestUtil.TestItem("UserId", "secretID"), + new IdentityTestUtil.TestItem("PushId", "token") + ); + props.updateCustomerIdentifiers(IdentityMap.fromXDMMap(customerIdentifierUpdate)); + + // test + final Map removedIdentityXDM = createXDMIdentityMap( + new IdentityTestUtil.TestItem("UserId", "secretID") + ); + props.removeCustomerIdentifiers(IdentityMap.fromXDMMap(removedIdentityXDM)); + + // Verify + final Map expectedProperties = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "internalECID"), + new IdentityTestUtil.TestItem("PushId", "token") + ); + assertEquals(expectedProperties, props.toXDMData(false)); + } + + @Test + public void test_removeCustomerIdentifiers_doesNotRemoveReservedNamespaces() { + // Setup + IdentityProperties props = new IdentityProperties(); + final ECID initialECID = new ECID(); + props.setECID(initialECID); + props.setAdId("initialADID"); + + // test + final Map removedIdentityXDM = createXDMIdentityMap( + new IdentityTestUtil.TestItem("GAID", "initialECID"), + new IdentityTestUtil.TestItem("ECID", initialECID.toString()) + ); + props.removeCustomerIdentifiers(IdentityMap.fromXDMMap(removedIdentityXDM)); + + // Verify + IdentityProperties expectedProperties = new IdentityProperties(); + expectedProperties.setECID(initialECID); + expectedProperties.setAdId("initialADID"); + + assertEquals(expectedProperties.toXDMData(false), props.toXDMData(false)); + } + + @Test + public void test_removeCustomerIdentifiers_removesCaseSensitively() { + // Setup + IdentityProperties props = new IdentityProperties(); + props.setECID(new ECID("internalECID")); + final Map customerIdentifierUpdate = createXDMIdentityMap( + new IdentityTestUtil.TestItem("caseSensitive", "somevalue"), + new IdentityTestUtil.TestItem("CASESENSITIVE", "SOMEVALUE") + ); + props.updateCustomerIdentifiers(IdentityMap.fromXDMMap(customerIdentifierUpdate)); + + // check that initial contents are expected + final Map expectedProperties = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "internalECID"), + new IdentityTestUtil.TestItem("caseSensitive", "somevalue"), + new IdentityTestUtil.TestItem("CASESENSITIVE", "SOMEVALUE") + ); + assertEquals(expectedProperties, props.toXDMData(false)); + + // test + final Map removedIdentityXDM = createXDMIdentityMap( + new IdentityTestUtil.TestItem("caseSensitive", "somevalue") + ); + + props.removeCustomerIdentifiers(IdentityMap.fromXDMMap(removedIdentityXDM)); + + // verify + final Map expectedIdentityXDM = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "internalECID"), + new IdentityTestUtil.TestItem("CASESENSITIVE", "SOMEVALUE") + ); + + assertEquals(expectedIdentityXDM, props.toXDMData(false)); + } } diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java index 2e39d3df..59d19029 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java @@ -12,7 +12,6 @@ package com.adobe.marketing.mobile.edge.identity; import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.createXDMIdentityMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.flattenJSONString; import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.flattenMap; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -21,223 +20,230 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -import android.app.Application; -import android.content.Context; -import android.content.SharedPreferences; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionErrorCallback; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.SharedStateResult; +import com.adobe.marketing.mobile.SharedStateStatus; +import com.adobe.marketing.mobile.services.DataStoring; +import com.adobe.marketing.mobile.services.NamedCollection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.json.JSONObject; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.MockitoAnnotations; -@RunWith(PowerMockRunner.class) -@PrepareForTest({ MobileCore.class }) public class IdentityStateTests { @Mock - Application mockApplication; + private DataStoring mockDataStoreService; @Mock - Context mockContext; + private NamedCollection mockEdgeIdentityNamedCollection; @Mock - SharedPreferences mockSharedPreference; + private NamedCollection mockDirectIdentityNamedCollection; @Mock - SharedPreferences.Editor mockSharedPreferenceEditor; + private IdentityStorageManager mockIdentityStorageManager; + @Mock private SharedStateCallback mockSharedStateCallback; - private Map hubSharedState; - private Map identityDirectSharedState; - private int setXDMSharedEventStateCalledTimes; @Before public void before() throws Exception { - PowerMockito.mockStatic(MobileCore.class); - - Mockito.when(MobileCore.getApplication()).thenReturn(mockApplication); - Mockito.when(mockApplication.getApplicationContext()).thenReturn(mockContext); - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito.when(mockSharedPreference.edit()).thenReturn(mockSharedPreferenceEditor); - - setXDMSharedEventStateCalledTimes = 0; - mockSharedStateCallback = - new SharedStateCallback() { - @Override - public Map getSharedState(final String stateOwner, final Event event) { - if (IdentityConstants.SharedState.Hub.NAME.equals(stateOwner)) { - return hubSharedState; - } else if (IdentityConstants.SharedState.IdentityDirect.NAME.equals(stateOwner)) { - return identityDirectSharedState; - } + MockitoAnnotations.openMocks(this); - return null; - } - - @Override - public boolean setXDMSharedEventState(Map state, Event event) { - setXDMSharedEventStateCalledTimes++; - return true; - } - }; + when(mockDataStoreService.getNamedCollection(IdentityConstants.DataStoreKey.DATASTORE_NAME)) + .thenReturn(mockEdgeIdentityNamedCollection); + when(mockDataStoreService.getNamedCollection(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME)) + .thenReturn(mockDirectIdentityNamedCollection); } @Test - public void testHasBooted() { - IdentityState state = new IdentityState(new IdentityProperties()); + public void testBootUpIfReady_persistedECIDIsReused() { + final IdentityProperties persistedProperties = new IdentityProperties(); + final ECID persistedECID = new ECID(); + persistedProperties.setECID(persistedECID); - // test - assertFalse(state.hasBooted()); + when(mockIdentityStorageManager.loadPropertiesFromPersistence()).thenReturn(persistedProperties); + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); - state.bootupIfReady(mockSharedStateCallback); - assertTrue(state.hasBooted()); + assertTrue(identityState.bootupIfReady(mockSharedStateCallback)); + assertEquals(persistedProperties.getECID(), identityState.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager, never()).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback) + .createXDMSharedState(identityState.getIdentityProperties().toXDMData(false), null); } @Test - public void testBootupIfReady_GeneratesECID() { - // setup - IdentityState state = new IdentityState(new IdentityProperties()); - assertNull(state.getIdentityProperties().getECID()); + public void testBootUpIfReady_waitsForHubSharedState_hubStateIsNull() { + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)).thenReturn(null); - // test - state.bootupIfReady(mockSharedStateCallback); - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); // saves to data store - - // verify - assertNotNull(state.getIdentityProperties().getECID()); - assertEquals(1, setXDMSharedEventStateCalledTimes); + assertFalse(identityState.bootupIfReady(mockSharedStateCallback)); } @Test - public void testBootupIfReady_LoadsDirectIdentityECID() { - // setup - ECID ecid = new ECID(); - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) - .thenReturn(ecid.toString()); - - IdentityState state = new IdentityState(new IdentityProperties()); - assertNull(state.getIdentityProperties().getECID()); + public void testBootUpIfReady_waitsForHubSharedState_hubStateIsPending() { + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.PENDING, Collections.EMPTY_MAP)); - // test - state.bootupIfReady(mockSharedStateCallback); - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); // saves to data store - - // verify - assertEquals(ecid, state.getIdentityProperties().getECID()); - assertEquals(1, setXDMSharedEventStateCalledTimes); + assertFalse(identityState.bootupIfReady(mockSharedStateCallback)); } @Test - public void testBootupIfReady_GeneratesECIDWhenDirectECIDIsNullInPersistence() { - // setup - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) - .thenReturn(null); - - IdentityState state = new IdentityState(new IdentityProperties()); - assertNull(state.getIdentityProperties().getECID()); + public void testBootUpIfReady_waitsForHubSharedState_hubStateIsSet() { + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, Collections.EMPTY_MAP)); - // test - state.bootupIfReady(mockSharedStateCallback); - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); // saves to data store - - // verify - assertNotNull(state.getIdentityProperties().getECID()); - assertEquals(1, setXDMSharedEventStateCalledTimes); + assertTrue(identityState.bootupIfReady(mockSharedStateCallback)); + assertNotNull(identityState.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback) + .createXDMSharedState(identityState.getIdentityProperties().toXDMData(false), null); } @Test - public void testBootupIfReady_LoadsFromPersistence() { - // setup - IdentityState state = new IdentityState(new IdentityProperties()); - - IdentityProperties persistedProps = new IdentityProperties(); - persistedProps.setECID(new ECID()); - final JSONObject jsonObject = new JSONObject(persistedProps.toXDMData(false)); - final String propsJSON = jsonObject.toString(); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, null)) - .thenReturn(propsJSON); - - // test - state.bootupIfReady(mockSharedStateCallback); - verify(mockSharedPreferenceEditor, never()).apply(); + public void testBootUpIfReady_reUsesIdentityDirectEcidWhenAvailableAndNoPersistedECIDExists() { + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + final Map hubSharedState = new HashMap<>(); + hubSharedState.put( + "extensions", + new HashMap() { + { + put( + "com.adobe.module.identity", + new HashMap() { + { + put("friendlyName", "Identity"); + put("version", "2.0.0"); + } + } + ); + } + } + ); - // verify - assertEquals(persistedProps.getECID().toString(), state.getIdentityProperties().getECID().toString()); - assertEquals(1, setXDMSharedEventStateCalledTimes); - } + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, hubSharedState)); + final ECID fetchedDirectIdentityECID = new ECID(); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.IdentityDirect.NAME, null)) + .thenReturn( + new SharedStateResult( + SharedStateStatus.SET, + Collections.singletonMap( + IdentityConstants.SharedState.IdentityDirect.ECID, + fetchedDirectIdentityECID.toString() + ) + ) + ); + + assertTrue(identityState.bootupIfReady(mockSharedStateCallback)); + assertNotNull(identityState.getIdentityProperties().getECID()); + assertEquals(fetchedDirectIdentityECID, identityState.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback) + .createXDMSharedState(identityState.getIdentityProperties().toXDMData(false), null); + } + + @Test + public void testBootUpIfReady_prefersPersistedIdentityDirectEcidOverFetchingFromState() { + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + + final ECID persistedDirectIdentityECID = new ECID(); + when(mockIdentityStorageManager.loadEcidFromDirectIdentityPersistence()) + .thenReturn(persistedDirectIdentityECID); + + final Map hubSharedState = new HashMap<>(); + hubSharedState.put( + "extensions", + new HashMap() { + { + put( + "com.adobe.module.identity", + new HashMap() { + { + put("friendlyName", "Identity"); + put("version", "2.0.0"); + } + } + ); + } + } + ); - @Test - public void testBootupIfReady_IfReadyLoadsFromPersistenceWhenDirectECIDIsValid() { - // setup - ECID ecid = new ECID(); - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) - .thenReturn(ecid.toString()); - - IdentityState state = new IdentityState(new IdentityProperties()); - - IdentityProperties persistedProps = new IdentityProperties(); - persistedProps.setECID(new ECID()); - final JSONObject jsonObject = new JSONObject(persistedProps.toXDMData(false)); - final String propsJSON = jsonObject.toString(); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, null)) - .thenReturn(propsJSON); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, hubSharedState)); + final ECID fetchedIdentityDirectECID = new ECID(); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.IdentityDirect.NAME, null)) + .thenReturn( + new SharedStateResult( + SharedStateStatus.SET, + Collections.singletonMap( + IdentityConstants.SharedState.IdentityDirect.ECID, + fetchedIdentityDirectECID.toString() // not the same persisted Identity ECID for the sake of tests + ) + ) + ); + + assertTrue(identityState.bootupIfReady(mockSharedStateCallback)); + assertNotNull(identityState.getIdentityProperties().getECID()); + assertEquals(persistedDirectIdentityECID, identityState.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback) + .createXDMSharedState(identityState.getIdentityProperties().toXDMData(false), null); + } + + @Test + public void testBootUpIfReady_waitsForIdentityDirectStateIfRegistered_stateIsNone() { + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + final Map hubSharedState = new HashMap<>(); + hubSharedState.put( + "extensions", + new HashMap() { + { + put( + "com.adobe.module.identity", + new HashMap() { + { + put("friendlyName", "Identity"); + put("version", "2.0.0"); + } + } + ); + } + } + ); - // test - state.bootupIfReady(mockSharedStateCallback); - verify(mockSharedPreferenceEditor, never()).apply(); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, hubSharedState)); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.IdentityDirect.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.NONE, null)); - // verify - assertEquals(persistedProps.getECID(), state.getIdentityProperties().getECID()); - assertEquals(1, setXDMSharedEventStateCalledTimes); + assertFalse(identityState.bootupIfReady(mockSharedStateCallback)); + assertNull(identityState.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager, never()).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback, times(0)).createXDMSharedState(any(), any()); } @Test - public void testBootupIfReady_whenIdentityDirectRegistered_onFirstBoot_waitsForIdentityDirectECID() { - // setup - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) - .thenReturn(null); - - IdentityState state = new IdentityState(new IdentityProperties()); - - // test - hubSharedState = new HashMap<>(); + public void testBootUpIfReady_waitsForIdentityDirectStateIfRegistered_stateIsPending() { + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + final Map hubSharedState = new HashMap<>(); hubSharedState.put( "extensions", new HashMap() { @@ -247,36 +253,29 @@ public void testBootupIfReady_whenIdentityDirectRegistered_onFirstBoot_waitsForI new HashMap() { { put("friendlyName", "Identity"); - put("version", "1.2.2"); + put("version", "2.0.0"); } } ); } } ); - state.bootupIfReady(mockSharedStateCallback); - verify(mockSharedPreferenceEditor, never()).apply(); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, hubSharedState)); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.IdentityDirect.NAME, null)) + .thenReturn(null); - // verify - assertNull(state.getIdentityProperties().getECID()); - assertEquals(0, setXDMSharedEventStateCalledTimes); + assertFalse(identityState.bootupIfReady(mockSharedStateCallback)); + assertNull(identityState.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager, never()).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback, times(0)).createXDMSharedState(any(), any()); } @Test - public void testBootupIfReady_whenIdentityDirectRegistered_onFirstBoot_usesIdentityDirectECID() { - // setup - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) - .thenReturn(null); - - IdentityState state = new IdentityState(new IdentityProperties()); - - // test - hubSharedState = new HashMap<>(); + public void testBootUpIfReady_waitsForPendingIdentityDirectStateIfRegistered_stateIsNull() { + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + final Map hubSharedState = new HashMap<>(); hubSharedState.put( "extensions", new HashMap() { @@ -286,38 +285,29 @@ public void testBootupIfReady_whenIdentityDirectRegistered_onFirstBoot_usesIdent new HashMap() { { put("friendlyName", "Identity"); - put("version", "1.2.2"); + put("version", "2.0.0"); } } ); } } ); - identityDirectSharedState = new HashMap<>(); - identityDirectSharedState.put("mid", "1234"); - state.bootupIfReady(mockSharedStateCallback); - // verify - assertEquals("1234", state.getIdentityProperties().getECID().toString()); // ECID from Identity direct - assertNull(state.getIdentityProperties().getECIDSecondary()); // should be null - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); - assertEquals(1, setXDMSharedEventStateCalledTimes); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, hubSharedState)); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.IdentityDirect.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.PENDING, null)); + + assertFalse(identityState.bootupIfReady(mockSharedStateCallback)); + assertNull(identityState.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager, never()).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback, times(0)).createXDMSharedState(any(), any()); } @Test - public void testBootupIfReady_whenIdentityDirectRegistered_onFirstBoot_whenIdentityDirectECIDNull_generatesNew() { - // setup - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) - .thenReturn(null); - - IdentityState state = new IdentityState(new IdentityProperties()); - - // test - hubSharedState = new HashMap<>(); + public void testBootUpIfReady_regeneratesECIDWhenIdentityDirectStateECIDIsNull() { + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + final Map hubSharedState = new HashMap<>(); hubSharedState.put( "extensions", new HashMap() { @@ -327,21 +317,73 @@ public void testBootupIfReady_whenIdentityDirectRegistered_onFirstBoot_whenIdent new HashMap() { { put("friendlyName", "Identity"); - put("version", "1.2.2"); + put("version", "2.0.0"); } } ); } } ); - identityDirectSharedState = new HashMap<>(); // no mid key - state.bootupIfReady(mockSharedStateCallback); - // verify - assertNotNull("1234", state.getIdentityProperties().getECID()); // new ECID generated - assertNull(state.getIdentityProperties().getECIDSecondary()); // should be null - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); - assertEquals(1, setXDMSharedEventStateCalledTimes); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, hubSharedState)); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.IdentityDirect.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, null)); + + assertTrue(identityState.bootupIfReady(mockSharedStateCallback)); + assertNotNull(identityState.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback) + .createXDMSharedState(identityState.getIdentityProperties().toXDMData(false), null); + } + + @Test + public void testBootUpIfReady_generatesNewECIDWhenDirectStateAndPersistedStateUnavailable() { + // No persisted properties + final IdentityProperties persistedProperties = new IdentityProperties(); + when(mockIdentityStorageManager.loadPropertiesFromPersistence()).thenReturn(persistedProperties); + + // No Identity direct extensions + final Map hubSharedState = new HashMap<>(); + hubSharedState.put("extensions", new HashMap()); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, hubSharedState)); + + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + + assertTrue(identityState.bootupIfReady(mockSharedStateCallback)); + assertNotNull(identityState.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback) + .createXDMSharedState(identityState.getIdentityProperties().toXDMData(false), null); + } + + @Test + public void testBootUpIfReady_doesNotBootMoreThanOnce() { + // Simulate generating a new ECID and booting + // No persisted properties + final IdentityProperties persistedProperties = new IdentityProperties(); + when(mockIdentityStorageManager.loadPropertiesFromPersistence()).thenReturn(persistedProperties); + + // No Identity direct extensions + final Map hubSharedState = new HashMap<>(); + hubSharedState.put("extensions", new HashMap()); + when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) + .thenReturn(new SharedStateResult(SharedStateStatus.SET, hubSharedState)); + + final IdentityState identityState = new IdentityState(mockIdentityStorageManager); + + // Verify that extension has booted + assertTrue(identityState.bootupIfReady(mockSharedStateCallback)); + + // Try calling boot up if ready once more + assertTrue(identityState.bootupIfReady(mockSharedStateCallback)); + + assertNotNull(identityState.getIdentityProperties().getECID()); + // verify that properties are set and saved only once + verify(mockIdentityStorageManager, times(1)).savePropertiesToPersistence(identityState.getIdentityProperties()); + verify(mockSharedStateCallback, times(1)) + .createXDMSharedState(identityState.getIdentityProperties().toXDMData(false), null); } // ====================================================================================================================== @@ -351,11 +393,11 @@ public void testBootupIfReady_whenIdentityDirectRegistered_onFirstBoot_whenIdent @Test public void testResetIdentifiers() { // setup - IdentityState state = new IdentityState(new IdentityProperties()); + final IdentityState state = new IdentityState(mockIdentityStorageManager); state.getIdentityProperties().setECID(new ECID()); state.getIdentityProperties().setECIDSecondary(new ECID()); state.getIdentityProperties().setAdId("adID"); - ECID existingEcid = state.getIdentityProperties().getECID(); + final ECID existingEcid = state.getIdentityProperties().getECID(); // test state.resetIdentifiers(); @@ -365,11 +407,11 @@ public void testResetIdentifiers() { assertFalse(state.getIdentityProperties().getECID().toString().isEmpty()); // ECID should not be empty assertNull(state.getIdentityProperties().getECIDSecondary()); // should be cleared assertNull(state.getIdentityProperties().getAdId()); // should be cleared - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); // should save to data store - + verify(mockIdentityStorageManager, times(1)).savePropertiesToPersistence(state.getIdentityProperties()); // should save to data store // Verify consent event not sent (or any event). Consent should not be dispatched by resetIdentifiers - PowerMockito.verifyStatic(MobileCore.class, Mockito.never()); - MobileCore.dispatchEvent(any(Event.class), any(ExtensionErrorCallback.class)); + + // PowerMockito.verifyStatic(MobileCore.class, Mockito.never()); + // MobileCore.dispatchEvent(any(Event.class), any(ExtensionErrorCallback.class)); } // ====================================================================================================================== @@ -379,32 +421,31 @@ public void testResetIdentifiers() { @Test public void testUpdateCustomerIdentifiers_happy() throws Exception { // setup - IdentityProperties properties = new IdentityProperties(); - IdentityState state = new IdentityState(properties); + final IdentityState state = new IdentityState(mockIdentityStorageManager); // test - Map identityXDM = createXDMIdentityMap(new IdentityTestUtil.TestItem("UserId", "secretID")); + final Map identityXDM = createXDMIdentityMap( + new IdentityTestUtil.TestItem("UserId", "secretID") + ); state.updateCustomerIdentifiers(IdentityMap.fromXDMMap(identityXDM)); // verify persistence - final ArgumentCaptor persistenceValueCaptor = ArgumentCaptor.forClass(String.class); - verify(mockSharedPreferenceEditor, times(1)) - .putString(eq(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES), persistenceValueCaptor.capture()); - Map persistedData = flattenJSONString(persistenceValueCaptor.getAllValues().get(0)); - assertEquals("secretID", persistedData.get("identityMap.UserId[0].id")); - assertEquals("ambiguous", persistedData.get("identityMap.UserId[0].authenticatedState")); - assertEquals("false", persistedData.get("identityMap.UserId[0].primary")); + final ArgumentCaptor identityPropertiesArgumentCaptor = ArgumentCaptor.forClass( + IdentityProperties.class + ); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityPropertiesArgumentCaptor.capture()); + final IdentityProperties capturedIdentityProperties = identityPropertiesArgumentCaptor.getValue(); + assertEquals(identityXDM, capturedIdentityProperties.toXDMData(false)); } @Test public void testUpdateCustomerIdentifiers_doesNotUpdateReservedNamespace() throws Exception { // setup - IdentityProperties properties = new IdentityProperties(); - properties.setECID(new ECID("internalECID")); - IdentityState state = new IdentityState(properties); + IdentityState state = new IdentityState(mockIdentityStorageManager); + state.getIdentityProperties().setECID(new ECID("internalECID")); // test - Map identityXDM = createXDMIdentityMap( + final Map inputIdentityXDM = createXDMIdentityMap( new IdentityTestUtil.TestItem("ECID", "somevalue"), new IdentityTestUtil.TestItem("GAID", "somevalue"), new IdentityTestUtil.TestItem("IDFA", "somevalue"), @@ -412,166 +453,172 @@ public void testUpdateCustomerIdentifiers_doesNotUpdateReservedNamespace() throw new IdentityTestUtil.TestItem("gaid", "somevalue"), new IdentityTestUtil.TestItem("UserId", "somevalue") ); - state.updateCustomerIdentifiers(IdentityMap.fromXDMMap(identityXDM)); + state.updateCustomerIdentifiers(IdentityMap.fromXDMMap(inputIdentityXDM)); // verify persistence - final ArgumentCaptor persistenceValueCaptor = ArgumentCaptor.forClass(String.class); - verify(mockSharedPreferenceEditor, times(1)) - .putString(eq(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES), persistenceValueCaptor.capture()); - Map persistedData = flattenJSONString(persistenceValueCaptor.getAllValues().get(0)); - assertEquals(6, persistedData.size()); // USERID identifier and initial ECID - assertEquals("somevalue", persistedData.get("identityMap.UserId[0].id")); - assertEquals("ambiguous", persistedData.get("identityMap.UserId[0].authenticatedState")); - assertEquals("false", persistedData.get("identityMap.UserId[0].primary")); - assertEquals("internalECID", persistedData.get("identityMap.ECID[0].id")); // verify that the ECID is not disturbed - assertEquals("ambiguous", persistedData.get("identityMap.ECID[0].authenticatedState")); - assertEquals("false", persistedData.get("identityMap.ECID[0].primary")); + final ArgumentCaptor identityPropertiesArgumentCaptor = ArgumentCaptor.forClass( + IdentityProperties.class + ); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityPropertiesArgumentCaptor.capture()); + final IdentityProperties capturedIdentityProperties = identityPropertiesArgumentCaptor.getValue(); + final Map expectedIdentityXDM = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "internalECID"), + new IdentityTestUtil.TestItem("UserId", "somevalue") + ); + assertEquals(expectedIdentityXDM, capturedIdentityProperties.toXDMData(false)); } @Test public void testUpdateCustomerIdentifiers_whenCaseSensitiveNamespace_storesAll() throws Exception { // setup - IdentityProperties properties = new IdentityProperties(); - properties.setECID(new ECID("internalECID")); - IdentityState state = new IdentityState(properties); + final IdentityState state = new IdentityState(mockIdentityStorageManager); + state.getIdentityProperties().setECID(new ECID("internalECID")); // test - Map identityXDM = createXDMIdentityMap( + final Map identityXDM = createXDMIdentityMap( new IdentityTestUtil.TestItem("caseSensitive", "somevalue"), new IdentityTestUtil.TestItem("CASESENSITIVE", "SOMEVALUE") ); state.updateCustomerIdentifiers(IdentityMap.fromXDMMap(identityXDM)); - final ArgumentCaptor sharedStateCaptor = ArgumentCaptor.forClass(Map.class); - - // verify shared state - final ArgumentCaptor persistenceValueCaptor = ArgumentCaptor.forClass(String.class); - verify(mockSharedPreferenceEditor, times(1)) - .putString(eq(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES), persistenceValueCaptor.capture()); - Map persistedData = flattenJSONString(persistenceValueCaptor.getAllValues().get(0)); - assertEquals(9, persistedData.size()); // updated ids + ECID - assertEquals("somevalue", persistedData.get("identityMap.caseSensitive[0].id")); - assertEquals("SOMEVALUE", persistedData.get("identityMap.CASESENSITIVE[0].id")); - assertEquals("internalECID", persistedData.get("identityMap.ECID[0].id")); + // verify persistence + final ArgumentCaptor identityPropertiesArgumentCaptor = ArgumentCaptor.forClass( + IdentityProperties.class + ); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityPropertiesArgumentCaptor.capture()); + final Map expectedIdentityXDM = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "internalECID"), + new IdentityTestUtil.TestItem("caseSensitive", "somevalue"), + new IdentityTestUtil.TestItem("CASESENSITIVE", "SOMEVALUE") + ); + final IdentityProperties capturedIdentityProperties = identityPropertiesArgumentCaptor.getValue(); + assertEquals(expectedIdentityXDM, capturedIdentityProperties.toXDMData(false)); } + // ====================================================================================================================== + // Tests for method : removeCustomerIdentifiers(final IdentityMap map) + // ====================================================================================================================== + @Test public void testRemoveCustomerIdentifiers_happy() throws Exception { // setup - Map identityXDM = createXDMIdentityMap( + final Map initialIdentityXDM = createXDMIdentityMap( new IdentityTestUtil.TestItem("UserId", "secretID"), new IdentityTestUtil.TestItem("PushId", "token") ); - IdentityProperties properties = new IdentityProperties(identityXDM); - IdentityState state = new IdentityState(properties); + final IdentityState state = new IdentityState(mockIdentityStorageManager); + state.getIdentityProperties().updateCustomerIdentifiers(IdentityMap.fromXDMMap(initialIdentityXDM)); + state.getIdentityProperties().setECID(new ECID("internalECID")); // test - Map removedIdentityXDM = createXDMIdentityMap( + final Map removedIdentityXDM = createXDMIdentityMap( new IdentityTestUtil.TestItem("UserId", "secretID") ); state.removeCustomerIdentifiers(IdentityMap.fromXDMMap(removedIdentityXDM)); - // verify - final ArgumentCaptor persistenceValueCaptor = ArgumentCaptor.forClass(String.class); - verify(mockSharedPreferenceEditor, times(1)) - .putString(eq(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES), persistenceValueCaptor.capture()); - Map persistedData = flattenJSONString(persistenceValueCaptor.getAllValues().get(0)); - assertEquals(3, persistedData.size()); - assertNull(persistedData.get("identityMap.UserId[0].id")); - assertEquals("token", persistedData.get("identityMap.PushId[0].id")); + final ArgumentCaptor identityPropertiesArgumentCaptor = ArgumentCaptor.forClass( + IdentityProperties.class + ); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityPropertiesArgumentCaptor.capture()); + final Map expectedIdentityXDM = createXDMIdentityMap( + new IdentityTestUtil.TestItem("ECID", "internalECID"), + new IdentityTestUtil.TestItem("PushId", "token") + ); + final IdentityProperties capturedIdentityProperties = identityPropertiesArgumentCaptor.getValue(); + assertEquals(expectedIdentityXDM, capturedIdentityProperties.toXDMData(false)); } @Test public void testRemoveCustomerIdentifiers_doesNotRemoveReservedNamespace() throws Exception { - // setup - Map identityXDM = createXDMIdentityMap( - new IdentityTestUtil.TestItem("GAID", "someGAID"), - new IdentityTestUtil.TestItem("ECID", "someECID"), - new IdentityTestUtil.TestItem("IDFA", "someIDFA") - ); - IdentityProperties properties = new IdentityProperties(identityXDM); - IdentityState state = new IdentityState(properties); + final IdentityState state = new IdentityState(mockIdentityStorageManager); + final ECID initialECID = new ECID(); + state.getIdentityProperties().setECID(initialECID); + state.getIdentityProperties().setAdId("initialADID"); + + final IdentityProperties initialProperties = state.getIdentityProperties(); // test - Map removedIdentityXDM = createXDMIdentityMap( - new IdentityTestUtil.TestItem("GAID", "someGAID"), - new IdentityTestUtil.TestItem("ecid", "someECID"), - new IdentityTestUtil.TestItem("Idfa", "someIDFA") + final Map removedIdentityXDM = createXDMIdentityMap( + new IdentityTestUtil.TestItem("GAID", "initialECID"), + new IdentityTestUtil.TestItem("ECID", initialECID.toString()) ); state.removeCustomerIdentifiers(IdentityMap.fromXDMMap(removedIdentityXDM)); - // verify - final ArgumentCaptor persistenceValueCaptor = ArgumentCaptor.forClass(String.class); - verify(mockSharedPreferenceEditor, times(1)) - .putString(eq(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES), persistenceValueCaptor.capture()); - Map persistedData = flattenJSONString(persistenceValueCaptor.getAllValues().get(0)); - assertEquals(9, persistedData.size()); - assertEquals("someGAID", persistedData.get("identityMap.GAID[0].id")); - assertEquals("someECID", persistedData.get("identityMap.ECID[0].id")); - assertEquals("someIDFA", persistedData.get("identityMap.IDFA[0].id")); + final ArgumentCaptor identityPropertiesArgumentCaptor = ArgumentCaptor.forClass( + IdentityProperties.class + ); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityPropertiesArgumentCaptor.capture()); + final IdentityProperties capturedProperties = identityPropertiesArgumentCaptor.getValue(); + assertEquals(initialProperties.toXDMData(false), capturedProperties.toXDMData(false)); } + // ====================================================================================================================== + // Tests for method : updateLegacyExperienceCloudId(final IdentityMap map) + // ====================================================================================================================== + @Test public void testUpdateLegacyExperienceCloudId() { - IdentityState state = new IdentityState(new IdentityProperties()); - state.getIdentityProperties().setECID(new ECID()); - ECID legacyEcid = new ECID(); + final IdentityState state = new IdentityState(mockIdentityStorageManager); + final ECID ecid = new ECID(); + state.getIdentityProperties().setECID(ecid); + final ECID legacyEcid = new ECID(); // test state.updateLegacyExperienceCloudId(legacyEcid); // verify assertEquals(legacyEcid, state.getIdentityProperties().getECIDSecondary()); - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); + assertEquals(ecid, state.getIdentityProperties().getECID()); + verify(mockIdentityStorageManager).savePropertiesToPersistence(state.getIdentityProperties()); } @Test public void testUpdateLegacyExperienceCloudId_notSetWhenECIDSame() { - IdentityState state = new IdentityState(new IdentityProperties()); - ECID legacyEcid = new ECID(); + final IdentityState state = new IdentityState(mockIdentityStorageManager); + final ECID legacyEcid = new ECID(); state.getIdentityProperties().setECID(legacyEcid); state.updateLegacyExperienceCloudId(legacyEcid); // verify assertNull(state.getIdentityProperties().getECIDSecondary()); - verify(mockSharedPreferenceEditor, Mockito.times(0)).apply(); + verify(mockIdentityStorageManager, times(0)).savePropertiesToPersistence(any()); } @Test public void testUpdateLegacyExperienceCloudId_notSetWhenSecondaryECIDSame() { - IdentityState state = new IdentityState(new IdentityProperties()); + final IdentityState state = new IdentityState(mockIdentityStorageManager); state.getIdentityProperties().setECID(new ECID()); - ECID legacyEcid = new ECID(); + final ECID legacyEcid = new ECID(); state.getIdentityProperties().setECIDSecondary(legacyEcid); state.updateLegacyExperienceCloudId(legacyEcid); assertEquals(legacyEcid, state.getIdentityProperties().getECIDSecondary()); - verify(mockSharedPreferenceEditor, Mockito.times(0)).apply(); + verify(mockIdentityStorageManager, times(0)).savePropertiesToPersistence(any()); } @Test public void testUpdateLegacyExperienceCloudId_clearsOnNull() { - IdentityState state = new IdentityState(new IdentityProperties()); + final IdentityState state = new IdentityState(mockIdentityStorageManager); state.getIdentityProperties().setECID(new ECID()); state.getIdentityProperties().setECIDSecondary(new ECID()); state.updateLegacyExperienceCloudId(null); assertNull(state.getIdentityProperties().getECIDSecondary()); - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); + verify(mockIdentityStorageManager, times(1)).savePropertiesToPersistence(state.getIdentityProperties()); } @Test public void testUpdateLegacyExperienceCloudId_notSetWhenExistingIsNull() { - IdentityState state = new IdentityState(new IdentityProperties()); + final IdentityState state = new IdentityState(mockIdentityStorageManager); state.getIdentityProperties().setECID(new ECID()); state.updateLegacyExperienceCloudId(null); assertNull(state.getIdentityProperties().getECIDSecondary()); - verify(mockSharedPreferenceEditor, Mockito.times(0)).apply(); + verify(mockIdentityStorageManager, times(0)).savePropertiesToPersistence(any()); } // ====================================================================================================================== @@ -581,11 +628,11 @@ public void testUpdateLegacyExperienceCloudId_notSetWhenExistingIsNull() { // With consent change @Test public void testUpdateAdvertisingIdentifier_notSet_whenInitializingIdentityState() { - IdentityState state = new IdentityState(new IdentityProperties()); + final IdentityState state = new IdentityState(mockIdentityStorageManager); state.getIdentityProperties().setECID(new ECID()); assertNull(state.getIdentityProperties().getAdId()); - verify(mockSharedPreferenceEditor, Mockito.times(0)).apply(); + verify(mockIdentityStorageManager, times(0)).savePropertiesToPersistence(any()); } @Test @@ -683,47 +730,42 @@ private void assertUpdateAdvertisingIdentifier( boolean isSharedStateUpdateExpected ) throws Exception { // Setup - IdentityState state = new IdentityState((new IdentityProperties())); + + final IdentityState state = new IdentityState(mockIdentityStorageManager); state.getIdentityProperties().setECID(new ECID()); state.getIdentityProperties().setAdId(persistedAdId); - - Event event = fakeGenericIdentityEvent(newAdId); - state.updateAdvertisingIdentifier(event, mockSharedStateCallback); - - // Verify consent event - if (expectedConsent == null) { - PowerMockito.verifyStatic(MobileCore.class, Mockito.never()); - MobileCore.dispatchEvent(any(Event.class), any(ExtensionErrorCallback.class)); - } else { - final ArgumentCaptor consentEventCaptor = ArgumentCaptor.forClass(Event.class); - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEvent(consentEventCaptor.capture(), any(ExtensionErrorCallback.class)); - - Event consentEvent = consentEventCaptor.getAllValues().get(0); - - Map consentEventData = flattenMap(consentEvent.getEventData()); - // `flattenMap` allows for checking the keys' hierarchy and literal values simultaneously - assertEquals("GAID", consentEventData.get("consents.adID.idType")); - assertEquals(expectedConsent, consentEventData.get("consents.adID.val")); + final Event event = fakeGenericIdentityEvent(newAdId); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + state.updateAdvertisingIdentifier(event, mockSharedStateCallback); + + // Verify consent event + if (expectedConsent == null) { + mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(any()), never()); + } else { + final ArgumentCaptor consentEventCaptor = ArgumentCaptor.forClass(Event.class); + mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(consentEventCaptor.capture()), times(1)); + + final Event consentEvent = consentEventCaptor.getValue(); + + final Map consentEventData = flattenMap(consentEvent.getEventData()); + // `flattenMap` allows for checking the keys' hierarchy and literal values simultaneously + assertEquals("GAID", consentEventData.get("consents.adID.idType")); + assertEquals(expectedConsent, consentEventData.get("consents.adID.val")); + } } if (isSharedStateUpdateExpected) { - // Verify persistent store - final ArgumentCaptor persistenceValueCaptor = ArgumentCaptor.forClass(String.class); - verify(mockSharedPreferenceEditor, times(1)) - .putString(eq(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES), persistenceValueCaptor.capture()); - Map persistedData = flattenJSONString(persistenceValueCaptor.getAllValues().get(0)); - verifyFlatIdentityMap(persistedData, expectedAdId, state.getIdentityProperties().getECID().toString()); - - // Verify shared state and properties - assertEquals(1, setXDMSharedEventStateCalledTimes); + final ArgumentCaptor identityPropertiesArgumentCaptor = ArgumentCaptor.forClass( + IdentityProperties.class + ); + verify(mockIdentityStorageManager).savePropertiesToPersistence(identityPropertiesArgumentCaptor.capture()); + final IdentityProperties capturedProperties = identityPropertiesArgumentCaptor.getValue(); + final Map flatMap = flattenMap(capturedProperties.toXDMData(false)); + verifyFlatIdentityMap(flatMap, expectedAdId, state.getIdentityProperties().getECID().toString()); + mockSharedStateCallback.createXDMSharedState(capturedProperties.toXDMData(false), event); } else { - // Verify persistent store - verify(mockSharedPreferenceEditor, never()) - .putString(eq(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES), any(String.class)); - - // Verify shared state and properties - assertEquals(0, setXDMSharedEventStateCalledTimes); + verify(mockIdentityStorageManager, times(0)).savePropertiesToPersistence(any()); + mockSharedStateCallback.createXDMSharedState(any(), any()); } // Verify identity map final Map flatIdentityMap = flattenMap(state.getIdentityProperties().toXDMData(false)); @@ -779,6 +821,5 @@ private void verifyFlatIdentityMap( assertEquals("false", flatIdentityMap.get("identityMap.ECID[0].primary")); assertEquals(expectedECID, flatIdentityMap.get("identityMap.ECID[0].id")); assertEquals("ambiguous", flatIdentityMap.get("identityMap.ECID[0].authenticatedState")); - return; } } diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageManagerTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageManagerTests.java new file mode 100644 index 00000000..d719f107 --- /dev/null +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageManagerTests.java @@ -0,0 +1,208 @@ +/* + Copyright 2021 Adobe. All rights reserved. + This file is licensed to you under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. You may obtain a copy + of the License at http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under + the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + OF ANY KIND, either express or implied. See the License for the specific language + governing permissions and limitations under the License. +*/ + +package com.adobe.marketing.mobile.edge.identity; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.adobe.marketing.mobile.services.DataStoring; +import com.adobe.marketing.mobile.services.NamedCollection; +import com.adobe.marketing.mobile.services.ServiceProvider; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +public class IdentityStorageManagerTests { + + @Mock + private ServiceProvider mockServiceProvider; + + private MockedStatic mockedStaticServiceProvider; + + @Mock + private DataStoring mockDataStoreService; + + @Mock + private NamedCollection mockEdgeIdentityNamedCollection; + + @Mock + private NamedCollection mockDirectIdentityNamedCollection; + + @Before + public void before() throws Exception { + MockitoAnnotations.openMocks(this); + + mockedStaticServiceProvider = Mockito.mockStatic(ServiceProvider.class); + mockedStaticServiceProvider.when(ServiceProvider::getInstance).thenReturn(mockServiceProvider); + when(mockServiceProvider.getDataStoreService()).thenReturn(mockDataStoreService); + + when(mockDataStoreService.getNamedCollection(IdentityConstants.DataStoreKey.DATASTORE_NAME)) + .thenReturn(mockEdgeIdentityNamedCollection); + when(mockDataStoreService.getNamedCollection(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME)) + .thenReturn(mockDirectIdentityNamedCollection); + } + + @Test + public void testLoadPropertiesFromPersistence_edgeIdentityDataStoreIsNull() { + // setup + when(mockDataStoreService.getNamedCollection(IdentityConstants.DataStoreKey.DATASTORE_NAME)).thenReturn(null); + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + // test + final IdentityProperties identityProperties = identityStorageManager.loadPropertiesFromPersistence(); + + // verify + assertNull(identityProperties); + } + + @Test + public void testLoadPropertiesFromPersistence_identityPropertiesAreEmpty() { + when(mockEdgeIdentityNamedCollection.getString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, null)) + .thenReturn(null); + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + // test + final IdentityProperties identityProperties = identityStorageManager.loadPropertiesFromPersistence(); + + // verify + assertNull(identityProperties); + } + + @Test + public void testLoadPropertiesFromPersistence_identityPropertiesIsInvalid() { + when(mockEdgeIdentityNamedCollection.getString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, null)) + .thenReturn("{someinvalidjson}"); + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + // test + final IdentityProperties identityProperties = identityStorageManager.loadPropertiesFromPersistence(); + + // verify + assertNull(identityProperties); + } + + @Test + public void testLoadPropertiesFromPersistence_validJSON() { + // setup + final IdentityProperties persistedProps = new IdentityProperties(); + persistedProps.setECID(new ECID()); + final JSONObject jsonObject = new JSONObject(persistedProps.toXDMData(false)); + final String propsJSON = jsonObject.toString(); + + when(mockEdgeIdentityNamedCollection.getString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, null)) + .thenReturn(propsJSON); + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + // test + IdentityProperties props = identityStorageManager.loadPropertiesFromPersistence(); + + // verify + assertEquals(persistedProps.toXDMData(false), props.toXDMData(false)); + } + + @Test + public void testSavePropertiesToPersistence_edgeIdentityStoreIsNull() { + // setup + when(mockDataStoreService.getNamedCollection(IdentityConstants.DataStoreKey.DATASTORE_NAME)).thenReturn(null); + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + // test + final IdentityProperties identityProperties = new IdentityProperties(); + identityStorageManager.savePropertiesToPersistence(identityProperties); + + // verify + verify(mockEdgeIdentityNamedCollection, never()).setString(any(), any()); + } + + @Test + public void testSavePropertiesToPersistence_nullProps() { + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + // test + identityStorageManager.savePropertiesToPersistence(null); + + // verify + verify(mockEdgeIdentityNamedCollection, times(1)).remove(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES); + } + + @Test + public void testSavePropertiesToPersistence_validProps() { + // test + final IdentityProperties properties = new IdentityProperties(); + properties.setECID(new ECID()); + + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + identityStorageManager.savePropertiesToPersistence(properties); + + // verify + final JSONObject jsonObject = new JSONObject(properties.toXDMData(false)); + final String expectedJSON = jsonObject.toString(); + verify(mockEdgeIdentityNamedCollection) + .setString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, expectedJSON); + } + + @Test + public void testLoadEcidFromDirectIdentityPersistence_DirectIdentityStoreIsNull() { + when(mockDataStoreService.getNamedCollection(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME)) + .thenReturn(null); + + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + assertNull(identityStorageManager.loadEcidFromDirectIdentityPersistence()); + } + + @Test + public void testLoadEcidFromDirectIdentityPersistence_loadValidECID() { + final ECID ecid = new ECID(); + when(mockDirectIdentityNamedCollection.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) + .thenReturn(ecid.toString()); + + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + assertEquals(ecid, identityStorageManager.loadEcidFromDirectIdentityPersistence()); + } + + @Test + public void testLoadEcidFromDirectIdentityPersistence_whenNullECID() { + when(mockDirectIdentityNamedCollection.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) + .thenReturn(null); + + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + assertNull(identityStorageManager.loadEcidFromDirectIdentityPersistence()); + } + + @Test + public void testLoadEcidFromDirectIdentityPersistence_whenEmptyECID() { + when(mockDirectIdentityNamedCollection.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) + .thenReturn(""); + + final IdentityStorageManager identityStorageManager = new IdentityStorageManager(mockDataStoreService); + + assertNull(identityStorageManager.loadEcidFromDirectIdentityPersistence()); + } + + @After + public void teardown() { + mockedStaticServiceProvider.close(); + } +} diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageServiceTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageServiceTests.java deleted file mode 100644 index ce229389..00000000 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageServiceTests.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -import android.app.Application; -import android.content.Context; -import android.content.SharedPreferences; -import com.adobe.marketing.mobile.MobileCore; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({ MobileCore.class }) -public class IdentityStorageServiceTests { - - @Mock - Application mockApplication; - - @Mock - Context mockContext; - - @Mock - SharedPreferences mockSharedPreference; - - @Mock - SharedPreferences.Editor mockSharedPreferenceEditor; - - @Before - public void before() throws Exception { - PowerMockito.mockStatic(MobileCore.class); - - Mockito.when(MobileCore.getApplication()).thenReturn(mockApplication); - Mockito.when(mockApplication.getApplicationContext()).thenReturn(mockContext); - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito.when(mockSharedPreference.edit()).thenReturn(mockSharedPreferenceEditor); - } - - @Test - public void testLoadPropertiesFromPersistence_nullSharedPrefs() { - // setup - Mockito.when(mockApplication.getApplicationContext()).thenReturn(null); - - // test - IdentityProperties props = IdentityStorageService.loadPropertiesFromPersistence(); - - // verify - assertNull(props); - } - - @Test - public void testLoadPropertiesFromPersistence_emptyPrefs() { - // setup - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, null)) - .thenReturn(null); - - // test - IdentityProperties props = IdentityStorageService.loadPropertiesFromPersistence(); - - // verify - assertNull(props); - } - - @Test - public void testLoadPropertiesFromPersistence_invalidJSON() { - // setup - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, null)) - .thenReturn("{"); - - // test - IdentityProperties props = IdentityStorageService.loadPropertiesFromPersistence(); - - // verify - assertNull(props); - } - - @Test - public void testLoadPropertiesFromPersistence_validJSON() { - // setup - IdentityProperties persistedProps = new IdentityProperties(); - persistedProps.setECID(new ECID()); - final JSONObject jsonObject = new JSONObject(persistedProps.toXDMData(false)); - final String propsJSON = jsonObject.toString(); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, null)) - .thenReturn(propsJSON); - - // test - IdentityProperties props = IdentityStorageService.loadPropertiesFromPersistence(); - - // verify - assertEquals(persistedProps.toXDMData(false), props.toXDMData(false)); - } - - @Test - public void testSavePropertiesToPersistence_nullSharedPrefs() { - // setup - Mockito.when(mockApplication.getApplicationContext()).thenReturn(null); - - // test - IdentityProperties props = new IdentityProperties(); - IdentityStorageService.savePropertiesToPersistence(props); - - // verify - verify(mockSharedPreferenceEditor, never()).apply(); - } - - @Test - public void testSavePropertiesToPersistence_nullEditor() { - // setup - Mockito.when(mockSharedPreference.edit()).thenReturn(null); - - // test - IdentityProperties props = new IdentityProperties(); - IdentityStorageService.savePropertiesToPersistence(props); - - // verify - verify(mockSharedPreferenceEditor, never()).apply(); - } - - @Test - public void testSavePropertiesToPersistence_nullProps() { - // test - IdentityStorageService.savePropertiesToPersistence(null); - - // verify - verify(mockSharedPreferenceEditor, Mockito.times(1)).remove(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES); - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); - } - - @Test - public void testSavePropertiesToPersistence_validProps() { - // test - IdentityProperties props = new IdentityProperties(); - props.setECID(new ECID()); - IdentityStorageService.savePropertiesToPersistence(props); - - // verify - final JSONObject jsonObject = new JSONObject(props.toXDMData(false)); - final String expectedJSON = jsonObject.toString(); - verify(mockSharedPreferenceEditor, Mockito.times(1)) - .putString(IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, expectedJSON); - verify(mockSharedPreferenceEditor, Mockito.times(1)).apply(); - } - - @Test - public void testLoadEcidFromDirectIdentityPersistence_loadECID() { - ECID ecid = new ECID(); - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) - .thenReturn(ecid.toString()); - - assertEquals(ecid, IdentityStorageService.loadEcidFromDirectIdentityPersistence()); - } - - @Test - public void testLoadEcidFromDirectIdentityPersistence_whenNullECID() { - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) - .thenReturn(null); - - assertNull(IdentityStorageService.loadEcidFromDirectIdentityPersistence()); - } - - @Test - public void testLoadEcidFromDirectIdentityPersistence_whenEmptyECID() { - Mockito - .when(mockContext.getSharedPreferences(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, 0)) - .thenReturn(mockSharedPreference); - Mockito - .when(mockSharedPreference.getString(IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, null)) - .thenReturn(""); - - assertNull(IdentityStorageService.loadEcidFromDirectIdentityPersistence()); - } -} diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTests.java index 281bf0ef..130c1050 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTests.java @@ -13,39 +13,40 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; -import android.util.Log; import com.adobe.marketing.mobile.AdobeCallback; import com.adobe.marketing.mobile.AdobeCallbackWithError; import com.adobe.marketing.mobile.AdobeError; import com.adobe.marketing.mobile.Event; +import com.adobe.marketing.mobile.ExtensionError; import com.adobe.marketing.mobile.ExtensionErrorCallback; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.JSONUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import org.json.JSONObject; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatchers; +import org.mockito.MockedStatic; import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.MockitoAnnotations; -@RunWith(PowerMockRunner.class) -@PrepareForTest({ MobileCore.class }) public class IdentityTests { @Before public void setup() { - PowerMockito.mockStatic(MobileCore.class); + MockitoAnnotations.openMocks(this); } // ======================================================================================== @@ -57,7 +58,7 @@ public void test_extensionVersionAPI() { // test String extensionVersion = Identity.extensionVersion(); assertEquals( - "The Extension version API returns the correct value", + "The Extension version API should return the correct value", IdentityConstants.EXTENSION_VERSION, extensionVersion ); @@ -68,22 +69,26 @@ public void test_extensionVersionAPI() { // ======================================================================================== @Test public void testRegistration() { - // test - Identity.registerExtension(); - final ArgumentCaptor callbackCaptor = ArgumentCaptor.forClass( - ExtensionErrorCallback.class - ); - - // The identity extension should register with core - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.registerExtension(ArgumentMatchers.eq(IdentityExtension.class), callbackCaptor.capture()); - - // verify the callback - ExtensionErrorCallback extensionErrorCallback = callbackCaptor.getValue(); - assertNotNull("The extension callback should not be null", extensionErrorCallback); - // TODO - enable when ExtensionError creation is available - // should not crash on calling the callback - //extensionErrorCallback.error(ExtensionError.UNEXPECTED_ERROR); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.registerExtension(); + + // verify + final ArgumentCaptor callbackCaptor = ArgumentCaptor.forClass( + ExtensionErrorCallback.class + ); + mockedStaticMobileCore.verify(() -> + MobileCore.registerExtension(eq(IdentityExtension.class), callbackCaptor.capture()) + ); + + final ExtensionErrorCallback extensionErrorCallback = callbackCaptor.getValue(); + assertNotNull("The extension callback should not be null", extensionErrorCallback); + + // verify that the callback invocation does not throw an exception + extensionErrorCallback.error(ExtensionError.UNEXPECTED_ERROR); + } catch (final Exception e) { + fail(); + } } // ======================================================================================== @@ -93,135 +98,194 @@ public void testRegistration() { public void testGetExperienceCloudId() { // setup final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); - final ArgumentCaptor extensionErrorCallbackCaptor = ArgumentCaptor.forClass( - ExtensionErrorCallback.class + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class ); + final List callbackReturnValues = new ArrayList<>(); - // test - Identity.getExperienceCloudId( - new AdobeCallback() { - @Override - public void call(String s) { - callbackReturnValues.add(s); - } - } - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.getExperienceCloudId(callbackReturnValues::add); + + //verify + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + + // verify the dispatched event details + final Event dispatchedEvent = eventCaptor.getValue(); + assertEquals(IdentityConstants.EventNames.IDENTITY_REQUEST_IDENTITY_ECID, dispatchedEvent.getName()); + assertEquals(IdentityConstants.EventType.EDGE_IDENTITY, dispatchedEvent.getType()); + assertEquals(IdentityConstants.EventSource.REQUEST_IDENTITY, dispatchedEvent.getSource()); + assertNull(dispatchedEvent.getEventData()); + + // verify callback responses + final ECID ecid = new ECID(); + final Map ecidDict = new HashMap<>(); + ecidDict.put("id", ecid.toString()); + final ArrayList ecidArr = new ArrayList<>(); + ecidArr.add(ecidDict); + final Map identityMap = new HashMap<>(); + identityMap.put("ECID", ecidArr); + final Map xdmData = new HashMap<>(); + xdmData.put("identityMap", identityMap); + + assertNotNull(adobeCallbackCaptor.getValue()); + adobeCallbackCaptor.getValue().call(buildIdentityResponseEvent(xdmData)); + assertEquals(ecid.toString(), callbackReturnValues.get(0)); + } catch (Exception e) { + fail(); + } + } - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - eventCaptor.capture(), - adobeCallbackCaptor.capture(), - extensionErrorCallbackCaptor.capture() + @Test + public void testGetExperienceCloudId_invokeCallbackOnfail() { + // setup + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; + final Map errorCapture = new HashMap<>(); + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class ); + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { + @Override + public void fail(AdobeError adobeError) { + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); + } - // verify the dispatched event details - Event dispatchedEvent = eventCaptor.getValue(); - assertEquals(IdentityConstants.EventNames.IDENTITY_REQUEST_IDENTITY_ECID, dispatchedEvent.getName()); - assertEquals(IdentityConstants.EventType.EDGE_IDENTITY.toLowerCase(), dispatchedEvent.getType()); - assertEquals(IdentityConstants.EventSource.REQUEST_IDENTITY.toLowerCase(), dispatchedEvent.getSource()); - assertTrue(dispatchedEvent.getEventData().isEmpty()); + @Override + public void call(String ecid) {} + }; - // verify callback responses - ECID ecid = new ECID(); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.getExperienceCloudId(callbackWithError); + + //verify + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } catch (Exception e) { + fail(); + } - Map ecidDict = new HashMap<>(); - ecidDict.put("id", ecid.toString()); - ArrayList ecidArr = new ArrayList<>(); - ecidArr.add(ecidDict); - Map identityMap = new HashMap<>(); - identityMap.put("ECID", ecidArr); - Map xdmData = new HashMap<>(); - xdmData.put("identityMap", identityMap); + // set response event to null + adobeCallbackCaptor.getValue().fail(AdobeError.UNEXPECTED_ERROR); - adobeCallbackCaptor.getValue().call(buildIdentityResponseEvent(xdmData)); - assertEquals(ecid.toString(), callbackReturnValues.get(0)); - // TODO - enable when ExtensionError creation is available - // should not crash on calling the callback - //extensionErrorCallback.error(ExtensionError.UNEXPECTED_ERROR); + // verify + assertTrue(((boolean) errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED))); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); } @Test public void testGetExperienceCloudId_nullCallback() { - // test - Identity.getExperienceCloudId(null); - - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(0)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - any(AdobeCallback.class), - any(ExtensionErrorCallback.class) - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.getExperienceCloudId(null); + + //verify + mockedStaticMobileCore.verify( + () -> + MobileCore.dispatchEventWithResponseCallback( + any(Event.class), + anyLong(), + any(AdobeCallbackWithError.class) + ), + times(0) + ); + } } @Test public void testGetExperienceCloudId_nullResponseEvent() { // setup - final String KEY_IS_ERRORCALLBACK_CALLED = "errorCallBackCalled"; - final String KEY_CAPTUREDERRORCALLBACK = "capturedErrorCallback"; + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; final Map errorCapture = new HashMap<>(); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); - final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { - errorCapture.put(KEY_IS_ERRORCALLBACK_CALLED, true); - errorCapture.put(KEY_CAPTUREDERRORCALLBACK, adobeError); + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); } @Override - public void call(Object o) {} + public void call(String ecid) {} }; - // test - Identity.getExperienceCloudId(callbackWithError); - - // verify if the event is dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - adobeCallbackCaptor.capture(), - any(ExtensionErrorCallback.class) - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.getExperienceCloudId(callbackWithError); + + //verify + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } catch (Exception e) { + fail(); + } // set response event to null adobeCallbackCaptor.getValue().call(null); // verify - assertTrue((boolean) errorCapture.get(KEY_IS_ERRORCALLBACK_CALLED)); - assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTUREDERRORCALLBACK)); + assertTrue(((boolean) errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED))); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); } @Test public void testGetExperienceCloudId_invalidEventData() { // setup - final String KEY_IS_ERRORCALLBACK_CALLED = "errorCallBackCalled"; - final String KEY_CAPTUREDERRORCALLBACK = "capturedErrorCallback"; + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); final Map errorCapture = new HashMap<>(); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); - final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { - errorCapture.put(KEY_IS_ERRORCALLBACK_CALLED, true); - errorCapture.put(KEY_CAPTUREDERRORCALLBACK, adobeError); + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); } @Override - public void call(Object o) {} + public void call(String ecid) {} }; - // test - Identity.getExperienceCloudId(callbackWithError); - - // verify if the event is dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - adobeCallbackCaptor.capture(), - any(ExtensionErrorCallback.class) - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + Identity.getExperienceCloudId(callbackWithError); + + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } catch (Exception e) { + fail(); + } // set response event to null Map eventData = new HashMap<>(); @@ -229,8 +293,8 @@ public void call(Object o) {} adobeCallbackCaptor.getValue().call(buildIdentityResponseEvent(eventData)); // verify - assertTrue((boolean) errorCapture.get(KEY_IS_ERRORCALLBACK_CALLED)); - assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTUREDERRORCALLBACK)); + assertTrue((boolean) errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED)); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); } @Test @@ -238,8 +302,11 @@ public void testGetExperienceCloudId_missingECID() { // setup final String KEY_IS_ERRORCALLBACK_CALLED = "errorCallBackCalled"; final String KEY_CAPTUREDERRORCALLBACK = "capturedErrorCallback"; + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); final Map errorCapture = new HashMap<>(); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { @@ -251,16 +318,19 @@ public void fail(AdobeError adobeError) { public void call(Object o) {} }; - // test - Identity.getExperienceCloudId(callbackWithError); - - // verify if the event is dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - adobeCallbackCaptor.capture(), - any(ExtensionErrorCallback.class) - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.getExperienceCloudId(callbackWithError); + + //verify + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } // set response event to map missing ECID Map emptyXDMData = new HashMap<>(); @@ -275,174 +345,203 @@ public void call(Object o) {} // getUrlVariables API // ======================================================================================== @Test - public void testGetUrlVariables() throws InterruptedException { + public void testGetUrlVariables() { // setup final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); - final ArgumentCaptor extensionErrorCallbackCaptor = ArgumentCaptor.forClass( - ExtensionErrorCallback.class + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class ); final List callbackReturnValues = new ArrayList<>(); - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - // test - Identity.getUrlVariables( - new AdobeCallback() { - @Override - public void call(String s) { - callbackReturnValues.add(s); - latch.countDown(); + + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.getUrlVariables( + new AdobeCallback() { + @Override + public void call(String s) { + callbackReturnValues.add(s); + } } - } - ); - latch.await(2000, TimeUnit.MILLISECONDS); - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - eventCaptor.capture(), - adobeCallbackCaptor.capture(), - extensionErrorCallbackCaptor.capture() - ); + ); + + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } catch (Exception e) { + fail(); + } // verify the dispatched event details - Event dispatchedEvent = eventCaptor.getValue(); + final Event dispatchedEvent = eventCaptor.getValue(); assertEquals(IdentityConstants.EventNames.IDENTITY_REQUEST_URL_VARIABLES, dispatchedEvent.getName()); - assertEquals(IdentityConstants.EventType.EDGE_IDENTITY.toLowerCase(), dispatchedEvent.getType()); - assertEquals(IdentityConstants.EventSource.REQUEST_IDENTITY.toLowerCase(), dispatchedEvent.getSource()); + assertEquals(IdentityConstants.EventType.EDGE_IDENTITY, dispatchedEvent.getType()); + assertEquals(IdentityConstants.EventSource.REQUEST_IDENTITY, dispatchedEvent.getSource()); assertTrue(dispatchedEvent.getEventData().containsKey("urlvariables")); assertTrue((boolean) dispatchedEvent.getEventData().get("urlvariables")); // verify callback responses - Map urlVariablesResponse = new HashMap<>(); + final Map urlVariablesResponse = new HashMap<>(); urlVariablesResponse.put("urlvariables", "test-url-variable-string"); adobeCallbackCaptor.getValue().call(buildUrlVariablesResponseEvent(urlVariablesResponse)); assertEquals("test-url-variable-string", callbackReturnValues.get(0)); - // TODO - enable when ExtensionError creation is available - // should not crash on calling the callback - //extensionErrorCallback.error(ExtensionError.UNEXPECTED_ERROR); } @Test public void testGetUrlVariables_nullCallback() { - // test - Identity.getExperienceCloudId(null); - - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(0)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - any(AdobeCallback.class), - any(ExtensionErrorCallback.class) - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.getUrlVariables(null); + + mockedStaticMobileCore.verify( + () -> + MobileCore.dispatchEventWithResponseCallback( + any(Event.class), + anyLong(), + any(AdobeCallbackWithError.class) + ), + never() + ); + } } @Test public void testGetUrlVariables_nullResponseEvent() { // setup - final String KEY_IS_ERRORCALLBACK_CALLED = "errorCallBackCalled"; - final String KEY_CAPTUREDERRORCALLBACK = "capturedErrorCallback"; + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; final Map errorCapture = new HashMap<>(); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); - final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { - errorCapture.put(KEY_IS_ERRORCALLBACK_CALLED, true); - errorCapture.put(KEY_CAPTUREDERRORCALLBACK, adobeError); + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); } @Override - public void call(Object o) {} + public void call(String o) {} }; - // test - Identity.getUrlVariables(callbackWithError); - - // verify if the event is dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - adobeCallbackCaptor.capture(), - any(ExtensionErrorCallback.class) - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.getUrlVariables(callbackWithError); + + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } catch (Exception e) { + fail(); + } + + final Event dispatchedEvent = eventCaptor.getValue(); + assertEquals(IdentityConstants.EventNames.IDENTITY_REQUEST_URL_VARIABLES, dispatchedEvent.getName()); + assertEquals(IdentityConstants.EventType.EDGE_IDENTITY, dispatchedEvent.getType()); + assertEquals(IdentityConstants.EventSource.REQUEST_IDENTITY, dispatchedEvent.getSource()); + assertTrue(dispatchedEvent.getEventData().containsKey("urlvariables")); + assertTrue((boolean) dispatchedEvent.getEventData().get("urlvariables")); // set response event to null adobeCallbackCaptor.getValue().call(null); // verify - assertTrue((boolean) errorCapture.get(KEY_IS_ERRORCALLBACK_CALLED)); - assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTUREDERRORCALLBACK)); + assertEquals(true, errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED)); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); } @Test public void testGetUrlVariables_invalidEventData() { // setup - final String KEY_IS_ERRORCALLBACK_CALLED = "errorCallBackCalled"; - final String KEY_CAPTUREDERRORCALLBACK = "capturedErrorCallback"; + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; final Map errorCapture = new HashMap<>(); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); - final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { - errorCapture.put(KEY_IS_ERRORCALLBACK_CALLED, true); - errorCapture.put(KEY_CAPTUREDERRORCALLBACK, adobeError); + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); } @Override - public void call(Object o) {} + public void call(String o) {} }; - // test - Identity.getUrlVariables(callbackWithError); - - // verify if the event is dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - adobeCallbackCaptor.capture(), - any(ExtensionErrorCallback.class) - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.getUrlVariables(callbackWithError); + + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } catch (Exception e) { + fail(); + } // set response event data to not have urlvariables key - Map eventData = new HashMap<>(); + final Map eventData = new HashMap<>(); eventData.put("someKey", "someValue"); eventData.put("urlvariables", true); adobeCallbackCaptor.getValue().call(buildUrlVariablesResponseEvent(eventData)); // verify - assertTrue((boolean) errorCapture.get(KEY_IS_ERRORCALLBACK_CALLED)); - assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTUREDERRORCALLBACK)); + assertEquals(true, errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED)); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); } @Test public void testGetUrlVariables_NullUrlVariablesStringInResponseData() { // setup - final String KEY_IS_ERRORCALLBACK_CALLED = "errorCallBackCalled"; - final String KEY_CAPTUREDERRORCALLBACK = "capturedErrorCallback"; + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; final Map errorCapture = new HashMap<>(); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); - final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { - errorCapture.put(KEY_IS_ERRORCALLBACK_CALLED, true); - errorCapture.put(KEY_CAPTUREDERRORCALLBACK, adobeError); + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); } @Override - public void call(Object o) { - Log.d("test", "test"); - } + public void call(String o) {} }; // test - Identity.getUrlVariables(callbackWithError); - - // verify if the event is dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - adobeCallbackCaptor.capture(), - any(ExtensionErrorCallback.class) - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + Identity.getUrlVariables(callbackWithError); + + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } catch (Exception e) { + fail(); + } // set response event to have urlvariables map to null value Map nullUrlVariablesData = new HashMap<>(); @@ -450,8 +549,49 @@ public void call(Object o) { adobeCallbackCaptor.getValue().call(buildUrlVariablesResponseEvent(nullUrlVariablesData)); // verify - assertTrue((boolean) errorCapture.get(KEY_IS_ERRORCALLBACK_CALLED)); - assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTUREDERRORCALLBACK)); + assertEquals(true, errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED)); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); + } + + @Test + public void testGetUrlVariables_callbackOnFail() { + // setup + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; + final Map errorCapture = new HashMap<>(); + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { + @Override + public void fail(AdobeError adobeError) { + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); + } + + @Override + public void call(String o) {} + }; + + // test + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + Identity.getUrlVariables(callbackWithError); + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } catch (Exception e) { + fail(); + } + adobeCallbackCaptor.getValue().fail(AdobeError.UNEXPECTED_ERROR); + + // verify + assertEquals(true, errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED)); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); } // ======================================================================================== @@ -461,70 +601,76 @@ public void call(Object o) { public void testUpdateIdentities() { // setup final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); - final ArgumentCaptor extensionErrorCallbackCaptor = ArgumentCaptor.forClass( - ExtensionErrorCallback.class - ); - - // test - IdentityMap map = new IdentityMap(); + final IdentityMap map = new IdentityMap(); map.addItem(new IdentityItem("id", AuthenticatedState.AUTHENTICATED, true), "mainspace"); map.addItem(new IdentityItem("idtwo", AuthenticatedState.LOGGED_OUT, false), "secondspace"); - Identity.updateIdentities(map); - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEvent(eventCaptor.capture(), extensionErrorCallbackCaptor.capture()); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.updateIdentities(map); - // TODO - enable when ExtensionError creation is available - // should not crash on calling the callback - //extensionErrorCallback.error(ExtensionError.UNEXPECTED_ERROR); + mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(eventCaptor.capture())); + } catch (Exception e) { + fail(); + } // verify the dispatched event details Event dispatchedEvent = eventCaptor.getValue(); assertEquals(IdentityConstants.EventNames.UPDATE_IDENTITIES, dispatchedEvent.getName()); - assertEquals(IdentityConstants.EventType.EDGE_IDENTITY.toLowerCase(), dispatchedEvent.getType()); - assertEquals(IdentityConstants.EventSource.UPDATE_IDENTITY.toLowerCase(), dispatchedEvent.getSource()); + assertEquals(IdentityConstants.EventType.EDGE_IDENTITY, dispatchedEvent.getType()); + assertEquals(IdentityConstants.EventSource.UPDATE_IDENTITY, dispatchedEvent.getSource()); assertEquals(map.asXDMMap(), dispatchedEvent.getEventData()); } @Test - public void testUpdateIdentitiesNullAndEmptyMap() { + public void testUpdateIdentitiesNullMap() { // test - IdentityMap map = new IdentityMap(); - Identity.updateIdentities(map); - Identity.updateIdentities(null); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.updateIdentities(null); - // verify none of these API calls dispatch an event - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(0)); - MobileCore.dispatchEvent(any(Event.class), any(ExtensionErrorCallback.class)); + // verify that no event is dispatched + mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(any(Event.class)), never()); + } } + @Test + public void testUpdateIdentities_EmptyMap() { + // test + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.updateIdentities(new IdentityMap()); + + // verify that no event is dispatched + mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(any(Event.class)), never()); + } + } + + // ======================================================================================== + // removeIdentity API + // ======================================================================================== + @Test public void testRemoveIdentity() { // setup final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); - final ArgumentCaptor extensionErrorCallbackCaptor = ArgumentCaptor.forClass( - ExtensionErrorCallback.class - ); - IdentityItem sampleItem = new IdentityItem("sample", AuthenticatedState.AMBIGUOUS, false); + final IdentityItem sampleItem = new IdentityItem("sample", AuthenticatedState.AMBIGUOUS, false); - // test - Identity.removeIdentity(sampleItem, "namespace"); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.removeIdentity(sampleItem, "namespace"); - // verify dispatch event - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEvent(eventCaptor.capture(), extensionErrorCallbackCaptor.capture()); + mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(eventCaptor.capture())); + } - Event dispatchedEvent = eventCaptor.getValue(); + final Event dispatchedEvent = eventCaptor.getValue(); assertEquals(IdentityConstants.EventNames.REMOVE_IDENTITIES, dispatchedEvent.getName()); - assertEquals(IdentityConstants.EventType.EDGE_IDENTITY.toLowerCase(), dispatchedEvent.getType()); - assertEquals(IdentityConstants.EventSource.REMOVE_IDENTITY.toLowerCase(), dispatchedEvent.getSource()); - IdentityMap sampleInputIdentitymap = new IdentityMap(); - sampleInputIdentitymap.addItem(sampleItem, "namespace"); - assertEquals(sampleInputIdentitymap.asXDMMap(), dispatchedEvent.getEventData()); - // TODO - enable when ExtensionError creation is available - // should not crash on calling the callback - //extensionErrorCallback.error(ExtensionError.UNEXPECTED_ERROR); + assertEquals(IdentityConstants.EventType.EDGE_IDENTITY, dispatchedEvent.getType()); + assertEquals(IdentityConstants.EventSource.REMOVE_IDENTITY, dispatchedEvent.getSource()); + + final IdentityMap expectedIdentityMap = new IdentityMap(); + expectedIdentityMap.addItem(sampleItem, "namespace"); + assertEquals(expectedIdentityMap.asXDMMap(), dispatchedEvent.getEventData()); } @Test @@ -532,14 +678,15 @@ public void testRemoveIdentity_WithInvalidInputs() { // setup IdentityItem sampleItem = new IdentityItem("sample", AuthenticatedState.AMBIGUOUS, false); - // test - Identity.removeIdentity(null, "namespace"); - Identity.removeIdentity(sampleItem, ""); - Identity.removeIdentity(sampleItem, null); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + // test + Identity.removeIdentity(null, "namespace"); + Identity.removeIdentity(sampleItem, ""); + Identity.removeIdentity(sampleItem, null); - // verify none of these API calls dispatch an event - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(0)); - MobileCore.dispatchEvent(any(Event.class), any(ExtensionErrorCallback.class)); + // verify that no event is dispatched + mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(any(Event.class)), never()); + } } // ======================================================================================== @@ -549,36 +696,37 @@ public void testRemoveIdentity_WithInvalidInputs() { public void testGetIdentities() throws Exception { // setup final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); - final ArgumentCaptor extensionErrorCallbackCaptor = ArgumentCaptor.forClass( - ExtensionErrorCallback.class + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class ); final List callbackReturnValues = new ArrayList<>(); - // test - Identity.getIdentities( - new AdobeCallback() { - @Override - public void call(IdentityMap map) { - callbackReturnValues.add(map); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + Identity.getIdentities( + new AdobeCallback() { + @Override + public void call(IdentityMap map) { + callbackReturnValues.add(map); + } } - } - ); - - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - eventCaptor.capture(), - adobeCallbackCaptor.capture(), - extensionErrorCallbackCaptor.capture() - ); + ); + + // verify + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } // verify the dispatched event details - Event dispatchedEvent = eventCaptor.getValue(); + final Event dispatchedEvent = eventCaptor.getValue(); assertEquals(IdentityConstants.EventNames.REQUEST_IDENTITIES, dispatchedEvent.getName()); - assertEquals(IdentityConstants.EventType.EDGE_IDENTITY.toLowerCase(), dispatchedEvent.getType()); - assertEquals(IdentityConstants.EventSource.REQUEST_IDENTITY.toLowerCase(), dispatchedEvent.getSource()); - assertTrue(dispatchedEvent.getEventData().isEmpty()); + assertEquals(IdentityConstants.EventType.EDGE_IDENTITY, dispatchedEvent.getType()); + assertEquals(IdentityConstants.EventSource.REQUEST_IDENTITY, dispatchedEvent.getSource()); + assertNull(dispatchedEvent.getEventData()); // verify callback responses final ECID ecid = new ECID(); @@ -608,11 +756,11 @@ public void call(IdentityMap map) { "}"; final JSONObject jsonObject = new JSONObject(jsonStr); - final Map xdmData = Utils.toMap(jsonObject); + final Map xdmData = JSONUtils.toMap(jsonObject); adobeCallbackCaptor.getValue().call(buildIdentityResponseEvent(xdmData)); - IdentityItem ecidItem = callbackReturnValues.get(0).getIdentityItemsForNamespace("ECID").get(0); - IdentityItem coreItem = callbackReturnValues.get(0).getIdentityItemsForNamespace("CORE").get(0); + final IdentityItem ecidItem = callbackReturnValues.get(0).getIdentityItemsForNamespace("ECID").get(0); + final IdentityItem coreItem = callbackReturnValues.get(0).getIdentityItemsForNamespace("CORE").get(0); assertEquals(ecid.toString(), ecidItem.getId()); assertEquals(AuthenticatedState.AMBIGUOUS, ecidItem.getAuthenticatedState()); @@ -621,141 +769,197 @@ public void call(IdentityMap map) { assertEquals(coreId, coreItem.getId()); assertEquals(AuthenticatedState.AUTHENTICATED, coreItem.getAuthenticatedState()); assertEquals(false, coreItem.isPrimary()); - // TODO - enable when ExtensionError creation is available - // should not crash on calling the callback - //extensionErrorCallback.error(ExtensionError.UNEXPECTED_ERROR); } @Test public void testGetIdentities_nullCallback() { - // test - Identity.getIdentities(null); - - // verify - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(0)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - any(AdobeCallback.class), - any(ExtensionErrorCallback.class) - ); + // setup + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + Identity.getIdentities(null); + + // verify + mockedStaticMobileCore.verify( + () -> + MobileCore.dispatchEventWithResponseCallback( + any(Event.class), + anyLong(), + any(AdobeCallbackWithError.class) + ), + never() + ); + } } @Test public void testGetIdentities_nullResponseEvent() { // setup - final String KEY_IS_ERRORCALLBACK_CALLED = "errorCallBackCalled"; - final String KEY_CAPTUREDERRORCALLBACK = "capturedErrorCallback"; + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); final Map errorCapture = new HashMap<>(); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { - errorCapture.put(KEY_IS_ERRORCALLBACK_CALLED, true); - errorCapture.put(KEY_CAPTUREDERRORCALLBACK, adobeError); + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); } @Override public void call(Object o) {} }; - // test - Identity.getIdentities(callbackWithError); - - // verify if the event is dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - adobeCallbackCaptor.capture(), - any(ExtensionErrorCallback.class) - ); + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + Identity.getIdentities(callbackWithError); + + // verify + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } // set response event to null adobeCallbackCaptor.getValue().call(null); // verify - assertTrue((boolean) errorCapture.get(KEY_IS_ERRORCALLBACK_CALLED)); - assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTUREDERRORCALLBACK)); + assertTrue((boolean) errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED)); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); } @Test public void testGetIdentities_invalidEventData() { // setup - final String KEY_IS_ERRORCALLBACK_CALLED = "errorCallBackCalled"; - final String KEY_CAPTUREDERRORCALLBACK = "capturedErrorCallback"; + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); final Map errorCapture = new HashMap<>(); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { - errorCapture.put(KEY_IS_ERRORCALLBACK_CALLED, true); - errorCapture.put(KEY_CAPTUREDERRORCALLBACK, adobeError); + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); } @Override public void call(Object o) {} }; - // test - Identity.getIdentities(callbackWithError); - - // verify if the event is dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - adobeCallbackCaptor.capture(), - any(ExtensionErrorCallback.class) - ); - - // set response event to null + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + Identity.getIdentities(callbackWithError); + + // verify + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } + // set response event Map eventData = new HashMap<>(); eventData.put("someKey", "someValue"); adobeCallbackCaptor.getValue().call(buildIdentityResponseEvent(eventData)); // verify - assertTrue((boolean) errorCapture.get(KEY_IS_ERRORCALLBACK_CALLED)); - assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTUREDERRORCALLBACK)); + assertTrue((boolean) errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED)); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); } @Test public void testGetIdentities_missingIdentityMap() { // setup - final String KEY_IS_ERRORCALLBACK_CALLED = "errorCallBackCalled"; - final String KEY_CAPTUREDERRORCALLBACK = "capturedErrorCallback"; + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); final Map errorCapture = new HashMap<>(); - final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass(AdobeCallback.class); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class + ); final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { - errorCapture.put(KEY_IS_ERRORCALLBACK_CALLED, true); - errorCapture.put(KEY_CAPTUREDERRORCALLBACK, adobeError); + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); } @Override public void call(Object o) {} }; - // test - Identity.getIdentities(callbackWithError); - - // verify if the event is dispatched - PowerMockito.verifyStatic(MobileCore.class, Mockito.times(1)); - MobileCore.dispatchEventWithResponseCallback( - any(Event.class), - adobeCallbackCaptor.capture(), - any(ExtensionErrorCallback.class) + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + Identity.getIdentities(callbackWithError); + + // verify + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } + // set response event with empty data + Map eventData = new HashMap<>(); + adobeCallbackCaptor.getValue().call(buildIdentityResponseEvent(eventData)); + + // verify + assertTrue((boolean) errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED)); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); + } + + @Test + public void testGetIdentities_callbackOnFail() { + // setup + final String KEY_IS_ERROR_CALLBACK_CALLED = "errorCallBackCalled"; + final String KEY_CAPTURED_ERROR_CALLBACK = "capturedErrorCallback"; + final ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); + final Map errorCapture = new HashMap<>(); + final ArgumentCaptor adobeCallbackCaptor = ArgumentCaptor.forClass( + AdobeCallbackWithError.class ); + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { + @Override + public void fail(AdobeError adobeError) { + errorCapture.put(KEY_IS_ERROR_CALLBACK_CALLED, true); + errorCapture.put(KEY_CAPTURED_ERROR_CALLBACK, adobeError); + } - // set response event to map missing IdentityMap - Map emptyXDMData = new HashMap<>(); - adobeCallbackCaptor.getValue().call(buildIdentityResponseEvent(emptyXDMData)); + @Override + public void call(Object o) {} + }; + + try (MockedStatic mockedStaticMobileCore = Mockito.mockStatic(MobileCore.class)) { + Identity.getIdentities(callbackWithError); + + // verify + mockedStaticMobileCore.verify(() -> + MobileCore.dispatchEventWithResponseCallback( + eventCaptor.capture(), + eq(500L), + adobeCallbackCaptor.capture() + ) + ); + } + // set response event with empty data + adobeCallbackCaptor.getValue().fail(AdobeError.UNEXPECTED_ERROR); // verify - assertTrue((boolean) errorCapture.get(KEY_IS_ERRORCALLBACK_CALLED)); - assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTUREDERRORCALLBACK)); + assertTrue((boolean) errorCapture.get(KEY_IS_ERROR_CALLBACK_CALLED)); + assertEquals(AdobeError.UNEXPECTED_ERROR, errorCapture.get(KEY_CAPTURED_ERROR_CALLBACK)); } // ======================================================================================== - // Private method + // Private methods // ======================================================================================== private Event buildIdentityResponseEvent(final Map eventData) { return new Event.Builder( diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRemoveIdentityTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRemoveIdentityTests.java deleted file mode 100644 index dab33b3d..00000000 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRemoveIdentityTests.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.MobileCore; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; - -public class ListenerEdgeIdentityRemoveIdentityTests { - - @Mock - private IdentityExtension mockIdentityExtension; - - private ListenerEdgeIdentityRemoveIdentity listener; - private ExecutorService testExecutor; - - @Before - public void setup() { - testExecutor = Executors.newSingleThreadExecutor(); - mockIdentityExtension = Mockito.mock(IdentityExtension.class); - doReturn(testExecutor).when(mockIdentityExtension).getExecutor(); - MobileCore.start(null); - listener = - spy( - new ListenerEdgeIdentityRemoveIdentity( - null, - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REMOVE_IDENTITY - ) - ); - } - - @Test - public void testHear() throws Exception { - // setup - Event event = new Event.Builder( - "Remove Identity", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REMOVE_IDENTITY - ) - .build(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(1)).processAddEvent(event); - } - - @Test - public void testHear_WhenParentExtensionNull() throws Exception { - // setup - Event event = new Event.Builder( - "Remove Identity", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REMOVE_IDENTITY - ) - .build(); - doReturn(null).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(any(Event.class)); - } - - @Test - public void testHear_WhenEventNull() throws Exception { - // setup - doReturn(null).when(listener).getIdentityExtension(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(null); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(any(Event.class)); - } -} diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRequestIdentityTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRequestIdentityTests.java deleted file mode 100644 index 91f32e66..00000000 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRequestIdentityTests.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.MobileCore; -import java.util.HashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; - -public class ListenerEdgeIdentityRequestIdentityTests { - - @Mock - private IdentityExtension mockIdentityExtension; - - private ListenerEdgeIdentityRequestIdentity listener; - private ExecutorService testExecutor; - - @Before - public void setup() { - testExecutor = Executors.newSingleThreadExecutor(); - mockIdentityExtension = Mockito.mock(IdentityExtension.class); - doReturn(testExecutor).when(mockIdentityExtension).getExecutor(); - MobileCore.start(null); - listener = - spy( - new ListenerEdgeIdentityRequestIdentity( - null, - IdentityConstants.EventType.IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - ); - } - - @Test - public void testHear() throws Exception { - // setup - Event event = new Event.Builder( - "Request Identity", - IdentityConstants.EventType.IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .build(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(1)).processAddEvent(event); - } - - @Test - public void testHear_urlVariables() throws Exception { - // setup - Event event = new Event.Builder( - "Request Identity", - IdentityConstants.EventType.IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .setEventData( - new HashMap() { - { - put(IdentityConstants.EventDataKeys.URL_VARIABLES, true); - } - } - ) - .build(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(1)).processAddEvent(event); - } - - @Test - public void testHear_WhenParentExtensionNull() throws Exception { - // setup - Event event = new Event.Builder( - "Request Identity", - IdentityConstants.EventType.IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .build(); - doReturn(null).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(any(Event.class)); - } - - @Test - public void testHear_WhenEventNull() throws Exception { - // setup - doReturn(null).when(listener).getIdentityExtension(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(null); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(any(Event.class)); - } -} diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityUpdateIdentityTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityUpdateIdentityTests.java deleted file mode 100644 index 6cf77eb0..00000000 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityUpdateIdentityTests.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.MobileCore; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; - -public class ListenerEdgeIdentityUpdateIdentityTests { - - @Mock - private IdentityExtension mockIdentityExtension; - - private ListenerEdgeIdentityUpdateIdentity listener; - private ExecutorService testExecutor; - - @Before - public void setup() { - testExecutor = Executors.newSingleThreadExecutor(); - mockIdentityExtension = Mockito.mock(IdentityExtension.class); - doReturn(testExecutor).when(mockIdentityExtension).getExecutor(); - MobileCore.start(null); - listener = - spy( - new ListenerEdgeIdentityUpdateIdentity( - null, - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.UPDATE_IDENTITY - ) - ); - } - - @Test - public void testHear() throws Exception { - // setup - Event event = new Event.Builder( - "Update Identities", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.UPDATE_IDENTITY - ) - .build(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(1)).processAddEvent(event); - } - - @Test - public void testHear_WhenParentExtensionNull() throws Exception { - // setup - Event event = new Event.Builder( - "Update Identities", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.UPDATE_IDENTITY - ) - .build(); - doReturn(null).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(event); - } - - @Test - public void testHear_WhenEventNull() throws Exception { - // setup - doReturn(null).when(listener).getIdentityExtension(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(null); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(any(Event.class)); - } -} diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEventHubBootTest.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEventHubBootTest.java deleted file mode 100644 index 460229b7..00000000 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerEventHubBootTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.MobileCore; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; - -public class ListenerEventHubBootTest { - - @Mock - private IdentityExtension mockIdentityExtension; - - private ListenerEventHubBoot listener; - private ExecutorService testExecutor; - - @Before - public void setup() { - testExecutor = Executors.newSingleThreadExecutor(); - mockIdentityExtension = Mockito.mock(IdentityExtension.class); - doReturn(testExecutor).when(mockIdentityExtension).getExecutor(); - MobileCore.start(null); - listener = - spy(new ListenerEventHubBoot(null, IdentityConstants.EventType.HUB, IdentityConstants.EventSource.BOOTED)); - } - - @Test - public void testHear() throws Exception { - // setup - Event event = new Event.Builder( - "Event Hub Boot", - IdentityConstants.EventType.HUB, - IdentityConstants.EventSource.BOOTED - ) - .build(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(1)).bootupIfReady(); - } - - @Test - public void testHear_WhenParentExtensionNull() throws Exception { - // setup - Event event = new Event.Builder( - "Event Hub Boot", - IdentityConstants.EventType.HUB, - IdentityConstants.EventSource.BOOTED - ) - .build(); - doReturn(null).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).bootupIfReady(); - } -} diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerHubSharedStateTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerHubSharedStateTests.java deleted file mode 100644 index 3e24eb86..00000000 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerHubSharedStateTests.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.MobileCore; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; - -public class ListenerHubSharedStateTests { - - @Mock - private IdentityExtension mockIdentityExtension; - - private ListenerHubSharedState listener; - private ExecutorService testExecutor; - - @Before - public void setup() { - testExecutor = Executors.newSingleThreadExecutor(); - mockIdentityExtension = Mockito.mock(IdentityExtension.class); - doReturn(testExecutor).when(mockIdentityExtension).getExecutor(); - MobileCore.start(null); - listener = - spy( - new ListenerHubSharedState( - null, - IdentityConstants.EventType.HUB, - IdentityConstants.EventSource.SHARED_STATE - ) - ); - } - - @Test - public void testHear() throws Exception { - // setup - Event event = new Event.Builder( - "Shared State Change", - IdentityConstants.EventType.HUB, - IdentityConstants.EventSource.SHARED_STATE - ) - .build(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(1)).handleHubSharedState(event); - } - - @Test - public void testHear_WhenParentExtensionNull() throws Exception { - // setup - Event event = new Event.Builder( - "Shared State Change", - IdentityConstants.EventType.HUB, - IdentityConstants.EventSource.SHARED_STATE - ) - .build(); - doReturn(null).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).handleHubSharedState(any(Event.class)); - } - - @Test - public void testHear_WhenEventNull() throws Exception { - // setup - doReturn(null).when(listener).getIdentityExtension(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(null); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).handleHubSharedState(any(Event.class)); - } -} diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestContentTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestContentTests.java deleted file mode 100644 index 008e88a4..00000000 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestContentTests.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2022 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.MobileCore; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; - -public class ListenerIdentityRequestContentTests { - - @Mock - private IdentityExtension mockIdentityExtension; - - private ListenerIdentityRequestContent listener; - private ExecutorService testExecutor; - - @Before - public void setup() { - testExecutor = Executors.newSingleThreadExecutor(); - mockIdentityExtension = Mockito.mock(IdentityExtension.class); - doReturn(testExecutor).when(mockIdentityExtension).getExecutor(); - MobileCore.start(null); - listener = - spy( - new ListenerIdentityRequestContent( - null, - IdentityConstants.EventType.GENERIC_IDENTITY, - IdentityConstants.EventSource.REQUEST_CONTENT - ) - ); - } - - @Test - public void testHear() throws Exception { - // setup - Event event = new Event.Builder( - "Request Identity", - IdentityConstants.EventType.IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .build(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(1)).processAddEvent(event); - } - - @Test - public void testHear_WhenParentExtensionNull() throws Exception { - // setup - Event event = new Event.Builder( - "Request Identity", - IdentityConstants.EventType.IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .build(); - doReturn(null).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(any(Event.class)); - } - - @Test - public void testHear_WhenEventNull() throws Exception { - // setup - doReturn(null).when(listener).getIdentityExtension(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(null); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(any(Event.class)); - } -} diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestResetTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestResetTests.java deleted file mode 100644 index 382d78aa..00000000 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestResetTests.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.MobileCore; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; - -public class ListenerIdentityRequestResetTests { - - @Mock - private IdentityExtension mockIdentityExtension; - - private ListenerIdentityRequestReset listener; - private ExecutorService testExecutor; - - @Before - public void setup() { - testExecutor = Executors.newSingleThreadExecutor(); - mockIdentityExtension = Mockito.mock(IdentityExtension.class); - doReturn(testExecutor).when(mockIdentityExtension).getExecutor(); - MobileCore.start(null); - listener = - spy( - new ListenerIdentityRequestReset( - null, - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REQUEST_RESET - ) - ); - } - - @Test - public void testHear() throws Exception { - // setup - Event event = new Event.Builder( - "Request Identity", - IdentityConstants.EventType.IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .build(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(1)).processAddEvent(event); - } - - @Test - public void testHear_WhenParentExtensionNull() throws Exception { - // setup - Event event = new Event.Builder( - "Request Identity", - IdentityConstants.EventType.IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY - ) - .build(); - doReturn(null).when(listener).getIdentityExtension(); - - // test - listener.hear(event); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(any(Event.class)); - } - - @Test - public void testHear_WhenEventNull() throws Exception { - // setup - doReturn(null).when(listener).getIdentityExtension(); - doReturn(mockIdentityExtension).when(listener).getIdentityExtension(); - - // test - listener.hear(null); - - // verify - testExecutor.awaitTermination(100, TimeUnit.MILLISECONDS); - verify(mockIdentityExtension, times(0)).processAddEvent(any(Event.class)); - } -} diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/MockIdentityState.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/MockIdentityState.java deleted file mode 100644 index bae44e42..00000000 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/MockIdentityState.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import java.util.ArrayList; -import java.util.List; - -/** - * Partial mock class for {@link IdentityState} to be used for testing - */ -class MockIdentityState extends IdentityState { - - MockIdentityState(final IdentityProperties identityProperties) { - super(identityProperties); - } - - int updateCustomerIdentifiersCalledTimes = 0; - List updateCustomerIdentifiersParams = new ArrayList<>(); - - @Override - void updateCustomerIdentifiers(final IdentityMap map) { - updateCustomerIdentifiersCalledTimes++; - updateCustomerIdentifiersParams.add(map); - } - - int removeCustomerIdentifiersCalledTimes = 0; - List removeCustomerIdentifiersParams = new ArrayList<>(); - - @Override - void removeCustomerIdentifiers(final IdentityMap map) { - removeCustomerIdentifiersCalledTimes++; - removeCustomerIdentifiersParams.add(map); - } - - boolean hasBooted = false; - - @Override - boolean hasBooted() { - return hasBooted; - } -} diff --git a/code/edgeidentity/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/code/edgeidentity/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..ca6ee9ce --- /dev/null +++ b/code/edgeidentity/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file From afd93c54ee4506f25478c2c9616203f545446297 Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Mon, 12 Dec 2022 13:03:51 -0800 Subject: [PATCH 02/13] Remove duplicate util classes --- .../edge/identity/IdentityAdIdTest.java | 40 ++- .../identity/IdentityAndroidTestUtil.java | 303 ------------------ .../edge/identity/IdentityBootUpTest.java | 10 +- .../identity/IdentityECIDHandlingTest.java | 16 +- .../identity/IdentityFunctionalTestUtil.java | 295 ++++++++++++++++- .../edge/identity/IdentityPublicAPITest.java | 30 +- .../identity/IdentityResetHandlingTest.java | 4 +- 7 files changed, 333 insertions(+), 365 deletions(-) delete mode 100644 code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAndroidTestUtil.java diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java index f7e080ee..b9dc704d 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java @@ -11,8 +11,8 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.createXDMIdentityMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.createXDMIdentityMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.flattenMap; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.setEdgeIdentityPersistence; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getDispatchedEventsWith; @@ -50,8 +50,8 @@ public void testGenericIdentityRequest_whenValidAdId_thenNewValidAdId() throws E String newAdId = "8d9ca5ff-7e74-44ac-bbcd-7aee7baf4f6c"; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), - new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) + new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), + new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) ) ); @@ -83,8 +83,8 @@ public void testGenericIdentityRequest_whenValidAdId_thenNonAdId() throws Except String initialAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), - new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) + new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), + new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) ) ); registerEdgeIdentityExtension(); @@ -116,8 +116,8 @@ public void testGenericIdentityRequest_whenValidAdId_thenSameValidAdId() throws String newAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), - new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) + new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), + new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) ) ); registerEdgeIdentityExtension(); @@ -148,8 +148,8 @@ public void testGenericIdentityRequest_whenValidAdId_thenEmptyAdId() throws Exce String newAdId = ""; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), - new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) + new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), + new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) ) ); registerEdgeIdentityExtension(); @@ -180,8 +180,8 @@ public void testGenericIdentityRequest_whenValidAdId_thenAllZerosAdId() throws E String newAdId = "00000000-0000-0000-0000-000000000000"; setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), - new IdentityAndroidTestUtil.TestItem("GAID", initialAdId) + new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), + new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) ) ); registerEdgeIdentityExtension(); @@ -209,7 +209,9 @@ public void testGenericIdentityRequest_whenValidAdId_thenAllZerosAdId() throws E public void testGenericIdentityRequest_whenNoAdId_thenNewValidAdId() throws Exception { // Test String newAdId = "8d9ca5ff-7e74-44ac-bbcd-7aee7baf4f6c"; - setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"))); + setEdgeIdentityPersistence( + createXDMIdentityMap(new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID")) + ); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); @@ -235,7 +237,9 @@ public void testGenericIdentityRequest_whenNoAdId_thenNewValidAdId() throws Exce @Test public void testGenericIdentityRequest_whenNoAdId_thenNonAdId() throws Exception { // Test - setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"))); + setEdgeIdentityPersistence( + createXDMIdentityMap(new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID")) + ); registerEdgeIdentityExtension(); dispatchGenericIdentityNonAdIdEvent(); @@ -262,7 +266,9 @@ public void testGenericIdentityRequest_whenNoAdId_thenNonAdId() throws Exception public void testGenericIdentityRequest_whenNoAdId_thenEmptyAdId() throws Exception { // Test String newAdId = ""; - setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"))); + setEdgeIdentityPersistence( + createXDMIdentityMap(new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID")) + ); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); @@ -288,7 +294,9 @@ public void testGenericIdentityRequest_whenNoAdId_thenEmptyAdId() throws Excepti public void testGenericIdentityRequest_whenNoAdId_thenAllZerosAdIdTwice() throws Exception { // Test String newAdId = "00000000-0000-0000-0000-000000000000"; - setEdgeIdentityPersistence(createXDMIdentityMap(new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"))); + setEdgeIdentityPersistence( + createXDMIdentityMap(new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID")) + ); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAndroidTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAndroidTestUtil.java deleted file mode 100644 index 9ef1bd82..00000000 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAndroidTestUtil.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import static com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants.LOG_TAG; - -import com.adobe.marketing.mobile.AdobeCallback; -import com.adobe.marketing.mobile.AdobeCallbackWithError; -import com.adobe.marketing.mobile.AdobeError; -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.edge.identity.util.ADBCountDownLatch; -import com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants; -import com.adobe.marketing.mobile.services.Log; -import com.adobe.marketing.mobile.util.JSONUtils; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.ValueNode; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import org.json.JSONException; -import org.json.JSONObject; - -/** - * Util class used by both Functional and Unit tests - */ -public class IdentityAndroidTestUtil { - - private static final String LOG_SOURCE = "IdentityAndroidTestUtil"; - - /** - * Helper method to create IdentityXDM Map using {@link TestItem}s - */ - static Map createXDMIdentityMap(TestItem... items) { - final Map>> allItems = new HashMap<>(); - - for (TestItem item : items) { - final Map itemMap = new HashMap<>(); - itemMap.put(IdentityConstants.XDMKeys.ID, item.id); - itemMap.put(IdentityConstants.XDMKeys.AUTHENTICATED_STATE, "ambiguous"); - itemMap.put(IdentityConstants.XDMKeys.PRIMARY, item.isPrimary); - List> nameSpaceItems = allItems.get(item.namespace); - - if (nameSpaceItems == null) { - nameSpaceItems = new ArrayList<>(); - } - - nameSpaceItems.add(itemMap); - allItems.put(item.namespace, nameSpaceItems); - } - - final Map identityMapDict = new HashMap<>(); - identityMapDict.put(IdentityConstants.XDMKeys.IDENTITY_MAP, allItems); - return identityMapDict; - } - - /** - * Helper method to build remove identity request event with XDM formatted Identity jsonString - */ - static Event buildRemoveIdentityRequestWithJSONString(final String jsonStr) throws Exception { - final JSONObject jsonObject = new JSONObject(jsonStr); - final Map xdmData = JSONUtils.toMap(jsonObject); - return buildRemoveIdentityRequest(xdmData); - } - - /** - * Helper method to build remove identity request event with XDM formatted Identity map - */ - static Event buildRemoveIdentityRequest(final Map map) { - return new Event.Builder( - "Remove Identity Event", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REMOVE_IDENTITY - ) - .setEventData(map) - .build(); - } - - /** - * Helper method to build update identity request event with XDM formatted Identity jsonString - */ - static Event buildUpdateIdentityRequestJSONString(final String jsonStr) throws Exception { - final JSONObject jsonObject = new JSONObject(jsonStr); - final Map xdmData = JSONUtils.toMap(jsonObject); - return buildUpdateIdentityRequest(xdmData); - } - - /** - * Helper method to build update identity request event with XDM formatted Identity map - */ - static Event buildUpdateIdentityRequest(final Map map) { - return new Event.Builder( - "Update Identity Event", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.UPDATE_IDENTITY - ) - .setEventData(map) - .build(); - } - - /** - * Serialize the given {@code jsonString} to a JSON Object, then flattens to {@code Map}. - * If the provided string is not in JSON structure an {@link JSONException} is thrown. - * - * @param jsonString the string in JSON structure to flatten - * @return new map with flattened structure - */ - static Map flattenJSONString(final String jsonString) throws JSONException { - JSONObject jsonObject = new JSONObject(jsonString); - Map persistenceValueMap = JSONUtils.toMap(jsonObject); - return flattenMap(persistenceValueMap); - } - - /** - * Serialize the given {@code map} to a JSON Object, then flattens to {@code Map}. - * For example, a JSON such as "{xdm: {stitchId: myID, eventType: myType}}" is flattened - * to two map elements "xdm.stitchId" = "myID" and "xdm.eventType" = "myType". - * - * @param map map with JSON structure to flatten - * @return new map with flattened structure - */ - static Map flattenMap(final Map map) { - if (map == null || map.isEmpty()) { - return Collections.emptyMap(); - } - - try { - JSONObject jsonObject = new JSONObject(map); - Map payloadMap = new HashMap<>(); - addKeys("", new ObjectMapper().readTree(jsonObject.toString()), payloadMap); - return payloadMap; - } catch (IOException e) { - Log.error(LOG_TAG, LOG_SOURCE, "Failed to parse JSON object to tree structure."); - } - - return Collections.emptyMap(); - } - - /** - * Deserialize {@code JsonNode} and flatten to provided {@code map}. - * For example, a JSON such as "{xdm: {stitchId: myID, eventType: myType}}" is flattened - * to two map elements "xdm.stitchId" = "myID" and "xdm.eventType" = "myType". - *

- * Method is called recursively. To use, call with an empty path such as - * {@code addKeys("", new ObjectMapper().readTree(JsonNodeAsString), map);} - * - * @param currentPath the path in {@code JsonNode} to process - * @param jsonNode {@link JsonNode} to deserialize - * @param map {@code Map} instance to store flattened JSON result - * @see Stack Overflow post - */ - static void addKeys(String currentPath, JsonNode jsonNode, Map map) { - if (jsonNode.isObject()) { - ObjectNode objectNode = (ObjectNode) jsonNode; - Iterator> iter = objectNode.fields(); - String pathPrefix = currentPath.isEmpty() ? "" : currentPath + "."; - - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - addKeys(pathPrefix + entry.getKey(), entry.getValue(), map); - } - } else if (jsonNode.isArray()) { - ArrayNode arrayNode = (ArrayNode) jsonNode; - - for (int i = 0; i < arrayNode.size(); i++) { - addKeys(currentPath + "[" + i + "]", arrayNode.get(i), map); - } - } else if (jsonNode.isValueNode()) { - ValueNode valueNode = (ValueNode) jsonNode; - map.put(currentPath, valueNode.asText()); - } - } - - /** - * Class similar to {@link IdentityItem} for a specific namespace used for easier testing. - * For simplicity this class does not involve authenticatedState and primary key - */ - static class TestItem { - - private final String namespace; - private final String id; - private final boolean isPrimary = false; - - public TestItem(String namespace, String id) { - this.namespace = namespace; - this.id = id; - } - } - - /** - * Retrieves identities from Identity extension synchronously - * @return a {@code Map} of identities if retrieved successfully; - * null in case of a failure to retrieve it within timeout. - */ - static Map getIdentitiesSync() { - try { - final HashMap getIdentityResponse = new HashMap<>(); - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - Identity.getIdentities( - new AdobeCallbackWithError() { - @Override - public void call(final IdentityMap identities) { - getIdentityResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, identities); - latch.countDown(); - } - - @Override - public void fail(final AdobeError adobeError) { - getIdentityResponse.put(IdentityTestConstants.GetIdentitiesHelper.ERROR, adobeError); - latch.countDown(); - } - } - ); - latch.await(2000, TimeUnit.MILLISECONDS); - - return getIdentityResponse; - } catch (Exception exp) { - return null; - } - } - - /** - * Retrieves Experience Cloud Id from Identity extension synchronously - * @return an ECID if retrieved successfully; - * null in case of a failure to retrieve it within timeout. - */ - static String getExperienceCloudIdSync() { - try { - final HashMap getExperienceCloudIdResponse = new HashMap<>(); - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - Identity.getExperienceCloudId( - new AdobeCallback() { - @Override - public void call(final String ecid) { - getExperienceCloudIdResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, ecid); - latch.countDown(); - } - } - ); - latch.await(2000, TimeUnit.MILLISECONDS); - return getExperienceCloudIdResponse.get(IdentityTestConstants.GetIdentitiesHelper.VALUE); - } catch (Exception exp) { - return null; - } - } - - /** - * Retrieves url variables from Identity extension synchronously - * @return a url variable string if retrieved successfully; - * null in case of a failure to retrieve it within timeout. - */ - static String getUrlVariablesSync() { - try { - final HashMap getUrlVariablesResponse = new HashMap<>(); - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - Identity.getUrlVariables( - new AdobeCallback() { - @Override - public void call(final String urlVariables) { - getUrlVariablesResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, urlVariables); - latch.countDown(); - } - } - ); - latch.await(2000, TimeUnit.MILLISECONDS); - return getUrlVariablesResponse.get(IdentityTestConstants.GetIdentitiesHelper.VALUE); - } catch (Exception exp) { - return null; - } - } - - static IdentityMap createIdentityMap(final String namespace, final String id) { - return createIdentityMap(namespace, id, AuthenticatedState.AMBIGUOUS, false); - } - - static IdentityMap createIdentityMap( - final String namespace, - final String id, - final AuthenticatedState state, - final boolean isPrimary - ) { - IdentityMap map = new IdentityMap(); - IdentityItem item = new IdentityItem(id, state, isPrimary); - map.addItem(item, namespace); - return map; - } -} diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java index 92261db0..ea4827ad 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java @@ -11,8 +11,6 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.createXDMIdentityMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.*; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; import static org.junit.Assert.assertEquals; @@ -42,10 +40,10 @@ public void testOnBootUp_LoadsAllIdentitiesFromPreference() throws Exception { // test setEdgeIdentityPersistence( createXDMIdentityMap( - new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), - new IdentityAndroidTestUtil.TestItem("ECID", "secondaryECID"), - new IdentityAndroidTestUtil.TestItem("Email", "example@email.com"), - new IdentityAndroidTestUtil.TestItem("UserId", "JohnDoe") + new TestItem("ECID", "primaryECID"), + new TestItem("ECID", "secondaryECID"), + new TestItem("Email", "example@email.com"), + new TestItem("UserId", "JohnDoe") ) ); registerEdgeIdentityExtension(); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java index 870e51ae..7f57e2a9 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java @@ -11,8 +11,6 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.createXDMIdentityMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getExperienceCloudIdSync; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.*; import static org.junit.Assert.*; @@ -46,10 +44,7 @@ public void testECID_autoGeneratedWhenBooted() throws InterruptedException { public void testECID_loadedFromPersistence() throws Exception { // setup setEdgeIdentityPersistence( - createXDMIdentityMap( - new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), - new IdentityAndroidTestUtil.TestItem("ECID", "secondaryECID") - ) + createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("ECID", "secondaryECID")) ); registerEdgeIdentityExtension(); @@ -62,7 +57,7 @@ public void testECID_loadedFromPersistence() throws Exception { public void testECID_edgePersistenceTakesPreferenceOverDirectExtension() throws Exception { // setup setIdentityDirectPersistedECID("legacyECID"); - setEdgeIdentityPersistence(IdentityAndroidTestUtil.createIdentityMap("ECID", "edgeECID").asXDMMap()); + setEdgeIdentityPersistence(createIdentityMap("ECID", "edgeECID").asXDMMap()); registerEdgeIdentityExtension(); // verify @@ -116,10 +111,7 @@ public void testECID_whenBothExtensionRegistered_migrationPath() throws Exceptio public void testECID_onResetClearsOldECID() throws Exception { // setup setEdgeIdentityPersistence( - createXDMIdentityMap( - new IdentityAndroidTestUtil.TestItem("ECID", "primaryECID"), - new IdentityAndroidTestUtil.TestItem("ECID", "secondaryECID") - ) + createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("ECID", "secondaryECID")) ); registerEdgeIdentityExtension(); @@ -186,7 +178,7 @@ public void testECID_AreDifferentAfterResetIdentitiesAndPrivacyChange() throws E public void testECID_DirectEcidIsRemovedOnPrivacyOptOut() throws Exception { // setup setIdentityDirectPersistedECID("legacyECID"); - setEdgeIdentityPersistence(IdentityAndroidTestUtil.createIdentityMap("ECID", "edgeECID").asXDMMap()); + setEdgeIdentityPersistence(createIdentityMap("ECID", "edgeECID").asXDMMap()); registerBothIdentityExtensions(); // verify ECID diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java index 29898f95..e1527d86 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java @@ -11,32 +11,48 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getExperienceCloudIdSync; +import static com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants.LOG_TAG; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.resetTestExpectations; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import com.adobe.marketing.mobile.AdobeCallback; +import com.adobe.marketing.mobile.AdobeCallbackWithError; +import com.adobe.marketing.mobile.AdobeError; +import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.MobileCore; import com.adobe.marketing.mobile.edge.identity.util.ADBCountDownLatch; import com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants; import com.adobe.marketing.mobile.edge.identity.util.TestHelper; import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; +import com.adobe.marketing.mobile.services.Log; import com.adobe.marketing.mobile.util.JSONUtils; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.ValueNode; +import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +import org.json.JSONException; import org.json.JSONObject; public class IdentityFunctionalTestUtil { + private static final String LOG_SOURCE = "IdentityFunctionalTestUtil"; + /** * Register's Edge Identity Extension and start the Core */ - static void registerEdgeIdentityExtension() throws InterruptedException { + public static void registerEdgeIdentityExtension() throws InterruptedException { final ADBCountDownLatch latch = new ADBCountDownLatch(1); MobileCore.registerExtensions(Arrays.asList(Identity.EXTENSION), o -> latch.countDown()); @@ -48,7 +64,7 @@ static void registerEdgeIdentityExtension() throws InterruptedException { /** * Register's Identity Direct and Edge Identity Extension. And then starts the MobileCore */ - static void registerBothIdentityExtensions() throws Exception { + public static void registerBothIdentityExtensions() throws Exception { HashMap config = new HashMap() { { put("global.privacy", "optedin"); @@ -72,7 +88,7 @@ static void registerBothIdentityExtensions() throws Exception { /** * Updates configuration shared state with an orgId */ - static void setupConfiguration() throws Exception { + public static void setupConfiguration() throws Exception { HashMap config = new HashMap() { { put("experienceCloud.org", "testOrg@AdobeOrg"); @@ -85,7 +101,7 @@ static void setupConfiguration() throws Exception { /** * Set the ECID in persistence for Identity Direct extension. */ - static void setIdentityDirectPersistedECID(final String legacyECID) { + public static void setIdentityDirectPersistedECID(final String legacyECID) { TestPersistenceHelper.updatePersistence( IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, @@ -96,7 +112,7 @@ static void setIdentityDirectPersistedECID(final String legacyECID) { /** * Set the persistence data for Edge Identity extension. */ - static void setEdgeIdentityPersistence(final Map persistedData) { + public static void setEdgeIdentityPersistence(final Map persistedData) { if (persistedData != null) { final JSONObject persistedJSON = new JSONObject(persistedData); TestPersistenceHelper.updatePersistence( @@ -110,7 +126,7 @@ static void setEdgeIdentityPersistence(final Map persistedData) /** * Method to get the ECID from Identity Direct extension synchronously. */ - static String getIdentityDirectECIDSync() { + public static String getIdentityDirectECIDSync() { try { final HashMap getExperienceCloudIdResponse = new HashMap<>(); final ADBCountDownLatch latch = new ADBCountDownLatch(1); @@ -131,6 +147,263 @@ public void call(final String ecid) { } } + /** + * Helper method to create IdentityXDM Map using {@link TestItem}s + */ + public static Map createXDMIdentityMap(TestItem... items) { + final Map>> allItems = new HashMap<>(); + + for (TestItem item : items) { + final Map itemMap = new HashMap<>(); + itemMap.put(IdentityConstants.XDMKeys.ID, item.id); + itemMap.put(IdentityConstants.XDMKeys.AUTHENTICATED_STATE, "ambiguous"); + itemMap.put(IdentityConstants.XDMKeys.PRIMARY, item.isPrimary); + List> nameSpaceItems = allItems.get(item.namespace); + + if (nameSpaceItems == null) { + nameSpaceItems = new ArrayList<>(); + } + + nameSpaceItems.add(itemMap); + allItems.put(item.namespace, nameSpaceItems); + } + + final Map identityMapDict = new HashMap<>(); + identityMapDict.put(IdentityConstants.XDMKeys.IDENTITY_MAP, allItems); + return identityMapDict; + } + + /** + * Helper method to build remove identity request event with XDM formatted Identity jsonString + */ + public static Event buildRemoveIdentityRequestWithJSONString(final String jsonStr) throws Exception { + final JSONObject jsonObject = new JSONObject(jsonStr); + final Map xdmData = JSONUtils.toMap(jsonObject); + return buildRemoveIdentityRequest(xdmData); + } + + /** + * Helper method to build remove identity request event with XDM formatted Identity map + */ + public static Event buildRemoveIdentityRequest(final Map map) { + return new Event.Builder( + "Remove Identity Event", + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.REMOVE_IDENTITY + ) + .setEventData(map) + .build(); + } + + /** + * Helper method to build update identity request event with XDM formatted Identity jsonString + */ + public static Event buildUpdateIdentityRequestJSONString(final String jsonStr) throws Exception { + final JSONObject jsonObject = new JSONObject(jsonStr); + final Map xdmData = JSONUtils.toMap(jsonObject); + return buildUpdateIdentityRequest(xdmData); + } + + /** + * Helper method to build update identity request event with XDM formatted Identity map + */ + public static Event buildUpdateIdentityRequest(final Map map) { + return new Event.Builder( + "Update Identity Event", + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.UPDATE_IDENTITY + ) + .setEventData(map) + .build(); + } + + /** + * Serialize the given {@code jsonString} to a JSON Object, then flattens to {@code Map}. + * If the provided string is not in JSON structure an {@link JSONException} is thrown. + * + * @param jsonString the string in JSON structure to flatten + * @return new map with flattened structure + */ + public static Map flattenJSONString(final String jsonString) throws JSONException { + JSONObject jsonObject = new JSONObject(jsonString); + Map persistenceValueMap = JSONUtils.toMap(jsonObject); + return flattenMap(persistenceValueMap); + } + + /** + * Serialize the given {@code map} to a JSON Object, then flattens to {@code Map}. + * For example, a JSON such as "{xdm: {stitchId: myID, eventType: myType}}" is flattened + * to two map elements "xdm.stitchId" = "myID" and "xdm.eventType" = "myType". + * + * @param map map with JSON structure to flatten + * @return new map with flattened structure + */ + public static Map flattenMap(final Map map) { + if (map == null || map.isEmpty()) { + return Collections.emptyMap(); + } + + try { + JSONObject jsonObject = new JSONObject(map); + Map payloadMap = new HashMap<>(); + addKeys("", new ObjectMapper().readTree(jsonObject.toString()), payloadMap); + return payloadMap; + } catch (IOException e) { + Log.error(LOG_TAG, LOG_SOURCE, "Failed to parse JSON object to tree structure."); + } + + return Collections.emptyMap(); + } + + /** + * Deserialize {@code JsonNode} and flatten to provided {@code map}. + * For example, a JSON such as "{xdm: {stitchId: myID, eventType: myType}}" is flattened + * to two map elements "xdm.stitchId" = "myID" and "xdm.eventType" = "myType". + *

+ * Method is called recursively. To use, call with an empty path such as + * {@code addKeys("", new ObjectMapper().readTree(JsonNodeAsString), map);} + * + * @param currentPath the path in {@code JsonNode} to process + * @param jsonNode {@link JsonNode} to deserialize + * @param map {@code Map} instance to store flattened JSON result + * @see Stack Overflow post + */ + public static void addKeys(String currentPath, JsonNode jsonNode, Map map) { + if (jsonNode.isObject()) { + ObjectNode objectNode = (ObjectNode) jsonNode; + Iterator> iter = objectNode.fields(); + String pathPrefix = currentPath.isEmpty() ? "" : currentPath + "."; + + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + addKeys(pathPrefix + entry.getKey(), entry.getValue(), map); + } + } else if (jsonNode.isArray()) { + ArrayNode arrayNode = (ArrayNode) jsonNode; + + for (int i = 0; i < arrayNode.size(); i++) { + addKeys(currentPath + "[" + i + "]", arrayNode.get(i), map); + } + } else if (jsonNode.isValueNode()) { + ValueNode valueNode = (ValueNode) jsonNode; + map.put(currentPath, valueNode.asText()); + } + } + + /** + * Class similar to {@link IdentityItem} for a specific namespace used for easier testing. + * For simplicity this class does not involve authenticatedState and primary key + */ + public static class TestItem { + + private final String namespace; + private final String id; + private final boolean isPrimary = false; + + public TestItem(String namespace, String id) { + this.namespace = namespace; + this.id = id; + } + } + + /** + * Retrieves identities from Identity extension synchronously + * @return a {@code Map} of identities if retrieved successfully; + * null in case of a failure to retrieve it within timeout. + */ + public static Map getIdentitiesSync() { + try { + final HashMap getIdentityResponse = new HashMap<>(); + final ADBCountDownLatch latch = new ADBCountDownLatch(1); + Identity.getIdentities( + new AdobeCallbackWithError() { + @Override + public void call(final IdentityMap identities) { + getIdentityResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, identities); + latch.countDown(); + } + + @Override + public void fail(final AdobeError adobeError) { + getIdentityResponse.put(IdentityTestConstants.GetIdentitiesHelper.ERROR, adobeError); + latch.countDown(); + } + } + ); + latch.await(2000, TimeUnit.MILLISECONDS); + + return getIdentityResponse; + } catch (Exception exp) { + return null; + } + } + + /** + * Retrieves Experience Cloud Id from Identity extension synchronously + * @return an ECID if retrieved successfully; + * null in case of a failure to retrieve it within timeout. + */ + public static String getExperienceCloudIdSync() { + try { + final HashMap getExperienceCloudIdResponse = new HashMap<>(); + final ADBCountDownLatch latch = new ADBCountDownLatch(1); + Identity.getExperienceCloudId( + new AdobeCallback() { + @Override + public void call(final String ecid) { + getExperienceCloudIdResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, ecid); + latch.countDown(); + } + } + ); + latch.await(2000, TimeUnit.MILLISECONDS); + return getExperienceCloudIdResponse.get(IdentityTestConstants.GetIdentitiesHelper.VALUE); + } catch (Exception exp) { + return null; + } + } + + /** + * Retrieves url variables from Identity extension synchronously + * @return a url variable string if retrieved successfully; + * null in case of a failure to retrieve it within timeout. + */ + public static String getUrlVariablesSync() { + try { + final HashMap getUrlVariablesResponse = new HashMap<>(); + final ADBCountDownLatch latch = new ADBCountDownLatch(1); + Identity.getUrlVariables( + new AdobeCallback() { + @Override + public void call(final String urlVariables) { + getUrlVariablesResponse.put(IdentityTestConstants.GetIdentitiesHelper.VALUE, urlVariables); + latch.countDown(); + } + } + ); + latch.await(2000, TimeUnit.MILLISECONDS); + return getUrlVariablesResponse.get(IdentityTestConstants.GetIdentitiesHelper.VALUE); + } catch (Exception exp) { + return null; + } + } + + public static IdentityMap createIdentityMap(final String namespace, final String id) { + return createIdentityMap(namespace, id, AuthenticatedState.AMBIGUOUS, false); + } + + public static IdentityMap createIdentityMap( + final String namespace, + final String id, + final AuthenticatedState state, + final boolean isPrimary + ) { + IdentityMap map = new IdentityMap(); + IdentityItem item = new IdentityItem(id, state, isPrimary); + map.addItem(item, namespace); + return map; + } + // -------------------------------------------------------------------------------------------- // Verifiers // -------------------------------------------------------------------------------------------- @@ -139,7 +412,7 @@ public void call(final String ecid) { * Verifies that primary ECID is not null for the Edge Identity extension. * This method checks for the data in shared state, persistence and through getExperienceCloudId API. */ - static void verifyPrimaryECIDNotNull() throws InterruptedException { + public static void verifyPrimaryECIDNotNull() throws InterruptedException { String ecid = getExperienceCloudIdSync(); assertNotNull(ecid); @@ -152,7 +425,7 @@ static void verifyPrimaryECIDNotNull() throws InterruptedException { * Verifies that primary ECID for the Edge Identity Extension is equal to the value provided. * This method checks for the data in shared state, persistence and through getExperienceCloudId API. */ - static void verifyPrimaryECID(final String primaryECID) throws Exception { + public static void verifyPrimaryECID(final String primaryECID) throws Exception { String ecid = getExperienceCloudIdSync(); assertEquals(primaryECID, ecid); @@ -173,7 +446,7 @@ static void verifyPrimaryECID(final String primaryECID) throws Exception { * Verifies that secondary ECID for the Edge Identity Extension is equal to the value provided * This method checks for the data in shared state and persistence. */ - static void verifySecondaryECID(final String secondaryECID) throws Exception { + public static void verifySecondaryECID(final String secondaryECID) throws Exception { // verify xdm shared state is has correct secondary ECID Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); assertEquals(secondaryECID, xdmSharedState.get("identityMap.ECID[1].id")); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java index 27df8d6e..bf584920 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java @@ -11,11 +11,11 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.createIdentityMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getExperienceCloudIdSync; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getIdentitiesSync; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getUrlVariablesSync; +import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.createIdentityMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.flattenMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.getExperienceCloudIdSync; +import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.getIdentitiesSync; +import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.getUrlVariablesSync; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.setupConfiguration; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.*; @@ -153,7 +153,7 @@ public void testUpdateAPI_emptyData() throws Exception { @Test public void testUpdateAPI_shouldReplaceExistingIdentities() throws Exception { // test - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("Email", "example@email.com")); + Identity.updateIdentities(createIdentityMap("Email", "example@email.com")); Identity.updateIdentities( createIdentityMap("Email", "example@email.com", AuthenticatedState.AUTHENTICATED, true) ); @@ -184,13 +184,13 @@ public void testUpdateAPI_shouldReplaceExistingIdentities() throws Exception { @Test public void testUpdateAPI_withReservedNamespaces() throws Exception { // test - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("ECID", "newECID")); - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("GAID", "")); - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("IDFA", "")); - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("IDFa", "")); - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("gaid", "")); - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("ecid", "")); - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("idfa", "")); + Identity.updateIdentities(createIdentityMap("ECID", "newECID")); + Identity.updateIdentities(createIdentityMap("GAID", "")); + Identity.updateIdentities(createIdentityMap("IDFA", "")); + Identity.updateIdentities(createIdentityMap("IDFa", "")); + Identity.updateIdentities(createIdentityMap("gaid", "")); + Identity.updateIdentities(createIdentityMap("ecid", "")); + Identity.updateIdentities(createIdentityMap("idfa", "")); TestHelper.waitForThreads(2000); // verify xdm shared state does not get updated @@ -415,7 +415,7 @@ public void testRemoveIdentity_nonExistentNamespace() throws Exception { public void testRemoveIdentity_nameSpaceCaseSensitive() throws Exception { // setup // update Identities through API - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("Email", "example@email.com")); + Identity.updateIdentities(createIdentityMap("Email", "example@email.com")); // test Identity.removeIdentity(new IdentityItem("example@email.com"), "email"); @@ -439,7 +439,7 @@ public void testRemoveIdentity_nameSpaceCaseSensitive() throws Exception { public void testRemoveIdentity_nonExistentItem() throws Exception { // setup // update Identities through API - Identity.updateIdentities(IdentityAndroidTestUtil.createIdentityMap("Email", "example@email.com")); + Identity.updateIdentities(createIdentityMap("Email", "example@email.com")); // test Identity.removeIdentity(new IdentityItem("secondary@email.com"), "Email"); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java index a1810a70..d51825b5 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java @@ -11,8 +11,8 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.flattenMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityAndroidTestUtil.getExperienceCloudIdSync; +import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.flattenMap; +import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.getExperienceCloudIdSync; import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.*; import static org.junit.Assert.*; From 16200d789c7c3e67eb99cbf0b52d4b4c634864ee Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Mon, 12 Dec 2022 13:09:24 -0800 Subject: [PATCH 03/13] Discard Identity test constants and change copyright year --- .../identity/IdentityFunctionalTestUtil.java | 2 +- .../edge/identity/IdentityTestConstants.java | 40 ------------------- 2 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestConstants.java diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java index e1527d86..66ac4ea2 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java @@ -1,5 +1,5 @@ /* - Copyright 2021 Adobe. All rights reserved. + Copyright 2022 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 diff --git a/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestConstants.java b/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestConstants.java deleted file mode 100644 index 2c217b7c..00000000 --- a/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestConstants.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -public class IdentityTestConstants { - - public final class DataStoreKey { - - public static final String CONFIG_DATASTORE = "AdobeMobile_ConfigState"; - public static final String IDENTITY_DATASTORE = "com.adobe.edge.identity"; - public static final String IDENTITY_DIRECT_DATASTORE = "visitorIDServiceDataStore"; - - private DataStoreKey() {} - } - - public final class SharedStateName { - - public static final String CONFIG = "com.adobe.module.configuration"; - public static final String EVENT_HUB = "com.adobe.module.eventhub"; - - private SharedStateName() {} - } - - public final class GetIdentitiesHelper { - - public static final String VALUE = "getConsentValue"; - public static final String ERROR = "getConsentError"; - - private GetIdentitiesHelper() {} - } -} From 50afa2ab8918e0231ac6aaa32596e9b0045ca75c Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Tue, 13 Dec 2022 09:10:16 -0800 Subject: [PATCH 04/13] Make imports consistent and unify test constants --- .../edge/identity/IdentityAdIdTest.java | 76 ++++++------------- .../edge/identity/IdentityBootUpTest.java | 2 +- .../identity/IdentityECIDHandlingTest.java | 2 +- .../edge/identity/IdentityPublicAPITest.java | 41 ++++------ .../identity/IdentityResetHandlingTest.java | 9 +-- .../IdentityFunctionalTestUtil.java | 61 ++++++++------- .../identity/util/IdentityTestConstants.java | 45 ++++++++++- .../edge/identity/util/MonitorExtension.java | 24 +++--- .../edge/identity/util/TestConstants.java | 44 ----------- .../mobile/edge/identity/util/TestHelper.java | 12 +-- .../edge/identity/IdentityStateTests.java | 32 ++++---- .../mobile/edge/identity/IdentityTests.java | 52 ++++++++++--- 12 files changed, 195 insertions(+), 205 deletions(-) rename code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/{ => util}/IdentityFunctionalTestUtil.java (89%) delete mode 100644 code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestConstants.java diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java index b9dc704d..332ce3d5 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java @@ -11,19 +11,14 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.createXDMIdentityMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.flattenMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.setEdgeIdentityPersistence; -import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getDispatchedEventsWith; -import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; +import static com.adobe.marketing.mobile.edge.identity.util.IdentityFunctionalTestUtil.*; +import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.*; import static org.junit.Assert.assertEquals; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.MobileCore; -import com.adobe.marketing.mobile.edge.identity.util.TestHelper; import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; import com.adobe.marketing.mobile.util.JSONUtils; import com.adobe.marketing.mobile.util.StringUtils; @@ -38,9 +33,7 @@ public class IdentityAdIdTest { @Rule - public RuleChain rule = RuleChain - .outerRule(new TestHelper.SetupCoreRule()) - .around(new TestHelper.RegisterMonitorExtensionRule()); + public RuleChain rule = RuleChain.outerRule(new SetupCoreRule()).around(new RegisterMonitorExtensionRule()); @Test public void testGenericIdentityRequest_whenValidAdId_thenNewValidAdId() throws Exception { @@ -49,17 +42,14 @@ public void testGenericIdentityRequest_whenValidAdId_thenNewValidAdId() throws E String initialAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; String newAdId = "8d9ca5ff-7e74-44ac-bbcd-7aee7baf4f6c"; setEdgeIdentityPersistence( - createXDMIdentityMap( - new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), - new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) - ) + createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); // After sending mobile core event, give a wait time to allow for processing - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Edge Consent event should not be dispatched; valid -> valid does not signal change in consent verifyDispatchedEvents(true, null); @@ -82,16 +72,13 @@ public void testGenericIdentityRequest_whenValidAdId_thenNonAdId() throws Except // Test String initialAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; setEdgeIdentityPersistence( - createXDMIdentityMap( - new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), - new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) - ) + createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); registerEdgeIdentityExtension(); dispatchGenericIdentityNonAdIdEvent(); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Edge Consent event should not be dispatched; valid -> (unchanged) valid does not signal change in consent verifyDispatchedEvents(false, null); @@ -115,15 +102,12 @@ public void testGenericIdentityRequest_whenValidAdId_thenSameValidAdId() throws String initialAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; String newAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; setEdgeIdentityPersistence( - createXDMIdentityMap( - new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), - new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) - ) + createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Edge Consent event should not be dispatched; valid -> valid does not signal change in consent verifyDispatchedEvents(true, null); @@ -147,15 +131,12 @@ public void testGenericIdentityRequest_whenValidAdId_thenEmptyAdId() throws Exce String initialAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; String newAdId = ""; setEdgeIdentityPersistence( - createXDMIdentityMap( - new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), - new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) - ) + createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Edge Consent event should be dispatched; valid -> invalid signals change in consent verifyDispatchedEvents(true, "n"); @@ -179,15 +160,12 @@ public void testGenericIdentityRequest_whenValidAdId_thenAllZerosAdId() throws E String initialAdId = "fa181743-2520-4ebc-b125-626baf1e3db8"; String newAdId = "00000000-0000-0000-0000-000000000000"; setEdgeIdentityPersistence( - createXDMIdentityMap( - new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID"), - new IdentityFunctionalTestUtil.TestItem("GAID", initialAdId) - ) + createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Edge Consent event should be dispatched; valid -> invalid signals change in consent verifyDispatchedEvents(true, "n"); @@ -209,13 +187,11 @@ public void testGenericIdentityRequest_whenValidAdId_thenAllZerosAdId() throws E public void testGenericIdentityRequest_whenNoAdId_thenNewValidAdId() throws Exception { // Test String newAdId = "8d9ca5ff-7e74-44ac-bbcd-7aee7baf4f6c"; - setEdgeIdentityPersistence( - createXDMIdentityMap(new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID")) - ); + setEdgeIdentityPersistence(createXDMIdentityMap(new TestItem("ECID", "primaryECID"))); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Generic Identity event containing advertisingIdentifier should be dispatched // Edge Consent event should not be dispatched; valid -> valid does not signal change in consent @@ -237,14 +213,12 @@ public void testGenericIdentityRequest_whenNoAdId_thenNewValidAdId() throws Exce @Test public void testGenericIdentityRequest_whenNoAdId_thenNonAdId() throws Exception { // Test - setEdgeIdentityPersistence( - createXDMIdentityMap(new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID")) - ); + setEdgeIdentityPersistence(createXDMIdentityMap(new TestItem("ECID", "primaryECID"))); registerEdgeIdentityExtension(); dispatchGenericIdentityNonAdIdEvent(); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Edge Consent event should not be dispatched; valid -> valid does not signal change in consent verifyDispatchedEvents(false, null); @@ -266,13 +240,11 @@ public void testGenericIdentityRequest_whenNoAdId_thenNonAdId() throws Exception public void testGenericIdentityRequest_whenNoAdId_thenEmptyAdId() throws Exception { // Test String newAdId = ""; - setEdgeIdentityPersistence( - createXDMIdentityMap(new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID")) - ); + setEdgeIdentityPersistence(createXDMIdentityMap(new TestItem("ECID", "primaryECID"))); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Edge Consent event should not be dispatched; invalid -> invalid does not signal change in consent verifyDispatchedEvents(true, null); @@ -294,13 +266,11 @@ public void testGenericIdentityRequest_whenNoAdId_thenEmptyAdId() throws Excepti public void testGenericIdentityRequest_whenNoAdId_thenAllZerosAdIdTwice() throws Exception { // Test String newAdId = "00000000-0000-0000-0000-000000000000"; - setEdgeIdentityPersistence( - createXDMIdentityMap(new IdentityFunctionalTestUtil.TestItem("ECID", "primaryECID")) - ); + setEdgeIdentityPersistence(createXDMIdentityMap(new TestItem("ECID", "primaryECID"))); registerEdgeIdentityExtension(); MobileCore.setAdvertisingIdentifier(newAdId); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Edge Consent event should not be dispatched; invalid -> invalid does not signal change in consent verifyDispatchedEvents(true, null); @@ -318,10 +288,10 @@ public void testGenericIdentityRequest_whenNoAdId_thenAllZerosAdIdTwice() throws verifyFlatIdentityMap(persistedMap, null); // Reset wildcard listener - TestHelper.resetTestExpectations(); + resetTestExpectations(); // Test all zeros sent again MobileCore.setAdvertisingIdentifier(newAdId); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // Verify dispatched events // Edge Consent event should not be dispatched; invalid -> invalid does not signal change in consent verifyDispatchedEvents(true, null); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java index ea4827ad..b30d4963 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java @@ -11,7 +11,7 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.*; +import static com.adobe.marketing.mobile.edge.identity.util.IdentityFunctionalTestUtil.*; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; import static org.junit.Assert.assertEquals; diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java index 7f57e2a9..9d70c65e 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java @@ -11,7 +11,7 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.*; +import static com.adobe.marketing.mobile.edge.identity.util.IdentityFunctionalTestUtil.*; import static org.junit.Assert.*; import androidx.test.ext.junit.runners.AndroidJUnit4; diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java index bf584920..9278a0c1 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java @@ -11,20 +11,13 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.createIdentityMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.flattenMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.getExperienceCloudIdSync; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.getIdentitiesSync; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.getUrlVariablesSync; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.setupConfiguration; +import static com.adobe.marketing.mobile.edge.identity.util.IdentityFunctionalTestUtil.*; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.*; import static org.junit.Assert.*; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants; -import com.adobe.marketing.mobile.edge.identity.util.TestHelper; import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; import com.adobe.marketing.mobile.util.JSONUtils; import java.util.List; @@ -40,9 +33,7 @@ public class IdentityPublicAPITest { @Rule - public RuleChain rule = RuleChain - .outerRule(new TestHelper.SetupCoreRule()) - .around(new TestHelper.RegisterMonitorExtensionRule()); + public RuleChain rule = RuleChain.outerRule(new SetupCoreRule()).around(new RegisterMonitorExtensionRule()); // -------------------------------------------------------------------------------------------- // Setup @@ -91,7 +82,7 @@ public void testUpdateIdentitiesAPI() throws Exception { Identity.updateIdentities( createIdentityMap("Email", "example@email.com", AuthenticatedState.AUTHENTICATED, true) ); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify xdm shared state Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); @@ -116,7 +107,7 @@ public void testUpdateIdentitiesAPI() throws Exception { public void testUpdateAPI_nullData() throws Exception { // test Identity.updateIdentities(null); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify no shares state change event dispatched List dispatchedEvents = getDispatchedEventsWith( @@ -135,7 +126,7 @@ public void testUpdateAPI_nullData() throws Exception { public void testUpdateAPI_emptyData() throws Exception { // test Identity.updateIdentities(new IdentityMap()); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify no shares state change event dispatched List dispatchedEvents = getDispatchedEventsWith( @@ -160,7 +151,7 @@ public void testUpdateAPI_shouldReplaceExistingIdentities() throws Exception { Identity.updateIdentities( createIdentityMap("Email", "example@email.com", AuthenticatedState.LOGGED_OUT, false) ); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify the final xdm shared state Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); @@ -191,7 +182,7 @@ public void testUpdateAPI_withReservedNamespaces() throws Exception { Identity.updateIdentities(createIdentityMap("gaid", "")); Identity.updateIdentities(createIdentityMap("ecid", "")); Identity.updateIdentities(createIdentityMap("idfa", "")); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify xdm shared state does not get updated Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); @@ -217,7 +208,7 @@ public void testUpdateAPI_multipleNamespaceMap() throws Exception { map.addItem(new IdentityItem("zzzyyyxxx"), "UserId"); map.addItem(new IdentityItem("John Doe"), "UserName"); Identity.updateIdentities(map); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify xdm shared state Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); @@ -247,7 +238,7 @@ public void testUpdateAPI_caseSensitiveNamespacesForCustomIdentifiers() throws E map.addItem(new IdentityItem("primary@email.com"), "Email"); map.addItem(new IdentityItem("secondary@email.com"), "email"); Identity.updateIdentities(map); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify xdm shared state Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); @@ -329,7 +320,7 @@ public void testGetIdentities() { // test Map getIdentitiesResponse = getIdentitiesSync(); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify IdentityMap responseMap = (IdentityMap) getIdentitiesResponse.get( @@ -367,7 +358,7 @@ public void testRemoveIdentity() throws Exception { // test Identity.removeIdentity(new IdentityItem("primary@email.com"), "Email"); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify xdm shared state Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); @@ -376,7 +367,7 @@ public void testRemoveIdentity() throws Exception { // test again Identity.removeIdentity(new IdentityItem("secondary@email.com"), "Email"); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify xdm shared state xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); @@ -395,7 +386,7 @@ public void testRemoveIdentity() throws Exception { public void testRemoveIdentity_nonExistentNamespace() throws Exception { // test Identity.removeIdentity(new IdentityItem("primary@email.com"), "Email"); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify item is not removed // verify xdm shared state @@ -419,7 +410,7 @@ public void testRemoveIdentity_nameSpaceCaseSensitive() throws Exception { // test Identity.removeIdentity(new IdentityItem("example@email.com"), "email"); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify item is not removed // verify xdm shared state @@ -443,7 +434,7 @@ public void testRemoveIdentity_nonExistentItem() throws Exception { // test Identity.removeIdentity(new IdentityItem("secondary@email.com"), "Email"); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // verify item is not removed // verify xdm shared state @@ -466,7 +457,7 @@ public void testRemoveIdentity_doesNotRemoveECID() throws Exception { // attempt to remove ECID Identity.removeIdentity(new IdentityItem(currentECID), "ECID"); - TestHelper.waitForThreads(2000); + waitForThreads(2000); // ECID is a reserved namespace and should not be removed // verify xdm shared state diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java index d51825b5..d223aac7 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java @@ -11,15 +11,12 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.flattenMap; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.getExperienceCloudIdSync; -import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension; +import static com.adobe.marketing.mobile.edge.identity.util.IdentityFunctionalTestUtil.*; import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.*; import static org.junit.Assert.*; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.MobileCore; -import com.adobe.marketing.mobile.edge.identity.util.TestHelper; import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; import com.adobe.marketing.mobile.util.JSONUtils; import java.util.List; @@ -33,9 +30,7 @@ public class IdentityResetHandlingTest { @Rule - public RuleChain rule = RuleChain - .outerRule(new TestHelper.SetupCoreRule()) - .around(new TestHelper.RegisterMonitorExtensionRule()); + public RuleChain rule = RuleChain.outerRule(new SetupCoreRule()).around(new RegisterMonitorExtensionRule()); // -------------------------------------------------------------------------------------------- // Setup diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java similarity index 89% rename from code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java rename to code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java index 66ac4ea2..a0ddd758 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityFunctionalTestUtil.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java @@ -9,11 +9,10 @@ governing permissions and limitations under the License. */ -package com.adobe.marketing.mobile.edge.identity; +package com.adobe.marketing.mobile.edge.identity.util; import static com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants.LOG_TAG; -import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; -import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.resetTestExpectations; +import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -21,11 +20,13 @@ import com.adobe.marketing.mobile.AdobeCallbackWithError; import com.adobe.marketing.mobile.AdobeError; import com.adobe.marketing.mobile.Event; +import com.adobe.marketing.mobile.EventSource; +import com.adobe.marketing.mobile.EventType; import com.adobe.marketing.mobile.MobileCore; -import com.adobe.marketing.mobile.edge.identity.util.ADBCountDownLatch; -import com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants; -import com.adobe.marketing.mobile.edge.identity.util.TestHelper; -import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; +import com.adobe.marketing.mobile.edge.identity.AuthenticatedState; +import com.adobe.marketing.mobile.edge.identity.Identity; +import com.adobe.marketing.mobile.edge.identity.IdentityItem; +import com.adobe.marketing.mobile.edge.identity.IdentityMap; import com.adobe.marketing.mobile.services.Log; import com.adobe.marketing.mobile.util.JSONUtils; import com.fasterxml.jackson.databind.JsonNode; @@ -103,8 +104,8 @@ public static void setupConfiguration() throws Exception { */ public static void setIdentityDirectPersistedECID(final String legacyECID) { TestPersistenceHelper.updatePersistence( - IdentityConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE_NAME, - IdentityConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, + IdentityTestConstants.DataStoreKey.IDENTITY_DIRECT_DATASTORE, + IdentityTestConstants.DataStoreKey.IDENTITY_DIRECT_ECID_KEY, legacyECID ); } @@ -116,8 +117,8 @@ public static void setEdgeIdentityPersistence(final Map persiste if (persistedData != null) { final JSONObject persistedJSON = new JSONObject(persistedData); TestPersistenceHelper.updatePersistence( - IdentityConstants.DataStoreKey.DATASTORE_NAME, - IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES, + IdentityTestConstants.DataStoreKey.IDENTITY_DATASTORE, + IdentityTestConstants.DataStoreKey.IDENTITY_PROPERTIES, persistedJSON.toString() ); } @@ -155,9 +156,9 @@ public static Map createXDMIdentityMap(TestItem... items) { for (TestItem item : items) { final Map itemMap = new HashMap<>(); - itemMap.put(IdentityConstants.XDMKeys.ID, item.id); - itemMap.put(IdentityConstants.XDMKeys.AUTHENTICATED_STATE, "ambiguous"); - itemMap.put(IdentityConstants.XDMKeys.PRIMARY, item.isPrimary); + itemMap.put(IdentityTestConstants.XDMKeys.ID, item.id); + itemMap.put(IdentityTestConstants.XDMKeys.AUTHENTICATED_STATE, "ambiguous"); + itemMap.put(IdentityTestConstants.XDMKeys.PRIMARY, item.isPrimary); List> nameSpaceItems = allItems.get(item.namespace); if (nameSpaceItems == null) { @@ -169,7 +170,7 @@ public static Map createXDMIdentityMap(TestItem... items) { } final Map identityMapDict = new HashMap<>(); - identityMapDict.put(IdentityConstants.XDMKeys.IDENTITY_MAP, allItems); + identityMapDict.put(IdentityTestConstants.XDMKeys.IDENTITY_MAP, allItems); return identityMapDict; } @@ -188,8 +189,8 @@ public static Event buildRemoveIdentityRequestWithJSONString(final String jsonSt public static Event buildRemoveIdentityRequest(final Map map) { return new Event.Builder( "Remove Identity Event", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REMOVE_IDENTITY + EventType.EDGE_IDENTITY, + "om.adobe.eventSource.updateIdentity" ) .setEventData(map) .build(); @@ -208,11 +209,7 @@ public static Event buildUpdateIdentityRequestJSONString(final String jsonStr) t * Helper method to build update identity request event with XDM formatted Identity map */ public static Event buildUpdateIdentityRequest(final Map map) { - return new Event.Builder( - "Update Identity Event", - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.UPDATE_IDENTITY - ) + return new Event.Builder("Update Identity Event", EventType.EDGE_IDENTITY, EventSource.UPDATE_IDENTITY) .setEventData(map) .build(); } @@ -417,7 +414,9 @@ public static void verifyPrimaryECIDNotNull() throws InterruptedException { assertNotNull(ecid); // verify xdm shared state is has ECID - Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); + Map xdmSharedState = flattenMap( + getXDMSharedStateFor(IdentityTestConstants.EXTENSION_NAME, 1000) + ); assertNotNull(xdmSharedState.get("identityMap.ECID[0].id")); } @@ -430,13 +429,15 @@ public static void verifyPrimaryECID(final String primaryECID) throws Exception assertEquals(primaryECID, ecid); // verify xdm shared state is has correct primary ECID - Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); + Map xdmSharedState = flattenMap( + getXDMSharedStateFor(IdentityTestConstants.EXTENSION_NAME, 1000) + ); assertEquals(primaryECID, xdmSharedState.get("identityMap.ECID[0].id")); // verify primary ECID in persistence final String persistedJson = TestPersistenceHelper.readPersistedData( - IdentityConstants.DataStoreKey.DATASTORE_NAME, - IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES + IdentityTestConstants.DataStoreKey.IDENTITY_DATASTORE, + IdentityTestConstants.DataStoreKey.IDENTITY_PROPERTIES ); Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(primaryECID, persistedMap.get("identityMap.ECID[0].id")); @@ -448,13 +449,15 @@ public static void verifyPrimaryECID(final String primaryECID) throws Exception */ public static void verifySecondaryECID(final String secondaryECID) throws Exception { // verify xdm shared state is has correct secondary ECID - Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); + Map xdmSharedState = flattenMap( + getXDMSharedStateFor(IdentityTestConstants.EXTENSION_NAME, 1000) + ); assertEquals(secondaryECID, xdmSharedState.get("identityMap.ECID[1].id")); // verify secondary ECID in persistence final String persistedJson = TestPersistenceHelper.readPersistedData( - IdentityConstants.DataStoreKey.DATASTORE_NAME, - IdentityConstants.DataStoreKey.IDENTITY_PROPERTIES + IdentityTestConstants.DataStoreKey.IDENTITY_DATASTORE, + IdentityTestConstants.DataStoreKey.IDENTITY_PROPERTIES ); Map persistedMap = flattenMap(JSONUtils.toMap(new JSONObject(persistedJson))); assertEquals(secondaryECID, persistedMap.get("identityMap.ECID[1].id")); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityTestConstants.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityTestConstants.java index 9e6cffc5..1a414924 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityTestConstants.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityTestConstants.java @@ -14,12 +14,15 @@ public class IdentityTestConstants { public static final String LOG_TAG = "EdgeIdentity"; + static final String EXTENSION_NAME = "com.adobe.edge.identity"; - public static final class DataStoreKey { + static final class DataStoreKey { - public static final String CONFIG_DATASTORE = "AdobeMobile_ConfigState"; - public static final String IDENTITY_DATASTORE = "com.adobe.edge.identity"; + static final String CONFIG_DATASTORE = "AdobeMobile_ConfigState"; + static final String IDENTITY_DATASTORE = "com.adobe.edge.identity"; public static final String IDENTITY_DIRECT_DATASTORE = "visitorIDServiceDataStore"; + public static final String IDENTITY_DIRECT_ECID_KEY = "ADOBEMOBILE_PERSISTED_MID"; + public static final String IDENTITY_PROPERTIES = "identity.properties"; private DataStoreKey() {} } @@ -39,4 +42,40 @@ public static final class GetIdentitiesHelper { private GetIdentitiesHelper() {} } + + public static class EventType { + + static final String MONITOR = "com.adobe.functional.eventType.monitor"; + + private EventType() {} + } + + public static class EventSource { + + // Used by Monitor Extension + static final String XDM_SHARED_STATE_REQUEST = "com.adobe.eventSource.xdmsharedStateRequest"; + static final String XDM_SHARED_STATE_RESPONSE = "com.adobe.eventSource.xdmsharedStateResponse"; + static final String SHARED_STATE_REQUEST = "com.adobe.eventSource.sharedStateRequest"; + static final String SHARED_STATE_RESPONSE = "com.adobe.eventSource.sharedStateResponse"; + static final String UNREGISTER = "com.adobe.eventSource.unregister"; + + private EventSource() {} + } + + public static class EventDataKey { + + static final String STATE_OWNER = "stateowner"; + + private EventDataKey() {} + } + + static final class XDMKeys { + + static final String IDENTITY_MAP = "identityMap"; + static final String ID = "id"; + static final String AUTHENTICATED_STATE = "authenticatedState"; + static final String PRIMARY = "primary"; + + private XDMKeys() {} + } } diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java index 9a4d95e9..372591db 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java @@ -83,8 +83,8 @@ public void error(ExtensionError extensionError) { public static void unregisterExtension() { Event event = new Event.Builder( "Unregister Monitor Extension Request", - TestConstants.EventType.MONITOR, - TestConstants.EventSource.UNREGISTER + IdentityTestConstants.EventType.MONITOR, + IdentityTestConstants.EventSource.UNREGISTER ) .build(); MobileCore.dispatchEvent(event); @@ -128,12 +128,12 @@ public static void reset() { * @param event the event to be processed */ public void wildcardProcessor(final Event event) { - if (TestConstants.EventType.MONITOR.equalsIgnoreCase(event.getType())) { - if (TestConstants.EventSource.SHARED_STATE_REQUEST.equalsIgnoreCase(event.getSource())) { + if (IdentityTestConstants.EventType.MONITOR.equalsIgnoreCase(event.getType())) { + if (IdentityTestConstants.EventSource.SHARED_STATE_REQUEST.equalsIgnoreCase(event.getSource())) { processSharedStateRequest(event); - } else if (TestConstants.EventSource.XDM_SHARED_STATE_REQUEST.equalsIgnoreCase(event.getSource())) { + } else if (IdentityTestConstants.EventSource.XDM_SHARED_STATE_REQUEST.equalsIgnoreCase(event.getSource())) { processXDMSharedStateRequest(event); - } else if (TestConstants.EventSource.UNREGISTER.equalsIgnoreCase(event.getSource())) { + } else if (IdentityTestConstants.EventSource.UNREGISTER.equalsIgnoreCase(event.getSource())) { processUnregisterRequest(event); } @@ -176,7 +176,7 @@ private void processXDMSharedStateRequest(final Event event) { return; } - final String stateOwner = DataReader.optString(eventData, TestConstants.EventDataKey.STATE_OWNER, null); + final String stateOwner = DataReader.optString(eventData, IdentityTestConstants.EventDataKey.STATE_OWNER, null); if (stateOwner == null) { return; @@ -187,8 +187,8 @@ private void processXDMSharedStateRequest(final Event event) { Event responseEvent = new Event.Builder( "Get Shared State Response", - TestConstants.EventType.MONITOR, - TestConstants.EventSource.XDM_SHARED_STATE_RESPONSE + IdentityTestConstants.EventType.MONITOR, + IdentityTestConstants.EventSource.XDM_SHARED_STATE_RESPONSE ) .setEventData(sharedStateResult == null ? null : sharedStateResult.getValue()) .inResponseToEvent(event) @@ -209,7 +209,7 @@ private void processSharedStateRequest(final Event event) { return; } - final String stateOwner = DataReader.optString(eventData, TestConstants.EventDataKey.STATE_OWNER, null); + final String stateOwner = DataReader.optString(eventData, IdentityTestConstants.EventDataKey.STATE_OWNER, null); if (stateOwner == null) { return; @@ -220,8 +220,8 @@ private void processSharedStateRequest(final Event event) { Event responseEvent = new Event.Builder( "Get Shared State Response", - TestConstants.EventType.MONITOR, - TestConstants.EventSource.SHARED_STATE_RESPONSE + IdentityTestConstants.EventType.MONITOR, + IdentityTestConstants.EventSource.SHARED_STATE_RESPONSE ) .setEventData(sharedStateResult == null ? null : sharedStateResult.getValue()) .inResponseToEvent(event) diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestConstants.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestConstants.java deleted file mode 100644 index 69045499..00000000 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestConstants.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity.util; - -/** - * Class to maintain test constants. - */ -public class TestConstants { - - public class EventType { - - static final String MONITOR = "com.adobe.functional.eventType.monitor"; - - private EventType() {} - } - - public class EventSource { - - // Used by Monitor Extension - static final String XDM_SHARED_STATE_REQUEST = "com.adobe.eventSource.xdmsharedStateRequest"; - static final String XDM_SHARED_STATE_RESPONSE = "com.adobe.eventSource.xdmsharedStateResponse"; - static final String SHARED_STATE_REQUEST = "com.adobe.eventSource.sharedStateRequest"; - static final String SHARED_STATE_RESPONSE = "com.adobe.eventSource.sharedStateResponse"; - static final String UNREGISTER = "com.adobe.eventSource.unregister"; - - private EventSource() {} - } - - public class EventDataKey { - - static final String STATE_OWNER = "stateowner"; - - private EventDataKey() {} - } -} diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java index 1e8c5b5f..d7f6ca4d 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java @@ -454,13 +454,13 @@ public static Map getSharedStateFor(final String stateOwner, int throws InterruptedException { Event event = new Event.Builder( "Get Shared State Request", - TestConstants.EventType.MONITOR, - TestConstants.EventSource.SHARED_STATE_REQUEST + IdentityTestConstants.EventType.MONITOR, + IdentityTestConstants.EventSource.SHARED_STATE_REQUEST ) .setEventData( new HashMap() { { - put(TestConstants.EventDataKey.STATE_OWNER, stateOwner); + put(IdentityTestConstants.EventDataKey.STATE_OWNER, stateOwner); } } ) @@ -505,13 +505,13 @@ public static Map getXDMSharedStateFor(final String stateOwner, throws InterruptedException { Event event = new Event.Builder( "Get Shared State Request", - TestConstants.EventType.MONITOR, - TestConstants.EventSource.XDM_SHARED_STATE_REQUEST + IdentityTestConstants.EventType.MONITOR, + IdentityTestConstants.EventSource.XDM_SHARED_STATE_REQUEST ) .setEventData( new HashMap() { { - put(TestConstants.EventDataKey.STATE_OWNER, stateOwner); + put(IdentityTestConstants.EventDataKey.STATE_OWNER, stateOwner); } } ) diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java index 59d19029..2b0b3ff8 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java @@ -399,19 +399,25 @@ public void testResetIdentifiers() { state.getIdentityProperties().setAdId("adID"); final ECID existingEcid = state.getIdentityProperties().getECID(); - // test - state.resetIdentifiers(); - - // verify - assertNotEquals(existingEcid, state.getIdentityProperties().getECID()); // ECID should be regenerated - assertFalse(state.getIdentityProperties().getECID().toString().isEmpty()); // ECID should not be empty - assertNull(state.getIdentityProperties().getECIDSecondary()); // should be cleared - assertNull(state.getIdentityProperties().getAdId()); // should be cleared - verify(mockIdentityStorageManager, times(1)).savePropertiesToPersistence(state.getIdentityProperties()); // should save to data store - // Verify consent event not sent (or any event). Consent should not be dispatched by resetIdentifiers - - // PowerMockito.verifyStatic(MobileCore.class, Mockito.never()); - // MobileCore.dispatchEvent(any(Event.class), any(ExtensionErrorCallback.class)); + try (MockedStatic mockedStaticCore = Mockito.mockStatic(MobileCore.class)) { + // test + state.resetIdentifiers(); + + // verify + assertNotEquals(existingEcid, state.getIdentityProperties().getECID()); // ECID should be regenerated + assertFalse(state.getIdentityProperties().getECID().toString().isEmpty()); // ECID should not be empty + assertNull(state.getIdentityProperties().getECIDSecondary()); // should be cleared + assertNull(state.getIdentityProperties().getAdId()); // should be cleared + verify(mockIdentityStorageManager, times(1)).savePropertiesToPersistence(state.getIdentityProperties()); // should save to data store + + // Verify consent event not sent (or any event). Consent should not be dispatched by resetIdentifiers + mockedStaticCore.verify( + () -> { + MobileCore.dispatchEvent(any()); + }, + never() + ); + } } // ====================================================================================================================== diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTests.java index 130c1050..bd2aa37f 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTests.java @@ -87,7 +87,7 @@ public void testRegistration() { // verify that the callback invocation does not throw an exception extensionErrorCallback.error(ExtensionError.UNEXPECTED_ERROR); } catch (final Exception e) { - fail(); + fail(e.getMessage()); } } @@ -139,7 +139,7 @@ public void testGetExperienceCloudId() { adobeCallbackCaptor.getValue().call(buildIdentityResponseEvent(xdmData)); assertEquals(ecid.toString(), callbackReturnValues.get(0)); } catch (Exception e) { - fail(); + fail(e.getMessage()); } } @@ -177,7 +177,7 @@ public void call(String ecid) {} ) ); } catch (Exception e) { - fail(); + fail(e.getMessage()); } // set response event to null @@ -204,6 +204,8 @@ public void testGetExperienceCloudId_nullCallback() { ), times(0) ); + } catch (Exception e) { + fail(e.getMessage()); } } @@ -241,7 +243,7 @@ public void call(String ecid) {} ) ); } catch (Exception e) { - fail(); + fail(e.getMessage()); } // set response event to null @@ -284,7 +286,7 @@ public void call(String ecid) {} ) ); } catch (Exception e) { - fail(); + fail(e.getMessage()); } // set response event to null @@ -330,6 +332,8 @@ public void call(Object o) {} adobeCallbackCaptor.capture() ) ); + } catch (Exception e) { + fail(e.getMessage()); } // set response event to map missing ECID @@ -372,7 +376,7 @@ public void call(String s) { ) ); } catch (Exception e) { - fail(); + fail(e.getMessage()); } // verify the dispatched event details @@ -406,6 +410,8 @@ public void testGetUrlVariables_nullCallback() { ), never() ); + } catch (Exception e) { + fail(e.getMessage()); } } @@ -442,7 +448,7 @@ public void call(String o) {} ) ); } catch (Exception e) { - fail(); + fail(e.getMessage()); } final Event dispatchedEvent = eventCaptor.getValue(); @@ -493,7 +499,7 @@ public void call(String o) {} ) ); } catch (Exception e) { - fail(); + fail(e.getMessage()); } // set response event data to not have urlvariables key @@ -540,7 +546,7 @@ public void call(String o) {} ) ); } catch (Exception e) { - fail(); + fail(e.getMessage()); } // set response event to have urlvariables map to null value @@ -585,8 +591,9 @@ public void call(String o) {} ) ); } catch (Exception e) { - fail(); + fail(e.getMessage()); } + adobeCallbackCaptor.getValue().fail(AdobeError.UNEXPECTED_ERROR); // verify @@ -611,7 +618,7 @@ public void testUpdateIdentities() { mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(eventCaptor.capture())); } catch (Exception e) { - fail(); + fail(e.getMessage()); } // verify the dispatched event details @@ -631,6 +638,8 @@ public void testUpdateIdentitiesNullMap() { // verify that no event is dispatched mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(any(Event.class)), never()); + } catch (Exception e) { + fail(e.getMessage()); } } @@ -643,6 +652,8 @@ public void testUpdateIdentities_EmptyMap() { // verify that no event is dispatched mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(any(Event.class)), never()); + } catch (Exception e) { + fail(e.getMessage()); } } @@ -661,6 +672,8 @@ public void testRemoveIdentity() { Identity.removeIdentity(sampleItem, "namespace"); mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(eventCaptor.capture())); + } catch (Exception e) { + fail(e.getMessage()); } final Event dispatchedEvent = eventCaptor.getValue(); @@ -686,6 +699,8 @@ public void testRemoveIdentity_WithInvalidInputs() { // verify that no event is dispatched mockedStaticMobileCore.verify(() -> MobileCore.dispatchEvent(any(Event.class)), never()); + } catch (Exception e) { + fail(e.getMessage()); } } @@ -719,6 +734,8 @@ public void call(IdentityMap map) { adobeCallbackCaptor.capture() ) ); + } catch (Exception e) { + fail(e.getMessage()); } // verify the dispatched event details @@ -787,6 +804,8 @@ public void testGetIdentities_nullCallback() { ), never() ); + } catch (Exception e) { + fail(e.getMessage()); } } @@ -822,6 +841,8 @@ public void call(Object o) {} adobeCallbackCaptor.capture() ) ); + } catch (Exception e) { + fail(e.getMessage()); } // set response event to null @@ -864,7 +885,10 @@ public void call(Object o) {} adobeCallbackCaptor.capture() ) ); + } catch (Exception e) { + fail(e.getMessage()); } + // set response event Map eventData = new HashMap<>(); eventData.put("someKey", "someValue"); @@ -907,7 +931,10 @@ public void call(Object o) {} adobeCallbackCaptor.capture() ) ); + } catch (Exception e) { + fail(e.getMessage()); } + // set response event with empty data Map eventData = new HashMap<>(); adobeCallbackCaptor.getValue().call(buildIdentityResponseEvent(eventData)); @@ -949,7 +976,10 @@ public void call(Object o) {} adobeCallbackCaptor.capture() ) ); + } catch (Exception e) { + fail(e.getMessage()); } + // set response event with empty data adobeCallbackCaptor.getValue().fail(AdobeError.UNEXPECTED_ERROR); From adca97d9e74c2f9185121435d48f54c9f1353816 Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Tue, 13 Dec 2022 10:56:22 -0800 Subject: [PATCH 05/13] Fix unit test imports --- .../marketing/mobile/edge/identity/ECIDTests.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java index 2dbee4f4..d4002cb0 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java @@ -111,12 +111,12 @@ public void testECID_equals() { ECID a = new ECID(); ECID b = new ECID(a.toString()); - Assert.assertEquals(a, b); - Assert.assertEquals(b, a); - Assert.assertEquals(a, a); - Assert.assertEquals(b, b); + assertEquals(a, b); + assertEquals(b, a); + assertEquals(a, a); + assertEquals(b, b); - Assert.assertNotNull(a); + assertNotNull(a); assertNotEquals(a, new ECID()); assertNotEquals(a, new NotECID(a.toString())); From fb12862b36e82607212b0bdfed954d957adc54c8 Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Tue, 13 Dec 2022 11:14:22 -0800 Subject: [PATCH 06/13] Fix incorrect constant --- .../mobile/edge/identity/util/IdentityFunctionalTestUtil.java | 3 ++- .../com/adobe/marketing/mobile/edge/identity/ECIDTests.java | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java index a0ddd758..462ddf3b 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java @@ -190,7 +190,8 @@ public static Event buildRemoveIdentityRequest(final Map map) { return new Event.Builder( "Remove Identity Event", EventType.EDGE_IDENTITY, - "om.adobe.eventSource.updateIdentity" + // TODO: Use event source from Core when available. + "com.adobe.eventSource.removeIdentity" ) .setEventData(map) .build(); diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java index d4002cb0..37b31b23 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/ECIDTests.java @@ -20,7 +20,6 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.junit.Assert; import org.junit.Test; public class ECIDTests { From c6a4e73980a8cfaf87e3259722403b6f2949e90a Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Tue, 13 Dec 2022 15:30:25 -0800 Subject: [PATCH 07/13] Rename state based unit tests --- code/build.gradle | 2 +- code/edgeidentity/build.gradle | 2 +- .../com/adobe/marketing/mobile/MobileCoreHelper.java | 4 ++-- .../mobile/edge/identity/util/TestHelper.java | 5 +++-- .../mobile/edge/identity/IdentityStateTests.java | 12 ++++++------ 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/code/build.gradle b/code/build.gradle index 56c90130..7c3df82e 100644 --- a/code/build.gradle +++ b/code/build.gradle @@ -24,7 +24,7 @@ ext { // test dependencies junitVersion = "1.1.3" - mockitoCoreVersion = "4.5.1" + mockitoVersion = "4.5.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" // spotless diff --git a/code/edgeidentity/build.gradle b/code/edgeidentity/build.gradle index 4e8529fc..a1de1d16 100644 --- a/code/edgeidentity/build.gradle +++ b/code/edgeidentity/build.gradle @@ -227,7 +227,7 @@ dependencies { implementation 'androidx.annotation:annotation:1.3.0' testImplementation "androidx.test.ext:junit:${rootProject.ext.junitVersion}" - testImplementation "org.mockito:mockito-core:${rootProject.ext.mockitoCoreVersion}" + testImplementation "org.mockito:mockito-core:${rootProject.ext.mockitoVersion}" testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.9.9' testImplementation 'org.json:json:20180813' diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MobileCoreHelper.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MobileCoreHelper.java index c34a117c..e333522f 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MobileCoreHelper.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/MobileCoreHelper.java @@ -12,8 +12,8 @@ package com.adobe.marketing.mobile; /** - * Helper class that exists as a to access test helper methods provided in core - * within the package com.adobe.marketing.mobile + * Helper class that exists as a way to access test helper methods provided in core + * within the package com.adobe.marketing.mobile */ public class MobileCoreHelper { diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java index d7f6ca4d..52fd466e 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java @@ -49,6 +49,7 @@ public class TestHelper { private static final String LOG_SOURCE = "TestHelper"; static final int WAIT_TIMEOUT_MS = 1000; static final int WAIT_EVENT_TIMEOUT_MS = 2000; + static final long WAIT_SHARED_STATE_MS = 5000; static Application defaultApplication; // List of threads to wait for after test execution @@ -470,7 +471,7 @@ public static Map getSharedStateFor(final String stateOwner, int final Map sharedState = new HashMap<>(); MobileCore.dispatchEventWithResponseCallback( event, - 5000L, + WAIT_SHARED_STATE_MS, new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { @@ -521,7 +522,7 @@ public static Map getXDMSharedStateFor(final String stateOwner, final Map sharedState = new HashMap<>(); MobileCore.dispatchEventWithResponseCallback( event, - 5000L, + WAIT_SHARED_STATE_MS, new AdobeCallbackWithError() { @Override public void fail(AdobeError adobeError) { diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java index 2b0b3ff8..ea5b44e4 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityStateTests.java @@ -96,7 +96,7 @@ public void testBootUpIfReady_waitsForHubSharedState_hubStateIsNull() { } @Test - public void testBootUpIfReady_waitsForHubSharedState_hubStateIsPending() { + public void testBootUpIfReady_waitsForHubSharedState_hubStateStatusIsPending() { final IdentityState identityState = new IdentityState(mockIdentityStorageManager); when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) .thenReturn(new SharedStateResult(SharedStateStatus.PENDING, Collections.EMPTY_MAP)); @@ -105,7 +105,7 @@ public void testBootUpIfReady_waitsForHubSharedState_hubStateIsPending() { } @Test - public void testBootUpIfReady_waitsForHubSharedState_hubStateIsSet() { + public void testBootUpIfReady_waitsForHubSharedState_hubStateStatusIsSet() { final IdentityState identityState = new IdentityState(mockIdentityStorageManager); when(mockSharedStateCallback.getSharedState(IdentityConstants.SharedState.Hub.NAME, null)) .thenReturn(new SharedStateResult(SharedStateStatus.SET, Collections.EMPTY_MAP)); @@ -209,7 +209,7 @@ public void testBootUpIfReady_prefersPersistedIdentityDirectEcidOverFetchingFrom } @Test - public void testBootUpIfReady_waitsForIdentityDirectStateIfRegistered_stateIsNone() { + public void testBootUpIfReady_waitsForIdentityDirectStateIfRegistered_stateStatusIsNone() { final IdentityState identityState = new IdentityState(mockIdentityStorageManager); final Map hubSharedState = new HashMap<>(); hubSharedState.put( @@ -241,7 +241,7 @@ public void testBootUpIfReady_waitsForIdentityDirectStateIfRegistered_stateIsNon } @Test - public void testBootUpIfReady_waitsForIdentityDirectStateIfRegistered_stateIsPending() { + public void testBootUpIfReady_waitsForIdentityDirectStateIfRegistered() { final IdentityState identityState = new IdentityState(mockIdentityStorageManager); final Map hubSharedState = new HashMap<>(); hubSharedState.put( @@ -273,7 +273,7 @@ public void testBootUpIfReady_waitsForIdentityDirectStateIfRegistered_stateIsPen } @Test - public void testBootUpIfReady_waitsForPendingIdentityDirectStateIfRegistered_stateIsNull() { + public void testBootUpIfReady_waitsForPendingIdentityDirectStateIfRegistered() { final IdentityState identityState = new IdentityState(mockIdentityStorageManager); final Map hubSharedState = new HashMap<>(); hubSharedState.put( @@ -338,7 +338,7 @@ public void testBootUpIfReady_regeneratesECIDWhenIdentityDirectStateECIDIsNull() } @Test - public void testBootUpIfReady_generatesNewECIDWhenDirectStateAndPersistedStateUnavailable() { + public void testBootUpIfReady_generatesNewECIDWhenDirectStateAndPersistedStateAreUnavailable() { // No persisted properties final IdentityProperties persistedProperties = new IdentityProperties(); when(mockIdentityStorageManager.loadPropertiesFromPersistence()).thenReturn(persistedProperties); From 35b4dbdeaa567465489eb43cbc1fdc7a29c98b67 Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Tue, 13 Dec 2022 17:27:32 -0800 Subject: [PATCH 08/13] Move IdentityTestUtil out of sharedutils --- .../adobe/marketing/mobile/edge/identity/IdentityTestUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename code/edgeidentity/src/{sharedTestUtils => test}/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java (99%) diff --git a/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java similarity index 99% rename from code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java rename to code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java index 59a97a99..dddc94b8 100644 --- a/code/edgeidentity/src/sharedTestUtils/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/IdentityTestUtil.java @@ -1,5 +1,5 @@ /* - Copyright 2021 Adobe. All rights reserved. + Copyright 2022 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 From 5a8d17aaceb73eda83033a58b010d77de80ce079 Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Wed, 14 Dec 2022 09:29:33 -0800 Subject: [PATCH 09/13] Switch to new registration for MoitorExtension and fix test rules --- .../edge/identity/IdentityAdIdTest.java | 24 +++--- .../edge/identity/IdentityBootUpTest.java | 11 +-- .../identity/IdentityECIDHandlingTest.java | 75 +++++++++++++++---- .../edge/identity/IdentityPublicAPITest.java | 8 +- .../identity/IdentityResetHandlingTest.java | 8 +- .../util/IdentityFunctionalTestUtil.java | 44 ++++------- .../edge/identity/util/MonitorExtension.java | 18 ----- .../mobile/edge/identity/util/TestHelper.java | 31 -------- 8 files changed, 106 insertions(+), 113 deletions(-) diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java index 332ce3d5..2a0a0367 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityAdIdTest.java @@ -19,21 +19,23 @@ import androidx.annotation.Nullable; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.edge.identity.util.MonitorExtension; import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; import com.adobe.marketing.mobile.util.JSONUtils; import com.adobe.marketing.mobile.util.StringUtils; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.json.JSONObject; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; public class IdentityAdIdTest { @Rule - public RuleChain rule = RuleChain.outerRule(new SetupCoreRule()).around(new RegisterMonitorExtensionRule()); + public TestRule rule = new SetupCoreRule(); @Test public void testGenericIdentityRequest_whenValidAdId_thenNewValidAdId() throws Exception { @@ -45,7 +47,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenNewValidAdId() throws E createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); MobileCore.setAdvertisingIdentifier(newAdId); // After sending mobile core event, give a wait time to allow for processing @@ -74,7 +76,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenNonAdId() throws Except setEdgeIdentityPersistence( createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); dispatchGenericIdentityNonAdIdEvent(); @@ -104,7 +106,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenSameValidAdId() throws setEdgeIdentityPersistence( createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); MobileCore.setAdvertisingIdentifier(newAdId); waitForThreads(2000); @@ -133,7 +135,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenEmptyAdId() throws Exce setEdgeIdentityPersistence( createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); MobileCore.setAdvertisingIdentifier(newAdId); waitForThreads(2000); @@ -162,7 +164,7 @@ public void testGenericIdentityRequest_whenValidAdId_thenAllZerosAdId() throws E setEdgeIdentityPersistence( createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("GAID", initialAdId)) ); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); MobileCore.setAdvertisingIdentifier(newAdId); waitForThreads(2000); @@ -188,7 +190,7 @@ public void testGenericIdentityRequest_whenNoAdId_thenNewValidAdId() throws Exce // Test String newAdId = "8d9ca5ff-7e74-44ac-bbcd-7aee7baf4f6c"; setEdgeIdentityPersistence(createXDMIdentityMap(new TestItem("ECID", "primaryECID"))); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); MobileCore.setAdvertisingIdentifier(newAdId); waitForThreads(2000); @@ -214,7 +216,7 @@ public void testGenericIdentityRequest_whenNoAdId_thenNewValidAdId() throws Exce public void testGenericIdentityRequest_whenNoAdId_thenNonAdId() throws Exception { // Test setEdgeIdentityPersistence(createXDMIdentityMap(new TestItem("ECID", "primaryECID"))); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); dispatchGenericIdentityNonAdIdEvent(); @@ -241,7 +243,7 @@ public void testGenericIdentityRequest_whenNoAdId_thenEmptyAdId() throws Excepti // Test String newAdId = ""; setEdgeIdentityPersistence(createXDMIdentityMap(new TestItem("ECID", "primaryECID"))); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); MobileCore.setAdvertisingIdentifier(newAdId); waitForThreads(2000); @@ -267,7 +269,7 @@ public void testGenericIdentityRequest_whenNoAdId_thenAllZerosAdIdTwice() throws // Test String newAdId = "00000000-0000-0000-0000-000000000000"; setEdgeIdentityPersistence(createXDMIdentityMap(new TestItem("ECID", "primaryECID"))); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); MobileCore.setAdvertisingIdentifier(newAdId); waitForThreads(2000); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java index b30d4963..eaee7d20 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityBootUpTest.java @@ -15,21 +15,21 @@ import static com.adobe.marketing.mobile.edge.identity.util.TestHelper.getXDMSharedStateFor; import static org.junit.Assert.assertEquals; +import com.adobe.marketing.mobile.edge.identity.util.MonitorExtension; import com.adobe.marketing.mobile.edge.identity.util.TestHelper; import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; import com.adobe.marketing.mobile.util.JSONUtils; +import java.util.Arrays; import java.util.Map; import org.json.JSONObject; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; public class IdentityBootUpTest { @Rule - public RuleChain rule = RuleChain - .outerRule(new TestHelper.SetupCoreRule()) - .around(new TestHelper.RegisterMonitorExtensionRule()); + public TestRule rule = new TestHelper.SetupCoreRule(); // -------------------------------------------------------------------------------------------- // OnBootUp @@ -46,7 +46,8 @@ public void testOnBootUp_LoadsAllIdentitiesFromPreference() throws Exception { new TestItem("UserId", "JohnDoe") ) ); - registerEdgeIdentityExtension(); + + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); // verify xdm shared state Map xdmSharedState = flattenMap(getXDMSharedStateFor(IdentityConstants.EXTENSION_NAME, 1000)); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java index 9d70c65e..d17e1f9e 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityECIDHandlingTest.java @@ -17,24 +17,33 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.adobe.marketing.mobile.MobileCore; import com.adobe.marketing.mobile.MobilePrivacyStatus; +import com.adobe.marketing.mobile.edge.identity.util.MonitorExtension; import com.adobe.marketing.mobile.edge.identity.util.TestHelper; +import java.util.Arrays; +import java.util.HashMap; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class IdentityECIDHandlingTest { @Rule - public RuleChain rule = RuleChain - .outerRule(new TestHelper.SetupCoreRule()) - .around(new TestHelper.RegisterMonitorExtensionRule()); + public TestRule rule = new TestHelper.SetupCoreRule(); + + private static final HashMap TEST_CONFIG = new HashMap() { + { + put("global.privacy", "optedin"); + put("experienceCloud.org", "testOrg@AdobeOrg"); + put("experienceCloud.server", "notaserver"); + } + }; @Test public void testECID_autoGeneratedWhenBooted() throws InterruptedException { // setup - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); // verify ECID is not null verifyPrimaryECIDNotNull(); @@ -46,7 +55,7 @@ public void testECID_loadedFromPersistence() throws Exception { setEdgeIdentityPersistence( createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("ECID", "secondaryECID")) ); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); // verify verifyPrimaryECID("primaryECID"); @@ -58,7 +67,7 @@ public void testECID_edgePersistenceTakesPreferenceOverDirectExtension() throws // setup setIdentityDirectPersistedECID("legacyECID"); setEdgeIdentityPersistence(createIdentityMap("ECID", "edgeECID").asXDMMap()); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); // verify verifyPrimaryECID("edgeECID"); @@ -70,7 +79,7 @@ public void testECID_loadsIdentityDirectECID() throws Exception { // This will happen when EdgeIdentity extension is installed after Identity direct extension // setup setIdentityDirectPersistedECID("legacyECID"); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); // verify verifyPrimaryECID("legacyECID"); @@ -79,7 +88,14 @@ public void testECID_loadsIdentityDirectECID() throws Exception { @Test public void testECID_whenBothExtensionRegistered_install() throws Exception { // setup - registerBothIdentityExtensions(); // no ECID exists before this step + registerExtensions( + Arrays.asList( + MonitorExtension.EXTENSION, + Identity.EXTENSION, + com.adobe.marketing.mobile.Identity.EXTENSION + ), + TEST_CONFIG + ); // no ECID exists before this step String directECID = getIdentityDirectECIDSync(); String edgeECID = getExperienceCloudIdSync(); @@ -95,7 +111,14 @@ public void testECID_whenBothExtensionRegistered_migrationPath() throws Exceptio // setup String existingECID = "legacyECID"; setIdentityDirectPersistedECID(existingECID); - registerBothIdentityExtensions(); + registerExtensions( + Arrays.asList( + MonitorExtension.EXTENSION, + Identity.EXTENSION, + com.adobe.marketing.mobile.Identity.EXTENSION + ), + TEST_CONFIG + ); String directECID = getIdentityDirectECIDSync(); String edgeECID = getExperienceCloudIdSync(); @@ -113,7 +136,7 @@ public void testECID_onResetClearsOldECID() throws Exception { setEdgeIdentityPersistence( createXDMIdentityMap(new TestItem("ECID", "primaryECID"), new TestItem("ECID", "secondaryECID")) ); - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); // test MobileCore.resetIdentities(); @@ -130,7 +153,14 @@ public void testECID_onResetClearsOldECID() throws Exception { public void testECID_AreDifferentAfterPrivacyChange() throws Exception { /// Test Edge Identity and IdentityDirect have same ECID on bootup, and after privacy change ECIDs are different setIdentityDirectPersistedECID("legacyECID"); - registerBothIdentityExtensions(); + registerExtensions( + Arrays.asList( + MonitorExtension.EXTENSION, + Identity.EXTENSION, + com.adobe.marketing.mobile.Identity.EXTENSION + ), + TEST_CONFIG + ); TestHelper.waitForThreads(2000); // verify ECID for both extensions are same @@ -154,7 +184,16 @@ public void testECID_AreDifferentAfterResetIdentitiesAndPrivacyChange() throws E // 1) Register Identity then Edge Identity and verify both have same ECID setIdentityDirectPersistedECID("legacyECID"); - registerBothIdentityExtensions(); + + registerExtensions( + Arrays.asList( + MonitorExtension.EXTENSION, + Identity.EXTENSION, + com.adobe.marketing.mobile.Identity.EXTENSION + ), + TEST_CONFIG + ); + TestHelper.waitForThreads(2000); // verify ECID for both extensions are same @@ -179,7 +218,15 @@ public void testECID_DirectEcidIsRemovedOnPrivacyOptOut() throws Exception { // setup setIdentityDirectPersistedECID("legacyECID"); setEdgeIdentityPersistence(createIdentityMap("ECID", "edgeECID").asXDMMap()); - registerBothIdentityExtensions(); + + registerExtensions( + Arrays.asList( + MonitorExtension.EXTENSION, + Identity.EXTENSION, + com.adobe.marketing.mobile.Identity.EXTENSION + ), + TEST_CONFIG + ); // verify ECID verifyPrimaryECID("edgeECID"); diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java index 9278a0c1..6af5dce6 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityPublicAPITest.java @@ -18,22 +18,24 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants; +import com.adobe.marketing.mobile.edge.identity.util.MonitorExtension; import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; import com.adobe.marketing.mobile.util.JSONUtils; +import java.util.Arrays; import java.util.List; import java.util.Map; import org.json.JSONObject; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class IdentityPublicAPITest { @Rule - public RuleChain rule = RuleChain.outerRule(new SetupCoreRule()).around(new RegisterMonitorExtensionRule()); + public TestRule rule = new SetupCoreRule(); // -------------------------------------------------------------------------------------------- // Setup @@ -41,7 +43,7 @@ public class IdentityPublicAPITest { @Before public void setup() throws Exception { - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); } // -------------------------------------------------------------------------------------------- diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java index d223aac7..6068fe47 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/IdentityResetHandlingTest.java @@ -17,20 +17,22 @@ import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.edge.identity.util.MonitorExtension; import com.adobe.marketing.mobile.edge.identity.util.TestPersistenceHelper; import com.adobe.marketing.mobile.util.JSONUtils; +import java.util.Arrays; import java.util.List; import java.util.Map; import org.json.JSONObject; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; public class IdentityResetHandlingTest { @Rule - public RuleChain rule = RuleChain.outerRule(new SetupCoreRule()).around(new RegisterMonitorExtensionRule()); + public TestRule rule = new SetupCoreRule(); // -------------------------------------------------------------------------------------------- // Setup @@ -38,7 +40,7 @@ public class IdentityResetHandlingTest { @Before public void setup() throws Exception { - registerEdgeIdentityExtension(); + registerExtensions(Arrays.asList(MonitorExtension.EXTENSION, Identity.EXTENSION), null); } // -------------------------------------------------------------------------------------------- diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java index 462ddf3b..3bb81637 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java @@ -22,6 +22,7 @@ import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.EventSource; import com.adobe.marketing.mobile.EventType; +import com.adobe.marketing.mobile.Extension; import com.adobe.marketing.mobile.MobileCore; import com.adobe.marketing.mobile.edge.identity.AuthenticatedState; import com.adobe.marketing.mobile.edge.identity.Identity; @@ -36,13 +37,13 @@ import com.fasterxml.jackson.databind.node.ValueNode; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; @@ -51,37 +52,24 @@ public class IdentityFunctionalTestUtil { private static final String LOG_SOURCE = "IdentityFunctionalTestUtil"; /** - * Register's Edge Identity Extension and start the Core + * Applies the configuration provided, registers the extensions and then starts + * core. + * @param extensions the extensions that need to be registered + * @param configuration the initial configuration update that needs to be applied + * @throws InterruptedException if the wait time for extension registration has elapsed */ - public static void registerEdgeIdentityExtension() throws InterruptedException { - final ADBCountDownLatch latch = new ADBCountDownLatch(1); - MobileCore.registerExtensions(Arrays.asList(Identity.EXTENSION), o -> latch.countDown()); - - latch.await(1000, TimeUnit.MILLISECONDS); - TestHelper.waitForThreads(2000); - resetTestExpectations(); - } - - /** - * Register's Identity Direct and Edge Identity Extension. And then starts the MobileCore - */ - public static void registerBothIdentityExtensions() throws Exception { - HashMap config = new HashMap() { - { - put("global.privacy", "optedin"); - put("experienceCloud.org", "testOrg@AdobeOrg"); - put("experienceCloud.server", "notaserver"); - } - }; - MobileCore.updateConfiguration(config); + public static void registerExtensions( + final List> extensions, + @Nullable final Map configuration + ) throws InterruptedException { + if (configuration != null) { + MobileCore.updateConfiguration(configuration); + } final ADBCountDownLatch latch = new ADBCountDownLatch(1); - MobileCore.registerExtensions( - Arrays.asList(Identity.EXTENSION, com.adobe.marketing.mobile.Identity.EXTENSION), - o -> latch.countDown() - ); + MobileCore.registerExtensions(extensions, o -> latch.countDown()); - latch.await(); + latch.await(1000, TimeUnit.MILLISECONDS); TestHelper.waitForThreads(2000); resetTestExpectations(); } diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java index 372591db..8aeeeda7 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java @@ -19,8 +19,6 @@ import com.adobe.marketing.mobile.EventType; import com.adobe.marketing.mobile.Extension; import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionError; -import com.adobe.marketing.mobile.ExtensionErrorCallback; import com.adobe.marketing.mobile.MobileCore; import com.adobe.marketing.mobile.SharedStateResolution; import com.adobe.marketing.mobile.SharedStateResult; @@ -61,22 +59,6 @@ protected void onRegistered() { getApi().registerEventListener(EventType.WILDCARD, EventSource.WILDCARD, this::wildcardProcessor); } - public static void registerExtension() { - MobileCore.registerExtension( - MonitorExtension.class, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - Log.error( - LOG_TAG, - LOG_SOURCE, - "There was an error registering the Monitor extension: " + extensionError.getErrorName() - ); - } - } - ); - } - /** * Unregister the Monitor Extension from the EventHub. */ diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java index 52fd466e..f0ce70f2 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java @@ -105,37 +105,6 @@ public void evaluate() throws Throwable { } } - /** - * {@code TestRule} which registers the {@code MonitorExtension}, allowing test cases to assert - * events passing through the {@code EventHub}. This {@code TestRule} must be applied after - * the {@link SetupCoreRule} to ensure the {@code MobileCore} is setup for testing first. - *

- * To use, add the following to your test class: - *

-	 *  @Rule
-	 *    public RuleChain rule = RuleChain.outerRule(new SetupCoreRule())
-	 * 							.around(new RegisterMonitorExtensionRule());
-	 * 
- */ - public static class RegisterMonitorExtensionRule implements TestRule { - - @Override - public Statement apply(final Statement base, final Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - MonitorExtension.registerExtension(); - - try { - base.evaluate(); - } finally { - MonitorExtension.reset(); - } - } - }; - } - } - /** * Waits for all the {@code #knownThreads} to finish or fails the test after timeoutMillis if some of them are still running * when the timer expires. If timeoutMillis is 0, a default timeout will be set = 1000ms From 943366a6465353f0883dce39c6c80ae6d583ef84 Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Wed, 14 Dec 2022 09:44:13 -0800 Subject: [PATCH 10/13] Fix constant and import correct Nullable --- .../edge/identity/util/IdentityFunctionalTestUtil.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java index 3bb81637..a995242a 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java @@ -16,6 +16,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import androidx.annotation.Nullable; import com.adobe.marketing.mobile.AdobeCallback; import com.adobe.marketing.mobile.AdobeCallbackWithError; import com.adobe.marketing.mobile.AdobeError; @@ -43,13 +44,13 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import javax.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; public class IdentityFunctionalTestUtil { private static final String LOG_SOURCE = "IdentityFunctionalTestUtil"; + private static final long REGISTRATION_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(2); /** * Applies the configuration provided, registers the extensions and then starts @@ -69,7 +70,7 @@ public static void registerExtensions( final ADBCountDownLatch latch = new ADBCountDownLatch(1); MobileCore.registerExtensions(extensions, o -> latch.countDown()); - latch.await(1000, TimeUnit.MILLISECONDS); + latch.await(REGISTRATION_TIMEOUT_MS, TimeUnit.MILLISECONDS); TestHelper.waitForThreads(2000); resetTestExpectations(); } From 6c064f427d3bcc257d88e28118056066ee3733b8 Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Wed, 14 Dec 2022 11:15:07 -0800 Subject: [PATCH 11/13] Remove unused helper methods --- .../util/IdentityFunctionalTestUtil.java | 58 ------- .../edge/identity/util/MonitorExtension.java | 11 -- .../mobile/edge/identity/util/TestHelper.java | 141 +----------------- 3 files changed, 1 insertion(+), 209 deletions(-) diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java index a995242a..43435db2 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java @@ -20,9 +20,6 @@ import com.adobe.marketing.mobile.AdobeCallback; import com.adobe.marketing.mobile.AdobeCallbackWithError; import com.adobe.marketing.mobile.AdobeError; -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.EventSource; -import com.adobe.marketing.mobile.EventType; import com.adobe.marketing.mobile.Extension; import com.adobe.marketing.mobile.MobileCore; import com.adobe.marketing.mobile.edge.identity.AuthenticatedState; @@ -44,7 +41,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import org.json.JSONException; import org.json.JSONObject; public class IdentityFunctionalTestUtil { @@ -163,60 +159,6 @@ public static Map createXDMIdentityMap(TestItem... items) { return identityMapDict; } - /** - * Helper method to build remove identity request event with XDM formatted Identity jsonString - */ - public static Event buildRemoveIdentityRequestWithJSONString(final String jsonStr) throws Exception { - final JSONObject jsonObject = new JSONObject(jsonStr); - final Map xdmData = JSONUtils.toMap(jsonObject); - return buildRemoveIdentityRequest(xdmData); - } - - /** - * Helper method to build remove identity request event with XDM formatted Identity map - */ - public static Event buildRemoveIdentityRequest(final Map map) { - return new Event.Builder( - "Remove Identity Event", - EventType.EDGE_IDENTITY, - // TODO: Use event source from Core when available. - "com.adobe.eventSource.removeIdentity" - ) - .setEventData(map) - .build(); - } - - /** - * Helper method to build update identity request event with XDM formatted Identity jsonString - */ - public static Event buildUpdateIdentityRequestJSONString(final String jsonStr) throws Exception { - final JSONObject jsonObject = new JSONObject(jsonStr); - final Map xdmData = JSONUtils.toMap(jsonObject); - return buildUpdateIdentityRequest(xdmData); - } - - /** - * Helper method to build update identity request event with XDM formatted Identity map - */ - public static Event buildUpdateIdentityRequest(final Map map) { - return new Event.Builder("Update Identity Event", EventType.EDGE_IDENTITY, EventSource.UPDATE_IDENTITY) - .setEventData(map) - .build(); - } - - /** - * Serialize the given {@code jsonString} to a JSON Object, then flattens to {@code Map}. - * If the provided string is not in JSON structure an {@link JSONException} is thrown. - * - * @param jsonString the string in JSON structure to flatten - * @return new map with flattened structure - */ - public static Map flattenJSONString(final String jsonString) throws JSONException { - JSONObject jsonObject = new JSONObject(jsonString); - Map persistenceValueMap = JSONUtils.toMap(jsonObject); - return flattenMap(persistenceValueMap); - } - /** * Serialize the given {@code map} to a JSON Object, then flattens to {@code Map}. * For example, a JSON such as "{xdm: {stitchId: myID, eventType: myType}}" is flattened diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java index 8aeeeda7..1e458885 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/MonitorExtension.java @@ -72,17 +72,6 @@ public static void unregisterExtension() { MobileCore.dispatchEvent(event); } - /** - * Add an event to the list of expected events. - * @param type the type of the event. - * @param source the source of the event. - * @param count the number of events expected to be received. - */ - public static void setExpectedEvent(final String type, final String source, final int count) { - EventSpec eventSpec = new EventSpec(source, type); - expectedEvents.put(eventSpec, new ADBCountDownLatch(count)); - } - public static Map getExpectedEvents() { return expectedEvents; } diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java index f0ce70f2..98ff6537 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/TestHelper.java @@ -12,9 +12,7 @@ package com.adobe.marketing.mobile.edge.identity.util; import static com.adobe.marketing.mobile.edge.identity.util.IdentityTestConstants.LOG_TAG; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import android.app.Application; import android.app.Instrumentation; @@ -227,145 +225,9 @@ public static void resetTestExpectations() { // --------------------------------------------------------------------------------------------- // Event Test Helpers // --------------------------------------------------------------------------------------------- - - /** - * Sets an expectation for a specific event type and source and how many times the event should be dispatched. - * - * @param type the event type - * @param source the event source - * @param count the expected number of times the event is dispatched - * @throws IllegalArgumentException if {@code count} is less than 1 - */ - public static void setExpectationEvent(final String type, final String source, final int count) { - if (count < 1) { - throw new IllegalArgumentException("Cannot set expectation event count less than 1!"); - } - - MonitorExtension.setExpectedEvent(type, source, count); - } - - /** - * Asserts if all the expected events were received and fails if an unexpected event was seen. - * - * @param ignoreUnexpectedEvents if set on false, an assertion is made on unexpected events, otherwise the unexpected events are ignored - * @throws InterruptedException - * @see #setExpectationEvent(String, String, int) - * @see #assertUnexpectedEvents() - */ - public static void assertExpectedEvents(final boolean ignoreUnexpectedEvents) throws InterruptedException { - Map expectedEvents = MonitorExtension.getExpectedEvents(); - - if (expectedEvents.isEmpty()) { - fail("There are no event expectations set, use this API after calling setExpectationEvent"); - return; - } - - for (Map.Entry expected : expectedEvents.entrySet()) { - boolean awaitResult = expected.getValue().await(WAIT_EVENT_TIMEOUT_MS, TimeUnit.MILLISECONDS); - String failMessage = String.format( - "Timed out waiting for event type %s and source %s.", - expected.getKey().type, - expected.getKey().source - ); - assertTrue(failMessage, awaitResult); - int expectedCount = expected.getValue().getInitialCount(); - int receivedCount = expected.getValue().getCurrentCount(); - failMessage = - String.format( - "Expected %d events for '%s', but received %d", - expectedCount, - expected.getKey(), - receivedCount - ); - assertEquals(failMessage, expectedCount, receivedCount); - } - - if (!ignoreUnexpectedEvents) { - assertUnexpectedEvents(false); - } - } - - /** - * Asserts if any unexpected event was received. Use this method to verify the received events - * are correct when setting event expectations. Waits a short time before evaluating received - * events to allow all events to come in. - * - * @see #setExpectationEvent - */ - public static void assertUnexpectedEvents() throws InterruptedException { - assertUnexpectedEvents(true); - } - - /** - * Asserts if any unexpected event was received. Use this method to verify the received events - * are correct when setting event expectations. - * - * @param shouldWait waits a short time to allow events to be received when true - * @see #setExpectationEvent - */ - public static void assertUnexpectedEvents(final boolean shouldWait) throws InterruptedException { - // Short wait to allow events to come in - if (shouldWait) { - sleep(WAIT_TIMEOUT_MS); - } - - int unexpectedEventsReceivedCount = 0; - StringBuilder unexpectedEventsErrorString = new StringBuilder(); - - Map> receivedEvents = MonitorExtension.getReceivedEvents(); - Map expectedEvents = MonitorExtension.getExpectedEvents(); - - for (Map.Entry> receivedEvent : receivedEvents.entrySet()) { - ADBCountDownLatch expectedEventLatch = expectedEvents.get(receivedEvent.getKey()); - - if (expectedEventLatch != null) { - expectedEventLatch.await(WAIT_EVENT_TIMEOUT_MS, TimeUnit.MILLISECONDS); - int expectedCount = expectedEventLatch.getInitialCount(); - int receivedCount = receivedEvent.getValue().size(); - String failMessage = String.format( - "Expected %d events for '%s', but received %d", - expectedCount, - receivedEvent.getKey(), - receivedCount - ); - assertEquals(failMessage, expectedCount, receivedCount); - } else { - unexpectedEventsReceivedCount += receivedEvent.getValue().size(); - unexpectedEventsErrorString.append( - String.format( - "(%s,%s,%d)", - receivedEvent.getKey().type, - receivedEvent.getKey().source, - receivedEvent.getValue().size() - ) - ); - Log.debug( - LOG_TAG, - LOG_SOURCE, - String.format( - "Received unexpected event with type: %s source: %s", - receivedEvent.getKey().type, - receivedEvent.getKey().source - ) - ); - } - } - - assertEquals( - String.format( - "Received %d unexpected event(s): %s", - unexpectedEventsReceivedCount, - unexpectedEventsErrorString.toString() - ), - 0, - unexpectedEventsReceivedCount - ); - } - /** * Returns the {@code Event}(s) dispatched through the Event Hub, or empty if none was found. - * Use this API after calling {@link #setExpectationEvent(String, String, int)} to wait for - * the expected events. The wait time for each event is {@link #WAIT_EVENT_TIMEOUT_MS}ms. + * The wait time for each event is {@link #WAIT_EVENT_TIMEOUT_MS}ms. * * @param type the event type as in the expectation * @param source the event source as in the expectation @@ -380,7 +242,6 @@ public static List getDispatchedEventsWith(final String type, final Strin /** * Returns the {@code Event}(s) dispatched through the Event Hub, or empty if none was found. - * Use this API after calling {@link #setExpectationEvent(String, String, int)} to wait for the right amount of time * * @param type the event type as in the expectation * @param source the event source as in the expectation From c66775e3c310ed34885f01a79714e01878c9ab1b Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Thu, 15 Dec 2022 12:49:58 -0800 Subject: [PATCH 12/13] Removed unused constants, utility methods and tasks --- code/edgeidentity/build.gradle | 12 -- .../edge/identity/IdentityConstants.java | 1 - .../marketing/mobile/edge/identity/Utils.java | 81 ++--------- .../mobile/edge/identity/UtilsTests.java | 133 ++---------------- 4 files changed, 25 insertions(+), 202 deletions(-) diff --git a/code/edgeidentity/build.gradle b/code/edgeidentity/build.gradle index a1de1d16..60f72702 100644 --- a/code/edgeidentity/build.gradle +++ b/code/edgeidentity/build.gradle @@ -64,18 +64,6 @@ android { sourceCompatibility rootProject.ext.sourceCompatibility targetCompatibility rootProject.ext.targetCompatibility } - - sourceSets { - String sharedTestUtilJavaDir = 'src/sharedTestUtils/java' - - test { - java.srcDirs += [sharedTestUtilJavaDir] - } - - androidTest { - java.srcDirs += [sharedTestUtilJavaDir] - } - } } afterEvaluate { diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java index bb1edfb1..ffa3df8b 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java @@ -26,7 +26,6 @@ private Default() {} static final class EventSource { - static final String BOOTED = "com.adobe.eventSource.booted"; static final String REMOVE_IDENTITY = "com.adobe.eventSource.removeIdentity"; static final String REQUEST_CONTENT = "com.adobe.eventSource.requestContent"; static final String REQUEST_IDENTITY = "com.adobe.eventSource.requestIdentity"; diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Utils.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Utils.java index 9d93020d..ebdcfc95 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Utils.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Utils.java @@ -1,5 +1,5 @@ /* - Copyright 2021 Adobe. All rights reserved. + Copyright 2022 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 @@ -11,89 +11,30 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityConstants.LOG_TAG; - -import com.adobe.marketing.mobile.services.Log; -import com.adobe.marketing.mobile.util.JSONUtils; -import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.json.JSONException; -import org.json.JSONObject; class Utils { - private static final String LOG_SOURCE = "Utils"; - private Utils() {} - static boolean isNullOrEmpty(final Map map) { - return map == null || map.isEmpty(); - } - - static boolean isNullOrEmpty(final List list) { - return list == null || list.isEmpty(); - } - /** - * Adds {@code key}/{@code value} to {@code map} if {@code value} is not null or an - * empty collection. + * Checks if the {@code Map} provided is null or empty. * - * @param map collection to put {@code value} mapped to {@code key} if {@code value} is - * non-null and contains at least one entry - * @param key key used to map {@code value} in {@code map} - * @param value a Object to add to {@code map} if not null + * @param map the {@code Map} to verify + * @return true if the {@code Map} provided is null or empty; false otherwise */ - static void putIfNotNull(final Map map, final String key, final Object value) { - boolean addValues = map != null && key != null && value != null; - - if (addValues) { - map.put(key, value); - } - } - - /** - * Creates a deep copy of the provided {@link Map}. - * - * @param map to be copied - * @return {@link Map} containing a deep copy of all the elements in {@code map} - */ - static Map deepCopy(final Map map) { - if (map == null) { - return null; - } - - try { - // Core's JSONUtils retains null in resulting Map but, EdgeIdentity 1.0 implementaion - // filtered out the null value keys. One issue this may cause is sending empty objects to - // Edge Network. - // TODO: Add/verify tests to check side effects of retaining nulls in the resulting Map - return JSONUtils.toMap(new JSONObject(map)); - } catch (final JSONException | NullPointerException e) { - Log.debug(LOG_TAG, LOG_SOURCE, "Unable to deep copy map, json string is invalid."); - } - - return null; + static boolean isNullOrEmpty(final Map map) { + return map == null || map.isEmpty(); } /** - * Creates a deep copy of the provided {@code listOfMaps}. + * Checks if the {@code List} provided is null or empty. * - * @param listOfMaps to be copied - * @return {@link List} containing a deep copy of all the elements in {@code listOfMaps} - * @see #deepCopy(Map) + * @param list the {@code List} to verify + * @return true if the {@code List} provided is null or empty; false otherwise */ - static List> deepCopy(final List> listOfMaps) { - if (listOfMaps == null) { - return null; - } - - List> deepCopy = new ArrayList<>(); - - for (Map map : listOfMaps) { - deepCopy.add(deepCopy(map)); - } - - return deepCopy; + static boolean isNullOrEmpty(final List list) { + return list == null || list.isEmpty(); } } diff --git a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/UtilsTests.java b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/UtilsTests.java index 957d6b37..3a5072b4 100644 --- a/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/UtilsTests.java +++ b/code/edgeidentity/src/test/java/com/adobe/marketing/mobile/edge/identity/UtilsTests.java @@ -11,14 +11,11 @@ package com.adobe.marketing.mobile.edge.identity; -import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertFalse; -import static junit.framework.TestCase.assertNotNull; -import static junit.framework.TestCase.assertNull; import static junit.framework.TestCase.assertTrue; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import org.junit.Test; @@ -27,134 +24,32 @@ public class UtilsTests { @Test - public void testUtils_deepCopyNull() { - assertNull(Utils.deepCopy((Map) null)); + public void test_isNullOrEmpty_nullMap() { + assertTrue(Utils.isNullOrEmpty((Map) null)); } @Test - public void testUtils_deepCopyEmpty() { - Map emptyMap = new HashMap<>(); - assertEquals(0, Utils.deepCopy(emptyMap).size()); + public void test_isNullOrEmpty_emptyMap() { + assertTrue(Utils.isNullOrEmpty(Collections.EMPTY_MAP)); } @Test - public void testUtils_deepCopyValidSimpleNull() { - Map map = new HashMap<>(); - map.put("key1", "value1"); - Map deepCopy = Utils.deepCopy(map); - - map = null; - assertNotNull(deepCopy); - } - - @Test - public void testUtils_deepCopyValidSimple() { - Map map = new HashMap<>(); - map.put("key1", "value1"); - - Map deepCopy = Utils.deepCopy(map); - deepCopy.remove("key1"); - - assertTrue(map.containsKey("key1")); + public void test_isNullOrEmpty_nonEmptyNonNullMap() { + assertFalse(Utils.isNullOrEmpty(Collections.singletonMap("someKey", "someValue"))); } @Test - public void testUtils_deepCopyValidNested() { - Map map = new HashMap<>(); - map.put("key1", "value1"); - - Map nested = new HashMap<>(); - nested.put("nestedKey", "nestedValue"); - map.put("nestedMap", nested); - - Map deepCopy = Utils.deepCopy(map); - Map nestedDeepCopy = (Map) deepCopy.get("nestedMap"); - nestedDeepCopy.put("newKey", "newValue"); - - assertFalse(nested.size() == nestedDeepCopy.size()); + public void test_isNullOrEmpty_nullList() { + assertTrue(Utils.isNullOrEmpty((List) null)); } @Test - public void testUtils_deepCopyNullKey_returnsNull() { - Map map = new HashMap<>(); - map.put("key1", "value1"); - map.put(null, "null"); - - Map nested = new HashMap<>(); - nested.put("nestedKey", "nestedValue"); - map.put(null, "nestednull"); - - assertNull(Utils.deepCopy(map)); - } - - @Test - public void testPutIfNotNull_NonNull_InsertsCorrectly() { - Map map = new HashMap<>(); - Utils.putIfNotNull(map, "testKey", new Integer(2)); - - assertEquals(1, map.size()); - assertEquals(2, map.get("testKey")); - } - - @Test - public void testPutIfNotNull_Null_NoInsert() { - Map map = new HashMap<>(); - Utils.putIfNotNull(map, "testKey", null); - - assertEquals(0, map.size()); + public void test_isNullOrEmpty_emptyList() { + assertTrue(Utils.isNullOrEmpty(Collections.EMPTY_LIST)); } @Test - public void testUtils_deepCopyListOfMaps_Null() { - assertNull(Utils.deepCopy((List) null)); - } - - @Test - public void testUtils_deepCopyListOfMaps_Empty() { - assertEquals(0, Utils.deepCopy(new ArrayList>()).size()); - } - - @Test - public void testUtils_deepCopyListOfMaps_ValidSimpleNull() { - List> list = new ArrayList<>(); - list.add(new HashMap()); - assertNotNull(Utils.deepCopy(list)); - } - - @Test - public void testUtils_deepCopyListOfMaps_ValidSimple() { - Map map = new HashMap<>(); - map.put("key1", "value1"); - List> list = new ArrayList<>(); - list.add(map); - - List> deepCopy = Utils.deepCopy(list); - deepCopy.remove(0); - - assertEquals(1, list.size()); - } - - @Test - public void testUtils_deepCopyListOfMaps_ValidNested() { - Map map = new HashMap<>(); - map.put("key1", "value1"); - - Map nested = new HashMap<>(); - nested.put("nestedKey", "nestedValue"); - map.put("nestedMap", nested); - - List> list = new ArrayList>(); - list.add(map); - - Map deepCopy = Utils.deepCopy(map); - List> nestedDeepCopy = Utils.deepCopy(list); - nestedDeepCopy.get(0).put("newKey", "newValue"); - ((Map) nestedDeepCopy.get(0).get("nestedMap")).put("nestedKey2", 2222); - - assertEquals(3, nestedDeepCopy.get(0).size()); - assertEquals(2, list.get(0).size()); - assertTrue(list.get(0).containsKey("key1")); - assertEquals(1, ((Map) list.get(0).get("nestedMap")).size()); - assertEquals(2, ((Map) nestedDeepCopy.get(0).get("nestedMap")).size()); + public void test_isNullOrEmpty_nonEmptyNonNullList() { + assertFalse(Utils.isNullOrEmpty(Arrays.asList("A", 1, true))); } } From 734d4b68e9a0a84c84be9ab4b49559b1f83840cd Mon Sep 17 00:00:00 2001 From: Prashanth Rudrabhat Date: Thu, 15 Dec 2022 14:20:20 -0800 Subject: [PATCH 13/13] Preserve copyright date for moved files --- .../marketing/mobile/edge/identity/util/ADBCountDownLatch.java | 2 +- .../mobile/edge/identity/util/IdentityFunctionalTestUtil.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/ADBCountDownLatch.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/ADBCountDownLatch.java index 3d36853c..b635d3c8 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/ADBCountDownLatch.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/ADBCountDownLatch.java @@ -1,5 +1,5 @@ /* - Copyright 2022 Adobe. All rights reserved. + Copyright 2021 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 diff --git a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java index 43435db2..793c369a 100644 --- a/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java +++ b/code/edgeidentity/src/androidTest/java/com/adobe/marketing/mobile/edge/identity/util/IdentityFunctionalTestUtil.java @@ -1,5 +1,5 @@ /* - Copyright 2022 Adobe. All rights reserved. + Copyright 2021 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0