Skip to content

Commit 77533d2

Browse files
committed
chore: improve test isolation and update dependencies
- Update GitHub Actions workflow to use gRPC tokens and increased idle timeouts for Android emulators. - Adjust API level 37 to '37.0' in the KMP test matrix. - Bump `androidSqlCipher` to 4.16.0 and `androidxNavigationEvent` to 1.1.0. - Refactor `JvmSafeRepo` and `JdbcDatabaseHolder` to support database path overrides, enabling better test isolation. - Implement temporary file-based database storage for JVM tests to ensure a clean state between runs. - Enhance `NoteUseCaseTest` teardown to explicitly close and delete the database. - Refine iOS database deletion logic to verify file existence before attempting removal.
1 parent 9bfa19f commit 77533d2

7 files changed

Lines changed: 35 additions & 16 deletions

File tree

.github/workflows/kmp.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ jobs:
6262
strategy:
6363
fail-fast: false
6464
matrix:
65-
api-level: [ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 ]
65+
api-level: [ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, '37.0' ]
6666
target: [default]
6767
steps:
6868
- name: Check out
@@ -99,7 +99,7 @@ jobs:
9999
arch: x86_64
100100
profile: Nexus 6
101101
force-avd-creation: false
102-
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
102+
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -grpc-use-token -idle-grpc-timeout 300
103103
disable-animations: false
104104
script: echo "Generated AVD snapshot for caching."
105105
- name: Run UI-tests on emulator
@@ -110,7 +110,7 @@ jobs:
110110
arch: x86_64
111111
profile: Nexus 6
112112
force-avd-creation: false
113-
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
113+
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -grpc-use-token -idle-grpc-timeout 300
114114
disable-animations: true
115115
script: ./gradlew :app:android:connectedCheck
116116
- name: Archive ui-tests-output artifacts

