LifecycleRegistryTest.java revision bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8
1/* 2 * Copyright (C) 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.lifecycle; 18 19import static androidx.lifecycle.Lifecycle.Event.ON_CREATE; 20import static androidx.lifecycle.Lifecycle.Event.ON_DESTROY; 21import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE; 22import static androidx.lifecycle.Lifecycle.Event.ON_RESUME; 23import static androidx.lifecycle.Lifecycle.Event.ON_START; 24import static androidx.lifecycle.Lifecycle.Event.ON_STOP; 25 26import static org.hamcrest.CoreMatchers.is; 27import static org.hamcrest.MatcherAssert.assertThat; 28import static org.mockito.Mockito.inOrder; 29import static org.mockito.Mockito.mock; 30import static org.mockito.Mockito.never; 31import static org.mockito.Mockito.reset; 32import static org.mockito.Mockito.spy; 33import static org.mockito.Mockito.times; 34import static org.mockito.Mockito.verify; 35import static org.mockito.Mockito.when; 36 37import org.junit.Before; 38import org.junit.Test; 39import org.junit.runner.RunWith; 40import org.junit.runners.JUnit4; 41import org.mockito.InOrder; 42 43@RunWith(JUnit4.class) 44public class LifecycleRegistryTest { 45 private LifecycleOwner mLifecycleOwner; 46 private Lifecycle mLifecycle; 47 private LifecycleRegistry mRegistry; 48 49 @Before 50 public void init() { 51 mLifecycleOwner = mock(LifecycleOwner.class); 52 mLifecycle = mock(Lifecycle.class); 53 when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycle); 54 mRegistry = new LifecycleRegistry(mLifecycleOwner); 55 } 56 57 @Test 58 public void addRemove() { 59 LifecycleObserver observer = mock(LifecycleObserver.class); 60 mRegistry.addObserver(observer); 61 assertThat(mRegistry.getObserverCount(), is(1)); 62 mRegistry.removeObserver(observer); 63 assertThat(mRegistry.getObserverCount(), is(0)); 64 } 65 66 @Test 67 public void addGenericAndObserve() { 68 GenericLifecycleObserver generic = mock(GenericLifecycleObserver.class); 69 mRegistry.addObserver(generic); 70 dispatchEvent(ON_CREATE); 71 verify(generic).onStateChanged(mLifecycleOwner, ON_CREATE); 72 reset(generic); 73 dispatchEvent(ON_CREATE); 74 verify(generic, never()).onStateChanged(mLifecycleOwner, ON_CREATE); 75 } 76 77 @Test 78 public void addRegularClass() { 79 TestObserver testObserver = mock(TestObserver.class); 80 mRegistry.addObserver(testObserver); 81 dispatchEvent(ON_START); 82 verify(testObserver, never()).onStop(); 83 dispatchEvent(ON_STOP); 84 verify(testObserver).onStop(); 85 } 86 87 @Test 88 public void add2RemoveOne() { 89 TestObserver observer1 = mock(TestObserver.class); 90 TestObserver observer2 = mock(TestObserver.class); 91 TestObserver observer3 = mock(TestObserver.class); 92 mRegistry.addObserver(observer1); 93 mRegistry.addObserver(observer2); 94 mRegistry.addObserver(observer3); 95 96 dispatchEvent(ON_CREATE); 97 98 verify(observer1).onCreate(); 99 verify(observer2).onCreate(); 100 verify(observer3).onCreate(); 101 reset(observer1, observer2, observer3); 102 103 mRegistry.removeObserver(observer2); 104 dispatchEvent(ON_START); 105 106 verify(observer1).onStart(); 107 verify(observer2, never()).onStart(); 108 verify(observer3).onStart(); 109 } 110 111 @Test 112 public void removeWhileTraversing() { 113 final TestObserver observer2 = mock(TestObserver.class); 114 TestObserver observer1 = spy(new TestObserver() { 115 @Override 116 public void onCreate() { 117 mRegistry.removeObserver(observer2); 118 } 119 }); 120 mRegistry.addObserver(observer1); 121 mRegistry.addObserver(observer2); 122 dispatchEvent(ON_CREATE); 123 verify(observer2, never()).onCreate(); 124 verify(observer1).onCreate(); 125 } 126 127 @Test 128 public void constructionOrder() { 129 fullyInitializeRegistry(); 130 final TestObserver observer = mock(TestObserver.class); 131 mRegistry.addObserver(observer); 132 InOrder inOrder = inOrder(observer); 133 inOrder.verify(observer).onCreate(); 134 inOrder.verify(observer).onStart(); 135 inOrder.verify(observer).onResume(); 136 } 137 138 @Test 139 public void constructionDestruction1() { 140 fullyInitializeRegistry(); 141 final TestObserver observer = spy(new TestObserver() { 142 @Override 143 void onStart() { 144 dispatchEvent(ON_PAUSE); 145 } 146 }); 147 mRegistry.addObserver(observer); 148 InOrder constructionOrder = inOrder(observer); 149 constructionOrder.verify(observer).onCreate(); 150 constructionOrder.verify(observer).onStart(); 151 constructionOrder.verify(observer, never()).onResume(); 152 } 153 154 @Test 155 public void constructionDestruction2() { 156 fullyInitializeRegistry(); 157 final TestObserver observer = spy(new TestObserver() { 158 @Override 159 void onStart() { 160 dispatchEvent(ON_PAUSE); 161 dispatchEvent(ON_STOP); 162 dispatchEvent(ON_DESTROY); 163 } 164 }); 165 mRegistry.addObserver(observer); 166 InOrder orderVerifier = inOrder(observer); 167 orderVerifier.verify(observer).onCreate(); 168 orderVerifier.verify(observer).onStart(); 169 orderVerifier.verify(observer).onStop(); 170 orderVerifier.verify(observer).onDestroy(); 171 orderVerifier.verify(observer, never()).onResume(); 172 } 173 174 @Test 175 public void twoObserversChangingState() { 176 final TestObserver observer1 = spy(new TestObserver() { 177 @Override 178 void onCreate() { 179 dispatchEvent(ON_START); 180 } 181 }); 182 final TestObserver observer2 = mock(TestObserver.class); 183 mRegistry.addObserver(observer1); 184 mRegistry.addObserver(observer2); 185 dispatchEvent(ON_CREATE); 186 verify(observer1, times(1)).onCreate(); 187 verify(observer2, times(1)).onCreate(); 188 verify(observer1, times(1)).onStart(); 189 verify(observer2, times(1)).onStart(); 190 } 191 192 @Test 193 public void addDuringTraversing() { 194 final TestObserver observer3 = mock(TestObserver.class); 195 final TestObserver observer1 = spy(new TestObserver() { 196 @Override 197 public void onStart() { 198 mRegistry.addObserver(observer3); 199 } 200 }); 201 final TestObserver observer2 = mock(TestObserver.class); 202 203 mRegistry.addObserver(observer1); 204 mRegistry.addObserver(observer2); 205 206 dispatchEvent(ON_CREATE); 207 dispatchEvent(ON_START); 208 209 InOrder inOrder = inOrder(observer1, observer2, observer3); 210 inOrder.verify(observer1).onCreate(); 211 inOrder.verify(observer2).onCreate(); 212 inOrder.verify(observer1).onStart(); 213 inOrder.verify(observer3).onCreate(); 214 inOrder.verify(observer2).onStart(); 215 inOrder.verify(observer3).onStart(); 216 } 217 218 @Test 219 public void addDuringAddition() { 220 final TestObserver observer3 = mock(TestObserver.class); 221 final TestObserver observer2 = spy(new TestObserver() { 222 @Override 223 public void onCreate() { 224 mRegistry.addObserver(observer3); 225 } 226 }); 227 228 final TestObserver observer1 = spy(new TestObserver() { 229 @Override 230 public void onResume() { 231 mRegistry.addObserver(observer2); 232 } 233 }); 234 235 mRegistry.addObserver(observer1); 236 237 dispatchEvent(ON_CREATE); 238 dispatchEvent(ON_START); 239 dispatchEvent(ON_RESUME); 240 241 InOrder inOrder = inOrder(observer1, observer2, observer3); 242 inOrder.verify(observer1).onCreate(); 243 inOrder.verify(observer1).onStart(); 244 inOrder.verify(observer1).onResume(); 245 inOrder.verify(observer2).onCreate(); 246 inOrder.verify(observer2).onStart(); 247 inOrder.verify(observer2).onResume(); 248 inOrder.verify(observer3).onCreate(); 249 inOrder.verify(observer3).onStart(); 250 inOrder.verify(observer3).onResume(); 251 } 252 253 @Test 254 public void subscribeToDead() { 255 dispatchEvent(ON_CREATE); 256 final TestObserver observer1 = mock(TestObserver.class); 257 mRegistry.addObserver(observer1); 258 verify(observer1).onCreate(); 259 dispatchEvent(ON_DESTROY); 260 verify(observer1).onDestroy(); 261 final TestObserver observer2 = mock(TestObserver.class); 262 mRegistry.addObserver(observer2); 263 verify(observer2, never()).onCreate(); 264 reset(observer1); 265 dispatchEvent(ON_CREATE); 266 verify(observer1).onCreate(); 267 verify(observer2).onCreate(); 268 } 269 270 @Test 271 public void downEvents() { 272 fullyInitializeRegistry(); 273 final TestObserver observer1 = mock(TestObserver.class); 274 final TestObserver observer2 = mock(TestObserver.class); 275 mRegistry.addObserver(observer1); 276 mRegistry.addObserver(observer2); 277 InOrder orderVerifier = inOrder(observer1, observer2); 278 dispatchEvent(ON_PAUSE); 279 orderVerifier.verify(observer2).onPause(); 280 orderVerifier.verify(observer1).onPause(); 281 dispatchEvent(ON_STOP); 282 orderVerifier.verify(observer2).onStop(); 283 orderVerifier.verify(observer1).onStop(); 284 dispatchEvent(ON_DESTROY); 285 orderVerifier.verify(observer2).onDestroy(); 286 orderVerifier.verify(observer1).onDestroy(); 287 } 288 289 @Test 290 public void downEventsAddition() { 291 dispatchEvent(ON_CREATE); 292 dispatchEvent(ON_START); 293 final TestObserver observer1 = mock(TestObserver.class); 294 final TestObserver observer3 = mock(TestObserver.class); 295 final TestObserver observer2 = spy(new TestObserver() { 296 @Override 297 void onStop() { 298 mRegistry.addObserver(observer3); 299 } 300 }); 301 mRegistry.addObserver(observer1); 302 mRegistry.addObserver(observer2); 303 InOrder orderVerifier = inOrder(observer1, observer2, observer3); 304 dispatchEvent(ON_STOP); 305 orderVerifier.verify(observer2).onStop(); 306 orderVerifier.verify(observer3).onCreate(); 307 orderVerifier.verify(observer1).onStop(); 308 dispatchEvent(ON_DESTROY); 309 orderVerifier.verify(observer3).onDestroy(); 310 orderVerifier.verify(observer2).onDestroy(); 311 orderVerifier.verify(observer1).onDestroy(); 312 } 313 314 @Test 315 public void downEventsRemoveAll() { 316 fullyInitializeRegistry(); 317 final TestObserver observer1 = mock(TestObserver.class); 318 final TestObserver observer3 = mock(TestObserver.class); 319 final TestObserver observer2 = spy(new TestObserver() { 320 @Override 321 void onStop() { 322 mRegistry.removeObserver(observer3); 323 mRegistry.removeObserver(this); 324 mRegistry.removeObserver(observer1); 325 assertThat(mRegistry.getObserverCount(), is(0)); 326 } 327 }); 328 mRegistry.addObserver(observer1); 329 mRegistry.addObserver(observer2); 330 mRegistry.addObserver(observer3); 331 InOrder orderVerifier = inOrder(observer1, observer2, observer3); 332 dispatchEvent(ON_PAUSE); 333 orderVerifier.verify(observer3).onPause(); 334 orderVerifier.verify(observer2).onPause(); 335 orderVerifier.verify(observer1).onPause(); 336 dispatchEvent(ON_STOP); 337 orderVerifier.verify(observer3).onStop(); 338 orderVerifier.verify(observer2).onStop(); 339 orderVerifier.verify(observer1, never()).onStop(); 340 dispatchEvent(ON_PAUSE); 341 orderVerifier.verify(observer3, never()).onPause(); 342 orderVerifier.verify(observer2, never()).onPause(); 343 orderVerifier.verify(observer1, never()).onPause(); 344 } 345 346 @Test 347 public void deadParentInAddition() { 348 fullyInitializeRegistry(); 349 final TestObserver observer2 = mock(TestObserver.class); 350 final TestObserver observer3 = mock(TestObserver.class); 351 352 TestObserver observer1 = spy(new TestObserver() { 353 @Override 354 void onStart() { 355 mRegistry.removeObserver(this); 356 assertThat(mRegistry.getObserverCount(), is(0)); 357 mRegistry.addObserver(observer2); 358 mRegistry.addObserver(observer3); 359 } 360 }); 361 362 mRegistry.addObserver(observer1); 363 364 InOrder inOrder = inOrder(observer1, observer2, observer3); 365 inOrder.verify(observer1).onCreate(); 366 inOrder.verify(observer1).onStart(); 367 inOrder.verify(observer2).onCreate(); 368 inOrder.verify(observer3).onCreate(); 369 inOrder.verify(observer2).onStart(); 370 inOrder.verify(observer2).onResume(); 371 inOrder.verify(observer3).onStart(); 372 inOrder.verify(observer3).onResume(); 373 } 374 375 @Test 376 public void deadParentWhileTraversing() { 377 final TestObserver observer2 = mock(TestObserver.class); 378 final TestObserver observer3 = mock(TestObserver.class); 379 TestObserver observer1 = spy(new TestObserver() { 380 @Override 381 void onStart() { 382 mRegistry.removeObserver(this); 383 assertThat(mRegistry.getObserverCount(), is(0)); 384 mRegistry.addObserver(observer2); 385 mRegistry.addObserver(observer3); 386 } 387 }); 388 InOrder inOrder = inOrder(observer1, observer2, observer3); 389 mRegistry.addObserver(observer1); 390 dispatchEvent(ON_CREATE); 391 dispatchEvent(ON_START); 392 inOrder.verify(observer1).onCreate(); 393 inOrder.verify(observer1).onStart(); 394 inOrder.verify(observer2).onCreate(); 395 inOrder.verify(observer3).onCreate(); 396 inOrder.verify(observer2).onStart(); 397 inOrder.verify(observer3).onStart(); 398 } 399 400 @Test 401 public void removeCascade() { 402 final TestObserver observer3 = mock(TestObserver.class); 403 final TestObserver observer4 = mock(TestObserver.class); 404 405 final TestObserver observer2 = spy(new TestObserver() { 406 @Override 407 void onStart() { 408 mRegistry.removeObserver(this); 409 } 410 }); 411 412 TestObserver observer1 = spy(new TestObserver() { 413 @Override 414 void onResume() { 415 mRegistry.removeObserver(this); 416 mRegistry.addObserver(observer2); 417 mRegistry.addObserver(observer3); 418 mRegistry.addObserver(observer4); 419 } 420 }); 421 fullyInitializeRegistry(); 422 mRegistry.addObserver(observer1); 423 InOrder inOrder = inOrder(observer1, observer2, observer3, observer4); 424 inOrder.verify(observer1).onCreate(); 425 inOrder.verify(observer1).onStart(); 426 inOrder.verify(observer1).onResume(); 427 inOrder.verify(observer2).onCreate(); 428 inOrder.verify(observer2).onStart(); 429 inOrder.verify(observer3).onCreate(); 430 inOrder.verify(observer3).onStart(); 431 inOrder.verify(observer4).onCreate(); 432 inOrder.verify(observer4).onStart(); 433 inOrder.verify(observer3).onResume(); 434 inOrder.verify(observer4).onResume(); 435 } 436 437 @Test 438 public void changeStateDuringDescending() { 439 final TestObserver observer2 = mock(TestObserver.class); 440 final TestObserver observer1 = spy(new TestObserver() { 441 @Override 442 void onPause() { 443 // but tonight I bounce back 444 mRegistry.handleLifecycleEvent(ON_RESUME); 445 mRegistry.addObserver(observer2); 446 } 447 }); 448 fullyInitializeRegistry(); 449 mRegistry.addObserver(observer1); 450 mRegistry.handleLifecycleEvent(ON_PAUSE); 451 InOrder inOrder = inOrder(observer1, observer2); 452 inOrder.verify(observer1).onPause(); 453 inOrder.verify(observer2).onCreate(); 454 inOrder.verify(observer2).onStart(); 455 inOrder.verify(observer1).onResume(); 456 inOrder.verify(observer2).onResume(); 457 } 458 459 @Test 460 public void siblingLimitationCheck() { 461 fullyInitializeRegistry(); 462 final TestObserver observer2 = mock(TestObserver.class); 463 final TestObserver observer3 = mock(TestObserver.class); 464 final TestObserver observer1 = spy(new TestObserver() { 465 @Override 466 void onStart() { 467 mRegistry.addObserver(observer2); 468 } 469 470 @Override 471 void onResume() { 472 mRegistry.addObserver(observer3); 473 } 474 }); 475 mRegistry.addObserver(observer1); 476 InOrder inOrder = inOrder(observer1, observer2, observer3); 477 inOrder.verify(observer1).onCreate(); 478 inOrder.verify(observer1).onStart(); 479 inOrder.verify(observer2).onCreate(); 480 inOrder.verify(observer1).onResume(); 481 inOrder.verify(observer3).onCreate(); 482 inOrder.verify(observer2).onStart(); 483 inOrder.verify(observer2).onResume(); 484 inOrder.verify(observer3).onStart(); 485 inOrder.verify(observer3).onResume(); 486 } 487 488 @Test 489 public void siblingRemovalLimitationCheck1() { 490 fullyInitializeRegistry(); 491 final TestObserver observer2 = mock(TestObserver.class); 492 final TestObserver observer3 = mock(TestObserver.class); 493 final TestObserver observer4 = mock(TestObserver.class); 494 final TestObserver observer1 = spy(new TestObserver() { 495 @Override 496 void onStart() { 497 mRegistry.addObserver(observer2); 498 } 499 500 @Override 501 void onResume() { 502 mRegistry.removeObserver(observer2); 503 mRegistry.addObserver(observer3); 504 mRegistry.addObserver(observer4); 505 } 506 }); 507 mRegistry.addObserver(observer1); 508 InOrder inOrder = inOrder(observer1, observer2, observer3, observer4); 509 inOrder.verify(observer1).onCreate(); 510 inOrder.verify(observer1).onStart(); 511 inOrder.verify(observer2).onCreate(); 512 inOrder.verify(observer1).onResume(); 513 inOrder.verify(observer3).onCreate(); 514 inOrder.verify(observer3).onStart(); 515 inOrder.verify(observer4).onCreate(); 516 inOrder.verify(observer4).onStart(); 517 inOrder.verify(observer3).onResume(); 518 inOrder.verify(observer4).onResume(); 519 } 520 521 @Test 522 public void siblingRemovalLimitationCheck2() { 523 fullyInitializeRegistry(); 524 final TestObserver observer2 = mock(TestObserver.class); 525 final TestObserver observer3 = spy(new TestObserver() { 526 @Override 527 void onCreate() { 528 mRegistry.removeObserver(observer2); 529 } 530 }); 531 final TestObserver observer4 = mock(TestObserver.class); 532 final TestObserver observer1 = spy(new TestObserver() { 533 @Override 534 void onStart() { 535 mRegistry.addObserver(observer2); 536 } 537 538 @Override 539 void onResume() { 540 mRegistry.addObserver(observer3); 541 mRegistry.addObserver(observer4); 542 } 543 }); 544 545 mRegistry.addObserver(observer1); 546 InOrder inOrder = inOrder(observer1, observer2, observer3, observer4); 547 inOrder.verify(observer1).onCreate(); 548 inOrder.verify(observer1).onStart(); 549 inOrder.verify(observer2).onCreate(); 550 inOrder.verify(observer1).onResume(); 551 inOrder.verify(observer3).onCreate(); 552 inOrder.verify(observer3).onStart(); 553 inOrder.verify(observer4).onCreate(); 554 inOrder.verify(observer4).onStart(); 555 inOrder.verify(observer3).onResume(); 556 inOrder.verify(observer4).onResume(); 557 } 558 559 @Test 560 public void sameObserverReAddition() { 561 TestObserver observer = mock(TestObserver.class); 562 mRegistry.addObserver(observer); 563 mRegistry.removeObserver(observer); 564 mRegistry.addObserver(observer); 565 dispatchEvent(ON_CREATE); 566 verify(observer).onCreate(); 567 } 568 569 private static void forceGc() { 570 Runtime.getRuntime().gc(); 571 Runtime.getRuntime().runFinalization(); 572 Runtime.getRuntime().gc(); 573 Runtime.getRuntime().runFinalization(); 574 } 575 576 @Test 577 public void goneLifecycleOwner() { 578 fullyInitializeRegistry(); 579 mLifecycleOwner = null; 580 forceGc(); 581 TestObserver observer = mock(TestObserver.class); 582 mRegistry.addObserver(observer); 583 verify(observer, never()).onCreate(); 584 verify(observer, never()).onStart(); 585 verify(observer, never()).onResume(); 586 } 587 588 private void dispatchEvent(Lifecycle.Event event) { 589 when(mLifecycle.getCurrentState()).thenReturn(LifecycleRegistry.getStateAfter(event)); 590 mRegistry.handleLifecycleEvent(event); 591 } 592 593 private void fullyInitializeRegistry() { 594 dispatchEvent(ON_CREATE); 595 dispatchEvent(ON_START); 596 dispatchEvent(ON_RESUME); 597 } 598 599 private abstract class TestObserver implements LifecycleObserver { 600 @OnLifecycleEvent(ON_CREATE) 601 void onCreate() { 602 } 603 604 @OnLifecycleEvent(ON_START) 605 void onStart() { 606 } 607 608 @OnLifecycleEvent(ON_RESUME) 609 void onResume() { 610 } 611 612 @OnLifecycleEvent(ON_PAUSE) 613 void onPause() { 614 } 615 616 @OnLifecycleEvent(ON_STOP) 617 void onStop() { 618 } 619 620 @OnLifecycleEvent(ON_DESTROY) 621 void onDestroy() { 622 } 623 } 624} 625