@opensip-cli/simulation 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +31 -0
- package/dist/__tests__/internal-surface.test.d.ts +9 -0
- package/dist/__tests__/internal-surface.test.d.ts.map +1 -0
- package/dist/__tests__/internal-surface.test.js +38 -0
- package/dist/__tests__/internal-surface.test.js.map +1 -0
- package/dist/__tests__/plugin-loader.test.d.ts +2 -0
- package/dist/__tests__/plugin-loader.test.d.ts.map +1 -0
- package/dist/__tests__/plugin-loader.test.js +64 -0
- package/dist/__tests__/plugin-loader.test.js.map +1 -0
- package/dist/__tests__/public-api.test.d.ts +15 -0
- package/dist/__tests__/public-api.test.d.ts.map +1 -0
- package/dist/__tests__/public-api.test.js +73 -0
- package/dist/__tests__/public-api.test.js.map +1 -0
- package/dist/__tests__/registry-cross-kind.test.d.ts +6 -0
- package/dist/__tests__/registry-cross-kind.test.d.ts.map +1 -0
- package/dist/__tests__/registry-cross-kind.test.js +86 -0
- package/dist/__tests__/registry-cross-kind.test.js.map +1 -0
- package/dist/__tests__/scenario-execution.test.d.ts +10 -0
- package/dist/__tests__/scenario-execution.test.d.ts.map +1 -0
- package/dist/__tests__/scenario-execution.test.js +92 -0
- package/dist/__tests__/scenario-execution.test.js.map +1 -0
- package/dist/__tests__/sim-capability-contract.test.d.ts +10 -0
- package/dist/__tests__/sim-capability-contract.test.d.ts.map +1 -0
- package/dist/__tests__/sim-capability-contract.test.js +131 -0
- package/dist/__tests__/sim-capability-contract.test.js.map +1 -0
- package/dist/__tests__/sim-config-schema.test.d.ts +5 -0
- package/dist/__tests__/sim-config-schema.test.d.ts.map +1 -0
- package/dist/__tests__/sim-config-schema.test.js +23 -0
- package/dist/__tests__/sim-config-schema.test.js.map +1 -0
- package/dist/__tests__/sim-failure-signal.test.d.ts +10 -0
- package/dist/__tests__/sim-failure-signal.test.d.ts.map +1 -0
- package/dist/__tests__/sim-failure-signal.test.js +86 -0
- package/dist/__tests__/sim-failure-signal.test.js.map +1 -0
- package/dist/__tests__/surviving-surface-edges.test.d.ts +10 -0
- package/dist/__tests__/surviving-surface-edges.test.d.ts.map +1 -0
- package/dist/__tests__/surviving-surface-edges.test.js +122 -0
- package/dist/__tests__/surviving-surface-edges.test.js.map +1 -0
- package/dist/__tests__/test-utils/targets.d.ts +26 -0
- package/dist/__tests__/test-utils/targets.d.ts.map +1 -0
- package/dist/__tests__/test-utils/targets.js +38 -0
- package/dist/__tests__/test-utils/targets.js.map +1 -0
- package/dist/__tests__/test-utils/with-sim-scope.d.ts +12 -0
- package/dist/__tests__/test-utils/with-sim-scope.d.ts.map +1 -0
- package/dist/__tests__/test-utils/with-sim-scope.js +22 -0
- package/dist/__tests__/test-utils/with-sim-scope.js.map +1 -0
- package/dist/__tests__/tool-live-view.test.d.ts +20 -0
- package/dist/__tests__/tool-live-view.test.d.ts.map +1 -0
- package/dist/__tests__/tool-live-view.test.js +146 -0
- package/dist/__tests__/tool-live-view.test.js.map +1 -0
- package/dist/__tests__/tool-show-mode.test.d.ts +10 -0
- package/dist/__tests__/tool-show-mode.test.d.ts.map +1 -0
- package/dist/__tests__/tool-show-mode.test.js +156 -0
- package/dist/__tests__/tool-show-mode.test.js.map +1 -0
- package/dist/__tests__/tool.test.d.ts +15 -0
- package/dist/__tests__/tool.test.d.ts.map +1 -0
- package/dist/__tests__/tool.test.js +250 -0
- package/dist/__tests__/tool.test.js.map +1 -0
- package/dist/cli/__tests__/sim-config.test.d.ts +2 -0
- package/dist/cli/__tests__/sim-config.test.d.ts.map +1 -0
- package/dist/cli/__tests__/sim-config.test.js +94 -0
- package/dist/cli/__tests__/sim-config.test.js.map +1 -0
- package/dist/cli/__tests__/sim-runner.test.d.ts +23 -0
- package/dist/cli/__tests__/sim-runner.test.d.ts.map +1 -0
- package/dist/cli/__tests__/sim-runner.test.js +188 -0
- package/dist/cli/__tests__/sim-runner.test.js.map +1 -0
- package/dist/cli/__tests__/sim-worker.test.d.ts +12 -0
- package/dist/cli/__tests__/sim-worker.test.d.ts.map +1 -0
- package/dist/cli/__tests__/sim-worker.test.js +69 -0
- package/dist/cli/__tests__/sim-worker.test.js.map +1 -0
- package/dist/cli/__tests__/sim.test.d.ts +2 -0
- package/dist/cli/__tests__/sim.test.d.ts.map +1 -0
- package/dist/cli/__tests__/sim.test.js +232 -0
- package/dist/cli/__tests__/sim.test.js.map +1 -0
- package/dist/cli/sim-config-schema.d.ts +30 -0
- package/dist/cli/sim-config-schema.d.ts.map +1 -0
- package/dist/cli/sim-config-schema.js +33 -0
- package/dist/cli/sim-config-schema.js.map +1 -0
- package/dist/cli/sim-config.d.ts +22 -0
- package/dist/cli/sim-config.d.ts.map +1 -0
- package/dist/cli/sim-config.js +73 -0
- package/dist/cli/sim-config.js.map +1 -0
- package/dist/cli/sim-runner.d.ts +60 -0
- package/dist/cli/sim-runner.d.ts.map +1 -0
- package/dist/cli/sim-runner.js +175 -0
- package/dist/cli/sim-runner.js.map +1 -0
- package/dist/cli/sim-worker.d.ts +24 -0
- package/dist/cli/sim-worker.d.ts.map +1 -0
- package/dist/cli/sim-worker.js +65 -0
- package/dist/cli/sim-worker.js.map +1 -0
- package/dist/cli/sim.d.ts +56 -0
- package/dist/cli/sim.d.ts.map +1 -0
- package/dist/cli/sim.js +265 -0
- package/dist/cli/sim.js.map +1 -0
- package/dist/framework/__tests__/assertions.test.d.ts +2 -0
- package/dist/framework/__tests__/assertions.test.d.ts.map +1 -0
- package/dist/framework/__tests__/assertions.test.js +122 -0
- package/dist/framework/__tests__/assertions.test.js.map +1 -0
- package/dist/framework/__tests__/misc-coverage.test.d.ts +18 -0
- package/dist/framework/__tests__/misc-coverage.test.d.ts.map +1 -0
- package/dist/framework/__tests__/misc-coverage.test.js +142 -0
- package/dist/framework/__tests__/misc-coverage.test.js.map +1 -0
- package/dist/framework/__tests__/resolve-metric.test.d.ts +12 -0
- package/dist/framework/__tests__/resolve-metric.test.d.ts.map +1 -0
- package/dist/framework/__tests__/resolve-metric.test.js +124 -0
- package/dist/framework/__tests__/resolve-metric.test.js.map +1 -0
- package/dist/framework/__tests__/result-builder.test.d.ts +2 -0
- package/dist/framework/__tests__/result-builder.test.d.ts.map +1 -0
- package/dist/framework/__tests__/result-builder.test.js +180 -0
- package/dist/framework/__tests__/result-builder.test.js.map +1 -0
- package/dist/framework/__tests__/scenario-logger.test.d.ts +9 -0
- package/dist/framework/__tests__/scenario-logger.test.d.ts.map +1 -0
- package/dist/framework/__tests__/scenario-logger.test.js +110 -0
- package/dist/framework/__tests__/scenario-logger.test.js.map +1 -0
- package/dist/framework/__tests__/validation.test.d.ts +9 -0
- package/dist/framework/__tests__/validation.test.d.ts.map +1 -0
- package/dist/framework/__tests__/validation.test.js +126 -0
- package/dist/framework/__tests__/validation.test.js.map +1 -0
- package/dist/framework/assertions.d.ts +106 -0
- package/dist/framework/assertions.d.ts.map +1 -0
- package/dist/framework/assertions.js +256 -0
- package/dist/framework/assertions.js.map +1 -0
- package/dist/framework/execution/__tests__/execution-engine.test.d.ts +9 -0
- package/dist/framework/execution/__tests__/execution-engine.test.d.ts.map +1 -0
- package/dist/framework/execution/__tests__/execution-engine.test.js +138 -0
- package/dist/framework/execution/__tests__/execution-engine.test.js.map +1 -0
- package/dist/framework/execution/__tests__/fault-builders.test.d.ts +5 -0
- package/dist/framework/execution/__tests__/fault-builders.test.d.ts.map +1 -0
- package/dist/framework/execution/__tests__/fault-builders.test.js +23 -0
- package/dist/framework/execution/__tests__/fault-builders.test.js.map +1 -0
- package/dist/framework/execution/__tests__/fault-model.test.d.ts +6 -0
- package/dist/framework/execution/__tests__/fault-model.test.d.ts.map +1 -0
- package/dist/framework/execution/__tests__/fault-model.test.js +64 -0
- package/dist/framework/execution/__tests__/fault-model.test.js.map +1 -0
- package/dist/framework/execution/__tests__/http-target.test.d.ts +5 -0
- package/dist/framework/execution/__tests__/http-target.test.d.ts.map +1 -0
- package/dist/framework/execution/__tests__/http-target.test.js +36 -0
- package/dist/framework/execution/__tests__/http-target.test.js.map +1 -0
- package/dist/framework/execution/__tests__/run-load-window.test.d.ts +7 -0
- package/dist/framework/execution/__tests__/run-load-window.test.d.ts.map +1 -0
- package/dist/framework/execution/__tests__/run-load-window.test.js +89 -0
- package/dist/framework/execution/__tests__/run-load-window.test.js.map +1 -0
- package/dist/framework/execution/execution-engine.d.ts +55 -0
- package/dist/framework/execution/execution-engine.d.ts.map +1 -0
- package/dist/framework/execution/execution-engine.js +111 -0
- package/dist/framework/execution/execution-engine.js.map +1 -0
- package/dist/framework/execution/fault-builders.d.ts +26 -0
- package/dist/framework/execution/fault-builders.d.ts.map +1 -0
- package/dist/framework/execution/fault-builders.js +24 -0
- package/dist/framework/execution/fault-builders.js.map +1 -0
- package/dist/framework/execution/fault-model.d.ts +49 -0
- package/dist/framework/execution/fault-model.d.ts.map +1 -0
- package/dist/framework/execution/fault-model.js +108 -0
- package/dist/framework/execution/fault-model.js.map +1 -0
- package/dist/framework/execution/fault-spec.d.ts +40 -0
- package/dist/framework/execution/fault-spec.d.ts.map +1 -0
- package/dist/framework/execution/fault-spec.js +23 -0
- package/dist/framework/execution/fault-spec.js.map +1 -0
- package/dist/framework/execution/http-target.d.ts +34 -0
- package/dist/framework/execution/http-target.d.ts.map +1 -0
- package/dist/framework/execution/http-target.js +41 -0
- package/dist/framework/execution/http-target.js.map +1 -0
- package/dist/framework/execution/latency-tracker.d.ts +44 -0
- package/dist/framework/execution/latency-tracker.d.ts.map +1 -0
- package/dist/framework/execution/latency-tracker.js +76 -0
- package/dist/framework/execution/latency-tracker.js.map +1 -0
- package/dist/framework/execution/run-load-window.d.ts +45 -0
- package/dist/framework/execution/run-load-window.d.ts.map +1 -0
- package/dist/framework/execution/run-load-window.js +136 -0
- package/dist/framework/execution/run-load-window.js.map +1 -0
- package/dist/framework/execution/scenario-aborted-error.d.ts +14 -0
- package/dist/framework/execution/scenario-aborted-error.d.ts.map +1 -0
- package/dist/framework/execution/scenario-aborted-error.js +24 -0
- package/dist/framework/execution/scenario-aborted-error.js.map +1 -0
- package/dist/framework/execution/target.d.ts +35 -0
- package/dist/framework/execution/target.d.ts.map +1 -0
- package/dist/framework/execution/target.js +21 -0
- package/dist/framework/execution/target.js.map +1 -0
- package/dist/framework/registry.d.ts +67 -0
- package/dist/framework/registry.d.ts.map +1 -0
- package/dist/framework/registry.js +113 -0
- package/dist/framework/registry.js.map +1 -0
- package/dist/framework/resolve-metric.d.ts +79 -0
- package/dist/framework/resolve-metric.d.ts.map +1 -0
- package/dist/framework/resolve-metric.js +135 -0
- package/dist/framework/resolve-metric.js.map +1 -0
- package/dist/framework/result-builder.d.ts +72 -0
- package/dist/framework/result-builder.d.ts.map +1 -0
- package/dist/framework/result-builder.js +214 -0
- package/dist/framework/result-builder.js.map +1 -0
- package/dist/framework/result-renderers.d.ts +37 -0
- package/dist/framework/result-renderers.d.ts.map +1 -0
- package/dist/framework/result-renderers.js +62 -0
- package/dist/framework/result-renderers.js.map +1 -0
- package/dist/framework/runnable-scenario.d.ts +37 -0
- package/dist/framework/runnable-scenario.d.ts.map +1 -0
- package/dist/framework/runnable-scenario.js +9 -0
- package/dist/framework/runnable-scenario.js.map +1 -0
- package/dist/framework/scenario-executor-result.d.ts +44 -0
- package/dist/framework/scenario-executor-result.d.ts.map +1 -0
- package/dist/framework/scenario-executor-result.js +13 -0
- package/dist/framework/scenario-executor-result.js.map +1 -0
- package/dist/framework/scenario-logger.d.ts +18 -0
- package/dist/framework/scenario-logger.d.ts.map +1 -0
- package/dist/framework/scenario-logger.js +39 -0
- package/dist/framework/scenario-logger.js.map +1 -0
- package/dist/framework/scenario-metric-key.d.ts +24 -0
- package/dist/framework/scenario-metric-key.d.ts.map +1 -0
- package/dist/framework/scenario-metric-key.js +17 -0
- package/dist/framework/scenario-metric-key.js.map +1 -0
- package/dist/framework/validation.d.ts +83 -0
- package/dist/framework/validation.d.ts.map +1 -0
- package/dist/framework/validation.js +93 -0
- package/dist/framework/validation.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +19 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +16 -0
- package/dist/internal.js.map +1 -0
- package/dist/kinds/chaos/__tests__/executor.test.d.ts +6 -0
- package/dist/kinds/chaos/__tests__/executor.test.d.ts.map +1 -0
- package/dist/kinds/chaos/__tests__/executor.test.js +117 -0
- package/dist/kinds/chaos/__tests__/executor.test.js.map +1 -0
- package/dist/kinds/chaos/config.d.ts +48 -0
- package/dist/kinds/chaos/config.d.ts.map +1 -0
- package/dist/kinds/chaos/config.js +15 -0
- package/dist/kinds/chaos/config.js.map +1 -0
- package/dist/kinds/chaos/define.d.ts +32 -0
- package/dist/kinds/chaos/define.d.ts.map +1 -0
- package/dist/kinds/chaos/define.js +111 -0
- package/dist/kinds/chaos/define.js.map +1 -0
- package/dist/kinds/chaos/executor.d.ts +21 -0
- package/dist/kinds/chaos/executor.d.ts.map +1 -0
- package/dist/kinds/chaos/executor.js +107 -0
- package/dist/kinds/chaos/executor.js.map +1 -0
- package/dist/kinds/chaos/result.d.ts +43 -0
- package/dist/kinds/chaos/result.d.ts.map +1 -0
- package/dist/kinds/chaos/result.js +12 -0
- package/dist/kinds/chaos/result.js.map +1 -0
- package/dist/kinds/load/__tests__/executor.test.d.ts +6 -0
- package/dist/kinds/load/__tests__/executor.test.d.ts.map +1 -0
- package/dist/kinds/load/__tests__/executor.test.js +75 -0
- package/dist/kinds/load/__tests__/executor.test.js.map +1 -0
- package/dist/kinds/load/config.d.ts +30 -0
- package/dist/kinds/load/config.d.ts.map +1 -0
- package/dist/kinds/load/config.js +9 -0
- package/dist/kinds/load/config.js.map +1 -0
- package/dist/kinds/load/define.d.ts +47 -0
- package/dist/kinds/load/define.d.ts.map +1 -0
- package/dist/kinds/load/define.js +76 -0
- package/dist/kinds/load/define.js.map +1 -0
- package/dist/kinds/load/executor.d.ts +16 -0
- package/dist/kinds/load/executor.d.ts.map +1 -0
- package/dist/kinds/load/executor.js +90 -0
- package/dist/kinds/load/executor.js.map +1 -0
- package/dist/kinds/load/result.d.ts +21 -0
- package/dist/kinds/load/result.d.ts.map +1 -0
- package/dist/kinds/load/result.js +10 -0
- package/dist/kinds/load/result.js.map +1 -0
- package/dist/persistence/session-payload.d.ts +32 -0
- package/dist/persistence/session-payload.d.ts.map +1 -0
- package/dist/persistence/session-payload.js +46 -0
- package/dist/persistence/session-payload.js.map +1 -0
- package/dist/persistence/session-replay.d.ts +13 -0
- package/dist/persistence/session-replay.d.ts.map +1 -0
- package/dist/persistence/session-replay.js +76 -0
- package/dist/persistence/session-replay.js.map +1 -0
- package/dist/persistence/session-replay.test.d.ts +10 -0
- package/dist/persistence/session-replay.test.d.ts.map +1 -0
- package/dist/persistence/session-replay.test.js +169 -0
- package/dist/persistence/session-replay.test.js.map +1 -0
- package/dist/plugins/__tests__/loader-scenarios.test.d.ts +12 -0
- package/dist/plugins/__tests__/loader-scenarios.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/loader-scenarios.test.js +61 -0
- package/dist/plugins/__tests__/loader-scenarios.test.js.map +1 -0
- package/dist/plugins/__tests__/scenario-package-discovery.test.d.ts +2 -0
- package/dist/plugins/__tests__/scenario-package-discovery.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/scenario-package-discovery.test.js +43 -0
- package/dist/plugins/__tests__/scenario-package-discovery.test.js.map +1 -0
- package/dist/plugins/loader.d.ts +32 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +119 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/scenario-package-discovery.d.ts +23 -0
- package/dist/plugins/scenario-package-discovery.d.ts.map +1 -0
- package/dist/plugins/scenario-package-discovery.js +42 -0
- package/dist/plugins/scenario-package-discovery.js.map +1 -0
- package/dist/plugins/types.d.ts +24 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +18 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/recipes/__tests__/recipes.test.d.ts +2 -0
- package/dist/recipes/__tests__/recipes.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/recipes.test.js +515 -0
- package/dist/recipes/__tests__/recipes.test.js.map +1 -0
- package/dist/recipes/built-in-recipes.d.ts +16 -0
- package/dist/recipes/built-in-recipes.d.ts.map +1 -0
- package/dist/recipes/built-in-recipes.js +37 -0
- package/dist/recipes/built-in-recipes.js.map +1 -0
- package/dist/recipes/define-recipe.d.ts +29 -0
- package/dist/recipes/define-recipe.d.ts.map +1 -0
- package/dist/recipes/define-recipe.js +68 -0
- package/dist/recipes/define-recipe.js.map +1 -0
- package/dist/recipes/registry.d.ts +54 -0
- package/dist/recipes/registry.d.ts.map +1 -0
- package/dist/recipes/registry.js +89 -0
- package/dist/recipes/registry.js.map +1 -0
- package/dist/recipes/service.d.ts +61 -0
- package/dist/recipes/service.d.ts.map +1 -0
- package/dist/recipes/service.js +205 -0
- package/dist/recipes/service.js.map +1 -0
- package/dist/recipes/types.d.ts +62 -0
- package/dist/recipes/types.d.ts.map +1 -0
- package/dist/recipes/types.js +10 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/scaffold/examples.d.ts +22 -0
- package/dist/scaffold/examples.d.ts.map +1 -0
- package/dist/scaffold/examples.js +91 -0
- package/dist/scaffold/examples.js.map +1 -0
- package/dist/scope-augmentation.d.ts +70 -0
- package/dist/scope-augmentation.d.ts.map +1 -0
- package/dist/scope-augmentation.js +28 -0
- package/dist/scope-augmentation.js.map +1 -0
- package/dist/tool.d.ts +21 -0
- package/dist/tool.d.ts.map +1 -0
- package/dist/tool.js +347 -0
- package/dist/tool.js.map +1 -0
- package/dist/types/base-types.d.ts +35 -0
- package/dist/types/base-types.d.ts.map +1 -0
- package/dist/types/base-types.js +8 -0
- package/dist/types/base-types.js.map +1 -0
- package/dist/types/framework-types.d.ts +62 -0
- package/dist/types/framework-types.d.ts.map +1 -0
- package/dist/types/framework-types.js +15 -0
- package/dist/types/framework-types.js.map +1 -0
- package/dist/types/kind-types.d.ts +24 -0
- package/dist/types/kind-types.d.ts.map +1 -0
- package/dist/types/kind-types.js +22 -0
- package/dist/types/kind-types.js.map +1 -0
- package/dist/types/workload.d.ts +30 -0
- package/dist/types/workload.d.ts.map +1 -0
- package/dist/types/workload.js +20 -0
- package/dist/types/workload.js.map +1 -0
- package/package.json +120 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Behaviour tests for the real load-window driver: it drives a
|
|
3
|
+
* BYO target, measures latency, classifies outcomes, bounds concurrency, and
|
|
4
|
+
* honours abort.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
7
|
+
import { countingTarget, failingTarget } from '../../../__tests__/test-utils/targets.js';
|
|
8
|
+
import { runLoadWindow } from '../run-load-window.js';
|
|
9
|
+
const ctx = (signal) => ({
|
|
10
|
+
scenarioId: 't',
|
|
11
|
+
correlationId: 'c',
|
|
12
|
+
abortSignal: signal,
|
|
13
|
+
logger: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
14
|
+
});
|
|
15
|
+
describe('runLoadWindow', () => {
|
|
16
|
+
it('drives the target and counts every resolve as a success', async () => {
|
|
17
|
+
const ct = countingTarget();
|
|
18
|
+
const r = await runLoadWindow({ workload: { rps: 50 } }, ctx(new AbortController().signal), {
|
|
19
|
+
windowMs: 300,
|
|
20
|
+
target: ct.target,
|
|
21
|
+
});
|
|
22
|
+
expect(r.metrics.totalRequests).toBeGreaterThan(0);
|
|
23
|
+
expect(ct.calls()).toBe(r.metrics.totalRequests);
|
|
24
|
+
expect(r.metrics.successfulRequests).toBe(r.metrics.totalRequests);
|
|
25
|
+
expect(r.metrics.failedRequests).toBe(0);
|
|
26
|
+
});
|
|
27
|
+
it('counts every throw as a failure + error', async () => {
|
|
28
|
+
const r = await runLoadWindow({ workload: { rps: 50 } }, ctx(new AbortController().signal), {
|
|
29
|
+
windowMs: 300,
|
|
30
|
+
target: failingTarget,
|
|
31
|
+
});
|
|
32
|
+
expect(r.metrics.totalRequests).toBeGreaterThan(0);
|
|
33
|
+
expect(r.metrics.successfulRequests).toBe(0);
|
|
34
|
+
expect(r.metrics.failedRequests).toBe(r.metrics.totalRequests);
|
|
35
|
+
expect(r.metrics.errorsGenerated).toBe(r.metrics.failedRequests);
|
|
36
|
+
});
|
|
37
|
+
it('never exceeds the workload concurrency cap', async () => {
|
|
38
|
+
const ct = countingTarget(40);
|
|
39
|
+
await runLoadWindow({ workload: { rps: 200, concurrency: 3 } }, ctx(new AbortController().signal), {
|
|
40
|
+
windowMs: 400,
|
|
41
|
+
target: ct.target,
|
|
42
|
+
});
|
|
43
|
+
expect(ct.maxConcurrent()).toBeLessThanOrEqual(3);
|
|
44
|
+
expect(ct.calls()).toBeGreaterThan(0);
|
|
45
|
+
});
|
|
46
|
+
it('records real measured latency in the snapshot', async () => {
|
|
47
|
+
const ct = countingTarget(20);
|
|
48
|
+
const r = await runLoadWindow({ workload: { rps: 20 } }, ctx(new AbortController().signal), {
|
|
49
|
+
windowMs: 300,
|
|
50
|
+
target: ct.target,
|
|
51
|
+
});
|
|
52
|
+
expect(r.metrics.p50LatencyMs).toBeGreaterThanOrEqual(15);
|
|
53
|
+
});
|
|
54
|
+
it('applies ramp-up (issues fewer requests early)', async () => {
|
|
55
|
+
const ct = countingTarget();
|
|
56
|
+
const r = await runLoadWindow({ workload: { rps: 100, rampUp: 1 } }, ctx(new AbortController().signal), {
|
|
57
|
+
windowMs: 300,
|
|
58
|
+
target: ct.target,
|
|
59
|
+
});
|
|
60
|
+
// With a 1s ramp and a 300ms window, the loop never reaches full rps, so it
|
|
61
|
+
// issues materially fewer than rps*window would suggest — but still > 0.
|
|
62
|
+
expect(r.metrics.totalRequests).toBeGreaterThan(0);
|
|
63
|
+
expect(r.metrics.totalRequests).toBeLessThan(30);
|
|
64
|
+
});
|
|
65
|
+
it('issues no requests when pre-aborted', async () => {
|
|
66
|
+
const ac = new AbortController();
|
|
67
|
+
ac.abort();
|
|
68
|
+
const ct = countingTarget();
|
|
69
|
+
const r = await runLoadWindow({ workload: { rps: 50 } }, ctx(ac.signal), {
|
|
70
|
+
windowMs: 1000,
|
|
71
|
+
target: ct.target,
|
|
72
|
+
});
|
|
73
|
+
expect(r.metrics.totalRequests).toBe(0);
|
|
74
|
+
expect(ct.calls()).toBe(0);
|
|
75
|
+
});
|
|
76
|
+
it('stops dispatching after a mid-window abort and returns promptly', async () => {
|
|
77
|
+
const ac = new AbortController();
|
|
78
|
+
const ct = countingTarget(5);
|
|
79
|
+
setTimeout(() => ac.abort(), 120);
|
|
80
|
+
const start = Date.now();
|
|
81
|
+
const r = await runLoadWindow({ workload: { rps: 100 } }, ctx(ac.signal), {
|
|
82
|
+
windowMs: 5000,
|
|
83
|
+
target: ct.target,
|
|
84
|
+
});
|
|
85
|
+
expect(Date.now() - start).toBeLessThan(2000);
|
|
86
|
+
expect(r.metrics.totalRequests).toBeGreaterThan(0);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=run-load-window.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-load-window.test.js","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/run-load-window.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Small public utilities for scenario execution.
|
|
3
|
+
*
|
|
4
|
+
* Historically this file housed the legacy `runSimulationLoop` /
|
|
5
|
+
* `createScenario` / `createStandardExecutor` orchestration model. That
|
|
6
|
+
* model was retired once both kinds (load, chaos) unified on the new
|
|
7
|
+
* `ScenarioExecutionContext` / `runLoadWindow` model in Wave 4 of the
|
|
8
|
+
* Layer 3 remediation plan; the legacy `defineScenario` alias was deleted
|
|
9
|
+
* in the same release.
|
|
10
|
+
*
|
|
11
|
+
* What remains here is a small set of stable helpers consumed across
|
|
12
|
+
* the simulation runtime:
|
|
13
|
+
*
|
|
14
|
+
* - `validateAssertions` — evaluate assertions against metrics.
|
|
15
|
+
* - `updateLatencyMetrics` — quick in-loop latency sample update
|
|
16
|
+
* (rough percentiles; prefer `LatencyTracker` when accuracy matters).
|
|
17
|
+
* - `sleepWithAbort` — abortable sleep used by both windowed runs and
|
|
18
|
+
* scenario test fixtures.
|
|
19
|
+
* - `scenarioAborted` — standalone abort-check helper.
|
|
20
|
+
*
|
|
21
|
+
* `ScenarioAbortedError` is re-exported here so kind executors can keep
|
|
22
|
+
* importing it from a single, stable location.
|
|
23
|
+
*/
|
|
24
|
+
import type { SimulationMetrics, ScenarioAssertion } from '../../types/base-types.js';
|
|
25
|
+
/**
|
|
26
|
+
* Validate assertions against metrics.
|
|
27
|
+
*/
|
|
28
|
+
export declare function validateAssertions(metrics: SimulationMetrics, assertions: ScenarioAssertion[]): {
|
|
29
|
+
passed: boolean;
|
|
30
|
+
failed: {
|
|
31
|
+
assertion: ScenarioAssertion;
|
|
32
|
+
actual: number;
|
|
33
|
+
}[];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Update latency metrics with a new sample.
|
|
37
|
+
*
|
|
38
|
+
* WARNING: Percentile values (p50, p95, p99) are rough estimates derived from
|
|
39
|
+
* the running average. For accurate percentiles, use LatencyTracker instead.
|
|
40
|
+
* This function is intended for quick in-loop metric updates where
|
|
41
|
+
* maintaining a full sample set is impractical.
|
|
42
|
+
*/
|
|
43
|
+
export declare function updateLatencyMetrics(metrics: SimulationMetrics, latency: number): void;
|
|
44
|
+
/**
|
|
45
|
+
* Sleep for a specified duration with abort support.
|
|
46
|
+
* @throws {ScenarioAbortedError} When the abort signal is triggered
|
|
47
|
+
*/
|
|
48
|
+
export declare function sleepWithAbort(ms: number, signal: AbortSignal): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Standalone checkAborted helper for use outside an execution loop.
|
|
51
|
+
* @throws {ScenarioAbortedError} When the abort signal has been triggered
|
|
52
|
+
*/
|
|
53
|
+
export declare function scenarioAborted(signal: AbortSignal | undefined, scenarioId?: string): void;
|
|
54
|
+
export { ScenarioAbortedError } from './scenario-aborted-error.js';
|
|
55
|
+
//# sourceMappingURL=execution-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-engine.d.ts","sourceRoot":"","sources":["../../../src/framework/execution/execution-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAMtF;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAE,iBAAiB,EAAE,GAC9B;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE;QAAE,SAAS,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAiBjF;AAMD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CActF;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB7E;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAI1F;AAED,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Small public utilities for scenario execution.
|
|
3
|
+
*
|
|
4
|
+
* Historically this file housed the legacy `runSimulationLoop` /
|
|
5
|
+
* `createScenario` / `createStandardExecutor` orchestration model. That
|
|
6
|
+
* model was retired once both kinds (load, chaos) unified on the new
|
|
7
|
+
* `ScenarioExecutionContext` / `runLoadWindow` model in Wave 4 of the
|
|
8
|
+
* Layer 3 remediation plan; the legacy `defineScenario` alias was deleted
|
|
9
|
+
* in the same release.
|
|
10
|
+
*
|
|
11
|
+
* What remains here is a small set of stable helpers consumed across
|
|
12
|
+
* the simulation runtime:
|
|
13
|
+
*
|
|
14
|
+
* - `validateAssertions` — evaluate assertions against metrics.
|
|
15
|
+
* - `updateLatencyMetrics` — quick in-loop latency sample update
|
|
16
|
+
* (rough percentiles; prefer `LatencyTracker` when accuracy matters).
|
|
17
|
+
* - `sleepWithAbort` — abortable sleep used by both windowed runs and
|
|
18
|
+
* scenario test fixtures.
|
|
19
|
+
* - `scenarioAborted` — standalone abort-check helper.
|
|
20
|
+
*
|
|
21
|
+
* `ScenarioAbortedError` is re-exported here so kind executors can keep
|
|
22
|
+
* importing it from a single, stable location.
|
|
23
|
+
*/
|
|
24
|
+
import { evaluateOperator } from '../assertions.js';
|
|
25
|
+
import { resolveMetric } from '../resolve-metric.js';
|
|
26
|
+
import { ScenarioAbortedError } from './scenario-aborted-error.js';
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// ASSERTION VALIDATION
|
|
29
|
+
// =============================================================================
|
|
30
|
+
/**
|
|
31
|
+
* Validate assertions against metrics.
|
|
32
|
+
*/
|
|
33
|
+
export function validateAssertions(metrics, assertions) {
|
|
34
|
+
if (!Array.isArray(assertions)) {
|
|
35
|
+
return { passed: false, failed: [] };
|
|
36
|
+
}
|
|
37
|
+
const failed = [];
|
|
38
|
+
for (const assertion of assertions) {
|
|
39
|
+
const actual = resolveMetric(assertion.metric, metrics);
|
|
40
|
+
const passed = evaluateOperator(actual, assertion.operator, assertion.value);
|
|
41
|
+
if (!passed) {
|
|
42
|
+
failed.push({ assertion, actual });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { passed: failed.length === 0, failed };
|
|
46
|
+
}
|
|
47
|
+
// =============================================================================
|
|
48
|
+
// METRICS UTILITIES
|
|
49
|
+
// =============================================================================
|
|
50
|
+
/**
|
|
51
|
+
* Update latency metrics with a new sample.
|
|
52
|
+
*
|
|
53
|
+
* WARNING: Percentile values (p50, p95, p99) are rough estimates derived from
|
|
54
|
+
* the running average. For accurate percentiles, use LatencyTracker instead.
|
|
55
|
+
* This function is intended for quick in-loop metric updates where
|
|
56
|
+
* maintaining a full sample set is impractical.
|
|
57
|
+
*/
|
|
58
|
+
export function updateLatencyMetrics(metrics, latency) {
|
|
59
|
+
const n = metrics.totalRequests;
|
|
60
|
+
if (n === 0) {
|
|
61
|
+
metrics.avgLatencyMs = latency;
|
|
62
|
+
metrics.p50LatencyMs = latency;
|
|
63
|
+
metrics.p95LatencyMs = latency;
|
|
64
|
+
metrics.p99LatencyMs = latency;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
metrics.avgLatencyMs = (metrics.avgLatencyMs * (n - 1) + latency) / n;
|
|
68
|
+
// Rough estimates — use LatencyTracker.getLatencySnapshot() for real percentiles
|
|
69
|
+
metrics.p50LatencyMs = metrics.avgLatencyMs * 0.9;
|
|
70
|
+
metrics.p95LatencyMs = metrics.avgLatencyMs * 1.5;
|
|
71
|
+
metrics.p99LatencyMs = metrics.avgLatencyMs * 2;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// =============================================================================
|
|
75
|
+
// SLEEP UTILITY
|
|
76
|
+
// =============================================================================
|
|
77
|
+
/**
|
|
78
|
+
* Sleep for a specified duration with abort support.
|
|
79
|
+
* @throws {ScenarioAbortedError} When the abort signal is triggered
|
|
80
|
+
*/
|
|
81
|
+
export function sleepWithAbort(ms, signal) {
|
|
82
|
+
return new Promise((resolve, reject) => {
|
|
83
|
+
if (signal.aborted) {
|
|
84
|
+
reject(new ScenarioAbortedError());
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const abortHandler = () => {
|
|
88
|
+
clearTimeout(timeout);
|
|
89
|
+
reject(new ScenarioAbortedError());
|
|
90
|
+
};
|
|
91
|
+
const timeout = setTimeout(() => {
|
|
92
|
+
signal.removeEventListener('abort', abortHandler);
|
|
93
|
+
resolve();
|
|
94
|
+
}, ms);
|
|
95
|
+
signal.addEventListener('abort', abortHandler, { once: true });
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// =============================================================================
|
|
99
|
+
// ABORT HELPER
|
|
100
|
+
// =============================================================================
|
|
101
|
+
/**
|
|
102
|
+
* Standalone checkAborted helper for use outside an execution loop.
|
|
103
|
+
* @throws {ScenarioAbortedError} When the abort signal has been triggered
|
|
104
|
+
*/
|
|
105
|
+
export function scenarioAborted(signal, scenarioId) {
|
|
106
|
+
if (signal?.aborted) {
|
|
107
|
+
throw new ScenarioAbortedError(scenarioId);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export { ScenarioAbortedError } from './scenario-aborted-error.js';
|
|
111
|
+
//# sourceMappingURL=execution-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-engine.js","sourceRoot":"","sources":["../../../src/framework/execution/execution-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `fault.*` — ergonomic builders for a {@link FaultSpec}.
|
|
3
|
+
*
|
|
4
|
+
* Authors describe client-side faults declaratively:
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* fault.of([fault.latency({ ms: 800 }), fault.drop()], { probability: 0.1 })
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
import type { Fault, FaultSpec } from './fault-spec.js';
|
|
11
|
+
/** Builders for the client-side fault vocabulary + a `FaultSpec` assembler. */
|
|
12
|
+
export declare const fault: {
|
|
13
|
+
/** Delay the real call by `ms` (a slow-dependency symptom). */
|
|
14
|
+
readonly latency: (o: {
|
|
15
|
+
ms: number;
|
|
16
|
+
}) => Fault;
|
|
17
|
+
/** Abort the in-flight request (a timeout / cancellation). */
|
|
18
|
+
readonly abort: () => Fault;
|
|
19
|
+
/** Skip the call entirely, counting a client-observed failure. */
|
|
20
|
+
readonly drop: () => Fault;
|
|
21
|
+
/** Assemble a probability-gated set of candidate faults. */
|
|
22
|
+
readonly of: (faults: readonly Fault[], o: {
|
|
23
|
+
probability: number;
|
|
24
|
+
}) => FaultSpec;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=fault-builders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fault-builders.d.ts","sourceRoot":"","sources":["../../../src/framework/execution/fault-builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAExD,+EAA+E;AAC/E,eAAO,MAAM,KAAK;IAChB,+DAA+D;0BAClD;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAG,KAAK;IACnC,8DAA8D;0BACnD,KAAK;IAChB,kEAAkE;yBACxD,KAAK;IACf,4DAA4D;0BAC/C,SAAS,KAAK,EAAE,KAAK;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAAG,SAAS;CAI7D,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `fault.*` — ergonomic builders for a {@link FaultSpec}.
|
|
3
|
+
*
|
|
4
|
+
* Authors describe client-side faults declaratively:
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* fault.of([fault.latency({ ms: 800 }), fault.drop()], { probability: 0.1 })
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
/** Builders for the client-side fault vocabulary + a `FaultSpec` assembler. */
|
|
11
|
+
export const fault = {
|
|
12
|
+
/** Delay the real call by `ms` (a slow-dependency symptom). */
|
|
13
|
+
latency: (o) => ({ kind: 'latency', ms: o.ms }),
|
|
14
|
+
/** Abort the in-flight request (a timeout / cancellation). */
|
|
15
|
+
abort: () => ({ kind: 'abort' }),
|
|
16
|
+
/** Skip the call entirely, counting a client-observed failure. */
|
|
17
|
+
drop: () => ({ kind: 'drop' }),
|
|
18
|
+
/** Assemble a probability-gated set of candidate faults. */
|
|
19
|
+
of: (faults, o) => ({
|
|
20
|
+
faults,
|
|
21
|
+
probability: o.probability,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=fault-builders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fault-builders.js","sourceRoot":"","sources":["../../../src/framework/execution/fault-builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,+DAA+D;IAC/D,OAAO,EAAE,CAAC,CAAiB,EAAS,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;IACtE,8DAA8D;IAC9D,KAAK,EAAE,GAAU,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACvC,kEAAkE;IAClE,IAAI,EAAE,GAAU,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACrC,4DAA4D;IAC5D,EAAE,EAAE,CAAC,MAAwB,EAAE,CAA0B,EAAa,EAAE,CAAC,CAAC;QACxE,MAAM;QACN,WAAW,EAAE,CAAC,CAAC,WAAW;KAC3B,CAAC;CACM,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `FaultModel` — real client-side fault injection as a
|
|
3
|
+
* `Target` decorator.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the old synthetic `injectChaos`. Where that fabricated failure
|
|
6
|
+
* outcomes, the fault model perturbs the **real** request:
|
|
7
|
+
*
|
|
8
|
+
* - `latency` — delay the real call by `ms` (the underlying target still
|
|
9
|
+
* runs; the added latency shows up in the measured snapshot).
|
|
10
|
+
* - `abort` — abort the in-flight request, so it fails as a timeout /
|
|
11
|
+
* cancellation. Enforced even for targets that ignore the
|
|
12
|
+
* abort signal (we await the aborted call, then throw).
|
|
13
|
+
* - `drop` — skip the call entirely and throw, so the driver counts a
|
|
14
|
+
* real client-observed failure.
|
|
15
|
+
*
|
|
16
|
+
* The probability gate is driven by an injected RNG (`deps.rng`, default
|
|
17
|
+
* `Math.random`) so tests can pass a stubbed sequence and assert the exact set
|
|
18
|
+
* of perturbed requests. Fault selection among `spec.faults` is round-robin —
|
|
19
|
+
* deterministic without consuming extra RNG draws.
|
|
20
|
+
*/
|
|
21
|
+
import type { FaultKind, FaultSpec } from './fault-spec.js';
|
|
22
|
+
import type { Target } from './target.js';
|
|
23
|
+
/** A fault occurrence recorded for diagnostics (→ `ChaosEvent`). */
|
|
24
|
+
export interface FiredFault {
|
|
25
|
+
readonly kind: FaultKind;
|
|
26
|
+
/** Absolute wall-clock time the fault fired (ms). */
|
|
27
|
+
readonly at: number;
|
|
28
|
+
}
|
|
29
|
+
/** Dependencies for the fault model. */
|
|
30
|
+
export interface FaultModelDeps {
|
|
31
|
+
/** Probability-gate RNG in `[0,1)`. Defaults to `Math.random`. */
|
|
32
|
+
readonly rng?: () => number;
|
|
33
|
+
}
|
|
34
|
+
/** A fault model bound to a `FaultSpec`. */
|
|
35
|
+
export interface FaultModel {
|
|
36
|
+
/** Decorate a target so each call may be perturbed at `spec.probability`. */
|
|
37
|
+
wrap(target: Target): Target;
|
|
38
|
+
/** The faults that fired so far, in order. */
|
|
39
|
+
drained(): readonly FiredFault[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Build a fault model for a `FaultSpec`.
|
|
43
|
+
*
|
|
44
|
+
* The returned `wrap` is intended to be called once (for the steady-state
|
|
45
|
+
* window); the recovery window uses the bare target. `drained()` reports the
|
|
46
|
+
* faults that fired, for the chaos result's `ChaosEvent[]`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createFaultModel(spec: FaultSpec, deps?: FaultModelDeps): FaultModel;
|
|
49
|
+
//# sourceMappingURL=fault-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fault-model.d.ts","sourceRoot":"","sources":["../../../src/framework/execution/fault-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAS,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAC;AAEzD,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,6EAA6E;IAC7E,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,8CAA8C;IAC9C,OAAO,IAAI,SAAS,UAAU,EAAE,CAAC;CAClC;AAoBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,GAAE,cAAmB,GAAG,UAAU,CAgEvF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `FaultModel` — real client-side fault injection as a
|
|
3
|
+
* `Target` decorator.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the old synthetic `injectChaos`. Where that fabricated failure
|
|
6
|
+
* outcomes, the fault model perturbs the **real** request:
|
|
7
|
+
*
|
|
8
|
+
* - `latency` — delay the real call by `ms` (the underlying target still
|
|
9
|
+
* runs; the added latency shows up in the measured snapshot).
|
|
10
|
+
* - `abort` — abort the in-flight request, so it fails as a timeout /
|
|
11
|
+
* cancellation. Enforced even for targets that ignore the
|
|
12
|
+
* abort signal (we await the aborted call, then throw).
|
|
13
|
+
* - `drop` — skip the call entirely and throw, so the driver counts a
|
|
14
|
+
* real client-observed failure.
|
|
15
|
+
*
|
|
16
|
+
* The probability gate is driven by an injected RNG (`deps.rng`, default
|
|
17
|
+
* `Math.random`) so tests can pass a stubbed sequence and assert the exact set
|
|
18
|
+
* of perturbed requests. Fault selection among `spec.faults` is round-robin —
|
|
19
|
+
* deterministic without consuming extra RNG draws.
|
|
20
|
+
*/
|
|
21
|
+
function delay(ms, signal) {
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
if (signal.aborted) {
|
|
24
|
+
resolve();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const timeout = setTimeout(() => {
|
|
28
|
+
signal.removeEventListener('abort', onAbort);
|
|
29
|
+
resolve();
|
|
30
|
+
}, ms);
|
|
31
|
+
const onAbort = () => {
|
|
32
|
+
clearTimeout(timeout);
|
|
33
|
+
resolve();
|
|
34
|
+
};
|
|
35
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build a fault model for a `FaultSpec`.
|
|
40
|
+
*
|
|
41
|
+
* The returned `wrap` is intended to be called once (for the steady-state
|
|
42
|
+
* window); the recovery window uses the bare target. `drained()` reports the
|
|
43
|
+
* faults that fired, for the chaos result's `ChaosEvent[]`.
|
|
44
|
+
*/
|
|
45
|
+
export function createFaultModel(spec, deps = {}) {
|
|
46
|
+
const rng = deps.rng ?? Math.random;
|
|
47
|
+
const fired = [];
|
|
48
|
+
let perturbCount = 0;
|
|
49
|
+
/**
|
|
50
|
+
* Apply a single fault to a target invocation.
|
|
51
|
+
* @throws {Error} `fault:abort` when the abort fault fires, or `fault:drop` when the drop fault fires.
|
|
52
|
+
*/
|
|
53
|
+
async function applyFault(fault, target, ctx) {
|
|
54
|
+
fired.push({ kind: fault.kind, at: Date.now() });
|
|
55
|
+
switch (fault.kind) {
|
|
56
|
+
case 'latency': {
|
|
57
|
+
await delay(fault.ms, ctx.signal);
|
|
58
|
+
await target(ctx);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
case 'abort': {
|
|
62
|
+
// Abort the request: hand a well-behaved target an already-aborted
|
|
63
|
+
// signal so it cancels, but guarantee the request fails regardless of
|
|
64
|
+
// whether the target honours the signal (we throw deterministically).
|
|
65
|
+
const controller = new AbortController();
|
|
66
|
+
// @fitness-ignore-next-line detached-promises -- AbortController.abort() is a synchronous void call, not a promise
|
|
67
|
+
controller.abort();
|
|
68
|
+
const signal = typeof AbortSignal.any === 'function'
|
|
69
|
+
? AbortSignal.any([ctx.signal, controller.signal])
|
|
70
|
+
: controller.signal;
|
|
71
|
+
// Let a signal-aware target observe the abort, but guarantee a failure:
|
|
72
|
+
// whether it rejects on the signal or ignores it and resolves, we throw.
|
|
73
|
+
try {
|
|
74
|
+
await target({ signal, correlationId: ctx.correlationId });
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// @swallow-ok target observed the abort (or otherwise failed); we throw fault:abort below regardless.
|
|
78
|
+
}
|
|
79
|
+
throw new Error('fault:abort');
|
|
80
|
+
}
|
|
81
|
+
case 'drop': {
|
|
82
|
+
// Never reach the target; the driver counts a client-observed failure.
|
|
83
|
+
throw new Error('fault:drop');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
wrap(target) {
|
|
89
|
+
return async (ctx) => {
|
|
90
|
+
if (rng() >= spec.probability || spec.faults.length === 0) {
|
|
91
|
+
await target(ctx);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const fault = spec.faults[perturbCount % spec.faults.length];
|
|
95
|
+
perturbCount++;
|
|
96
|
+
if (!fault) {
|
|
97
|
+
await target(ctx);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
await applyFault(fault, target, ctx);
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
drained() {
|
|
104
|
+
return fired;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=fault-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fault-model.js","sourceRoot":"","sources":["../../../src/framework/execution/fault-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `FaultSpec` — the author-facing, **client-side** fault
|
|
3
|
+
* vocabulary for the chaos kind.
|
|
4
|
+
*
|
|
5
|
+
* The harness can honestly inject only client-side perturbations of the real
|
|
6
|
+
* request stream:
|
|
7
|
+
*
|
|
8
|
+
* - `latency` — delay the real call (a slow-dependency symptom).
|
|
9
|
+
* - `abort` — abort the in-flight request (a timeout / cancellation).
|
|
10
|
+
* - `drop` — skip the call entirely, counting a client-observed failure
|
|
11
|
+
* (a dropped request / open circuit).
|
|
12
|
+
*
|
|
13
|
+
* Server-side faults (kill a pod, force 500s, sever a dependency) cannot be
|
|
14
|
+
* injected honestly from the client. They are achieved by pointing the
|
|
15
|
+
* `Target` at a **fault-injectable endpoint you control** (e.g. a Toxiproxy
|
|
16
|
+
* proxy, a chaos-mesh'd staging env, a test-flagged endpoint) — the harness
|
|
17
|
+
* drives and measures around it. That pattern is documented, not expressed
|
|
18
|
+
* here.
|
|
19
|
+
*
|
|
20
|
+
* Leaf module: imports nothing from the type or runtime layers.
|
|
21
|
+
*/
|
|
22
|
+
/** The client-injectable fault kinds. */
|
|
23
|
+
export type FaultKind = 'latency' | 'abort' | 'drop';
|
|
24
|
+
/** A single client-side fault the model may apply to a request. */
|
|
25
|
+
export type Fault = {
|
|
26
|
+
readonly kind: 'latency';
|
|
27
|
+
readonly ms: number;
|
|
28
|
+
} | {
|
|
29
|
+
readonly kind: 'abort';
|
|
30
|
+
} | {
|
|
31
|
+
readonly kind: 'drop';
|
|
32
|
+
};
|
|
33
|
+
/** Probability-gated set of client-side faults for a chaos scenario. */
|
|
34
|
+
export interface FaultSpec {
|
|
35
|
+
/** Candidate faults; one is selected when a request is perturbed. */
|
|
36
|
+
readonly faults: readonly Fault[];
|
|
37
|
+
/** Per-request probability `[0,1]` that a fault is applied. */
|
|
38
|
+
readonly probability: number;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=fault-spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fault-spec.d.ts","sourceRoot":"","sources":["../../../src/framework/execution/fault-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,yCAAyC;AACzC,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAErD,mEAAmE;AACnE,MAAM,MAAM,KAAK,GACb;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9B,wEAAwE;AACxE,MAAM,WAAW,SAAS;IACxB,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `FaultSpec` — the author-facing, **client-side** fault
|
|
3
|
+
* vocabulary for the chaos kind.
|
|
4
|
+
*
|
|
5
|
+
* The harness can honestly inject only client-side perturbations of the real
|
|
6
|
+
* request stream:
|
|
7
|
+
*
|
|
8
|
+
* - `latency` — delay the real call (a slow-dependency symptom).
|
|
9
|
+
* - `abort` — abort the in-flight request (a timeout / cancellation).
|
|
10
|
+
* - `drop` — skip the call entirely, counting a client-observed failure
|
|
11
|
+
* (a dropped request / open circuit).
|
|
12
|
+
*
|
|
13
|
+
* Server-side faults (kill a pod, force 500s, sever a dependency) cannot be
|
|
14
|
+
* injected honestly from the client. They are achieved by pointing the
|
|
15
|
+
* `Target` at a **fault-injectable endpoint you control** (e.g. a Toxiproxy
|
|
16
|
+
* proxy, a chaos-mesh'd staging env, a test-flagged endpoint) — the harness
|
|
17
|
+
* drives and measures around it. That pattern is documented, not expressed
|
|
18
|
+
* here.
|
|
19
|
+
*
|
|
20
|
+
* Leaf module: imports nothing from the type or runtime layers.
|
|
21
|
+
*/
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=fault-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fault-spec.js","sourceRoot":"","sources":["../../../src/framework/execution/fault-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `httpTarget` — an HTTP `Target` factory.
|
|
3
|
+
*
|
|
4
|
+
* The smallest BYO seam is a function, but most users point at an HTTP
|
|
5
|
+
* endpoint. `httpTarget` wraps the built-in `fetch` (Node 24+) into a `Target`:
|
|
6
|
+
* it forwards `ctx.signal` (so scenario abort + `abort` faults cancel the
|
|
7
|
+
* request) and **throws on a non-OK status** so the driver classifies it as a
|
|
8
|
+
* failure.
|
|
9
|
+
*
|
|
10
|
+
* Point this only at a target you own. For server-side fault injection (kill a
|
|
11
|
+
* dependency, force 500s), put a fault-injectable proxy (e.g. Toxiproxy) in
|
|
12
|
+
* front and aim `httpTarget` at the proxy — the harness drives and measures
|
|
13
|
+
* around it.
|
|
14
|
+
*/
|
|
15
|
+
import type { Target } from './target.js';
|
|
16
|
+
/** Options for {@link httpTarget}. */
|
|
17
|
+
export interface HttpTargetOptions {
|
|
18
|
+
/** Absolute URL to request. */
|
|
19
|
+
readonly url: string;
|
|
20
|
+
/** HTTP method. Defaults to `GET`. */
|
|
21
|
+
readonly method?: string;
|
|
22
|
+
/** Request headers. */
|
|
23
|
+
readonly headers?: Record<string, string>;
|
|
24
|
+
/** Optional request body. */
|
|
25
|
+
readonly body?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Predicate deciding whether a response counts as success. Defaults to
|
|
28
|
+
* `200`–`299`. A non-OK status makes the request throw (a failure).
|
|
29
|
+
*/
|
|
30
|
+
readonly okStatus?: (status: number) => boolean;
|
|
31
|
+
}
|
|
32
|
+
/** Build an HTTP {@link Target} from a URL + method/headers/body. */
|
|
33
|
+
export declare function httpTarget(opts: HttpTargetOptions): Target;
|
|
34
|
+
//# sourceMappingURL=http-target.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-target.d.ts","sourceRoot":"","sources":["../../../src/framework/execution/http-target.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAC;AAEzD,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;CACjD;AAID,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAsB1D"}
|