Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: do not throw NotImplemented error for existing "legacy database"file if the file is not a sqlite file #147

Merged
merged 2 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteException
import android.database.sqlite.SQLiteOpenHelper
import com.amplitude.common.Logger
import com.amplitude.common.android.LogcatLogger
import com.amplitude.core.Amplitude
import com.amplitude.core.Configuration
Expand Down Expand Up @@ -39,18 +40,25 @@ object DatabaseConstants {
* The SDK doesn't need to write/read from local sqlite database.
* This storage class is used for migrating events only.
*/
class DatabaseStorage(context: Context, databaseName: String) : SQLiteOpenHelper(
class DatabaseStorage(
context: Context,
databaseName: String,
private val logger: Logger
) : SQLiteOpenHelper(
context,
databaseName,
null,
DatabaseConstants.DATABASE_VERSION
) {
private var file: File = context.getDatabasePath(databaseName)
private var isValidDatabaseFile = true
var currentDbVersion: Int = DatabaseConstants.DATABASE_VERSION
private set

override fun onCreate(db: SQLiteDatabase) {
throw NotImplementedError()
// File exists but it is not a legacy database for some reason.
justin-fiedler marked this conversation as resolved.
Show resolved Hide resolved
this.isValidDatabaseFile = false
logger.error("Attempt to re-create existing legacy database file ${file.absolutePath}")
}

override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
Expand Down Expand Up @@ -121,6 +129,10 @@ class DatabaseStorage(context: Context, databaseName: String) : SQLiteOpenHelper
var cursor: Cursor? = null
try {
val db = readableDatabase
if (!isValidDatabaseFile) {
return arrayListOf()
}

cursor = queryDb(
db,
table,
Expand Down Expand Up @@ -220,6 +232,10 @@ class DatabaseStorage(context: Context, databaseName: String) : SQLiteOpenHelper
var cursor: Cursor? = null
try {
val db = readableDatabase
if (!isValidDatabaseFile) {
return null
}

cursor = queryDb(
db,
table,
Expand Down Expand Up @@ -304,7 +320,7 @@ object DatabaseStorageProvider {
val databaseName = getDatabaseName(configuration.instanceName)
var storage = instances[databaseName]
if (storage == null) {
storage = DatabaseStorage(configuration.context, databaseName)
storage = DatabaseStorage(configuration.context, databaseName, configuration.loggerProvider.getLogger(amplitude))
instances[databaseName] = storage
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.amplitude.android.migration
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import com.amplitude.common.jvm.ConsoleLogger
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkConstructor
Expand All @@ -29,17 +30,10 @@ class DatabaseStorageTest {
@BeforeEach
fun setUp() {
context = mockk(relaxed = true)
databaseStorage = DatabaseStorage(context!!, "")
databaseStorage = DatabaseStorage(context!!, "", ConsoleLogger())
db = mockk()
}

@Test
fun databaseStorage_onCreate_throwsNotImplementedError() {
Assertions.assertThrows(NotImplementedError::class.java) {
databaseStorage?.onCreate(db!!)
}
}

@Test
fun databaseStorage_onUpgrade_shouldSaveCurrentDbVersion() {
Assertions.assertEquals(DatabaseConstants.DATABASE_VERSION, databaseStorage?.currentDbVersion)
Expand All @@ -64,7 +58,7 @@ class DatabaseStorageTest {
every { anyConstructed<JSONObject>().put(any(), any<Long>()) } returns JSONObject()
every { anyConstructed<JSONObject>().get("event_id") } returnsMany listOf(1, 2)

val mockedDatabaseStorage = spyk(DatabaseStorage(context!!, ""), recordPrivateCalls = true)
val mockedDatabaseStorage = spyk(DatabaseStorage(context!!, "", ConsoleLogger()), recordPrivateCalls = true)
every {
mockedDatabaseStorage["queryDb"](
any<SQLiteDatabase>(),
Expand All @@ -86,7 +80,7 @@ class DatabaseStorageTest {

@Test
fun databaseStorage_removeEvent_returnsEventsContent() {
val mockedDatabaseStorage = spyk(DatabaseStorage(context!!, ""), recordPrivateCalls = true)
val mockedDatabaseStorage = spyk(DatabaseStorage(context!!, "", ConsoleLogger()), recordPrivateCalls = true)
every { mockedDatabaseStorage.close() } answers { nothing }
every { mockedDatabaseStorage.writableDatabase } returns db
every { db!!.delete(any(), any(), arrayOf("2")) } returns 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.test.core.app.ApplicationProvider
import com.amplitude.android.Amplitude
import com.amplitude.android.Configuration
import com.amplitude.core.Storage
import com.amplitude.core.utilities.ConsoleLoggerProvider
import kotlinx.coroutines.runBlocking
import org.json.JSONArray
import org.junit.Test
Expand Down Expand Up @@ -37,6 +38,11 @@ class RemnantDataMigrationTest {
checkLegacyDataMigration("legacy_v4.sqlite", 4, false)
}

@Test
fun `not database file should not fail`() {
checkLegacyDataMigration("not_db_file", 0)
}

private fun checkLegacyDataMigration(legacyDbName: String, dbVersion: Int, migrateLegacyData: Boolean = true) {
val context = ApplicationProvider.getApplicationContext<Context>()

Expand All @@ -46,13 +52,15 @@ class RemnantDataMigrationTest {
if (inputStream != null) {
copyStream(inputStream, dbPath)
}
val isValidDbFile = inputStream != null && legacyDbName != "not_db_file"

val amplitude = Amplitude(
Configuration(
"test-api-key",
context,
instanceName = instanceName,
migrateLegacyData = migrateLegacyData,
loggerProvider = ConsoleLoggerProvider()
)
)

Expand All @@ -63,7 +71,7 @@ class RemnantDataMigrationTest {
amplitude.isBuilt.await()

val identity = amplitude.idContainer.identityManager.getIdentity()
if (inputStream != null && migrateLegacyData) {
if (isValidDbFile && migrateLegacyData) {
Assertions.assertEquals(deviceId, identity.deviceId)
Assertions.assertEquals(userId, identity.userId)
} else {
Expand All @@ -74,7 +82,7 @@ class RemnantDataMigrationTest {
amplitude.storage.rollover()
amplitude.identifyInterceptStorage.rollover()

if (inputStream != null && migrateLegacyData) {
if (isValidDbFile && migrateLegacyData) {
Assertions.assertEquals(1684219150343, amplitude.storage.read(Storage.Constants.PREVIOUS_SESSION_ID)?.toLongOrNull())
Assertions.assertEquals(1684219150344, amplitude.storage.read(Storage.Constants.LAST_EVENT_TIME)?.toLongOrNull())
Assertions.assertEquals(2, amplitude.storage.read(Storage.Constants.LAST_EVENT_ID)?.toLongOrNull())
Expand All @@ -85,7 +93,7 @@ class RemnantDataMigrationTest {
}

val eventsData = amplitude.storage.readEventsContent()
if (inputStream != null && migrateLegacyData) {
if (isValidDbFile && migrateLegacyData) {
val jsonEvents = JSONArray()
for (eventsPath in eventsData) {
val eventsString = amplitude.storage.getEventsString(eventsPath)
Expand Down Expand Up @@ -128,7 +136,7 @@ class RemnantDataMigrationTest {
}

val interceptedIdentifiesData = amplitude.identifyInterceptStorage.readEventsContent()
if (inputStream != null && dbVersion >= 4 && migrateLegacyData) {
if (isValidDbFile && dbVersion >= 4 && migrateLegacyData) {
val jsonInterceptedIdentifies = JSONArray()
for (eventsPath in interceptedIdentifiesData) {
val eventsString = amplitude.storage.getEventsString(eventsPath)
Expand Down Expand Up @@ -170,7 +178,7 @@ class RemnantDataMigrationTest {
}

// User/device id should not be cleaned.
if (inputStream != null) {
if (isValidDbFile) {
Assertions.assertEquals(deviceId, databaseStorage.getValue(RemnantDataMigration.DEVICE_ID_KEY))
Assertions.assertEquals(userId, databaseStorage.getValue(RemnantDataMigration.USER_ID_KEY))
} else {
Expand Down
1 change: 1 addition & 0 deletions android/src/test/resources/not_db_file
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
It is not a sqlite database.