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