diff options
Diffstat (limited to 'android/arch/persistence/room/integration')
25 files changed, 553 insertions, 40 deletions
diff --git a/android/arch/persistence/room/integration/testapp/CustomerViewModel.java b/android/arch/persistence/room/integration/testapp/CustomerViewModel.java index 1f434ad6..320b2cdd 100644 --- a/android/arch/persistence/room/integration/testapp/CustomerViewModel.java +++ b/android/arch/persistence/room/integration/testapp/CustomerViewModel.java @@ -17,7 +17,7 @@ package android.arch.persistence.room.integration.testapp; import android.app.Application; -import android.arch.core.executor.AppToolkitTaskExecutor; +import android.arch.core.executor.ArchTaskExecutor; import android.arch.lifecycle.AndroidViewModel; import android.arch.lifecycle.LiveData; import android.arch.paging.DataSource; @@ -47,7 +47,7 @@ public class CustomerViewModel extends AndroidViewModel { mDatabase = Room.databaseBuilder(this.getApplication(), SampleDatabase.class, "customerDatabase").build(); - AppToolkitTaskExecutor.getInstance().executeOnDiskIO(new Runnable() { + ArchTaskExecutor.getInstance().executeOnDiskIO(new Runnable() { @Override public void run() { // fill with some simple data @@ -73,7 +73,7 @@ public class CustomerViewModel extends AndroidViewModel { } void insertCustomer() { - AppToolkitTaskExecutor.getInstance().executeOnDiskIO(new Runnable() { + ArchTaskExecutor.getInstance().executeOnDiskIO(new Runnable() { @Override public void run() { mDatabase.getCustomerDao().insert(createCustomer()); diff --git a/android/arch/persistence/room/integration/testapp/PKeyTestDatabase.java b/android/arch/persistence/room/integration/testapp/PKeyTestDatabase.java index e61d808c..63b95072 100644 --- a/android/arch/persistence/room/integration/testapp/PKeyTestDatabase.java +++ b/android/arch/persistence/room/integration/testapp/PKeyTestDatabase.java @@ -23,13 +23,18 @@ import android.arch.persistence.room.Query; import android.arch.persistence.room.RoomDatabase; import android.arch.persistence.room.integration.testapp.vo.IntAutoIncPKeyEntity; import android.arch.persistence.room.integration.testapp.vo.IntegerAutoIncPKeyEntity; +import android.arch.persistence.room.integration.testapp.vo.IntegerPKeyEntity; +import android.arch.persistence.room.integration.testapp.vo.ObjectPKeyEntity; import java.util.List; -@Database(entities = {IntAutoIncPKeyEntity.class, IntegerAutoIncPKeyEntity.class}, version = 1, +@Database(entities = {IntAutoIncPKeyEntity.class, IntegerAutoIncPKeyEntity.class, + ObjectPKeyEntity.class, IntegerPKeyEntity.class}, version = 1, exportSchema = false) public abstract class PKeyTestDatabase extends RoomDatabase { public abstract IntPKeyDao intPKeyDao(); + public abstract IntegerAutoIncPKeyDao integerAutoIncPKeyDao(); + public abstract ObjectPKeyDao objectPKeyDao(); public abstract IntegerPKeyDao integerPKeyDao(); @Dao @@ -50,9 +55,10 @@ public abstract class PKeyTestDatabase extends RoomDatabase { } @Dao - public interface IntegerPKeyDao { + public interface IntegerAutoIncPKeyDao { @Insert - void insertMe(IntegerAutoIncPKeyEntity items); + void insertMe(IntegerAutoIncPKeyEntity item); + @Query("select * from IntegerAutoIncPKeyEntity WHERE pKey = :key") IntegerAutoIncPKeyEntity getMe(int key); @@ -65,4 +71,19 @@ public abstract class PKeyTestDatabase extends RoomDatabase { @Query("select data from IntegerAutoIncPKeyEntity WHERE pKey IN(:ids)") List<String> loadDataById(long... ids); } + + @Dao + public interface ObjectPKeyDao { + @Insert + void insertMe(ObjectPKeyEntity item); + } + + @Dao + public interface IntegerPKeyDao { + @Insert + void insertMe(IntegerPKeyEntity item); + + @Query("select * from IntegerPKeyEntity") + List<IntegerPKeyEntity> loadAll(); + } } diff --git a/android/arch/persistence/room/integration/testapp/TestDatabase.java b/android/arch/persistence/room/integration/testapp/TestDatabase.java index 94172965..2fad7b1f 100644 --- a/android/arch/persistence/room/integration/testapp/TestDatabase.java +++ b/android/arch/persistence/room/integration/testapp/TestDatabase.java @@ -21,6 +21,7 @@ import android.arch.persistence.room.RoomDatabase; import android.arch.persistence.room.TypeConverter; import android.arch.persistence.room.TypeConverters; import android.arch.persistence.room.integration.testapp.dao.BlobEntityDao; +import android.arch.persistence.room.integration.testapp.dao.FunnyNamedDao; import android.arch.persistence.room.integration.testapp.dao.PetCoupleDao; import android.arch.persistence.room.integration.testapp.dao.PetDao; import android.arch.persistence.room.integration.testapp.dao.ProductDao; @@ -31,6 +32,7 @@ import android.arch.persistence.room.integration.testapp.dao.UserDao; import android.arch.persistence.room.integration.testapp.dao.UserPetDao; import android.arch.persistence.room.integration.testapp.dao.WithClauseDao; import android.arch.persistence.room.integration.testapp.vo.BlobEntity; +import android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity; import android.arch.persistence.room.integration.testapp.vo.Pet; import android.arch.persistence.room.integration.testapp.vo.PetCouple; import android.arch.persistence.room.integration.testapp.vo.Product; @@ -41,7 +43,7 @@ import android.arch.persistence.room.integration.testapp.vo.User; import java.util.Date; @Database(entities = {User.class, Pet.class, School.class, PetCouple.class, Toy.class, - BlobEntity.class, Product.class}, + BlobEntity.class, Product.class, FunnyNamedEntity.class}, version = 1, exportSchema = false) @TypeConverters(TestDatabase.Converters.class) public abstract class TestDatabase extends RoomDatabase { @@ -55,6 +57,7 @@ public abstract class TestDatabase extends RoomDatabase { public abstract ProductDao getProductDao(); public abstract SpecificDogDao getSpecificDogDao(); public abstract WithClauseDao getWithClauseDao(); + public abstract FunnyNamedDao getFunnyNamedDao(); @SuppressWarnings("unused") public static class Converters { diff --git a/android/arch/persistence/room/integration/testapp/dao/FunnyNamedDao.java b/android/arch/persistence/room/integration/testapp/dao/FunnyNamedDao.java new file mode 100644 index 00000000..93b5e72e --- /dev/null +++ b/android/arch/persistence/room/integration/testapp/dao/FunnyNamedDao.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.arch.persistence.room.integration.testapp.dao; + +import static android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity.COLUMN_ID; +import static android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity.TABLE_NAME; + +import android.arch.lifecycle.LiveData; +import android.arch.persistence.room.Dao; +import android.arch.persistence.room.Delete; +import android.arch.persistence.room.Insert; +import android.arch.persistence.room.Query; +import android.arch.persistence.room.Update; +import android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity; + +import java.util.List; + +@Dao +public interface FunnyNamedDao { + String SELECT_ONE = "select * from \"" + TABLE_NAME + "\" WHERE \"" + COLUMN_ID + "\" = :id"; + @Insert + void insert(FunnyNamedEntity... entities); + @Delete + void delete(FunnyNamedEntity... entities); + @Update + void update(FunnyNamedEntity... entities); + + @Query("select * from \"" + TABLE_NAME + "\" WHERE \"" + COLUMN_ID + "\" IN (:ids)") + List<FunnyNamedEntity> loadAll(int... ids); + + @Query(SELECT_ONE) + LiveData<FunnyNamedEntity> observableOne(int id); + + @Query(SELECT_ONE) + FunnyNamedEntity load(int id); +} diff --git a/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java b/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java index 7bb137fe..18e8d93e 100644 --- a/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java +++ b/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java @@ -35,16 +35,16 @@ public abstract class SchoolDao { @Query("SELECT * from School WHERE address_street LIKE '%' || :street || '%'") public abstract List<School> findByStreet(String street); - @Query("SELECT mName, manager_mName FROM School") + @Query("SELECT mId, mName, manager_mName FROM School") public abstract List<School> schoolAndManagerNames(); - @Query("SELECT mName, manager_mName FROM School") + @Query("SELECT mId, mName, manager_mName FROM School") @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) public abstract List<SchoolRef> schoolAndManagerNamesAsPojo(); @Query("SELECT address_lat as lat, address_lng as lng FROM School WHERE mId = :schoolId") public abstract Coordinates loadCoordinates(int schoolId); - @Query("SELECT address_lat, address_lng FROM School WHERE mId = :schoolId") + @Query("SELECT mId, address_lat, address_lng FROM School WHERE mId = :schoolId") public abstract School loadCoordinatesAsSchool(int schoolId); } diff --git a/android/arch/persistence/room/integration/testapp/dao/UserDao.java b/android/arch/persistence/room/integration/testapp/dao/UserDao.java index 337c233f..665a1aeb 100644 --- a/android/arch/persistence/room/integration/testapp/dao/UserDao.java +++ b/android/arch/persistence/room/integration/testapp/dao/UserDao.java @@ -24,6 +24,7 @@ import android.arch.persistence.room.Delete; import android.arch.persistence.room.Insert; import android.arch.persistence.room.OnConflictStrategy; import android.arch.persistence.room.Query; +import android.arch.persistence.room.Transaction; import android.arch.persistence.room.Update; import android.arch.persistence.room.integration.testapp.TestDatabase; import android.arch.persistence.room.integration.testapp.vo.AvgWeightByAge; @@ -259,4 +260,10 @@ public abstract class UserDao { + " WHERE mLastName > :lastName or (mLastName = :lastName and (mName < :name or (mName = :name and mId > :id)))" + " ORDER BY mLastName ASC, mName DESC, mId ASC") public abstract int userComplexCountBefore(String lastName, String name, int id); + + @Transaction + public void insertBothByAnnotation(final User a, final User b) { + insert(a); + insert(b); + } } diff --git a/android/arch/persistence/room/integration/testapp/dao/UserPetDao.java b/android/arch/persistence/room/integration/testapp/dao/UserPetDao.java index 3507aeea..eb159014 100644 --- a/android/arch/persistence/room/integration/testapp/dao/UserPetDao.java +++ b/android/arch/persistence/room/integration/testapp/dao/UserPetDao.java @@ -33,6 +33,8 @@ import android.arch.persistence.room.integration.testapp.vo.UserWithPetsAndToys; import java.util.List; +import io.reactivex.Flowable; + @Dao public interface UserPetDao { @Query("SELECT * FROM User u, Pet p WHERE u.mId = p.mUserId") @@ -62,6 +64,9 @@ public interface UserPetDao { @Query("SELECT * FROM User u where u.mId = :userId") LiveData<UserAndAllPets> liveUserWithPets(int userId); + @Query("SELECT * FROM User u where u.mId = :userId") + Flowable<UserAndAllPets> flowableUserWithPets(int userId); + @Query("SELECT * FROM User u where u.mId = :uid") EmbeddedUserAndAllPets loadUserAndPetsAsEmbedded(int uid); diff --git a/android/arch/persistence/room/integration/testapp/dao/WithClauseDao.java b/android/arch/persistence/room/integration/testapp/dao/WithClauseDao.java index b1c38eda..40098ed4 100644 --- a/android/arch/persistence/room/integration/testapp/dao/WithClauseDao.java +++ b/android/arch/persistence/room/integration/testapp/dao/WithClauseDao.java @@ -16,13 +16,16 @@ package android.arch.persistence.room.integration.testapp.dao; +import android.annotation.TargetApi; import android.arch.lifecycle.LiveData; import android.arch.persistence.room.Dao; import android.arch.persistence.room.Query; +import android.os.Build; import java.util.List; @Dao +@TargetApi(Build.VERSION_CODES.LOLLIPOP) public interface WithClauseDao { @Query("WITH RECURSIVE factorial(n, fact) AS \n" + "(SELECT 0, 1 \n" diff --git a/android/arch/persistence/room/integration/testapp/database/SampleDatabase.java b/android/arch/persistence/room/integration/testapp/database/SampleDatabase.java index eec59f6a..9020eb16 100644 --- a/android/arch/persistence/room/integration/testapp/database/SampleDatabase.java +++ b/android/arch/persistence/room/integration/testapp/database/SampleDatabase.java @@ -18,10 +18,6 @@ package android.arch.persistence.room.integration.testapp.database; import android.arch.persistence.room.Database; import android.arch.persistence.room.RoomDatabase; -import android.arch.persistence.room.TypeConverter; -import android.arch.persistence.room.TypeConverters; - -import java.util.Date; /** * Sample database of customers. diff --git a/android/arch/persistence/room/integration/testapp/migration/MigrationTest.java b/android/arch/persistence/room/integration/testapp/migration/MigrationTest.java index 725d53f8..7fe2bc94 100644 --- a/android/arch/persistence/room/integration/testapp/migration/MigrationTest.java +++ b/android/arch/persistence/room/integration/testapp/migration/MigrationTest.java @@ -318,6 +318,8 @@ public class MigrationTest { + " (`id` INTEGER NOT NULL, `name` TEXT COLLATE NOCASE, PRIMARY KEY(`id`)," + " FOREIGN KEY(`name`) REFERENCES `Entity1`(`name`)" + " ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED)"); + database.execSQL("CREATE UNIQUE INDEX `index_entity1` ON " + + MigrationDb.Entity1.TABLE_NAME + " (`name`)"); } }; diff --git a/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java b/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java index 4c9d73e1..df70a170 100644 --- a/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java +++ b/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java @@ -21,17 +21,17 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; -import android.arch.core.executor.AppToolkitTaskExecutor; +import android.arch.core.executor.ArchTaskExecutor; import android.arch.core.executor.testing.CountingTaskExecutorRule; import android.arch.lifecycle.Lifecycle; import android.arch.lifecycle.LifecycleOwner; import android.arch.lifecycle.LifecycleRegistry; import android.arch.lifecycle.LiveData; import android.arch.lifecycle.Observer; +import android.arch.paging.PagedList; import android.arch.persistence.room.integration.testapp.test.TestDatabaseTest; import android.arch.persistence.room.integration.testapp.test.TestUtil; import android.arch.persistence.room.integration.testapp.vo.User; -import android.arch.paging.PagedList; import android.support.annotation.Nullable; import android.support.test.filters.LargeTest; import android.support.test.runner.AndroidJUnit4; @@ -131,7 +131,7 @@ public class LivePagedListProviderTest extends TestDatabaseTest { return null; } }); - AppToolkitTaskExecutor.getInstance().executeOnMainThread(futureTask); + ArchTaskExecutor.getInstance().executeOnMainThread(futureTask); futureTask.get(); } @@ -155,7 +155,7 @@ public class LivePagedListProviderTest extends TestDatabaseTest { private static class PagedListObserver<T> implements Observer<PagedList<T>> { private PagedList<T> mList; - public void reset() { + void reset() { mList = null; } diff --git a/android/arch/persistence/room/integration/testapp/test/CustomDatabaseTest.java b/android/arch/persistence/room/integration/testapp/test/CustomDatabaseTest.java index 353c2e39..6f44546b 100644 --- a/android/arch/persistence/room/integration/testapp/test/CustomDatabaseTest.java +++ b/android/arch/persistence/room/integration/testapp/test/CustomDatabaseTest.java @@ -55,7 +55,6 @@ public class CustomDatabaseTest { Customer customer = new Customer(); for (int i = 0; i < 100; i++) { SampleDatabase db = builder.build(); - customer.setId(i); db.getCustomerDao().insert(customer); // Give InvalidationTracker enough time to start #mRefreshRunnable and pass the // initialization check. diff --git a/android/arch/persistence/room/integration/testapp/test/FunnyNamedDaoTest.java b/android/arch/persistence/room/integration/testapp/test/FunnyNamedDaoTest.java new file mode 100644 index 00000000..f4fca7f2 --- /dev/null +++ b/android/arch/persistence/room/integration/testapp/test/FunnyNamedDaoTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.arch.persistence.room.integration.testapp.test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +import android.arch.core.executor.testing.CountingTaskExecutorRule; +import android.arch.lifecycle.Observer; +import android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity; +import android.support.annotation.Nullable; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class FunnyNamedDaoTest extends TestDatabaseTest { + @Rule + public CountingTaskExecutorRule mExecutorRule = new CountingTaskExecutorRule(); + + @Test + public void readWrite() { + FunnyNamedEntity entity = new FunnyNamedEntity(1, "a"); + mFunnyNamedDao.insert(entity); + FunnyNamedEntity loaded = mFunnyNamedDao.load(1); + assertThat(loaded, is(entity)); + } + + @Test + public void update() { + FunnyNamedEntity entity = new FunnyNamedEntity(1, "a"); + mFunnyNamedDao.insert(entity); + entity.setValue("b"); + mFunnyNamedDao.update(entity); + FunnyNamedEntity loaded = mFunnyNamedDao.load(1); + assertThat(loaded.getValue(), is("b")); + } + + @Test + public void delete() { + FunnyNamedEntity entity = new FunnyNamedEntity(1, "a"); + mFunnyNamedDao.insert(entity); + assertThat(mFunnyNamedDao.load(1), notNullValue()); + mFunnyNamedDao.delete(entity); + assertThat(mFunnyNamedDao.load(1), nullValue()); + } + + @Test + public void observe() throws TimeoutException, InterruptedException { + final FunnyNamedEntity[] item = new FunnyNamedEntity[1]; + mFunnyNamedDao.observableOne(2).observeForever(new Observer<FunnyNamedEntity>() { + @Override + public void onChanged(@Nullable FunnyNamedEntity funnyNamedEntity) { + item[0] = funnyNamedEntity; + } + }); + + FunnyNamedEntity entity = new FunnyNamedEntity(1, "a"); + mFunnyNamedDao.insert(entity); + mExecutorRule.drainTasks(1, TimeUnit.MINUTES); + assertThat(item[0], nullValue()); + + final FunnyNamedEntity entity2 = new FunnyNamedEntity(2, "b"); + mFunnyNamedDao.insert(entity2); + mExecutorRule.drainTasks(1, TimeUnit.MINUTES); + assertThat(item[0], is(entity2)); + + final FunnyNamedEntity entity3 = new FunnyNamedEntity(2, "c"); + mFunnyNamedDao.update(entity3); + mExecutorRule.drainTasks(1, TimeUnit.MINUTES); + assertThat(item[0], is(entity3)); + } +} diff --git a/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java b/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java index 4787ce52..84f20ec5 100644 --- a/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java +++ b/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java @@ -21,7 +21,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; -import android.arch.core.executor.AppToolkitTaskExecutor; +import android.arch.core.executor.ArchTaskExecutor; import android.arch.core.executor.TaskExecutor; import android.arch.persistence.room.InvalidationTracker; import android.arch.persistence.room.Room; @@ -68,7 +68,7 @@ public class InvalidationTest { @Before public void setSingleThreadedIO() { - AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() { + ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() { ExecutorService mIOExecutor = Executors.newSingleThreadExecutor(); Handler mHandler = new Handler(Looper.getMainLooper()); @@ -91,7 +91,7 @@ public class InvalidationTest { @After public void clearExecutor() { - AppToolkitTaskExecutor.getInstance().setDelegate(null); + ArchTaskExecutor.getInstance().setDelegate(null); } private void waitUntilIOThreadIsIdle() { @@ -101,7 +101,7 @@ public class InvalidationTest { return null; } }); - AppToolkitTaskExecutor.getInstance().executeOnDiskIO(future); + ArchTaskExecutor.getInstance().executeOnDiskIO(future); //noinspection TryWithIdenticalCatches try { future.get(); diff --git a/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java b/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java index cae8445b..d78411f8 100644 --- a/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java +++ b/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java @@ -21,7 +21,7 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; -import android.arch.core.executor.AppToolkitTaskExecutor; +import android.arch.core.executor.ArchTaskExecutor; import android.arch.core.executor.testing.CountingTaskExecutorRule; import android.arch.lifecycle.Lifecycle; import android.arch.lifecycle.LifecycleOwner; @@ -35,9 +35,11 @@ import android.arch.persistence.room.integration.testapp.vo.PetsToys; import android.arch.persistence.room.integration.testapp.vo.Toy; import android.arch.persistence.room.integration.testapp.vo.User; import android.arch.persistence.room.integration.testapp.vo.UserAndAllPets; +import android.os.Build; import android.support.annotation.Nullable; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; +import android.support.test.filters.SdkSuppress; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -235,6 +237,7 @@ public class LiveDataQueryTest extends TestDatabaseTest { } @Test + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP) public void withWithClause() throws ExecutionException, InterruptedException, TimeoutException { LiveData<List<String>> actual = @@ -322,7 +325,7 @@ public class LiveDataQueryTest extends TestDatabaseTest { return null; } }); - AppToolkitTaskExecutor.getInstance().executeOnMainThread(futureTask); + ArchTaskExecutor.getInstance().executeOnMainThread(futureTask); futureTask.get(); } diff --git a/android/arch/persistence/room/integration/testapp/test/PrimaryKeyTest.java b/android/arch/persistence/room/integration/testapp/test/PrimaryKeyTest.java index 97ce10c2..fda43732 100644 --- a/android/arch/persistence/room/integration/testapp/test/PrimaryKeyTest.java +++ b/android/arch/persistence/room/integration/testapp/test/PrimaryKeyTest.java @@ -16,29 +16,35 @@ package android.arch.persistence.room.integration.testapp.test; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; - -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; +import static org.junit.Assert.assertNotNull; import android.arch.persistence.room.Room; import android.arch.persistence.room.integration.testapp.PKeyTestDatabase; import android.arch.persistence.room.integration.testapp.vo.IntAutoIncPKeyEntity; import android.arch.persistence.room.integration.testapp.vo.IntegerAutoIncPKeyEntity; +import android.arch.persistence.room.integration.testapp.vo.IntegerPKeyEntity; +import android.arch.persistence.room.integration.testapp.vo.ObjectPKeyEntity; +import android.database.sqlite.SQLiteConstraintException; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.util.Arrays; +import java.util.List; @RunWith(AndroidJUnit4.class) @SmallTest public class PrimaryKeyTest { private PKeyTestDatabase mDatabase; + @Before public void setup() { mDatabase = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getTargetContext(), @@ -49,8 +55,8 @@ public class PrimaryKeyTest { public void integerTest() { IntegerAutoIncPKeyEntity entity = new IntegerAutoIncPKeyEntity(); entity.data = "foo"; - mDatabase.integerPKeyDao().insertMe(entity); - IntegerAutoIncPKeyEntity loaded = mDatabase.integerPKeyDao().getMe(1); + mDatabase.integerAutoIncPKeyDao().insertMe(entity); + IntegerAutoIncPKeyEntity loaded = mDatabase.integerAutoIncPKeyDao().getMe(1); assertThat(loaded, notNullValue()); assertThat(loaded.data, is(entity.data)); } @@ -60,8 +66,8 @@ public class PrimaryKeyTest { IntegerAutoIncPKeyEntity entity = new IntegerAutoIncPKeyEntity(); entity.pKey = 0; entity.data = "foo"; - mDatabase.integerPKeyDao().insertMe(entity); - IntegerAutoIncPKeyEntity loaded = mDatabase.integerPKeyDao().getMe(0); + mDatabase.integerAutoIncPKeyDao().insertMe(entity); + IntegerAutoIncPKeyEntity loaded = mDatabase.integerAutoIncPKeyDao().getMe(0); assertThat(loaded, notNullValue()); assertThat(loaded.data, is(entity.data)); } @@ -98,8 +104,8 @@ public class PrimaryKeyTest { public void getInsertedIdFromInteger() { IntegerAutoIncPKeyEntity entity = new IntegerAutoIncPKeyEntity(); entity.data = "foo"; - final long id = mDatabase.integerPKeyDao().insertAndGetId(entity); - assertThat(mDatabase.integerPKeyDao().getMe((int) id).data, is("foo")); + final long id = mDatabase.integerAutoIncPKeyDao().insertAndGetId(entity); + assertThat(mDatabase.integerAutoIncPKeyDao().getMe((int) id).data, is("foo")); } @Test @@ -108,7 +114,34 @@ public class PrimaryKeyTest { entity.data = "foo"; IntegerAutoIncPKeyEntity entity2 = new IntegerAutoIncPKeyEntity(); entity2.data = "foo2"; - final long[] ids = mDatabase.integerPKeyDao().insertAndGetIds(entity, entity2); - assertThat(mDatabase.integerPKeyDao().loadDataById(ids), is(Arrays.asList("foo", "foo2"))); + final long[] ids = mDatabase.integerAutoIncPKeyDao().insertAndGetIds(entity, entity2); + assertThat(mDatabase.integerAutoIncPKeyDao().loadDataById(ids), + is(Arrays.asList("foo", "foo2"))); + } + + @Test + public void insertNullPrimaryKey() throws Exception { + ObjectPKeyEntity o1 = new ObjectPKeyEntity(null, "1"); + + Throwable throwable = null; + try { + mDatabase.objectPKeyDao().insertMe(o1); + } catch (Throwable t) { + throwable = t; + } + assertNotNull("Was expecting an exception", throwable); + assertThat(throwable, instanceOf(SQLiteConstraintException.class)); + } + + @Test + public void insertNullPrimaryKeyForInteger() throws Exception { + IntegerPKeyEntity entity = new IntegerPKeyEntity(); + entity.data = "data"; + mDatabase.integerPKeyDao().insertMe(entity); + + List<IntegerPKeyEntity> list = mDatabase.integerPKeyDao().loadAll(); + assertThat(list.size(), is(1)); + assertThat(list.get(0).data, is("data")); + assertNotNull(list.get(0).pKey); } } diff --git a/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java b/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java index 1bbc1406..01d071e7 100644 --- a/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java +++ b/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java @@ -19,10 +19,12 @@ package android.arch.persistence.room.integration.testapp.test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -import android.arch.core.executor.AppToolkitTaskExecutor; +import android.arch.core.executor.ArchTaskExecutor; import android.arch.core.executor.TaskExecutor; import android.arch.persistence.room.EmptyResultSetException; +import android.arch.persistence.room.integration.testapp.vo.Pet; import android.arch.persistence.room.integration.testapp.vo.User; +import android.arch.persistence.room.integration.testapp.vo.UserAndAllPets; import android.support.test.filters.MediumTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -38,6 +40,7 @@ import java.util.Collections; import java.util.List; import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Predicate; import io.reactivex.observers.TestObserver; import io.reactivex.schedulers.TestScheduler; import io.reactivex.subscribers.TestSubscriber; @@ -52,7 +55,7 @@ public class RxJava2Test extends TestDatabaseTest { public void setupSchedulers() { mTestScheduler = new TestScheduler(); mTestScheduler.start(); - AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() { + ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() { @Override public void executeOnDiskIO(Runnable runnable) { mTestScheduler.scheduleDirect(runnable); @@ -73,7 +76,7 @@ public class RxJava2Test extends TestDatabaseTest { @After public void clearSchedulers() { mTestScheduler.shutdown(); - AppToolkitTaskExecutor.getInstance().setDelegate(null); + ArchTaskExecutor.getInstance().setDelegate(null); } private void drain() throws InterruptedException { @@ -269,4 +272,60 @@ public class RxJava2Test extends TestDatabaseTest { subscriber.cancel(); subscriber.assertNoErrors(); } + + @Test + public void flowableWithRelation() throws InterruptedException { + final TestSubscriber<UserAndAllPets> subscriber = new TestSubscriber<>(); + + mUserPetDao.flowableUserWithPets(3).subscribe(subscriber); + drain(); + subscriber.assertSubscribed(); + + drain(); + subscriber.assertNoValues(); + + final User user = TestUtil.createUser(3); + mUserDao.insert(user); + drain(); + subscriber.assertValue(new Predicate<UserAndAllPets>() { + @Override + public boolean test(UserAndAllPets userAndAllPets) throws Exception { + return userAndAllPets.user.equals(user); + } + }); + subscriber.assertValueCount(1); + final Pet[] pets = TestUtil.createPetsForUser(3, 1, 2); + mPetDao.insertAll(pets); + drain(); + subscriber.assertValueAt(1, new Predicate<UserAndAllPets>() { + @Override + public boolean test(UserAndAllPets userAndAllPets) throws Exception { + return userAndAllPets.user.equals(user) + && userAndAllPets.pets.equals(Arrays.asList(pets)); + } + }); + } + + @Test + public void flowable_updateInTransaction() throws InterruptedException { + // When subscribing to the emissions of the user + final TestSubscriber<User> userTestSubscriber = mUserDao + .flowableUserById(3) + .observeOn(mTestScheduler) + .test(); + drain(); + userTestSubscriber.assertValueCount(0); + + // When inserting a new user in the data source + mDatabase.beginTransaction(); + try { + mUserDao.insert(TestUtil.createUser(3)); + mDatabase.setTransactionSuccessful(); + + } finally { + mDatabase.endTransaction(); + } + drain(); + userTestSubscriber.assertValueCount(1); + } } diff --git a/android/arch/persistence/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java b/android/arch/persistence/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java new file mode 100644 index 00000000..fcd0b004 --- /dev/null +++ b/android/arch/persistence/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.arch.persistence.room.integration.testapp.test; + +import android.arch.core.executor.testing.InstantTaskExecutorRule; +import android.arch.persistence.room.Room; +import android.arch.persistence.room.integration.testapp.TestDatabase; +import android.arch.persistence.room.integration.testapp.vo.User; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import io.reactivex.subscribers.TestSubscriber; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RxJava2WithInstantTaskExecutorTest { + @Rule + public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule(); + + private TestDatabase mDatabase; + + @Before + public void initDb() throws Exception { + // using an in-memory database because the information stored here disappears when the + // process is killed + mDatabase = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(), + TestDatabase.class) + // allowing main thread queries, just for testing + .allowMainThreadQueries() + .build(); + } + + @Test + public void testFlowableInTransaction() { + // When subscribing to the emissions of the user + TestSubscriber<User> subscriber = mDatabase.getUserDao().flowableUserById(3).test(); + subscriber.assertValueCount(0); + + // When inserting a new user in the data source + mDatabase.beginTransaction(); + try { + mDatabase.getUserDao().insert(TestUtil.createUser(3)); + mDatabase.setTransactionSuccessful(); + } finally { + mDatabase.endTransaction(); + } + + subscriber.assertValueCount(1); + } +} diff --git a/android/arch/persistence/room/integration/testapp/test/SimpleEntityReadWriteTest.java b/android/arch/persistence/room/integration/testapp/test/SimpleEntityReadWriteTest.java index 8861adbc..f8049f35 100644 --- a/android/arch/persistence/room/integration/testapp/test/SimpleEntityReadWriteTest.java +++ b/android/arch/persistence/room/integration/testapp/test/SimpleEntityReadWriteTest.java @@ -502,4 +502,26 @@ public class SimpleEntityReadWriteTest { assertThat(mUserDao.updateByAgeAndIds(3f, 30, Arrays.asList(3, 5)), is(1)); assertThat(mUserDao.loadByIds(3)[0].getWeight(), is(3f)); } + + @Test + public void transactionByAnnotation() { + User a = TestUtil.createUser(3); + User b = TestUtil.createUser(5); + mUserDao.insertBothByAnnotation(a, b); + assertThat(mUserDao.count(), is(2)); + } + + @Test + public void transactionByAnnotation_failure() { + User a = TestUtil.createUser(3); + User b = TestUtil.createUser(3); + boolean caught = false; + try { + mUserDao.insertBothByAnnotation(a, b); + } catch (SQLiteConstraintException e) { + caught = true; + } + assertTrue("SQLiteConstraintException expected", caught); + assertThat(mUserDao.count(), is(0)); + } } diff --git a/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java b/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java index 51d5bb33..ec775617 100644 --- a/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java +++ b/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java @@ -18,6 +18,7 @@ package android.arch.persistence.room.integration.testapp.test; import android.arch.persistence.room.Room; import android.arch.persistence.room.integration.testapp.TestDatabase; +import android.arch.persistence.room.integration.testapp.dao.FunnyNamedDao; import android.arch.persistence.room.integration.testapp.dao.PetCoupleDao; import android.arch.persistence.room.integration.testapp.dao.PetDao; import android.arch.persistence.room.integration.testapp.dao.SchoolDao; @@ -42,6 +43,7 @@ public abstract class TestDatabaseTest { protected ToyDao mToyDao; protected SpecificDogDao mSpecificDogDao; protected WithClauseDao mWithClauseDao; + protected FunnyNamedDao mFunnyNamedDao; @Before public void createDb() { @@ -55,5 +57,6 @@ public abstract class TestDatabaseTest { mToyDao = mDatabase.getToyDao(); mSpecificDogDao = mDatabase.getSpecificDogDao(); mWithClauseDao = mDatabase.getWithClauseDao(); + mFunnyNamedDao = mDatabase.getFunnyNamedDao(); } } diff --git a/android/arch/persistence/room/integration/testapp/test/WithClauseTest.java b/android/arch/persistence/room/integration/testapp/test/WithClauseTest.java index 10897da1..92096380 100644 --- a/android/arch/persistence/room/integration/testapp/test/WithClauseTest.java +++ b/android/arch/persistence/room/integration/testapp/test/WithClauseTest.java @@ -20,6 +20,8 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import android.arch.persistence.room.integration.testapp.vo.User; +import android.os.Build; +import android.support.test.filters.SdkSuppress; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -32,6 +34,7 @@ import java.util.List; @RunWith(AndroidJUnit4.class) @SmallTest +@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP) public class WithClauseTest extends TestDatabaseTest{ @Test public void noSourceOfData() { diff --git a/android/arch/persistence/room/integration/testapp/vo/FunnyNamedEntity.java b/android/arch/persistence/room/integration/testapp/vo/FunnyNamedEntity.java new file mode 100644 index 00000000..20f3c216 --- /dev/null +++ b/android/arch/persistence/room/integration/testapp/vo/FunnyNamedEntity.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.arch.persistence.room.integration.testapp.vo; + +import android.arch.persistence.room.ColumnInfo; +import android.arch.persistence.room.Entity; +import android.arch.persistence.room.PrimaryKey; + +/** + * An entity that was weird names + */ +@Entity(tableName = FunnyNamedEntity.TABLE_NAME) +public class FunnyNamedEntity { + public static final String TABLE_NAME = "funny but not so funny"; + public static final String COLUMN_ID = "_this $is id$"; + public static final String COLUMN_VALUE = "unlikely-Ωşå¨ıünames"; + @PrimaryKey(autoGenerate = true) + @ColumnInfo(name = COLUMN_ID) + private int mId; + @ColumnInfo(name = COLUMN_VALUE) + private String mValue; + + public FunnyNamedEntity(int id, String value) { + mId = id; + mValue = value; + } + + public int getId() { + return mId; + } + + public void setId(int id) { + mId = id; + } + + public String getValue() { + return mValue; + } + + public void setValue(String value) { + mValue = value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FunnyNamedEntity entity = (FunnyNamedEntity) o; + + if (mId != entity.mId) return false; + return mValue != null ? mValue.equals(entity.mValue) : entity.mValue == null; + } + + @Override + public int hashCode() { + int result = mId; + result = 31 * result + (mValue != null ? mValue.hashCode() : 0); + return result; + } +} diff --git a/android/arch/persistence/room/integration/testapp/vo/IntegerPKeyEntity.java b/android/arch/persistence/room/integration/testapp/vo/IntegerPKeyEntity.java new file mode 100644 index 00000000..cae1843e --- /dev/null +++ b/android/arch/persistence/room/integration/testapp/vo/IntegerPKeyEntity.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.arch.persistence.room.integration.testapp.vo; + +import android.arch.persistence.room.Entity; +import android.arch.persistence.room.PrimaryKey; + +@Entity +public class IntegerPKeyEntity { + @PrimaryKey + public Integer pKey; + public String data; +} diff --git a/android/arch/persistence/room/integration/testapp/vo/ObjectPKeyEntity.java b/android/arch/persistence/room/integration/testapp/vo/ObjectPKeyEntity.java new file mode 100644 index 00000000..895a35a2 --- /dev/null +++ b/android/arch/persistence/room/integration/testapp/vo/ObjectPKeyEntity.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.arch.persistence.room.integration.testapp.vo; + +import android.arch.persistence.room.Entity; +import android.arch.persistence.room.PrimaryKey; +import android.support.annotation.NonNull; + +@Entity +public class ObjectPKeyEntity { + @PrimaryKey + @NonNull + public String pKey; + public String data; + + public ObjectPKeyEntity(String pKey, String data) { + this.pKey = pKey; + this.data = data; + } +} diff --git a/android/arch/persistence/room/integration/testapp/vo/PetCouple.java b/android/arch/persistence/room/integration/testapp/vo/PetCouple.java index f27b1313..e5208ed7 100644 --- a/android/arch/persistence/room/integration/testapp/vo/PetCouple.java +++ b/android/arch/persistence/room/integration/testapp/vo/PetCouple.java @@ -20,11 +20,13 @@ import android.arch.persistence.room.Embedded; import android.arch.persistence.room.Entity; import android.arch.persistence.room.PrimaryKey; import android.arch.persistence.room.RoomWarnings; +import android.support.annotation.NonNull; @Entity @SuppressWarnings(RoomWarnings.PRIMARY_KEY_FROM_EMBEDDED_IS_DROPPED) public class PetCouple { @PrimaryKey + @NonNull public String id; @Embedded(prefix = "male_") public Pet male; |