app: fix crash when installing module and download size is 0
authorDa Risk <da_risk@geekorum.com>
Sun, 28 Jan 2024 13:56:22 -0400
changeset 1182 0a170c214de9
parent 1181 6a3eb3ff8888
child 1183 22cc664b40bc
app: fix crash when installing module and download size is 0 This seems to happen on some device ro version of play store services
app/build.gradle.kts
app/src/main/java/com/geekorum/ttrss/articles_list/TtrssAccountViewModel.kt
app/src/main/java/com/geekorum/ttrss/on_demand_modules/ImmutableModuleManager.kt
app/src/main/java/com/geekorum/ttrss/on_demand_modules/InstallModuleViewModel.kt
app/src/test/java/com/geekorum/ttrss/on_demand_modules/InstallModuleViewModelTest.kt
gradle/libs.versions.toml
--- a/app/build.gradle.kts	Wed Jan 10 21:30:18 2024 -0400
+++ b/app/build.gradle.kts	Sun Jan 28 13:56:22 2024 -0400
@@ -239,6 +239,7 @@
     implementation(libs.kotlinx.coroutines.android)
     implementation(libs.kotlinx.coroutines.jdk8)
     testImplementation(libs.kotlinx.coroutines.test)
+    testImplementation(libs.turbine)
     androidTestImplementation(libs.kotlinx.coroutines.test)
 
     implementation(enforcedPlatform(libs.firebase.bom))
