1 /* 2 * Copyright 2018 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 17 package com.android.car.arch.common; 18 19 import static com.android.car.arch.common.LiveDataFunctions.coalesceNull; 20 import static com.android.car.arch.common.LiveDataFunctions.dataOf; 21 import static com.android.car.arch.common.LiveDataFunctions.distinct; 22 import static com.android.car.arch.common.LiveDataFunctions.emitsNull; 23 import static com.android.car.arch.common.LiveDataFunctions.falseLiveData; 24 import static com.android.car.arch.common.LiveDataFunctions.freezable; 25 import static com.android.car.arch.common.LiveDataFunctions.ifThenElse; 26 import static com.android.car.arch.common.LiveDataFunctions.not; 27 import static com.android.car.arch.common.LiveDataFunctions.nullLiveData; 28 import static com.android.car.arch.common.LiveDataFunctions.split; 29 import static com.android.car.arch.common.LiveDataFunctions.trueLiveData; 30 31 import static com.google.common.truth.Truth.assertThat; 32 33 import androidx.core.util.Pair; 34 import androidx.lifecycle.LiveData; 35 import androidx.lifecycle.MutableLiveData; 36 37 import com.android.car.arch.common.testing.CaptureObserver; 38 import com.android.car.arch.common.testing.InstantTaskExecutorRule; 39 import com.android.car.arch.common.testing.TestLifecycleOwner; 40 41 import org.junit.Rule; 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 import org.robolectric.RobolectricTestRunner; 45 import org.robolectric.annotation.Config; 46 47 import java.util.Objects; 48 import java.util.function.BiFunction; 49 import java.util.function.Function; 50 import java.util.function.Supplier; 51 52 @RunWith(RobolectricTestRunner.class) 53 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) 54 public class LiveDataFunctionsTest { 55 56 @Rule 57 public final InstantTaskExecutorRule mRule = new InstantTaskExecutorRule(); 58 @Rule 59 public final TestLifecycleOwner mLifecycleOwner = new TestLifecycleOwner(); 60 61 @Test testNullLiveData()62 public void testNullLiveData() { 63 CaptureObserver<Object> observer = new CaptureObserver<>(); 64 nullLiveData().observe(mLifecycleOwner, observer); 65 66 assertThat(observer.hasBeenNotified()).isTrue(); 67 assertThat(observer.getObservedValue()).isNull(); 68 assertThat(nullLiveData().getValue()).isNull(); 69 } 70 71 @Test testTrueLiveData()72 public void testTrueLiveData() { 73 CaptureObserver<Boolean> observer = new CaptureObserver<>(); 74 trueLiveData().observe(mLifecycleOwner, observer); 75 76 assertThat(observer.hasBeenNotified()).isTrue(); 77 assertThat(observer.getObservedValue()).isTrue(); 78 assertThat(trueLiveData().getValue()).isTrue(); 79 } 80 81 @Test testFalseLiveData()82 public void testFalseLiveData() { 83 CaptureObserver<Boolean> observer = new CaptureObserver<>(); 84 falseLiveData().observe(mLifecycleOwner, observer); 85 86 assertThat(observer.hasBeenNotified()).isTrue(); 87 assertThat(observer.getObservedValue()).isFalse(); 88 assertThat(falseLiveData().getValue()).isFalse(); 89 } 90 91 @Test testNot()92 public void testNot() { 93 testUnaryOperator( 94 LiveDataFunctions::not, 95 pair(trueLiveData(), false), 96 pair(falseLiveData(), true), 97 pair(nullLiveData(), null)); 98 99 checkUninitialized(not(new MutableLiveData<>())); 100 } 101 102 @Test testEmitsNull()103 public void testEmitsNull() { 104 testUnaryOperator( 105 LiveDataFunctions::emitsNull, 106 pair(dataOf(new Object()), false), 107 pair(nullLiveData(), true)); 108 checkUninitialized(emitsNull(new MutableLiveData<>())); 109 } 110 111 @Test testDistinct()112 public void testDistinct() { 113 CaptureObserver<Integer> observer = new CaptureObserver<>(); 114 MutableLiveData<Integer> source = dataOf(0); 115 LiveData<Integer> distinct = distinct(source); 116 distinct.observe(mLifecycleOwner, observer); 117 observer.reset(); 118 119 source.setValue(1); 120 assertThat(observer.hasBeenNotified()).isTrue(); 121 assertThat(observer.getObservedValue()).isEqualTo(1); 122 observer.reset(); 123 124 source.setValue(1); 125 assertThat(observer.hasBeenNotified()).isFalse(); 126 127 source.setValue(2); 128 assertThat(observer.hasBeenNotified()).isTrue(); 129 assertThat(observer.getObservedValue()).isEqualTo(2); 130 } 131 132 @Test testFreezable()133 public void testFreezable() { 134 CaptureObserver<Integer> observer = new CaptureObserver<>(); 135 MutableLiveData<Boolean> isFrozen = dataOf(false); 136 MutableLiveData<Integer> source = dataOf(0); 137 LiveData<Integer> freezable = freezable(isFrozen, source); 138 freezable.observe(mLifecycleOwner, observer); 139 140 // Initialized to correct value. 141 assertThat(observer.hasBeenNotified()).isTrue(); 142 assertThat(observer.getObservedValue()).isEqualTo(0); 143 observer.reset(); 144 145 // Updates with source when not frozen. 146 source.setValue(1); 147 assertThat(observer.hasBeenNotified()).isTrue(); 148 assertThat(observer.getObservedValue()).isEqualTo(1); 149 observer.reset(); 150 151 // Doesn't update when frozen. 152 isFrozen.setValue(true); 153 source.setValue(2); 154 assertThat(observer.hasBeenNotified()).isFalse(); 155 156 // Updates when unfrozen. 157 isFrozen.setValue(false); 158 assertThat(observer.hasBeenNotified()).isTrue(); 159 assertThat(observer.getObservedValue()).isEqualTo(2); 160 observer.reset(); 161 162 // Doesn't notify if no changes while frozen. 163 isFrozen.setValue(true); 164 isFrozen.setValue(false); 165 assertThat(observer.hasBeenNotified()).isFalse(); 166 } 167 168 @Test testAnd_truthTable()169 public void testAnd_truthTable() { 170 testBinaryOperator( 171 LiveDataFunctions::and, 172 pair(pair(trueLiveData(), trueLiveData()), true), 173 pair(pair(trueLiveData(), falseLiveData()), false), 174 pair(pair(trueLiveData(), nullLiveData()), null), 175 pair(pair(falseLiveData(), trueLiveData()), false), 176 pair(pair(falseLiveData(), falseLiveData()), false), 177 pair(pair(falseLiveData(), nullLiveData()), false), 178 pair(pair(nullLiveData(), trueLiveData()), null), 179 pair(pair(nullLiveData(), falseLiveData()), false), 180 pair(pair(nullLiveData(), nullLiveData()), null)); 181 } 182 183 @Test testAnd_uninitialized()184 public void testAnd_uninitialized() { 185 MutableLiveData<Boolean> empty = new MutableLiveData<>(); 186 checkUninitializedBinary( 187 LiveDataFunctions::and, 188 pair(trueLiveData(), empty), 189 pair(falseLiveData(), empty), 190 pair(nullLiveData(), empty), 191 pair(empty, trueLiveData()), 192 pair(empty, falseLiveData()), 193 pair(empty, nullLiveData())); 194 } 195 196 @Test testAnd_changeValue()197 public void testAnd_changeValue() { 198 MutableLiveData<Boolean> source = new MutableLiveData<>(); 199 CaptureObserver<Boolean> observer = new CaptureObserver<>(); 200 201 LiveDataFunctions.and(trueLiveData(), source).observe(mLifecycleOwner, observer); 202 assertThat(observer.hasBeenNotified()).isFalse(); 203 204 source.setValue(true); 205 206 assertThat(observer.hasBeenNotified()).isTrue(); 207 assertThat(observer.getObservedValue()).isTrue(); 208 } 209 210 @Test testOr_truthTable()211 public void testOr_truthTable() { 212 testBinaryOperator( 213 LiveDataFunctions::or, 214 pair(pair(trueLiveData(), trueLiveData()), true), 215 pair(pair(trueLiveData(), falseLiveData()), true), 216 pair(pair(trueLiveData(), nullLiveData()), true), 217 pair(pair(falseLiveData(), trueLiveData()), true), 218 pair(pair(falseLiveData(), falseLiveData()), false), 219 pair(pair(falseLiveData(), nullLiveData()), null), 220 pair(pair(nullLiveData(), trueLiveData()), true), 221 pair(pair(nullLiveData(), falseLiveData()), null), 222 pair(pair(nullLiveData(), nullLiveData()), null)); 223 } 224 225 @Test testOr_uninitialized()226 public void testOr_uninitialized() { 227 LiveData<Boolean> empty = new MutableLiveData<>(); 228 checkUninitializedBinary( 229 LiveDataFunctions::or, 230 pair(trueLiveData(), empty), 231 pair(falseLiveData(), empty), 232 pair(nullLiveData(), empty), 233 pair(empty, trueLiveData()), 234 pair(empty, falseLiveData()), 235 pair(empty, nullLiveData())); 236 } 237 238 @Test testOr_changeValue()239 public void testOr_changeValue() { 240 MutableLiveData<Boolean> source = new MutableLiveData<>(); 241 CaptureObserver<Boolean> observer = new CaptureObserver<>(); 242 243 LiveDataFunctions.or(trueLiveData(), source).observe(mLifecycleOwner, observer); 244 assertThat(observer.hasBeenNotified()).isFalse(); 245 246 source.setValue(true); 247 248 assertThat(observer.hasBeenNotified()).isTrue(); 249 assertThat(observer.getObservedValue()).isTrue(); 250 } 251 252 @Test testIff_truthTable()253 public void testIff_truthTable() { 254 Object object = new Object(); 255 testBinaryOperator( 256 (predicate, value) -> LiveDataFunctions.iff(predicate, Boolean::booleanValue, 257 value), 258 pair(pair(trueLiveData(), dataOf(object)), object), 259 pair(pair(falseLiveData(), dataOf(object)), null), 260 pair(pair(nullLiveData(), dataOf(object)), null)); 261 } 262 263 @Test testIff_uninitialized()264 public void testIff_uninitialized() { 265 checkUninitializedBinary( 266 (predicate, value) -> LiveDataFunctions.iff(predicate, Boolean::booleanValue, 267 value), 268 pair(new MutableLiveData<>(), dataOf(new Object())), 269 pair(falseLiveData(), new MutableLiveData<>()), 270 pair(trueLiveData(), new MutableLiveData<>())); 271 } 272 273 @Test testIff_changePredicate()274 public void testIff_changePredicate() { 275 MutableLiveData<Boolean> predicate = new MutableLiveData<>(); 276 MutableLiveData<Object> value = new MutableLiveData<>(); 277 Object valueObject = new Object(); 278 value.setValue(valueObject); 279 CaptureObserver<Object> observer = new CaptureObserver<>(); 280 281 LiveDataFunctions.iff(predicate, Boolean::booleanValue, value) 282 .observe(mLifecycleOwner, observer); 283 assertThat(observer.hasBeenNotified()).isFalse(); 284 285 predicate.setValue(false); 286 287 assertThat(observer.hasBeenNotified()).isTrue(); 288 assertThat(observer.getObservedValue()).isNull(); 289 observer.reset(); 290 291 predicate.setValue(true); 292 293 assertThat(observer.hasBeenNotified()).isTrue(); 294 assertThat(observer.getObservedValue()).isSameAs(valueObject); 295 observer.reset(); 296 297 predicate.setValue(null); 298 299 assertThat(observer.hasBeenNotified()).isTrue(); 300 assertThat(observer.getObservedValue()).isNull(); 301 } 302 303 @Test testIff_changeValue()304 public void testIff_changeValue() { 305 LiveData<Boolean> predicate = trueLiveData(); 306 MutableLiveData<Object> value = new MutableLiveData<>(); 307 Object firstObject = new Object(); 308 CaptureObserver<Object> observer = new CaptureObserver<>(); 309 310 LiveDataFunctions.iff(predicate, Boolean::booleanValue, value) 311 .observe(mLifecycleOwner, observer); 312 assertThat(observer.hasBeenNotified()).isFalse(); 313 314 value.setValue(null); 315 316 assertThat(observer.hasBeenNotified()).isTrue(); 317 assertThat(observer.getObservedValue()).isNull(); 318 observer.reset(); 319 320 value.setValue(firstObject); 321 322 assertThat(observer.hasBeenNotified()).isTrue(); 323 assertThat(observer.getObservedValue()).isSameAs(firstObject); 324 observer.reset(); 325 326 value.setValue(new Object()); 327 328 assertThat(observer.hasBeenNotified()).isTrue(); 329 assertThat(observer.getObservedValue()).isNotSameAs(firstObject); 330 } 331 332 @Test testIff_changeValue_doesntNotifyForIrrelevantChanges()333 public void testIff_changeValue_doesntNotifyForIrrelevantChanges() { 334 MutableLiveData<Object> irrelevantValue = new MutableLiveData<>(); 335 irrelevantValue.setValue(new Object()); 336 CaptureObserver<Object> observer = new CaptureObserver<>(); 337 338 // irrelevantValue irrelevant because iff() always emits null when predicate is false. 339 LiveDataFunctions.iff(falseLiveData(), Boolean::booleanValue, irrelevantValue) 340 .observe(mLifecycleOwner, observer); 341 assertThat(observer.hasBeenNotified()).isTrue(); 342 observer.reset(); 343 344 irrelevantValue.setValue(null); 345 346 assertThat(observer.hasBeenNotified()).isFalse(); 347 } 348 349 @Test testIfThenElse_liveDataParams_truthTable()350 public void testIfThenElse_liveDataParams_truthTable() { 351 Object trueObject = new Object(); 352 Object falseObject = new Object(); 353 354 LiveData<Object> trueObjectData = dataOf(trueObject); 355 LiveData<Object> falseObjectData = dataOf(falseObject); 356 357 testOperator(arg -> () -> 358 ifThenElse(arg.mPredicate, Boolean::booleanValue, arg.mTrueData, 359 arg.mFalseData), 360 pair(new IfThenElseDataParams<>(trueLiveData(), trueObjectData, falseObjectData), 361 trueObject), 362 pair(new IfThenElseDataParams<>(falseLiveData(), trueObjectData, falseObjectData), 363 falseObject), 364 pair(new IfThenElseDataParams<>(dataOf(null), trueObjectData, falseObjectData), 365 null)); 366 } 367 368 @Test testIfThenElse_liveDataParams_uninitialized()369 public void testIfThenElse_liveDataParams_uninitialized() { 370 Object trueObject = new Object(); 371 Object falseObject = new Object(); 372 373 LiveData<Object> trueObjectData = dataOf(trueObject); 374 LiveData<Object> falseObjectData = dataOf(falseObject); 375 376 checkUninitialized( 377 ifThenElse( 378 new MutableLiveData<>(), Boolean::booleanValue, trueObjectData, 379 falseObjectData)); 380 checkUninitialized( 381 ifThenElse( 382 trueLiveData(), Boolean::booleanValue, new MutableLiveData<>(), 383 falseObjectData)); 384 checkUninitialized( 385 ifThenElse( 386 falseLiveData(), Boolean::booleanValue, trueObjectData, 387 new MutableLiveData<>())); 388 } 389 390 @Test testIfThenElse_liveDataParams_changePredicate()391 public void testIfThenElse_liveDataParams_changePredicate() { 392 Object trueObject = new Object(); 393 Object falseObject = new Object(); 394 395 LiveData<Object> trueObjectData = dataOf(trueObject); 396 LiveData<Object> falseObjectData = dataOf(falseObject); 397 398 MutableLiveData<Boolean> predicate = new MutableLiveData<>(); 399 CaptureObserver<Object> observer = new CaptureObserver<>(); 400 401 ifThenElse(predicate, Boolean::booleanValue, trueObjectData, 402 falseObjectData) 403 .observe(mLifecycleOwner, observer); 404 assertThat(observer.hasBeenNotified()).isFalse(); 405 406 predicate.setValue(false); 407 408 assertThat(observer.hasBeenNotified()).isTrue(); 409 assertThat(observer.getObservedValue()).isSameAs(falseObject); 410 observer.reset(); 411 412 predicate.setValue(true); 413 414 assertThat(observer.hasBeenNotified()).isTrue(); 415 assertThat(observer.getObservedValue()).isSameAs(trueObject); 416 observer.reset(); 417 418 predicate.setValue(null); 419 420 assertThat(observer.hasBeenNotified()).isTrue(); 421 assertThat(observer.getObservedValue()).isNull(); 422 } 423 424 @Test testIfThenElse_liveDataParams_changeValue_value()425 public void testIfThenElse_liveDataParams_changeValue_value() { 426 Object trueObject = new Object(); 427 Object falseObject = new Object(); 428 429 MutableLiveData<Object> trueObjectData = new MutableLiveData<>(); 430 LiveData<Object> falseObjectData = dataOf(falseObject); 431 432 LiveData<Boolean> predicate = trueLiveData(); 433 CaptureObserver<Object> observer = new CaptureObserver<>(); 434 435 ifThenElse(predicate, Boolean::booleanValue, trueObjectData, 436 falseObjectData) 437 .observe(mLifecycleOwner, observer); 438 assertThat(observer.hasBeenNotified()).isFalse(); 439 440 trueObjectData.setValue(null); 441 442 assertThat(observer.hasBeenNotified()).isTrue(); 443 assertThat(observer.getObservedValue()).isNull(); 444 observer.reset(); 445 446 trueObjectData.setValue(trueObject); 447 448 assertThat(observer.hasBeenNotified()).isTrue(); 449 assertThat(observer.getObservedValue()).isSameAs(trueObject); 450 observer.reset(); 451 452 trueObjectData.setValue(new Object()); 453 454 assertThat(observer.hasBeenNotified()).isTrue(); 455 assertThat(observer.getObservedValue()).isNotSameAs(trueObject); 456 } 457 458 @Test testIfThenElse_liveDataParams_changeValue_doesntNotifyForIrrelevantChanges()459 public void testIfThenElse_liveDataParams_changeValue_doesntNotifyForIrrelevantChanges() { 460 MutableLiveData<Object> irrelevantValue = new MutableLiveData<>(); 461 irrelevantValue.setValue(new Object()); 462 CaptureObserver<Object> observer = new CaptureObserver<>(); 463 464 // irrelevantValue irrelevant because ifThenElse() is backed by other param when 465 // predicate is 466 // false. 467 ifThenElse( 468 falseLiveData(), Boolean::booleanValue, irrelevantValue, dataOf(new Object())) 469 .observe(mLifecycleOwner, observer); 470 assertThat(observer.hasBeenNotified()).isTrue(); 471 observer.reset(); 472 473 irrelevantValue.setValue(null); 474 475 assertThat(observer.hasBeenNotified()).isFalse(); 476 } 477 478 @Test testIfThenElse_valueParams_truthTable()479 public void testIfThenElse_valueParams_truthTable() { 480 Object trueObject = new Object(); 481 Object falseObject = new Object(); 482 483 testOperator(arg -> () -> ifThenElse(arg.mPredicate, Boolean::booleanValue, arg.mTrueValue, 484 arg.mFalseValue), 485 pair(new IfThenElseValueParams<>(trueLiveData(), trueObject, falseObject), 486 trueObject), 487 pair(new IfThenElseValueParams<>(falseLiveData(), trueObject, falseObject), 488 falseObject), 489 pair(new IfThenElseValueParams<>(dataOf(null), trueObject, falseObject), null)); 490 } 491 492 @Test testIfThenElse_valueParams_uninitialized()493 public void testIfThenElse_valueParams_uninitialized() { 494 Object trueObject = new Object(); 495 Object falseObject = new Object(); 496 497 checkUninitialized( 498 ifThenElse(new MutableLiveData<>(), Boolean::booleanValue, trueObject, 499 falseObject)); 500 } 501 502 @Test testIfThenElse_valueParams_changePredicate()503 public void testIfThenElse_valueParams_changePredicate() { 504 Object trueObject = new Object(); 505 Object falseObject = new Object(); 506 507 MutableLiveData<Boolean> predicate = new MutableLiveData<>(); 508 CaptureObserver<Object> observer = new CaptureObserver<>(); 509 510 ifThenElse(predicate, Boolean::booleanValue, trueObject, falseObject) 511 .observe(mLifecycleOwner, observer); 512 assertThat(observer.hasBeenNotified()).isFalse(); 513 514 predicate.setValue(false); 515 516 assertThat(observer.hasBeenNotified()).isTrue(); 517 assertThat(observer.getObservedValue()).isSameAs(falseObject); 518 observer.reset(); 519 520 predicate.setValue(true); 521 522 assertThat(observer.hasBeenNotified()).isTrue(); 523 assertThat(observer.getObservedValue()).isSameAs(trueObject); 524 observer.reset(); 525 526 predicate.setValue(null); 527 528 assertThat(observer.hasBeenNotified()).isTrue(); 529 assertThat(observer.getObservedValue()).isNull(); 530 } 531 532 @Test testCoalesceNull_liveDataParams_truthTable()533 public void testCoalesceNull_liveDataParams_truthTable() { 534 TestObject sourceObject = new TestObject(); 535 TestObject fallbackObject = new TestObject(); 536 537 LiveData<TestObject> sourceData = dataOf(sourceObject); 538 LiveData<TestObject> fallbackData = dataOf(fallbackObject); 539 testBinaryOperator(LiveDataFunctions::coalesceNull, 540 pair(pair(sourceData, fallbackData), sourceObject), 541 pair(pair(sourceData, nullLiveData()), sourceObject), 542 // uninitialized fallback is fine. 543 pair(pair(sourceData, new MutableLiveData<>()), sourceObject), 544 pair(pair(nullLiveData(), fallbackData), fallbackObject), 545 pair(pair(nullLiveData(), nullLiveData()), null)); 546 } 547 548 @Test testCoalesceNull_liveDataParams_uninitialized()549 public void testCoalesceNull_liveDataParams_uninitialized() { 550 TestObject fallbackObject = new TestObject(); 551 LiveData<TestObject> fallbackData = dataOf(fallbackObject); 552 553 checkUninitialized(coalesceNull(new MutableLiveData<TestObject>(), fallbackData)); 554 } 555 556 @Test testCoalesceNull_liveDataParams_changeSource()557 public void testCoalesceNull_liveDataParams_changeSource() { 558 TestObject firstSourceObject = new TestObject(); 559 TestObject secondSourceObject = new TestObject(); 560 TestObject fallbackObject = new TestObject(); 561 562 MutableLiveData<TestObject> sourceData = dataOf(null); 563 LiveData<TestObject> fallbackData = dataOf(fallbackObject); 564 565 CaptureObserver<TestObject> observer = new CaptureObserver<>(); 566 LiveData<TestObject> data = coalesceNull(sourceData, fallbackData); 567 568 data.observe(mLifecycleOwner, observer); 569 570 assertThat(observer.hasBeenNotified()).isTrue(); 571 assertThat(observer.getObservedValue()).isSameAs(fallbackObject); 572 observer.reset(); 573 574 sourceData.setValue(firstSourceObject); 575 576 assertThat(observer.hasBeenNotified()).isTrue(); 577 assertThat(observer.getObservedValue()).isSameAs(firstSourceObject); 578 observer.reset(); 579 580 sourceData.setValue(secondSourceObject); 581 582 assertThat(observer.hasBeenNotified()).isTrue(); 583 assertThat(observer.getObservedValue()).isSameAs(secondSourceObject); 584 observer.reset(); 585 586 sourceData.setValue(null); 587 588 assertThat(observer.hasBeenNotified()).isTrue(); 589 assertThat(observer.getObservedValue()).isSameAs(fallbackObject); 590 observer.reset(); 591 } 592 593 @Test testCoalesceNull_liveDataParams_changeFallback()594 public void testCoalesceNull_liveDataParams_changeFallback() { 595 TestObject firstFallbackObject = new TestObject(); 596 TestObject secondFallbackObject = new TestObject(); 597 598 LiveData<TestObject> sourceData = nullLiveData(); 599 MutableLiveData<TestObject> fallbackData = dataOf(null); 600 601 CaptureObserver<TestObject> observer = new CaptureObserver<>(); 602 LiveData<TestObject> data = coalesceNull(sourceData, fallbackData); 603 604 data.observe(mLifecycleOwner, observer); 605 606 assertThat(observer.hasBeenNotified()).isTrue(); 607 assertThat(observer.getObservedValue()).isNull(); 608 observer.reset(); 609 610 fallbackData.setValue(firstFallbackObject); 611 612 assertThat(observer.hasBeenNotified()).isTrue(); 613 assertThat(observer.getObservedValue()).isSameAs(firstFallbackObject); 614 observer.reset(); 615 616 fallbackData.setValue(secondFallbackObject); 617 618 assertThat(observer.hasBeenNotified()).isTrue(); 619 assertThat(observer.getObservedValue()).isSameAs(secondFallbackObject); 620 observer.reset(); 621 622 fallbackData.setValue(null); 623 624 assertThat(observer.hasBeenNotified()).isTrue(); 625 assertThat(observer.getObservedValue()).isSameAs(null); 626 observer.reset(); 627 } 628 629 @Test testCoalesceNull_liveDataParams_changeFallback_doesntNotifyForIrrelevantChanges()630 public void testCoalesceNull_liveDataParams_changeFallback_doesntNotifyForIrrelevantChanges() { 631 TestObject sourceObject = new TestObject(); 632 TestObject fallbackObject = new TestObject(); 633 634 LiveData<TestObject> sourceData = dataOf(sourceObject); 635 // Irrelevant because sourceData is always non-null 636 MutableLiveData<TestObject> irrelevantData = dataOf(fallbackObject); 637 638 CaptureObserver<TestObject> observer = new CaptureObserver<>(); 639 LiveData<TestObject> data = coalesceNull(sourceData, irrelevantData); 640 data.observe(mLifecycleOwner, observer); 641 observer.reset(); 642 643 irrelevantData.setValue(null); 644 645 assertThat(observer.hasBeenNotified()).isFalse(); 646 } 647 648 @Test testCoalesceNull_valueParams_truthTable()649 public void testCoalesceNull_valueParams_truthTable() { 650 Object sourceObject = new Object(); 651 Object fallbackObject = new Object(); 652 653 LiveData<Object> sourceData = dataOf(sourceObject); 654 655 testOperator(args -> () -> coalesceNull(Objects.requireNonNull(args.first), args.second), 656 pair(pair(sourceData, fallbackObject), sourceObject), 657 pair(pair(sourceData, null), sourceObject), 658 pair(pair(nullLiveData(), fallbackObject), fallbackObject), 659 pair(pair(nullLiveData(), null), null)); 660 661 } 662 663 @Test testCoalesceNull_valueParams_uninitialized()664 public void testCoalesceNull_valueParams_uninitialized() { 665 // Values contained in SoftReference don't actually matter. SoftReference is just used as 666 // an easily instantiable type. Object cannot be used because LiveData extends Object, 667 // and thus some method calls would become ambiguous due to overloads. 668 Object fallbackObject = new Object(); 669 670 checkUninitialized(coalesceNull(new MutableLiveData<>(), fallbackObject)); 671 } 672 673 @Test testCoalesceNull_valueParams_changeSource()674 public void testCoalesceNull_valueParams_changeSource() { 675 // Values contained in SoftReference don't actually matter. SoftReference is just used as 676 // an easily instantiable type. Object cannot be used because LiveData extends Object, 677 // and thus some method calls would become ambiguous. 678 Object firstSourceObject = new Object(); 679 Object secondSourceObject = new Object(); 680 Object fallbackObject = new Object(); 681 682 MutableLiveData<Object> sourceData = dataOf(null); 683 684 CaptureObserver<Object> observer = new CaptureObserver<>(); 685 LiveData<Object> data = coalesceNull(sourceData, fallbackObject); 686 687 data.observe(mLifecycleOwner, observer); 688 689 assertThat(observer.hasBeenNotified()).isTrue(); 690 assertThat(observer.getObservedValue()).isSameAs(fallbackObject); 691 observer.reset(); 692 693 sourceData.setValue(firstSourceObject); 694 695 assertThat(observer.hasBeenNotified()).isTrue(); 696 assertThat(observer.getObservedValue()).isSameAs(firstSourceObject); 697 observer.reset(); 698 699 sourceData.setValue(secondSourceObject); 700 701 assertThat(observer.hasBeenNotified()).isTrue(); 702 assertThat(observer.getObservedValue()).isSameAs(secondSourceObject); 703 observer.reset(); 704 705 sourceData.setValue(null); 706 707 assertThat(observer.hasBeenNotified()).isTrue(); 708 assertThat(observer.getObservedValue()).isSameAs(fallbackObject); 709 observer.reset(); 710 } 711 712 @Test testSplit()713 public void testSplit() { 714 Object first = new Object(); 715 Object second = new Object(); 716 717 MutableLiveData<Object> firstData = new MutableLiveData<>(); 718 MutableLiveData<Object> secondData = new MutableLiveData<>(); 719 firstData.setValue(first); 720 secondData.setValue(second); 721 722 Object[] observedValues = new Object[2]; 723 boolean[] notified = new boolean[1]; 724 725 LiveDataFunctions.pair(firstData, secondData) 726 .observe( 727 mLifecycleOwner, 728 split( 729 (left, right) -> { 730 notified[0] = true; 731 observedValues[0] = left; 732 observedValues[1] = right; 733 })); 734 735 assertThat(notified[0]).isTrue(); 736 assertThat(observedValues[0]).isSameAs(first); 737 assertThat(observedValues[1]).isSameAs(second); 738 } 739 740 @Test testSplit_null()741 public void testSplit_null() { 742 Object[] observedValues = new Object[2]; 743 boolean[] notified = new boolean[1]; 744 745 dataOf((Pair<Object, Object>) null) 746 .observe( 747 mLifecycleOwner, 748 split( 749 (left, right) -> { 750 notified[0] = true; 751 observedValues[0] = left; 752 observedValues[1] = right; 753 })); 754 755 assertThat(notified[0]).isTrue(); 756 assertThat(observedValues[0]).isNull(); 757 assertThat(observedValues[1]).isNull(); 758 } 759 760 @Test testCombine()761 public void testCombine() { 762 Object first = new Object(); 763 Object second = new Object(); 764 765 MutableLiveData<Object> firstData = new MutableLiveData<>(); 766 MutableLiveData<Object> secondData = new MutableLiveData<>(); 767 firstData.setValue(first); 768 secondData.setValue(second); 769 770 CaptureObserver<Pair<Object, Object>> observer = new CaptureObserver<>(); 771 LiveDataFunctions.combine(firstData, secondData, Pair::new).observe(mLifecycleOwner, 772 observer); 773 774 Pair<Object, Object> observedValue = observer.getObservedValue(); 775 assertThat(observedValue).isNotNull(); 776 assertThat(observedValue.first).isSameAs(first); 777 assertThat(observedValue.second).isSameAs(second); 778 779 Object third = new Object(); 780 firstData.setValue(third); 781 782 observedValue = observer.getObservedValue(); 783 assertThat(observedValue).isNotNull(); 784 assertThat(observedValue.first).isSameAs(third); 785 assertThat(observedValue.second).isSameAs(second); 786 } 787 788 private static class IfThenElseDataParams<T> { 789 final LiveData<Boolean> mPredicate; 790 final LiveData<T> mTrueData; 791 final LiveData<T> mFalseData; 792 IfThenElseDataParams( LiveData<Boolean> predicate, LiveData<T> trueData, LiveData<T> falseData)793 private IfThenElseDataParams( 794 LiveData<Boolean> predicate, LiveData<T> trueData, LiveData<T> falseData) { 795 this.mPredicate = predicate; 796 this.mTrueData = trueData; 797 this.mFalseData = falseData; 798 } 799 } 800 801 private static class IfThenElseValueParams<T> { 802 final LiveData<Boolean> mPredicate; 803 final T mTrueValue; 804 final T mFalseValue; 805 IfThenElseValueParams(LiveData<Boolean> predicate, T trueValue, T falseValue)806 private IfThenElseValueParams(LiveData<Boolean> predicate, T trueValue, T falseValue) { 807 this.mPredicate = predicate; 808 this.mTrueValue = trueValue; 809 this.mFalseValue = falseValue; 810 } 811 } 812 testOperator(Supplier<LiveData<R>> op, R result)813 private <R> void testOperator(Supplier<LiveData<R>> op, R result) { 814 CaptureObserver<R> observer = new CaptureObserver<>(); 815 LiveData<R> data = op.get(); 816 817 data.observe(mLifecycleOwner, observer); 818 819 assertThat(observer.hasBeenNotified()).isTrue(); 820 assertThat(observer.getObservedValue()).isEqualTo(result); 821 assertThat(data.getValue()).isEqualTo(result); 822 } 823 824 @SafeVarargs // args are never written to testOperator( Function<P, Supplier<LiveData<R>>> ops, Pair<P, R>... args)825 private final <P, R> void testOperator( 826 Function<P, Supplier<LiveData<R>>> ops, Pair<P, R>... args) { 827 for (Pair<P, R> arg : args) { 828 testOperator(ops.apply(arg.first), arg.second); 829 } 830 } 831 832 @SafeVarargs // args are never written to testUnaryOperator( Function<LiveData<T>, LiveData<R>> op, Pair<LiveData<T>, R>... args)833 private final <T, R> void testUnaryOperator( 834 Function<LiveData<T>, LiveData<R>> op, Pair<LiveData<T>, R>... args) { 835 testOperator(arg -> () -> op.apply(arg), args); 836 } 837 838 @SafeVarargs // args are never written to testBinaryOperator( BiFunction<LiveData<A>, LiveData<B>, LiveData<R>> op, Pair<Pair<LiveData<A>, LiveData<B>>, R>... args)839 private final <A, B, R> void testBinaryOperator( 840 BiFunction<LiveData<A>, LiveData<B>, LiveData<R>> op, 841 Pair<Pair<LiveData<A>, LiveData<B>>, R>... args) { 842 testOperator(arg -> () -> op.apply(arg.first, arg.second), args); 843 } 844 pair(T first, R second)845 private <T, R> Pair<T, R> pair(T first, R second) { 846 return new Pair<>(first, second); 847 } 848 checkUninitialized(LiveData<T> liveData)849 private <T> void checkUninitialized(LiveData<T> liveData) { 850 CaptureObserver<T> observer = new CaptureObserver<>(); 851 852 liveData.observe(mLifecycleOwner, observer); 853 854 assertThat(observer.hasBeenNotified()).isFalse(); 855 assertThat(liveData.getValue()).isNull(); 856 } 857 858 @SafeVarargs // args are never written to checkUninitializedBinary( BiFunction<LiveData<A>, LiveData<B>, LiveData<?>> op, Pair<LiveData<A>, LiveData<B>>... args)859 private final <A, B> void checkUninitializedBinary( 860 BiFunction<LiveData<A>, LiveData<B>, LiveData<?>> op, 861 Pair<LiveData<A>, LiveData<B>>... args) { 862 for (Pair<LiveData<A>, LiveData<B>> arg : args) { 863 checkUninitialized(op.apply(arg.first, arg.second)); 864 } 865 } 866 867 /** 868 * Used as an easily instantiable type where Object cannot be used because LiveData extends 869 * Object, and thus some method calls would become ambiguous. 870 **/ 871 private class TestObject { 872 } 873 } 874