1 /*
2  * Copyright 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.work.impl;
18 
19 import static androidx.work.ExistingWorkPolicy.APPEND;
20 import static androidx.work.ExistingWorkPolicy.KEEP;
21 import static androidx.work.ExistingWorkPolicy.REPLACE;
22 import static androidx.work.NetworkType.METERED;
23 import static androidx.work.NetworkType.NOT_REQUIRED;
24 import static androidx.work.State.BLOCKED;
25 import static androidx.work.State.CANCELLED;
26 import static androidx.work.State.ENQUEUED;
27 import static androidx.work.State.FAILED;
28 import static androidx.work.State.RUNNING;
29 import static androidx.work.State.SUCCEEDED;
30 
31 import static org.hamcrest.CoreMatchers.is;
32 import static org.hamcrest.CoreMatchers.not;
33 import static org.hamcrest.CoreMatchers.notNullValue;
34 import static org.hamcrest.CoreMatchers.nullValue;
35 import static org.hamcrest.MatcherAssert.assertThat;
36 import static org.hamcrest.Matchers.contains;
37 import static org.hamcrest.Matchers.containsInAnyOrder;
38 import static org.hamcrest.Matchers.emptyCollectionOf;
39 import static org.hamcrest.Matchers.greaterThan;
40 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
41 import static org.hamcrest.Matchers.isIn;
42 import static org.hamcrest.Matchers.isOneOf;
43 import static org.mockito.Mockito.clearInvocations;
44 import static org.mockito.Mockito.mock;
45 import static org.mockito.Mockito.times;
46 import static org.mockito.Mockito.verify;
47 
48 import android.arch.core.executor.ArchTaskExecutor;
49 import android.arch.core.executor.TaskExecutor;
50 import android.arch.lifecycle.LiveData;
51 import android.arch.lifecycle.Observer;
52 import android.arch.persistence.db.SupportSQLiteDatabase;
53 import android.arch.persistence.db.SupportSQLiteOpenHelper;
54 import android.content.Context;
55 import android.net.Uri;
56 import android.os.Build;
57 import android.provider.MediaStore;
58 import android.support.annotation.NonNull;
59 import android.support.test.InstrumentationRegistry;
60 import android.support.test.filters.LargeTest;
61 import android.support.test.filters.MediumTest;
62 import android.support.test.filters.SdkSuppress;
63 import android.support.test.filters.SmallTest;
64 import android.support.test.runner.AndroidJUnit4;
65 
66 import androidx.work.BackoffPolicy;
67 import androidx.work.Configuration;
68 import androidx.work.Constraints;
69 import androidx.work.ContentUriTriggers;
70 import androidx.work.Data;
71 import androidx.work.ExistingPeriodicWorkPolicy;
72 import androidx.work.OneTimeWorkRequest;
73 import androidx.work.PeriodicWorkRequest;
74 import androidx.work.TestLifecycleOwner;
75 import androidx.work.WorkContinuation;
76 import androidx.work.WorkRequest;
77 import androidx.work.WorkStatus;
78 import androidx.work.impl.model.Dependency;
79 import androidx.work.impl.model.DependencyDao;
80 import androidx.work.impl.model.WorkName;
81 import androidx.work.impl.model.WorkSpec;
82 import androidx.work.impl.model.WorkSpecDao;
83 import androidx.work.impl.model.WorkTag;
84 import androidx.work.impl.model.WorkTagDao;
85 import androidx.work.impl.utils.CancelWorkRunnable;
86 import androidx.work.impl.utils.Preferences;
87 import androidx.work.impl.utils.taskexecutor.InstantTaskExecutorRule;
88 import androidx.work.impl.workers.ConstraintTrackingWorker;
89 import androidx.work.worker.InfiniteTestWorker;
90 import androidx.work.worker.TestWorker;
91 
92 import org.junit.After;
93 import org.junit.Before;
94 import org.junit.Rule;
95 import org.junit.Test;
96 import org.junit.runner.RunWith;
97 import org.mockito.ArgumentCaptor;
98 
99 import java.util.Arrays;
100 import java.util.Collections;
101 import java.util.List;
102 import java.util.UUID;
103 import java.util.concurrent.Executors;
104 import java.util.concurrent.TimeUnit;
105 
106 @RunWith(AndroidJUnit4.class)
107 public class WorkManagerImplTest {
108 
109     private WorkDatabase mDatabase;
110     private WorkManagerImpl mWorkManagerImpl;
111 
112     @Rule
113     public InstantTaskExecutorRule mRule = new InstantTaskExecutorRule();
114 
115     @Before
setUp()116     public void setUp() {
117         ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
118             @Override
119             public void executeOnDiskIO(@NonNull Runnable runnable) {
120                 runnable.run();
121             }
122 
123             @Override
124             public void postToMainThread(@NonNull Runnable runnable) {
125                 runnable.run();
126             }
127 
128             @Override
129             public boolean isMainThread() {
130                 return true;
131             }
132         });
133 
134         Context context = InstrumentationRegistry.getTargetContext();
135         Configuration configuration = new Configuration.Builder()
136                 .setExecutor(Executors.newSingleThreadExecutor())
137                 .build();
138         mWorkManagerImpl = new WorkManagerImpl(context, configuration);
139         WorkManagerImpl.setDelegate(mWorkManagerImpl);
140         mDatabase = mWorkManagerImpl.getWorkDatabase();
141     }
142 
143     @After
tearDown()144     public void tearDown() {
145         WorkManagerImpl.setDelegate(null);
146         ArchTaskExecutor.getInstance().setDelegate(null);
147     }
148 
149     @Test
150     @SmallTest
testEnqueue_insertWork()151     public void testEnqueue_insertWork() {
152         final int workCount = 3;
153         final OneTimeWorkRequest[] workArray = new OneTimeWorkRequest[workCount];
154         for (int i = 0; i < workCount; ++i) {
155             workArray[i] = new OneTimeWorkRequest.Builder(TestWorker.class).build();
156         }
157 
158         mWorkManagerImpl.beginWith(workArray[0]).then(workArray[1])
159                 .then(workArray[2])
160                 .synchronous().enqueueSync();
161 
162         for (int i = 0; i < workCount; ++i) {
163             String id = workArray[i].getStringId();
164             assertThat(mDatabase.workSpecDao().getWorkSpec(id), is(notNullValue()));
165             assertThat(
166                     "index " + i + " does not have expected number of dependencies!",
167                     mDatabase.dependencyDao().getPrerequisites(id).size() > 0,
168                     is(i > 0));
169         }
170     }
171 
172     @Test
173     @SmallTest
testEnqueue_AddsImplicitTags()174     public void testEnqueue_AddsImplicitTags() {
175         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
176         mWorkManagerImpl.synchronous().enqueueSync(work);
177 
178         WorkTagDao workTagDao = mDatabase.workTagDao();
179         List<String> tags = workTagDao.getTagsForWorkSpecId(work.getStringId());
180         assertThat(tags, is(notNullValue()));
181         assertThat(tags, contains(TestWorker.class.getName()));
182     }
183 
184     @Test
185     @SmallTest
testEnqueue_insertMultipleWork()186     public void testEnqueue_insertMultipleWork() {
187         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
188         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
189         OneTimeWorkRequest work3 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
190 
191         mWorkManagerImpl.synchronous().enqueueSync(work1, work2, work3);
192 
193         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
194         assertThat(workSpecDao.getWorkSpec(work1.getStringId()), is(notNullValue()));
195         assertThat(workSpecDao.getWorkSpec(work2.getStringId()), is(notNullValue()));
196         assertThat(workSpecDao.getWorkSpec(work3.getStringId()), is(notNullValue()));
197     }
198 
199     @Test
200     @SmallTest
testEnqueue_insertMultipleWork_continuationBlocking()201     public void testEnqueue_insertMultipleWork_continuationBlocking() {
202         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
203         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
204         OneTimeWorkRequest work3 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
205 
206         mWorkManagerImpl.beginWith(work1, work2, work3)
207                 .synchronous()
208                 .enqueueSync();
209 
210         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
211         assertThat(workSpecDao.getWorkSpec(work1.getStringId()), is(notNullValue()));
212         assertThat(workSpecDao.getWorkSpec(work2.getStringId()), is(notNullValue()));
213         assertThat(workSpecDao.getWorkSpec(work3.getStringId()), is(notNullValue()));
214     }
215 
216     @Test
217     @SmallTest
testEnqueue_insertWithDependencies()218     public void testEnqueue_insertWithDependencies() {
219         OneTimeWorkRequest work1a = new OneTimeWorkRequest.Builder(TestWorker.class).build();
220         OneTimeWorkRequest work1b = new OneTimeWorkRequest.Builder(TestWorker.class).build();
221         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
222         OneTimeWorkRequest work3a = new OneTimeWorkRequest.Builder(TestWorker.class).build();
223         OneTimeWorkRequest work3b = new OneTimeWorkRequest.Builder(TestWorker.class).build();
224 
225         mWorkManagerImpl.beginWith(work1a, work1b).then(work2)
226                 .then(work3a, work3b)
227                 .synchronous()
228                 .enqueueSync();
229 
230         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
231         assertThat(workSpecDao.getWorkSpec(work1a.getStringId()), is(notNullValue()));
232         assertThat(workSpecDao.getWorkSpec(work1b.getStringId()), is(notNullValue()));
233         assertThat(workSpecDao.getWorkSpec(work2.getStringId()), is(notNullValue()));
234         assertThat(workSpecDao.getWorkSpec(work3a.getStringId()), is(notNullValue()));
235         assertThat(workSpecDao.getWorkSpec(work3b.getStringId()), is(notNullValue()));
236 
237         DependencyDao dependencyDao = mDatabase.dependencyDao();
238         assertThat(dependencyDao.getPrerequisites(work1a.getStringId()),
239                 is(emptyCollectionOf(String.class)));
240         assertThat(dependencyDao.getPrerequisites(work1b.getStringId()),
241                 is(emptyCollectionOf(String.class)));
242 
243         List<String> prerequisites = dependencyDao.getPrerequisites(work2.getStringId());
244         assertThat(prerequisites, containsInAnyOrder(work1a.getStringId(), work1b.getStringId()));
245 
246         prerequisites = dependencyDao.getPrerequisites(work3a.getStringId());
247         assertThat(prerequisites, containsInAnyOrder(work2.getStringId()));
248 
249         prerequisites = dependencyDao.getPrerequisites(work3b.getStringId());
250         assertThat(prerequisites, containsInAnyOrder(work2.getStringId()));
251     }
252 
253     @Test
254     @SmallTest
testEnqueue_insertWithCompletedDependencies_isNotStatusBlocked()255     public void testEnqueue_insertWithCompletedDependencies_isNotStatusBlocked() {
256         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
257                 .setInitialState(SUCCEEDED)
258                 .build();
259 
260         WorkContinuation workContinuation = mWorkManagerImpl.beginWith(work1);
261         workContinuation.synchronous().enqueueSync();
262         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
263         assertThat(workSpecDao.getState(work1.getStringId()), is(SUCCEEDED));
264 
265         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
266         workContinuation.then(work2).synchronous().enqueueSync();
267         assertThat(workSpecDao.getState(work2.getStringId()), isOneOf(ENQUEUED, RUNNING));
268     }
269 
270     @Test
271     @SmallTest
testEnqueue_insertWithFailedDependencies_isStatusFailed()272     public void testEnqueue_insertWithFailedDependencies_isStatusFailed() {
273         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
274                 .setInitialState(FAILED)
275                 .build();
276 
277         WorkContinuation workContinuation = mWorkManagerImpl.beginWith(work1);
278         workContinuation.synchronous().enqueueSync();
279         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
280         assertThat(workSpecDao.getState(work1.getStringId()), is(FAILED));
281 
282         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
283         workContinuation.then(work2).synchronous().enqueueSync();
284         assertThat(workSpecDao.getState(work2.getStringId()), is(FAILED));
285     }
286 
287     @Test
288     @SmallTest
testEnqueue_insertWithCancelledDependencies_isStatusCancelled()289     public void testEnqueue_insertWithCancelledDependencies_isStatusCancelled() {
290         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
291                 .setInitialState(CANCELLED)
292                 .build();
293 
294         WorkContinuation workContinuation = mWorkManagerImpl.beginWith(work1);
295         workContinuation.synchronous().enqueueSync();
296         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
297         assertThat(workSpecDao.getState(work1.getStringId()), is(CANCELLED));
298 
299         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
300         workContinuation.then(work2).synchronous().enqueueSync();
301         assertThat(workSpecDao.getState(work2.getStringId()), is(CANCELLED));
302     }
303 
304     @Test
305     @SmallTest
306     @SdkSuppress(minSdkVersion = 23)
testEnqueue_insertWorkConstraints()307     public void testEnqueue_insertWorkConstraints() {
308         Uri testUri1 = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
309         Uri testUri2 = MediaStore.Images.Media.INTERNAL_CONTENT_URI;
310 
311         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
312                 .setConstraints(
313                         new Constraints.Builder()
314                                 .setRequiresCharging(true)
315                                 .setRequiresDeviceIdle(true)
316                                 .setRequiredNetworkType(METERED)
317                                 .setRequiresBatteryNotLow(true)
318                                 .setRequiresStorageNotLow(true)
319                                 .addContentUriTrigger(testUri1, true)
320                                 .addContentUriTrigger(testUri2, false)
321                                 .build())
322                 .build();
323         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
324         mWorkManagerImpl.beginWith(work0).then(work1).synchronous().enqueueSync();
325 
326         WorkSpec workSpec0 = mDatabase.workSpecDao().getWorkSpec(work0.getStringId());
327         WorkSpec workSpec1 = mDatabase.workSpecDao().getWorkSpec(work1.getStringId());
328 
329         ContentUriTriggers expectedTriggers = new ContentUriTriggers();
330         expectedTriggers.add(testUri1, true);
331         expectedTriggers.add(testUri2, false);
332 
333         Constraints constraints = workSpec0.constraints;
334         assertThat(constraints, is(notNullValue()));
335         assertThat(constraints.requiresCharging(), is(true));
336         assertThat(constraints.requiresDeviceIdle(), is(true));
337         assertThat(constraints.requiresBatteryNotLow(), is(true));
338         assertThat(constraints.requiresStorageNotLow(), is(true));
339         assertThat(constraints.getRequiredNetworkType(), is(METERED));
340         if (Build.VERSION.SDK_INT >= 24) {
341             assertThat(constraints.getContentUriTriggers(), is(expectedTriggers));
342         } else {
343             assertThat(constraints.getContentUriTriggers(), is(new ContentUriTriggers()));
344         }
345 
346         constraints = workSpec1.constraints;
347         assertThat(constraints, is(notNullValue()));
348         assertThat(constraints.requiresCharging(), is(false));
349         assertThat(constraints.requiresDeviceIdle(), is(false));
350         assertThat(constraints.requiresBatteryNotLow(), is(false));
351         assertThat(constraints.requiresStorageNotLow(), is(false));
352         assertThat(constraints.getRequiredNetworkType(), is(NOT_REQUIRED));
353         assertThat(constraints.getContentUriTriggers().size(), is(0));
354     }
355 
356     @Test
357     @SmallTest
testEnqueue_insertWorkInitialDelay()358     public void testEnqueue_insertWorkInitialDelay() {
359         final long expectedInitialDelay = 5000L;
360         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
361                 .setInitialDelay(expectedInitialDelay, TimeUnit.MILLISECONDS)
362                 .build();
363         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
364         mWorkManagerImpl.beginWith(work0).then(work1).synchronous().enqueueSync();
365 
366         WorkSpec workSpec0 = mDatabase.workSpecDao().getWorkSpec(work0.getStringId());
367         WorkSpec workSpec1 = mDatabase.workSpecDao().getWorkSpec(work1.getStringId());
368 
369         assertThat(workSpec0.initialDelay, is(expectedInitialDelay));
370         assertThat(workSpec1.initialDelay, is(0L));
371     }
372 
373     @Test
374     @SmallTest
testEnqueue_insertWorkBackoffPolicy()375     public void testEnqueue_insertWorkBackoffPolicy() {
376         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
377                 .setBackoffCriteria(BackoffPolicy.LINEAR, 50000, TimeUnit.MILLISECONDS)
378                 .build();
379         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
380         mWorkManagerImpl.beginWith(work0).then(work1).synchronous().enqueueSync();
381 
382         WorkSpec workSpec0 = mDatabase.workSpecDao().getWorkSpec(work0.getStringId());
383         WorkSpec workSpec1 = mDatabase.workSpecDao().getWorkSpec(work1.getStringId());
384 
385         assertThat(workSpec0.backoffPolicy, is(BackoffPolicy.LINEAR));
386         assertThat(workSpec0.backoffDelayDuration, is(50000L));
387 
388         assertThat(workSpec1.backoffPolicy, is(BackoffPolicy.EXPONENTIAL));
389         assertThat(workSpec1.backoffDelayDuration,
390                 is(WorkRequest.DEFAULT_BACKOFF_DELAY_MILLIS));
391     }
392 
393     @Test
394     @SmallTest
testEnqueue_insertWorkTags()395     public void testEnqueue_insertWorkTags() {
396         final String firstTag = "first_tag";
397         final String secondTag = "second_tag";
398         final String thirdTag = "third_tag";
399 
400         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
401                 .addTag(firstTag)
402                 .addTag(secondTag)
403                 .build();
404         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
405                 .addTag(firstTag)
406                 .build();
407         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
408         mWorkManagerImpl.beginWith(work0).then(work1).then(work2).synchronous().enqueueSync();
409 
410         WorkTagDao workTagDao = mDatabase.workTagDao();
411         assertThat(workTagDao.getWorkSpecIdsWithTag(firstTag),
412                 containsInAnyOrder(work0.getStringId(), work1.getStringId()));
413         assertThat(workTagDao.getWorkSpecIdsWithTag(secondTag),
414                 containsInAnyOrder(work0.getStringId()));
415         assertThat(workTagDao.getWorkSpecIdsWithTag(thirdTag), emptyCollectionOf(String.class));
416     }
417 
418     @Test
419     @SmallTest
testEnqueue_insertPeriodicWork()420     public void testEnqueue_insertPeriodicWork() {
421         PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(
422                 TestWorker.class,
423                 PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
424                 TimeUnit.MILLISECONDS)
425                 .build();
426 
427         mWorkManagerImpl.synchronous().enqueueSync(periodicWork);
428 
429         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(periodicWork.getStringId());
430         assertThat(workSpec.isPeriodic(), is(true));
431         assertThat(workSpec.intervalDuration, is(PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS));
432         assertThat(workSpec.flexDuration, is(PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS));
433     }
434 
435     @Test
436     @SmallTest
testEnqueued_work_setsPeriodStartTime()437     public void testEnqueued_work_setsPeriodStartTime() {
438         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
439         assertThat(work.getWorkSpec().periodStartTime, is(0L));
440 
441         long beforeEnqueueTime = System.currentTimeMillis();
442 
443         mWorkManagerImpl.beginWith(work).synchronous().enqueueSync();
444         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getStringId());
445         assertThat(workSpec.periodStartTime, is(greaterThanOrEqualTo(beforeEnqueueTime)));
446     }
447 
448     @Test
449     @SmallTest
testEnqueued_periodicWork_setsPeriodStartTime()450     public void testEnqueued_periodicWork_setsPeriodStartTime() {
451         PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(
452                 TestWorker.class,
453                 PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
454                 TimeUnit.MILLISECONDS)
455                 .build();
456         assertThat(periodicWork.getWorkSpec().periodStartTime, is(0L));
457 
458         long beforeEnqueueTime = System.currentTimeMillis();
459 
460         mWorkManagerImpl.synchronous().enqueueSync(periodicWork);
461 
462         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(periodicWork.getStringId());
463         assertThat(workSpec.periodStartTime, is(greaterThanOrEqualTo(beforeEnqueueTime)));
464     }
465 
466     @Test
467     @SmallTest
testBeginUniqueWork_setsUniqueName()468     public void testBeginUniqueWork_setsUniqueName() {
469         final String uniqueName = "myname";
470 
471         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
472         mWorkManagerImpl.beginUniqueWork(uniqueName, REPLACE)
473                 .then(work)
474                 .synchronous()
475                 .enqueueSync();
476 
477         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
478         assertThat(work.getStringId(), isIn(workSpecIds));
479     }
480 
481     @Test
482     @SmallTest
testEnqueueUniquePeriodicWork_setsUniqueName()483     public void testEnqueueUniquePeriodicWork_setsUniqueName() {
484         final String uniqueName = "myname";
485 
486         PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(
487                 TestWorker.class,
488                 15L,
489                 TimeUnit.MINUTES)
490                 .build();
491         mWorkManagerImpl.enqueueUniquePeriodicWorkSync(
492                 uniqueName,
493                 ExistingPeriodicWorkPolicy.REPLACE,
494                 periodicWork);
495 
496         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
497         assertThat(periodicWork.getStringId(), isIn(workSpecIds));
498     }
499 
500     @Test
501     @SmallTest
testBeginUniqueWork_deletesOldWorkOnReplace()502     public void testBeginUniqueWork_deletesOldWorkOnReplace() {
503         final String uniqueName = "myname";
504 
505         OneTimeWorkRequest originalWork =
506                 new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
507         insertNamedWorks(uniqueName, originalWork);
508 
509         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
510         assertThat(workSpecIds, containsInAnyOrder(originalWork.getStringId()));
511 
512         OneTimeWorkRequest replacementWork1 =
513                 new OneTimeWorkRequest.Builder(TestWorker.class).build();
514         OneTimeWorkRequest replacementWork2 =
515                 new OneTimeWorkRequest.Builder(TestWorker.class).build();
516         mWorkManagerImpl
517                 .beginUniqueWork(uniqueName, REPLACE, replacementWork1)
518                 .then(replacementWork2)
519                 .synchronous()
520                 .enqueueSync();
521 
522         workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
523         assertThat(
524                 workSpecIds,
525                 containsInAnyOrder(replacementWork1.getStringId(), replacementWork2.getStringId()));
526 
527         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
528         assertThat(workSpecDao.getWorkSpec(originalWork.getStringId()), is(nullValue()));
529         assertThat(workSpecDao.getWorkSpec(replacementWork1.getStringId()), is(not(nullValue())));
530         assertThat(workSpecDao.getWorkSpec(replacementWork2.getStringId()), is(not(nullValue())));
531     }
532 
533     @Test
534     @SmallTest
testEnqueueUniquePeriodicWork_deletesOldWorkOnReplace()535     public void testEnqueueUniquePeriodicWork_deletesOldWorkOnReplace() {
536         final String uniqueName = "myname";
537 
538         PeriodicWorkRequest originalWork = new PeriodicWorkRequest.Builder(
539                 InfiniteTestWorker.class,
540                 15L,
541                 TimeUnit.MINUTES)
542                 .build();
543         insertNamedWorks(uniqueName, originalWork);
544 
545         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
546         assertThat(workSpecIds, containsInAnyOrder(originalWork.getStringId()));
547 
548         PeriodicWorkRequest replacementWork = new PeriodicWorkRequest.Builder(
549                 TestWorker.class,
550                 30L,
551                 TimeUnit.MINUTES)
552                 .build();
553         mWorkManagerImpl.enqueueUniquePeriodicWorkSync(
554                 uniqueName,
555                 ExistingPeriodicWorkPolicy.REPLACE,
556                 replacementWork);
557 
558         workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
559         assertThat(workSpecIds, contains(replacementWork.getStringId()));
560 
561         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
562         assertThat(workSpecDao.getWorkSpec(originalWork.getStringId()), is(nullValue()));
563         assertThat(workSpecDao.getWorkSpec(replacementWork.getStringId()), is(not(nullValue())));
564     }
565 
566     @Test
567     @SmallTest
testBeginUniqueWork_keepsExistingWorkOnKeep()568     public void testBeginUniqueWork_keepsExistingWorkOnKeep() {
569         final String uniqueName = "myname";
570 
571         OneTimeWorkRequest originalWork =
572                 new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
573         insertNamedWorks(uniqueName, originalWork);
574 
575         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
576         assertThat(workSpecIds, containsInAnyOrder(originalWork.getStringId()));
577 
578         OneTimeWorkRequest replacementWork1 =
579                 new OneTimeWorkRequest.Builder(TestWorker.class).build();
580         OneTimeWorkRequest replacementWork2 =
581                 new OneTimeWorkRequest.Builder(TestWorker.class).build();
582         mWorkManagerImpl
583                 .beginUniqueWork(uniqueName, KEEP, replacementWork1)
584                 .then(replacementWork2)
585                 .synchronous()
586                 .enqueueSync();
587 
588         workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
589         assertThat(workSpecIds, contains(originalWork.getStringId()));
590 
591         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
592         assertThat(workSpecDao.getWorkSpec(originalWork.getStringId()), is(not(nullValue())));
593         assertThat(workSpecDao.getWorkSpec(replacementWork1.getStringId()), is(nullValue()));
594         assertThat(workSpecDao.getWorkSpec(replacementWork2.getStringId()), is(nullValue()));
595     }
596 
597     @Test
598     @SmallTest
testEnqueueUniquePeriodicWork_keepsExistingWorkOnKeep()599     public void testEnqueueUniquePeriodicWork_keepsExistingWorkOnKeep() {
600         final String uniqueName = "myname";
601 
602         PeriodicWorkRequest originalWork = new PeriodicWorkRequest.Builder(
603                 InfiniteTestWorker.class,
604                 15L,
605                 TimeUnit.MINUTES)
606                 .build();
607         insertNamedWorks(uniqueName, originalWork);
608 
609         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
610         assertThat(workSpecIds, containsInAnyOrder(originalWork.getStringId()));
611 
612         PeriodicWorkRequest replacementWork = new PeriodicWorkRequest.Builder(
613                 TestWorker.class,
614                 30L,
615                 TimeUnit.MINUTES)
616                 .build();
617         mWorkManagerImpl.enqueueUniquePeriodicWorkSync(
618                 uniqueName,
619                 ExistingPeriodicWorkPolicy.KEEP,
620                 replacementWork);
621 
622         workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
623         assertThat(workSpecIds, contains(originalWork.getStringId()));
624 
625         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
626         assertThat(workSpecDao.getWorkSpec(originalWork.getStringId()), is(not(nullValue())));
627         assertThat(workSpecDao.getWorkSpec(replacementWork.getStringId()), is(nullValue()));
628     }
629 
630     @Test
631     @SmallTest
testBeginUniqueWork_replacesExistingWorkOnKeepWhenExistingWorkIsDone()632     public void testBeginUniqueWork_replacesExistingWorkOnKeepWhenExistingWorkIsDone() {
633         final String uniqueName = "myname";
634 
635         OneTimeWorkRequest originalWork = new OneTimeWorkRequest.Builder(TestWorker.class)
636                 .setInitialState(SUCCEEDED)
637                 .build();
638         insertNamedWorks(uniqueName, originalWork);
639 
640         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
641         assertThat(workSpecIds, containsInAnyOrder(originalWork.getStringId()));
642 
643         OneTimeWorkRequest replacementWork1 =
644                 new OneTimeWorkRequest.Builder(TestWorker.class).build();
645         OneTimeWorkRequest replacementWork2 =
646                 new OneTimeWorkRequest.Builder(TestWorker.class).build();
647         mWorkManagerImpl
648                 .beginUniqueWork(uniqueName, KEEP, replacementWork1)
649                 .then(replacementWork2)
650                 .synchronous()
651                 .enqueueSync();
652 
653         workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
654         assertThat(workSpecIds,
655                 containsInAnyOrder(replacementWork1.getStringId(), replacementWork2.getStringId()));
656 
657         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
658         assertThat(workSpecDao.getWorkSpec(originalWork.getStringId()), is(nullValue()));
659         assertThat(workSpecDao.getWorkSpec(replacementWork1.getStringId()), is(not(nullValue())));
660         assertThat(workSpecDao.getWorkSpec(replacementWork2.getStringId()), is(not(nullValue())));
661     }
662 
663     @Test
664     @SmallTest
testEnqueueUniquePeriodicWork_replacesExistingWorkOnKeepWhenExistingWorkIsDone()665     public void testEnqueueUniquePeriodicWork_replacesExistingWorkOnKeepWhenExistingWorkIsDone() {
666         final String uniqueName = "myname";
667 
668         PeriodicWorkRequest originalWork = new PeriodicWorkRequest.Builder(
669                 InfiniteTestWorker.class,
670                 15L,
671                 TimeUnit.MINUTES)
672                 .setInitialState(SUCCEEDED)
673                 .build();
674         insertNamedWorks(uniqueName, originalWork);
675 
676         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
677         assertThat(workSpecIds, containsInAnyOrder(originalWork.getStringId()));
678 
679         PeriodicWorkRequest replacementWork = new PeriodicWorkRequest.Builder(
680                 TestWorker.class,
681                 30L,
682                 TimeUnit.MINUTES)
683                 .build();
684         mWorkManagerImpl.enqueueUniquePeriodicWorkSync(
685                 uniqueName,
686                 ExistingPeriodicWorkPolicy.KEEP,
687                 replacementWork);
688 
689         workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
690         assertThat(workSpecIds, contains(replacementWork.getStringId()));
691 
692         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
693         assertThat(workSpecDao.getWorkSpec(originalWork.getStringId()), is(nullValue()));
694         assertThat(workSpecDao.getWorkSpec(replacementWork.getStringId()), is(not(nullValue())));
695     }
696 
697     @Test
698     @SmallTest
testBeginUniqueWork_appendsExistingWorkOnAppend()699     public void testBeginUniqueWork_appendsExistingWorkOnAppend() {
700         final String uniqueName = "myname";
701 
702         OneTimeWorkRequest originalWork =
703                 new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
704         insertNamedWorks(uniqueName, originalWork);
705 
706         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
707         assertThat(workSpecIds, containsInAnyOrder(originalWork.getStringId()));
708 
709         OneTimeWorkRequest appendWork1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
710         OneTimeWorkRequest appendWork2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
711         mWorkManagerImpl
712                 .beginUniqueWork(uniqueName, APPEND, appendWork1)
713                 .then(appendWork2)
714                 .synchronous()
715                 .enqueueSync();
716 
717         workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
718         assertThat(workSpecIds,
719                 containsInAnyOrder(
720                         originalWork.getStringId(),
721                         appendWork1.getStringId(),
722                         appendWork2.getStringId()));
723 
724         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
725         assertThat(workSpecDao.getWorkSpec(originalWork.getStringId()), is(not(nullValue())));
726         assertThat(workSpecDao.getState(appendWork1.getStringId()), is(BLOCKED));
727         assertThat(workSpecDao.getState(appendWork2.getStringId()), is(BLOCKED));
728 
729         assertThat(mDatabase.dependencyDao().getDependentWorkIds(originalWork.getStringId()),
730                 containsInAnyOrder(appendWork1.getStringId()));
731     }
732 
733     @Test
734     @SmallTest
testBeginUniqueWork_appendsExistingWorkToOnlyLeavesOnAppend()735     public void testBeginUniqueWork_appendsExistingWorkToOnlyLeavesOnAppend() {
736         final String uniqueName = "myname";
737 
738         OneTimeWorkRequest originalWork1 =
739                 new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
740         OneTimeWorkRequest originalWork2 =
741                 new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
742         OneTimeWorkRequest originalWork3 =
743                 new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
744         OneTimeWorkRequest originalWork4 =
745                 new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
746 
747         insertNamedWorks(uniqueName, originalWork1, originalWork2, originalWork3, originalWork4);
748         insertDependency(originalWork4, originalWork2);
749         insertDependency(originalWork3, originalWork2);
750         insertDependency(originalWork2, originalWork1);
751 
752         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
753         assertThat(workSpecIds,
754                 containsInAnyOrder(
755                         originalWork1.getStringId(),
756                         originalWork2.getStringId(),
757                         originalWork3.getStringId(),
758                         originalWork4.getStringId()));
759 
760         OneTimeWorkRequest appendWork1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
761         OneTimeWorkRequest appendWork2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
762         mWorkManagerImpl
763                 .beginUniqueWork(uniqueName, APPEND, appendWork1)
764                 .then(appendWork2)
765                 .synchronous()
766                 .enqueueSync();
767 
768         workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
769         assertThat(workSpecIds,
770                 containsInAnyOrder(
771                         originalWork1.getStringId(),
772                         originalWork2.getStringId(),
773                         originalWork3.getStringId(),
774                         originalWork4.getStringId(),
775                         appendWork1.getStringId(),
776                         appendWork2.getStringId()));
777 
778         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
779         assertThat(workSpecDao.getWorkSpec(originalWork1.getStringId()), is(not(nullValue())));
780         assertThat(workSpecDao.getWorkSpec(originalWork2.getStringId()), is(not(nullValue())));
781         assertThat(workSpecDao.getWorkSpec(originalWork3.getStringId()), is(not(nullValue())));
782         assertThat(workSpecDao.getWorkSpec(originalWork4.getStringId()), is(not(nullValue())));
783         assertThat(workSpecDao.getState(appendWork1.getStringId()), is(BLOCKED));
784         assertThat(workSpecDao.getState(appendWork2.getStringId()), is(BLOCKED));
785 
786         DependencyDao dependencyDao = mDatabase.dependencyDao();
787         assertThat(dependencyDao.getPrerequisites(appendWork1.getStringId()),
788                 containsInAnyOrder(originalWork3.getStringId(), originalWork4.getStringId()));
789         assertThat(dependencyDao.getPrerequisites(appendWork2.getStringId()),
790                 containsInAnyOrder(appendWork1.getStringId()));
791     }
792 
793     @Test
794     @SmallTest
testBeginUniqueWork_insertsExistingWorkWhenNothingToAppendTo()795     public void testBeginUniqueWork_insertsExistingWorkWhenNothingToAppendTo() {
796         final String uniqueName = "myname";
797 
798         OneTimeWorkRequest appendWork1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
799         OneTimeWorkRequest appendWork2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
800         mWorkManagerImpl
801                 .beginUniqueWork(uniqueName, APPEND, appendWork1)
802                 .then(appendWork2)
803                 .synchronous()
804                 .enqueueSync();
805 
806         List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(uniqueName);
807         assertThat(workSpecIds,
808                 containsInAnyOrder(appendWork1.getStringId(), appendWork2.getStringId()));
809     }
810 
811     @Test
812     @SmallTest
testGetStatusByIdSync()813     public void testGetStatusByIdSync() {
814         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
815                 .setInitialState(SUCCEEDED)
816                 .build();
817         insertWorkSpecAndTags(work);
818 
819         WorkStatus workStatus = mWorkManagerImpl.getStatusByIdSync(work.getId());
820         assertThat(workStatus.getId().toString(), is(work.getStringId()));
821         assertThat(workStatus.getState(), is(SUCCEEDED));
822     }
823 
824     @Test
825     @SmallTest
testGetStatusByIdSync_returnsNullIfNotInDatabase()826     public void testGetStatusByIdSync_returnsNullIfNotInDatabase() {
827         WorkStatus workStatus = mWorkManagerImpl.getStatusByIdSync(UUID.randomUUID());
828         assertThat(workStatus, is(nullValue()));
829     }
830 
831     @Test
832     @SmallTest
833     @SuppressWarnings("unchecked")
testGetStatusesById()834     public void testGetStatusesById() {
835         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
836         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
837         insertWorkSpecAndTags(work0);
838         insertWorkSpecAndTags(work1);
839 
840         Observer<List<WorkStatus>> mockObserver = mock(Observer.class);
841 
842         TestLifecycleOwner testLifecycleOwner = new TestLifecycleOwner();
843         LiveData<List<WorkStatus>> liveData = mWorkManagerImpl.getStatusesById(
844                 Arrays.asList(work0.getStringId(), work1.getStringId()));
845         liveData.observe(testLifecycleOwner, mockObserver);
846 
847         ArgumentCaptor<List<WorkStatus>> captor = ArgumentCaptor.forClass(List.class);
848         verify(mockObserver).onChanged(captor.capture());
849         assertThat(captor.getValue(), is(not(nullValue())));
850         assertThat(captor.getValue().size(), is(2));
851 
852         WorkStatus workStatus0 = new WorkStatus(
853                 work0.getId(),
854                 ENQUEUED,
855                 Data.EMPTY,
856                 Collections.singletonList(TestWorker.class.getName()));
857         WorkStatus workStatus1 = new WorkStatus(
858                 work1.getId(),
859                 ENQUEUED,
860                 Data.EMPTY,
861                 Collections.singletonList(TestWorker.class.getName()));
862         assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
863 
864         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
865         workSpecDao.setState(RUNNING, work0.getStringId());
866 
867         verify(mockObserver, times(2)).onChanged(captor.capture());
868         assertThat(captor.getValue(), is(not(nullValue())));
869         assertThat(captor.getValue().size(), is(2));
870 
871         workStatus0 = new WorkStatus(
872                 work0.getId(),
873                 RUNNING,
874                 Data.EMPTY,
875                 Collections.singletonList(TestWorker.class.getName()));
876         assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
877 
878         clearInvocations(mockObserver);
879         workSpecDao.setState(RUNNING, work1.getStringId());
880 
881         verify(mockObserver).onChanged(captor.capture());
882         assertThat(captor.getValue(), is(not(nullValue())));
883         assertThat(captor.getValue().size(), is(2));
884 
885         workStatus1 = new WorkStatus(
886                 work1.getId(),
887                 RUNNING,
888                 Data.EMPTY,
889                 Collections.singletonList(TestWorker.class.getName()));
890         assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
891 
892         liveData.removeObservers(testLifecycleOwner);
893     }
894 
895     @Test
896     @SmallTest
testGetStatusesByTagSync()897     public void testGetStatusesByTagSync() {
898         final String firstTag = "first_tag";
899         final String secondTag = "second_tag";
900 
901         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
902                 .addTag(firstTag)
903                 .addTag(secondTag)
904                 .setInitialState(RUNNING)
905                 .build();
906         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
907                 .addTag(firstTag)
908                 .setInitialState(BLOCKED)
909                 .build();
910         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class)
911                 .addTag(secondTag)
912                 .setInitialState(SUCCEEDED)
913                 .build();
914         insertWorkSpecAndTags(work0);
915         insertWorkSpecAndTags(work1);
916         insertWorkSpecAndTags(work2);
917 
918         WorkStatus workStatus0 = new WorkStatus(
919                 work0.getId(),
920                 RUNNING,
921                 Data.EMPTY,
922                 Arrays.asList(TestWorker.class.getName(), firstTag, secondTag));
923         WorkStatus workStatus1 = new WorkStatus(
924                 work1.getId(),
925                 BLOCKED,
926                 Data.EMPTY,
927                 Arrays.asList(TestWorker.class.getName(), firstTag));
928         WorkStatus workStatus2 = new WorkStatus(
929                 work2.getId(),
930                 SUCCEEDED,
931                 Data.EMPTY,
932                 Arrays.asList(TestWorker.class.getName(), secondTag));
933 
934         List<WorkStatus> workStatuses = mWorkManagerImpl.getStatusesByTagSync(firstTag);
935         assertThat(workStatuses, containsInAnyOrder(workStatus0, workStatus1));
936 
937         workStatuses = mWorkManagerImpl.getStatusesByTagSync(secondTag);
938         assertThat(workStatuses, containsInAnyOrder(workStatus0, workStatus2));
939 
940         workStatuses = mWorkManagerImpl.getStatusesByTagSync("dummy");
941         assertThat(workStatuses.size(), is(0));
942     }
943 
944     @Test
945     @SmallTest
946     @SuppressWarnings("unchecked")
testGetStatusesByTag()947     public void testGetStatusesByTag() {
948         final String firstTag = "first_tag";
949         final String secondTag = "second_tag";
950         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
951 
952         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
953                 .addTag(firstTag)
954                 .addTag(secondTag)
955                 .setInitialState(RUNNING)
956                 .build();
957         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
958                 .addTag(firstTag)
959                 .setInitialState(BLOCKED)
960                 .build();
961         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class)
962                 .addTag(secondTag)
963                 .setInitialState(SUCCEEDED)
964                 .build();
965         insertWorkSpecAndTags(work0);
966         insertWorkSpecAndTags(work1);
967         insertWorkSpecAndTags(work2);
968 
969         Observer<List<WorkStatus>> mockObserver = mock(Observer.class);
970 
971         TestLifecycleOwner testLifecycleOwner = new TestLifecycleOwner();
972         LiveData<List<WorkStatus>> liveData = mWorkManagerImpl.getStatusesByTag(firstTag);
973         liveData.observe(testLifecycleOwner, mockObserver);
974 
975         ArgumentCaptor<List<WorkStatus>> captor = ArgumentCaptor.forClass(List.class);
976         verify(mockObserver).onChanged(captor.capture());
977         assertThat(captor.getValue(), is(not(nullValue())));
978         assertThat(captor.getValue().size(), is(2));
979 
980         WorkStatus workStatus0 = new WorkStatus(
981                 work0.getId(),
982                 RUNNING,
983                 Data.EMPTY,
984                 Arrays.asList(TestWorker.class.getName(), firstTag, secondTag));
985         WorkStatus workStatus1 = new WorkStatus(
986                 work1.getId(),
987                 BLOCKED,
988                 Data.EMPTY,
989                 Arrays.asList(TestWorker.class.getName(), firstTag));
990         assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
991 
992         workSpecDao.setState(ENQUEUED, work0.getStringId());
993 
994         verify(mockObserver, times(2)).onChanged(captor.capture());
995         assertThat(captor.getValue(), is(not(nullValue())));
996         assertThat(captor.getValue().size(), is(2));
997 
998         workStatus0 = new WorkStatus(
999                 work0.getId(),
1000                 ENQUEUED,
1001                 Data.EMPTY,
1002                 Arrays.asList(TestWorker.class.getName(), firstTag, secondTag));
1003         assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
1004 
1005         liveData.removeObservers(testLifecycleOwner);
1006     }
1007 
1008     @Test
1009     @SmallTest
getStatusByNameSync()1010     public void getStatusByNameSync() {
1011         final String uniqueName = "myname";
1012 
1013         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class)
1014                 .setInitialState(RUNNING)
1015                 .build();
1016         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class)
1017                 .setInitialState(BLOCKED)
1018                 .build();
1019         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class)
1020                 .setInitialState(BLOCKED)
1021                 .build();
1022         insertNamedWorks(uniqueName, work0, work1, work2);
1023         insertDependency(work1, work0);
1024         insertDependency(work2, work1);
1025 
1026         WorkStatus workStatus0 = new WorkStatus(
1027                 work0.getId(),
1028                 RUNNING,
1029                 Data.EMPTY,
1030                 Collections.singletonList(InfiniteTestWorker.class.getName()));
1031         WorkStatus workStatus1 = new WorkStatus(
1032                 work1.getId(),
1033                 BLOCKED,
1034                 Data.EMPTY,
1035                 Collections.singletonList(InfiniteTestWorker.class.getName()));
1036         WorkStatus workStatus2 = new WorkStatus(
1037                 work2.getId(),
1038                 BLOCKED,
1039                 Data.EMPTY,
1040                 Collections.singletonList(InfiniteTestWorker.class.getName()));
1041 
1042         List<WorkStatus> workStatuses = mWorkManagerImpl.getStatusesForUniqueWorkSync(uniqueName);
1043         assertThat(workStatuses, containsInAnyOrder(workStatus0, workStatus1, workStatus2));
1044 
1045         workStatuses = mWorkManagerImpl.getStatusesForUniqueWorkSync("dummy");
1046         assertThat(workStatuses.size(), is(0));
1047     }
1048 
1049     @Test
1050     @SmallTest
1051     @SuppressWarnings("unchecked")
testGetStatusesByName()1052     public void testGetStatusesByName() {
1053         final String uniqueName = "myname";
1054         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1055 
1056         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class)
1057                 .setInitialState(RUNNING)
1058                 .build();
1059         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class)
1060                 .setInitialState(BLOCKED)
1061                 .build();
1062         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class)
1063                 .setInitialState(BLOCKED)
1064                 .build();
1065         insertNamedWorks(uniqueName, work0, work1, work2);
1066         insertDependency(work1, work0);
1067         insertDependency(work2, work1);
1068 
1069         Observer<List<WorkStatus>> mockObserver = mock(Observer.class);
1070 
1071         TestLifecycleOwner testLifecycleOwner = new TestLifecycleOwner();
1072         LiveData<List<WorkStatus>> liveData = mWorkManagerImpl.getStatusesForUniqueWork(uniqueName);
1073         liveData.observe(testLifecycleOwner, mockObserver);
1074 
1075         ArgumentCaptor<List<WorkStatus>> captor = ArgumentCaptor.forClass(List.class);
1076         verify(mockObserver).onChanged(captor.capture());
1077         assertThat(captor.getValue(), is(not(nullValue())));
1078         assertThat(captor.getValue().size(), is(3));
1079 
1080         WorkStatus workStatus0 = new WorkStatus(
1081                 work0.getId(),
1082                 RUNNING,
1083                 Data.EMPTY,
1084                 Collections.singletonList(InfiniteTestWorker.class.getName()));
1085         WorkStatus workStatus1 = new WorkStatus(
1086                 work1.getId(),
1087                 BLOCKED,
1088                 Data.EMPTY,
1089                 Collections.singletonList(InfiniteTestWorker.class.getName()));
1090         WorkStatus workStatus2 = new WorkStatus(
1091                 work2.getId(),
1092                 BLOCKED,
1093                 Data.EMPTY,
1094                 Collections.singletonList(InfiniteTestWorker.class.getName()));
1095         assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1, workStatus2));
1096 
1097         workSpecDao.setState(ENQUEUED, work0.getStringId());
1098 
1099         verify(mockObserver, times(2)).onChanged(captor.capture());
1100         assertThat(captor.getValue(), is(not(nullValue())));
1101         assertThat(captor.getValue().size(), is(3));
1102 
1103         workStatus0 = new WorkStatus(
1104                 work0.getId(),
1105                 ENQUEUED,
1106                 Data.EMPTY,
1107                 Collections.singletonList(InfiniteTestWorker.class.getName()));
1108         assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1, workStatus2));
1109 
1110         liveData.removeObservers(testLifecycleOwner);
1111     }
1112 
1113     @Test
1114     @SmallTest
testCancelWorkById()1115     public void testCancelWorkById() {
1116         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1117 
1118         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1119         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1120         insertWorkSpecAndTags(work0);
1121         insertWorkSpecAndTags(work1);
1122 
1123         mWorkManagerImpl.synchronous().cancelWorkByIdSync(work0.getId());
1124         assertThat(workSpecDao.getState(work0.getStringId()), is(CANCELLED));
1125         assertThat(workSpecDao.getState(work1.getStringId()), is(not(CANCELLED)));
1126     }
1127 
1128     @Test
1129     @SmallTest
testCancelWorkById_cancelsDependentWork()1130     public void testCancelWorkById_cancelsDependentWork() {
1131         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1132 
1133         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1134         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
1135                 .setInitialState(BLOCKED)
1136                 .build();
1137         insertWorkSpecAndTags(work0);
1138         insertWorkSpecAndTags(work1);
1139         insertDependency(work1, work0);
1140 
1141         mWorkManagerImpl.synchronous().cancelWorkByIdSync(work0.getId());
1142 
1143         assertThat(workSpecDao.getState(work0.getStringId()), is(CANCELLED));
1144         assertThat(workSpecDao.getState(work1.getStringId()), is(CANCELLED));
1145     }
1146 
1147     @Test
1148     @SmallTest
testCancelWorkById_cancelsUnfinishedWorkOnly()1149     public void testCancelWorkById_cancelsUnfinishedWorkOnly() {
1150         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1151 
1152         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
1153                 .setInitialState(SUCCEEDED)
1154                 .build();
1155         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
1156                 .setInitialState(ENQUEUED)
1157                 .build();
1158         insertWorkSpecAndTags(work0);
1159         insertWorkSpecAndTags(work1);
1160         insertDependency(work1, work0);
1161 
1162         mWorkManagerImpl.synchronous().cancelWorkByIdSync(work0.getId());
1163 
1164         assertThat(workSpecDao.getState(work0.getStringId()), is(SUCCEEDED));
1165         assertThat(workSpecDao.getState(work1.getStringId()), is(CANCELLED));
1166     }
1167 
1168     @Test
1169     @SmallTest
testCancelAllWorkByTag()1170     public void testCancelAllWorkByTag() {
1171         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1172 
1173         final String tagToClear = "tag_to_clear";
1174         final String tagNotToClear = "tag_not_to_clear";
1175 
1176         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
1177                 .addTag(tagToClear)
1178                 .build();
1179         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
1180                 .addTag(tagToClear)
1181                 .build();
1182         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class)
1183                 .addTag(tagNotToClear)
1184                 .build();
1185         OneTimeWorkRequest work3 = new OneTimeWorkRequest.Builder(TestWorker.class)
1186                 .addTag(tagNotToClear)
1187                 .build();
1188         insertWorkSpecAndTags(work0);
1189         insertWorkSpecAndTags(work1);
1190         insertWorkSpecAndTags(work2);
1191         insertWorkSpecAndTags(work3);
1192 
1193         mWorkManagerImpl.synchronous().cancelAllWorkByTagSync(tagToClear);
1194 
1195         assertThat(workSpecDao.getState(work0.getStringId()), is(CANCELLED));
1196         assertThat(workSpecDao.getState(work1.getStringId()), is(CANCELLED));
1197         assertThat(workSpecDao.getState(work2.getStringId()), is(not(CANCELLED)));
1198         assertThat(workSpecDao.getState(work3.getStringId()), is(not(CANCELLED)));
1199     }
1200 
1201     @Test
1202     @SmallTest
testCancelAllWorkByTag_cancelsDependentWork()1203     public void testCancelAllWorkByTag_cancelsDependentWork() {
1204         String tag = "tag";
1205 
1206         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
1207                 .addTag(tag)
1208                 .build();
1209 
1210         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1211         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1212         OneTimeWorkRequest work3 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1213         OneTimeWorkRequest work4 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1214 
1215         insertWorkSpecAndTags(work0);
1216         insertWorkSpecAndTags(work1);
1217         insertWorkSpecAndTags(work2);
1218         insertWorkSpecAndTags(work3);
1219         insertWorkSpecAndTags(work4);
1220 
1221         // Dependency graph:
1222         //                             0
1223         //                             |
1224         //                       |------------|
1225         //            3          1            4
1226         //            |          |
1227         //            ------------
1228         //                 |
1229         //                 2
1230 
1231         insertDependency(work2, work1);
1232         insertDependency(work2, work3);
1233         insertDependency(work1, work0);
1234         insertDependency(work4, work0);
1235 
1236         mWorkManagerImpl.synchronous().cancelAllWorkByTagSync(tag);
1237 
1238         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1239         assertThat(workSpecDao.getState(work0.getStringId()), is(CANCELLED));
1240         assertThat(workSpecDao.getState(work1.getStringId()), is(CANCELLED));
1241         assertThat(workSpecDao.getState(work2.getStringId()), is(CANCELLED));
1242         assertThat(workSpecDao.getState(work3.getStringId()), is(not(CANCELLED)));
1243         assertThat(workSpecDao.getState(work4.getStringId()), is(CANCELLED));
1244     }
1245 
1246     @Test
1247     @SmallTest
testCancelWorkByName()1248     public void testCancelWorkByName() {
1249         final String uniqueName = "myname";
1250 
1251         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
1252         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
1253         insertNamedWorks(uniqueName, work0, work1);
1254 
1255         mWorkManagerImpl.synchronous().cancelUniqueWorkSync(uniqueName);
1256 
1257         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1258         assertThat(workSpecDao.getState(work0.getStringId()), is(CANCELLED));
1259         assertThat(workSpecDao.getState(work1.getStringId()), is(CANCELLED));
1260     }
1261 
1262     @Test
1263     @LargeTest
testCancelWorkByName_ignoresFinishedWork()1264     public void testCancelWorkByName_ignoresFinishedWork() {
1265         final String uniqueName = "myname";
1266 
1267         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class)
1268                 .setInitialState(SUCCEEDED)
1269                 .build();
1270         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(InfiniteTestWorker.class).build();
1271         insertNamedWorks(uniqueName, work0, work1);
1272 
1273         mWorkManagerImpl.synchronous().cancelUniqueWorkSync(uniqueName);
1274 
1275         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1276         assertThat(workSpecDao.getState(work0.getStringId()), is(SUCCEEDED));
1277         assertThat(workSpecDao.getState(work1.getStringId()), is(CANCELLED));
1278     }
1279 
1280     @Test
1281     @SmallTest
testCancelAllWork()1282     public void testCancelAllWork() {
1283         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1284         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1285         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class)
1286                 .setInitialState(SUCCEEDED)
1287                 .build();
1288         insertWorkSpecAndTags(work0);
1289         insertWorkSpecAndTags(work1);
1290         insertWorkSpecAndTags(work2);
1291 
1292         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1293         assertThat(workSpecDao.getState(work0.getStringId()), is(ENQUEUED));
1294         assertThat(workSpecDao.getState(work1.getStringId()), is(ENQUEUED));
1295         assertThat(workSpecDao.getState(work2.getStringId()), is(SUCCEEDED));
1296 
1297         mWorkManagerImpl.synchronous().cancelAllWorkSync();
1298         assertThat(workSpecDao.getState(work0.getStringId()), is(CANCELLED));
1299         assertThat(workSpecDao.getState(work1.getStringId()), is(CANCELLED));
1300         assertThat(workSpecDao.getState(work2.getStringId()), is(SUCCEEDED));
1301     }
1302 
1303     @Test
1304     @MediumTest
testCancelAllWork_updatesLastCancelAllTime()1305     public void testCancelAllWork_updatesLastCancelAllTime() {
1306         Preferences preferences = new Preferences(InstrumentationRegistry.getTargetContext());
1307         preferences.setLastCancelAllTimeMillis(0L);
1308 
1309         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1310         insertWorkSpecAndTags(work);
1311 
1312         CancelWorkRunnable.forAll(mWorkManagerImpl).run();
1313 
1314         assertThat(preferences.getLastCancelAllTimeMillis(), is(greaterThan(0L)));
1315     }
1316 
1317     @Test
1318     @SmallTest
1319     @SuppressWarnings("unchecked")
testCancelAllWork_updatesLastCancelAllTimeLiveData()1320     public void testCancelAllWork_updatesLastCancelAllTimeLiveData() throws InterruptedException {
1321         Preferences preferences = new Preferences(InstrumentationRegistry.getTargetContext());
1322         preferences.setLastCancelAllTimeMillis(0L);
1323 
1324         TestLifecycleOwner testLifecycleOwner = new TestLifecycleOwner();
1325         LiveData<Long> cancelAllTimeLiveData = mWorkManagerImpl.getLastCancelAllTimeMillis();
1326         Observer<Long> mockObserver = mock(Observer.class);
1327         cancelAllTimeLiveData.observe(testLifecycleOwner, mockObserver);
1328 
1329         ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(Long.class);
1330         verify(mockObserver).onChanged(captor.capture());
1331         assertThat(captor.getValue(), is(0L));
1332 
1333         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1334         insertWorkSpecAndTags(work);
1335 
1336         clearInvocations(mockObserver);
1337         CancelWorkRunnable.forAll(mWorkManagerImpl).run();
1338 
1339         Thread.sleep(1000L);
1340         verify(mockObserver).onChanged(captor.capture());
1341         assertThat(captor.getValue(), is(greaterThan(0L)));
1342 
1343         cancelAllTimeLiveData.removeObservers(testLifecycleOwner);
1344     }
1345 
1346     @Test
1347     @SmallTest
pruneFinishedWork()1348     public void pruneFinishedWork() {
1349         OneTimeWorkRequest enqueuedWork = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1350         OneTimeWorkRequest finishedWork =
1351                 new OneTimeWorkRequest.Builder(TestWorker.class).setInitialState(SUCCEEDED).build();
1352         OneTimeWorkRequest finishedWorkWithUnfinishedDependent =
1353                 new OneTimeWorkRequest.Builder(TestWorker.class).setInitialState(SUCCEEDED).build();
1354         OneTimeWorkRequest finishedWorkWithLongKeepForAtLeast =
1355                 new OneTimeWorkRequest.Builder(TestWorker.class)
1356                         .setInitialState(SUCCEEDED)
1357                         .keepResultsForAtLeast(999, TimeUnit.DAYS)
1358                         .build();
1359 
1360         insertWorkSpecAndTags(enqueuedWork);
1361         insertWorkSpecAndTags(finishedWork);
1362         insertWorkSpecAndTags(finishedWorkWithUnfinishedDependent);
1363         insertWorkSpecAndTags(finishedWorkWithLongKeepForAtLeast);
1364 
1365         insertDependency(enqueuedWork, finishedWorkWithUnfinishedDependent);
1366 
1367         mWorkManagerImpl.synchronous().pruneWorkSync();
1368 
1369         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1370         assertThat(workSpecDao.getWorkSpec(enqueuedWork.getStringId()), is(notNullValue()));
1371         assertThat(workSpecDao.getWorkSpec(finishedWork.getStringId()), is(nullValue()));
1372         assertThat(workSpecDao.getWorkSpec(finishedWorkWithUnfinishedDependent.getStringId()),
1373                 is(notNullValue()));
1374         assertThat(workSpecDao.getWorkSpec(finishedWorkWithLongKeepForAtLeast.getStringId()),
1375                 is(nullValue()));
1376     }
1377 
1378     @Test
1379     @SmallTest
testSynchronousCancelAndGetStatus()1380     public void testSynchronousCancelAndGetStatus() {
1381         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
1382         insertWorkSpecAndTags(work);
1383 
1384         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1385         assertThat(workSpecDao.getState(work.getStringId()), is(ENQUEUED));
1386 
1387         mWorkManagerImpl.synchronous().cancelWorkByIdSync(work.getId());
1388         assertThat(mWorkManagerImpl.getStatusByIdSync(work.getId()).getState(), is(CANCELLED));
1389     }
1390 
1391     @Test
1392     @SmallTest
testGenerateCleanupCallback_resetsRunningWorkStatuses()1393     public void testGenerateCleanupCallback_resetsRunningWorkStatuses() {
1394         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1395 
1396         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
1397                 .setInitialState(RUNNING)
1398                 .build();
1399         workSpecDao.insertWorkSpec(work.getWorkSpec());
1400 
1401         assertThat(workSpecDao.getState(work.getStringId()), is(RUNNING));
1402 
1403         SupportSQLiteOpenHelper openHelper = mDatabase.getOpenHelper();
1404         SupportSQLiteDatabase db = openHelper.getWritableDatabase();
1405         WorkDatabase.generateCleanupCallback().onOpen(db);
1406 
1407         assertThat(workSpecDao.getState(work.getStringId()), is(ENQUEUED));
1408     }
1409 
1410     @Test
1411     @SmallTest
testGenerateCleanupCallback_deletesOldFinishedWork()1412     public void testGenerateCleanupCallback_deletesOldFinishedWork() {
1413         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
1414                 .setInitialState(SUCCEEDED)
1415                 .setPeriodStartTime(WorkDatabase.getPruneDate() - 1L, TimeUnit.MILLISECONDS)
1416                 .build();
1417         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class)
1418                 .setPeriodStartTime(Long.MAX_VALUE, TimeUnit.MILLISECONDS)
1419                 .build();
1420 
1421         insertWorkSpecAndTags(work1);
1422         insertWorkSpecAndTags(work2);
1423 
1424         SupportSQLiteOpenHelper openHelper = mDatabase.getOpenHelper();
1425         SupportSQLiteDatabase db = openHelper.getWritableDatabase();
1426         WorkDatabase.generateCleanupCallback().onOpen(db);
1427 
1428         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1429         assertThat(workSpecDao.getWorkSpec(work1.getStringId()), is(nullValue()));
1430         assertThat(workSpecDao.getWorkSpec(work2.getStringId()), is(not(nullValue())));
1431     }
1432 
1433     @Test
1434     @SmallTest
testGenerateCleanupCallback_doesNotDeleteOldFinishedWorkWithActiveDependents()1435     public void testGenerateCleanupCallback_doesNotDeleteOldFinishedWorkWithActiveDependents() {
1436         OneTimeWorkRequest work0 = new OneTimeWorkRequest.Builder(TestWorker.class)
1437                 .setInitialState(SUCCEEDED)
1438                 .setPeriodStartTime(WorkDatabase.getPruneDate() - 1L, TimeUnit.MILLISECONDS)
1439                 .build();
1440         OneTimeWorkRequest work1 = new OneTimeWorkRequest.Builder(TestWorker.class)
1441                 .setInitialState(SUCCEEDED)
1442                 .setPeriodStartTime(WorkDatabase.getPruneDate() - 1L, TimeUnit.MILLISECONDS)
1443                 .build();
1444         OneTimeWorkRequest work2 = new OneTimeWorkRequest.Builder(TestWorker.class)
1445                 .setInitialState(ENQUEUED)
1446                 .setPeriodStartTime(WorkDatabase.getPruneDate() - 1L, TimeUnit.MILLISECONDS)
1447                 .build();
1448 
1449         insertWorkSpecAndTags(work0);
1450         insertWorkSpecAndTags(work1);
1451         insertWorkSpecAndTags(work2);
1452 
1453         // Dependency graph: 0 -> 1 -> 2
1454         insertDependency(work1, work0);
1455         insertDependency(work2, work1);
1456 
1457         SupportSQLiteOpenHelper openHelper = mDatabase.getOpenHelper();
1458         SupportSQLiteDatabase db = openHelper.getWritableDatabase();
1459         WorkDatabase.generateCleanupCallback().onOpen(db);
1460 
1461         WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1462         assertThat(workSpecDao.getWorkSpec(work0.getStringId()), is(nullValue()));
1463         assertThat(workSpecDao.getWorkSpec(work1.getStringId()), is(not(nullValue())));
1464         assertThat(workSpecDao.getWorkSpec(work2.getStringId()), is(not(nullValue())));
1465     }
1466 
1467     @Test
1468     @SmallTest
1469     @SdkSuppress(maxSdkVersion = 22)
testEnqueueApi22OrLower_withBatteryNotLowConstraint_expectsOriginalWorker()1470     public void testEnqueueApi22OrLower_withBatteryNotLowConstraint_expectsOriginalWorker() {
1471         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
1472                 .setConstraints(new Constraints.Builder()
1473                         .setRequiresBatteryNotLow(true)
1474                         .build())
1475                 .build();
1476         mWorkManagerImpl.beginWith(work).synchronous().enqueueSync();
1477 
1478         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getStringId());
1479         assertThat(workSpec.workerClassName, is(TestWorker.class.getName()));
1480     }
1481 
1482     @Test
1483     @SmallTest
1484     @SdkSuppress(maxSdkVersion = 22)
testEnqueueApi22OrLower_withStorageNotLowConstraint_expectsOriginalWorker()1485     public void testEnqueueApi22OrLower_withStorageNotLowConstraint_expectsOriginalWorker() {
1486         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
1487                 .setConstraints(new Constraints.Builder()
1488                         .setRequiresStorageNotLow(true)
1489                         .build())
1490                 .build();
1491         mWorkManagerImpl.beginWith(work).synchronous().enqueueSync();
1492 
1493         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getStringId());
1494         assertThat(workSpec.workerClassName, is(TestWorker.class.getName()));
1495     }
1496 
1497     @Test
1498     @SmallTest
1499     @SdkSuppress(minSdkVersion = 23, maxSdkVersion = 25)
testEnqueueApi23To25_withBatteryNotLowConstraint_expectsConstraintTrackingWorker()1500     public void testEnqueueApi23To25_withBatteryNotLowConstraint_expectsConstraintTrackingWorker() {
1501         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
1502                 .setConstraints(new Constraints.Builder()
1503                 .setRequiresBatteryNotLow(true)
1504                 .build())
1505                 .build();
1506         mWorkManagerImpl.beginWith(work).synchronous().enqueueSync();
1507 
1508         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getStringId());
1509         assertThat(workSpec.workerClassName, is(ConstraintTrackingWorker.class.getName()));
1510         assertThat(workSpec.input.getString(
1511                 ConstraintTrackingWorker.ARGUMENT_CLASS_NAME, null),
1512                 is(TestWorker.class.getName()));
1513     }
1514 
1515     @Test
1516     @SmallTest
1517     @SdkSuppress(minSdkVersion = 23, maxSdkVersion = 25)
testEnqueueApi23To25_withStorageNotLowConstraint_expectsConstraintTrackingWorker()1518     public void testEnqueueApi23To25_withStorageNotLowConstraint_expectsConstraintTrackingWorker() {
1519         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
1520                 .setConstraints(new Constraints.Builder()
1521                         .setRequiresStorageNotLow(true)
1522                         .build())
1523                 .build();
1524         mWorkManagerImpl.beginWith(work).synchronous().enqueueSync();
1525 
1526         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getStringId());
1527         assertThat(workSpec.workerClassName, is(ConstraintTrackingWorker.class.getName()));
1528         assertThat(workSpec.input.getString(
1529                 ConstraintTrackingWorker.ARGUMENT_CLASS_NAME, null),
1530                 is(TestWorker.class.getName()));
1531     }
1532 
1533     @Test
1534     @SmallTest
1535     @SdkSuppress(minSdkVersion = 26)
testEnqueueApi26OrHigher_withBatteryNotLowConstraint_expectsOriginalWorker()1536     public void testEnqueueApi26OrHigher_withBatteryNotLowConstraint_expectsOriginalWorker() {
1537         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
1538                 .setConstraints(new Constraints.Builder()
1539                         .setRequiresBatteryNotLow(true)
1540                         .build())
1541                 .build();
1542         mWorkManagerImpl.beginWith(work).synchronous().enqueueSync();
1543 
1544         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getStringId());
1545         assertThat(workSpec.workerClassName, is(TestWorker.class.getName()));
1546     }
1547 
1548     @Test
1549     @SmallTest
1550     @SdkSuppress(minSdkVersion = 26)
testEnqueueApi26OrHigher_withStorageNotLowConstraint_expectsOriginalWorker()1551     public void testEnqueueApi26OrHigher_withStorageNotLowConstraint_expectsOriginalWorker() {
1552         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
1553                 .setConstraints(new Constraints.Builder()
1554                         .setRequiresStorageNotLow(true)
1555                         .build())
1556                 .build();
1557         mWorkManagerImpl.beginWith(work).synchronous().enqueueSync();
1558 
1559         WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getStringId());
1560         assertThat(workSpec.workerClassName, is(TestWorker.class.getName()));
1561     }
1562 
insertWorkSpecAndTags(WorkRequest work)1563     private void insertWorkSpecAndTags(WorkRequest work) {
1564         mDatabase.workSpecDao().insertWorkSpec(work.getWorkSpec());
1565         for (String tag : work.getTags()) {
1566             mDatabase.workTagDao().insert(new WorkTag(tag, work.getStringId()));
1567         }
1568     }
1569 
insertNamedWorks(String name, WorkRequest... works)1570     private void insertNamedWorks(String name, WorkRequest... works) {
1571         for (WorkRequest work : works) {
1572             insertWorkSpecAndTags(work);
1573             mDatabase.workNameDao().insert(new WorkName(name, work.getStringId()));
1574         }
1575     }
1576 
insertDependency(OneTimeWorkRequest work, OneTimeWorkRequest prerequisiteWork)1577     private void insertDependency(OneTimeWorkRequest work, OneTimeWorkRequest prerequisiteWork) {
1578         mDatabase.dependencyDao().insertDependency(
1579                 new Dependency(work.getStringId(), prerequisiteWork.getStringId()));
1580     }
1581 }
1582