Skip to content

Commit 45b59f3

Browse files
authored
Verify remote-data info is the same when it was prepared (#1332)
1 parent 4c56635 commit 45b59f3

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

urbanairship-automation/src/main/java/com/urbanairship/automation/InAppAutomation.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public class InAppAutomation extends AirshipComponent implements InAppAutomation
7979

8080
private final Map<String, ScheduleDelegate<?>> scheduleDelegateMap = new HashMap<>();
8181
private final Map<String, FrequencyChecker> frequencyCheckerMap = new HashMap<>();
82+
private final Map<String, RemoteDataInfo> remoteDataInfoMap = new HashMap<>();
8283

8384
private final Map<String, Uri> redirectURLs = new HashMap<>();
8485

@@ -543,6 +544,7 @@ private void onPrepareSchedule(final @NonNull Schedule<? extends ScheduleData> s
543544
final AutomationDriver.PrepareScheduleCallback callbackWrapper = result -> {
544545
if (result != AutomationDriver.PREPARE_RESULT_CONTINUE) {
545546
frequencyCheckerMap.remove(schedule.getId());
547+
remoteDataInfoMap.remove(schedule.getId());
546548
}
547549
callback.onFinish(result);
548550
};
@@ -560,6 +562,12 @@ private void onPrepareSchedule(final @NonNull Schedule<? extends ScheduleData> s
560562
return RetryingExecutor.cancelResult();
561563
}
562564

565+
RemoteDataInfo info = remoteDataSubscriber.parseRemoteDataInfo(schedule);
566+
if (info != null) {
567+
remoteDataInfoMap.put(schedule.getId(), info);
568+
}
569+
570+
563571
return RetryingExecutor.finishedResult();
564572
};
565573

@@ -765,7 +773,9 @@ private int onCheckExecutionReadiness(@NonNull Schedule<? extends ScheduleData>
765773
return AutomationDriver.READY_RESULT_NOT_READY;
766774
}
767775

768-
if (!this.remoteDataSubscriber.isScheduleValid(schedule)) {
776+
RemoteDataInfo info = remoteDataSubscriber.parseRemoteDataInfo(schedule);
777+
778+
if ((info != null && !info.equals(remoteDataInfoMap.get(schedule.getId()))) || !this.remoteDataSubscriber.isScheduleValid(schedule)) {
769779
ScheduleDelegate<?> delegate = scheduleDelegateMap.remove(schedule.getId());
770780
if (delegate != null) {
771781
delegate.onExecutionInvalidated(schedule);
@@ -797,6 +807,7 @@ private void onExecuteTriggeredSchedule(@NonNull Schedule<? extends
797807
ScheduleData> schedule, @NonNull AutomationDriver.ExecutionCallback callback) {
798808
UALog.v("onExecuteTriggeredSchedule schedule: %s", schedule.getId());
799809
frequencyCheckerMap.remove(schedule.getId());
810+
remoteDataInfoMap.remove(schedule.getId());
800811

801812
ScheduleDelegate<?> delegate = scheduleDelegateMap.remove(schedule.getId());
802813
if (delegate != null) {

urbanairship-automation/src/test/java/com/urbanairship/automation/InAppAutomationTest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,59 @@ public void testOnExecuteControlEventIsSentForHoldoutGroup() {
11851185
verify(mockMessageScheduleDelegate).onExecute(schedule, executeCallback);
11861186
}
11871187

1188+
@Test
1189+
public void testRemoteDataInfoChangesBeforeExecute() {
1190+
InAppMessage message = InAppMessage.newBuilder()
1191+
.setDisplayContent(new CustomDisplayContent(JsonValue.NULL))
1192+
.build();
1193+
1194+
Schedule<InAppMessage> schedule = Schedule.newBuilder(message)
1195+
.setId("test-id")
1196+
.addTrigger(Triggers.newAppInitTriggerBuilder().setGoal(1).build())
1197+
.build();
1198+
1199+
when(mockObserver.requiresRefresh(eq(schedule))).thenReturn(false);
1200+
when(mockObserver.bestEffortRefresh(eq(schedule))).thenReturn(true);
1201+
when(mockObserver.isScheduleValid(eq(schedule))).thenReturn(true);
1202+
1203+
MessageInfo expectedInfo = new MessageInfo("transactional", null);
1204+
JsonMap experimentMetadata = JsonMap
1205+
.newBuilder()
1206+
.put("report", "metadata")
1207+
.build();
1208+
1209+
List<JsonMap> metadata = Collections.singletonList(experimentMetadata);
1210+
ExperimentResult results = new ExperimentResult("cid", "coid", "eid", true, metadata);
1211+
1212+
PendingResult<ExperimentResult> pendingResult = new PendingResult<>();
1213+
pendingResult.setResult(results);
1214+
doReturn(pendingResult)
1215+
.when(mockExperimentManager)
1216+
.evaluateGlobalHoldoutsPendingResult(eq(expectedInfo), nullable(String.class));
1217+
1218+
doReturn(new RemoteDataInfo("url", null, RemoteDataSource.APP, null))
1219+
.when(mockObserver).parseRemoteDataInfo(eq(schedule));
1220+
1221+
AutomationDriver.PrepareScheduleCallback callback = mock(AutomationDriver.PrepareScheduleCallback.class);
1222+
driver.onPrepareSchedule(schedule, null, callback);
1223+
1224+
ArgumentCaptor<AutomationDriver.PrepareScheduleCallback> argumentCaptor = ArgumentCaptor.forClass(AutomationDriver.PrepareScheduleCallback.class);
1225+
verify(mockMessageScheduleDelegate, times(1)).onPrepareSchedule(eq(schedule), eq(schedule.getData()), eq(results), argumentCaptor.capture());
1226+
argumentCaptor.getValue().onFinish(AutomationDriver.PREPARE_RESULT_CONTINUE);
1227+
verify(callback).onFinish(AutomationDriver.PREPARE_RESULT_CONTINUE);
1228+
1229+
// Verify its not invalid before the remote-data info changes
1230+
assertEquals(AutomationDriver.READY_RESULT_NOT_READY, driver.onCheckExecutionReadiness(schedule));
1231+
1232+
// Change remote data
1233+
doReturn(new RemoteDataInfo("some other url", null, RemoteDataSource.APP, null))
1234+
.when(mockObserver).parseRemoteDataInfo(eq(schedule));
1235+
1236+
// Should be invalid since the remote-data info is not longer the same as when it was prepared
1237+
assertEquals(AutomationDriver.READY_RESULT_INVALIDATE, driver.onCheckExecutionReadiness(schedule));
1238+
1239+
}
1240+
11881241
/**
11891242
* Helper method to run all the looper tasks.
11901243
*/

0 commit comments

Comments
 (0)