LiveDataTest.java revision d069a4c914b2b43912fa6267b2f4c65408b6a4dc
1c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar/*
2c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * Copyright (C) 2017 The Android Open Source Project
3c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar *
4c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
5c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * you may not use this file except in compliance with the License.
6c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * You may obtain a copy of the License at
7c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar *
8c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
9c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar *
10c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * Unless required by applicable law or agreed to in writing, software
11c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
12c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * See the License for the specific language governing permissions and
14c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * limitations under the License.
15c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar */
16c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
17c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarpackage android.arch.lifecycle;
18c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
19c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_CREATE;
20c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_DESTROY;
21c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_PAUSE;
22c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_RESUME;
23c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_START;
24c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
25c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
26c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.hamcrest.CoreMatchers.instanceOf;
27c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.hamcrest.CoreMatchers.is;
28c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.hamcrest.MatcherAssert.assertThat;
29c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Matchers.anyBoolean;
30c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Matchers.anyString;
31c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.mock;
324d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyarimport static org.mockito.Mockito.never;
33c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.reset;
34c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.spy;
35c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.verify;
36c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport static org.mockito.Mockito.verifyNoMoreInteractions;
374d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyarimport static org.mockito.Mockito.when;
384d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
39c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport android.arch.core.executor.AppToolkitTaskExecutor;
40c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport android.arch.lifecycle.util.InstantTaskExecutor;
41c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport android.support.annotation.Nullable;
42c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
43c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.After;
44c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.Before;
45c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.Test;
46c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.runner.RunWith;
47c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.junit.runners.JUnit4;
48c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.mockito.InOrder;
49c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarimport org.mockito.Mockito;
50c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
51c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar@SuppressWarnings({"unchecked"})
52c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar@RunWith(JUnit4.class)
53c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyarpublic class LiveDataTest {
54c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    private PublicLiveData<String> mLiveData;
55c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    private LifecycleOwner mOwner;
56c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    private LifecycleRegistry mRegistry;
57c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    private MethodExec mActiveObserversChanged;
58c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    private boolean mInObserver;
59c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
60c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @Before
61c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void init() {
62c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData = new PublicLiveData<>();
63c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mOwner = mock(LifecycleOwner.class);
64c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry = new LifecycleRegistry(mOwner);
654d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        when(mOwner.getLifecycle()).thenReturn(mRegistry);
664d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mActiveObserversChanged = mock(MethodExec.class);
67c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.activeObserversChanged = mActiveObserversChanged;
68c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mInObserver = false;
69c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
704d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
714d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    @Before
72c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void swapExecutorDelegate() {
73c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
74c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
75c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
76c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @After
77c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void removeExecutorDelegate() {
78c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        AppToolkitTaskExecutor.getInstance().setDelegate(null);
79c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
804d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
814d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    @Test
82c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void testObserverToggle() {
83c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Observer<String> observer = (Observer<String>) mock(Observer.class);
84c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, observer);
854d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
864d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        verify(mActiveObserversChanged, never()).onCall(anyBoolean());
87c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(true));
88c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(false));
89c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
904d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.removeObserver(observer);
914d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        verify(mActiveObserversChanged, never()).onCall(anyBoolean());
92c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(false));
934d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(false));
94c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
95c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
964d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    @Test
974d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    public void testActiveObserverToggle() {
98c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Observer<String> observer = (Observer<String>) mock(Observer.class);
994d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.observe(mOwner, observer);
100c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
101c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(mActiveObserversChanged, never()).onCall(anyBoolean());
1024d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mLiveData.hasObservers(), is(true));
1034d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(false));
104c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
1054d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mRegistry.handleLifecycleEvent(ON_START);
106c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(mActiveObserversChanged).onCall(true);
107c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(true));
108c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        reset(mActiveObserversChanged);
109c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
110c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_STOP);
111c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(mActiveObserversChanged).onCall(false);
112c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(false));
1134d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mLiveData.hasObservers(), is(true));
114c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
115c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        reset(mActiveObserversChanged);
116c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_START);
117c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(mActiveObserversChanged).onCall(true);
118c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(true));
119c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(true));
120c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
121c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        reset(mActiveObserversChanged);
1224d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.removeObserver(observer);
123c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(mActiveObserversChanged).onCall(false);
124c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(false));
125c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(false));
126c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
127c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verifyNoMoreInteractions(mActiveObserversChanged);
128c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
129c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
130c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @Test
131c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void testReAddSameObserverTuple() {
132c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Observer<String> observer = (Observer<String>) mock(Observer.class);
1334d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.observe(mOwner, observer);
134c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, observer);
135c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(true));
136c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
137c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
138c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @Test
139c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void testAdd2ObserversWithSameOwnerAndRemove() {
140c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Observer<String> o1 = (Observer<String>) mock(Observer.class);
141c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Observer<String> o2 = (Observer<String>) mock(Observer.class);
142c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, o1);
143c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, o2);
144c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(true));
145c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(mActiveObserversChanged, never()).onCall(anyBoolean());
146c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
147c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_START);
148c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(mActiveObserversChanged).onCall(true);
149c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.setValue("a");
150c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(o1).onChanged("a");
151c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(o2).onChanged("a");
152c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
153c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.removeObservers(mOwner);
154c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
155c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(false));
156c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mRegistry.getObserverCount(), is(0));
157c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
158c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
159c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @Test
160c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void testAddSameObserverIn2LifecycleOwners() {
161c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Observer<String> observer = (Observer<String>) mock(Observer.class);
1624d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        LifecycleOwner owner2 = mock(LifecycleOwner.class);
1634d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        LifecycleRegistry registry2 = new LifecycleRegistry(owner2);
1644d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        when(owner2.getLifecycle()).thenReturn(registry2);
1654d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
166c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, observer);
167c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Throwable throwable = null;
1684d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        try {
1694d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar            mLiveData.observe(owner2, observer);
170c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        } catch (Throwable t) {
171c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar            throwable = t;
172c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        }
173c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(throwable, instanceOf(IllegalArgumentException.class));
174c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        //noinspection ConstantConditions
175c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(throwable.getMessage(),
176c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar                is("Cannot add the same observer with different lifecycles"));
177c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
1784d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
179c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @Test
180c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void testRemoveDestroyedObserver() {
181c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Observer<String> observer = (Observer<String>) mock(Observer.class);
182c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, observer);
183c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_START);
184c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(mActiveObserversChanged).onCall(true);
185c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(true));
186c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(true));
187c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
188c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        reset(mActiveObserversChanged);
189c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
190c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_DESTROY);
191c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(false));
192c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(false));
193c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(mActiveObserversChanged).onCall(false);
194c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
195c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
196c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @Test
197c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void testInactiveRegistry() {
198c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Observer<String> observer = (Observer<String>) mock(Observer.class);
199c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_DESTROY);
200c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, observer);
201c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasObservers(), is(false));
202c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
203c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
204c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @Test
205c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void testNotifyActiveInactive() {
206c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Observer<String> observer = (Observer<String>) mock(Observer.class);
207c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_CREATE);
208c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, observer);
209c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.setValue("a");
210c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(observer, never()).onChanged(anyString());
211c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_START);
212c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(observer).onChanged("a");
213c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
214c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.setValue("b");
215c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(observer).onChanged("b");
216c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
217c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_STOP);
218c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.setValue("c");
219c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(observer, never()).onChanged("c");
220c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
221c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_START);
222c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(observer).onChanged("c");
223c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
224c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        reset(observer);
225c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_STOP);
226c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_START);
227c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(observer, never()).onChanged(anyString());
2284d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    }
2294d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
2304d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    @Test
2314d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    public void testStopObservingOwner_onDestroy() {
2324d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        Observer<String> observer = (Observer<String>) mock(Observer.class);
2334d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mRegistry.handleLifecycleEvent(ON_CREATE);
2344d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.observe(mOwner, observer);
2354d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mRegistry.getObserverCount(), is(1));
2364d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mRegistry.handleLifecycleEvent(ON_DESTROY);
2374d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mRegistry.getObserverCount(), is(0));
2384d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    }
2394d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
2404d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    @Test
2414d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    public void testStopObservingOwner_onStopObserving() {
2424d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        Observer<String> observer = (Observer<String>) mock(Observer.class);
2434d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mRegistry.handleLifecycleEvent(ON_CREATE);
2444d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.observe(mOwner, observer);
2454d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mRegistry.getObserverCount(), is(1));
2464d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
2474d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.removeObserver(observer);
2484d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mRegistry.getObserverCount(), is(0));
2494d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    }
2504d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
2514d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    @Test
2524d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    public void testActiveChangeInCallback() {
2534d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mRegistry.handleLifecycleEvent(ON_START);
2544d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        Observer<String> observer1 = spy(new Observer<String>() {
2554d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar            @Override
2564d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar            public void onChanged(@Nullable String s) {
2574d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar                mRegistry.handleLifecycleEvent(ON_STOP);
2584d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar                assertThat(mLiveData.hasObservers(), is(true));
2594d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar                assertThat(mLiveData.hasActiveObservers(), is(false));
2604d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar            }
2614d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        });
2624d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        final Observer observer2 = mock(Observer.class);
2634d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.observe(mOwner, observer1);
2644d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.observe(mOwner, observer2);
2654d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        mLiveData.setValue("bla");
2664d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        verify(observer1).onChanged(anyString());
2674d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        verify(observer2, Mockito.never()).onChanged(anyString());
2684d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mLiveData.hasObservers(), is(true));
2694d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(false));
2704d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    }
2714d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
2724d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    @Test
2734d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    public void testActiveChangeInCallback2() {
2744d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        Observer<String> observer1 = spy(new Observer<String>() {
2754d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar            @Override
2764d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar            public void onChanged(@Nullable String s) {
2774d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar                assertThat(mInObserver, is(false));
2784d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar                mInObserver = true;
2794d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar                mRegistry.handleLifecycleEvent(ON_START);
280c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar                assertThat(mLiveData.hasActiveObservers(), is(true));
281c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar                mInObserver = false;
282c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar            }
283c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        });
284c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        final Observer observer2 = spy(new FailReentranceObserver());
285c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observeForever(observer1);
286c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, observer2);
287c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.setValue("bla");
288c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(observer1).onChanged(anyString());
289c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(observer2).onChanged(anyString());
2904d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        assertThat(mLiveData.hasObservers(), is(true));
291c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        assertThat(mLiveData.hasActiveObservers(), is(true));
2924d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    }
293c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
294c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @Test
295c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public void testObserverRemovalInCallback() {
296c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mRegistry.handleLifecycleEvent(ON_START);
2974d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar        Observer<String> observer = spy(new Observer<String>() {
2984d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar            @Override
2994d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar            public void onChanged(@Nullable String s) {
300c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar                assertThat(mLiveData.hasObservers(), is(true));
301c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar                mLiveData.removeObserver(this);
302c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar                assertThat(mLiveData.hasObservers(), is(false));
303c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar            }
304c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        });
305c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.observe(mOwner, observer);
306c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        mLiveData.setValue("bla");
307c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        verify(observer).onChanged(anyString());
308        assertThat(mLiveData.hasObservers(), is(false));
309    }
310
311    @Test
312    public void testObserverAdditionInCallback() {
313        mRegistry.handleLifecycleEvent(ON_START);
314        final Observer observer2 = spy(new FailReentranceObserver());
315        Observer<String> observer1 = spy(new Observer<String>() {
316            @Override
317            public void onChanged(@Nullable String s) {
318                assertThat(mInObserver, is(false));
319                mInObserver = true;
320                mLiveData.observe(mOwner, observer2);
321                assertThat(mLiveData.hasObservers(), is(true));
322                assertThat(mLiveData.hasActiveObservers(), is(true));
323                mInObserver = false;
324            }
325        });
326        mLiveData.observe(mOwner, observer1);
327        mLiveData.setValue("bla");
328        verify(observer1).onChanged(anyString());
329        verify(observer2).onChanged(anyString());
330        assertThat(mLiveData.hasObservers(), is(true));
331        assertThat(mLiveData.hasActiveObservers(), is(true));
332    }
333
334    @Test
335    public void testObserverWithoutLifecycleOwner() {
336        Observer<String> observer = (Observer<String>) mock(Observer.class);
337        mLiveData.setValue("boring");
338        mLiveData.observeForever(observer);
339        verify(mActiveObserversChanged).onCall(true);
340        verify(observer).onChanged("boring");
341        mLiveData.setValue("tihs");
342        verify(observer).onChanged("tihs");
343        mLiveData.removeObserver(observer);
344        verify(mActiveObserversChanged).onCall(false);
345        mLiveData.setValue("boring");
346        reset(observer);
347        verify(observer, never()).onChanged(anyString());
348    }
349
350    @Test
351    public void testSetValueDuringSetValue() {
352        mRegistry.handleLifecycleEvent(ON_START);
353        final Observer observer1 = spy(new Observer<String>() {
354            @Override
355            public void onChanged(String o) {
356                assertThat(mInObserver, is(false));
357                mInObserver = true;
358                if (o.equals(("bla"))) {
359                    mLiveData.setValue("gt");
360                }
361                mInObserver = false;
362            }
363        });
364        final Observer observer2 = spy(new FailReentranceObserver());
365        mLiveData.observe(mOwner, observer1);
366        mLiveData.observe(mOwner, observer2);
367        mLiveData.setValue("bla");
368        verify(observer1, Mockito.atMost(2)).onChanged("gt");
369        verify(observer2, Mockito.atMost(2)).onChanged("gt");
370    }
371
372    @Test
373    public void testRemoveDuringSetValue() {
374        mRegistry.handleLifecycleEvent(ON_START);
375        final Observer observer1 = spy(new Observer<String>() {
376            @Override
377            public void onChanged(String o) {
378                mLiveData.removeObserver(this);
379            }
380        });
381        Observer<String> observer2 = (Observer<String>) mock(Observer.class);
382        mLiveData.observeForever(observer1);
383        mLiveData.observe(mOwner, observer2);
384        mLiveData.setValue("gt");
385        verify(observer2).onChanged("gt");
386    }
387
388    @Test
389    public void testDataChangeDuringStateChange() {
390        mRegistry.handleLifecycleEvent(ON_START);
391        mRegistry.addObserver(new LifecycleObserver() {
392            @OnLifecycleEvent(ON_STOP)
393            public void onStop() {
394                // change data in onStop, observer should not be called!
395                mLiveData.setValue("b");
396            }
397        });
398        Observer<String> observer = (Observer<String>) mock(Observer.class);
399        mLiveData.setValue("a");
400        mLiveData.observe(mOwner, observer);
401        verify(observer).onChanged("a");
402        mRegistry.handleLifecycleEvent(ON_PAUSE);
403        mRegistry.handleLifecycleEvent(ON_STOP);
404        verify(observer, never()).onChanged("b");
405
406        mRegistry.handleLifecycleEvent(ON_RESUME);
407        verify(observer).onChanged("b");
408    }
409
410    @Test
411    public void testNotCallInactiveWithObserveForever() {
412        mRegistry.handleLifecycleEvent(ON_START);
413        Observer<String> observer = (Observer<String>) mock(Observer.class);
414        Observer<String> observer2 = (Observer<String>) mock(Observer.class);
415        mLiveData.observe(mOwner, observer);
416        mLiveData.observeForever(observer2);
417        verify(mActiveObserversChanged).onCall(true);
418        reset(mActiveObserversChanged);
419        mRegistry.handleLifecycleEvent(ON_STOP);
420        verify(mActiveObserversChanged, never()).onCall(anyBoolean());
421        mRegistry.handleLifecycleEvent(ON_START);
422        verify(mActiveObserversChanged, never()).onCall(anyBoolean());
423    }
424
425    @Test
426    public void testRemoveDuringAddition() {
427        mRegistry.handleLifecycleEvent(ON_START);
428        mLiveData.setValue("bla");
429        mLiveData.observeForever(new Observer<String>() {
430            @Override
431            public void onChanged(@Nullable String s) {
432                mLiveData.removeObserver(this);
433            }
434        });
435        assertThat(mLiveData.hasActiveObservers(), is(false));
436        InOrder inOrder = Mockito.inOrder(mActiveObserversChanged);
437        inOrder.verify(mActiveObserversChanged).onCall(true);
438        inOrder.verify(mActiveObserversChanged).onCall(false);
439        inOrder.verifyNoMoreInteractions();
440    }
441
442    @Test
443    public void testRemoveDuringBringingUpToState() {
444        mLiveData.setValue("bla");
445        mLiveData.observeForever(new Observer<String>() {
446            @Override
447            public void onChanged(@Nullable String s) {
448                mLiveData.removeObserver(this);
449            }
450        });
451        mRegistry.handleLifecycleEvent(ON_RESUME);
452        assertThat(mLiveData.hasActiveObservers(), is(false));
453        InOrder inOrder = Mockito.inOrder(mActiveObserversChanged);
454        inOrder.verify(mActiveObserversChanged).onCall(true);
455        inOrder.verify(mActiveObserversChanged).onCall(false);
456        inOrder.verifyNoMoreInteractions();
457    }
458
459    @SuppressWarnings("WeakerAccess")
460    static class PublicLiveData<T> extends LiveData<T> {
461        // cannot spy due to internal calls
462        public MethodExec activeObserversChanged;
463
464        @Override
465        protected void onActive() {
466            if (activeObserversChanged != null) {
467                activeObserversChanged.onCall(true);
468            }
469        }
470
471        @Override
472        protected void onInactive() {
473            if (activeObserversChanged != null) {
474                activeObserversChanged.onCall(false);
475            }
476        }
477    }
478
479    private class FailReentranceObserver<T> implements Observer<T> {
480        @Override
481        public void onChanged(@Nullable T t) {
482            assertThat(mInObserver, is(false));
483        }
484    }
485
486    interface MethodExec {
487        void onCall(boolean value);
488    }
489}
490