Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 1 | package com.android.server.job; |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 2 | |
| 3 | |
| 4 | import android.content.ComponentName; |
| 5 | import android.content.Context; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 6 | import android.app.job.JobInfo; |
| 7 | import android.app.job.JobInfo.Builder; |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 8 | import android.os.PersistableBundle; |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 9 | import android.os.SystemClock; |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 10 | import android.test.AndroidTestCase; |
| 11 | import android.test.RenamingDelegatingContext; |
| 12 | import android.util.Log; |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 13 | import android.util.Pair; |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 14 | |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 15 | import com.android.server.job.JobStore.JobSet; |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 16 | import com.android.server.job.controllers.JobStatus; |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 17 | |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 18 | import java.util.Iterator; |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 19 | |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 20 | /** |
| 21 | * Test reading and writing correctly from file. |
| 22 | */ |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 23 | public class JobStoreTest extends AndroidTestCase { |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 24 | private static final String TAG = "TaskStoreTest"; |
| 25 | private static final String TEST_PREFIX = "_test_"; |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 26 | |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 27 | private static final int SOME_UID = 34234; |
| 28 | private ComponentName mComponent; |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 29 | private static final long IO_WAIT = 1000L; |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 30 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 31 | JobStore mTaskStoreUnderTest; |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 32 | Context mTestContext; |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 33 | |
| 34 | @Override |
| 35 | public void setUp() throws Exception { |
| 36 | mTestContext = new RenamingDelegatingContext(getContext(), TEST_PREFIX); |
| 37 | Log.d(TAG, "Saving tasks to '" + mTestContext.getFilesDir() + "'"); |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 38 | mTaskStoreUnderTest = |
| 39 | JobStore.initAndGetForTesting(mTestContext, mTestContext.getFilesDir()); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 40 | mComponent = new ComponentName(getContext().getPackageName(), StubClass.class.getName()); |
| 41 | } |
| 42 | |
| 43 | @Override |
| 44 | public void tearDown() throws Exception { |
| 45 | mTaskStoreUnderTest.clear(); |
| 46 | } |
| 47 | |
| 48 | public void testMaybeWriteStatusToDisk() throws Exception { |
| 49 | int taskId = 5; |
| 50 | long runByMillis = 20000L; // 20s |
| 51 | long runFromMillis = 2000L; // 2s |
| 52 | long initialBackoff = 10000L; // 10s |
| 53 | |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 54 | final JobInfo task = new Builder(taskId, mComponent) |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 55 | .setRequiresCharging(true) |
Matthew Williams | d1c0675 | 2014-08-22 14:15:28 -0700 | [diff] [blame] | 56 | .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) |
| 57 | .setBackoffCriteria(initialBackoff, JobInfo.BACKOFF_POLICY_EXPONENTIAL) |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 58 | .setOverrideDeadline(runByMillis) |
| 59 | .setMinimumLatency(runFromMillis) |
Matthew Williams | d1c0675 | 2014-08-22 14:15:28 -0700 | [diff] [blame] | 60 | .setPersisted(true) |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 61 | .build(); |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 62 | final JobStatus ts = JobStatus.createFromJobInfo(task, SOME_UID, null, -1, null); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 63 | mTaskStoreUnderTest.add(ts); |
| 64 | Thread.sleep(IO_WAIT); |
| 65 | // Manually load tasks from xml file. |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 66 | final JobSet jobStatusSet = new JobSet(); |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 67 | mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true); |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 68 | |
| 69 | assertEquals("Didn't get expected number of persisted tasks.", 1, jobStatusSet.size()); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 70 | final JobStatus loadedTaskStatus = jobStatusSet.getAllJobs().get(0); |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 71 | assertTasksEqual(task, loadedTaskStatus.getJob()); |
Matthew Williams | 48a30db | 2014-09-23 13:39:36 -0700 | [diff] [blame] | 72 | assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(ts)); |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 73 | assertEquals("Different uids.", SOME_UID, loadedTaskStatus.getUid()); |
| 74 | compareTimestampsSubjectToIoLatency("Early run-times not the same after read.", |
| 75 | ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime()); |
| 76 | compareTimestampsSubjectToIoLatency("Late run-times not the same after read.", |
| 77 | ts.getLatestRunTimeElapsed(), loadedTaskStatus.getLatestRunTimeElapsed()); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 78 | |
| 79 | } |
| 80 | |
| 81 | public void testWritingTwoFilesToDisk() throws Exception { |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 82 | final JobInfo task1 = new Builder(8, mComponent) |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 83 | .setRequiresDeviceIdle(true) |
| 84 | .setPeriodic(10000L) |
| 85 | .setRequiresCharging(true) |
Matthew Williams | d1c0675 | 2014-08-22 14:15:28 -0700 | [diff] [blame] | 86 | .setPersisted(true) |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 87 | .build(); |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 88 | final JobInfo task2 = new Builder(12, mComponent) |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 89 | .setMinimumLatency(5000L) |
Matthew Williams | d1c0675 | 2014-08-22 14:15:28 -0700 | [diff] [blame] | 90 | .setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR) |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 91 | .setOverrideDeadline(30000L) |
Matthew Williams | d1c0675 | 2014-08-22 14:15:28 -0700 | [diff] [blame] | 92 | .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) |
| 93 | .setPersisted(true) |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 94 | .build(); |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 95 | final JobStatus taskStatus1 = JobStatus.createFromJobInfo(task1, SOME_UID, null, -1, null); |
| 96 | final JobStatus taskStatus2 = JobStatus.createFromJobInfo(task2, SOME_UID, null, -1, null); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 97 | mTaskStoreUnderTest.add(taskStatus1); |
| 98 | mTaskStoreUnderTest.add(taskStatus2); |
| 99 | Thread.sleep(IO_WAIT); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 100 | |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 101 | final JobSet jobStatusSet = new JobSet(); |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 102 | mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true); |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 103 | assertEquals("Incorrect # of persisted tasks.", 2, jobStatusSet.size()); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 104 | Iterator<JobStatus> it = jobStatusSet.getAllJobs().iterator(); |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 105 | JobStatus loaded1 = it.next(); |
| 106 | JobStatus loaded2 = it.next(); |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 107 | |
| 108 | // Reverse them so we know which comparison to make. |
| 109 | if (loaded1.getJobId() != 8) { |
| 110 | JobStatus tmp = loaded1; |
| 111 | loaded1 = loaded2; |
| 112 | loaded2 = tmp; |
| 113 | } |
| 114 | |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 115 | assertTasksEqual(task1, loaded1.getJob()); |
| 116 | assertTasksEqual(task2, loaded2.getJob()); |
Matthew Williams | 48a30db | 2014-09-23 13:39:36 -0700 | [diff] [blame] | 117 | assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus1)); |
| 118 | assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus2)); |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 119 | // Check that the loaded task has the correct runtimes. |
| 120 | compareTimestampsSubjectToIoLatency("Early run-times not the same after read.", |
| 121 | taskStatus1.getEarliestRunTime(), loaded1.getEarliestRunTime()); |
| 122 | compareTimestampsSubjectToIoLatency("Late run-times not the same after read.", |
| 123 | taskStatus1.getLatestRunTimeElapsed(), loaded1.getLatestRunTimeElapsed()); |
| 124 | compareTimestampsSubjectToIoLatency("Early run-times not the same after read.", |
| 125 | taskStatus2.getEarliestRunTime(), loaded2.getEarliestRunTime()); |
| 126 | compareTimestampsSubjectToIoLatency("Late run-times not the same after read.", |
| 127 | taskStatus2.getLatestRunTimeElapsed(), loaded2.getLatestRunTimeElapsed()); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 128 | |
| 129 | } |
| 130 | |
| 131 | public void testWritingTaskWithExtras() throws Exception { |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 132 | JobInfo.Builder b = new Builder(8, mComponent) |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 133 | .setRequiresDeviceIdle(true) |
| 134 | .setPeriodic(10000L) |
Matthew Williams | 900c67f | 2014-07-09 12:46:53 -0700 | [diff] [blame] | 135 | .setRequiresCharging(true) |
Matthew Williams | d1c0675 | 2014-08-22 14:15:28 -0700 | [diff] [blame] | 136 | .setPersisted(true); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 137 | |
| 138 | PersistableBundle extras = new PersistableBundle(); |
| 139 | extras.putDouble("hello", 3.2); |
| 140 | extras.putString("hi", "there"); |
| 141 | extras.putInt("into", 3); |
| 142 | b.setExtras(extras); |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 143 | final JobInfo task = b.build(); |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 144 | JobStatus taskStatus = JobStatus.createFromJobInfo(task, SOME_UID, null, -1, null); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 145 | |
| 146 | mTaskStoreUnderTest.add(taskStatus); |
| 147 | Thread.sleep(IO_WAIT); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 148 | |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 149 | final JobSet jobStatusSet = new JobSet(); |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 150 | mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true); |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 151 | assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size()); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 152 | JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 153 | assertTasksEqual(task, loaded.getJob()); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 154 | } |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 155 | public void testWritingTaskWithSourcePackage() throws Exception { |
| 156 | JobInfo.Builder b = new Builder(8, mComponent) |
| 157 | .setRequiresDeviceIdle(true) |
| 158 | .setPeriodic(10000L) |
| 159 | .setRequiresCharging(true) |
| 160 | .setPersisted(true); |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 161 | JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID, |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 162 | "com.google.android.gms", 0, null); |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 163 | |
| 164 | mTaskStoreUnderTest.add(taskStatus); |
| 165 | Thread.sleep(IO_WAIT); |
| 166 | |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 167 | final JobSet jobStatusSet = new JobSet(); |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 168 | mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true); |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 169 | assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size()); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 170 | JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 171 | assertEquals("Source package not equal.", loaded.getSourcePackageName(), |
| 172 | taskStatus.getSourcePackageName()); |
| 173 | assertEquals("Source user not equal.", loaded.getSourceUserId(), |
| 174 | taskStatus.getSourceUserId()); |
| 175 | } |
| 176 | |
| 177 | public void testWritingTaskWithFlex() throws Exception { |
| 178 | JobInfo.Builder b = new Builder(8, mComponent) |
| 179 | .setRequiresDeviceIdle(true) |
| 180 | .setPeriodic(5*60*60*1000, 1*60*60*1000) |
| 181 | .setRequiresCharging(true) |
| 182 | .setPersisted(true); |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 183 | JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null); |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 184 | |
| 185 | mTaskStoreUnderTest.add(taskStatus); |
| 186 | Thread.sleep(IO_WAIT); |
| 187 | |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 188 | final JobSet jobStatusSet = new JobSet(); |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 189 | mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true); |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 190 | assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size()); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 191 | JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 192 | assertEquals("Period not equal.", loaded.getJob().getIntervalMillis(), |
| 193 | taskStatus.getJob().getIntervalMillis()); |
| 194 | assertEquals("Flex not equal.", loaded.getJob().getFlexMillis(), |
| 195 | taskStatus.getJob().getFlexMillis()); |
| 196 | } |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 197 | |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 198 | public void testMassivePeriodClampedOnRead() throws Exception { |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 199 | final long ONE_HOUR = 60*60*1000L; // flex |
| 200 | final long TWO_HOURS = 2 * ONE_HOUR; // period |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 201 | JobInfo.Builder b = new Builder(8, mComponent) |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 202 | .setPeriodic(TWO_HOURS, ONE_HOUR) |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 203 | .setPersisted(true); |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 204 | final long rtcNow = System.currentTimeMillis(); |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 205 | final long invalidLateRuntimeElapsedMillis = |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 206 | SystemClock.elapsedRealtime() + (TWO_HOURS * ONE_HOUR) + TWO_HOURS; // > period+flex |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 207 | final long invalidEarlyRuntimeElapsedMillis = |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 208 | invalidLateRuntimeElapsedMillis - TWO_HOURS; // Early is (late - period). |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 209 | final Pair<Long, Long> persistedExecutionTimesUTC = new Pair<>(rtcNow, rtcNow + ONE_HOUR); |
Dianne Hackborn | b0001f6 | 2016-02-16 10:30:33 -0800 | [diff] [blame] | 210 | final JobStatus js = new JobStatus(b.build(), SOME_UID, "somePackage", |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 211 | 0 /* sourceUserId */, "someTag", |
Makoto Onuki | ab8a67f | 2017-06-20 12:20:34 -0700 | [diff] [blame] | 212 | invalidEarlyRuntimeElapsedMillis, invalidLateRuntimeElapsedMillis, |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 213 | 0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */, |
| 214 | persistedExecutionTimesUTC); |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 215 | |
| 216 | mTaskStoreUnderTest.add(js); |
| 217 | Thread.sleep(IO_WAIT); |
| 218 | |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 219 | final JobSet jobStatusSet = new JobSet(); |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 220 | mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true); |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 221 | assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size()); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 222 | JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 223 | |
| 224 | // Assert early runtime was clamped to be under now + period. We can do <= here b/c we'll |
| 225 | // call SystemClock.elapsedRealtime after doing the disk i/o. |
| 226 | final long newNowElapsed = SystemClock.elapsedRealtime(); |
| 227 | assertTrue("Early runtime wasn't correctly clamped.", |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 228 | loaded.getEarliestRunTime() <= newNowElapsed + TWO_HOURS); |
| 229 | // Assert late runtime was clamped to be now + period + flex. |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 230 | assertTrue("Early runtime wasn't correctly clamped.", |
Shreyas Basarge | 8e64e2e | 2016-02-12 15:49:31 +0000 | [diff] [blame] | 231 | loaded.getEarliestRunTime() <= newNowElapsed + TWO_HOURS + ONE_HOUR); |
Shreyas Basarge | 5db0908 | 2016-01-07 13:38:29 +0000 | [diff] [blame] | 232 | } |
| 233 | |
| 234 | public void testPriorityPersisted() throws Exception { |
| 235 | JobInfo.Builder b = new Builder(92, mComponent) |
| 236 | .setOverrideDeadline(5000) |
| 237 | .setPriority(42) |
| 238 | .setPersisted(true); |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 239 | final JobStatus js = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null); |
Shreyas Basarge | 5db0908 | 2016-01-07 13:38:29 +0000 | [diff] [blame] | 240 | mTaskStoreUnderTest.add(js); |
| 241 | Thread.sleep(IO_WAIT); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 242 | final JobSet jobStatusSet = new JobSet(); |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 243 | mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 244 | JobStatus loaded = jobStatusSet.getAllJobs().iterator().next(); |
Shreyas Basarge | 5db0908 | 2016-01-07 13:38:29 +0000 | [diff] [blame] | 245 | assertEquals("Priority not correctly persisted.", 42, loaded.getPriority()); |
Matthew Williams | fa8e508 | 2015-10-15 15:59:12 -0700 | [diff] [blame] | 246 | } |
| 247 | |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 248 | /** |
Shreyas Basarge | 7ef490f | 2015-12-03 16:45:22 +0000 | [diff] [blame] | 249 | * Test that non persisted job is not written to disk. |
| 250 | */ |
| 251 | public void testNonPersistedTaskIsNotPersisted() throws Exception { |
| 252 | JobInfo.Builder b = new Builder(42, mComponent) |
| 253 | .setOverrideDeadline(10000) |
| 254 | .setPersisted(false); |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 255 | JobStatus jsNonPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null); |
Shreyas Basarge | 7ef490f | 2015-12-03 16:45:22 +0000 | [diff] [blame] | 256 | mTaskStoreUnderTest.add(jsNonPersisted); |
| 257 | b = new Builder(43, mComponent) |
| 258 | .setOverrideDeadline(10000) |
| 259 | .setPersisted(true); |
Dianne Hackborn | 1085ff6 | 2016-02-23 17:04:58 -0800 | [diff] [blame] | 260 | JobStatus jsPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null); |
Shreyas Basarge | 7ef490f | 2015-12-03 16:45:22 +0000 | [diff] [blame] | 261 | mTaskStoreUnderTest.add(jsPersisted); |
| 262 | Thread.sleep(IO_WAIT); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 263 | final JobSet jobStatusSet = new JobSet(); |
Christopher Tate | 616541d | 2017-07-26 14:27:38 -0700 | [diff] [blame] | 264 | mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true); |
Shreyas Basarge | 7ef490f | 2015-12-03 16:45:22 +0000 | [diff] [blame] | 265 | assertEquals("Job count is incorrect.", 1, jobStatusSet.size()); |
Christopher Tate | 2f36fd6 | 2016-02-18 18:36:08 -0800 | [diff] [blame] | 266 | JobStatus jobStatus = jobStatusSet.getAllJobs().iterator().next(); |
Shreyas Basarge | 7ef490f | 2015-12-03 16:45:22 +0000 | [diff] [blame] | 267 | assertEquals("Wrong job persisted.", 43, jobStatus.getJobId()); |
| 268 | } |
| 269 | |
| 270 | /** |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 271 | * Helper function to throw an error if the provided task and TaskStatus objects are not equal. |
| 272 | */ |
Christopher Tate | 7060b04 | 2014-06-09 19:50:00 -0700 | [diff] [blame] | 273 | private void assertTasksEqual(JobInfo first, JobInfo second) { |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 274 | assertEquals("Different task ids.", first.getId(), second.getId()); |
| 275 | assertEquals("Different components.", first.getService(), second.getService()); |
| 276 | assertEquals("Different periodic status.", first.isPeriodic(), second.isPeriodic()); |
| 277 | assertEquals("Different period.", first.getIntervalMillis(), second.getIntervalMillis()); |
| 278 | assertEquals("Different inital backoff.", first.getInitialBackoffMillis(), |
| 279 | second.getInitialBackoffMillis()); |
| 280 | assertEquals("Different backoff policy.", first.getBackoffPolicy(), |
| 281 | second.getBackoffPolicy()); |
| 282 | |
| 283 | assertEquals("Invalid charging constraint.", first.isRequireCharging(), |
| 284 | second.isRequireCharging()); |
Dianne Hackborn | a06ec6a | 2017-02-13 10:08:42 -0800 | [diff] [blame] | 285 | assertEquals("Invalid battery not low constraint.", first.isRequireBatteryNotLow(), |
| 286 | second.isRequireBatteryNotLow()); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 287 | assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(), |
| 288 | second.isRequireDeviceIdle()); |
| 289 | assertEquals("Invalid unmetered constraint.", |
Matthew Williams | d1c0675 | 2014-08-22 14:15:28 -0700 | [diff] [blame] | 290 | first.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED, |
| 291 | second.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 292 | assertEquals("Invalid connectivity constraint.", |
Matthew Williams | d1c0675 | 2014-08-22 14:15:28 -0700 | [diff] [blame] | 293 | first.getNetworkType() == JobInfo.NETWORK_TYPE_ANY, |
| 294 | second.getNetworkType() == JobInfo.NETWORK_TYPE_ANY); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 295 | assertEquals("Invalid deadline constraint.", |
| 296 | first.hasLateConstraint(), |
| 297 | second.hasLateConstraint()); |
| 298 | assertEquals("Invalid delay constraint.", |
| 299 | first.hasEarlyConstraint(), |
| 300 | second.hasEarlyConstraint()); |
| 301 | assertEquals("Extras don't match", |
| 302 | first.getExtras().toString(), second.getExtras().toString()); |
Dianne Hackborn | ba60473 | 2016-02-10 17:05:10 -0800 | [diff] [blame] | 303 | assertEquals("Transient xtras don't match", |
| 304 | first.getTransientExtras().toString(), second.getTransientExtras().toString()); |
Matthew Williams | 3d86fd2 | 2014-05-16 18:02:17 -0700 | [diff] [blame] | 305 | } |
| 306 | |
| 307 | /** |
| 308 | * When comparing timestamps before and after DB read/writes (to make sure we're saving/loading |
| 309 | * the correct values), there is some latency involved that terrorises a naive assertEquals(). |
| 310 | * We define a <code>DELTA_MILLIS</code> as a function variable here to make this comparision |
| 311 | * more reasonable. |
| 312 | */ |
| 313 | private void compareTimestampsSubjectToIoLatency(String error, long ts1, long ts2) { |
| 314 | final long DELTA_MILLIS = 700L; // We allow up to 700ms of latency for IO read/writes. |
| 315 | assertTrue(error, Math.abs(ts1 - ts2) < DELTA_MILLIS + IO_WAIT); |
| 316 | } |
| 317 | |
| 318 | private static class StubClass {} |
| 319 | |
Matthew Williams | 01ac45b | 2014-07-22 20:44:12 -0700 | [diff] [blame] | 320 | } |