1c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay/*
2c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Copyright (C) 2017 The Android Open Source Project
3c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *
4c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Licensed under the Apache License, Version 2.0 (the "License");
5c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * you may not use this file except in compliance with the License.
6c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * You may obtain a copy of the License at
7c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *
8c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *      http://www.apache.org/licenses/LICENSE-2.0
9c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *
10c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Unless required by applicable law or agreed to in writing, software
11c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * distributed under the License is distributed on an "AS IS" BASIS,
12c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * See the License for the specific language governing permissions and
14c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * limitations under the License.
15c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */
16c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.contentpager.content;
18c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.contentpager.content.ContentPager.createArgs;
20ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.contentpager.content.TestContentProvider.PAGED_URI;
21ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.contentpager.content.TestContentProvider.PAGED_WINDOWED_URI;
22ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.contentpager.content.TestContentProvider.UNPAGED_URI;
23c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
24fa39e2bca1b284ad7c931d9194287770b7b507faAurimas Liutikasimport static org.junit.Assert.assertEquals;
25c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport static org.junit.Assert.assertFalse;
26fa39e2bca1b284ad7c931d9194287770b7b507faAurimas Liutikasimport static org.junit.Assert.assertNotNull;
27fa39e2bca1b284ad7c931d9194287770b7b507faAurimas Liutikasimport static org.junit.Assert.assertTrue;
28c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
29c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.app.Activity;
30c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.content.ContentResolver;
31c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.database.Cursor;
32c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.net.Uri;
33c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.os.Bundle;
34c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.os.Handler;
35c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.os.Looper;
36c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.support.test.filters.MediumTest;
37c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.support.test.rule.ActivityTestRule;
38c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.support.test.runner.AndroidJUnit4;
39c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
40fb4b6f71b6a30ea0acc67fce323853e4beb096d7Aurimas Liutikasimport androidx.annotation.Nullable;
41fb4b6f71b6a30ea0acc67fce323853e4beb096d7Aurimas Liutikasimport androidx.contentpager.content.ContentPager.ContentCallback;
42fb4b6f71b6a30ea0acc67fce323853e4beb096d7Aurimas Liutikas
43c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport org.junit.Before;
44c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport org.junit.Rule;
45c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport org.junit.Test;
46c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport org.junit.runner.RunWith;
47c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
48c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport java.util.Arrays;
49c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport java.util.HashMap;
50c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport java.util.List;
51c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport java.util.Map;
52c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport java.util.concurrent.TimeUnit;
53c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
54c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay@MediumTest
55c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay@RunWith(AndroidJUnit4.class)
56c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKaypublic class ContentPagerTest {
57c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
58c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private ContentResolver mResolver;
59c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private TestQueryRunner mRunner;
60c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private TestContentCallback mCallback;
61c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private ContentPager mPager;
62c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
63c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Rule
64c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public ActivityTestRule<Activity> mActivityRule = new ActivityTestRule(TestActivity.class);
65c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
66c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Before
67c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void setUp() {
68c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mRunner = new TestQueryRunner();
69c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mResolver = mActivityRule.getActivity().getContentResolver();
70c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback = new TestContentCallback();
71c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mPager = new ContentPager(mResolver, mRunner);
72c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
73c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
74c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Test
75c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void testRelaysProviderPagedResults() throws Throwable {
76c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        int offset = 0;
77c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        int limit = 10;
78c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
79c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // NOTE: Paging on Android O is accompolished by way of ContentResolver#query that
80c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // accepts a Bundle. That means on older platforms we either have to cook up
81c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // a special way of paging that doesn't use the bundle (that's what we do here)
82c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // or we simply skip testing how we deal with provider paged results.
83c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Uri uriWithTestPagingData = TestContentProvider.forcePagingSpec(PAGED_URI, offset, limit);
84c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
85c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Query query = mPager.query(
86c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                uriWithTestPagingData,
87c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
88c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(offset, limit),
89c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
90c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
91c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
92c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertNumPagesLoaded(1);
93c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertPageLoaded(query);
94c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Cursor cursor = mCallback.getCursor(query);
95c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Bundle extras = cursor.getExtras();
96c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
97c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertExpectedRecords(cursor, query.getOffset());
98c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
99c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
100c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentPager.CURSOR_DISPOSITION_PAGED,
101c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.CURSOR_DISPOSITION, -1));
102c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
103c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
104c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                TestContentProvider.DEFAULT_RECORD_COUNT,
105c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentResolver.EXTRA_TOTAL_COUNT));
106c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
107c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertHasHonoredArgs(
108c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras,
109c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_LIMIT,
110c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_OFFSET);
111c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
112c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
113c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
114c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_PROVIDER_PAGED));
115c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
116c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
117c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_RESOLVED_QUERIES));
118c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
119c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
120c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_TOTAL_QUERIES));
121c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
122c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
123c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Test
124c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void testLimitsPagedResultsToWindowSize() throws Throwable {
125c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        int offset = 0;
126c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        int limit = 10;
127c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
128c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // NOTE: Paging on Android O is accompolished by way of ContentResolver#query that
129c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // accepts a Bundle. That means on older platforms we either have to cook up
130c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // a special way of paging that doesn't use the bundle (that's what we do here)
131c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // or we simply skip testing how we deal with provider paged results.
132c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Uri uriWithTestPagingData = TestContentProvider.forcePagingSpec(
133c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                PAGED_WINDOWED_URI, offset, limit);
134c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
135c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Query query = mPager.query(
136c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                uriWithTestPagingData,
137c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
138c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(offset, limit),
139c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
140c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
141c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
142c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertNumPagesLoaded(1);
143c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertPageLoaded(query);
144c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Cursor cursor = mCallback.getCursor(query);
145c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Bundle extras = cursor.getExtras();
146c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
147c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertExpectedRecords(cursor, query.getOffset());
148c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
149c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
150c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentPager.CURSOR_DISPOSITION_REPAGED,
151c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.CURSOR_DISPOSITION, -1));
152c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
153c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
154c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                TestContentProvider.DEFAULT_RECORD_COUNT,
155c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentResolver.EXTRA_TOTAL_COUNT));
156c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
157c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
158c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(limit, extras.getInt(ContentPager.EXTRA_REQUESTED_LIMIT));
159c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
160c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(7, extras.getInt(ContentPager.EXTRA_SUGGESTED_LIMIT));
161c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
162c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertHasHonoredArgs(
163c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras,
164c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_LIMIT,
165c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_OFFSET);
166c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
167c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
168c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
169c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_PROVIDER_PAGED));
170c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
171c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
172c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_RESOLVED_QUERIES));
173c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
174c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
175c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_TOTAL_QUERIES));
176c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
177c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
178c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Test
179c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void testAdaptsUnpagedToPaged() throws Throwable {
180c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Query query = mPager.query(
181c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                UNPAGED_URI,
182c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
183c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(0, 10),
184c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
185c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
186c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
187c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertNumPagesLoaded(1);
188c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertPageLoaded(query);
189c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Cursor cursor = mCallback.getCursor(query);
190c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Bundle extras = cursor.getExtras();
191c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
192c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertExpectedRecords(cursor, query.getOffset());
193c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
194c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
195c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentPager.CURSOR_DISPOSITION_COPIED,
196c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.CURSOR_DISPOSITION));
197c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
198c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
199c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                TestContentProvider.DEFAULT_RECORD_COUNT,
200c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentResolver.EXTRA_TOTAL_COUNT));
201c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
202c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertHasHonoredArgs(
203c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras,
204c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_LIMIT,
205c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_OFFSET);
206c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
207c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
208c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
209c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_COMPAT_PAGED));
210c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
211c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
212c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_RESOLVED_QUERIES));
213c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
214c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
215c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_TOTAL_QUERIES));
216c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
217c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
218c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Test
219c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void testCachesUnpagedCursor() throws Throwable {
220c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mPager.query(
221c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                UNPAGED_URI,
222c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
223c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(0, 10),
224c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
225c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
226c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
227c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mPager.query(
228c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                UNPAGED_URI,
229c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
230c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(10, 10),
231c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
232c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
233c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
234c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // Rerun the same query as the first...extra exercise to ensure we can return
235c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // to previously loaded results.
236c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Query query = mPager.query(
237c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                UNPAGED_URI,
238c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
239c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(0, 10),
240c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
241c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
242c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
243c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertNumPagesLoaded(3);
244c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Cursor cursor = mCallback.getCursor(query);
245c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Bundle extras = cursor.getExtras();
246c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
247c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
248c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                3,
249c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_COMPAT_PAGED));
250c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
251c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
252c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_RESOLVED_QUERIES));
253c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
254c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                3,
255c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_TOTAL_QUERIES));
256c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
257c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
258c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Test
259c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void testWrapsCursorsThatJustHappenToFitInPageRange() throws Throwable {
260c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
261c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // NOTE: Paging on Android O is accompolished by way of ContentResolver#query that
262c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // accepts a Bundle. That means on older platforms we either have to cook up
263c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // a special way of paging that doesn't use the bundle (that's what we do here)
264c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // or we simply skip testing how we deal with provider paged results.
265c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Uri uri = TestContentProvider.forceRecordCount(UNPAGED_URI, 22);
266c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
267c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Query query = mPager.query(
268c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                uri,
269c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
270c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(0, 44),
271c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
272c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
273c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
274c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertNumPagesLoaded(1);
275c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // mCallback.assertPageLoaded(pageId);
276c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertPageLoaded(query);
277c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Cursor cursor = mCallback.getCursor(query);
278c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Bundle extras = cursor.getExtras();
279c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
280c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertExpectedRecords(cursor, query.getOffset());
281c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
282c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
283c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentPager.CURSOR_DISPOSITION_WRAPPED,
284c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.CURSOR_DISPOSITION));
285c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
286c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
287c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                22,
288c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentResolver.EXTRA_TOTAL_COUNT));
289c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
290c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertHasHonoredArgs(
291c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras,
292c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_LIMIT,
293c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_OFFSET);
294c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
295c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
296c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
297c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_COMPAT_PAGED));
298c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
299c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
300c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_RESOLVED_QUERIES));
301c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
302c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
303c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_TOTAL_QUERIES));
304c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
305c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
306c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Test
307c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void testCorrectlyCopiesRecords_EndOfResults() throws Throwable {
308c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // finally, check the last page.
309c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        int limit = 100;
310c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        // This will be the size of the last page. Should be 67.
311c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        int leftOvers = TestContentProvider.DEFAULT_RECORD_COUNT % limit;
312c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        int offset = TestContentProvider.DEFAULT_RECORD_COUNT - leftOvers;
313c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
314c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Query query = mPager.query(
315c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                UNPAGED_URI,
316c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
317c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(offset, limit),
318c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
319c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
320c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
321c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertNumPagesLoaded(1);
322c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mCallback.assertPageLoaded(query);
323c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Cursor cursor = mCallback.getCursor(query);
324c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(leftOvers, cursor.getCount());
325c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Bundle extras = cursor.getExtras();
326c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
327c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertExpectedRecords(cursor, query.getOffset());
328c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
329c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
330c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentPager.CURSOR_DISPOSITION_COPIED,
331c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.CURSOR_DISPOSITION));
332c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
333c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertHasHonoredArgs(
334c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras,
335c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_LIMIT,
336c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                ContentResolver.QUERY_ARG_OFFSET);
337c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
338c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
339c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
340c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_COMPAT_PAGED));
341c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
342c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
343c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_RESOLVED_QUERIES));
344c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertEquals(
345c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                1,
346c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getInt(ContentPager.Stats.EXTRA_TOTAL_QUERIES));
347c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
348c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
349c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Test
350c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void testCancelsRunningQueriesOnReset() throws Throwable {
351c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mRunner.runQuery = false;
352c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Query query = mPager.query(
353c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                UNPAGED_URI,
354c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
355c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(0, 10),
356c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
357c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
358c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
359c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertTrue(mRunner.isRunning(query));
360c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
361c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mPager.reset();
362c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
363c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertFalse(mRunner.isRunning(query));
364c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
365c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
366c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    @Test
367c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    public void testRelaysContentChangeNotificationsOnPagedCursors() throws Throwable {
368c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
369c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        TestContentObserver observer = new TestContentObserver(
370c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                new Handler(Looper.getMainLooper()));
371c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        observer.expectNotifications(1);
372c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
373c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Query query = mPager.query(
374c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                UNPAGED_URI,
375c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
376c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                createArgs(10, 99),
377c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                null,
378c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                mCallback);
379c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
380c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        Cursor cursor = mCallback.getCursor(query);
381c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        cursor.registerContentObserver(observer);
382c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
383c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        mResolver.notifyChange(UNPAGED_URI, null);
384c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
385c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        assertTrue(observer.mNotifiedLatch.await(1000, TimeUnit.MILLISECONDS));
386c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
387c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
388c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private void assertExpectedRecords(Cursor cursor, int offset) {
389c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        for (int row = 0; row < cursor.getCount(); row++) {
390c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            assertTrue(cursor.moveToPosition(row));
391c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            int unpagedRow = offset + row;
392c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            for (int column = 0; column < cursor.getColumnCount(); column++) {
393c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                TestContentProvider.assertExpectedCellValue(cursor, unpagedRow, column);
394c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            }
395c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        }
396c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
397c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
398c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private static void assertHasHonoredArgs(Bundle extras, String... expectedArgs) {
399c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        List<String> honored = Arrays.asList(
400c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay                extras.getStringArray(ContentResolver.EXTRA_HONORED_ARGS));
401c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
402c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        for (String arg : expectedArgs) {
403c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            assertTrue(honored.contains(arg));
404c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        }
405c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
406c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
407c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    private static final class TestContentCallback implements ContentCallback {
408c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
409c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        private int mPagesLoaded;
410c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        private Map<Query, Cursor> mCursors = new HashMap<>();
411c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
412c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        @Override
413c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        public void onCursorReady(Query query, Cursor cursor) {
414c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            mPagesLoaded++;
415c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            mCursors.put(query, cursor);
416c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        }
417c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
418c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        private void assertPageLoaded(Query query) {
419c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            assertTrue(mCursors.containsKey(query));
420c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            assertNotNull(mCursors.get(query));
421c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        }
422c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
423c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        private void assertNumPagesLoaded(int expected) {
424c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            assertEquals(expected, mPagesLoaded);
425c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        }
426c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay
427c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        private @Nullable Cursor getCursor(Query query) {
428c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay            return mCursors.get(query);
429c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay        }
430c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay    }
431c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay}
432