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