16ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets/*
26ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets * Copyright (C) 2017 The Android Open Source Project
36ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets *
46ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets * Licensed under the Apache License, Version 2.0 (the "License");
56ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets * you may not use this file except in compliance with the License.
66ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets * You may obtain a copy of the License at
76ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets *
86ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets *      http://www.apache.org/licenses/LICENSE-2.0
96ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets *
106ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets * Unless required by applicable law or agreed to in writing, software
116ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets * distributed under the License is distributed on an "AS IS" BASIS,
126ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets * See the License for the specific language governing permissions and
146ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets * limitations under the License.
156ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets */
166ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
17ba069d50913c3fb250bb60ec310439db36895337Alan Viverettepackage androidx.lifecycle;
186ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
196ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport static org.hamcrest.CoreMatchers.is;
206ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport static org.hamcrest.MatcherAssert.assertThat;
216ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport static org.mockito.Matchers.any;
226ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport static org.mockito.Mockito.mock;
236ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport static org.mockito.Mockito.never;
246ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport static org.mockito.Mockito.reset;
256ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport static org.mockito.Mockito.verify;
266ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport static org.mockito.Mockito.when;
276ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
28ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.annotation.Nullable;
29ddee2b5170ae257a7b2494f8aaa8459ebed806dcAurimas Liutikasimport androidx.arch.core.executor.ArchTaskExecutor;
30ddee2b5170ae257a7b2494f8aaa8459ebed806dcAurimas Liutikasimport androidx.arch.core.executor.testing.InstantTaskExecutorRule;
31ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.util.InstantTaskExecutor;
326ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
336ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport org.junit.Before;
341e6eadb9fb537c6bd81cc6a50ab685711cd84fd9Sergey Vasilinetsimport org.junit.Rule;
356ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport org.junit.Test;
366ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport org.junit.runner.RunWith;
376ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetsimport org.junit.runners.JUnit4;
386ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
396ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets@SuppressWarnings("unchecked")
406ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets@RunWith(JUnit4.class)
416ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinetspublic class MediatorLiveDataTest {
426ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
431e6eadb9fb537c6bd81cc6a50ab685711cd84fd9Sergey Vasilinets    @Rule
441e6eadb9fb537c6bd81cc6a50ab685711cd84fd9Sergey Vasilinets    public InstantTaskExecutorRule mInstantTaskExecutorRule = new InstantTaskExecutorRule();
451e6eadb9fb537c6bd81cc6a50ab685711cd84fd9Sergey Vasilinets
466ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    private LifecycleOwner mOwner;
476ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    private LifecycleRegistry mRegistry;
486ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    private MediatorLiveData<String> mMediator;
496ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    private LiveData<String> mSource;
506ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    private boolean mSourceActive;
516ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
526ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Before
536ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void setup() {
546ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mOwner = mock(LifecycleOwner.class);
556ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mRegistry = new LifecycleRegistry(mOwner);
566ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        when(mOwner.getLifecycle()).thenReturn(mRegistry);
576ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator = new MediatorLiveData<>();
586ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource = new LiveData<String>() {
596ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets            @Override
606ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets            protected void onActive() {
616ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets                mSourceActive = true;
626ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets            }
636ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
646ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets            @Override
656ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets            protected void onInactive() {
666ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets                mSourceActive = false;
676ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets            }
686ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        };
696ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSourceActive = false;
706ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.observe(mOwner, mock(Observer.class));
71b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
72b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
736ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
746ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
756ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Before
766ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void swapExecutorDelegate() {
77ae36c8b11a64d3cdc9ba6e37d9f3d1d250fdc4a8Yigit Boyar        ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
786ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
796ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
806ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Test
816ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void testSingleDelivery() {
826ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        Observer observer = mock(Observer.class);
836ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.addSource(mSource, observer);
846ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource.setValue("flatfoot");
856ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer).onChanged("flatfoot");
86b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
876ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        reset(observer);
886ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer, never()).onChanged(any());
896ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
906ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
916ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Test
926ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void testChangeWhileInactive() {
936ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        Observer observer = mock(Observer.class);
946ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.addSource(mSource, observer);
956ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.observe(mOwner, mock(Observer.class));
966ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource.setValue("one");
976ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer).onChanged("one");
98b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
996ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        reset(observer);
1006ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource.setValue("flatfoot");
101b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
1026ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer).onChanged("flatfoot");
1036ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
1046ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
1056ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
1066ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Test
1076ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void testAddSourceToActive() {
1086ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource.setValue("flatfoot");
1096ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        Observer observer = mock(Observer.class);
1106ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.addSource(mSource, observer);
1116ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer).onChanged("flatfoot");
1126ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
1136ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
1146ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Test
1156ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void testAddSourceToInActive() {
1166ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource.setValue("flatfoot");
117b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
1186ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        Observer observer = mock(Observer.class);
1196ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.addSource(mSource, observer);
1206ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer, never()).onChanged(any());
121b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
1226ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer).onChanged("flatfoot");
1236ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
1246ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
1256ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Test
1266ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void testRemoveSource() {
1276ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource.setValue("flatfoot");
1286ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        Observer observer = mock(Observer.class);
1296ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.addSource(mSource, observer);
1306ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer).onChanged("flatfoot");
1316ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.removeSource(mSource);
1326ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        reset(observer);
1336ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource.setValue("failure");
1346ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer, never()).onChanged(any());
1356ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
1366ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
1376ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Test
1386ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void testSourceInactive() {
1396ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        Observer observer = mock(Observer.class);
1406ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.addSource(mSource, observer);
1416ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        assertThat(mSourceActive, is(true));
142b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
1436ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        assertThat(mSourceActive, is(false));
144b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
1456ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        assertThat(mSourceActive, is(true));
1466ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
1476ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
1486ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Test
1496ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void testNoLeakObserver() {
1506ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        // Imitates a destruction of a ViewModel: a listener of LiveData is destroyed,
1516ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        // a reference to MediatorLiveData is cleaned up. In this case we shouldn't leak
1526ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        // MediatorLiveData as an observer of mSource.
153abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets        assertThat(mSource.hasObservers(), is(false));
1546ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        Observer observer = mock(Observer.class);
1556ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.addSource(mSource, observer);
156abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets        assertThat(mSource.hasObservers(), is(true));
157b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
158b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
1596ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator = null;
160abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets        assertThat(mSource.hasObservers(), is(false));
1616ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
1626ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
1636ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    @Test
1646ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    public void testMultipleSources() {
1656ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        Observer observer1 = mock(Observer.class);
1666ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.addSource(mSource, observer1);
1676ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        MutableLiveData<Integer> source2 = new MutableLiveData<>();
1686ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        Observer observer2 = mock(Observer.class);
1696ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mMediator.addSource(source2, observer2);
1706ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource.setValue("flatfoot");
1716ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer1).onChanged("flatfoot");
1726ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer2, never()).onChanged(any());
1736ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        reset(observer1, observer2);
1746ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        source2.setValue(1703);
1756ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer1, never()).onChanged(any());
1766ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer2).onChanged(1703);
1776ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        reset(observer1, observer2);
178b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
1796ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        mSource.setValue("failure");
1806ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        source2.setValue(0);
1816ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer1, never()).onChanged(any());
1826ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        verify(observer2, never()).onChanged(any());
1836ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
1847b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets
1857b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets    @Test
1867b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets    public void removeSourceDuringOnActive() {
1877b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        // to trigger ConcurrentModificationException,
1887b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        // we have to call remove from a collection during "for" loop.
1897b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        // ConcurrentModificationException is thrown from next() method of an iterator
1907b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        // so this modification shouldn't be at the last iteration,
1917b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        // because if it is a last iteration, then next() wouldn't be called.
1927b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        // And the last: an order of an iteration over sources is not defined,
1937b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        // so I have to call it remove operation  from all observers.
1947b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
1957b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        Observer<String> removingObserver = new Observer<String>() {
1967b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets            @Override
1977b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets            public void onChanged(@Nullable String s) {
1987b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets                mMediator.removeSource(mSource);
1997b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets            }
2007b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        };
2017b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mMediator.addSource(mSource, removingObserver);
2027b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        MutableLiveData<String> source2 = new MutableLiveData<>();
2037b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        source2.setValue("nana");
2047b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mMediator.addSource(source2, removingObserver);
2057b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mSource.setValue("petjack");
2067b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
2077b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets    }
2087b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets
2097b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets    @Test(expected = IllegalArgumentException.class)
2107b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets    public void reAddSameSourceWithDifferentObserver() {
2117b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mMediator.addSource(mSource, mock(Observer.class));
2127b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mMediator.addSource(mSource, mock(Observer.class));
2137b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets    }
2147b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets
2157b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets    @Test
21694209fa7c603b9b0e226ce7e351461a479b5b595Sergey Vasilinets    public void addSameSourceWithSameObserver() {
21794209fa7c603b9b0e226ce7e351461a479b5b595Sergey Vasilinets        Observer observer = mock(Observer.class);
21894209fa7c603b9b0e226ce7e351461a479b5b595Sergey Vasilinets        mMediator.addSource(mSource, observer);
21994209fa7c603b9b0e226ce7e351461a479b5b595Sergey Vasilinets        mMediator.addSource(mSource, observer);
22094209fa7c603b9b0e226ce7e351461a479b5b595Sergey Vasilinets        // no exception was thrown
22194209fa7c603b9b0e226ce7e351461a479b5b595Sergey Vasilinets    }
22294209fa7c603b9b0e226ce7e351461a479b5b595Sergey Vasilinets
22394209fa7c603b9b0e226ce7e351461a479b5b595Sergey Vasilinets    @Test
2247b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets    public void addSourceDuringOnActive() {
2257b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
2267b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mSource.setValue("a");
2277b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mMediator.addSource(mSource, new Observer<String>() {
2287b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets            @Override
2297b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets            public void onChanged(@Nullable String s) {
2307b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets                MutableLiveData<String> source = new MutableLiveData<>();
2317b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets                source.setValue("b");
2327b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets                mMediator.addSource(source, new Observer<String>() {
2337b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets                    @Override
2347b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets                    public void onChanged(@Nullable String s) {
2357b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets                        mMediator.setValue("c");
2367b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets                    }
2377b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets                });
2387b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets            }
2397b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        });
2407b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
2417b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets        assertThat(mMediator.getValue(), is("c"));
2427b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets    }
2437b81f6101e2c1c68108243688f7d1d7302d1179eSergey Vasilinets
2446ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets}
245