diff --git a/app/src/androidTest/java/com/samco/trackandgraph/MigrationTests.kt b/app/src/androidTest/java/com/samco/trackandgraph/MigrationTests.kt index 2b7fdc56..65519f98 100644 --- a/app/src/androidTest/java/com/samco/trackandgraph/MigrationTests.kt +++ b/app/src/androidTest/java/com/samco/trackandgraph/MigrationTests.kt @@ -23,6 +23,7 @@ import androidx.test.platform.app.InstrumentationRegistry import androidx.test.runner.AndroidJUnit4 import androidx.room.testing.MigrationTestHelper import com.samco.trackandgraph.database.* +import junit.framework.Assert.assertEquals import junit.framework.Assert.assertTrue import org.junit.After import org.junit.Rule @@ -76,15 +77,49 @@ class MigrationTest { assertTrue(featureStrings.contains("4!!Weather!!0!!0!!0!!0!!0.0!!1.0")) } + @Test + @Throws(IOException::class) + fun testMigrateLineGraphFeatures_31_32_no_values() { + helper.createDatabase(TEST_DB, 31).apply { + this.execSQL("INSERT INTO features_table (id, name, track_group_id, type, discrete_values, display_index) VALUES ('4', 'Weather', '1', '0', '2:Meh||5:Great||3:Ok||4:Good||0:Very Poor||1:Poor', '0');") + this.execSQL("INSERT INTO features_table (id, name, track_group_id, type, discrete_values, display_index) VALUES ('10', 'Anxiety', '1', '0', '0:None||1:Low||2:Medium||3:High', '0');") + this.execSQL("INSERT INTO features_table (id, name, track_group_id, type, discrete_values, display_index) VALUES ('11', 'Stress', '1', '0', '0:None||1:Low||2:Medium||3:High', '0');") + close() + } + } + + @Test + @Throws(IOException::class) + fun testMigrateLineGraphFeatures_31_32_bad_names() { + helper.createDatabase(TEST_DB, 31).apply { + this.execSQL("INSERT INTO features_table (id, name, track_group_id, type, discrete_values, display_index) VALUES ('4', 'Weather''s', '1', '0', '2:Meh||5:Great||3:Ok||4:Good||0:Very Poor||1:Poor', '0');") + this.execSQL("INSERT INTO features_table (id, name, track_group_id, type, discrete_values, display_index) VALUES ('10', 'Anxiety', '1', '0', '0:None||1:Low||2:Medium||3:High', '0');") + this.execSQL("INSERT INTO features_table (id, name, track_group_id, type, discrete_values, display_index) VALUES ('11', 'Stress', '1', '0', '0:None||1:Low||2:Medium||3:High', '0');") + this.execSQL("INSERT INTO graphs_and_stats_table (id, graph_stat_group_id, name, graph_stat_type, display_index) VALUES ('1', '1', 'l1', '0', '1');") + this.execSQL("INSERT INTO graphs_and_stats_table (id, graph_stat_group_id, name, graph_stat_type, display_index) VALUES ('2', '1', 'l2', '0', '0');") + this.execSQL("INSERT INTO line_graphs_table (id, graph_stat_id, features, duration, y_range_type, y_from, y_to) VALUES ('2', '2', '10!!Anxiety!!4!!6!!3!!9.0!!1.01||11!!Stress!!7!!3!!0!!10.0!!0.255', 'PT744H', '1', '-10.0', '10.0');") + this.execSQL("INSERT INTO line_graphs_table (id, graph_stat_id, features, duration, y_range_type, y_from, y_to) VALUES ('1', '1', '4!!Weather''s!!0!!0!!0!!0.0!!1.0', '', '0', '0.0', '1.0');") + close() + } + val db = helper.runMigrationsAndValidate(TEST_DB, 32, true, *allMigrations) + val featuresCursor = db.query("SELECT features FROM line_graphs_table") + val featureStrings = mutableListOf() + while (featuresCursor.moveToNext()) { + featureStrings.add(featuresCursor.getString(0)) + } + assertTrue(featureStrings.contains("10!!Anxiety!!4!!6!!3!!0!!9.0!!1.01||11!!Stress!!7!!3!!0!!0!!10.0!!0.255")) + assertTrue(featureStrings.contains("4!!Weather's!!0!!0!!0!!0!!0.0!!1.0")) + } + @Test @Throws(IOException::class) fun testMigrateLineGraphFeatures_32_33() { helper.createDatabase(TEST_DB, 32).apply { - this.execSQL("INSERT INTO features_table (id, name, track_group_id, type, discrete_values, display_index) VALUES ('4', 'Weather', '1', '0', '2:Meh||5:Great||3:Ok||4:Good||0:Very Poor||1:Poor', '0');") + this.execSQL("INSERT INTO features_table (id, name, track_group_id, type, discrete_values, display_index) VALUES ('4', 'Weather''s', '1', '0', '2:Meh||5:Great||3:Ok||4:Good||0:Very Poor||1:Poor', '0');") this.execSQL("INSERT INTO graphs_and_stats_table (id, graph_stat_group_id, name, graph_stat_type, display_index) VALUES ('1', '1', 'l1', '0', '1');") this.execSQL("INSERT INTO graphs_and_stats_table (id, graph_stat_group_id, name, graph_stat_type, display_index) VALUES ('2', '1', 'l2', '0', '0');") - this.execSQL("INSERT INTO line_graphs_table (id, graph_stat_id, features, duration, y_range_type, y_from, y_to) VALUES ('2', '2', '4!!Weather!!4!!6!!4!!0!!9.0!!1.01||4!!Weather!!7!!3!!0!!1!!10.0!!0.255', 'PT744H', '1', '-10.0', '10.0');") - this.execSQL("INSERT INTO line_graphs_table (id, graph_stat_id, features, duration, y_range_type, y_from, y_to) VALUES ('1', '1', '4!!Weather!!0!!0!!0!!0!!0.0!!1.0||4!!Weather!!7!!3!!1!!1!!10.0!!0.255', '', '0', '0.0', '1.0');") + this.execSQL("INSERT INTO line_graphs_table (id, graph_stat_id, features, duration, y_range_type, y_from, y_to) VALUES ('2', '2', '4!!Weather''s!!4!!6!!4!!0!!9.0!!1.01||4!!Weather!!7!!3!!0!!1!!10.0!!0.255', 'PT744H', '1', '-10.0', '10.0');") + this.execSQL("INSERT INTO line_graphs_table (id, graph_stat_id, features, duration, y_range_type, y_from, y_to) VALUES ('1', '1', '4!!Weather''s!!0!!0!!0!!0!!0.0!!1.0||4!!Weather!!7!!3!!1!!1!!10.0!!0.255', '', '0', '0.0', '1.0');") close() } val db = helper.runMigrationsAndValidate(TEST_DB, 33, true, *allMigrations) @@ -93,8 +128,37 @@ class MigrationTest { while (featuresCursor.moveToNext()) { featureStrings.add(featuresCursor.getString(0)) } - assertTrue(featureStrings.contains("4!!Weather!!4!!6!!5!!0!!9.0!!1.01||4!!Weather!!7!!3!!0!!1!!10.0!!0.255")) - assertTrue(featureStrings.contains("4!!Weather!!0!!0!!0!!0!!0.0!!1.0||4!!Weather!!7!!3!!2!!1!!10.0!!0.255")) + assertTrue(featureStrings.contains("4!!Weather's!!4!!6!!5!!0!!9.0!!1.01||4!!Weather!!7!!3!!0!!1!!10.0!!0.255")) + assertTrue(featureStrings.contains("4!!Weather's!!0!!0!!0!!0!!0.0!!1.0||4!!Weather!!7!!3!!2!!1!!10.0!!0.255")) + } + + @Test + @Throws(IOException::class) + fun testMigrateLineGraphFeatures_34_35() { + helper.createDatabase(TEST_DB, 34).apply { + this.execSQL("INSERT INTO average_time_between_stat_table (id, graph_stat_id, feature_id, from_value, to_value, duration) VALUES (1, 2, 3, 0, 1, 'PT2232H');") + this.execSQL("INSERT INTO time_since_last_stat_table (id, graph_stat_id, feature_id, from_value, to_value) VALUES (2, 3, 4, -5, 10);") + close() + } + val db = helper.runMigrationsAndValidate(TEST_DB, 35, true, *allMigrations) + val avCursor = db.query("SELECT * FROM average_time_between_stat_table") + avCursor.moveToNext() + assertEquals(avCursor.getLong(0), 1) + assertEquals(avCursor.getLong(1), 2) + assertEquals(avCursor.getLong(2), 3) + assertEquals(avCursor.getString(3), "0") + assertEquals(avCursor.getString(4), "1") + assertEquals(avCursor.getString(5), "PT2232H") + assertEquals(avCursor.getString(6), listOf(0, 1).joinToString(splitChars1) { i -> i.toString() }) + + val tsCursor = db.query("SELECT * FROM time_since_last_stat_table") + tsCursor.moveToNext() + assertEquals(tsCursor.getLong(0), 2) + assertEquals(tsCursor.getLong(1), 3) + assertEquals(tsCursor.getLong(2), 4) + assertEquals(tsCursor.getString(3), "-5") + assertEquals(tsCursor.getString(4), "10") + assertEquals(tsCursor.getString(5), listOf(-5, 10).joinToString(splitChars1) { i -> i.toString() }) } private fun tryOpenDatabase() { diff --git a/app/src/main/java/com/samco/trackandgraph/database/DatabaseMigrations.kt b/app/src/main/java/com/samco/trackandgraph/database/DatabaseMigrations.kt index fa8c1275..b66bd63b 100644 --- a/app/src/main/java/com/samco/trackandgraph/database/DatabaseMigrations.kt +++ b/app/src/main/java/com/samco/trackandgraph/database/DatabaseMigrations.kt @@ -29,7 +29,7 @@ val MIGRATION_30_31 = object : Migration(30, 31) { val MIGRATION_31_32 = object : Migration(31, 32) { override fun migrate(database: SupportSQLiteDatabase) { val lineGraphsCursor = database.query("SELECT * FROM line_graphs_table") - val updates = mutableListOf() + val updates = mutableListOf>>() while (lineGraphsCursor.moveToNext()) { val id = lineGraphsCursor.getLong(0) val oldFeaturesString = lineGraphsCursor.getString(2) @@ -40,16 +40,17 @@ val MIGRATION_31_32 = object : Migration(31, 32) { params.joinToString(splitChars2) } val newFeaturesString = newFeatures.joinToString(splitChars1) - updates.add("UPDATE line_graphs_table SET features='$newFeaturesString' WHERE id=$id") + updates.add(Pair("UPDATE line_graphs_table SET features=? WHERE id=?", + listOf(newFeaturesString, id.toString()))) } - if (updates.size > 0) updates.forEach { database.execSQL(it) } + if (updates.size > 0) updates.forEach { database.execSQL(it.first, it.second.toTypedArray()) } } } val MIGRATION_32_33 = object : Migration(32, 33) { override fun migrate(database: SupportSQLiteDatabase) { val lineGraphsCursor = database.query("SELECT * FROM line_graphs_table") - val updates = mutableListOf() + val updates = mutableListOf>>() while (lineGraphsCursor.moveToNext()) { val id = lineGraphsCursor.getLong(0) val oldFeaturesString = lineGraphsCursor.getString(2) @@ -62,9 +63,10 @@ val MIGRATION_32_33 = object : Migration(32, 33) { params.joinToString(splitChars2) } val newFeaturesString = newFeatures.joinToString(splitChars1) - updates.add("UPDATE line_graphs_table SET features='$newFeaturesString' WHERE id=$id") + updates.add(Pair("UPDATE line_graphs_table SET features=? WHERE id=?", + listOf(newFeaturesString, id.toString()))) } - if (updates.size > 0) updates.forEach { database.execSQL(it) } + if (updates.size > 0) updates.forEach { database.execSQL(it.first, it.second.toTypedArray()) } } } @@ -80,15 +82,16 @@ val MIGRATION_34_35 = object : Migration(34, 35) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL("ALTER TABLE average_time_between_stat_table ADD discrete_values TEXT NOT NULL DEFAULT ''") database.execSQL("ALTER TABLE time_since_last_stat_table ADD discrete_values TEXT NOT NULL DEFAULT ''") - val updates = mutableListOf() + val updates = mutableListOf>>() val avTimeCursor = database.query("SELECT * FROM average_time_between_stat_table") while (avTimeCursor.moveToNext()) { val id = avTimeCursor.getLong(0) val from = avTimeCursor.getString(3) val to = avTimeCursor.getString(4) val discreteValues = from + splitChars1 + to - updates.add("UPDATE average_time_between_stat_table " + - "SET discrete_values='$discreteValues' WHERE id=$id") + val query = "UPDATE average_time_between_stat_table SET discrete_values=? WHERE id=?" + val args = listOf(discreteValues, id.toString()) + updates.add(Pair(query, args)) } val timeSinceCursor = database.query("SELECT * FROM time_since_last_stat_table") while (timeSinceCursor.moveToNext()) { @@ -96,10 +99,11 @@ val MIGRATION_34_35 = object : Migration(34, 35) { val from = timeSinceCursor.getString(3) val to = timeSinceCursor.getString(4) val discreteValues = from + splitChars1 + to - updates.add("UPDATE time_since_last_stat_table " + - "SET discrete_values='$discreteValues' WHERE id=$id") + val query = "UPDATE time_since_last_stat_table SET discrete_values=? WHERE id=?" + val args = listOf(discreteValues, id.toString()) + updates.add(Pair(query, args)) } - if (updates.size > 0) updates.forEach { database.execSQL(it) } + if (updates.size > 0) updates.forEach { database.execSQL(it.first, it.second.toTypedArray()) } } }