134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar/* 234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * Copyright (C) 2017 The Android Open Source Project 334e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * 434e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 534e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * you may not use this file except in compliance with the License. 634e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * You may obtain a copy of the License at 734e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * 834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 934e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * 1034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * Unless required by applicable law or agreed to in writing, software 1134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 1234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1334e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * See the License for the specific language governing permissions and 1434e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * limitations under the License. 1534e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar */ 1634e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 17ba069d50913c3fb250bb60ec310439db36895337Alan Viverettepackage androidx.room.integration.testapp.test; 1834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 192ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Arakiimport static org.hamcrest.CoreMatchers.hasItem; 20d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyarimport static org.hamcrest.CoreMatchers.nullValue; 2134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyarimport static org.hamcrest.MatcherAssert.assertThat; 222ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Arakiimport static org.hamcrest.collection.IsCollectionWithSize.hasSize; 2334e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 242ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Arakiimport android.content.Context; 252ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Arakiimport android.support.test.InstrumentationRegistry; 262ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Arakiimport android.support.test.filters.SmallTest; 272ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Arakiimport android.support.test.runner.AndroidJUnit4; 2834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 29ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.annotation.NonNull; 30ddee2b5170ae257a7b2494f8aaa8459ebed806dcAurimas Liutikasimport androidx.arch.core.executor.testing.CountingTaskExecutorRule; 31ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.InvalidationTracker; 32ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.Room; 33ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.integration.testapp.TestDatabase; 34ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.integration.testapp.dao.UserDao; 35ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.room.integration.testapp.vo.User; 36ba069d50913c3fb250bb60ec310439db36895337Alan Viverette 37abd1282bf69658247b310982d529aa48a9466cf4Yigit Boyarimport org.junit.After; 3834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyarimport org.junit.Before; 39d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyarimport org.junit.Rule; 4034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyarimport org.junit.Test; 4134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyarimport org.junit.runner.RunWith; 4234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 432ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Arakiimport java.util.Set; 4434e5031083f735db3a395b0f6aa430880b072d71Yigit Boyarimport java.util.concurrent.TimeUnit; 45d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyarimport java.util.concurrent.TimeoutException; 4634e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 4734e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar/** 4834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar * Tests invalidation tracking. 4934e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar */ 5034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar@SmallTest 5134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar@RunWith(AndroidJUnit4.class) 5234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyarpublic class InvalidationTest { 53d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar @Rule 54d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar public CountingTaskExecutorRule executorRule = new CountingTaskExecutorRule(); 5534e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar private UserDao mUserDao; 5634e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar private TestDatabase mDb; 5734e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 5834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar @Before 59d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar public void createDb() throws TimeoutException, InterruptedException { 6034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar Context context = InstrumentationRegistry.getTargetContext(); 6134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mDb = Room.inMemoryDatabaseBuilder(context, TestDatabase.class).build(); 6234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mUserDao = mDb.getUserDao(); 63d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 64abd1282bf69658247b310982d529aa48a9466cf4Yigit Boyar } 65abd1282bf69658247b310982d529aa48a9466cf4Yigit Boyar 66abd1282bf69658247b310982d529aa48a9466cf4Yigit Boyar @After 67d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar public void closeDb() throws TimeoutException, InterruptedException { 68d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar mDb.close(); 69d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 70abd1282bf69658247b310982d529aa48a9466cf4Yigit Boyar } 71abd1282bf69658247b310982d529aa48a9466cf4Yigit Boyar 72d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar private void drain() throws TimeoutException, InterruptedException { 73d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar executorRule.drainTasks(1, TimeUnit.MINUTES); 7434e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar } 7534e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 7634e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar @Test 77d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar public void testInvalidationOnUpdate() throws InterruptedException, TimeoutException { 7834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar User user = TestUtil.createUser(3); 7934e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mUserDao.insert(user); 80d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar LoggingObserver observer = new LoggingObserver("User"); 8134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mDb.getInvalidationTracker().addObserver(observer); 82d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 8334e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mUserDao.updateById(3, "foo2"); 84d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 852ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki assertThat(observer.getInvalidatedTables(), hasSize(1)); 862ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki assertThat(observer.getInvalidatedTables(), hasItem("User")); 8734e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar } 8834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 8934e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar @Test 90d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar public void testInvalidationOnDelete() throws InterruptedException, TimeoutException { 9134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar User user = TestUtil.createUser(3); 9234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mUserDao.insert(user); 93d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar LoggingObserver observer = new LoggingObserver("User"); 9434e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mDb.getInvalidationTracker().addObserver(observer); 95d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 9634e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mUserDao.delete(user); 97d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 982ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki assertThat(observer.getInvalidatedTables(), hasSize(1)); 992ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki assertThat(observer.getInvalidatedTables(), hasItem("User")); 10034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar } 10134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 10234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar @Test 103d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar public void testInvalidationOnInsert() throws InterruptedException, TimeoutException { 104d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar LoggingObserver observer = new LoggingObserver("User"); 10534e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mDb.getInvalidationTracker().addObserver(observer); 106d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 10734e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mUserDao.insert(TestUtil.createUser(3)); 108d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 1092ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki assertThat(observer.getInvalidatedTables(), hasSize(1)); 1102ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki assertThat(observer.getInvalidatedTables(), hasItem("User")); 11134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar } 11234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 11334e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar @Test 114d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar public void testDontInvalidateOnLateInsert() throws InterruptedException, TimeoutException { 115d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar LoggingObserver observer = new LoggingObserver("User"); 11634e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mUserDao.insert(TestUtil.createUser(3)); 117d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 11834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar mDb.getInvalidationTracker().addObserver(observer); 119d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 120d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar assertThat(observer.getInvalidatedTables(), nullValue()); 12134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar } 12234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 12308385cfa2c450904f437f8361ec3d3553834989bYuichi Araki @Test 124d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar public void testMultipleTables() throws InterruptedException, TimeoutException { 125d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar LoggingObserver observer = new LoggingObserver("User", "Pet"); 12608385cfa2c450904f437f8361ec3d3553834989bYuichi Araki mDb.getInvalidationTracker().addObserver(observer); 127d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 12808385cfa2c450904f437f8361ec3d3553834989bYuichi Araki mUserDao.insert(TestUtil.createUser(3)); 129d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar drain(); 13008385cfa2c450904f437f8361ec3d3553834989bYuichi Araki assertThat(observer.getInvalidatedTables(), hasSize(1)); 13108385cfa2c450904f437f8361ec3d3553834989bYuichi Araki assertThat(observer.getInvalidatedTables(), hasItem("User")); 13208385cfa2c450904f437f8361ec3d3553834989bYuichi Araki } 13308385cfa2c450904f437f8361ec3d3553834989bYuichi Araki 134d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar private static class LoggingObserver extends InvalidationTracker.Observer { 1352ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki private Set<String> mInvalidatedTables; 1362ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki 137d2cdfecb16af89f7b6a92d95f8854b261d2c6c0cYigit Boyar LoggingObserver(String... tables) { 13834e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar super(tables); 13934e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar } 14034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar 14134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar @Override 1422ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki public void onInvalidated(@NonNull Set<String> tables) { 1432ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki mInvalidatedTables = tables; 14434e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar } 1452ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki 1462ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki Set<String> getInvalidatedTables() { 1472ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki return mInvalidatedTables; 1482ec1285ef79d4849069efe95cfbac2307d291a47Yuichi Araki } 14934e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar } 15034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar} 151