1/*
2 * Copyright (C) 2017 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.room.integration.testapp.test;
18
19import static org.hamcrest.CoreMatchers.hasItem;
20import static org.hamcrest.CoreMatchers.nullValue;
21import static org.hamcrest.MatcherAssert.assertThat;
22import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
23
24import android.content.Context;
25import android.support.test.InstrumentationRegistry;
26import android.support.test.filters.SmallTest;
27import android.support.test.runner.AndroidJUnit4;
28
29import androidx.annotation.NonNull;
30import androidx.arch.core.executor.testing.CountingTaskExecutorRule;
31import androidx.room.InvalidationTracker;
32import androidx.room.Room;
33import androidx.room.integration.testapp.TestDatabase;
34import androidx.room.integration.testapp.dao.UserDao;
35import androidx.room.integration.testapp.vo.User;
36
37import org.junit.After;
38import org.junit.Before;
39import org.junit.Rule;
40import org.junit.Test;
41import org.junit.runner.RunWith;
42
43import java.util.Set;
44import java.util.concurrent.TimeUnit;
45import java.util.concurrent.TimeoutException;
46
47/**
48 * Tests invalidation tracking.
49 */
50@SmallTest
51@RunWith(AndroidJUnit4.class)
52public class InvalidationTest {
53    @Rule
54    public CountingTaskExecutorRule executorRule = new CountingTaskExecutorRule();
55    private UserDao mUserDao;
56    private TestDatabase mDb;
57
58    @Before
59    public void createDb() throws TimeoutException, InterruptedException {
60        Context context = InstrumentationRegistry.getTargetContext();
61        mDb = Room.inMemoryDatabaseBuilder(context, TestDatabase.class).build();
62        mUserDao = mDb.getUserDao();
63        drain();
64    }
65
66    @After
67    public void closeDb() throws TimeoutException, InterruptedException {
68        mDb.close();
69        drain();
70    }
71
72    private void drain() throws TimeoutException, InterruptedException {
73        executorRule.drainTasks(1, TimeUnit.MINUTES);
74    }
75
76    @Test
77    public void testInvalidationOnUpdate() throws InterruptedException, TimeoutException {
78        User user = TestUtil.createUser(3);
79        mUserDao.insert(user);
80        LoggingObserver observer = new LoggingObserver("User");
81        mDb.getInvalidationTracker().addObserver(observer);
82        drain();
83        mUserDao.updateById(3, "foo2");
84        drain();
85        assertThat(observer.getInvalidatedTables(), hasSize(1));
86        assertThat(observer.getInvalidatedTables(), hasItem("User"));
87    }
88
89    @Test
90    public void testInvalidationOnDelete() throws InterruptedException, TimeoutException {
91        User user = TestUtil.createUser(3);
92        mUserDao.insert(user);
93        LoggingObserver observer = new LoggingObserver("User");
94        mDb.getInvalidationTracker().addObserver(observer);
95        drain();
96        mUserDao.delete(user);
97        drain();
98        assertThat(observer.getInvalidatedTables(), hasSize(1));
99        assertThat(observer.getInvalidatedTables(), hasItem("User"));
100    }
101
102    @Test
103    public void testInvalidationOnInsert() throws InterruptedException, TimeoutException {
104        LoggingObserver observer = new LoggingObserver("User");
105        mDb.getInvalidationTracker().addObserver(observer);
106        drain();
107        mUserDao.insert(TestUtil.createUser(3));
108        drain();
109        assertThat(observer.getInvalidatedTables(), hasSize(1));
110        assertThat(observer.getInvalidatedTables(), hasItem("User"));
111    }
112
113    @Test
114    public void testDontInvalidateOnLateInsert() throws InterruptedException, TimeoutException {
115        LoggingObserver observer = new LoggingObserver("User");
116        mUserDao.insert(TestUtil.createUser(3));
117        drain();
118        mDb.getInvalidationTracker().addObserver(observer);
119        drain();
120        assertThat(observer.getInvalidatedTables(), nullValue());
121    }
122
123    @Test
124    public void testMultipleTables() throws InterruptedException, TimeoutException {
125        LoggingObserver observer = new LoggingObserver("User", "Pet");
126        mDb.getInvalidationTracker().addObserver(observer);
127        drain();
128        mUserDao.insert(TestUtil.createUser(3));
129        drain();
130        assertThat(observer.getInvalidatedTables(), hasSize(1));
131        assertThat(observer.getInvalidatedTables(), hasItem("User"));
132    }
133
134    private static class LoggingObserver extends InvalidationTracker.Observer {
135        private Set<String> mInvalidatedTables;
136
137        LoggingObserver(String... tables) {
138            super(tables);
139        }
140
141        @Override
142        public void onInvalidated(@NonNull Set<String> tables) {
143            mInvalidatedTables = tables;
144        }
145
146        Set<String> getInvalidatedTables() {
147            return mInvalidatedTables;
148        }
149    }
150}
151