core/data/db-sqldelight/src/commonTest/kotlin/com/softartdev/notedelight/NoteUseCaseTest.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class NoteUseCaseTest : BaseTest() {
4242
@BeforeTest
4343
fun setUp() = runTest {
4444
Logger.setLogWriters(PrintLogWriter())
45+
deleteDb()
4546
val noteDB = noteDB()
4647
noteDAO = safeRepo.noteDAO
4748
createNoteUseCase = CreateNoteUseCase(noteDAO!!)
@@ -52,7 +53,9 @@ class NoteUseCaseTest : BaseTest() {
5253

5354
@AfterTest
5455
fun tearDown() = runTest {
55-
noteDAO!!.deleteAll()
56+
noteDAO?.deleteAll()
57+
safeRepo.closeDatabase()
58+
deleteDb()
5659
noteDAO = null
5760
createNoteUseCase = null
5861
saveNoteUseCase = null
@@ -130,4 +133,4 @@ class NoteUseCaseTest : BaseTest() {
130133
): TestResult = kotlinx.coroutines.test.runTest(context, timeout) {
131134
mutex.withLock { testBody() }
132135
}
133-
}
136+
}

core/data/db-sqldelight/src/iosMain/kotlin/com/softartdev/notedelight/db/IosCipherUtils.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ object IosCipherUtils {
281281
nsFileManager.createDirectoryAtPath(path, true, null, null)
282282
}
283283
val dbPath = getDatabasePath(dbName)
284+
val dbFileExisted = nsFileManager.fileExistsAtPath(dbPath)
284285
val paths = listOf(
285286
dbPath,
286287
"$dbPath-wal",
@@ -293,7 +294,7 @@ object IosCipherUtils {
293294
deleted = nsFileManager.removeItemAtPath(path, null) && deleted
294295
}
295296
}
296-
return deleted
297+
return dbFileExisted && deleted
297298
}
298299

299300
fun checkCipherVersion(dbName: String): String? {

core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JdbcDatabaseHolder.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import java.nio.charset.StandardCharsets
1010
import java.sql.SQLException
1111
import java.util.Properties
1212

13-
class JdbcDatabaseHolder(props: Properties = Properties()) : SqlDelightDbHolder {
13+
class JdbcDatabaseHolder(
14+
props: Properties = Properties(),
15+
dbPath: String = FilePathResolver().invoke()
16+
) : SqlDelightDbHolder {
1417
override val logger = Logger.withTag(this@JdbcDatabaseHolder::class.simpleName.toString())
15-
private val dbPath = FilePathResolver().invoke()
1618

1719
val jdbcUrl: String = buildJdbcUrl(dbPath, props)
1820
override val driver: SqlDriver = createDriver(jdbcUrl, props)

core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/repository/JvmSafeRepo.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import java.util.Properties
1414
class JvmSafeRepo(private val coroutineDispatchers: CoroutineDispatchers) : SafeRepo() {
1515
@Volatile
1616
private var databaseHolder: JdbcDatabaseHolder? = null
17+
private var dbPathOverride: String? = null
1718

1819
override val databaseState: PlatformSQLiteState
1920
get() = JvmCipherUtils.getDatabaseState(dbPath)
@@ -22,14 +23,18 @@ class JvmSafeRepo(private val coroutineDispatchers: CoroutineDispatchers) : Safe
2223
get() = SqlDelightNoteDAO({ databaseHolder!!.noteQueries }, coroutineDispatchers)
2324

2425
override val dbPath: String
25-
get() = FilePathResolver().invoke()
26+
get() = dbPathOverride ?: FilePathResolver().invoke()
27+
28+
internal fun overrideDbPath(dbPath: String) {
29+
dbPathOverride = dbPath
30+
}
2631

2732
override suspend fun buildDbIfNeed(passphrase: CharSequence): JdbcDatabaseHolder {
2833
var instance = databaseHolder
2934
if (instance == null) {
3035
val properties = Properties()
3136
if (passphrase.isNotEmpty()) properties["password"] = StringBuilder(passphrase).toString()
32-
instance = JdbcDatabaseHolder(properties)
37+
instance = JdbcDatabaseHolder(properties, dbPath)
3338
instance.createSchema()
3439
databaseHolder = instance
3540
}
@@ -78,4 +83,4 @@ class JvmSafeRepo(private val coroutineDispatchers: CoroutineDispatchers) : Safe
7883
databaseHolder?.close()
7984
databaseHolder = null
8085
}
81-
}
86+
}

core/data/db-sqldelight/src/jvmTest/kotlin/com/softartdev/notedelight/BaseTest.jvm.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,21 @@ import com.softartdev.notedelight.db.JdbcDatabaseHolder
66
import com.softartdev.notedelight.db.NoteDb
77
import com.softartdev.notedelight.repository.JvmSafeRepo
88
import com.softartdev.notedelight.repository.SafeRepo
9+
import java.io.File
910
import kotlinx.coroutines.ExperimentalCoroutinesApi
1011
import kotlinx.coroutines.test.UnconfinedTestDispatcher
1112

1213
actual abstract class BaseTest actual constructor() {
1314

1415
private var _noteDb: NoteDb? = null
16+
private val testDbFile: File = File.createTempFile("notedelight-test-", ".db").apply {
17+
delete()
18+
deleteOnExit()
19+
}
1520

1621
actual val safeRepo: SafeRepo = JvmSafeRepo(
1722
coroutineDispatchers = CoroutineDispatchersStub(testDispatcher = UnconfinedTestDispatcher())
18-
)
23+
).also { it.overrideDbPath(testDbFile.absolutePath) }
1924

2025
actual suspend fun noteDB(): NoteDb {
2126
if (_noteDb == null) {
@@ -26,5 +31,8 @@ actual abstract class BaseTest actual constructor() {
2631
return _noteDb!!
2732
}
2833

29-
actual fun deleteDb() {}
30-
}
34+
actual fun deleteDb() {
35+
_noteDb = null
36+
testDbFile.delete()
37+
}
38+
}

gradle/libs.versions.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ sqlDelight = "2.3.2"
1111
room = "2.8.4"
1212
androidxSqlite = "2.6.2"
1313
saferoom = "1.4.0"
14-
androidSqlCipher = "4.15.0"
14+
androidSqlCipher = "4.16.0"
1515
iosSqlCipher = "4.9.0"
1616
jdbcSQLite = "3.51.2.0"
1717
koin-bom = "4.2.1"
@@ -28,7 +28,7 @@ androidxBiometric = "1.1.0"
2828
androidxDatastore = "1.2.1"
2929
androidxViewModel = "2.10.0"
3030
androidxNavigation = "2.9.2"
31-
androidxNavigationEvent = "1.0.1"
31+
androidxNavigationEvent = "1.1.0"
3232
androidxActivityCompose = "1.13.0"
3333
androidxComposeTest = "1.11.1"
3434
androidxCoreSplashscreen = "1.2.0"

0 commit comments

Comments
 (0)