feat: simulate network failures, deterministic and probabilistic - #128
Open
MaxMichel2 wants to merge 1 commit into
Open
MaxMichel2 wants to merge 1 commit into
MaxMichel2 wants to merge 1 commit into
Conversation
Adds the ability to make an operation fail instead of returning a response - the network-mocking equivalent of a chaos-testing knob for the class of bugs (timeouts, dropped connections) that's hardest to reproduce on demand during manual testing. - OperationMockState.Failure(kind: FailureKind): a new sealed-interface variant alongside Network/Mock. Every request to the operation fails the same way until the selection changes. FailureKind has two values, TIMEOUT and CONNECTION_REFUSED, each mapped in the Ktor plugin to the real exception a Ktor engine throws for the equivalent condition (HttpRequestTimeoutException / kotlinx.io.IOException) so existing app error handling exercises the same code path. - Operation.failureRate (from a new x-devview.failureRate extension field, operation-level only - no spec-wide default, unlike delayMs): each request to an otherwise-mocked operation independently rolls against the configured rate before serving its response. Applies only to requests that would otherwise be mocked; Network passthrough is never affected. - NetworkMockConfig.random: Random, injectable so tests can pin the probabilistic roll deterministically instead of relying on real randomness. - UI: a "Simulate Failure" section in the operation picker page with one row per FailureKind, plus a read-only note showing the configured failure rate when the spec declares one. MockColorScheme gains a failure StatusColors slot; ModelUtils' icon/color extensions and every exhaustive when over OperationMockState (EndpointCard, EndpointStateChip, the operation sheet, the Mocked/Network list filter) updated for the new variant. Breaking (fine during 0.2.0 alphas, matches Operation.method's precedent in alpha03): OperationMockState gains a new sealed subtype, and MockColorScheme gains a new required constructor parameter. Closes #88, #95. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #88, #95.
Stacked on #127 (PR chain: #123 → #124 → #127 → this) — merge in order.
Adds the ability to make an operation fail instead of returning a response — the class of bugs (timeouts, dropped connections) that's hardest to reproduce on demand during manual testing, and most valuable to have mockable.
What changed
OperationMockState.Failure(kind: FailureKind): a new sealed-interface variant alongsideNetwork/Mock. Every request to the operation fails the same way until the selection changes — the deterministic case (feat: simulate network failures #88).FailureKindhasTIMEOUTandCONNECTION_REFUSED, each mapped in the Ktor plugin to the real exception a Ktor engine throws for the equivalent condition (HttpRequestTimeoutException/ a connection-levelkotlinx.io.IOException), so an app's existing error handling exercises the same code path against the simulated failure.Operation.failureRate(from a newx-devview.failureRateextension field) — the probabilistic case (feat: probabilistic failure-rate injection #95). Deliberately operation-level only, with no spec-wide default (unlikedelayMs) — "some percentage of everything fails" is a much blunter tool than "this specific flaky endpoint fails sometimes." Each request to an otherwise-mocked operation independently rolls against the configured rate before serving its response; an operation left onNetworkpassthrough is never affected.NetworkMockConfig.random: Random: injectable, defaults toRandom.Default, so tests pin the probabilistic roll deterministically instead of relying on real randomness.FailureKind, plus a read-only note showing the configured failure rate when the spec declares one.Public API (breaking, per your call on 0.2.0 alphas)
OperationMockStategains a new sealed subtype (Failure) — any exhaustivewhenan integrator has over it needs a new branch. Updated internally:EndpointCard,EndpointStateChip,NetworkMockOperationSheet's selected-response lookup,ModelUtils' icon/color extensions, andNetworkMockScreen's Mocked/Network list filter (foldsFailureinto "Mocked", since it's a deliberately-configured non-default state likeMock).MockColorSchemegains a new required constructor parameter (failure: StatusColors) — matchesOperation.method's precedent in alpha03.api.txtregenerated for all three affected modules (devview-networkmock-core,devview-networkmock-ktor,devview-networkmock) viametalavaGenerateSignature.Tests
MockConfigRepositoryTest:x-devview.failureRateparses as operation-level with no spec-wide default.MockStateRepositoryTest:Failurestate round-trips through the real DataStore JSON encode/decode path.NetworkMockPluginTest: deterministicFailure(TIMEOUT)/Failure(CONNECTION_REFUSED)throw the right exception type; a fakeRandompinned to "always hits"/"always misses" proves the probabilistic roll; the roll is confirmed to not apply when the endpoint state isNetwork.Docs updated:
networkmock-core.md(new "Simulating failures" section),networkmock-ui.md,networkmock-workflows.md(new workflow),theming.md, and all three moduleCLAUDE.mdfiles.Verification
All green, including a full repo-wide
testAndroidHostTestrun to confirm no fallout outside the networkmock modules.🤖 Generated with Claude Code