19fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik/*
29fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * Copyright (C) 2017 The Android Open Source Project
39fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik *
49fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
59fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * you may not use this file except in compliance with the License.
69fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * You may obtain a copy of the License at
79fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik *
89fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
99fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik *
109fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * Unless required by applicable law or agreed to in writing, software
119fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
129fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * See the License for the specific language governing permissions and
149fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik * limitations under the License.
159fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik */
169fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
17ba069d50913c3fb250bb60ec310439db36895337Alan Viverettepackage androidx.room.integration.testapp.paging;
189fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
199fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport static org.hamcrest.CoreMatchers.is;
209fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport static org.hamcrest.CoreMatchers.notNullValue;
219fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport static org.hamcrest.CoreMatchers.nullValue;
229fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport static org.hamcrest.MatcherAssert.assertThat;
231b805d37217a328107a7ad021c877d3c224e5869Chris Craikimport static org.junit.Assert.assertNotNull;
249fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
259fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport android.support.test.filters.LargeTest;
269fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport android.support.test.runner.AndroidJUnit4;
279fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
28ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.annotation.Nullable;
29ddee2b5170ae257a7b2494f8aaa8459ebed806dcAurimas Liutikasimport androidx.arch.core.executor.ArchTaskExecutor;
30ddee2b5170ae257a7b2494f8aaa8459ebed806dcAurimas Liutikasimport androidx.arch.core.executor.testing.CountingTaskExecutorRule;
31ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.Lifecycle;
32ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.LifecycleOwner;
33ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.LifecycleRegistry;
34ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.LiveData;
35ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.Observer;
36ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.paging.DataSource;
37ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.paging.LivePagedListBuilder;
38ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.paging.PagedList;
39ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.integration.testapp.test.TestDatabaseTest;
40ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.integration.testapp.test.TestUtil;
41ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.integration.testapp.vo.Pet;
42ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.integration.testapp.vo.User;
43ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.integration.testapp.vo.UserAndAllPets;
44ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.sqlite.db.SimpleSQLiteQuery;
45ba069d50913c3fb250bb60ec310439db36895337Alan Viverette
469fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport org.junit.Rule;
479fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport org.junit.Test;
489fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport org.junit.runner.RunWith;
499fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
501b805d37217a328107a7ad021c877d3c224e5869Chris Craikimport java.util.Arrays;
511b805d37217a328107a7ad021c877d3c224e5869Chris Craikimport java.util.Collections;
529fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport java.util.concurrent.ExecutionException;
539fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport java.util.concurrent.FutureTask;
549fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport java.util.concurrent.TimeUnit;
559fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craikimport java.util.concurrent.TimeoutException;
569fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
5767077406223e49eba5ecd0def10ca80dd6909f16Chris Craik@LargeTest
589fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik@RunWith(AndroidJUnit4.class)
5967077406223e49eba5ecd0def10ca80dd6909f16Chris Craikpublic class DataSourceFactoryTest extends TestDatabaseTest {
609fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    @Rule
619fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    public CountingTaskExecutorRule mExecutorRule = new CountingTaskExecutorRule();
62e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar
6367077406223e49eba5ecd0def10ca80dd6909f16Chris Craik    private interface LivePagedListFactory {
6467077406223e49eba5ecd0def10ca80dd6909f16Chris Craik        LiveData<PagedList<User>> create();
6567077406223e49eba5ecd0def10ca80dd6909f16Chris Craik    }
6667077406223e49eba5ecd0def10ca80dd6909f16Chris Craik
679fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    @Test
6824418e9aafa6ae3128ae47cf7087eda46dae4f5dChris Craik    public void getUsersAsPagedList()
699fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            throws InterruptedException, ExecutionException, TimeoutException {
70dc60cacc66972b47f27acdf727332878ce5958aeChris Craik        validateUsersAsPagedList(() -> new LivePagedListBuilder<>(
71dc60cacc66972b47f27acdf727332878ce5958aeChris Craik                mUserDao.loadPagedByAge(3),
72dc60cacc66972b47f27acdf727332878ce5958aeChris Craik                new PagedList.Config.Builder()
73dc60cacc66972b47f27acdf727332878ce5958aeChris Craik                        .setPageSize(10)
74dc60cacc66972b47f27acdf727332878ce5958aeChris Craik                        .setPrefetchDistance(1)
75dc60cacc66972b47f27acdf727332878ce5958aeChris Craik                        .setInitialLoadSizeHint(10).build())
76dc60cacc66972b47f27acdf727332878ce5958aeChris Craik                .build());
7767077406223e49eba5ecd0def10ca80dd6909f16Chris Craik    }
7867077406223e49eba5ecd0def10ca80dd6909f16Chris Craik
79cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar    @Test
80cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar    public void getUsersAsPagedList_ViaRawQuery_WithObservable()
81cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar            throws InterruptedException, ExecutionException, TimeoutException {
82cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar        SimpleSQLiteQuery query = new SimpleSQLiteQuery(
83cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar                "SELECT * FROM user where mAge > ?",
84cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar                new Object[]{3});
85cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar        validateUsersAsPagedList(() -> new LivePagedListBuilder<>(
86cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar                mUserDao.loadPagedByAgeWithObserver(query),
87cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar                new PagedList.Config.Builder()
88cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar                        .setPageSize(10)
89cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar                        .setPrefetchDistance(1)
90cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar                        .setInitialLoadSizeHint(10).build())
91cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar                .build());
92cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar    }
93cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar
94cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar    private void validateUsersAsPagedList(
95cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar            LivePagedListFactory factory)
9667077406223e49eba5ecd0def10ca80dd6909f16Chris Craik            throws InterruptedException, ExecutionException, TimeoutException {
979fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        mDatabase.beginTransaction();
989fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        try {
999fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            for (int i = 0; i < 100; i++) {
1009fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik                final User user = TestUtil.createUser(i + 1);
1019fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik                user.setAge(i);
1029fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik                mUserDao.insert(user);
1039fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            }
1049fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            mDatabase.setTransactionSuccessful();
1059fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        } finally {
1069fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            mDatabase.endTransaction();
1079fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        }
1089fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        assertThat(mUserDao.count(), is(100));
10967077406223e49eba5ecd0def10ca80dd6909f16Chris Craik
11067077406223e49eba5ecd0def10ca80dd6909f16Chris Craik        final LiveData<PagedList<User>> livePagedUsers = factory.create();
1119fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
1129fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        final TestLifecycleOwner testOwner = new TestLifecycleOwner();
1139fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        testOwner.handleEvent(Lifecycle.Event.ON_CREATE);
1149fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        drain();
11524418e9aafa6ae3128ae47cf7087eda46dae4f5dChris Craik        PagedListObserver<User> observer = new PagedListObserver<>();
1169fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
1179fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        observe(livePagedUsers, testOwner, observer);
1189fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        assertThat(observer.get(), nullValue());
1199fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        observer.reset();
1209fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
1219fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        testOwner.handleEvent(Lifecycle.Event.ON_START);
1229fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        drain();
1239fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
1247d2309c06787d20bafe9582e1f47d106b624ab59Yuichi Araki        final PagedList<User> pagedList1 = observer.get();
12524418e9aafa6ae3128ae47cf7087eda46dae4f5dChris Craik        assertThat(pagedList1, is(notNullValue()));
1269fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
12724418e9aafa6ae3128ae47cf7087eda46dae4f5dChris Craik        assertThat(pagedList1.size(), is(96));
128e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        assertThat(getAndLoad(pagedList1, 20), is(nullValue()));
1299fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        drain();
130e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        assertThat(getAndLoad(pagedList1, 31), nullValue());
131e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        assertThat(getAndLoad(pagedList1, 20), notNullValue());
132e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        assertThat(getAndLoad(pagedList1, 16), notNullValue());
1339fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
1349fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        drain();
135e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        assertThat(getAndLoad(pagedList1, 31), notNullValue());
136e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        assertThat(getAndLoad(pagedList1, 50), nullValue());
1379fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        drain();
138e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        assertThat(getAndLoad(pagedList1, 50), notNullValue());
1399fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        observer.reset();
1409fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        // now invalidate the database but don't get the new paged list
1419fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        mUserDao.updateById(50, "foo");
1427d2309c06787d20bafe9582e1f47d106b624ab59Yuichi Araki        drain(); // Sync with InvalidationTracker
143e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        assertThat(getAndLoad(pagedList1, 70), nullValue());
1449fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        drain();
145e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        assertThat(getAndLoad(pagedList1, 70), nullValue());
1467d2309c06787d20bafe9582e1f47d106b624ab59Yuichi Araki        final PagedList<User> pagedList = observer.get();
1477d2309c06787d20bafe9582e1f47d106b624ab59Yuichi Araki        assertThat(getAndLoad(pagedList, 50), notNullValue());
1487d2309c06787d20bafe9582e1f47d106b624ab59Yuichi Araki        assertThat(getAndLoad(pagedList, 70), nullValue());
149e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar    }
150e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar
151e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar    private <T> T getAndLoad(PagedList<T> list, int pos) {
152e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        T result = list.get(pos);
153e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        list.loadAround(pos);
154e385da30d6d674daa1dccef17e5e7ccc519bc3ddYigit Boyar        return result;
1559fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    }
1569fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
1579fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    private void drain() throws InterruptedException, TimeoutException {
1589fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        mExecutorRule.drainTasks(60, TimeUnit.SECONDS);
1599fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    }
1609fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
1619fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    private void observe(final LiveData liveData, final LifecycleOwner provider,
1629fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            final Observer observer) throws ExecutionException, InterruptedException {
163cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar        FutureTask<Void> futureTask = new FutureTask<>(() -> {
164cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar            //noinspection unchecked
165cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar            liveData.observe(provider, observer);
166cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar            return null;
1679fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        });
168ae36c8b11a64d3cdc9ba6e37d9f3d1d250fdc4a8Yigit Boyar        ArchTaskExecutor.getInstance().executeOnMainThread(futureTask);
1699fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        futureTask.get();
1709fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    }
1719fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
1721b805d37217a328107a7ad021c877d3c224e5869Chris Craik    @Test
1731b805d37217a328107a7ad021c877d3c224e5869Chris Craik    public void withRelation() throws ExecutionException, InterruptedException, TimeoutException {
1741b805d37217a328107a7ad021c877d3c224e5869Chris Craik        // verify DataSourceFactory can be created from a multi table join
1751b805d37217a328107a7ad021c877d3c224e5869Chris Craik        DataSource.Factory<Integer, UserAndAllPets> factory =
1761b805d37217a328107a7ad021c877d3c224e5869Chris Craik                mUserPetDao.dataSourceFactoryMultiTable();
1771b805d37217a328107a7ad021c877d3c224e5869Chris Craik        LiveData<PagedList<UserAndAllPets>> liveData =
1781b805d37217a328107a7ad021c877d3c224e5869Chris Craik                new LivePagedListBuilder<>(mUserPetDao.dataSourceFactoryMultiTable(), 10).build();
1791b805d37217a328107a7ad021c877d3c224e5869Chris Craik        assertNotNull(factory.create());
1801b805d37217a328107a7ad021c877d3c224e5869Chris Craik
1811b805d37217a328107a7ad021c877d3c224e5869Chris Craik        PagedListObserver<UserAndAllPets> observer = new PagedListObserver<>();
1821b805d37217a328107a7ad021c877d3c224e5869Chris Craik        final TestLifecycleOwner lifecycleOwner = new TestLifecycleOwner();
1831b805d37217a328107a7ad021c877d3c224e5869Chris Craik        lifecycleOwner.handleEvent(Lifecycle.Event.ON_START);
1841b805d37217a328107a7ad021c877d3c224e5869Chris Craik        observe(liveData, lifecycleOwner, observer);
1851b805d37217a328107a7ad021c877d3c224e5869Chris Craik        drain();
1861b805d37217a328107a7ad021c877d3c224e5869Chris Craik        assertThat(observer.get(), is(Collections.emptyList()));
1871b805d37217a328107a7ad021c877d3c224e5869Chris Craik
1881b805d37217a328107a7ad021c877d3c224e5869Chris Craik        observer.reset();
1891b805d37217a328107a7ad021c877d3c224e5869Chris Craik        User user = TestUtil.createUser(3);
1901b805d37217a328107a7ad021c877d3c224e5869Chris Craik        mUserDao.insert(user);
1911b805d37217a328107a7ad021c877d3c224e5869Chris Craik        drain();
1921b805d37217a328107a7ad021c877d3c224e5869Chris Craik        final UserAndAllPets noPets = observer.get().get(0);
1931b805d37217a328107a7ad021c877d3c224e5869Chris Craik        assertThat(noPets.user, is(user));
1941b805d37217a328107a7ad021c877d3c224e5869Chris Craik
1951b805d37217a328107a7ad021c877d3c224e5869Chris Craik        observer.reset();
1961b805d37217a328107a7ad021c877d3c224e5869Chris Craik        Pet[] pets = TestUtil.createPetsForUser(3, 1, 2);
1971b805d37217a328107a7ad021c877d3c224e5869Chris Craik        mPetDao.insertAll(pets);
1981b805d37217a328107a7ad021c877d3c224e5869Chris Craik
1991b805d37217a328107a7ad021c877d3c224e5869Chris Craik        drain();
2001b805d37217a328107a7ad021c877d3c224e5869Chris Craik        final UserAndAllPets withPets = observer.get().get(0);
2011b805d37217a328107a7ad021c877d3c224e5869Chris Craik        assertThat(withPets.user, is(user));
2021b805d37217a328107a7ad021c877d3c224e5869Chris Craik        assertThat(withPets.pets, is(Arrays.asList(pets)));
2031b805d37217a328107a7ad021c877d3c224e5869Chris Craik    }
2041b805d37217a328107a7ad021c877d3c224e5869Chris Craik
2059fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    static class TestLifecycleOwner implements LifecycleOwner {
2069fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
2079fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        private LifecycleRegistry mLifecycle;
2089fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
2099fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        TestLifecycleOwner() {
2109fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            mLifecycle = new LifecycleRegistry(this);
2119fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        }
2129fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
2139fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        @Override
2149fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        public Lifecycle getLifecycle() {
2159fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            return mLifecycle;
2169fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        }
2179fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
2189fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        void handleEvent(Lifecycle.Event event) {
2199fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            mLifecycle.handleLifecycleEvent(event);
2209fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        }
2219fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    }
2229fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
22324418e9aafa6ae3128ae47cf7087eda46dae4f5dChris Craik    private static class PagedListObserver<T> implements Observer<PagedList<T>> {
22424418e9aafa6ae3128ae47cf7087eda46dae4f5dChris Craik        private PagedList<T> mList;
225cab865bed3b4e9df8b86b0b16c589c4e6dd0b71dYigit Boyar
226ae36c8b11a64d3cdc9ba6e37d9f3d1d250fdc4a8Yigit Boyar        void reset() {
2279fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            mList = null;
2289fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        }
2299fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
23024418e9aafa6ae3128ae47cf7087eda46dae4f5dChris Craik        public PagedList<T> get() {
2319fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik            return mList;
2329fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        }
2339fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik
2349fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        @Override
23524418e9aafa6ae3128ae47cf7087eda46dae4f5dChris Craik        public void onChanged(@Nullable PagedList<T> pagedList) {
23624418e9aafa6ae3128ae47cf7087eda46dae4f5dChris Craik            mList = pagedList;
2379fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik        }
2389fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik    }
2399fd8e6171bbdc37f5516fe15b2d96f4ae926ef1aChris Craik}
240