/*package*/ static JobRequest fromCursor(Cursor cursor) { JobRequest request = new Builder(cursor).build(); request.mFailureCount = cursor.getInt(cursor.getColumnIndex(JobStorage.COLUMN_NUM_FAILURES)); request.mScheduledAt = cursor.getLong(cursor.getColumnIndex(JobStorage.COLUMN_SCHEDULED_AT)); request.mStarted = cursor.getInt(cursor.getColumnIndex(JobStorage.COLUMN_STARTED)) > 0; request.mFlexSupport = cursor.getInt(cursor.getColumnIndex(JobStorage.COLUMN_FLEX_SUPPORT)) > 0; request.mLastRun = cursor.getLong(cursor.getColumnIndex(JobStorage.COLUMN_LAST_RUN)); JobPreconditions.checkArgumentNonnegative(request.mFailureCount, "failure count can't be negative"); JobPreconditions.checkArgumentNonnegative(request.mScheduledAt, "scheduled at can't be negative"); return request; }
@Test public void testPeriodicJobNotInStartedState() throws Throwable { int jobId = DummyJobs.createBuilder(DummyJobs.TwoSecondPauseJob.class) .setPeriodic(TimeUnit.MINUTES.toMillis(15)) .build() .schedule(); executeJobAsync(jobId, Job.Result.SUCCESS); // wait until the job is started Thread.sleep(100); // request should be in started state, running but not removed from DB JobRequest startedRequest = manager().getJobRequest(jobId, true); assertThat(startedRequest).isNotNull(); assertThat(startedRequest.isStarted()).isFalse(); }
@Test public void testFlex() { JobConfig.forceApi(JobApi.V_14); long interval = JobRequest.MIN_INTERVAL * 5; long flex = JobRequest.MIN_FLEX * 5; JobRequest request = getBuilder() .setPeriodic(interval, flex) .build(); JobManager.instance().schedule(request); assertThat(request.getJobId()).isGreaterThan(0); assertThat(request.getTag()).isEqualTo(DummyJobs.SuccessJob.TAG); assertThat(request.getIntervalMs()).isEqualTo(interval); assertThat(request.getFlexMs()).isEqualTo(flex); assertThat(request.isPeriodic()).isTrue(); assertThat(request.isFlexSupport()).isTrue(); }
@Test public void testSameIdAfterCancel() { JobRequest request = DummyJobs.createOneOff(); int jobId = request.getJobId(); assertThat(request.getScheduledAt()).isEqualTo(0L); manager().schedule(request); assertThat(request.getScheduledAt()).isGreaterThan(0L); JobRequest requestNew = request.cancelAndEdit().build(); assertThat(request.getScheduledAt()).isEqualTo(0L); int newId = requestNew.schedule(); assertThat(newId).isEqualTo(jobId); assertThat(request.getScheduledAt()).isEqualTo(0L); assertThat(requestNew.getScheduledAt()).isGreaterThan(0L); }
@Test public void verifyTransientJobNotRescheduled() throws Exception { assertThat(manager().getAllJobRequests()).isEmpty(); Bundle bundle = new Bundle(); bundle.putString("key", "value"); ContentValues contentValues = new JobRequest.Builder("tag") .setExact(TimeUnit.HOURS.toMillis(1)) .setTransientExtras(bundle) .build() .toContentValues(); manager().getJobStorage().getDatabase() .insert(JobStorage.JOB_TABLE_NAME, null, contentValues); Set<JobRequest> requests = manager().getAllJobRequests(); assertThat(requests).isEmpty(); } }
@Test public void verifyPendingRequestNullWhenMarkedStated() { final int jobId = DummyJobs.createBuilder(DummyJobs.SuccessJob.class) .setPeriodic(TimeUnit.MINUTES.toMillis(15)) .build() .schedule(); final JobProxy.Common common = new JobProxy.Common(context(), TestLogger.INSTANCE, jobId); assertThat(common.getPendingRequest(true, false)).isNotNull(); assertThat(common.getPendingRequest(true, false)).isNotNull(); JobRequest request = common.getPendingRequest(true, false); assertThat(request).isNotNull(); common.markStarting(request); assertThat(common.getPendingRequest(true, false)).isNull(); }
private void testPeriodicJob(Class<? extends Job> clazz, Job.Result result) throws Exception { int jobId = DummyJobs.createBuilder(clazz) .setPeriodic(TimeUnit.MINUTES.toMillis(15)) .build() .schedule(); assertThat(manager().getJobRequest(jobId).getLastRun()).isEqualTo(0); executeJob(jobId, result); long lastRun = manager().getJobRequest(jobId).getLastRun(); assertThat(lastRun).isGreaterThan(0); Thread.sleep(2L); resetJob(jobId); executeJob(jobId, result); assertThat(manager().getJobRequest(jobId).getLastRun()).isGreaterThan(lastRun); }
/*package*/ JobRequest reschedule(boolean failure, boolean newJob) { JobRequest newRequest = new Builder(this.mBuilder, newJob).build(); if (failure) { newRequest.mFailureCount = mFailureCount + 1; } try { newRequest.schedule(); } catch (Exception e) { CAT.e(e); // this may crash (e.g. more than 100 jobs with JobScheduler), but it's not catchable for the user, wait for reschedule } return newRequest; }
@Test public void incrementPeriodicJobFailureCount() { int jobId = DummyJobs.createBuilder(DummyJobs.FailureJob.class) .setPeriodic(TimeUnit.MINUTES.toMillis(15)) .build() .schedule(); executeJob(jobId, Job.Result.FAILURE); assertThat(manager().getJobRequest(jobId).getFailureCount()).isEqualTo(1); resetJob(jobId); executeJob(jobId, Job.Result.FAILURE); assertThat(manager().getJobRequest(jobId).getFailureCount()).isEqualTo(2); }
@Test(expected = Exception.class) public void testPeriodicTooLittleInterval() { getBuilder() .setPeriodic(JobRequest.MIN_INTERVAL - 1) .build(); }
private void testPeriodic() { mLastJobId = new JobRequest.Builder(DemoSyncJob.TAG) .setPeriodic(JobRequest.MIN_INTERVAL, JobRequest.MIN_FLEX) .setRequiresCharging(mRequiresCharging.isChecked()) .setRequiresDeviceIdle(mRequiresDeviceIdle.isChecked()) .setRequiredNetworkType(JobRequest.NetworkType.values()[mNetworkTypeSpinner.getSelectedItemPosition()]) .build() .schedule(); }
@Test public void verifyNotFoundJobCanceledPeriodic() { final String tag = "something"; final int jobId = new JobRequest.Builder(tag) .setPeriodic(TimeUnit.HOURS.toMillis(4)) .build() .schedule(); assertThat(manager().getAllJobRequestsForTag(tag)).hasSize(1); executeJob(jobId, Job.Result.FAILURE); assertThat(manager().getAllJobRequestsForTag(tag)).isEmpty(); }
@Test public void verifyNotFoundJobCanceledOneOff() { final String tag = "something"; final int jobId = new JobRequest.Builder(tag) .setExecutionWindow(TimeUnit.HOURS.toMillis(4), TimeUnit.HOURS.toMillis(5)) .build() .schedule(); assertThat(manager().getAllJobRequestsForTag(tag)).hasSize(1); executeJob(jobId, Job.Result.FAILURE); assertThat(manager().getAllJobRequestsForTag(tag)).isEmpty(); }
@Test(expected = Exception.class) public void testNoConstraints() { getBuilder().build(); }
@Test @Config(sdk = Build.VERSION_CODES.M) public void verifyNotFoundJobCanceledPeriodicFlexSupport() { final String tag = "something"; final int jobId = new JobRequest.Builder(tag) .setPeriodic(TimeUnit.HOURS.toMillis(4)) .build() .schedule(); assertThat(manager().getAllJobRequestsForTag(tag)).hasSize(1); executeJob(jobId, Job.Result.FAILURE); assertThat(manager().getAllJobRequestsForTag(tag)).isEmpty(); } }
@Test(expected = Exception.class) public void testPeriodicTooLittleFlex() { getBuilder() .setPeriodic(JobRequest.MIN_FLEX - 1) .build(); }
@Test public void verifyNotFoundJobCanceledExact() { final String tag = "something"; final int jobId = new JobRequest.Builder(tag) .setExact(TimeUnit.HOURS.toMillis(4)) .build() .schedule(); assertThat(manager().getAllJobRequestsForTag(tag)).hasSize(1); executeJob(jobId, Job.Result.FAILURE); assertThat(manager().getAllJobRequestsForTag(tag)).isEmpty(); }
@Test public void testStartNow() throws Exception { mJob = new TestJob(); new JobRequest.Builder("tag") .startNow() .setTransientExtras(createTransientBundle()) .build() .schedule(); mJob.verifyJob(3, TimeUnit.SECONDS); }
@Test public void testStartNow() throws Exception { mJob = new TestJob(PlatformAlarmService.class); new JobRequest.Builder("tag") .startNow() .build() .schedule(); mJob.verifyJob(3, TimeUnit.SECONDS); }
@Test public void testPeriodicJob() throws Exception { int jobId = DummyJobs.createBuilder(DummyJobs.SuccessJob.class) .setPeriodic(TimeUnit.MINUTES.toMillis(15)) .build() .schedule(); executeJob(jobId, Job.Result.SUCCESS); // make sure job request is still around assertThat(manager().getAllJobRequestsForTag(DummyJobs.SuccessJob.TAG)).hasSize(1); }