--- a/app/src/main/java/com/geekorum/ttrss/articles_list/TtrssAccountViewModel.kt	Wed Jan 10 21:30:18 2024 -0400
+++ b/app/src/main/java/com/geekorum/ttrss/articles_list/TtrssAccountViewModel.kt	Sun Jan 28 13:56:22 2024 -0400
@@ -52,8 +52,10 @@
 ): AccountsListViewModel(accountManager, accountSelector, AccountAuthenticator.TTRSS_ACCOUNT_TYPE) {
 
     val selectedAccountHost = selectedAccount.map { account ->
-        val url = accountManager.getUserData(account, AccountAuthenticator.USERDATA_URL)
-        Uri.parse(url).host ?: ""
+        if (account != null) {
+            val url = accountManager.getUserData(account, AccountAuthenticator.USERDATA_URL)
+            Uri.parse(url).host ?: ""
+        } else ""
     }
     private val noAccountSelectedEventSource = MutableLiveData<EmptyEvent>()
     val noAccountSelectedEvent:LiveData<EmptyEvent> = noAccountSelectedEventSource
--- a/app/src/main/java/com/geekorum/ttrss/on_demand_modules/ImmutableModuleManager.kt	Wed Jan 10 21:30:18 2024 -0400
+++ b/app/src/main/java/com/geekorum/ttrss/on_demand_modules/ImmutableModuleManager.kt	Sun Jan 28 13:56:22 2024 -0400
@@ -109,6 +109,10 @@
         emit(state)
         delay(500)
 
+        state = State(State.Status.DOWNLOADING, 0, 0)
+        emit(state)
+        delay(500)
+
         state = State(State.Status.DOWNLOADING, 0, 1000)
         emit(state)
         delay(500)
--- a/app/src/main/java/com/geekorum/ttrss/on_demand_modules/InstallModuleViewModel.kt	Wed Jan 10 21:30:18 2024 -0400
+++ b/app/src/main/java/com/geekorum/ttrss/on_demand_modules/InstallModuleViewModel.kt	Sun Jan 28 13:56:22 2024 -0400
@@ -98,7 +98,7 @@
         }
         val max = 100
         val percent = when (state.status) {
-            DOWNLOADING -> ((state.bytesDownloaded.toFloat() / state.totalBytesDownloaded) * max).roundToInt()
+            DOWNLOADING -> ((state.bytesDownloaded.toFloat() / state.totalBytesDownloaded) * max).takeIf { it.isFinite() }?.roundToInt() ?: 0
             INSTALLED -> 100
             else -> 0
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/src/test/java/com/geekorum/ttrss/on_demand_modules/InstallModuleViewModelTest.kt	Sun Jan 28 13:56:22 2024 -0400
@@ -0,0 +1,91 @@
+/*
+ * Geekttrss is a RSS feed reader application on the Android Platform.
+ *
+ * Copyright (C) 2017-2024 by Frederic-Charles Barthelery.
+ *
+ * This file is part of Geekttrss.
+ *
+ * Geekttrss 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.
+ *
+ * Geekttrss 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 Geekttrss.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.geekorum.ttrss.on_demand_modules
+
+import app.cash.turbine.test
+import com.geekorum.ttrss.R
+import com.geekorum.ttrss.on_demand_modules.InstallSession.State.Status
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.Test
+import kotlin.test.BeforeTest
+
+class InstallModuleViewModelTest {
+    lateinit var subject: InstallModuleViewModel
+
+    private lateinit var mockModuleManager: SuccessfulMockModuleManager
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @BeforeTest
+    fun setUp() {
+        Dispatchers.setMain(StandardTestDispatcher())
+        mockModuleManager = SuccessfulMockModuleManager()
+        subject = InstallModuleViewModel(mockModuleManager)
+    }
+
+    @Test
+    fun testSuccessfulSessionState() = runTest {
+        subject.sessionState.test {
+            assertThat(awaitItem()).isEqualTo(InstallSession.State(Status.PENDING,  0 , 0))
+            subject.startInstallModules("fakemodule")
+
+            assertThat(awaitItem()).isEqualTo(InstallSession.State(Status.DOWNLOADING,  0 , 0))
+            assertThat(awaitItem()).isEqualTo(InstallSession.State(Status.DOWNLOADING,  0 , 1000))
+            assertThat(awaitItem()).isEqualTo(InstallSession.State(Status.DOWNLOADING,  200 , 1000))
+            assertThat(awaitItem()).isEqualTo(InstallSession.State(Status.DOWNLOADING,  700 , 1000))
+            assertThat(awaitItem()).isEqualTo(InstallSession.State(Status.DOWNLOADING,  1000 , 1000))
+            assertThat(awaitItem()).isEqualTo(InstallSession.State(Status.INSTALLING,  1000 , 1000))
+            assertThat(awaitItem()).isEqualTo(InstallSession.State(Status.INSTALLED,  1000 , 1000))
+        }
+    }
+
+    @Test
+    fun testSuccessfulSessionProgress() = runTest {
+        subject.progress.test {
+            assertThat(awaitItem()).isEqualTo(InstallModuleViewModel.InstallProgression(R.string.lbl_download_in_progress, 0, 100, true))
+            subject.startInstallModules("fakemodule")
+
+            assertThat(awaitItem()).isEqualTo(InstallModuleViewModel.InstallProgression(R.string.lbl_download_in_progress, 0, 100, false))
+            assertThat(awaitItem()).isEqualTo(InstallModuleViewModel.InstallProgression(R.string.lbl_download_in_progress, 20, 100, false))
+            assertThat(awaitItem()).isEqualTo(InstallModuleViewModel.InstallProgression(R.string.lbl_download_in_progress, 70, 100, false))
+            assertThat(awaitItem()).isEqualTo(InstallModuleViewModel.InstallProgression(R.string.lbl_download_in_progress, 100, 100, false))
+            assertThat(awaitItem()).isEqualTo(InstallModuleViewModel.InstallProgression(R.string.lbl_install_in_progress, 0, 100, true))
+            assertThat(awaitItem()).isEqualTo(InstallModuleViewModel.InstallProgression(R.string.lbl_install_complete, 100, 100, false))
+        }
+    }
+}
+
+private class SuccessfulMockModuleManager(override val installedModules: Set<String> = emptySet()) : OnDemandModuleManager {
+
+    override fun deferredInstall(vararg modules: String) {}
+
+    override fun uninstall(vararg modules: String) {}
+
+    override suspend fun startInstallModule(vararg modules: String): InstallSession {
+        return MockedSession(1)
+    }
+
+    override val canInstallModule: Boolean = true
+}
\ No newline at end of file
--- a/gradle/libs.versions.toml	Wed Jan 10 21:30:18 2024 -0400
+++ b/gradle/libs.versions.toml	Sun Jan 28 13:56:22 2024 -0400
@@ -53,6 +53,7 @@
 play-publisher = "3.8.6"
 timber = "5.0.1"
 truth = "1.2.0"
+turbine = "1.0.0"
 mockk = "1.13.8"
 firebase-bom = "32.7.0"
 google-play-core = "2.1.0"
@@ -212,6 +213,7 @@
 
 timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
 truth = { module = "com.google.truth:truth", version.ref = "truth" }
+turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
 mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
 
 # Non free