LoaderInfoTest.java revision ba069d50913c3fb250bb60ec310439db36895337
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
17package androidx.loader.app;
18
19import static org.junit.Assert.assertFalse;
20import static org.junit.Assert.assertTrue;
21import static org.mockito.Mockito.mock;
22import static org.mockito.Mockito.when;
23
24import android.content.Context;
25import android.support.test.annotation.UiThreadTest;
26import android.support.test.filters.SmallTest;
27import android.support.test.rule.ActivityTestRule;
28import android.support.test.runner.AndroidJUnit4;
29
30import androidx.lifecycle.Lifecycle;
31import androidx.lifecycle.LifecycleOwner;
32import androidx.lifecycle.LifecycleRegistry;
33import androidx.loader.app.test.DelayLoader;
34import androidx.loader.app.test.DummyLoaderCallbacks;
35import androidx.loader.app.test.EmptyActivity;
36import androidx.loader.content.Loader;
37
38import org.junit.Before;
39import org.junit.Rule;
40import org.junit.Test;
41import org.junit.runner.RunWith;
42
43import java.util.concurrent.CountDownLatch;
44import java.util.concurrent.TimeUnit;
45
46@RunWith(AndroidJUnit4.class)
47@SmallTest
48public class LoaderInfoTest {
49
50    private LifecycleOwner mOwner;
51    private LifecycleRegistry mRegistry;
52
53    @Before
54    public void setup() {
55        mOwner = mock(LifecycleOwner.class);
56        mRegistry = new LifecycleRegistry(mOwner);
57        when(mOwner.getLifecycle()).thenReturn(mRegistry);
58        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
59        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
60    }
61
62    @Rule
63    public ActivityTestRule<EmptyActivity> mActivityRule =
64            new ActivityTestRule<>(EmptyActivity.class);
65
66    @Test
67    public void testIsCallbackWaitingForData() throws Throwable {
68        final DummyLoaderCallbacks loaderCallback = new DummyLoaderCallbacks(mock(Context.class));
69        final CountDownLatch deliverResultLatch = new CountDownLatch(1);
70        Loader<Boolean> delayLoader = new DelayLoader(mActivityRule.getActivity(),
71                deliverResultLatch);
72        final LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
73                0, null, delayLoader, null);
74        assertFalse("isCallbackWaitingForData should be false before setCallback",
75                loaderInfo.isCallbackWaitingForData());
76
77        mActivityRule.runOnUiThread(new Runnable() {
78            @Override
79            public void run() {
80                loaderInfo.setCallback(mActivityRule.getActivity(), loaderCallback);
81            }
82        });
83        assertTrue("isCallbackWaitingForData should be true immediately after setCallback",
84                loaderInfo.isCallbackWaitingForData());
85
86        assertTrue("Loader timed out delivering results",
87                deliverResultLatch.await(1, TimeUnit.SECONDS));
88        // Results are posted to the UI thread, so we wait for them there
89        mActivityRule.runOnUiThread(new Runnable() {
90            @Override
91            public void run() {
92                assertTrue("onLoadFinished should be called after setCallback",
93                        loaderCallback.mOnLoadFinished);
94                assertFalse("isCallbackWaitingForData should be false after onLoadFinished",
95                        loaderInfo.isCallbackWaitingForData());
96            }
97        });
98    }
99
100    @UiThreadTest
101    @Test
102    public void testSetCallback() throws Throwable {
103        final DummyLoaderCallbacks loaderCallback = new DummyLoaderCallbacks(mock(Context.class));
104        Loader<Boolean> loader = loaderCallback.onCreateLoader(0, null);
105        final LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
106                0, null, loader, null);
107        assertFalse("onLoadFinished shouldn't be called before setCallback",
108                loaderCallback.mOnLoadFinished);
109
110        loaderInfo.setCallback(mActivityRule.getActivity(), loaderCallback);
111        assertTrue("onLoadFinished should be called after setCallback",
112                loaderCallback.mOnLoadFinished);
113    }
114
115    @UiThreadTest
116    @Test
117    public void testSetCallback_replace() throws Throwable {
118        final DummyLoaderCallbacks initialCallback = new DummyLoaderCallbacks(mock(Context.class));
119        Loader<Boolean> loader = initialCallback.onCreateLoader(0, null);
120        LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
121                0, null, loader, null);
122        assertFalse("onLoadFinished for initial shouldn't be called before setCallback initial",
123                initialCallback.mOnLoadFinished);
124
125        loaderInfo.setCallback(mActivityRule.getActivity(), initialCallback);
126        assertTrue("onLoadFinished for initial should be called after setCallback initial",
127                initialCallback.mOnLoadFinished);
128
129        final DummyLoaderCallbacks replacementCallback =
130                new DummyLoaderCallbacks(mActivityRule.getActivity());
131        initialCallback.mOnLoadFinished = false;
132
133        loaderInfo.setCallback(mActivityRule.getActivity(), replacementCallback);
134        assertFalse("onLoadFinished for initial should not be called "
135                        + "after setCallback replacement",
136                initialCallback.mOnLoadFinished);
137        assertTrue("onLoadFinished for replacement should be called "
138                        + " after setCallback replacement",
139                replacementCallback.mOnLoadFinished);
140    }
141
142    @UiThreadTest
143    @Test
144    public void testMarkForRedelivery() throws Throwable {
145        DummyLoaderCallbacks loaderCallback =
146                new DummyLoaderCallbacks(mock(Context.class));
147        Loader<Boolean> loader = loaderCallback.onCreateLoader(0, null);
148        LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
149                0, null, loader, null);
150        loaderInfo.setCallback(mOwner, loaderCallback);
151        assertTrue("onLoadFinished should be called after setCallback",
152                loaderCallback.mOnLoadFinished);
153
154        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
155        loaderCallback.mOnLoadFinished = false;
156        loaderInfo.markForRedelivery();
157        assertFalse("onLoadFinished should not be called when stopped after markForRedelivery",
158                loaderCallback.mOnLoadFinished);
159
160        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
161        assertTrue("onLoadFinished should be called after markForRedelivery",
162                loaderCallback.mOnLoadFinished);
163    }
164
165    @UiThreadTest
166    @Test
167    public void testMarkForRedelivery_replace() throws Throwable {
168        DummyLoaderCallbacks initialCallback =
169                new DummyLoaderCallbacks(mock(Context.class));
170        Loader<Boolean> loader = initialCallback.onCreateLoader(0, null);
171        LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
172                0, null, loader, null);
173        loaderInfo.setCallback(mOwner, initialCallback);
174        assertTrue("onLoadFinished for initial should be called after setCallback initial",
175                initialCallback.mOnLoadFinished);
176
177        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
178        initialCallback.mOnLoadFinished = false;
179        loaderInfo.markForRedelivery();
180        assertFalse("onLoadFinished should not be called when stopped after markForRedelivery",
181                initialCallback.mOnLoadFinished);
182
183        // Replace the callback
184        final DummyLoaderCallbacks replacementCallback =
185                new DummyLoaderCallbacks(mock(Context.class));
186        loaderInfo.setCallback(mOwner, replacementCallback);
187
188        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
189        assertFalse("onLoadFinished for initial should not be called "
190                        + "after setCallback replacement",
191                initialCallback.mOnLoadFinished);
192        assertTrue("onLoadFinished for replacement should be called "
193                        + " after setCallback replacement",
194                replacementCallback.mOnLoadFinished);
195    }
196
197    @UiThreadTest
198    @Test
199    public void testDestroy() throws Throwable {
200        final DummyLoaderCallbacks loaderCallback = new DummyLoaderCallbacks(mock(Context.class));
201        final Loader<Boolean> loader = loaderCallback.onCreateLoader(0, null);
202        final LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
203                0, null, loader, null);
204
205        loaderInfo.setCallback(mActivityRule.getActivity(), loaderCallback);
206        assertTrue("Loader should be started after setCallback", loader.isStarted());
207        loaderInfo.destroy(true);
208        assertFalse("Loader should not be started after destroy", loader.isStarted());
209    }
210}
211