WorkManagerImplTest.java revision 697d6a4a3797bc71d0dd8685937a318e9934066b
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
17package androidx.work.impl;
18
19import static androidx.work.ExistingWorkPolicy.APPEND;
20import static androidx.work.ExistingWorkPolicy.KEEP;
21import static androidx.work.ExistingWorkPolicy.REPLACE;
22import static androidx.work.NetworkType.METERED;
23import static androidx.work.NetworkType.NOT_REQUIRED;
24import static androidx.work.State.BLOCKED;
25import static androidx.work.State.CANCELLED;
26import static androidx.work.State.ENQUEUED;
27import static androidx.work.State.FAILED;
28import static androidx.work.State.RUNNING;
29import static androidx.work.State.SUCCEEDED;
30
31import static org.hamcrest.CoreMatchers.is;
32import static org.hamcrest.CoreMatchers.not;
33import static org.hamcrest.CoreMatchers.notNullValue;
34import static org.hamcrest.CoreMatchers.nullValue;
35import static org.hamcrest.MatcherAssert.assertThat;
36import static org.hamcrest.Matchers.containsInAnyOrder;
37import static org.hamcrest.Matchers.emptyCollectionOf;
38import static org.hamcrest.Matchers.greaterThanOrEqualTo;
39import static org.hamcrest.Matchers.isIn;
40import static org.hamcrest.Matchers.isOneOf;
41import static org.mockito.Mockito.clearInvocations;
42import static org.mockito.Mockito.mock;
43import static org.mockito.Mockito.times;
44import static org.mockito.Mockito.verify;
45
46import android.arch.core.executor.ArchTaskExecutor;
47import android.arch.core.executor.TaskExecutor;
48import android.arch.lifecycle.LiveData;
49import android.arch.lifecycle.Observer;
50import android.arch.persistence.db.SupportSQLiteDatabase;
51import android.arch.persistence.db.SupportSQLiteOpenHelper;
52import android.content.Context;
53import android.net.Uri;
54import android.os.Build;
55import android.provider.MediaStore;
56import android.support.annotation.NonNull;
57import android.support.test.InstrumentationRegistry;
58import android.support.test.filters.SdkSuppress;
59import android.support.test.filters.SmallTest;
60import android.support.test.runner.AndroidJUnit4;
61import android.util.Log;
62
63import androidx.work.BackoffPolicy;
64import androidx.work.BaseWorkRequest;
65import androidx.work.Configuration;
66import androidx.work.Constraints;
67import androidx.work.ContentUriTriggers;
68import androidx.work.Data;
69import androidx.work.PeriodicWorkRequest;
70import androidx.work.TestLifecycleOwner;
71import androidx.work.WorkContinuation;
72import androidx.work.WorkRequest;
73import androidx.work.WorkStatus;
74import androidx.work.impl.logger.InternalLogger;
75import androidx.work.impl.model.Dependency;
76import androidx.work.impl.model.DependencyDao;
77import androidx.work.impl.model.WorkName;
78import androidx.work.impl.model.WorkSpec;
79import androidx.work.impl.model.WorkSpecDao;
80import androidx.work.impl.model.WorkTag;
81import androidx.work.impl.model.WorkTagDao;
82import androidx.work.impl.utils.taskexecutor.InstantTaskExecutorRule;
83import androidx.work.impl.workers.ConstraintTrackingWorker;
84import androidx.work.worker.InfiniteTestWorker;
85import androidx.work.worker.TestWorker;
86
87import org.junit.After;
88import org.junit.Before;
89import org.junit.Rule;
90import org.junit.Test;
91import org.junit.runner.RunWith;
92import org.mockito.ArgumentCaptor;
93
94import java.util.Arrays;
95import java.util.Collections;
96import java.util.List;
97import java.util.concurrent.Executors;
98import java.util.concurrent.TimeUnit;
99
100@RunWith(AndroidJUnit4.class)
101public class WorkManagerImplTest {
102
103    static {
104        InternalLogger.LOG_LEVEL = Log.DEBUG;
105    }
106
107    private WorkDatabase mDatabase;
108    private WorkManagerImpl mWorkManagerImpl;
109
110    @Rule
111    public InstantTaskExecutorRule mRule = new InstantTaskExecutorRule();
112
113    @Before
114    public void setUp() {
115        ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
116            @Override
117            public void executeOnDiskIO(@NonNull Runnable runnable) {
118                runnable.run();
119            }
120
121            @Override
122            public void postToMainThread(@NonNull Runnable runnable) {
123                runnable.run();
124            }
125
126            @Override
127            public boolean isMainThread() {
128                return true;
129            }
130        });
131
132        Context context = InstrumentationRegistry.getTargetContext();
133        Configuration configuration = new Configuration.Builder()
134                .withExecutorService(Executors.newSingleThreadExecutor())
135                .build();
136        mWorkManagerImpl = new WorkManagerImpl(context, configuration);
137        WorkManagerImpl.setDelegate(mWorkManagerImpl);
138        mDatabase = mWorkManagerImpl.getWorkDatabase();
139    }
140
141    @After
142    public void tearDown() {
143        List<String> ids = mDatabase.workSpecDao().getAllWorkSpecIds();
144        for (String id : ids) {
145            mWorkManagerImpl.blocking().cancelWorkByIdBlocking(id);
146        }
147        WorkManagerImpl.setDelegate(null);
148        ArchTaskExecutor.getInstance().setDelegate(null);
149    }
150
151    @Test
152    @SmallTest
153    public void testEnqueue_insertWork() throws InterruptedException {
154        final int workCount = 3;
155        final WorkRequest[] workArray = new WorkRequest[workCount];
156        for (int i = 0; i < workCount; ++i) {
157            workArray[i] = new WorkRequest.Builder(TestWorker.class).build();
158        }
159
160        mWorkManagerImpl.beginWith(workArray[0]).then(workArray[1])
161                .then(workArray[2])
162                .blocking().enqueueBlocking();
163
164        for (int i = 0; i < workCount; ++i) {
165            String id = workArray[i].getId();
166            assertThat(mDatabase.workSpecDao().getWorkSpec(id), is(notNullValue()));
167            assertThat(
168                    "index " + i + " does not have expected number of dependencies!",
169                    mDatabase.dependencyDao().getPrerequisites(id).size() > 0,
170                    is(i > 0));
171        }
172    }
173
174    @Test
175    @SmallTest
176    public void testEnqueue_insertMultipleWork() {
177        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).build();
178        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class).build();
179        WorkRequest work3 = new WorkRequest.Builder(TestWorker.class).build();
180
181        mWorkManagerImpl.blocking().enqueueBlocking(work1, work2, work3);
182
183        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
184        assertThat(workSpecDao.getWorkSpec(work1.getId()), is(notNullValue()));
185        assertThat(workSpecDao.getWorkSpec(work2.getId()), is(notNullValue()));
186        assertThat(workSpecDao.getWorkSpec(work3.getId()), is(notNullValue()));
187    }
188
189    @Test
190    @SmallTest
191    public void testEnqueue_insertMultipleWork_continuationBlocking() {
192        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).build();
193        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class).build();
194        WorkRequest work3 = new WorkRequest.Builder(TestWorker.class).build();
195
196        mWorkManagerImpl.beginWith(work1, work2, work3)
197                .blocking()
198                .enqueueBlocking();
199
200        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
201        assertThat(workSpecDao.getWorkSpec(work1.getId()), is(notNullValue()));
202        assertThat(workSpecDao.getWorkSpec(work2.getId()), is(notNullValue()));
203        assertThat(workSpecDao.getWorkSpec(work3.getId()), is(notNullValue()));
204    }
205
206    @Test
207    @SmallTest
208    public void testEnqueue_insertWithDependencies() {
209        WorkRequest work1a = new WorkRequest.Builder(TestWorker.class).build();
210        WorkRequest work1b = new WorkRequest.Builder(TestWorker.class).build();
211        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class).build();
212        WorkRequest work3a = new WorkRequest.Builder(TestWorker.class).build();
213        WorkRequest work3b = new WorkRequest.Builder(TestWorker.class).build();
214
215        mWorkManagerImpl.beginWith(work1a, work1b).then(work2)
216                .then(work3a, work3b)
217                .blocking()
218                .enqueueBlocking();
219
220        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
221        assertThat(workSpecDao.getWorkSpec(work1a.getId()), is(notNullValue()));
222        assertThat(workSpecDao.getWorkSpec(work1b.getId()), is(notNullValue()));
223        assertThat(workSpecDao.getWorkSpec(work2.getId()), is(notNullValue()));
224        assertThat(workSpecDao.getWorkSpec(work3a.getId()), is(notNullValue()));
225        assertThat(workSpecDao.getWorkSpec(work3b.getId()), is(notNullValue()));
226
227        DependencyDao dependencyDao = mDatabase.dependencyDao();
228        assertThat(dependencyDao.getPrerequisites(work1a.getId()),
229                is(emptyCollectionOf(String.class)));
230        assertThat(dependencyDao.getPrerequisites(work1b.getId()),
231                is(emptyCollectionOf(String.class)));
232
233        List<String> prerequisites = dependencyDao.getPrerequisites(work2.getId());
234        assertThat(prerequisites, containsInAnyOrder(work1a.getId(), work1b.getId()));
235
236        prerequisites = dependencyDao.getPrerequisites(work3a.getId());
237        assertThat(prerequisites, containsInAnyOrder(work2.getId()));
238
239        prerequisites = dependencyDao.getPrerequisites(work3b.getId());
240        assertThat(prerequisites, containsInAnyOrder(work2.getId()));
241    }
242
243    @Test
244    @SmallTest
245    public void testEnqueue_insertWithCompletedDependencies_isNotStatusBlocked() {
246        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class)
247                .withInitialState(SUCCEEDED)
248                .build();
249
250        WorkContinuation workContinuation = mWorkManagerImpl.beginWith(work1);
251        workContinuation.blocking().enqueueBlocking();
252        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
253        assertThat(workSpecDao.getState(work1.getId()), is(SUCCEEDED));
254
255        WorkRequest work2 = new WorkRequest.Builder(InfiniteTestWorker.class).build();
256        workContinuation.then(work2).blocking().enqueueBlocking();
257        assertThat(workSpecDao.getState(work2.getId()), isOneOf(ENQUEUED, RUNNING));
258    }
259
260    @Test
261    @SmallTest
262    public void testEnqueue_insertWithFailedDependencies_isStatusFailed() {
263        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class)
264                .withInitialState(FAILED)
265                .build();
266
267        WorkContinuation workContinuation = mWorkManagerImpl.beginWith(work1);
268        workContinuation.blocking().enqueueBlocking();
269        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
270        assertThat(workSpecDao.getState(work1.getId()), is(FAILED));
271
272        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class).build();
273        workContinuation.then(work2).blocking().enqueueBlocking();
274        assertThat(workSpecDao.getState(work2.getId()), is(FAILED));
275    }
276
277    @Test
278    @SmallTest
279    public void testEnqueue_insertWithCancelledDependencies_isStatusCancelled() {
280        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class)
281                .withInitialState(CANCELLED)
282                .build();
283
284        WorkContinuation workContinuation = mWorkManagerImpl.beginWith(work1);
285        workContinuation.blocking().enqueueBlocking();
286        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
287        assertThat(workSpecDao.getState(work1.getId()), is(CANCELLED));
288
289        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class).build();
290        workContinuation.then(work2).blocking().enqueueBlocking();
291        assertThat(workSpecDao.getState(work2.getId()), is(CANCELLED));
292    }
293
294    @Test
295    @SmallTest
296    @SdkSuppress(minSdkVersion = 23)
297    public void testEnqueue_insertWorkConstraints() {
298        Uri testUri1 = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
299        Uri testUri2 = MediaStore.Images.Media.INTERNAL_CONTENT_URI;
300
301        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class)
302                .withConstraints(
303                        new Constraints.Builder()
304                                .setRequiresCharging(true)
305                                .setRequiresDeviceIdle(true)
306                                .setRequiredNetworkType(METERED)
307                                .setRequiresBatteryNotLow(true)
308                                .setRequiresStorageNotLow(true)
309                                .addContentUriTrigger(testUri1, true)
310                                .addContentUriTrigger(testUri2, false)
311                                .build())
312                .build();
313        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).build();
314        mWorkManagerImpl.beginWith(work0).then(work1).blocking().enqueueBlocking();
315
316        WorkSpec workSpec0 = mDatabase.workSpecDao().getWorkSpec(work0.getId());
317        WorkSpec workSpec1 = mDatabase.workSpecDao().getWorkSpec(work1.getId());
318
319        ContentUriTriggers expectedTriggers = new ContentUriTriggers();
320        expectedTriggers.add(testUri1, true);
321        expectedTriggers.add(testUri2, false);
322
323        Constraints constraints = workSpec0.constraints;
324        assertThat(constraints, is(notNullValue()));
325        assertThat(constraints.requiresCharging(), is(true));
326        assertThat(constraints.requiresDeviceIdle(), is(true));
327        assertThat(constraints.requiresBatteryNotLow(), is(true));
328        assertThat(constraints.requiresStorageNotLow(), is(true));
329        assertThat(constraints.getRequiredNetworkType(), is(METERED));
330        if (Build.VERSION.SDK_INT >= 24) {
331            assertThat(constraints.getContentUriTriggers(), is(expectedTriggers));
332        } else {
333            assertThat(constraints.getContentUriTriggers(), is(new ContentUriTriggers()));
334        }
335
336        constraints = workSpec1.constraints;
337        assertThat(constraints, is(notNullValue()));
338        assertThat(constraints.requiresCharging(), is(false));
339        assertThat(constraints.requiresDeviceIdle(), is(false));
340        assertThat(constraints.requiresBatteryNotLow(), is(false));
341        assertThat(constraints.requiresStorageNotLow(), is(false));
342        assertThat(constraints.getRequiredNetworkType(), is(NOT_REQUIRED));
343        assertThat(constraints.getContentUriTriggers().size(), is(0));
344    }
345
346    @Test
347    @SmallTest
348    public void testEnqueue_insertWorkInitialDelay() {
349        final long expectedInitialDelay = 5000L;
350        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class)
351                .withInitialDelay(expectedInitialDelay, TimeUnit.MILLISECONDS)
352                .build();
353        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).build();
354        mWorkManagerImpl.beginWith(work0).then(work1).blocking().enqueueBlocking();
355
356        WorkSpec workSpec0 = mDatabase.workSpecDao().getWorkSpec(work0.getId());
357        WorkSpec workSpec1 = mDatabase.workSpecDao().getWorkSpec(work1.getId());
358
359        assertThat(workSpec0.initialDelay, is(expectedInitialDelay));
360        assertThat(workSpec1.initialDelay, is(0L));
361    }
362
363    @Test
364    @SmallTest
365    public void testEnqueue_insertWorkBackoffPolicy() {
366        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class)
367                .withBackoffCriteria(BackoffPolicy.LINEAR, 50000, TimeUnit.MILLISECONDS)
368                .build();
369        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).build();
370        mWorkManagerImpl.beginWith(work0).then(work1).blocking().enqueueBlocking();
371
372        WorkSpec workSpec0 = mDatabase.workSpecDao().getWorkSpec(work0.getId());
373        WorkSpec workSpec1 = mDatabase.workSpecDao().getWorkSpec(work1.getId());
374
375        assertThat(workSpec0.backoffPolicy, is(BackoffPolicy.LINEAR));
376        assertThat(workSpec0.backoffDelayDuration, is(50000L));
377
378        assertThat(workSpec1.backoffPolicy, is(BackoffPolicy.EXPONENTIAL));
379        assertThat(workSpec1.backoffDelayDuration,
380                is(BaseWorkRequest.DEFAULT_BACKOFF_DELAY_MILLIS));
381    }
382
383    @Test
384    @SmallTest
385    public void testEnqueue_insertWorkTags() {
386        final String firstTag = "first_tag";
387        final String secondTag = "second_tag";
388        final String thirdTag = "third_tag";
389
390        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class)
391                .addTag(firstTag)
392                .addTag(secondTag)
393                .build();
394        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).addTag(firstTag).build();
395        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class).build();
396        mWorkManagerImpl.beginWith(work0).then(work1).then(work2).blocking().enqueueBlocking();
397
398        WorkTagDao workTagDao = mDatabase.workTagDao();
399        assertThat(workTagDao.getWorkSpecIdsWithTag(firstTag),
400                containsInAnyOrder(work0.getId(), work1.getId()));
401        assertThat(workTagDao.getWorkSpecIdsWithTag(secondTag), containsInAnyOrder(work0.getId()));
402        assertThat(workTagDao.getWorkSpecIdsWithTag(thirdTag), emptyCollectionOf(String.class));
403    }
404
405    @Test
406    @SmallTest
407    public void testEnqueue_insertPeriodicWork() {
408        PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(
409                TestWorker.class,
410                PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
411                TimeUnit.MILLISECONDS)
412                .build();
413
414        mWorkManagerImpl.blocking().enqueueBlocking(periodicWork);
415
416        WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(periodicWork.getId());
417        assertThat(workSpec.isPeriodic(), is(true));
418        assertThat(workSpec.intervalDuration, is(PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS));
419        assertThat(workSpec.flexDuration, is(PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS));
420    }
421
422    @Test
423    @SmallTest
424    public void testEnqueued_work_setsPeriodStartTime() {
425        WorkRequest work = new WorkRequest.Builder(TestWorker.class).build();
426        assertThat(work.getWorkSpec().periodStartTime, is(0L));
427
428        long beforeEnqueueTime = System.currentTimeMillis();
429
430        mWorkManagerImpl.beginWith(work).blocking().enqueueBlocking();
431        WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getId());
432        assertThat(workSpec.periodStartTime, is(greaterThanOrEqualTo(beforeEnqueueTime)));
433    }
434
435    @Test
436    @SmallTest
437    public void testEnqueued_periodicWork_setsPeriodStartTime() {
438        PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(
439                TestWorker.class,
440                PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
441                TimeUnit.MILLISECONDS)
442                .build();
443        assertThat(periodicWork.getWorkSpec().periodStartTime, is(0L));
444
445        long beforeEnqueueTime = System.currentTimeMillis();
446
447        mWorkManagerImpl.blocking().enqueueBlocking(periodicWork);
448
449        WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(periodicWork.getId());
450        assertThat(workSpec.periodStartTime, is(greaterThanOrEqualTo(beforeEnqueueTime)));
451    }
452
453    @Test
454    @SmallTest
455    public void testBeginWithName_setsUniqueName() {
456        final String testName = "myname";
457
458        WorkRequest work = new WorkRequest.Builder(TestWorker.class).build();
459        mWorkManagerImpl.beginUniqueWork(testName, REPLACE)
460                .then(work)
461                .blocking()
462                .enqueueBlocking();
463
464        List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
465        assertThat(work.getId(), isIn(workSpecIds));
466    }
467
468    @Test
469    @SmallTest
470    public void testBeginWithName_deletesOldWorkOnReplace() {
471        final String testName = "myname";
472
473        WorkRequest originalWork = new WorkRequest.Builder(InfiniteTestWorker.class).build();
474        insertNamedWorks(testName, originalWork);
475
476        List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
477        assertThat(workSpecIds, containsInAnyOrder(originalWork.getId()));
478
479        WorkRequest replacementWork1 = new WorkRequest.Builder(TestWorker.class).build();
480        WorkRequest replacementWork2 = new WorkRequest.Builder(TestWorker.class).build();
481        mWorkManagerImpl
482                .beginUniqueWork(testName, REPLACE, replacementWork1)
483                .then(replacementWork2)
484                .blocking()
485                .enqueueBlocking();
486
487        workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
488        assertThat(
489                workSpecIds,
490                containsInAnyOrder(replacementWork1.getId(), replacementWork2.getId()));
491
492        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
493        assertThat(workSpecDao.getWorkSpec(originalWork.getId()), is(nullValue()));
494        assertThat(workSpecDao.getWorkSpec(replacementWork1.getId()), is(not(nullValue())));
495        assertThat(workSpecDao.getWorkSpec(replacementWork2.getId()), is(not(nullValue())));
496    }
497
498    @Test
499    @SmallTest
500    public void testBeginWithName_keepsExistingWorkOnKeep() {
501        final String testName = "myname";
502
503        WorkRequest originalWork = new WorkRequest.Builder(InfiniteTestWorker.class).build();
504        insertNamedWorks(testName, originalWork);
505
506        List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
507        assertThat(workSpecIds, containsInAnyOrder(originalWork.getId()));
508
509        WorkRequest replacementWork1 = new WorkRequest.Builder(TestWorker.class).build();
510        WorkRequest replacementWork2 = new WorkRequest.Builder(TestWorker.class).build();
511        mWorkManagerImpl
512                .beginUniqueWork(testName, KEEP, replacementWork1)
513                .then(replacementWork2)
514                .blocking()
515                .enqueueBlocking();
516
517        workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
518        assertThat(workSpecIds, containsInAnyOrder(originalWork.getId()));
519
520        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
521        assertThat(workSpecDao.getWorkSpec(originalWork.getId()), is(not(nullValue())));
522        assertThat(workSpecDao.getWorkSpec(replacementWork1.getId()), is(nullValue()));
523        assertThat(workSpecDao.getWorkSpec(replacementWork2.getId()), is(nullValue()));
524    }
525
526    @Test
527    @SmallTest
528    public void testBeginWithName_replacesExistingWorkOnKeepWhenExistingWorkIsFinished() {
529        final String testName = "myname";
530
531        WorkRequest originalWork = new WorkRequest.Builder(TestWorker.class)
532                .withInitialState(SUCCEEDED)
533                .build();
534        insertNamedWorks(testName, originalWork);
535
536        List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
537        assertThat(workSpecIds, containsInAnyOrder(originalWork.getId()));
538
539        WorkRequest replacementWork1 = new WorkRequest.Builder(TestWorker.class).build();
540        WorkRequest replacementWork2 = new WorkRequest.Builder(TestWorker.class).build();
541        mWorkManagerImpl
542                .beginUniqueWork(testName, KEEP, replacementWork1)
543                .then(replacementWork2)
544                .blocking()
545                .enqueueBlocking();
546
547        workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
548        assertThat(workSpecIds,
549                containsInAnyOrder(replacementWork1.getId(), replacementWork2.getId()));
550
551        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
552        assertThat(workSpecDao.getWorkSpec(originalWork.getId()), is(nullValue()));
553        assertThat(workSpecDao.getWorkSpec(replacementWork1.getId()), is(not(nullValue())));
554        assertThat(workSpecDao.getWorkSpec(replacementWork2.getId()), is(not(nullValue())));
555    }
556
557    @Test
558    @SmallTest
559    public void testBeginWithName_appendsExistingWorkOnAppend() {
560        final String testName = "myname";
561
562        WorkRequest originalWork = new WorkRequest.Builder(InfiniteTestWorker.class).build();
563        insertNamedWorks(testName, originalWork);
564
565        List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
566        assertThat(workSpecIds, containsInAnyOrder(originalWork.getId()));
567
568        WorkRequest appendWork1 = new WorkRequest.Builder(TestWorker.class).build();
569        WorkRequest appendWork2 = new WorkRequest.Builder(TestWorker.class).build();
570        mWorkManagerImpl
571                .beginUniqueWork(testName, APPEND, appendWork1)
572                .then(appendWork2)
573                .blocking()
574                .enqueueBlocking();
575
576        workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
577        assertThat(workSpecIds,
578                containsInAnyOrder(originalWork.getId(), appendWork1.getId(), appendWork2.getId()));
579
580        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
581        assertThat(workSpecDao.getWorkSpec(originalWork.getId()), is(not(nullValue())));
582        assertThat(workSpecDao.getState(appendWork1.getId()), is(BLOCKED));
583        assertThat(workSpecDao.getState(appendWork2.getId()), is(BLOCKED));
584
585        assertThat(mDatabase.dependencyDao().getDependentWorkIds(originalWork.getId()),
586                containsInAnyOrder(appendWork1.getId()));
587    }
588
589    @Test
590    @SmallTest
591    public void testBeginWithName_appendsExistingWorkToOnlyLeavesOnAppend() {
592        final String testName = "myname";
593
594        WorkRequest originalWork1 = new WorkRequest.Builder(InfiniteTestWorker.class).build();
595        WorkRequest originalWork2 = new WorkRequest.Builder(InfiniteTestWorker.class).build();
596        WorkRequest originalWork3 = new WorkRequest.Builder(InfiniteTestWorker.class).build();
597        WorkRequest originalWork4 = new WorkRequest.Builder(InfiniteTestWorker.class).build();
598        insertNamedWorks(testName, originalWork1, originalWork2, originalWork3, originalWork4);
599        insertDependency(originalWork4, originalWork2);
600        insertDependency(originalWork3, originalWork2);
601        insertDependency(originalWork2, originalWork1);
602
603        List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
604        assertThat(workSpecIds,
605                containsInAnyOrder(
606                        originalWork1.getId(),
607                        originalWork2.getId(),
608                        originalWork3.getId(),
609                        originalWork4.getId()));
610
611        WorkRequest appendWork1 = new WorkRequest.Builder(TestWorker.class).build();
612        WorkRequest appendWork2 = new WorkRequest.Builder(TestWorker.class).build();
613        mWorkManagerImpl
614                .beginUniqueWork(testName, APPEND, appendWork1)
615                .then(appendWork2)
616                .blocking()
617                .enqueueBlocking();
618
619        workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
620        assertThat(workSpecIds,
621                containsInAnyOrder(
622                        originalWork1.getId(),
623                        originalWork2.getId(),
624                        originalWork3.getId(),
625                        originalWork4.getId(),
626                        appendWork1.getId(),
627                        appendWork2.getId()));
628
629        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
630        assertThat(workSpecDao.getWorkSpec(originalWork1.getId()), is(not(nullValue())));
631        assertThat(workSpecDao.getWorkSpec(originalWork2.getId()), is(not(nullValue())));
632        assertThat(workSpecDao.getWorkSpec(originalWork3.getId()), is(not(nullValue())));
633        assertThat(workSpecDao.getWorkSpec(originalWork4.getId()), is(not(nullValue())));
634        assertThat(workSpecDao.getState(appendWork1.getId()), is(BLOCKED));
635        assertThat(workSpecDao.getState(appendWork2.getId()), is(BLOCKED));
636
637        DependencyDao dependencyDao = mDatabase.dependencyDao();
638        assertThat(dependencyDao.getPrerequisites(appendWork1.getId()),
639                containsInAnyOrder(originalWork3.getId(), originalWork4.getId()));
640        assertThat(dependencyDao.getPrerequisites(appendWork2.getId()),
641                containsInAnyOrder(appendWork1.getId()));
642    }
643
644    @Test
645    @SmallTest
646    public void testBeginWithName_insertsExistingWorkWhenNothingToAppendTo() {
647        final String testName = "myname";
648
649        WorkRequest appendWork1 = new WorkRequest.Builder(TestWorker.class).build();
650        WorkRequest appendWork2 = new WorkRequest.Builder(TestWorker.class).build();
651        mWorkManagerImpl
652                .beginUniqueWork(testName, APPEND, appendWork1)
653                .then(appendWork2)
654                .blocking()
655                .enqueueBlocking();
656
657        List<String> workSpecIds = mDatabase.workNameDao().getWorkSpecIdsWithName(testName);
658        assertThat(workSpecIds,
659                containsInAnyOrder(appendWork1.getId(), appendWork2.getId()));
660    }
661
662    @Test
663    @SmallTest
664    public void testGetStatusByIdSync() {
665        WorkRequest work = new WorkRequest.Builder(TestWorker.class)
666                .withInitialState(SUCCEEDED)
667                .build();
668        insertWorkSpecAndTags(work);
669
670        WorkStatus workStatus = mWorkManagerImpl.getStatusByIdBlocking(work.getId());
671        assertThat(workStatus.getId(), is(work.getId()));
672        assertThat(workStatus.getState(), is(SUCCEEDED));
673    }
674
675    @Test
676    @SmallTest
677    public void testGetStatusByIdSync_returnsNullIfNotInDatabase() {
678        WorkStatus workStatus = mWorkManagerImpl.getStatusByIdBlocking("dummy");
679        assertThat(workStatus, is(nullValue()));
680    }
681
682    @Test
683    @SmallTest
684    @SuppressWarnings("unchecked")
685    public void testGetStatusesById() {
686        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class).build();
687        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).build();
688        insertWorkSpecAndTags(work0);
689        insertWorkSpecAndTags(work1);
690
691        Observer<List<WorkStatus>> mockObserver = mock(Observer.class);
692
693        TestLifecycleOwner testLifecycleOwner = new TestLifecycleOwner();
694        LiveData<List<WorkStatus>> liveData =
695                mWorkManagerImpl.getStatusesById(Arrays.asList(work0.getId(), work1.getId()));
696        liveData.observe(testLifecycleOwner, mockObserver);
697
698        ArgumentCaptor<List<WorkStatus>> captor = ArgumentCaptor.forClass(List.class);
699        verify(mockObserver).onChanged(captor.capture());
700        assertThat(captor.getValue(), is(not(nullValue())));
701        assertThat(captor.getValue().size(), is(2));
702
703        WorkStatus workStatus0 = new WorkStatus(
704                work0.getId(),
705                ENQUEUED,
706                Data.EMPTY,
707                Collections.<String>emptyList());
708        WorkStatus workStatus1 = new WorkStatus(
709                work1.getId(),
710                ENQUEUED,
711                Data.EMPTY,
712                Collections.<String>emptyList());
713        assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
714
715        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
716        workSpecDao.setState(RUNNING, work0.getId());
717
718        verify(mockObserver, times(2)).onChanged(captor.capture());
719        assertThat(captor.getValue(), is(not(nullValue())));
720        assertThat(captor.getValue().size(), is(2));
721
722        workStatus0 = new WorkStatus(
723                work0.getId(),
724                RUNNING,
725                Data.EMPTY,
726                Collections.<String>emptyList());
727        assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
728
729        clearInvocations(mockObserver);
730        workSpecDao.setState(RUNNING, work1.getId());
731
732        verify(mockObserver).onChanged(captor.capture());
733        assertThat(captor.getValue(), is(not(nullValue())));
734        assertThat(captor.getValue().size(), is(2));
735
736        workStatus1 = new WorkStatus(
737                work1.getId(),
738                RUNNING,
739                Data.EMPTY,
740                Collections.<String>emptyList());
741        assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
742
743        liveData.removeObservers(testLifecycleOwner);
744    }
745
746    @Test
747    @SmallTest
748    public void testGetStatusesByTagSync() {
749        final String firstTag = "first_tag";
750        final String secondTag = "second_tag";
751
752        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class)
753                .addTag(firstTag)
754                .addTag(secondTag)
755                .withInitialState(RUNNING)
756                .build();
757        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class)
758                .addTag(firstTag)
759                .withInitialState(BLOCKED)
760                .build();
761        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class)
762                .addTag(secondTag)
763                .withInitialState(SUCCEEDED)
764                .build();
765        insertWorkSpecAndTags(work0);
766        insertWorkSpecAndTags(work1);
767        insertWorkSpecAndTags(work2);
768
769        WorkStatus workStatus0 = new WorkStatus(
770                work0.getId(),
771                RUNNING,
772                Data.EMPTY,
773                Arrays.asList(firstTag, secondTag));
774        WorkStatus workStatus1 = new WorkStatus(
775                work1.getId(),
776                BLOCKED,
777                Data.EMPTY,
778                Collections.singletonList(firstTag));
779        WorkStatus workStatus2 = new WorkStatus(
780                work2.getId(),
781                SUCCEEDED,
782                Data.EMPTY,
783                Collections.singletonList(secondTag));
784
785        List<WorkStatus> workStatuses = mWorkManagerImpl.getStatusesByTagBlocking(firstTag);
786        assertThat(workStatuses, containsInAnyOrder(workStatus0, workStatus1));
787
788        workStatuses = mWorkManagerImpl.getStatusesByTagBlocking(secondTag);
789        assertThat(workStatuses, containsInAnyOrder(workStatus0, workStatus2));
790
791        workStatuses = mWorkManagerImpl.getStatusesByTagBlocking("dummy");
792        assertThat(workStatuses.size(), is(0));
793    }
794
795    @Test
796    @SmallTest
797    @SuppressWarnings("unchecked")
798    public void testGetStatusesByTag() {
799        final String firstTag = "first_tag";
800        final String secondTag = "second_tag";
801        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
802
803        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class)
804                .addTag(firstTag)
805                .addTag(secondTag)
806                .withInitialState(RUNNING)
807                .build();
808        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class)
809                .addTag(firstTag)
810                .withInitialState(BLOCKED)
811                .build();
812        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class)
813                .addTag(secondTag)
814                .withInitialState(SUCCEEDED)
815                .build();
816        insertWorkSpecAndTags(work0);
817        insertWorkSpecAndTags(work1);
818        insertWorkSpecAndTags(work2);
819
820        Observer<List<WorkStatus>> mockObserver = mock(Observer.class);
821
822        TestLifecycleOwner testLifecycleOwner = new TestLifecycleOwner();
823        LiveData<List<WorkStatus>> liveData = mWorkManagerImpl.getStatusesByTag(firstTag);
824        liveData.observe(testLifecycleOwner, mockObserver);
825
826        ArgumentCaptor<List<WorkStatus>> captor = ArgumentCaptor.forClass(List.class);
827        verify(mockObserver).onChanged(captor.capture());
828        assertThat(captor.getValue(), is(not(nullValue())));
829        assertThat(captor.getValue().size(), is(2));
830
831        WorkStatus workStatus0 = new WorkStatus(
832                work0.getId(),
833                RUNNING,
834                Data.EMPTY,
835                Arrays.asList(firstTag, secondTag));
836        WorkStatus workStatus1 = new WorkStatus(
837                work1.getId(),
838                BLOCKED,
839                Data.EMPTY,
840                Collections.singletonList(firstTag));
841        assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
842
843        workSpecDao.setState(ENQUEUED, work0.getId());
844
845        verify(mockObserver, times(2)).onChanged(captor.capture());
846        assertThat(captor.getValue(), is(not(nullValue())));
847        assertThat(captor.getValue().size(), is(2));
848
849        workStatus0 = new WorkStatus(
850                work0.getId(),
851                ENQUEUED,
852                Data.EMPTY,
853                Arrays.asList(firstTag, secondTag));
854        assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1));
855
856        liveData.removeObservers(testLifecycleOwner);
857    }
858
859    @Test
860    @SmallTest
861    public void getStatusByNameSync() {
862        final String testName = "myname";
863
864        WorkRequest work0 = new WorkRequest.Builder(InfiniteTestWorker.class)
865                .withInitialState(RUNNING)
866                .build();
867        WorkRequest work1 = new WorkRequest.Builder(InfiniteTestWorker.class)
868                .withInitialState(BLOCKED)
869                .build();
870        WorkRequest work2 = new WorkRequest.Builder(InfiniteTestWorker.class)
871                .withInitialState(BLOCKED)
872                .build();
873        insertNamedWorks(testName, work0, work1, work2);
874        insertDependency(work1, work0);
875        insertDependency(work2, work1);
876
877        WorkStatus workStatus0 = new WorkStatus(
878                work0.getId(),
879                RUNNING,
880                Data.EMPTY,
881                Collections.<String>emptyList());
882        WorkStatus workStatus1 = new WorkStatus(
883                work1.getId(),
884                BLOCKED,
885                Data.EMPTY,
886                Collections.<String>emptyList());
887        WorkStatus workStatus2 = new WorkStatus(
888                work2.getId(),
889                BLOCKED,
890                Data.EMPTY,
891                Collections.<String>emptyList());
892
893        List<WorkStatus> workStatuses = mWorkManagerImpl.getStatusesForUniqueWorkBlocking(testName);
894        assertThat(workStatuses, containsInAnyOrder(workStatus0, workStatus1, workStatus2));
895
896        workStatuses = mWorkManagerImpl.getStatusesForUniqueWorkBlocking("dummy");
897        assertThat(workStatuses.size(), is(0));
898    }
899
900    @Test
901    @SmallTest
902    @SuppressWarnings("unchecked")
903    public void testGetStatusesByName() {
904        final String testName = "myname";
905        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
906
907        WorkRequest work0 = new WorkRequest.Builder(InfiniteTestWorker.class)
908                .withInitialState(RUNNING)
909                .build();
910        WorkRequest work1 = new WorkRequest.Builder(InfiniteTestWorker.class)
911                .withInitialState(BLOCKED)
912                .build();
913        WorkRequest work2 = new WorkRequest.Builder(InfiniteTestWorker.class)
914                .withInitialState(BLOCKED)
915                .build();
916        insertNamedWorks(testName, work0, work1, work2);
917        insertDependency(work1, work0);
918        insertDependency(work2, work1);
919
920        Observer<List<WorkStatus>> mockObserver = mock(Observer.class);
921
922        TestLifecycleOwner testLifecycleOwner = new TestLifecycleOwner();
923        LiveData<List<WorkStatus>> liveData = mWorkManagerImpl.getStatusesForUniqueWork(testName);
924        liveData.observe(testLifecycleOwner, mockObserver);
925
926        ArgumentCaptor<List<WorkStatus>> captor = ArgumentCaptor.forClass(List.class);
927        verify(mockObserver).onChanged(captor.capture());
928        assertThat(captor.getValue(), is(not(nullValue())));
929        assertThat(captor.getValue().size(), is(3));
930
931        WorkStatus workStatus0 = new WorkStatus(
932                work0.getId(),
933                RUNNING,
934                Data.EMPTY,
935                Collections.<String>emptyList());
936        WorkStatus workStatus1 = new WorkStatus(
937                work1.getId(),
938                BLOCKED,
939                Data.EMPTY,
940                Collections.<String>emptyList());
941        WorkStatus workStatus2 = new WorkStatus(
942                work2.getId(),
943                BLOCKED,
944                Data.EMPTY,
945                Collections.<String>emptyList());
946        assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1, workStatus2));
947
948        workSpecDao.setState(ENQUEUED, work0.getId());
949
950        verify(mockObserver, times(2)).onChanged(captor.capture());
951        assertThat(captor.getValue(), is(not(nullValue())));
952        assertThat(captor.getValue().size(), is(3));
953
954        workStatus0 = new WorkStatus(
955                work0.getId(),
956                ENQUEUED,
957                Data.EMPTY,
958                Collections.<String>emptyList());
959        assertThat(captor.getValue(), containsInAnyOrder(workStatus0, workStatus1, workStatus2));
960
961        liveData.removeObservers(testLifecycleOwner);
962    }
963
964    @Test
965    @SmallTest
966    public void testCancelWorkById() {
967        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
968
969        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class).build();
970        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).build();
971        insertWorkSpecAndTags(work0);
972        insertWorkSpecAndTags(work1);
973
974        mWorkManagerImpl.blocking().cancelWorkByIdBlocking(work0.getId());
975        assertThat(workSpecDao.getState(work0.getId()), is(CANCELLED));
976        assertThat(workSpecDao.getState(work1.getId()), is(not(CANCELLED)));
977    }
978
979    @Test
980    @SmallTest
981    public void testCancelWorkById_cancelsDependentWork() {
982        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
983
984        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class).build();
985        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class)
986                .withInitialState(BLOCKED)
987                .build();
988        insertWorkSpecAndTags(work0);
989        insertWorkSpecAndTags(work1);
990        insertDependency(work1, work0);
991
992        mWorkManagerImpl.blocking().cancelWorkByIdBlocking(work0.getId());
993
994        assertThat(workSpecDao.getState(work0.getId()), is(CANCELLED));
995        assertThat(workSpecDao.getState(work1.getId()), is(CANCELLED));
996    }
997
998    @Test
999    @SmallTest
1000    public void testCancelWorkById_cancelsUnfinishedWorkOnly() {
1001        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1002
1003        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class)
1004                .withInitialState(SUCCEEDED)
1005                .build();
1006        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class)
1007                .withInitialState(ENQUEUED)
1008                .build();
1009        insertWorkSpecAndTags(work0);
1010        insertWorkSpecAndTags(work1);
1011        insertDependency(work1, work0);
1012
1013        mWorkManagerImpl.blocking().cancelWorkByIdBlocking(work0.getId());
1014
1015        assertThat(workSpecDao.getState(work0.getId()), is(SUCCEEDED));
1016        assertThat(workSpecDao.getState(work1.getId()), is(CANCELLED));
1017    }
1018
1019    @Test
1020    @SmallTest
1021    public void testCancelAllWorkByTag() {
1022        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1023
1024        final String tagToClear = "tag_to_clear";
1025        final String tagNotToClear = "tag_not_to_clear";
1026
1027        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class).addTag(tagToClear).build();
1028        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).addTag(tagToClear).build();
1029        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class).addTag(tagNotToClear).build();
1030        WorkRequest work3 = new WorkRequest.Builder(TestWorker.class).addTag(tagNotToClear).build();
1031        insertWorkSpecAndTags(work0);
1032        insertWorkSpecAndTags(work1);
1033        insertWorkSpecAndTags(work2);
1034        insertWorkSpecAndTags(work3);
1035
1036        mWorkManagerImpl.blocking().cancelAllWorkByTagBlocking(tagToClear);
1037
1038        assertThat(workSpecDao.getState(work0.getId()), is(CANCELLED));
1039        assertThat(workSpecDao.getState(work1.getId()), is(CANCELLED));
1040        assertThat(workSpecDao.getState(work2.getId()), is(not(CANCELLED)));
1041        assertThat(workSpecDao.getState(work3.getId()), is(not(CANCELLED)));
1042    }
1043
1044    @Test
1045    @SmallTest
1046    public void testCancelAllWorkByTag_cancelsDependentWork() {
1047        String tag = "tag";
1048
1049        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class).addTag(tag).build();
1050        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class).build();
1051        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class).build();
1052        WorkRequest work3 = new WorkRequest.Builder(TestWorker.class).build();
1053        WorkRequest work4 = new WorkRequest.Builder(TestWorker.class).build();
1054
1055        insertWorkSpecAndTags(work0);
1056        insertWorkSpecAndTags(work1);
1057        insertWorkSpecAndTags(work2);
1058        insertWorkSpecAndTags(work3);
1059        insertWorkSpecAndTags(work4);
1060
1061        // Dependency graph:
1062        //                             0
1063        //                             |
1064        //                       |------------|
1065        //            3          1            4
1066        //            |          |
1067        //            ------------
1068        //                 |
1069        //                 2
1070
1071        insertDependency(work2, work1);
1072        insertDependency(work2, work3);
1073        insertDependency(work1, work0);
1074        insertDependency(work4, work0);
1075
1076        mWorkManagerImpl.blocking().cancelAllWorkByTagBlocking(tag);
1077
1078        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1079        assertThat(workSpecDao.getState(work0.getId()), is(CANCELLED));
1080        assertThat(workSpecDao.getState(work1.getId()), is(CANCELLED));
1081        assertThat(workSpecDao.getState(work2.getId()), is(CANCELLED));
1082        assertThat(workSpecDao.getState(work3.getId()), is(not(CANCELLED)));
1083        assertThat(workSpecDao.getState(work4.getId()), is(CANCELLED));
1084    }
1085
1086    @Test
1087    @SmallTest
1088    public void testCancelWorkByName() {
1089        final String testName = "myname";
1090
1091        WorkRequest work0 = new WorkRequest.Builder(InfiniteTestWorker.class).build();
1092        WorkRequest work1 = new WorkRequest.Builder(InfiniteTestWorker.class).build();
1093        insertNamedWorks(testName, work0, work1);
1094
1095        mWorkManagerImpl.blocking().cancelUniqueWorkBlocking(testName);
1096
1097        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1098        assertThat(workSpecDao.getState(work0.getId()), is(CANCELLED));
1099        assertThat(workSpecDao.getState(work1.getId()), is(CANCELLED));
1100    }
1101
1102    @Test
1103    @SmallTest
1104    public void testCancelWorkByName_ignoresFinishedWork() {
1105        final String testName = "myname";
1106
1107        WorkRequest work0 = new WorkRequest.Builder(InfiniteTestWorker.class)
1108                .withInitialState(SUCCEEDED)
1109                .build();
1110        WorkRequest work1 = new WorkRequest.Builder(InfiniteTestWorker.class).build();
1111        insertNamedWorks(testName, work0, work1);
1112
1113        mWorkManagerImpl.blocking().cancelUniqueWorkBlocking(testName);
1114
1115        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1116        assertThat(workSpecDao.getState(work0.getId()), is(SUCCEEDED));
1117        assertThat(workSpecDao.getState(work1.getId()), is(CANCELLED));
1118    }
1119
1120    @Test
1121    @SmallTest
1122    public void testSynchronousCancelAndGetStatus() {
1123        WorkRequest work = new WorkRequest.Builder(TestWorker.class).build();
1124        insertWorkSpecAndTags(work);
1125
1126        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1127        assertThat(workSpecDao.getState(work.getId()), is(ENQUEUED));
1128
1129        mWorkManagerImpl.blocking().cancelWorkByIdBlocking(work.getId());
1130        assertThat(mWorkManagerImpl.getStatusByIdBlocking(work.getId()).getState(), is(CANCELLED));
1131    }
1132
1133    @Test
1134    @SmallTest
1135    public void testGenerateCleanupCallback_resetsRunningWorkStatuses() {
1136        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1137
1138        WorkRequest work = new WorkRequest.Builder(TestWorker.class)
1139                .withInitialState(RUNNING)
1140                .build();
1141        workSpecDao.insertWorkSpec(work.getWorkSpec());
1142
1143        assertThat(workSpecDao.getState(work.getId()), is(RUNNING));
1144
1145        SupportSQLiteOpenHelper openHelper = mDatabase.getOpenHelper();
1146        SupportSQLiteDatabase db = openHelper.getWritableDatabase();
1147        WorkDatabase.generateCleanupCallback().onOpen(db);
1148
1149        assertThat(workSpecDao.getState(work.getId()), is(ENQUEUED));
1150    }
1151
1152    @Test
1153    @SmallTest
1154    public void testGenerateCleanupCallback_deletesOldFinishedWork() {
1155        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class)
1156                .withInitialState(SUCCEEDED)
1157                .withPeriodStartTime(WorkDatabase.getPruneDate() - 1L, TimeUnit.MILLISECONDS)
1158                .build();
1159        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class)
1160                .withPeriodStartTime(Long.MAX_VALUE, TimeUnit.MILLISECONDS)
1161                .build();
1162
1163        insertWorkSpecAndTags(work1);
1164        insertWorkSpecAndTags(work2);
1165
1166        SupportSQLiteOpenHelper openHelper = mDatabase.getOpenHelper();
1167        SupportSQLiteDatabase db = openHelper.getWritableDatabase();
1168        WorkDatabase.generateCleanupCallback().onOpen(db);
1169
1170        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1171        assertThat(workSpecDao.getWorkSpec(work1.getId()), is(nullValue()));
1172        assertThat(workSpecDao.getWorkSpec(work2.getId()), is(not(nullValue())));
1173    }
1174
1175    @Test
1176    @SmallTest
1177    public void testGenerateCleanupCallback_doesNotDeleteOldFinishedWorkWithActiveDependents() {
1178        WorkRequest work0 = new WorkRequest.Builder(TestWorker.class)
1179                .withInitialState(SUCCEEDED)
1180                .withPeriodStartTime(WorkDatabase.getPruneDate() - 1L, TimeUnit.MILLISECONDS)
1181                .build();
1182        WorkRequest work1 = new WorkRequest.Builder(TestWorker.class)
1183                .withInitialState(SUCCEEDED)
1184                .withPeriodStartTime(WorkDatabase.getPruneDate() - 1L, TimeUnit.MILLISECONDS)
1185                .build();
1186        WorkRequest work2 = new WorkRequest.Builder(TestWorker.class)
1187                .withInitialState(ENQUEUED)
1188                .withPeriodStartTime(WorkDatabase.getPruneDate() - 1L, TimeUnit.MILLISECONDS)
1189                .build();
1190
1191        insertWorkSpecAndTags(work0);
1192        insertWorkSpecAndTags(work1);
1193        insertWorkSpecAndTags(work2);
1194
1195        // Dependency graph: 0 -> 1 -> 2
1196        insertDependency(work1, work0);
1197        insertDependency(work2, work1);
1198
1199        SupportSQLiteOpenHelper openHelper = mDatabase.getOpenHelper();
1200        SupportSQLiteDatabase db = openHelper.getWritableDatabase();
1201        WorkDatabase.generateCleanupCallback().onOpen(db);
1202
1203        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
1204        assertThat(workSpecDao.getWorkSpec(work0.getId()), is(nullValue()));
1205        assertThat(workSpecDao.getWorkSpec(work1.getId()), is(not(nullValue())));
1206        assertThat(workSpecDao.getWorkSpec(work2.getId()), is(not(nullValue())));
1207    }
1208
1209    @Test
1210    @SmallTest
1211    @SdkSuppress(maxSdkVersion = 22)
1212    public void testEnqueueApi22OrLower_withBatteryNotLowConstraint_expectsOriginalWorker() {
1213        WorkRequest work = new WorkRequest.Builder(TestWorker.class)
1214                .withConstraints(new Constraints.Builder()
1215                        .setRequiresBatteryNotLow(true)
1216                        .build())
1217                .build();
1218        mWorkManagerImpl.beginWith(work).blocking().enqueueBlocking();
1219
1220        WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getId());
1221        assertThat(workSpec.workerClassName, is(TestWorker.class.getName()));
1222    }
1223
1224    @Test
1225    @SmallTest
1226    @SdkSuppress(maxSdkVersion = 22)
1227    public void testEnqueueApi22OrLower_withStorageNotLowConstraint_expectsOriginalWorker() {
1228        WorkRequest work = new WorkRequest.Builder(TestWorker.class)
1229                .withConstraints(new Constraints.Builder()
1230                        .setRequiresStorageNotLow(true)
1231                        .build())
1232                .build();
1233        mWorkManagerImpl.beginWith(work).blocking().enqueueBlocking();
1234
1235        WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getId());
1236        assertThat(workSpec.workerClassName, is(TestWorker.class.getName()));
1237    }
1238
1239    @Test
1240    @SmallTest
1241    @SdkSuppress(minSdkVersion = 23, maxSdkVersion = 25)
1242    public void testEnqueueApi23To25_withBatteryNotLowConstraint_expectsConstraintTrackingWorker() {
1243        WorkRequest work = new WorkRequest.Builder(TestWorker.class)
1244                .withConstraints(new Constraints.Builder()
1245                .setRequiresBatteryNotLow(true)
1246                .build())
1247                .build();
1248        mWorkManagerImpl.beginWith(work).blocking().enqueueBlocking();
1249
1250        WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getId());
1251        assertThat(workSpec.workerClassName, is(ConstraintTrackingWorker.class.getName()));
1252        assertThat(workSpec.input.getString(
1253                ConstraintTrackingWorker.ARGUMENT_CLASS_NAME, null),
1254                is(TestWorker.class.getName()));
1255    }
1256
1257    @Test
1258    @SmallTest
1259    @SdkSuppress(minSdkVersion = 23, maxSdkVersion = 25)
1260    public void testEnqueueApi23To25_withStorageNotLowConstraint_expectsConstraintTrackingWorker() {
1261        WorkRequest work = new WorkRequest.Builder(TestWorker.class)
1262                .withConstraints(new Constraints.Builder()
1263                        .setRequiresStorageNotLow(true)
1264                        .build())
1265                .build();
1266        mWorkManagerImpl.beginWith(work).blocking().enqueueBlocking();
1267
1268        WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getId());
1269        assertThat(workSpec.workerClassName, is(ConstraintTrackingWorker.class.getName()));
1270        assertThat(workSpec.input.getString(
1271                ConstraintTrackingWorker.ARGUMENT_CLASS_NAME, null),
1272                is(TestWorker.class.getName()));
1273    }
1274
1275    @Test
1276    @SmallTest
1277    @SdkSuppress(minSdkVersion = 26)
1278    public void testEnqueueApi26OrHigher_withBatteryNotLowConstraint_expectsOriginalWorker() {
1279        WorkRequest work = new WorkRequest.Builder(TestWorker.class)
1280                .withConstraints(new Constraints.Builder()
1281                        .setRequiresBatteryNotLow(true)
1282                        .build())
1283                .build();
1284        mWorkManagerImpl.beginWith(work).blocking().enqueueBlocking();
1285
1286        WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getId());
1287        assertThat(workSpec.workerClassName, is(TestWorker.class.getName()));
1288    }
1289
1290    @Test
1291    @SmallTest
1292    @SdkSuppress(minSdkVersion = 26)
1293    public void testEnqueueApi26OrHigher_withStorageNotLowConstraint_expectsOriginalWorker() {
1294        WorkRequest work = new WorkRequest.Builder(TestWorker.class)
1295                .withConstraints(new Constraints.Builder()
1296                        .setRequiresStorageNotLow(true)
1297                        .build())
1298                .build();
1299        mWorkManagerImpl.beginWith(work).blocking().enqueueBlocking();
1300
1301        WorkSpec workSpec = mDatabase.workSpecDao().getWorkSpec(work.getId());
1302        assertThat(workSpec.workerClassName, is(TestWorker.class.getName()));
1303    }
1304
1305    private void insertWorkSpecAndTags(WorkRequest work) {
1306        mDatabase.workSpecDao().insertWorkSpec(work.getWorkSpec());
1307        for (String tag : work.getTags()) {
1308            mDatabase.workTagDao().insert(new WorkTag(tag, work.getId()));
1309        }
1310    }
1311
1312    private void insertNamedWorks(String name, WorkRequest... works) {
1313        for (WorkRequest work : works) {
1314            insertWorkSpecAndTags(work);
1315            mDatabase.workNameDao().insert(new WorkName(name, work.getId()));
1316        }
1317    }
1318
1319    private void insertDependency(WorkRequest work, WorkRequest prerequisiteWork) {
1320        mDatabase.dependencyDao().insertDependency(
1321                new Dependency(work.getId(), prerequisiteWork.getId()));
1322    }
1323}
1324