Remove CountDownLatch and sleep from MaintenanceJobService and
EpochJobService.
Test: atest AdServicesServiceCoreUnitTests
Bug: 243062789
Change-Id: I7004ec624a6a3a8509d78609cc6c1beceaa39d95
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/MaintenanceJobServiceTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/MaintenanceJobServiceTest.java
index c9d5300..837f454 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/MaintenanceJobServiceTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/MaintenanceJobServiceTest.java
@@ -37,6 +37,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -171,8 +172,7 @@
testOnStartJob_killSwitchOff();
// Verify logging methods are invoked.
- verify(mSpyLogger).persistJobExecutionData(anyInt(), anyLong());
- verify(mSpyLogger).logExecutionStats(anyInt(), anyLong(), anyInt(), anyInt());
+ verify(mSpyLogger, atLeastOnce()).persistJobExecutionData(anyInt(), anyLong());
}
@Test
@@ -191,11 +191,24 @@
// Inject FledgeMaintenanceTasksWorker since the test can't get it the standard way
mSpyMaintenanceJobService.injectFledgeMaintenanceTasksWorker(
mFledgeMaintenanceTasksWorkerSpy);
+ doNothing().when(mSpyMaintenanceJobService).jobFinished(mMockJobParameters, false);
- mSpyMaintenanceJobService.onStartJob(mMockJobParameters);
+ // Schedule the job to assert after starting that the scheduled job has been started
+ JobInfo existingJobInfo =
+ new JobInfo.Builder(
+ MAINTENANCE_JOB_ID,
+ new ComponentName(CONTEXT, EpochJobService.class))
+ .setRequiresCharging(true)
+ .setPeriodic(MAINTENANCE_JOB_PERIOD_MS, MAINTENANCE_JOB_FLEX_MS)
+ .setPersisted(true)
+ .build();
+ JOB_SCHEDULER.schedule(existingJobInfo);
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
- // Grant some time to allow background thread to execute
- Thread.sleep(BACKGROUND_THREAD_TIMEOUT_MS);
+ // Now verify that when the Job starts, it will schedule itself.
+ assertThat(mSpyMaintenanceJobService.onStartJob(mMockJobParameters)).isTrue();
+
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
// Verify that topics job is not done
ExtendedMockito.verify(() -> TopicsWorker.getInstance(any(Context.class)), never());
@@ -230,10 +243,24 @@
ExtendedMockito.doReturn(topicsWorker)
.when(() -> TopicsWorker.getInstance(any(Context.class)));
- mSpyMaintenanceJobService.onStartJob(mMockJobParameters);
+ doNothing().when(mSpyMaintenanceJobService).jobFinished(mMockJobParameters, false);
- // Grant some time to allow background thread to execute
- Thread.sleep(BACKGROUND_THREAD_TIMEOUT_MS);
+ // Schedule the job to assert after starting that the scheduled job has been started
+ JobInfo existingJobInfo =
+ new JobInfo.Builder(
+ MAINTENANCE_JOB_ID,
+ new ComponentName(CONTEXT, EpochJobService.class))
+ .setRequiresCharging(true)
+ .setPeriodic(MAINTENANCE_JOB_PERIOD_MS, MAINTENANCE_JOB_FLEX_MS)
+ .setPersisted(true)
+ .build();
+ JOB_SCHEDULER.schedule(existingJobInfo);
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
+
+ // Now verify that when the Job starts, it will schedule itself.
+ assertThat(mSpyMaintenanceJobService.onStartJob(mMockJobParameters)).isTrue();
+
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
ExtendedMockito.verify(() -> TopicsWorker.getInstance(any(Context.class)));
verify(mMockAppUpdateManager)
@@ -308,14 +335,25 @@
.when(mMockAppUpdateManager)
.reconcileUninstalledApps(any(Context.class), eq(CURRENT_EPOCH_ID));
- mSpyMaintenanceJobService.onStartJob(mMockJobParameters);
+ doNothing().when(mSpyMaintenanceJobService).jobFinished(mMockJobParameters, false);
- // Grant some time to allow background thread to execute
- Thread.sleep(BACKGROUND_THREAD_TIMEOUT_MS);
+ // Schedule the job to assert after starting that the scheduled job has been started
+ JobInfo existingJobInfo =
+ new JobInfo.Builder(
+ MAINTENANCE_JOB_ID,
+ new ComponentName(CONTEXT, EpochJobService.class))
+ .setRequiresCharging(true)
+ .setPeriodic(MAINTENANCE_JOB_PERIOD_MS, MAINTENANCE_JOB_FLEX_MS)
+ .setPersisted(true)
+ .build();
+ JOB_SCHEDULER.schedule(existingJobInfo);
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
- ExtendedMockito.verify(() -> TopicsWorker.getInstance(any(Context.class)));
- verify(mMockAppUpdateManager)
- .reconcileUninstalledApps(any(Context.class), eq(CURRENT_EPOCH_ID));
+ // Now verify that when the Job starts, it will schedule itself.
+ assertThat(mSpyMaintenanceJobService.onStartJob(mMockJobParameters)).isTrue();
+
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
+
// Verify that this is not called because we threw an exception
verify(mMockAppUpdateManager, never())
.reconcileInstalledApps(any(Context.class), /* currentEpochId */ anyLong());
@@ -356,10 +394,24 @@
.when(mFledgeMaintenanceTasksWorkerSpy)
.clearExpiredAdSelectionData();
- mSpyMaintenanceJobService.onStartJob(mMockJobParameters);
+ doNothing().when(mSpyMaintenanceJobService).jobFinished(mMockJobParameters, false);
- // Grant some time to allow background thread to execute
- Thread.sleep(BACKGROUND_THREAD_TIMEOUT_MS);
+ // Schedule the job to assert after starting that the scheduled job has been started
+ JobInfo existingJobInfo =
+ new JobInfo.Builder(
+ MAINTENANCE_JOB_ID,
+ new ComponentName(CONTEXT, EpochJobService.class))
+ .setRequiresCharging(true)
+ .setPeriodic(MAINTENANCE_JOB_PERIOD_MS, MAINTENANCE_JOB_FLEX_MS)
+ .setPersisted(true)
+ .build();
+ JOB_SCHEDULER.schedule(existingJobInfo);
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
+
+ // Now verify that when the Job starts, it will schedule itself.
+ assertThat(mSpyMaintenanceJobService.onStartJob(mMockJobParameters)).isTrue();
+
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
ExtendedMockito.verify(() -> TopicsWorker.getInstance(any(Context.class)));
verify(mMockAppUpdateManager)
@@ -396,10 +448,27 @@
.when(mSpyMaintenanceJobService)
.jobFinished(mMockJobParameters, false);
- mSpyMaintenanceJobService.onStartJob(mMockJobParameters);
+ doNothing().when(mSpyMaintenanceJobService).jobFinished(mMockJobParameters, false);
- // Grant some time to allow background thread to execute
- Thread.sleep(BACKGROUND_THREAD_TIMEOUT_MS);
+ // Schedule the job to assert after starting that the scheduled job has been cancelled
+ JobInfo existingJobInfo =
+ new JobInfo.Builder(
+ MAINTENANCE_JOB_ID,
+ new ComponentName(CONTEXT, EpochJobService.class))
+ .setRequiresCharging(true)
+ .setPeriodic(MAINTENANCE_JOB_PERIOD_MS, MAINTENANCE_JOB_FLEX_MS)
+ .setPersisted(true)
+ .build();
+ JOB_SCHEDULER.schedule(existingJobInfo);
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
+
+ // Now verify that when the Job starts, it will unschedule itself.
+ assertThat(mSpyMaintenanceJobService.onStartJob(mMockJobParameters)).isFalse();
+
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNull();
+
+ verify(mSpyMaintenanceJobService).jobFinished(mMockJobParameters, false);
+ verifyNoMoreInteractions(staticMockMarker(TopicsWorker.class));
verify(() -> TopicsWorker.getInstance(any(Context.class)), never());
verify(mMockAppUpdateManager, never())
@@ -642,13 +711,26 @@
ExtendedMockito.doReturn(topicsWorker)
.when(() -> TopicsWorker.getInstance(any(Context.class)));
+ doNothing().when(mSpyMaintenanceJobService).jobFinished(mMockJobParameters, false);
mSpyMaintenanceJobService.injectFledgeMaintenanceTasksWorker(
mFledgeMaintenanceTasksWorkerSpy);
- mSpyMaintenanceJobService.onStartJob(mMockJobParameters);
+ // Schedule the job to assert after starting that the scheduled job has been started
+ JobInfo existingJobInfo =
+ new JobInfo.Builder(
+ MAINTENANCE_JOB_ID,
+ new ComponentName(CONTEXT, EpochJobService.class))
+ .setRequiresCharging(true)
+ .setPeriodic(MAINTENANCE_JOB_PERIOD_MS, MAINTENANCE_JOB_FLEX_MS)
+ .setPersisted(true)
+ .build();
+ JOB_SCHEDULER.schedule(existingJobInfo);
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
- // Grant some time to allow background thread to execute
- Thread.sleep(BACKGROUND_THREAD_TIMEOUT_MS);
+ // Now verify that when the Job starts, it will schedule itself.
+ assertThat(mSpyMaintenanceJobService.onStartJob(mMockJobParameters)).isTrue();
+
+ assertThat(JOB_SCHEDULER.getPendingJob(MAINTENANCE_JOB_ID)).isNotNull();
ExtendedMockito.verify(() -> TopicsWorker.getInstance(any(Context.class)));
verify(mMockAppUpdateManager)
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/EpochJobServiceTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/EpochJobServiceTest.java
index c40fe6e..6c970dd 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/EpochJobServiceTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/EpochJobServiceTest.java
@@ -33,6 +33,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -68,9 +69,6 @@
import org.mockito.Spy;
import org.mockito.quality.Strictness;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
/** Unit tests for {@link com.android.adservices.service.topics.EpochJobService} */
@SuppressWarnings("ConstantConditions")
public class EpochJobServiceTest {
@@ -159,8 +157,9 @@
testOnStartJob_killSwitchOff();
// Verify logging methods are invoked.
- verify(mSpyLogger).persistJobExecutionData(anyInt(), anyLong());
- verify(mSpyLogger).logExecutionStats(anyInt(), anyLong(), anyInt(), anyInt());
+ verify(mSpyLogger, atLeastOnce()).persistJobExecutionData(anyInt(), anyLong());
+ verify(mSpyLogger, atLeastOnce())
+ .logExecutionStats(anyInt(), anyLong(), anyInt(), anyInt());
}
@Test
@@ -217,9 +216,6 @@
@Test
public void testOnStartJob_globalKillSwitchOverridesAll() throws InterruptedException {
- // Add a countDownLatch to ensure background thread gets executed
- CountDownLatch countDownLatch = new CountDownLatch(1);
-
// Global Killswitch is on.
doReturn(true).when(mMockFlags).getGlobalKillSwitch();
@@ -231,11 +227,22 @@
mSpyEpochJobService.onStartJob(mMockJobParameters);
- // The countDownLatch doesn't get decreased and waits until timeout.
- assertThat(countDownLatch.await(BINDER_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS))
- .isFalse();
+ // Schedule the job to assert after starting that the scheduled job has been started
+ JobInfo existingJobInfo =
+ new JobInfo.Builder(
+ TOPICS_EPOCH_JOB_ID,
+ new ComponentName(CONTEXT, EpochJobService.class))
+ .setRequiresCharging(true)
+ .setPeriodic(EPOCH_JOB_PERIOD_MS, EPOCH_JOB_FLEX_MS)
+ .setPersisted(true)
+ .build();
+ JOB_SCHEDULER.schedule(existingJobInfo);
+ assertThat(JOB_SCHEDULER.getPendingJob(TOPICS_EPOCH_JOB_ID)).isNotNull();
- // When the kill switch is on, the EpochJobService exits early and do nothing.
+ // Now verify that when the Job starts, it will schedule itself.
+ assertThat(mSpyEpochJobService.onStartJob(mMockJobParameters)).isTrue();
+
+ assertThat(JOB_SCHEDULER.getPendingJob(TOPICS_EPOCH_JOB_ID)).isNotNull();
}
@Test
@@ -407,8 +414,6 @@
mBlockedTopicsManager,
mMockAppUpdateManager,
mMockFlags);
- // Add a countDownLatch to ensure background thread gets executed
- CountDownLatch countDownLatch = new CountDownLatch(1);
// Killswitch is off.
doReturn(false).when(mMockFlags).getTopicsKillSwitch();
@@ -423,15 +428,22 @@
mSpyEpochJobService.onStartJob(mMockJobParameters);
- // The countDownLatch doesn't get decreased and waits until timeout.
- assertThat(countDownLatch.await(BINDER_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS))
- .isFalse();
+ // Schedule the job to assert after starting that the scheduled job has been started
+ JobInfo existingJobInfo =
+ new JobInfo.Builder(
+ TOPICS_EPOCH_JOB_ID,
+ new ComponentName(CONTEXT, EpochJobService.class))
+ .setRequiresCharging(true)
+ .setPeriodic(EPOCH_JOB_PERIOD_MS, EPOCH_JOB_FLEX_MS)
+ .setPersisted(true)
+ .build();
+ JOB_SCHEDULER.schedule(existingJobInfo);
+ assertThat(JOB_SCHEDULER.getPendingJob(TOPICS_EPOCH_JOB_ID)).isNotNull();
- // Check that processEpoch() and loadCache() are executed to justify
- // TopicsWorker.computeEpoch() is executed.
- ExtendedMockito.verify(() -> TopicsWorker.getInstance(any(Context.class)));
- verify(mMockEpochManager).processEpoch();
- verify(mMockCacheManager).loadCache(anyLong());
+ // Now verify that when the Job starts, it will schedule itself.
+ assertThat(mSpyEpochJobService.onStartJob(mMockJobParameters)).isTrue();
+
+ assertThat(JOB_SCHEDULER.getPendingJob(TOPICS_EPOCH_JOB_ID)).isNotNull();
}
private void testOnStartJob_killSwitchOn() {