From 5c47256b3fdb1a5f0ba4b187dc9009107c195912 Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Sun, 12 Apr 2026 15:45:19 -0500 Subject: [PATCH] test(prefs): migrate DataStore tests from androidHostTest to commonTest (#5092) --- core/prefs/build.gradle.kts | 2 +- .../core/prefs/filter/FilterPrefsTest.kt | 21 ++++++++++--------- .../notification/NotificationPrefsTest.kt | 21 ++++++++++--------- .../meshtastic/core/prefs/tak/TakPrefsTest.kt | 21 ++++++++++++++----- core/repository/build.gradle.kts | 5 ++++- core/testing/build.gradle.kts | 1 + docs/decisions/architecture-review-2026-03.md | 3 ++- feature/wifi-provision/build.gradle.kts | 1 + 8 files changed, 47 insertions(+), 28 deletions(-) rename core/prefs/src/{androidHostTest => commonTest}/kotlin/org/meshtastic/core/prefs/filter/FilterPrefsTest.kt (84%) rename core/prefs/src/{androidHostTest => commonTest}/kotlin/org/meshtastic/core/prefs/notification/NotificationPrefsTest.kt (85%) rename core/prefs/src/{androidHostTest => commonTest}/kotlin/org/meshtastic/core/prefs/tak/TakPrefsTest.kt (79%) diff --git a/core/prefs/build.gradle.kts b/core/prefs/build.gradle.kts index eba3604d7..96bba529e 100644 --- a/core/prefs/build.gradle.kts +++ b/core/prefs/build.gradle.kts @@ -24,7 +24,7 @@ kotlin { android { namespace = "org.meshtastic.core.prefs" androidResources.enable = false - withHostTest { isIncludeAndroidResources = true } + withHostTest {} } sourceSets { diff --git a/core/prefs/src/androidHostTest/kotlin/org/meshtastic/core/prefs/filter/FilterPrefsTest.kt b/core/prefs/src/commonTest/kotlin/org/meshtastic/core/prefs/filter/FilterPrefsTest.kt similarity index 84% rename from core/prefs/src/androidHostTest/kotlin/org/meshtastic/core/prefs/filter/FilterPrefsTest.kt rename to core/prefs/src/commonTest/kotlin/org/meshtastic/core/prefs/filter/FilterPrefsTest.kt index 3ba095531..b38c822fe 100644 --- a/core/prefs/src/androidHostTest/kotlin/org/meshtastic/core/prefs/filter/FilterPrefsTest.kt +++ b/core/prefs/src/commonTest/kotlin/org/meshtastic/core/prefs/filter/FilterPrefsTest.kt @@ -22,18 +22,22 @@ import androidx.datastore.preferences.core.Preferences import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest +import okio.FileSystem +import okio.Path import org.meshtastic.core.di.CoroutineDispatchers import org.meshtastic.core.repository.FilterPrefs -import java.io.File import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue +import kotlin.uuid.ExperimentalUuidApi +import kotlin.uuid.Uuid +@OptIn(ExperimentalUuidApi::class) class FilterPrefsTest { - private lateinit var tmpFolder: File + private lateinit var tmpDir: Path private lateinit var dataStore: DataStore private lateinit var filterPrefs: FilterPrefs @@ -44,15 +48,12 @@ class FilterPrefsTest { @BeforeTest fun setup() { - tmpFolder = - File.createTempFile("filterPrefsTest", null).apply { - delete() - mkdirs() - } + tmpDir = FileSystem.SYSTEM_TEMPORARY_DIRECTORY / "filterPrefsTest-${Uuid.random()}" + FileSystem.SYSTEM.createDirectories(tmpDir) dataStore = - PreferenceDataStoreFactory.create( + PreferenceDataStoreFactory.createWithPath( scope = testScope, - produceFile = { File(tmpFolder, "test.preferences_pb").also { it.createNewFile() } }, + produceFile = { tmpDir / "test.preferences_pb" }, ) dispatchers = CoroutineDispatchers(testDispatcher, testDispatcher, testDispatcher) filterPrefs = FilterPrefsImpl(dataStore, dispatchers) @@ -60,7 +61,7 @@ class FilterPrefsTest { @AfterTest fun tearDown() { - tmpFolder.deleteRecursively() + FileSystem.SYSTEM.deleteRecursively(tmpDir) } @Test fun `filterEnabled defaults to false`() = testScope.runTest { assertFalse(filterPrefs.filterEnabled.value) } diff --git a/core/prefs/src/androidHostTest/kotlin/org/meshtastic/core/prefs/notification/NotificationPrefsTest.kt b/core/prefs/src/commonTest/kotlin/org/meshtastic/core/prefs/notification/NotificationPrefsTest.kt similarity index 85% rename from core/prefs/src/androidHostTest/kotlin/org/meshtastic/core/prefs/notification/NotificationPrefsTest.kt rename to core/prefs/src/commonTest/kotlin/org/meshtastic/core/prefs/notification/NotificationPrefsTest.kt index 51571786c..a5792e800 100644 --- a/core/prefs/src/androidHostTest/kotlin/org/meshtastic/core/prefs/notification/NotificationPrefsTest.kt +++ b/core/prefs/src/commonTest/kotlin/org/meshtastic/core/prefs/notification/NotificationPrefsTest.kt @@ -22,17 +22,21 @@ import androidx.datastore.preferences.core.Preferences import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest +import okio.FileSystem +import okio.Path import org.meshtastic.core.di.CoroutineDispatchers import org.meshtastic.core.repository.NotificationPrefs -import java.io.File import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertFalse import kotlin.test.assertTrue +import kotlin.uuid.ExperimentalUuidApi +import kotlin.uuid.Uuid +@OptIn(ExperimentalUuidApi::class) class NotificationPrefsTest { - private lateinit var tmpFolder: File + private lateinit var tmpDir: Path private lateinit var dataStore: DataStore private lateinit var notificationPrefs: NotificationPrefs @@ -43,15 +47,12 @@ class NotificationPrefsTest { @BeforeTest fun setup() { - tmpFolder = - File.createTempFile("notificationPrefsTest", null).apply { - delete() - mkdirs() - } + tmpDir = FileSystem.SYSTEM_TEMPORARY_DIRECTORY / "notificationPrefsTest-${Uuid.random()}" + FileSystem.SYSTEM.createDirectories(tmpDir) dataStore = - PreferenceDataStoreFactory.create( + PreferenceDataStoreFactory.createWithPath( scope = testScope, - produceFile = { File(tmpFolder, "test.preferences_pb").also { it.createNewFile() } }, + produceFile = { tmpDir / "test.preferences_pb" }, ) dispatchers = CoroutineDispatchers(testDispatcher, testDispatcher, testDispatcher) notificationPrefs = NotificationPrefsImpl(dataStore, dispatchers) @@ -59,7 +60,7 @@ class NotificationPrefsTest { @AfterTest fun tearDown() { - tmpFolder.deleteRecursively() + FileSystem.SYSTEM.deleteRecursively(tmpDir) } @Test diff --git a/core/prefs/src/androidHostTest/kotlin/org/meshtastic/core/prefs/tak/TakPrefsTest.kt b/core/prefs/src/commonTest/kotlin/org/meshtastic/core/prefs/tak/TakPrefsTest.kt similarity index 79% rename from core/prefs/src/androidHostTest/kotlin/org/meshtastic/core/prefs/tak/TakPrefsTest.kt rename to core/prefs/src/commonTest/kotlin/org/meshtastic/core/prefs/tak/TakPrefsTest.kt index caa60fe70..2ad0ad21c 100644 --- a/core/prefs/src/androidHostTest/kotlin/org/meshtastic/core/prefs/tak/TakPrefsTest.kt +++ b/core/prefs/src/commonTest/kotlin/org/meshtastic/core/prefs/tak/TakPrefsTest.kt @@ -22,17 +22,21 @@ import androidx.datastore.preferences.core.Preferences import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest -import org.junit.Rule -import org.junit.rules.TemporaryFolder +import okio.FileSystem +import okio.Path import org.meshtastic.core.di.CoroutineDispatchers import org.meshtastic.core.repository.TakPrefs +import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertFalse import kotlin.test.assertTrue +import kotlin.uuid.ExperimentalUuidApi +import kotlin.uuid.Uuid +@OptIn(ExperimentalUuidApi::class) class TakPrefsTest { - @get:Rule val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build() + private lateinit var tmpDir: Path private lateinit var dataStore: DataStore private lateinit var takPrefs: TakPrefs @@ -43,15 +47,22 @@ class TakPrefsTest { @BeforeTest fun setup() { + tmpDir = FileSystem.SYSTEM_TEMPORARY_DIRECTORY / "takPrefsTest-${Uuid.random()}" + FileSystem.SYSTEM.createDirectories(tmpDir) dataStore = - PreferenceDataStoreFactory.create( + PreferenceDataStoreFactory.createWithPath( scope = testScope, - produceFile = { tmpFolder.newFile("test.preferences_pb") }, + produceFile = { tmpDir / "test.preferences_pb" }, ) dispatchers = CoroutineDispatchers(testDispatcher, testDispatcher, testDispatcher) takPrefs = TakPrefsImpl(dataStore, dispatchers) } + @AfterTest + fun tearDown() { + FileSystem.SYSTEM.deleteRecursively(tmpDir) + } + @Test fun `isTakServerEnabled defaults to false`() = testScope.runTest { assertFalse(takPrefs.isTakServerEnabled.value) } diff --git a/core/repository/build.gradle.kts b/core/repository/build.gradle.kts index 9eb277575..ce7ac4abc 100644 --- a/core/repository/build.gradle.kts +++ b/core/repository/build.gradle.kts @@ -22,7 +22,10 @@ plugins { kotlin { @Suppress("UnstableApiUsage") - android { androidResources.enable = false } + android { + androidResources.enable = false + withHostTest {} + } sourceSets { commonMain.dependencies { diff --git a/core/testing/build.gradle.kts b/core/testing/build.gradle.kts index 53c361a62..25e1a3d91 100644 --- a/core/testing/build.gradle.kts +++ b/core/testing/build.gradle.kts @@ -22,6 +22,7 @@ kotlin { android { namespace = "org.meshtastic.core.testing" androidResources.enable = false + withHostTest {} } sourceSets { diff --git a/docs/decisions/architecture-review-2026-03.md b/docs/decisions/architecture-review-2026-03.md index 4d225d58c..be43f823b 100644 --- a/docs/decisions/architecture-review-2026-03.md +++ b/docs/decisions/architecture-review-2026-03.md @@ -181,10 +181,11 @@ Android uses `@Module`-annotated classes (`CoreDataModule`, `CoreBleAndroidModul 36 `commonTest` files exist but are concentrated in `core:domain` (22 files) and `core:data` (10 files). Limited or zero tests in: - `core:service` (has `ServiceRepositoryImpl`, `DirectRadioControllerImpl`, `MeshServiceOrchestrator`) - `core:network` (has `StreamFrameCodecTest` — 10 tests; `TcpTransport` untested) -- `core:prefs` (preference flows, default values) - `core:ble` (connection state machine) - `core:ui` (utility functions) +`core:prefs` now has 12 `commonTest` tests (3 files: `FilterPrefsTest`, `TakPrefsTest`, `NotificationPrefsTest`) migrated from `androidHostTest` using Okio + `PreferenceDataStoreFactory.createWithPath()` for KMP compatibility. + ### D4. Desktop has 2 tests `desktop/src/test/` contains `DesktopKoinTest.kt` and `DesktopTopLevelDestinationParityTest.kt`. Still needs: diff --git a/feature/wifi-provision/build.gradle.kts b/feature/wifi-provision/build.gradle.kts index 4b44b0544..3ce123dec 100644 --- a/feature/wifi-provision/build.gradle.kts +++ b/feature/wifi-provision/build.gradle.kts @@ -24,6 +24,7 @@ kotlin { android { namespace = "org.meshtastic.feature.wifiprovision" androidResources.enable = false + withHostTest {} } sourceSets {