From 45651a88e8344c161a544dc0ddfc3f1ee5c83c68 Mon Sep 17 00:00:00 2001 From: saquib-adobe Date: Thu, 7 Nov 2024 19:59:27 +0530 Subject: [PATCH 1/7] Overloaded getPropositions and updatePropositions with new timeout argument in Optimize.java --- .../marketing/mobile/optimize/Optimize.java | 75 +++++++++++++++++-- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java index 5033e55c..db88e867 100644 --- a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java +++ b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java @@ -49,7 +49,7 @@ private Optimize() {} * Experience Edge network. * *

The returned decision propositions are cached in-memory in the Optimize SDK extension and - * can be retrieved using {@link #getPropositions(List, AdobeCallback)} API. + * can be retrieved using {@link #getPropositions(List, long, AdobeCallback)} API. * * @param decisionScopes {@code List} containing scopes for which offers need to * be updated. @@ -61,9 +61,10 @@ private Optimize() {} public static void updatePropositions( @NonNull final List decisionScopes, @Nullable final Map xdm, - @Nullable final Map data) { + @Nullable final Map data, + final long timeout) { - updatePropositions(decisionScopes, xdm, data, null); + updatePropositions(decisionScopes, xdm, data, timeout, null); } /** @@ -88,6 +89,44 @@ public static void updatePropositions( @Nullable final Map xdm, @Nullable final Map data, @Nullable final AdobeCallback> callback) { + final long defaultTimeout = OptimizeConstants.EDGE_CONTENT_COMPLETE_RESPONSE_TIMEOUT; + updatePropositionsInternal(decisionScopes, xdm, data, defaultTimeout, callback); + } + + /** + * This API dispatches an Event for the Edge network extension to fetch decision propositions, + * for the provided decision scopes list, from the decisioning services enabled in the + * Experience Edge network. + * + *

The returned decision propositions are cached in-memory in the Optimize SDK extension and + * can be retrieved using {@link #getPropositions(List, long, AdobeCallback)} API. + * + * @param decisionScopes {@code List} containing scopes for which offers need to + * be updated. + * @param xdm {@code Map} containing additional XDM-formatted data to be sent in + * the personalization query request. + * @param data {@code Map} containing additional free-form data to be sent in + * the personalization query request. + * @param timeoutMillis {@code Long} containing additional configurable timeout to be sent in the + * personalization query request. + * @param callback {@code AdobeCallback>} which will be + * invoked when decision propositions are received from the Edge network. + */ + public static void updatePropositions( + @NonNull final List decisionScopes, + @Nullable final Map xdm, + @Nullable final Map data, + final long timeoutMillis, + @Nullable final AdobeCallback> callback) { + updatePropositionsInternal(decisionScopes, xdm, data, timeoutMillis, callback); + } + + private static void updatePropositionsInternal( + @NonNull final List decisionScopes, + @Nullable final Map xdm, + @Nullable final Map data, + final long timeoutMillis, + @Nullable final AdobeCallback> callback) { if (OptimizeUtils.isNullOrEmpty(decisionScopes)) { Log.warning( @@ -148,7 +187,7 @@ public static void updatePropositions( MobileCore.dispatchEventWithResponseCallback( event, - OptimizeConstants.EDGE_CONTENT_COMPLETE_RESPONSE_TIMEOUT, + timeoutMillis, new AdobeCallbackWithError() { @Override public void fail(final AdobeError adobeError) { @@ -236,6 +275,30 @@ public void call(final Event event) { public static void getPropositions( @NonNull final List decisionScopes, @NonNull final AdobeCallback> callback) { + long defaultTimeout = OptimizeConstants.GET_RESPONSE_CALLBACK_TIMEOUT; + getPropositionsInternal(decisionScopes, defaultTimeout, callback); + } + + /** + * This API retrieves the previously fetched propositions, for the provided decision scopes, + * from the in-memory extension propositions cache. + * + * @param decisionScopes {@code List} containing scopes for which offers need to + * be requested. + * @param callback {@code AdobeCallbackWithError>} which + * will be invoked when decision propositions are retrieved from the local cache. + */ + public static void getPropositions( + @NonNull final List decisionScopes, + final long timeoutMillis, + @NonNull final AdobeCallback> callback) { + getPropositionsInternal(decisionScopes, timeoutMillis, callback); + } + + private static void getPropositionsInternal( + @NonNull final List decisionScopes, + final long timeoutMillis, + @NonNull final AdobeCallback> callback) { if (OptimizeUtils.isNullOrEmpty(decisionScopes)) { Log.warning( OptimizeConstants.LOG_TAG, @@ -286,7 +349,7 @@ public static void getPropositions( // requests have enough time to complete. MobileCore.dispatchEventWithResponseCallback( event, - OptimizeConstants.GET_RESPONSE_CALLBACK_TIMEOUT, + timeoutMillis, new AdobeCallbackWithError() { @Override public void fail(final AdobeError adobeError) { @@ -348,7 +411,7 @@ public void call(final Event event) { * query. * *

The personalization query requests can be triggered by the {@link - * Optimize#updatePropositions(List, Map, Map)} API, Edge extension {@code + * Optimize#updatePropositions(List, Map, Map, long)} API, Edge extension {@code * sendEvent(ExperienceEvent, EdgeCallback)} API or launch consequence rules. * * @param callback {@code AdobeCallbackWithError>} which From 2b948f10f51f584c3c6396cae74b9fadb23af68b Mon Sep 17 00:00:00 2001 From: saquib-adobe Date: Thu, 7 Nov 2024 20:00:34 +0530 Subject: [PATCH 2/7] Propagated the changes to test app --- .../marketing/mobile/optimize/Optimize.java | 4 +- .../marketing/optimizeapp/OffersScreen.kt | 8 +++- .../optimizeapp/viewmodels/MainViewModel.kt | 41 ++++++++++++++----- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java index db88e867..7af9d94d 100644 --- a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java +++ b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java @@ -107,8 +107,8 @@ public static void updatePropositions( * the personalization query request. * @param data {@code Map} containing additional free-form data to be sent in * the personalization query request. - * @param timeoutMillis {@code Long} containing additional configurable timeout to be sent in the - * personalization query request. + * @param timeoutMillis {@code Long} containing additional configurable timeout to be sent in + * the personalization query request. * @param callback {@code AdobeCallback>} which will be * invoked when decision propositions are received from the Edge network. */ diff --git a/code/testapp/src/main/java/com/adobe/marketing/optimizeapp/OffersScreen.kt b/code/testapp/src/main/java/com/adobe/marketing/optimizeapp/OffersScreen.kt index 37c6d060..173bf29c 100644 --- a/code/testapp/src/main/java/com/adobe/marketing/optimizeapp/OffersScreen.kt +++ b/code/testapp/src/main/java/com/adobe/marketing/optimizeapp/OffersScreen.kt @@ -181,7 +181,8 @@ fun OffersView(viewModel: MainViewModel) { viewModel.updatePropositions( decisionScopes = decisionScopeList, xdm = mapOf(Pair("xdmKey", "1234")), - data = data + data = data, + timeout = 200 ) }) { Text( @@ -200,7 +201,10 @@ fun OffersView(viewModel: MainViewModel) { viewModel.jsonDecisionScope?.also { decisionScopeList.add(it) } viewModel.targetMboxDecisionScope?.also { decisionScopeList.add(it) } - viewModel.getPropositions(decisionScopes = decisionScopeList) + viewModel.getPropositions( + decisionScopes = decisionScopeList, + timeout = 200 + ) }) { Text( text = "Get \n Propositions", diff --git a/code/testapp/src/main/java/com/adobe/marketing/optimizeapp/viewmodels/MainViewModel.kt b/code/testapp/src/main/java/com/adobe/marketing/optimizeapp/viewmodels/MainViewModel.kt index a7832f5e..3768678f 100644 --- a/code/testapp/src/main/java/com/adobe/marketing/optimizeapp/viewmodels/MainViewModel.kt +++ b/code/testapp/src/main/java/com/adobe/marketing/optimizeapp/viewmodels/MainViewModel.kt @@ -71,10 +71,11 @@ class MainViewModel: ViewModel() { * Calls the Optimize SDK API to get the Propositions see [Optimize.getPropositions] * * @param [decisionScopes] a [List] of [DecisionScope] + * @param [timeout] a [Long] in milliseconds */ - fun getPropositions(decisionScopes: List) { + fun getPropositions(decisionScopes: List, timeout: Long? = null) { optimizePropositionStateMap.clear() - Optimize.getPropositions(decisionScopes, object: AdobeCallbackWithError>{ + val callback = object : AdobeCallbackWithError> { override fun call(propositions: Map?) { propositions?.forEach { optimizePropositionStateMap[it.key.name] = it.value @@ -84,8 +85,10 @@ class MainViewModel: ViewModel() { override fun fail(error: AdobeError?) { print("Error in getting Propositions.") } - - }) + } + timeout?.let { milliseconds -> + Optimize.getPropositions(decisionScopes, milliseconds, callback) + } ?: Optimize.getPropositions(decisionScopes, callback) } /** @@ -94,19 +97,37 @@ class MainViewModel: ViewModel() { * @param decisionScopes a [List] of [DecisionScope] * @param xdm a [Map] of xdm params * @param data a [Map] of data + * @param timeout a [Long] in milliseconds */ - fun updatePropositions(decisionScopes: List , xdm: Map , data: Map) { - optimizePropositionStateMap.clear() - Optimize.updatePropositions(decisionScopes, xdm, data, object: AdobeCallbackWithOptimizeError>{ + fun updatePropositions( + decisionScopes: List, + xdm: Map, + data: Map, + timeout: Long? = null + ) { + val callback = object : AdobeCallbackWithOptimizeError> { override fun call(propositions: Map?) { - Log.i("Optimize Test App","Propositions updated successfully.") + Log.i("Optimize Test App", "Propositions updated successfully.") } override fun fail(error: AEPOptimizeError?) { - Log.i("Optimize Test App","Error in updating Propositions:: ${error?.title ?: "Undefined"}.") + Log.i( + "Optimize Test App", + "Error in updating Propositions:: ${error?.title ?: "Undefined"}." + ) } - }) + } + optimizePropositionStateMap.clear() + timeout?.let { milliseconds -> + Optimize.updatePropositions( + decisionScopes, + xdm, + data, + milliseconds, + callback + ) + } ?: Optimize.updatePropositions(decisionScopes, xdm, data, callback) } /** From 8d79c5ac2e582fbf90d2136e36f82509865c989e Mon Sep 17 00:00:00 2001 From: saquib-adobe Date: Mon, 11 Nov 2024 20:42:09 +0530 Subject: [PATCH 3/7] Adding another overloaded method with no callback and no timeout --- .../marketing/mobile/optimize/Optimize.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java index 7af9d94d..84507af2 100644 --- a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java +++ b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java @@ -43,6 +43,29 @@ private Optimize() {} return OptimizeConstants.EXTENSION_VERSION; } + /** + * This API dispatches an Event for the Edge network extension to fetch decision propositions, + * for the provided decision scopes list, from the decisioning services enabled in the + * Experience Edge network. + * + *

The returned decision propositions are cached in-memory in the Optimize SDK extension and + * can be retrieved using {@link #getPropositions(List, long, AdobeCallback)} API. + * + * @param decisionScopes {@code List} containing scopes for which offers need to + * be updated. + * @param xdm {@code Map} containing additional XDM-formatted data to be sent in + * the personalization query request. + * @param data {@code Map} containing additional free-form data to be sent in + * the personalization query request. + */ + public static void updatePropositions( + @NonNull final List decisionScopes, + @Nullable final Map xdm, + @Nullable final Map data) { + final long defaultTimeout = OptimizeConstants.EDGE_CONTENT_COMPLETE_RESPONSE_TIMEOUT; + updatePropositions(decisionScopes, xdm, data, defaultTimeout, null); + } + /** * This API dispatches an Event for the Edge network extension to fetch decision propositions, * for the provided decision scopes list, from the decisioning services enabled in the From 715e898a0482775672c5e3919d8d3e2fdb75cf85 Mon Sep 17 00:00:00 2001 From: saquib-adobe Date: Wed, 13 Nov 2024 16:11:59 +0530 Subject: [PATCH 4/7] Timeout propagated to handleUpdatePropositions from updatePropositions --- .../java/com/adobe/marketing/mobile/optimize/Optimize.java | 1 + .../adobe/marketing/mobile/optimize/OptimizeConstants.java | 1 + .../adobe/marketing/mobile/optimize/OptimizeExtension.java | 5 +++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java index 84507af2..0d93f781 100644 --- a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java +++ b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java @@ -199,6 +199,7 @@ private static void updatePropositionsInternal( if (!OptimizeUtils.isNullOrEmpty(data)) { eventData.put(OptimizeConstants.EventDataKeys.DATA, data); } + eventData.put(OptimizeConstants.EventDataKeys.TIMEOUT, timeoutMillis); final Event event = new Event.Builder( diff --git a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/OptimizeConstants.java b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/OptimizeConstants.java index 4633cf71..ff27229b 100644 --- a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/OptimizeConstants.java +++ b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/OptimizeConstants.java @@ -74,6 +74,7 @@ static final class EventDataKeys { static final String DECISION_SCOPE_NAME = "name"; static final String XDM = "xdm"; static final String DATA = "data"; + static final String TIMEOUT = "timeout"; static final String PROPOSITIONS = "propositions"; static final String RESPONSE_ERROR = "responseerror"; static final String PROPOSITION_INTERACTIONS = "propositioninteractions"; diff --git a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/OptimizeExtension.java b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/OptimizeExtension.java index 4a9f168d..8147e125 100644 --- a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/OptimizeExtension.java +++ b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/OptimizeExtension.java @@ -449,10 +449,11 @@ void handleUpdatePropositions(@NonNull final Event event) { // add the Edge event to update propositions in the events queue. eventsDispatcher.offer(edgeEvent); - + long timeoutMillis = + DataReader.getLong(eventData, OptimizeConstants.EventDataKeys.TIMEOUT); MobileCore.dispatchEventWithResponseCallback( edgeEvent, - OptimizeConstants.EDGE_CONTENT_COMPLETE_RESPONSE_TIMEOUT, + timeoutMillis, new AdobeCallbackWithError() { @Override public void fail(final AdobeError error) { From 3ed034b7a4398ed6e3e8fa63f3c2b666a780c1d3 Mon Sep 17 00:00:00 2001 From: saquib-adobe Date: Thu, 14 Nov 2024 20:01:10 +0530 Subject: [PATCH 5/7] Removing the updatePropositions overload with timeout and without callback --- .../marketing/mobile/optimize/Optimize.java | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java index 0d93f781..a0c58bc0 100644 --- a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java +++ b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/Optimize.java @@ -66,30 +66,6 @@ public static void updatePropositions( updatePropositions(decisionScopes, xdm, data, defaultTimeout, null); } - /** - * This API dispatches an Event for the Edge network extension to fetch decision propositions, - * for the provided decision scopes list, from the decisioning services enabled in the - * Experience Edge network. - * - *

The returned decision propositions are cached in-memory in the Optimize SDK extension and - * can be retrieved using {@link #getPropositions(List, long, AdobeCallback)} API. - * - * @param decisionScopes {@code List} containing scopes for which offers need to - * be updated. - * @param xdm {@code Map} containing additional XDM-formatted data to be sent in - * the personalization query request. - * @param data {@code Map} containing additional free-form data to be sent in - * the personalization query request. - */ - public static void updatePropositions( - @NonNull final List decisionScopes, - @Nullable final Map xdm, - @Nullable final Map data, - final long timeout) { - - updatePropositions(decisionScopes, xdm, data, timeout, null); - } - /** * This API dispatches an Event for the Edge network extension to fetch decision propositions, * for the provided decision scopes list, from the decisioning services enabled in the @@ -435,7 +411,7 @@ public void call(final Event event) { * query. * *

The personalization query requests can be triggered by the {@link - * Optimize#updatePropositions(List, Map, Map, long)} API, Edge extension {@code + * Optimize#updatePropositions(List, Map, Map)} API, Edge extension {@code * sendEvent(ExperienceEvent, EdgeCallback)} API or launch consequence rules. * * @param callback {@code AdobeCallbackWithError>} which From 34f1183191f27b121cdd2ff6fb3946a9639e939d Mon Sep 17 00:00:00 2001 From: saquib-adobe Date: Mon, 18 Nov 2024 15:13:18 +0530 Subject: [PATCH 6/7] Adding the unit test for update proposition with timeout --- .../mobile/optimize/AEPOptimizeError.kt | 1 + .../mobile/optimize/OptimizeTests.java | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/AEPOptimizeError.kt b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/AEPOptimizeError.kt index 5a092da4..63a60355 100644 --- a/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/AEPOptimizeError.kt +++ b/code/optimize/src/main/java/com/adobe/marketing/mobile/optimize/AEPOptimizeError.kt @@ -84,6 +84,7 @@ data class AEPOptimizeError( return getAdobeErrorFromStatus(data[STATUS] as Int?) } + @JvmStatic fun getTimeoutError(): AEPOptimizeError { return AEPOptimizeError( null, diff --git a/code/optimize/src/test/java/com/adobe/marketing/mobile/optimize/OptimizeTests.java b/code/optimize/src/test/java/com/adobe/marketing/mobile/optimize/OptimizeTests.java index a880b206..cb2161a4 100644 --- a/code/optimize/src/test/java/com/adobe/marketing/mobile/optimize/OptimizeTests.java +++ b/code/optimize/src/test/java/com/adobe/marketing/mobile/optimize/OptimizeTests.java @@ -11,6 +11,11 @@ package com.adobe.marketing.mobile.optimize; +import static com.adobe.marketing.mobile.optimize.Optimize.failWithOptimizeError; +import static com.adobe.marketing.mobile.optimize.Optimize.updatePropositions; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + import android.util.Base64; import com.adobe.marketing.mobile.AdobeCallbackWithError; import com.adobe.marketing.mobile.AdobeError; @@ -896,4 +901,63 @@ public void test_clearCachedPropositions() { Assert.assertNull(event.getEventData()); } } + + @Test + public void testUpdatePropositions_timeoutError() { + + long timeoutMillis = 100; // Short timeout for testing + Map xdm = new HashMap<>(); + Map data = new HashMap<>(); + final List scopes = new ArrayList<>(); + scopes.add( + new DecisionScope( + "eyJhY3Rpdml0eUlkIjoieGNvcmU6b2ZmZXItYWN0aXZpdHk6MTExMTExMTExMTExMTExMSIsInBsYWNlbWVudElkIjoieGNvcmU6b2ZmZXItcGxhY2VtZW50OjExMTExMTExMTExMTExMTEifQ==")); + + // Mock the callback + AdobeCallbackWithError> callbackMock = + Mockito.mock(AdobeCallbackWithError.class); + + AdobeCallbackWithOptimizeError callbackMockEvent = + Mockito.mock(AdobeCallbackWithOptimizeError.class); + + try (MockedStatic mobileCoreMockedStatic = + Mockito.mockStatic(MobileCore.class); + MockedStatic base64MockedStatic = Mockito.mockStatic(Base64.class)) { + + base64MockedStatic + .when( + () -> + Base64.decode( + ArgumentMatchers.anyString(), + ArgumentMatchers.anyInt())) + .thenAnswer( + (Answer) + invocation -> + java.util.Base64.getDecoder() + .decode((String) invocation.getArguments()[0])); + + mobileCoreMockedStatic + .when( + () -> + MobileCore.dispatchEventWithResponseCallback( + ArgumentMatchers.any(Event.class), + ArgumentMatchers.anyLong(), + ArgumentMatchers.any(AdobeCallbackWithError.class))) + .thenAnswer( + (Answer) + invocation -> { + failWithOptimizeError( + callbackMockEvent, + AEPOptimizeError.Companion.getTimeoutError()); + return null; + }); + + updatePropositions(scopes, xdm, data, timeoutMillis, callbackMock); + ArgumentCaptor errorCaptor = + ArgumentCaptor.forClass(AEPOptimizeError.class); + verify(callbackMockEvent, times(1)).fail(errorCaptor.capture()); + Assert.assertEquals( + AEPOptimizeError.Companion.getTimeoutError(), errorCaptor.getValue()); + } + } } From b9eff05423799949b9966666df636c4d83a5041c Mon Sep 17 00:00:00 2001 From: saquib-adobe Date: Mon, 18 Nov 2024 15:34:24 +0530 Subject: [PATCH 7/7] Adding the unit test for get proposition with timeout --- .../mobile/optimize/OptimizeTests.java | 70 +++++++++++++++++-- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/code/optimize/src/test/java/com/adobe/marketing/mobile/optimize/OptimizeTests.java b/code/optimize/src/test/java/com/adobe/marketing/mobile/optimize/OptimizeTests.java index cb2161a4..92544132 100644 --- a/code/optimize/src/test/java/com/adobe/marketing/mobile/optimize/OptimizeTests.java +++ b/code/optimize/src/test/java/com/adobe/marketing/mobile/optimize/OptimizeTests.java @@ -12,6 +12,7 @@ package com.adobe.marketing.mobile.optimize; import static com.adobe.marketing.mobile.optimize.Optimize.failWithOptimizeError; +import static com.adobe.marketing.mobile.optimize.Optimize.getPropositions; import static com.adobe.marketing.mobile.optimize.Optimize.updatePropositions; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -459,7 +460,7 @@ public void testGetPropositions_validDecisionScope() throws Exception { new DecisionScope( "eyJhY3Rpdml0eUlkIjoieGNvcmU6b2ZmZXItYWN0aXZpdHk6MTExMTExMTExMTExMTExMSIsInBsYWNlbWVudElkIjoieGNvcmU6b2ZmZXItcGxhY2VtZW50OjExMTExMTExMTExMTExMTEifQ==")); - Optimize.getPropositions( + getPropositions( scopes, new AdobeCallbackWithError>() { @Override @@ -566,7 +567,7 @@ public void testGetPropositions_multipleValidDecisionScopes() { "eyJhY3Rpdml0eUlkIjoieGNvcmU6b2ZmZXItYWN0aXZpdHk6MTExMTExMTExMTExMTExMSIsInBsYWNlbWVudElkIjoieGNvcmU6b2ZmZXItcGxhY2VtZW50OjExMTExMTExMTExMTExMTEifQ==")); scopes.add(new DecisionScope("myMbox")); - Optimize.getPropositions( + getPropositions( scopes, new AdobeCallbackWithError>() { @Override @@ -636,7 +637,7 @@ public void testGetPropositions_invalidDecisionScopeInList() { new DecisionScope( "eyJhY3Rpdml0eUlkIjoiIiwicGxhY2VtZW50SWQiOiJ4Y29yZTpvZmZlci1wbGFjZW1lbnQ6MTExMTExMTExMTExMTExMSJ9")); - Optimize.getPropositions( + getPropositions( scopes, new AdobeCallbackWithError>() { @Override @@ -665,7 +666,7 @@ public void call(Map propositionsMap) { public void testGetPropositions_emptyDecisionScopesList() { try (MockedStatic logMockedStatic = Mockito.mockStatic(Log.class)) { // test - Optimize.getPropositions( + getPropositions( new ArrayList(), new AdobeCallbackWithError>() { @Override @@ -694,7 +695,7 @@ public void call(Map propositionsMap) { public void testGetPropositions_nullDecisionScopesList() { try (MockedStatic logMockedStatic = Mockito.mockStatic(Log.class)) { // test - Optimize.getPropositions( + getPropositions( null, new AdobeCallbackWithError>() { @Override @@ -905,7 +906,7 @@ public void test_clearCachedPropositions() { @Test public void testUpdatePropositions_timeoutError() { - long timeoutMillis = 100; // Short timeout for testing + long timeoutMillis = 100; Map xdm = new HashMap<>(); Map data = new HashMap<>(); final List scopes = new ArrayList<>(); @@ -960,4 +961,61 @@ public void testUpdatePropositions_timeoutError() { AEPOptimizeError.Companion.getTimeoutError(), errorCaptor.getValue()); } } + + @Test + public void testGetPropositions_timeoutError() { + + long timeoutMillis = 100; + final List scopes = new ArrayList<>(); + scopes.add( + new DecisionScope( + "eyJhY3Rpdml0eUlkIjoieGNvcmU6b2ZmZXItYWN0aXZpdHk6MTExMTExMTExMTExMTExMSIsInBsYWNlbWVudElkIjoieGNvcmU6b2ZmZXItcGxhY2VtZW50OjExMTExMTExMTExMTExMTEifQ==")); + + // Mock the callback + AdobeCallbackWithError> callbackMock = + Mockito.mock(AdobeCallbackWithError.class); + + AdobeCallbackWithOptimizeError callbackMockEvent = + Mockito.mock(AdobeCallbackWithOptimizeError.class); + + try (MockedStatic mobileCoreMockedStatic = + Mockito.mockStatic(MobileCore.class); + MockedStatic base64MockedStatic = Mockito.mockStatic(Base64.class)) { + + base64MockedStatic + .when( + () -> + Base64.decode( + ArgumentMatchers.anyString(), + ArgumentMatchers.anyInt())) + .thenAnswer( + (Answer) + invocation -> + java.util.Base64.getDecoder() + .decode((String) invocation.getArguments()[0])); + + mobileCoreMockedStatic + .when( + () -> + MobileCore.dispatchEventWithResponseCallback( + ArgumentMatchers.any(Event.class), + ArgumentMatchers.anyLong(), + ArgumentMatchers.any(AdobeCallbackWithError.class))) + .thenAnswer( + (Answer) + invocation -> { + failWithOptimizeError( + callbackMockEvent, + AEPOptimizeError.Companion.getTimeoutError()); + return null; + }); + + getPropositions(scopes, timeoutMillis, callbackMock); + ArgumentCaptor errorCaptor = + ArgumentCaptor.forClass(AEPOptimizeError.class); + verify(callbackMockEvent, times(1)).fail(errorCaptor.capture()); + Assert.assertEquals( + AEPOptimizeError.Companion.getTimeoutError(), errorCaptor.getValue()); + } + } }