test: use in-memory cache store in tests - #1306
Conversation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Regtest APKDownload bitkit-dev-debug universal APK (expires in 30 days). |
jvsena42
left a comment
There was a problem hiding this comment.
Approved — no HIGH/MEDIUM findings at head 30be0e17a. (Posted as a comment because GitHub does not allow approving your own PR.)
Reviewed as a production change: ServiceQueue, CacheStore and LightningService gain injection seams. Production wiring is unchanged (details below).
Checked: Verified zero production behaviour change. ServiceQueue.queueContext (app/src/main/java/to/bitkit/async/ServiceQueue.kt:20) returns the same scope.coroutineContext object that is the default argument of background/blocking, and the @Inject constructor of LightningService passes exactly that (app/src/main/java/to/bitkit/services/LightningService.kt:191), so all 38 ServiceQueue.LDK.background(ldkQueue) calls in the service still run on the single-thread ldk-queue dispatcher plus its SupervisorJob; the only observable difference is that the lazy queue thread is created when the singleton is constructed rather than on the first queue call. WatchOnlyAccountRepo still uses the default context, which is the same object. The Hilt wiring is intact: exactly one @Inject constructor per class, @BgDispatcher/@IoDispatcher/@ApplicationContext qualifiers preserved on it, @Singleton unchanged, BaseCoroutineScope(bgDispatcher, TAG) unchanged. CacheStore keeps the same top-level Context.appCacheDataStore delegate with fileName = "app_cache.json" and AppCacheSerializer (app/src/main/java/to/bitkit/data/CacheStore.kt:25-36); no file rename, no migration, no scope/dispatcher change, and the store is resolved the same way at construction. On the test side, InMemoryDataStore.updateData runs the transform on the caller's dispatcher under a mutex and the MutableStateFlow makes data.first() observe the new value, which removes the real Dispatchers.IO hop that let runTest skip past SEND_LN_TIMEOUT; passing testDispatcher as ldkQueue and ioDispatcher keeps stop() and releaseHandle entirely on virtual time so the 1s NODE_RELEASE_TIMEOUT join completes. This covers all three tests listed in #1193. No iOS twin needed.
There was a problem hiding this comment.
Verdict: ✅ Approve
Review: diff 6 files.
Findings:
1 inline (non-blocking)
Audit:
Audited - no findings.
Coverage:
Unit tests: 70% - QuickPayRepoTest.kt and LightningServiceTest.kt cover the three tests the issue names; no test asserts the injected LDK queue.
Reviewed by claude-opus-5-xhigh via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest · audit (author or owner)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jvsena42
left a comment
There was a problem hiding this comment.
Approved — no blocking HIGH/MEDIUM findings at head c5cb0b6d4. (Posted as a comment because GitHub does not allow approving your own PR.)
Checked: Follow-up: Follow-up on c5cb0b6. The only change since 30be0e1 is a two-line comment in LightningServiceTest.kt above the teardown verify(..., timeout(VERIFY_TIMEOUT_MS)) calls. git diff --stat 30be0e17a origin/test/1193-deflake-cache-store-tests shows one file with 2 insertions and no code changes.
Fixes #1193
Related to #1275
This PR:
Description
QuickPayRepoTestfor an in-memory one, because real disk I/O onDispatchers.IOletrunTestskip virtual time past the QuickPay completion timeout, so tests sawPendingwhere they expectedSuccess.DataStore, plus a small in-memoryDataStorefake for tests; the injected constructor still uses the app's file-backed store.stop()hopped onto the real LDK thread and let virtual time pass the 1s node release timeout beforenode.destroy()ran.ServiceQueue.LDKcontext,SupervisorJobincluded, to all 38 LDK queue calls.Out of Scope
app/src/test: timeouts are not raised; the tests now avoid the real dispatchers instead.WatchOnlyAccountLifecycleCoordinatorTest.ktandWatchOnlyAccountRestoreTest.kt: still build the Lightning service with the real LDK queue, on purpose or because they do not mixstop()with virtual time.WatchOnlyAccountRepo: still callsServiceQueue.LDK.backgrounddirectly; none of the flaky tests go through it.LightningServiceTest.kt: the test passes a bare dispatcher, without theSupervisorJobproduction uses; no current test depends on cancellation semantics there.CacheStoreTest.kt: keeps the real file-backed store, since it tests that store.QuickPayRepoTest.kt; expect a text conflict there.Design
N/A — no UI changes.
Preview
N/A
QA Notes
Manual Tests
N/A
Automated Checks
QuickPayRepoTest.ktuses the in-memory cache store and drops its file reset and teardown.LightningServiceTest.ktruns the LDK queue on the test dispatcher.InMemoryDataStore.kt../gradlew testDevDebugUnitTest --tests '*LightningServiceTest' --tests '*QuickPayRepoTest' --rerun10 times locally: all passed (23 and 51 tests). The failures never reproduced locally before the fix either, so this does not prove the fix.just compile,just test(2594 tests, 0 failures) andjust lintlocally: all passed.