Home | History | Annotate | Download | only in job
      1 package com.android.server.job;
      2 
      3 
      4 import android.content.ComponentName;
      5 import android.content.Context;
      6 import android.app.job.JobInfo;
      7 import android.app.job.JobInfo.Builder;
      8 import android.os.PersistableBundle;
      9 import android.test.AndroidTestCase;
     10 import android.test.RenamingDelegatingContext;
     11 import android.util.Log;
     12 import android.util.ArraySet;
     13 
     14 import com.android.server.job.controllers.JobStatus;
     15 
     16 import java.util.Iterator;
     17 
     18 /**
     19  * Test reading and writing correctly from file.
     20  */
     21 public class JobStoreTest extends AndroidTestCase {
     22     private static final String TAG = "TaskStoreTest";
     23     private static final String TEST_PREFIX = "_test_";
     24 
     25     private static final int SOME_UID = 34234;
     26     private ComponentName mComponent;
     27     private static final long IO_WAIT = 1000L;
     28 
     29     JobStore mTaskStoreUnderTest;
     30     Context mTestContext;
     31 
     32     @Override
     33     public void setUp() throws Exception {
     34         mTestContext = new RenamingDelegatingContext(getContext(), TEST_PREFIX);
     35         Log.d(TAG, "Saving tasks to '" + mTestContext.getFilesDir() + "'");
     36         mTaskStoreUnderTest =
     37                 JobStore.initAndGetForTesting(mTestContext, mTestContext.getFilesDir());
     38         mComponent = new ComponentName(getContext().getPackageName(), StubClass.class.getName());
     39     }
     40 
     41     @Override
     42     public void tearDown() throws Exception {
     43         mTaskStoreUnderTest.clear();
     44     }
     45 
     46     public void testMaybeWriteStatusToDisk() throws Exception {
     47         int taskId = 5;
     48         long runByMillis = 20000L; // 20s
     49         long runFromMillis = 2000L; // 2s
     50         long initialBackoff = 10000L; // 10s
     51 
     52         final JobInfo task = new Builder(taskId, mComponent)
     53                 .setRequiresCharging(true)
     54                 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
     55                 .setBackoffCriteria(initialBackoff, JobInfo.BACKOFF_POLICY_EXPONENTIAL)
     56                 .setOverrideDeadline(runByMillis)
     57                 .setMinimumLatency(runFromMillis)
     58                 .setPersisted(true)
     59                 .build();
     60         final JobStatus ts = new JobStatus(task, SOME_UID);
     61         mTaskStoreUnderTest.add(ts);
     62         Thread.sleep(IO_WAIT);
     63         // Manually load tasks from xml file.
     64         final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
     65         mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
     66 
     67         assertEquals("Didn't get expected number of persisted tasks.", 1, jobStatusSet.size());
     68         final JobStatus loadedTaskStatus = jobStatusSet.iterator().next();
     69         assertTasksEqual(task, loadedTaskStatus.getJob());
     70         assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(ts));
     71         assertEquals("Different uids.", SOME_UID, loadedTaskStatus.getUid());
     72         compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
     73                 ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime());
     74         compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
     75                 ts.getLatestRunTimeElapsed(), loadedTaskStatus.getLatestRunTimeElapsed());
     76 
     77     }
     78 
     79     public void testWritingTwoFilesToDisk() throws Exception {
     80         final JobInfo task1 = new Builder(8, mComponent)
     81                 .setRequiresDeviceIdle(true)
     82                 .setPeriodic(10000L)
     83                 .setRequiresCharging(true)
     84                 .setPersisted(true)
     85                 .build();
     86         final JobInfo task2 = new Builder(12, mComponent)
     87                 .setMinimumLatency(5000L)
     88                 .setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR)
     89                 .setOverrideDeadline(30000L)
     90                 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
     91                 .setPersisted(true)
     92                 .build();
     93         final JobStatus taskStatus1 = new JobStatus(task1, SOME_UID);
     94         final JobStatus taskStatus2 = new JobStatus(task2, SOME_UID);
     95         mTaskStoreUnderTest.add(taskStatus1);
     96         mTaskStoreUnderTest.add(taskStatus2);
     97         Thread.sleep(IO_WAIT);
     98 
     99         final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
    100         mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
    101         assertEquals("Incorrect # of persisted tasks.", 2, jobStatusSet.size());
    102         Iterator<JobStatus> it = jobStatusSet.iterator();
    103         JobStatus loaded1 = it.next();
    104         JobStatus loaded2 = it.next();
    105         assertTasksEqual(task1, loaded1.getJob());
    106         assertTasksEqual(task2, loaded2.getJob());
    107         assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus1));
    108         assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus2));
    109         // Check that the loaded task has the correct runtimes.
    110         compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
    111                 taskStatus1.getEarliestRunTime(), loaded1.getEarliestRunTime());
    112         compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
    113                 taskStatus1.getLatestRunTimeElapsed(), loaded1.getLatestRunTimeElapsed());
    114         compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
    115                 taskStatus2.getEarliestRunTime(), loaded2.getEarliestRunTime());
    116         compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
    117                 taskStatus2.getLatestRunTimeElapsed(), loaded2.getLatestRunTimeElapsed());
    118 
    119     }
    120 
    121     public void testWritingTaskWithExtras() throws Exception {
    122         JobInfo.Builder b = new Builder(8, mComponent)
    123                 .setRequiresDeviceIdle(true)
    124                 .setPeriodic(10000L)
    125                 .setRequiresCharging(true)
    126                 .setPersisted(true);
    127 
    128         PersistableBundle extras = new PersistableBundle();
    129         extras.putDouble("hello", 3.2);
    130         extras.putString("hi", "there");
    131         extras.putInt("into", 3);
    132         b.setExtras(extras);
    133         final JobInfo task = b.build();
    134         JobStatus taskStatus = new JobStatus(task, SOME_UID);
    135 
    136         mTaskStoreUnderTest.add(taskStatus);
    137         Thread.sleep(IO_WAIT);
    138 
    139         final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
    140         mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
    141         assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
    142         JobStatus loaded = jobStatusSet.iterator().next();
    143         assertTasksEqual(task, loaded.getJob());
    144     }
    145 
    146     /**
    147      * Helper function to throw an error if the provided task and TaskStatus objects are not equal.
    148      */
    149     private void assertTasksEqual(JobInfo first, JobInfo second) {
    150         assertEquals("Different task ids.", first.getId(), second.getId());
    151         assertEquals("Different components.", first.getService(), second.getService());
    152         assertEquals("Different periodic status.", first.isPeriodic(), second.isPeriodic());
    153         assertEquals("Different period.", first.getIntervalMillis(), second.getIntervalMillis());
    154         assertEquals("Different inital backoff.", first.getInitialBackoffMillis(),
    155                 second.getInitialBackoffMillis());
    156         assertEquals("Different backoff policy.", first.getBackoffPolicy(),
    157                 second.getBackoffPolicy());
    158 
    159         assertEquals("Invalid charging constraint.", first.isRequireCharging(),
    160                 second.isRequireCharging());
    161         assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(),
    162                 second.isRequireDeviceIdle());
    163         assertEquals("Invalid unmetered constraint.",
    164                 first.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED,
    165                 second.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED);
    166         assertEquals("Invalid connectivity constraint.",
    167                 first.getNetworkType() == JobInfo.NETWORK_TYPE_ANY,
    168                 second.getNetworkType() == JobInfo.NETWORK_TYPE_ANY);
    169         assertEquals("Invalid deadline constraint.",
    170                 first.hasLateConstraint(),
    171                 second.hasLateConstraint());
    172         assertEquals("Invalid delay constraint.",
    173                 first.hasEarlyConstraint(),
    174                 second.hasEarlyConstraint());
    175         assertEquals("Extras don't match",
    176                 first.getExtras().toString(), second.getExtras().toString());
    177     }
    178 
    179     /**
    180      * When comparing timestamps before and after DB read/writes (to make sure we're saving/loading
    181      * the correct values), there is some latency involved that terrorises a naive assertEquals().
    182      * We define a <code>DELTA_MILLIS</code> as a function variable here to make this comparision
    183      * more reasonable.
    184      */
    185     private void compareTimestampsSubjectToIoLatency(String error, long ts1, long ts2) {
    186         final long DELTA_MILLIS = 700L;  // We allow up to 700ms of latency for IO read/writes.
    187         assertTrue(error, Math.abs(ts1 - ts2) < DELTA_MILLIS + IO_WAIT);
    188     }
    189 
    190     private static class StubClass {}
    191 
    192 }
    193