diff --git a/app/build.gradle b/app/build.gradle
index 5952355749a..7241b8dc045 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -23,9 +23,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-import com.github.spotbugs.snom.SpotBugsTask
+
import com.github.spotbugs.snom.Confidence
import com.github.spotbugs.snom.Effort
+import com.github.spotbugs.snom.SpotBugsTask
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
@@ -91,6 +92,10 @@ android {
}
}
+ sourceSets {
+ androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
+ }
+
testInstrumentationRunnerArgument "TEST_SERVER_URL", "${NC_TEST_SERVER_BASEURL}"
testInstrumentationRunnerArgument "TEST_SERVER_USERNAME", "${NC_TEST_SERVER_USERNAME}"
testInstrumentationRunnerArgument "TEST_SERVER_PASSWORD", "${NC_TEST_SERVER_PASSWORD}"
@@ -238,6 +243,7 @@ dependencies {
implementation "androidx.room:room-rxjava2:${roomVersion}"
kapt "androidx.room:room-compiler:${roomVersion}"
implementation "androidx.room:room-ktx:${roomVersion}"
+ androidTestImplementation "androidx.room:room-testing:2.6.1"
implementation "org.parceler:parceler-api:$parcelerVersion"
implementation 'eu.davidea:flexible-adapter:5.1.0'
diff --git a/app/src/androidTest/java/com/nextcloud/talk/migrations/MigrationsTest.kt b/app/src/androidTest/java/com/nextcloud/talk/migrations/MigrationsTest.kt
new file mode 100644
index 00000000000..d0a31cc05c9
--- /dev/null
+++ b/app/src/androidTest/java/com/nextcloud/talk/migrations/MigrationsTest.kt
@@ -0,0 +1,71 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Julius Linus
+ * Copyright (C) 2023 Julius Linus
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.nextcloud.talk.migrations
+
+import androidx.room.Room
+import androidx.room.testing.MigrationTestHelper
+import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
+import androidx.test.platform.app.InstrumentationRegistry
+import com.nextcloud.talk.data.source.local.Migrations
+import com.nextcloud.talk.data.source.local.TalkDatabase
+import org.junit.Rule
+import org.junit.Test
+import java.io.IOException
+
+
+class MigrationsTest {
+
+ @get:Rule
+ val helper: MigrationTestHelper = MigrationTestHelper(
+ InstrumentationRegistry.getInstrumentation(),
+ TalkDatabase::class.java.canonicalName!!,
+ FrameworkSQLiteOpenHelperFactory()
+ )
+
+ @Test
+ @Throws(IOException::class)
+ fun migrateAll() {
+ // Create earliest version of the database.
+ helper.createDatabase(TEST_DB, 8).apply {
+ close()
+ }
+
+ // Open latest version of the database. Room validates the schema
+ // once all migrations execute.
+ Room.databaseBuilder(
+ InstrumentationRegistry.getInstrumentation().targetContext,
+ TalkDatabase::class.java,
+ TEST_DB
+ ).addMigrations(*migrations).build().apply {
+ openHelper.writableDatabase.close()
+ }
+ }
+
+ companion object {
+ private const val TEST_DB = "migration-test"
+ private val migrations = arrayOf(
+ Migrations.MIGRATION_6_8,
+ Migrations.MIGRATION_7_8,
+ Migrations.MIGRATION_8_9,
+ Migrations.MIGRATION_9_10
+ )
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
index ce631df93f7..26e55a96158 100644
--- a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
+++ b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
@@ -272,6 +272,7 @@ class MainActivity : BaseActivity(), ActionBarProvider {
} else {
if (!appPreferences.isDbRoomMigrated) {
appPreferences.isDbRoomMigrated = true
+ Log.d("Julius", "isDbRoomMigrated set to true")
}
userManager.users.subscribe(object : SingleObserver> {
diff --git a/app/src/main/java/com/nextcloud/talk/data/source/local/Migrations.kt b/app/src/main/java/com/nextcloud/talk/data/source/local/Migrations.kt
index aca16d0a6b9..6789573f4eb 100644
--- a/app/src/main/java/com/nextcloud/talk/data/source/local/Migrations.kt
+++ b/app/src/main/java/com/nextcloud/talk/data/source/local/Migrations.kt
@@ -47,6 +47,13 @@ object Migrations {
}
}
+ val MIGRATION_9_10 = object : Migration(9, 10) {
+ override fun migrate(db: SupportSQLiteDatabase) {
+ Log.i("Migrations", "Migrating 9 to 10")
+ migrateToTriplePrimaryKeyArbitraryStorage(db)
+ }
+ }
+
fun migrateToRoom(db: SupportSQLiteDatabase) {
db.execSQL(
"CREATE TABLE User_new (" +
@@ -124,4 +131,29 @@ object Migrations {
// Change the table name to the correct one
db.execSQL("ALTER TABLE ArbitraryStorage_dualPK RENAME TO ArbitraryStorage")
}
+
+ fun migrateToTriplePrimaryKeyArbitraryStorage(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ "CREATE TABLE ArbitraryStorage_dualPK (" +
+ "accountIdentifier INTEGER NOT NULL, " +
+ "\"key\" TEXT NOT NULL, " +
+ "object TEXT, " +
+ "value TEXT, " +
+ "PRIMARY KEY(accountIdentifier, \"key\", object)" +
+ ")"
+ )
+ // Copy the data
+ db.execSQL(
+ "INSERT INTO ArbitraryStorage_dualPK (" +
+ "accountIdentifier, \"key\", object, value) " +
+ "SELECT " +
+ "accountIdentifier, \"key\", object, value " +
+ "FROM ArbitraryStorage"
+ )
+ // Remove the old table
+ db.execSQL("DROP TABLE ArbitraryStorage")
+
+ // Change the table name to the correct one
+ db.execSQL("ALTER TABLE ArbitraryStorage_dualPK RENAME TO ArbitraryStorage")
+ }
}
diff --git a/app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt b/app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt
index f736624398a..0825d4a2ccb 100644
--- a/app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt
+++ b/app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt
@@ -45,7 +45,7 @@ import java.util.Locale
@Database(
entities = [UserEntity::class, ArbitraryStorageEntity::class],
- version = 9,
+ version = 10,
exportSchema = true
)
@TypeConverters(
@@ -76,7 +76,7 @@ abstract class TalkDatabase : RoomDatabase() {
val passCharArray = context.getString(R.string.nc_talk_database_encryption_key).toCharArray()
val passphrase: ByteArray = SQLiteDatabase.getBytes(passCharArray)
- val factory = if (appPreferences.isDbRoomMigrated) {
+ val factory = if (appPreferences.isDbRoomMigrated) { // Why isn't this set??? This should be set
Log.i(TAG, "No cipher migration needed")
SupportFactory(passphrase)
} else {
@@ -95,8 +95,13 @@ abstract class TalkDatabase : RoomDatabase() {
return Room
.databaseBuilder(context.applicationContext, TalkDatabase::class.java, dbName)
// NOTE: comment out openHelperFactory to view the database entries in Android Studio for debugging
- .openHelperFactory(factory)
- .addMigrations(Migrations.MIGRATION_6_8, Migrations.MIGRATION_7_8, Migrations.MIGRATION_8_9)
+ // .openHelperFactory(factory) // FIXME crashes when database Migration works
+ .addMigrations(
+ Migrations.MIGRATION_6_8,
+ Migrations.MIGRATION_7_8,
+ Migrations.MIGRATION_8_9,
+ Migrations.MIGRATION_9_10
+ )
.allowMainThreadQueries()
.addCallback(
object : RoomDatabase.Callback() {