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