Skip to content

test: use in-memory cache store in tests - #1306

Merged
jvsena42 merged 3 commits into
masterfrom
test/1193-deflake-cache-store-tests
Sep 18, 2026
Merged

jvsena42 merged 3 commits into
masterfrom
test/1193-deflake-cache-store-tests

Conversation

@jvsena42

@jvsena42 jvsena42 commented Sep 17, 2026

Copy link
Copy Markdown
Member

Fixes #1193
Related to #1275

This PR:

  1. Uses an in-memory cache store in the QuickPay repository tests
  2. Runs the Lightning service's LDK queue on the test dispatcher in its unit tests

Description

  • Swaps the file-backed cache store in QuickPayRepoTest for an in-memory one, because real disk I/O on Dispatchers.IO let runTest skip virtual time past the QuickPay completion timeout, so tests saw Pending where they expected Success.
  • Adds an internal cache store constructor that takes a DataStore, plus a small in-memory DataStore fake for tests; the injected constructor still uses the app's file-backed store.
  • Makes the LDK queue context a constructor parameter of the Lightning service, because stop() hopped onto the real LDK thread and let virtual time pass the 1s node release timeout before node.destroy() ran.
  • Keeps production behaviour unchanged: the injected constructor passes the same ServiceQueue.LDK context, SupervisorJob included, to all 38 LDK queue calls.

Out of Scope

  • app/src/test: timeouts are not raised; the tests now avoid the real dispatchers instead.
  • Release-gate tests, WatchOnlyAccountLifecycleCoordinatorTest.kt and WatchOnlyAccountRestoreTest.kt: still build the Lightning service with the real LDK queue, on purpose or because they do not mix stop() with virtual time.
  • WatchOnlyAccountRepo: still calls ServiceQueue.LDK.background directly; none of the flaky tests go through it.
  • LightningServiceTest.kt: the test passes a bare dispatcher, without the SupervisorJob production uses; no current test depends on cancellation semantics there.
  • CacheStoreTest.kt: keeps the real file-backed store, since it tests that store.
  • iOS parity: none needed, the change is Android test infrastructure only.
  • Draft PR fix: require accepted onchain broadcasts #1225 also edits QuickPayRepoTest.kt; expect a text conflict there.

Design

N/A — no UI changes.

Preview

N/A

QA Notes

Manual Tests

N/A

Automated Checks

  • Unit tests modified: QuickPayRepoTest.kt uses the in-memory cache store and drops its file reset and teardown.
  • Unit tests modified: LightningServiceTest.kt runs the LDK queue on the test dispatcher.
  • Test helper added: InMemoryDataStore.kt.
  • Ran ./gradlew testDevDebugUnitTest --tests '*LightningServiceTest' --tests '*QuickPayRepoTest' --rerun 10 times locally: all passed (23 and 51 tests). The failures never reproduced locally before the fix either, so this does not prove the fix.
  • Ran just compile, just test (2594 tests, 0 failures) and just lint locally: all passed.
  • To confirm on CI: rerun the unit test workflow on this PR several times and check none of the three tests from fix: flaky unit tests from virtual-time timeouts racing real datastore i/o #1193 fail.

jvsena42 and others added 2 commits September 17, 2026 08:56
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42 jvsena42 self-assigned this Sep 17, 2026
@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge with production queueing and persistence behavior unchanged.

Summary

The PR removes real-dispatcher timing from two unit-test fixtures while preserving production storage and LDK queue behavior.

  • Adds internal injection points for a DataStore<AppCacheData> and the Lightning LDK coroutine context.
  • Introduces a mutex-serialized in-memory DataStore for QuickPayRepoTest.
  • Runs Lightning service LDK operations on the test dispatcher in LightningServiceTest.
  • Keeps dependency-injected production instances on the existing file-backed cache and ServiceQueue.LDK context.

Reviews (1) · Last reviewed commit: "test: run lightning service ldk queue on..."

@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Regtest APK

Built from c5cb0b6 (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@jvsena42
jvsena42 requested a review from ovitrif September 18, 2026 13:26
@jvsena42
jvsena42 enabled auto-merge September 18, 2026 13:56

@ovi-reviewer ovi-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Comment thread app/src/test/java/to/bitkit/services/LightningServiceTest.kt
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utAck - tests only

@jvsena42
jvsena42 merged commit f6a5353 into master Sep 18, 2026
19 checks passed
@jvsena42
jvsena42 deleted the test/1193-deflake-cache-store-tests branch September 18, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: flaky unit tests from virtual-time timeouts racing real datastore i/o

2 participants