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