Coverage Summary for Class: MigrationManager (cloud.mindbox.mobile_sdk.utils)

Class Method, % Branch, % Line, % Instruction, %
MigrationManager 100% (7/7) 50% (4/8) 100% (29/29) 98.5% (201/204)
MigrationManager$gson$2 100% (1/1) 100% (1/1) 100% (2/2)
MigrationManager$migrateAll$1
MigrationManager$migrateAll$3$job$1 100% (1/1) 50% (1/2) 100% (3/3) 100% (22/22)
MigrationManager$Migration
MigrationManager$timeProvider$2 100% (1/1) 100% (1/1) 100% (2/2)
MigrationManager$version2120$1 50% (2/4) 12.5% (2/16) 18.8% (3/16) 15.5% (17/110)
MigrationManager$version2140$1 100% (4/4) 75% (3/4) 100% (11/11) 97.2% (69/71)
MigrationManager$version2140$1$run$newMapString$1 100% (1/1) 100% (1/1) 100% (9/9)
MigrationManager$version2140$1$run$newMapString$1$invoke$$inlined$toJsonTyped$1 0% (0/1)
MigrationManager$version2140$1$run$oldShownInApps$1 100% (1/1) 50% (1/2) 66.7% (2/3) 86.7% (13/15)
MigrationManager$version2140$1$run$oldShownInApps$1$invoke$$inlined$fromJsonTyped$1 0% (0/1)
MigrationManager$version2150$1 100% (4/4) 80% (8/10) 100% (15/15) 95.9% (70/73)
MigrationManager$version290$1 100% (4/4) 100% (9/9) 100% (53/53)
MigrationManager$version290$1$run$newMapString$1 100% (1/1) 100% (1/1) 100% (10/10)
MigrationManager$version290$1$run$newMapString$1$1 100% (1/1) 100% (1/1) 100% (2/2)
MigrationManager$version290$1$run$oldShownInApps$1 100% (1/1) 50% (1/2) 75% (3/4) 86.7% (13/15)
MigrationManager$version290$1$run$oldShownInApps$1$1 100% (1/1) 100% (1/1) 100% (2/2)
Total 88.2% (30/34) 45.5% (20/44) 84.4% (81/96) 82.2% (485/590)


 package cloud.mindbox.mobile_sdk.utils
 
 import android.content.Context
 import cloud.mindbox.mobile_sdk.InitializeLock
 import cloud.mindbox.mobile_sdk.Mindbox
 import cloud.mindbox.mobile_sdk.di.mindboxInject
 import cloud.mindbox.mobile_sdk.fromJsonTyped
 import cloud.mindbox.mobile_sdk.logger.MindboxLog
 import cloud.mindbox.mobile_sdk.logger.mindboxLogI
 import cloud.mindbox.mobile_sdk.managers.SharedPreferencesManager
 import cloud.mindbox.mobile_sdk.models.convertToIso8601String
 import cloud.mindbox.mobile_sdk.models.toTimestamp
 import cloud.mindbox.mobile_sdk.pushes.PrefPushToken
 import cloud.mindbox.mobile_sdk.repository.MindboxPreferences
 import cloud.mindbox.mobile_sdk.toJsonTyped
 import com.google.gson.reflect.TypeToken
 import kotlinx.coroutines.launch
 import java.text.SimpleDateFormat
 import java.util.Date
 import java.util.Locale
 
 internal class MigrationManager(val context: Context) : MindboxLog {
 
     @Volatile
     private var isMigrating = false
 
     private val gson by mindboxInject { gson }
     private val timeProvider by mindboxInject { timeProvider }
 
     suspend fun migrateAll() {
         if (isMigrating) return
         mindboxLogI("Check migrations needed")
 
         if (MindboxPreferences.isFirstInitialize) {
             MindboxPreferences.versionCode = Constants.SDK_VERSION_CODE
         }
 
         isMigrating = true
         listOf(
             version290(),
             version2120(),
             version2140(),
             version2150()
         ).filter { it.isNeeded }
             .onEach { migration ->
                 val job = Mindbox.mindboxScope.launch {
                     if (migration.isNeeded) {
                         logI("Run migration '${migration.description}'")
                         migration.run()
                     }
                 }
                 job.join()
             }.also {
                 if (MindboxPreferences.versionCode != Constants.SDK_VERSION_CODE) {
                     logE("Migrations failed, reset memory")
                     MindboxPreferences.softReset()
                     MindboxPreferences.versionCode = Constants.SDK_VERSION_CODE
                 }
             }
 
         InitializeLock.complete(InitializeLock.State.MIGRATION)
     }
 
     private interface Migration {
         val description: String
         val isNeeded: Boolean
 
         suspend fun run()
     }
 
     private fun version290() = object : Migration {
         override val description: String
             get() = "Replaces set of shown inapps to map of inapp metadata"
         override val isNeeded: Boolean
             get() = MindboxPreferences.shownInAppIds != ""
 
         override suspend fun run() {
             val oldShownInApps = LoggingExceptionHandler.runCatching<Set<String>>(HashSet()) {
                 gson.fromJson(
                     MindboxPreferences.shownInAppIds,
                     object : TypeToken<HashSet<String>>() {}.type
                 ) ?: emptySet()
             }
             val newShownInApps = oldShownInApps.associateWith {
                 0L
             }
             val newMapString = LoggingExceptionHandler.runCatching("") {
                 gson.toJson(newShownInApps, object : TypeToken<HashMap<String, Long>>() {}.type)
             }
             MindboxPreferences.shownInApps = newMapString
             MindboxPreferences.shownInAppIds = ""
         }
     }
 
     private fun version2120() = object : Migration {
         val VERSION_CODE = 2
 
         override val description: String
             get() = "Changes the push token save format to multiple tokens with providers."
         override val isNeeded: Boolean
             get() = (MindboxPreferences.versionCode ?: 0) < VERSION_CODE
 
         override suspend fun run() {
             val provider = SharedPreferencesManager.getString("key_notification_provider")
             val token = SharedPreferencesManager.getString("key_firebase_token")
             val updateDate = SharedPreferencesManager.getString("key_firebase_token_save_date")
 
             SharedPreferencesManager.remove("key_notification_provider")
             SharedPreferencesManager.remove("key_firebase_token")
             SharedPreferencesManager.remove("key_firebase_token_save_date")
             val savedTokens = MindboxPreferences.pushTokens
             if (token != null && provider != null && savedTokens.isEmpty()) {
                 val timestamp: Long? = updateDate?.let {
                     SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH).parse(it)?.time
                 }
                 MindboxPreferences.pushTokens = mapOf(provider to PrefPushToken(token, timestamp ?: Date().time))
             }
 
             MindboxPreferences.versionCode = VERSION_CODE
         }
     }
 
     private fun version2140() = object : Migration {
         val VERSION_CODE = 3
 
         override val description: String
             get() = "Changes the format of shown in-app messages from Map<String, Long> to Map<String, List<Long>>"
         override val isNeeded: Boolean
             get() = (MindboxPreferences.versionCode ?: 0) < VERSION_CODE
 
         override suspend fun run() {
             val oldShownInApps = loggingRunCatching(emptyMap()) {
                 gson.fromJsonTyped<Map<String, Long>>(
                     MindboxPreferences.shownInApps
                 ) ?: emptyMap()
             }
 
             val newShownInApps = oldShownInApps.mapValues { (_, timestamp) ->
                 listOf(timestamp)
             }
 
             val newMapString = loggingRunCatching("") {
                 gson.toJsonTyped<Map<String, List<Long>>>(newShownInApps)
             }
 
             MindboxPreferences.shownInApps = newMapString
             SharedPreferencesManager.remove("SHOWN_IDS")
             MindboxPreferences.versionCode = VERSION_CODE
         }
     }
 
     private fun version2150() = object : Migration {
         val VERSION_CODE = 4
 
         override val description: String
             get() = "Stores the first SDK initialization time"
         override val isNeeded: Boolean
             get() = (MindboxPreferences.versionCode ?: 0) < VERSION_CODE
 
         override suspend fun run() {
             if (MindboxPreferences.firstInitializationTime == null) {
                 val firstInitTimestamp = MindboxPreferences.pushTokens.values
                     .map { token -> token.updateDate }
                     .filter { timestamp -> timestamp > 0L }
                     .minOrNull()
                     ?: timeProvider.currentTimestamp().ms
                 MindboxPreferences.firstInitializationTime =
                     firstInitTimestamp
                         .toTimestamp()
                         .convertToIso8601String()
             }
             MindboxPreferences.versionCode = VERSION_CODE
         }
     }
 }