test(subgroups): stop a ceremony-queue test throwing into another test's name
`./gradlew :composeApp:jvmTest` failed `NavigationRoutingTest > an account already on
the device does not stay on the loading screen` with `UncaughtExceptionsBeforeTest:
There were uncaught exceptions before the test started`. **"Before the test started" is
the tell.** `runTest` reports exceptions that reached the default handler before it
began, so the name on the failure is whichever `runTest` ran next -- not the one that
threw. `NavigationRoutingTest` passes alone and the subgroups work never touched it.
The thrower is `CeremonyQueueRoutingJvmTest`, and the chain is five links with no
branch in it:
1. `awaiting()` builds a `ChatMessageListViewModel` on the bare
`NO_OP_NOSTR_REPOSITORY` and calls `initiate()`.
2. `initiate()`'s second line is `scheduleSynchronization()`.
3. That launches on `Dispatchers.IO` and asks `MemberProfileSync` who cannot be named.
4. The fixture's `room()` gives every `LocalParticipant` a `profile = null`, so the
answer is never empty and the next line always runs.
5. `queueNegentropySynchronizeRequest` is one of the **forty-one**
`TODO("Not yet implemented")` bodies on that no-op, out of forty-five members. It
throws in a coroutine nobody awaits, four times a run -- once per test in the class.
Fixed the way this file already fixes it for `DkgRepository`: an `object : X by NO_OP_X`
with the one member overridden. The comment above it carries the chain, because the next
person to see `UncaughtExceptionsBeforeTest` will be reading the name of the wrong test.
**Verified under the condition that reproduced it.** It is order-dependent, so a
filtered run is not evidence -- the culprit passes alone, and the pair passed too. The
full suite under `--rerun-tasks` failed reproducibly before and is 982 of 982 after.
**Not fixed here: the landmine itself.** Sixty `TODO()` bodies sit across four no-op
repositories -- 41 of 45 on `NostrRepository`, 12 of 37 on `ChatRepository`, 6 of 7 on
`MarmotRepository`, 1 of 1 on `SearchRepository` -- and seventeen jvmTest files build
view models on the Nostr one alone, so this will recur; the reporter had already hit it
through `getProfileWithPublicKey`. It is not a sweep, though: "no-op" means something
different for each member, the return types vary from `Unit` to `Flow<Int>`, and a
blanket empty body could make a test pass vacuously where it currently fails honestly.
Sixty judgement calls about shared code do not belong in a commit about one flake, so it
is flagged for its own change.
982 jvm tests, 0 failed, under `--rerun-tasks`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import kotlinx.coroutines.withTimeout
|
||||
import kotlinx.coroutines.delay
|
||||
import press.mantra.compose.database.model.ChatRoom
|
||||
import press.mantra.compose.database.model.DkgSession
|
||||
import press.mantra.compose.database.model.NegentropySynchronizeRequest
|
||||
import press.mantra.compose.database.model.Participant
|
||||
import press.mantra.compose.database.model.intermdiate.LocalChatRoom
|
||||
import press.mantra.compose.database.model.intermdiate.LocalParticipant
|
||||
@@ -151,7 +152,23 @@ class CeremonyQueueRoutingJvmTest {
|
||||
val viewModel = ChatMessageListViewModel(
|
||||
initialChatMessageListUIState = ChatMessageListUIState.Loading,
|
||||
localChatRoom = room(),
|
||||
nostrRepository = NostrRepository.NO_OP_NOSTR_REPOSITORY,
|
||||
// Not the bare no-op. `initiate` calls `scheduleSynchronization` on
|
||||
// its second line, which launches on `Dispatchers.IO` and -- because
|
||||
// `room()` gives every participant a null profile, so there is always
|
||||
// somebody it cannot name -- reaches
|
||||
// `queueNegentropySynchronizeRequest`. That member is one of the
|
||||
// forty-one `TODO("Not yet implemented")` bodies on
|
||||
// NO_OP_NOSTR_REPOSITORY, so it throws in a coroutine nobody awaits.
|
||||
//
|
||||
// Nothing catches it, so it reaches the default handler, and the next
|
||||
// `runTest` in the same JVM reports it as `UncaughtExceptionsBeforeTest`
|
||||
// -- against its own name. That is how this test failed
|
||||
// `NavigationRoutingTest` four times a run while passing itself.
|
||||
nostrRepository = object : NostrRepository by NostrRepository.NO_OP_NOSTR_REPOSITORY {
|
||||
override suspend fun queueNegentropySynchronizeRequest(
|
||||
negentropySynchronizeRequests: List<NegentropySynchronizeRequest>
|
||||
) = Unit
|
||||
},
|
||||
chatRepository = ChatRepository.NO_OP_CHAT_REPOSITORY,
|
||||
frostSigningRepository = FrostSigningRepository.NO_OP_FROST_SIGNING_REPOSITORY,
|
||||
dkgRepository = object : DkgRepository by DkgRepository.NO_OP_DKG_REPOSITORY {
|
||||
|
||||
Reference in New Issue
Block a user