• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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