Merge "Supporting auto migrations in MigrationTestHelper." into androidx-main
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
index 16dc991..9938afa4 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
@@ -16,6 +16,7 @@
package androidx.room.writer
+import androidx.annotation.NonNull
import androidx.room.ext.AndroidTypeNames
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.L
@@ -130,7 +131,7 @@
val scope = CodeGenScope(this)
return MethodSpec.methodBuilder("getRequiredAutoMigrationSpecs").apply {
addAnnotation(Override::class.java)
- addModifiers(PROTECTED)
+ addModifiers(PUBLIC)
returns(
ParameterizedTypeName.get(
CommonTypeNames.SET,
@@ -349,13 +350,27 @@
private fun getAutoMigrations(): MethodSpec {
return MethodSpec.methodBuilder("getAutoMigrations").apply {
- addModifiers(PROTECTED)
+ addModifiers(PUBLIC)
addAnnotation(Override::class.java)
+ addParameter(
+ ParameterSpec.builder(
+ ParameterizedTypeName.get(
+ CommonTypeNames.MAP,
+ ParameterizedTypeName.get(
+ ClassName.get(Class::class.java),
+ WildcardTypeName.subtypeOf(RoomTypeNames.AUTO_MIGRATION_SPEC)
+ ),
+ RoomTypeNames.AUTO_MIGRATION_SPEC
+ ),
+ "autoMigrationSpecsMap"
+ ).addAnnotation(NonNull::class.java).build()
+ )
+
returns(ParameterizedTypeName.get(CommonTypeNames.LIST, RoomTypeNames.MIGRATION))
val autoMigrationsList = database.autoMigrations.map { autoMigrationResult ->
if (autoMigrationResult.isSpecProvided) {
CodeBlock.of(
- "new $T(mAutoMigrationSpecs.get($T.class))",
+ "new $T(autoMigrationSpecsMap.get($T.class))",
autoMigrationResult.implTypeName,
autoMigrationResult.specClassName
)
diff --git a/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java b/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
index 5dd84db..e9df8c9 100644
--- a/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
+++ b/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
@@ -1,5 +1,6 @@
package foo.bar;
+import androidx.annotation.NonNull;
import androidx.room.DatabaseConfiguration;
import androidx.room.InvalidationTracker;
import androidx.room.RoomOpenHelper;
@@ -188,13 +189,14 @@
}
@Override
- protected Set<Class<? extends AutoMigrationSpec>> getRequiredAutoMigrationSpecs() {
+ public Set<Class<? extends AutoMigrationSpec>> getRequiredAutoMigrationSpecs() {
final HashSet<Class<? extends AutoMigrationSpec>> _autoMigrationSpecsSet = new HashSet<Class<? extends AutoMigrationSpec>>();
return _autoMigrationSpecsSet;
}
@Override
- protected List<Migration> getAutoMigrations() {
+ public List<Migration> getAutoMigrations(
+ @NonNull Map<Class<? extends AutoMigrationSpec>, AutoMigrationSpec> autoMigrationSpecsMap) {
return Arrays.asList();
}
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
index faabb9d..8c72847 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
@@ -17,11 +17,11 @@
package androidx.room.integration.kotlintestapp.migration
import androidx.room.Room
+import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.room.testing.MigrationTestHelper
import androidx.room.util.TableInfo
import androidx.sqlite.db.SupportSQLiteDatabase
-import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.filters.MediumTest
import androidx.test.platform.app.InstrumentationRegistry
import org.hamcrest.CoreMatchers.`is`
@@ -40,20 +40,21 @@
@get:Rule
var helper: MigrationTestHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
- MigrationDbKotlin::class.java.canonicalName,
- FrameworkSQLiteOpenHelperFactory()
+ MigrationDbKotlin::class.java
)
companion object {
val TEST_DB = "migration-test"
}
+ abstract class EmptyDb : RoomDatabase()
+
@Test
@Throws(IOException::class)
fun giveBadResource() {
val helper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
- "foo", FrameworkSQLiteOpenHelperFactory()
+ EmptyDb::class.java
)
try {
helper.createDatabase(TEST_DB, 1)
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/AutoMigrationTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/AutoMigrationTest.java
index fa6fa9d..3206ff9 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/AutoMigrationTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/AutoMigrationTest.java
@@ -16,17 +16,13 @@
package androidx.room.integration.testapp.migration;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.fail;
-
-import android.database.sqlite.SQLiteException;
import androidx.annotation.NonNull;
-import androidx.room.Room;
import androidx.room.migration.Migration;
import androidx.room.testing.MigrationTestHelper;
+import androidx.room.util.TableInfo;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
@@ -49,88 +45,42 @@
public MigrationTestHelper helper;
public AutoMigrationTest() {
- helper = new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
- AutoMigrationDb.class.getCanonicalName());
+ helper = new MigrationTestHelper(
+ InstrumentationRegistry.getInstrumentation(),
+ AutoMigrationDb.class
+ );
}
// Run this to create the very 1st version of the db.
public void createFirstVersion() throws IOException {
- SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 2);
+ SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 1);
+ db.execSQL("INSERT INTO Entity1 (id, name) VALUES (1, 'row1')");
db.close();
}
- /**
- * Tests the case where a non existent auto migration is called.
- */
- @Test
- public void testBadAutoMigrationInput() throws IOException {
- try (SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 1)) {
- db.execSQL("INSERT INTO Entity1 (id, name) VALUES (1, 'row1')");
- AutoMigrationDb autoMigrationDbV2 = getLatestDb();
- helper.runMigrationsAndValidate(
- TEST_DB,
- 2,
- true,
- autoMigrationDbV2.getAutoGeneratedMigration(3, 4)
- );
- fail();
- } catch (IllegalArgumentException ex) {
- assertThat(
- ex.getMessage(),
- is("No AutoMigrations between versions 'from = 3', 'to = "
- + "4' have been provided. Annotate Database class with @AutoMigration(from = "
- + "3, to = 4) to generate this AutoMigration.")
- );
- }
- }
-
@Test
public void goFromV1ToV2() throws IOException {
- try (SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 1)) {
- db.execSQL("INSERT INTO Entity1 (id, name) VALUES (1, 'row1')");
- }
- AutoMigrationDb autoMigrationDbV2 = getLatestDb();
- helper.runMigrationsAndValidate(
+ createFirstVersion();
+ SupportSQLiteDatabase db = helper.runMigrationsAndValidate(
TEST_DB,
2,
true
);
- assertThat(autoMigrationDbV2.dao().getAllEntity1s().size(), is(1));
+ final TableInfo info = TableInfo.read(db, AutoMigrationDb.Entity1.TABLE_NAME);
+ assertThat(info.columns.size(), is(3));
}
/**
* Verifies that the user defined migration is selected over using an autoMigration.
*/
@Test
- public void goFromV1ToV2WithUserDefinedMigration() throws IOException {
- try (SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 1)) {
- db.execSQL("INSERT INTO Entity1 (id, name) VALUES (1, 'row1')");
- }
-
- try {
- AutoMigrationDb autoMigrationDbV2 = Room.databaseBuilder(
- InstrumentationRegistry.getInstrumentation().getTargetContext(),
- AutoMigrationDb.class, TEST_DB).addMigrations(MIGRATION_1_2).build();
- autoMigrationDbV2.getOpenHelper().getWritableDatabase(); // trigger open
- helper.closeWhenFinished(autoMigrationDbV2);
-
- helper.runMigrationsAndValidate(
- TEST_DB,
- 2,
- true
- );
- } catch (SQLiteException exception) {
- assertThat(exception.getMessage(), containsString("no such table: Entity0"));
- }
- }
-
- private AutoMigrationDb getLatestDb() {
- AutoMigrationDb db = Room.databaseBuilder(
- InstrumentationRegistry.getInstrumentation().getTargetContext(),
- AutoMigrationDb.class, TEST_DB).build();
- db.getOpenHelper().getWritableDatabase(); // trigger open
- helper.closeWhenFinished(db);
- return db;
+ public void testAutoMigrationsNotProcessedBeforeCustomMigrations() throws IOException {
+ helper.runMigrationsAndValidate(
+ TEST_DB,
+ 2,
+ true,
+ MIGRATION_1_2
+ );
}
private static final Migration MIGRATION_1_2 = new Migration(1, 2) {
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/ProvidedAutoMigrationSpecTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/ProvidedAutoMigrationSpecTest.java
index da5c158..6fdb83b 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/ProvidedAutoMigrationSpecTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/ProvidedAutoMigrationSpecTest.java
@@ -27,11 +27,11 @@
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import androidx.room.ProvidedAutoMigrationSpec;
-import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.migration.AutoMigrationSpec;
import androidx.room.testing.MigrationTestHelper;
import androidx.sqlite.db.SupportSQLiteDatabase;
+import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -41,6 +41,8 @@
import org.junit.runner.RunWith;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
/**
* Test custom database migrations.
@@ -53,11 +55,24 @@
new ProvidedAutoMigrationDb.MyProvidedAutoMigration("Hi");
@Rule
- public MigrationTestHelper helper;
+ public MigrationTestHelper helperWithoutSpec;
+ public MigrationTestHelper helperWithSpec;
public ProvidedAutoMigrationSpecTest() {
- helper = new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
- ProvidedAutoMigrationDb.class.getCanonicalName());
+ helperWithoutSpec = new MigrationTestHelper(
+ InstrumentationRegistry.getInstrumentation(),
+ ProvidedAutoMigrationDb.class
+ );
+
+ List<AutoMigrationSpec> specs = new ArrayList<>();
+ specs.add(mProvidedSpec);
+
+ helperWithSpec = new MigrationTestHelper(
+ InstrumentationRegistry.getInstrumentation(),
+ ProvidedAutoMigrationDb.class,
+ specs,
+ new FrameworkSQLiteOpenHelperFactory()
+ );
}
@Database(
@@ -123,15 +138,15 @@
// Run this to create the very 1st version of the db.
public void createFirstVersion() throws IOException {
- SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 2);
+ SupportSQLiteDatabase db = helperWithoutSpec.createDatabase(TEST_DB, 1);
+ db.execSQL("INSERT INTO Entity1 (id, name) VALUES (1, 'row1')");
db.close();
}
@Test
public void testOnPostMigrate() throws IOException {
- SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 1);
- ProvidedAutoMigrationDb autoMigrationDbV2 = getLatestDb();
- helper.runMigrationsAndValidate(
+ createFirstVersion();
+ helperWithSpec.runMigrationsAndValidate(
TEST_DB,
2,
true
@@ -143,32 +158,24 @@
* Verifies that the user defined migration is selected over using an autoMigration.
*/
@Test
- public void testNoSpecProvidedInConfig() {
+ public void testNoSpecProvidedInConfig() throws IOException {
+ createFirstVersion();
try {
- ProvidedAutoMigrationDb autoMigrationDbV2 = Room.databaseBuilder(
- InstrumentationRegistry.getInstrumentation().getTargetContext(),
- ProvidedAutoMigrationDb.class, TEST_DB).build();
+ helperWithoutSpec.runMigrationsAndValidate(
+ TEST_DB,
+ 2,
+ true
+ );
} catch (IllegalArgumentException exception) {
assertThat(
exception.getMessage(),
containsString(
"A required auto migration spec (androidx.room.integration.testapp"
+ ".migration.ProvidedAutoMigrationSpecTest"
- + ".ProvidedAutoMigrationDb.MyProvidedAutoMigration) is "
- + "missing in the database configuration."
+ + ".ProvidedAutoMigrationDb.MyProvidedAutoMigration) has not "
+ + "been provided."
)
);
}
}
-
- private ProvidedAutoMigrationDb getLatestDb() {
- ProvidedAutoMigrationDb db = Room.databaseBuilder(
- InstrumentationRegistry.getInstrumentation().getTargetContext(),
- ProvidedAutoMigrationDb.class, TEST_DB)
- .addAutoMigrationSpec(mProvidedSpec)
- .build();
- db.getOpenHelper().getWritableDatabase(); // trigger open
- helper.closeWhenFinished(db);
- return db;
- }
}
diff --git a/room/runtime/api/current.txt b/room/runtime/api/current.txt
index 50f212f..c6616ad 100644
--- a/room/runtime/api/current.txt
+++ b/room/runtime/api/current.txt
@@ -52,7 +52,6 @@
method protected abstract androidx.room.InvalidationTracker createInvalidationTracker();
method protected abstract androidx.sqlite.db.SupportSQLiteOpenHelper createOpenHelper(androidx.room.DatabaseConfiguration!);
method @Deprecated public void endTransaction();
- method protected java.util.List<androidx.room.migration.Migration!> getAutoMigrations();
method public androidx.room.InvalidationTracker getInvalidationTracker();
method public androidx.sqlite.db.SupportSQLiteOpenHelper getOpenHelper();
method public java.util.concurrent.Executor getQueryExecutor();
diff --git a/room/runtime/api/public_plus_experimental_current.txt b/room/runtime/api/public_plus_experimental_current.txt
index 758a9f6..bc1f3c0 100644
--- a/room/runtime/api/public_plus_experimental_current.txt
+++ b/room/runtime/api/public_plus_experimental_current.txt
@@ -42,6 +42,7 @@
public class Room {
ctor @Deprecated public Room();
method public static <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T!> databaseBuilder(android.content.Context, Class<T!>, String);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static <T, C> T getGeneratedImplementation(Class<C!>, String);
method public static <T extends androidx.room.RoomDatabase> androidx.room.RoomDatabase.Builder<T!> inMemoryDatabaseBuilder(android.content.Context, Class<T!>);
field public static final String MASTER_TABLE_NAME = "room_master_table";
}
@@ -55,7 +56,6 @@
method protected abstract androidx.room.InvalidationTracker createInvalidationTracker();
method protected abstract androidx.sqlite.db.SupportSQLiteOpenHelper createOpenHelper(androidx.room.DatabaseConfiguration!);
method @Deprecated public void endTransaction();
- method protected java.util.List<androidx.room.migration.Migration!> getAutoMigrations();
method public androidx.room.InvalidationTracker getInvalidationTracker();
method public androidx.sqlite.db.SupportSQLiteOpenHelper getOpenHelper();
method public java.util.concurrent.Executor getQueryExecutor();
diff --git a/room/runtime/api/restricted_current.txt b/room/runtime/api/restricted_current.txt
index 14c301a..51e2dac 100644
--- a/room/runtime/api/restricted_current.txt
+++ b/room/runtime/api/restricted_current.txt
@@ -94,7 +94,6 @@
method protected abstract androidx.room.InvalidationTracker createInvalidationTracker();
method protected abstract androidx.sqlite.db.SupportSQLiteOpenHelper createOpenHelper(androidx.room.DatabaseConfiguration!);
method @Deprecated public void endTransaction();
- method protected java.util.List<androidx.room.migration.Migration!> getAutoMigrations();
method public androidx.room.InvalidationTracker getInvalidationTracker();
method public androidx.sqlite.db.SupportSQLiteOpenHelper getOpenHelper();
method public java.util.concurrent.Executor getQueryExecutor();
diff --git a/room/runtime/src/main/java/androidx/room/Room.java b/room/runtime/src/main/java/androidx/room/Room.java
index 6a570c4..d252099 100644
--- a/room/runtime/src/main/java/androidx/room/Room.java
+++ b/room/runtime/src/main/java/androidx/room/Room.java
@@ -19,6 +19,7 @@
import android.content.Context;
import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
/**
* Utility class for Room.
@@ -75,7 +76,9 @@
@SuppressWarnings({"TypeParameterUnusedInFormals", "ClassNewInstance"})
@NonNull
- static <T, C> T getGeneratedImplementation(Class<C> klass, String suffix) {
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public static <T, C> T getGeneratedImplementation(@NonNull Class<C> klass,
+ @NonNull String suffix) {
final String fullPackage = klass.getPackage().getName();
String name = klass.getCanonicalName();
final String postPackageName = fullPackage.isEmpty()
diff --git a/room/runtime/src/main/java/androidx/room/RoomDatabase.java b/room/runtime/src/main/java/androidx/room/RoomDatabase.java
index 0de4563..b6cf417 100644
--- a/room/runtime/src/main/java/androidx/room/RoomDatabase.java
+++ b/room/runtime/src/main/java/androidx/room/RoomDatabase.java
@@ -228,7 +228,7 @@
}
}
- List<Migration> autoMigrations = getAutoMigrations();
+ List<Migration> autoMigrations = getAutoMigrations(mAutoMigrationSpecs);
for (Migration autoMigration : autoMigrations) {
boolean migrationExists = configuration.migrationContainer.getMigrations()
.containsKey(autoMigration.startVersion);
@@ -312,43 +312,16 @@
* Returns a list of {@link Migration} of a database that have been automatically generated.
*
* @return A list of migration instances each of which is a generated autoMigration
- */
- @NonNull
- protected List<Migration> getAutoMigrations() {
- return Collections.emptyList();
- }
-
- /**
- * Returns a {@link Migration} of a database that have been generated using
- * {@link AutoMigration} with the specific "from" and "to" version pair.
- * <p>
- * If a {@link Migration} with the given "from" and "to" versions cannot be found, this
- * method will throw a {@link IllegalArgumentException}.
- *
- * <p>
- * This API is intended for testing and all auto-migrations are added by default.
- *
- * @param from version of the original database schema to migrate from
- * @param to version of the new database schema to migrate to
- * @return migration instance of a generated autoMigration
+ * @param autoMigrationSpecs
*
* @hide
*/
@NonNull
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- public Migration getAutoGeneratedMigration(int from, int to) {
- // TODO: (b/181985265) Support testing automigrations in MigrationTestHelper and remove
- // this method
- List<Migration> autoMigrations = getAutoMigrations();
- for (Migration autoMigration : autoMigrations) {
- if (autoMigration.startVersion == from && autoMigration.endVersion == to) {
- return autoMigration;
- }
- }
- throw new IllegalArgumentException("No AutoMigrations between versions 'from = " + from
- + "', 'to = " + to + "' have been provided. Annotate Database class with "
- + "@AutoMigration(from = " + from + ", to = " + to + ") to generate this "
- + "AutoMigration.");
+ public List<Migration> getAutoMigrations(
+ @NonNull Map<Class<? extends AutoMigrationSpec>, AutoMigrationSpec> autoMigrationSpecs
+ ) {
+ return Collections.emptyList();
}
/**
@@ -428,7 +401,7 @@
*/
@NonNull
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- protected Set<Class<? extends AutoMigrationSpec>> getRequiredAutoMigrationSpecs() {
+ public Set<Class<? extends AutoMigrationSpec>> getRequiredAutoMigrationSpecs() {
return Collections.emptySet();
}
diff --git a/room/testing/api/current.txt b/room/testing/api/current.txt
index 891c1b7..ea0639e 100644
--- a/room/testing/api/current.txt
+++ b/room/testing/api/current.txt
@@ -2,8 +2,11 @@
package androidx.room.testing {
public class MigrationTestHelper extends org.junit.rules.TestWatcher {
- ctor public MigrationTestHelper(android.app.Instrumentation!, String!);
- ctor public MigrationTestHelper(android.app.Instrumentation!, String!, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory!);
+ ctor @Deprecated public MigrationTestHelper(android.app.Instrumentation!, String!);
+ ctor @Deprecated public MigrationTestHelper(android.app.Instrumentation!, String!, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory!);
+ ctor public MigrationTestHelper(android.app.Instrumentation, Class<? extends androidx.room.RoomDatabase>);
+ ctor public MigrationTestHelper(android.app.Instrumentation, Class<? extends androidx.room.RoomDatabase>, java.util.List<androidx.room.migration.AutoMigrationSpec!>);
+ ctor public MigrationTestHelper(android.app.Instrumentation, Class<? extends androidx.room.RoomDatabase>, java.util.List<androidx.room.migration.AutoMigrationSpec!>, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory);
method public void closeWhenFinished(androidx.sqlite.db.SupportSQLiteDatabase!);
method public void closeWhenFinished(androidx.room.RoomDatabase!);
method public androidx.sqlite.db.SupportSQLiteDatabase! createDatabase(String!, int) throws java.io.IOException;
diff --git a/room/testing/api/public_plus_experimental_current.txt b/room/testing/api/public_plus_experimental_current.txt
index 891c1b7..ea0639e 100644
--- a/room/testing/api/public_plus_experimental_current.txt
+++ b/room/testing/api/public_plus_experimental_current.txt
@@ -2,8 +2,11 @@
package androidx.room.testing {
public class MigrationTestHelper extends org.junit.rules.TestWatcher {
- ctor public MigrationTestHelper(android.app.Instrumentation!, String!);
- ctor public MigrationTestHelper(android.app.Instrumentation!, String!, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory!);
+ ctor @Deprecated public MigrationTestHelper(android.app.Instrumentation!, String!);
+ ctor @Deprecated public MigrationTestHelper(android.app.Instrumentation!, String!, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory!);
+ ctor public MigrationTestHelper(android.app.Instrumentation, Class<? extends androidx.room.RoomDatabase>);
+ ctor public MigrationTestHelper(android.app.Instrumentation, Class<? extends androidx.room.RoomDatabase>, java.util.List<androidx.room.migration.AutoMigrationSpec!>);
+ ctor public MigrationTestHelper(android.app.Instrumentation, Class<? extends androidx.room.RoomDatabase>, java.util.List<androidx.room.migration.AutoMigrationSpec!>, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory);
method public void closeWhenFinished(androidx.sqlite.db.SupportSQLiteDatabase!);
method public void closeWhenFinished(androidx.room.RoomDatabase!);
method public androidx.sqlite.db.SupportSQLiteDatabase! createDatabase(String!, int) throws java.io.IOException;
diff --git a/room/testing/api/restricted_current.txt b/room/testing/api/restricted_current.txt
index 891c1b7..ea0639e 100644
--- a/room/testing/api/restricted_current.txt
+++ b/room/testing/api/restricted_current.txt
@@ -2,8 +2,11 @@
package androidx.room.testing {
public class MigrationTestHelper extends org.junit.rules.TestWatcher {
- ctor public MigrationTestHelper(android.app.Instrumentation!, String!);
- ctor public MigrationTestHelper(android.app.Instrumentation!, String!, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory!);
+ ctor @Deprecated public MigrationTestHelper(android.app.Instrumentation!, String!);
+ ctor @Deprecated public MigrationTestHelper(android.app.Instrumentation!, String!, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory!);
+ ctor public MigrationTestHelper(android.app.Instrumentation, Class<? extends androidx.room.RoomDatabase>);
+ ctor public MigrationTestHelper(android.app.Instrumentation, Class<? extends androidx.room.RoomDatabase>, java.util.List<androidx.room.migration.AutoMigrationSpec!>);
+ ctor public MigrationTestHelper(android.app.Instrumentation, Class<? extends androidx.room.RoomDatabase>, java.util.List<androidx.room.migration.AutoMigrationSpec!>, androidx.sqlite.db.SupportSQLiteOpenHelper.Factory);
method public void closeWhenFinished(androidx.sqlite.db.SupportSQLiteDatabase!);
method public void closeWhenFinished(androidx.room.RoomDatabase!);
method public androidx.sqlite.db.SupportSQLiteDatabase! createDatabase(String!, int) throws java.io.IOException;
diff --git a/room/testing/src/main/java/androidx/room/testing/MigrationTestHelper.java b/room/testing/src/main/java/androidx/room/testing/MigrationTestHelper.java
index c846037..02c5192 100644
--- a/room/testing/src/main/java/androidx/room/testing/MigrationTestHelper.java
+++ b/room/testing/src/main/java/androidx/room/testing/MigrationTestHelper.java
@@ -23,12 +23,15 @@
import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.room.AutoMigration;
import androidx.room.DatabaseConfiguration;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.RoomOpenHelper;
import androidx.room.RoomOpenHelper.ValidationResult;
+import androidx.room.migration.AutoMigrationSpec;
import androidx.room.migration.Migration;
import androidx.room.migration.bundle.DatabaseBundle;
import androidx.room.migration.bundle.DatabaseViewBundle;
@@ -91,14 +94,27 @@
private List<WeakReference<RoomDatabase>> mManagedRoomDatabases = new ArrayList<>();
private boolean mTestStarted;
private Instrumentation mInstrumentation;
+ @Nullable
+ private List<AutoMigrationSpec> mSpecs;
+ @Nullable
+ private Class<? extends RoomDatabase> mDatabaseClass;
/**
* Creates a new migration helper. It uses the Instrumentation context to load the schema
* (falls back to the app resources) and the target context to create the database.
*
+ * @deprecated Cannot be used to run migration tests involving {@link AutoMigration}.
+ * <p>
+ * To test {@link AutoMigration}, you must use
+ * {@link #MigrationTestHelper(Instrumentation, Class, List, SupportSQLiteOpenHelper.Factory)}
+ * for tests containing a {@link androidx.room.ProvidedAutoMigrationSpec}, or use
+ * {@link #MigrationTestHelper(Instrumentation, Class, List)}
+ * otherwise.
+ *
* @param instrumentation The instrumentation instance.
* @param assetsFolder The asset folder in the assets directory.
*/
+ @Deprecated
public MigrationTestHelper(Instrumentation instrumentation, String assetsFolder) {
this(instrumentation, assetsFolder, new FrameworkSQLiteOpenHelperFactory());
}
@@ -107,18 +123,88 @@
* Creates a new migration helper. It uses the Instrumentation context to load the schema
* (falls back to the app resources) and the target context to create the database.
*
+ * @deprecated Cannot be used to run migration tests involving {@link AutoMigration}.
+ * <p>
+ * To test {@link AutoMigration}, you must use
+ * {@link #MigrationTestHelper(Instrumentation, Class, List, SupportSQLiteOpenHelper.Factory)}
+ * for tests containing a {@link androidx.room.ProvidedAutoMigrationSpec}, or use
+ * {@link #MigrationTestHelper(Instrumentation, Class, List)}
+ * otherwise.
+ *
* @param instrumentation The instrumentation instance.
* @param assetsFolder The asset folder in the assets directory.
* @param openFactory Factory class that allows creation of {@link SupportSQLiteOpenHelper}
*/
+ @Deprecated
public MigrationTestHelper(Instrumentation instrumentation, String assetsFolder,
SupportSQLiteOpenHelper.Factory openFactory) {
mInstrumentation = instrumentation;
+ mAssetsFolder = assetsFolder;
+ mOpenFactory = openFactory;
+ mDatabaseClass = null;
+ mSpecs = new ArrayList<>();
+ }
+
+ /**
+ * Creates a new migration helper. It uses the Instrumentation context to load the schema
+ * (falls back to the app resources) and the target context to create the database.
+ *
+ * @param instrumentation The instrumentation instance.
+ * @param databaseClass The Database class to be tested.
+ */
+ public MigrationTestHelper(@NonNull Instrumentation instrumentation,
+ @NonNull Class<? extends RoomDatabase> databaseClass) {
+ this(instrumentation, databaseClass, new ArrayList<>(),
+ new FrameworkSQLiteOpenHelperFactory());
+ }
+
+ /**
+ * Creates a new migration helper. It uses the Instrumentation context to load the schema
+ * (falls back to the app resources) and the target context to create the database.
+ * <p>
+ * An instance of a class annotated with {@link androidx.room.ProvidedAutoMigrationSpec} has
+ * to be provided to Room using this constructor. MigrationTestHelper will map auto migration
+ * spec classes to their provided instances before running and validatingt the Migrations.
+ *
+ * @param instrumentation The instrumentation instance.
+ * @param databaseClass The Database class to be tested.
+ * @param specs The list of available auto migration specs that will be provided to
+ * Room at runtime.
+ */
+ public MigrationTestHelper(@NonNull Instrumentation instrumentation,
+ @NonNull Class<? extends RoomDatabase> databaseClass,
+ @NonNull List<AutoMigrationSpec> specs) {
+ this(instrumentation, databaseClass, specs, new FrameworkSQLiteOpenHelperFactory());
+ }
+
+ /**
+ * Creates a new migration helper. It uses the Instrumentation context to load the schema
+ * (falls back to the app resources) and the target context to create the database.
+ * <p>
+ * An instance of a class annotated with {@link androidx.room.ProvidedAutoMigrationSpec} has
+ * to be provided to Room using this constructor. MigrationTestHelper will map auto migration
+ * spec classes to their provided instances before running and validatingt the Migrations.
+ *
+ * @param instrumentation The instrumentation instance.
+ * @param databaseClass The Database class to be tested.
+ * @param specs The list of available auto migration specs that will be provided to
+ * Room at runtime.
+ * @param openFactory Factory class that allows creation of {@link SupportSQLiteOpenHelper}
+ */
+ public MigrationTestHelper(@NonNull Instrumentation instrumentation,
+ @NonNull Class<? extends RoomDatabase> databaseClass,
+ @NonNull List<AutoMigrationSpec> specs,
+ @NonNull SupportSQLiteOpenHelper.Factory openFactory
+ ) {
+ String assetsFolder = databaseClass.getCanonicalName();
+ mInstrumentation = instrumentation;
if (assetsFolder.endsWith("/")) {
assetsFolder = assetsFolder.substring(0, assetsFolder.length() - 1);
}
mAssetsFolder = assetsFolder;
mOpenFactory = openFactory;
+ mDatabaseClass = databaseClass;
+ mSpecs = specs;
}
@Override
@@ -144,7 +230,7 @@
if (dbPath.exists()) {
Log.d(TAG, "deleting database file " + name);
if (!dbPath.delete()) {
- throw new IllegalStateException("there is a database file and i could not delete"
+ throw new IllegalStateException("There is a database file and I could not delete"
+ " it. Make sure you don't have any open connections to that database"
+ " before calling this method.");
}
@@ -214,6 +300,7 @@
}
SchemaBundle schemaBundle = loadSchema(version);
RoomDatabase.MigrationContainer container = new RoomDatabase.MigrationContainer();
+ container.addMigrations(getAutoMigrations(mSpecs));
container.addMigrations(migrations);
DatabaseConfiguration configuration = new DatabaseConfiguration(
mInstrumentation.getTargetContext(),
@@ -244,6 +331,75 @@
return openDatabase(name, roomOpenHelper);
}
+ /**
+ * Returns a list of {@link Migration} of a database that has been generated using
+ * {@link AutoMigration}.
+ */
+ @NonNull
+ private List<Migration> getAutoMigrations(List<AutoMigrationSpec> userProvidedSpecs) {
+ if (mDatabaseClass == null) {
+ if (userProvidedSpecs.isEmpty()) {
+ // TODO: Detect that there are auto migrations to test when a deprecated
+ // constructor is used.
+ Log.e(TAG, "If you have any AutoMigrations in your implementation, you must use "
+ + "a non-deprecated MigrationTestHelper constructor to provide the "
+ + "Database class in order to test them. If you do not have any "
+ + "AutoMigrations to test, you may ignore this warning.");
+ return new ArrayList<>();
+ } else {
+ throw new IllegalStateException("You must provide the database class in the "
+ + "MigrationTestHelper constructor in order to test auto migrations.");
+ }
+ }
+
+ RoomDatabase db = Room.getGeneratedImplementation(mDatabaseClass, "_Impl");
+ Set<Class<? extends AutoMigrationSpec>> requiredAutoMigrationSpecs =
+ db.getRequiredAutoMigrationSpecs();
+ return db.getAutoMigrations(
+ createAutoMigrationSpecMap(requiredAutoMigrationSpecs, userProvidedSpecs)
+ );
+ }
+
+ /**
+ * Maps auto migration spec classes to their provided instance.
+ */
+ private Map<Class<? extends AutoMigrationSpec>, AutoMigrationSpec> createAutoMigrationSpecMap(
+ Set<Class<? extends AutoMigrationSpec>> requiredAutoMigrationSpecs,
+ List<AutoMigrationSpec> userProvidedSpecs) {
+ Map<Class<? extends AutoMigrationSpec>, AutoMigrationSpec> specMap = new HashMap<>();
+ if (requiredAutoMigrationSpecs.isEmpty()) {
+ return specMap;
+ }
+
+ if (userProvidedSpecs == null) {
+ throw new IllegalStateException(
+ "You must provide all required auto migration specs in the "
+ + "MigrationTestHelper constructor."
+ );
+ }
+
+ for (Class<? extends AutoMigrationSpec> spec : requiredAutoMigrationSpecs) {
+ boolean found = false;
+ AutoMigrationSpec match = null;
+ for (AutoMigrationSpec provided : userProvidedSpecs) {
+ if (spec.isAssignableFrom(provided.getClass())) {
+ found = true;
+ match = provided;
+ break;
+ }
+ }
+ if (!found) {
+ throw new IllegalArgumentException(
+ "A required auto migration spec (" + spec.getCanonicalName() + ") has not"
+ + " been provided."
+ );
+ }
+ specMap.put(spec, match);
+ }
+ return specMap;
+ }
+
+
private SupportSQLiteDatabase openDatabase(String name, RoomOpenHelper roomOpenHelper) {
SupportSQLiteOpenHelper.Configuration config =
SupportSQLiteOpenHelper.Configuration
diff --git a/work/workmanager/src/androidTest/java/androidx/work/WorkDatabasePathHelperTest.kt b/work/workmanager/src/androidTest/java/androidx/work/WorkDatabasePathHelperTest.kt
index fc3f164..cd70bd7 100644
--- a/work/workmanager/src/androidTest/java/androidx/work/WorkDatabasePathHelperTest.kt
+++ b/work/workmanager/src/androidTest/java/androidx/work/WorkDatabasePathHelperTest.kt
@@ -37,6 +37,8 @@
@RunWith(AndroidJUnit4::class)
@LargeTest
+@Suppress("DEPRECATION")
+// TODO: (b/189268580) Update this test to use the new constructors in MigrationTestHelper.
class WorkDatabasePathHelperTest {
@get:Rule
val migrationTestHelper = MigrationTestHelper(