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