Skip to content

Commit

Permalink
DB: move migrations to separate files and use DI (#1206)
Browse files Browse the repository at this point in the history
* DB: move migrations to separate files

* Use Hilt for AutoMigrationSpecs

* Tests in separate package

* Use Hilt for explicit Migrations
  • Loading branch information
rfc2822 authored Dec 31, 2024
1 parent 77a795d commit 365f879
Show file tree
Hide file tree
Showing 17 changed files with 543 additions and 342 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package at.bitfire.davdroid.db

import android.content.Context
import androidx.room.Room
import androidx.room.migration.AutoMigrationSpec
import androidx.room.migration.Migration
import androidx.room.testing.MigrationTestHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.platform.app.InstrumentationRegistry
Expand All @@ -24,13 +26,18 @@ class AppDatabaseTest {
@get:Rule
val hiltRule = HiltAndroidRule(this)

@Inject
@ApplicationContext
@Inject @ApplicationContext
lateinit var context: Context

@Inject
lateinit var autoMigrations: Set<@JvmSuppressWildcards AutoMigrationSpec>

@Inject
lateinit var logger: Logger

@Inject
lateinit var manualMigrations: Set<@JvmSuppressWildcards Migration>

@Before
fun setup() {
hiltRule.inject()
Expand All @@ -53,10 +60,10 @@ class AppDatabaseTest {
// open and migrate (to current version) database
Room.databaseBuilder(context, AppDatabase::class.java, TEST_DB)
// manual migrations
.addMigrations(*AppDatabase.manualMigrations)
.addMigrations(*manualMigrations.toTypedArray())
// auto-migrations that need to be specified explicitly
.apply {
for (spec in AppDatabase.getAutoMigrationSpecs(context))
for (spec in autoMigrations)
addAutoMigrationSpec(spec)
}
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package at.bitfire.davdroid.db

import android.content.Context
import androidx.room.Room
import androidx.room.migration.AutoMigrationSpec
import dagger.Module
import dagger.Provides
import dagger.hilt.android.qualifiers.ApplicationContext
Expand All @@ -24,11 +25,14 @@ class MemoryDbModule {

@Provides
@Singleton
fun inMemoryDatabase(@ApplicationContext context: Context): AppDatabase =
fun inMemoryDatabase(
autoMigrations: Set<@JvmSuppressWildcards AutoMigrationSpec>,
@ApplicationContext context: Context
): AppDatabase =
Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
// auto-migration specs that need to be specified explicitly
.apply {
for (spec in AppDatabase.getAutoMigrationSpecs(context)) {
for (spec in autoMigrations) {
addAutoMigrationSpec(spec)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/

package at.bitfire.davdroid.db.migration

import at.bitfire.davdroid.db.Collection.Companion.TYPE_CALENDAR
import at.bitfire.davdroid.db.Service
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test

@HiltAndroidTest
class AutoMigration16Test: DatabaseMigrationTest(toVersion = 16) {

@Test
fun testMigrate_WithTimeZone() = testMigration(
prepare = { db ->
val minimalVTimezone = """
BEGIN:VCALENDAR
VERSION:2.0
PRODID:DAVx5
BEGIN:VTIMEZONE
TZID:America/New_York
END:VTIMEZONE
END:VCALENDAR
""".trimIndent()
db.execSQL(
"INSERT INTO service (id, accountName, type) VALUES (?, ?, ?)",
arrayOf(1, "test", Service.Companion.TYPE_CALDAV)
)
db.execSQL(
"INSERT INTO collection (id, serviceId, type, url, privWriteContent, privUnbind, forceReadOnly, sync, timezone) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
arrayOf(1, 1, TYPE_CALENDAR, "https://example.com", true, true, false, false, minimalVTimezone)
)
}
) { db ->
db.query("SELECT timezoneId FROM collection WHERE id=1").use { cursor ->
cursor.moveToFirst()
assertEquals("America/New_York", cursor.getString(0))
}
}

@Test
fun testMigrate_WithTimeZone_Unparseable() = testMigration(
prepare = { db ->
db.execSQL(
"INSERT INTO service (id, accountName, type) VALUES (?, ?, ?)",
arrayOf(1, "test", Service.Companion.TYPE_CALDAV)
)
db.execSQL(
"INSERT INTO collection (id, serviceId, type, url, privWriteContent, privUnbind, forceReadOnly, sync, timezone) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
arrayOf(1, 1, TYPE_CALENDAR, "https://example.com", true, true, false, false, "Some Garbage Content")
)
}
) { db ->
db.query("SELECT timezoneId FROM collection WHERE id=1").use { cursor ->
cursor.moveToFirst()
assertNull(cursor.getString(0))
}
}

@Test
fun testMigrate_WithoutTimezone() = testMigration(
prepare = { db ->
db.execSQL(
"INSERT INTO service (id, accountName, type) VALUES (?, ?, ?)",
arrayOf(1, "test", Service.Companion.TYPE_CALDAV)
)
db.execSQL(
"INSERT INTO collection (id, serviceId, type, url, privWriteContent, privUnbind, forceReadOnly, sync) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
arrayOf(1, 1, TYPE_CALENDAR, "https://example.com", true, true, false, false)
)
}
) { db ->
db.query("SELECT timezoneId FROM collection WHERE id=1").use { cursor ->
cursor.moveToFirst()
assertNull(cursor.getString(0))
}
}

}
Loading

0 comments on commit 365f879

Please sign in to comment.