# TL;DR The implementation should always follow the following format: ``` @Database( entities = {}, autoMigrations = { @AutoMigration(from = 1, to = 2), }, version = PlaceholderDatabase.DATABASE_VERSION) public class PlaceholderDatabase extends RoomDatabase { public static final int DATABASE_VERSION = 2; // This is not enforced but a preferred pattern. public static final String DATABASE_NAME = "placeholder.db"; // Singleton and dao declaration. } public class PlaceholderDatabaseMigrationTest { @Test public void testMigration1To2() { // Must create a old version of DB and migrate to new. } } class RoomDatabaseRegistration { private RoomDatabaseRegistration() {} PlaceholderDatabase mPlaceholderDatabase; } ``` You MUST bump up the db version when you make any change to a DB already cutted into an M-train! One version bump per M-train please! You will get pre-submit failure if you don’t do so. # Risk Assessment Database missing migration path or test could result in loss of db data and in worst case a crash and dead database. * A DB fallback to deconstruction can lead to data loss. * A DB failed to test migration path can lead to a deconstruction migration * A deleted/altered field could lead to a crash due to incompatible data The major topic here is enforcing DB version bumped when required, migration paths in place and tested. # Problems and Gap People usually will implement the Dao test to comply with the test coverage and more simply, as a normal implementation. But the problems are: * The database versions easily forget to bump between 2 releases. * We want to limit how people can modify an existing database to avoid potential errors. # Required Checks ## 1. General Requirements * exportSchema must be set to true or leave absent(Default to true) * version attribute must be linked to the const DATABASE_VERSION. * Database must be registered in RoomDatabaseRegistor. * Newest Schema json file must align with the database implementation. ## 2. If a new DB file is created. * VERSION should be 1. * autoMigrations can be missing or empty. ## 3. If VERSION is changed: * A new json file must be created(In case no local build ran). * autoMigrations must be added with all migrations all the way from Version 1. * A class named \MigrationTest must be added or patched with method naming testMigrationTo created. * The new version can only have new tables and/or new columns. ## 4. Version is bumped up between major release(M-train) * If the database is changed after a M-train release, we must bump up the version. # Implementation ## Enforce Database class compliance with Lint Check Enforce the @Database annotation is configured as required. Enforcing DBs are registered in the dedicated register. Implementation RoomDatabaseMigrationDetector.kt ### Limitation On Lint And Fallback to use Unit Test 1. Lint is running on presubmit against adservices-service-core package. It is not possible to validate the schema json file(The file is not included in the apex package because 1. Save space; 2. Not necessary.) 2. For the same reason, to validate the test exists is not possible to be done within lint. ## Enforce Test existence, schema is present, and migration is legit Implementation RoomSchemaMigrationGuardrailTest.java ### Register Database class in a static utility class ``` class RoomDatabaseRegistration { private RoomDatabaseRegistration() {} PlaceholderDatabase mPlaceholderDatabase; // Blablabla. } ``` Perform check on both side: 1. On the code side: Lint should check all classes included in the registration. 2. On the test side, we can implement class use reflection to check required classes and methods. Also provide some flexibility on intentional skip of check. ### Extracting json schema and validate schema change is legit 1. Assert Database version declared in class align with latest json version. * By comparing the create sql statement in json and generated by the class. 2. Assert new field/table only. * By reading the json and comparing the latest VX and the previous VX-1. ### Ensure proper migration tests in place 1. Use reflection to get the migration class with the desired name. 2. Use reflection to verify migration tests exist for each version. ## Enforce Version is bumped up after M-train cut RoomDatabaseVersionBumpGuardrailTest.java This will be done on both pre and post submit. Reading our Unit test package from android-mts.zip from test suite build. Extract json schema files from the Unit Test package of git_udc-mainline-prod and latest M-train build(git_mainline-adservices-release). Ensure no change is made to an existing json file in M-train build. ### Corner Case If we try to cherry-pick a database change into a release, we should bump up the version as well so we don’t have to bypass the check. ## Other considered methods ### Track test existence and schema is present #### Option 2: Run Lint in pre-upload Lint check run in pre-upload may be able to access all files in the whole repo. Pro: Utilize the same code to do all the checks. Cons: The Lint code will need to be run on multi-run. The check can be skipped and left unresolved and can make other teams not using ROOM confused about the error. ### Ensure Version is bumped up accordingly #### Option 2: Bump up version every time we change the db. Pros: Can be done for each change. Cons: This is introducing extra work during implementation possible performance issues during migration.