@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.
Files changed (348) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +31 -0
  4. package/dist/__tests__/internal-surface.test.d.ts +9 -0
  5. package/dist/__tests__/internal-surface.test.d.ts.map +1 -0
  6. package/dist/__tests__/internal-surface.test.js +38 -0
  7. package/dist/__tests__/internal-surface.test.js.map +1 -0
  8. package/dist/__tests__/plugin-loader.test.d.ts +2 -0
  9. package/dist/__tests__/plugin-loader.test.d.ts.map +1 -0
  10. package/dist/__tests__/plugin-loader.test.js +64 -0
  11. package/dist/__tests__/plugin-loader.test.js.map +1 -0
  12. package/dist/__tests__/public-api.test.d.ts +15 -0
  13. package/dist/__tests__/public-api.test.d.ts.map +1 -0
  14. package/dist/__tests__/public-api.test.js +73 -0
  15. package/dist/__tests__/public-api.test.js.map +1 -0
  16. package/dist/__tests__/registry-cross-kind.test.d.ts +6 -0
  17. package/dist/__tests__/registry-cross-kind.test.d.ts.map +1 -0
  18. package/dist/__tests__/registry-cross-kind.test.js +86 -0
  19. package/dist/__tests__/registry-cross-kind.test.js.map +1 -0
  20. package/dist/__tests__/scenario-execution.test.d.ts +10 -0
  21. package/dist/__tests__/scenario-execution.test.d.ts.map +1 -0
  22. package/dist/__tests__/scenario-execution.test.js +92 -0
  23. package/dist/__tests__/scenario-execution.test.js.map +1 -0
  24. package/dist/__tests__/sim-capability-contract.test.d.ts +10 -0
  25. package/dist/__tests__/sim-capability-contract.test.d.ts.map +1 -0
  26. package/dist/__tests__/sim-capability-contract.test.js +131 -0
  27. package/dist/__tests__/sim-capability-contract.test.js.map +1 -0
  28. package/dist/__tests__/sim-config-schema.test.d.ts +5 -0
  29. package/dist/__tests__/sim-config-schema.test.d.ts.map +1 -0
  30. package/dist/__tests__/sim-config-schema.test.js +23 -0
  31. package/dist/__tests__/sim-config-schema.test.js.map +1 -0
  32. package/dist/__tests__/sim-failure-signal.test.d.ts +10 -0
  33. package/dist/__tests__/sim-failure-signal.test.d.ts.map +1 -0
  34. package/dist/__tests__/sim-failure-signal.test.js +86 -0
  35. package/dist/__tests__/sim-failure-signal.test.js.map +1 -0
  36. package/dist/__tests__/surviving-surface-edges.test.d.ts +10 -0
  37. package/dist/__tests__/surviving-surface-edges.test.d.ts.map +1 -0
  38. package/dist/__tests__/surviving-surface-edges.test.js +122 -0
  39. package/dist/__tests__/surviving-surface-edges.test.js.map +1 -0
  40. package/dist/__tests__/test-utils/targets.d.ts +26 -0
  41. package/dist/__tests__/test-utils/targets.d.ts.map +1 -0
  42. package/dist/__tests__/test-utils/targets.js +38 -0
  43. package/dist/__tests__/test-utils/targets.js.map +1 -0
  44. package/dist/__tests__/test-utils/with-sim-scope.d.ts +12 -0
  45. package/dist/__tests__/test-utils/with-sim-scope.d.ts.map +1 -0
  46. package/dist/__tests__/test-utils/with-sim-scope.js +22 -0
  47. package/dist/__tests__/test-utils/with-sim-scope.js.map +1 -0
  48. package/dist/__tests__/tool-live-view.test.d.ts +20 -0
  49. package/dist/__tests__/tool-live-view.test.d.ts.map +1 -0
  50. package/dist/__tests__/tool-live-view.test.js +146 -0
  51. package/dist/__tests__/tool-live-view.test.js.map +1 -0
  52. package/dist/__tests__/tool-show-mode.test.d.ts +10 -0
  53. package/dist/__tests__/tool-show-mode.test.d.ts.map +1 -0
  54. package/dist/__tests__/tool-show-mode.test.js +156 -0
  55. package/dist/__tests__/tool-show-mode.test.js.map +1 -0
  56. package/dist/__tests__/tool.test.d.ts +15 -0
  57. package/dist/__tests__/tool.test.d.ts.map +1 -0
  58. package/dist/__tests__/tool.test.js +250 -0
  59. package/dist/__tests__/tool.test.js.map +1 -0
  60. package/dist/cli/__tests__/sim-config.test.d.ts +2 -0
  61. package/dist/cli/__tests__/sim-config.test.d.ts.map +1 -0
  62. package/dist/cli/__tests__/sim-config.test.js +94 -0
  63. package/dist/cli/__tests__/sim-config.test.js.map +1 -0
  64. package/dist/cli/__tests__/sim-runner.test.d.ts +23 -0
  65. package/dist/cli/__tests__/sim-runner.test.d.ts.map +1 -0
  66. package/dist/cli/__tests__/sim-runner.test.js +188 -0
  67. package/dist/cli/__tests__/sim-runner.test.js.map +1 -0
  68. package/dist/cli/__tests__/sim-worker.test.d.ts +12 -0
  69. package/dist/cli/__tests__/sim-worker.test.d.ts.map +1 -0
  70. package/dist/cli/__tests__/sim-worker.test.js +69 -0
  71. package/dist/cli/__tests__/sim-worker.test.js.map +1 -0
  72. package/dist/cli/__tests__/sim.test.d.ts +2 -0
  73. package/dist/cli/__tests__/sim.test.d.ts.map +1 -0
  74. package/dist/cli/__tests__/sim.test.js +232 -0
  75. package/dist/cli/__tests__/sim.test.js.map +1 -0
  76. package/dist/cli/sim-config-schema.d.ts +30 -0
  77. package/dist/cli/sim-config-schema.d.ts.map +1 -0
  78. package/dist/cli/sim-config-schema.js +33 -0
  79. package/dist/cli/sim-config-schema.js.map +1 -0
  80. package/dist/cli/sim-config.d.ts +22 -0
  81. package/dist/cli/sim-config.d.ts.map +1 -0
  82. package/dist/cli/sim-config.js +73 -0
  83. package/dist/cli/sim-config.js.map +1 -0
  84. package/dist/cli/sim-runner.d.ts +60 -0
  85. package/dist/cli/sim-runner.d.ts.map +1 -0
  86. package/dist/cli/sim-runner.js +175 -0
  87. package/dist/cli/sim-runner.js.map +1 -0
  88. package/dist/cli/sim-worker.d.ts +24 -0
  89. package/dist/cli/sim-worker.d.ts.map +1 -0
  90. package/dist/cli/sim-worker.js +65 -0
  91. package/dist/cli/sim-worker.js.map +1 -0
  92. package/dist/cli/sim.d.ts +56 -0
  93. package/dist/cli/sim.d.ts.map +1 -0
  94. package/dist/cli/sim.js +265 -0
  95. package/dist/cli/sim.js.map +1 -0
  96. package/dist/framework/__tests__/assertions.test.d.ts +2 -0
  97. package/dist/framework/__tests__/assertions.test.d.ts.map +1 -0
  98. package/dist/framework/__tests__/assertions.test.js +122 -0
  99. package/dist/framework/__tests__/assertions.test.js.map +1 -0
  100. package/dist/framework/__tests__/misc-coverage.test.d.ts +18 -0
  101. package/dist/framework/__tests__/misc-coverage.test.d.ts.map +1 -0
  102. package/dist/framework/__tests__/misc-coverage.test.js +142 -0
  103. package/dist/framework/__tests__/misc-coverage.test.js.map +1 -0
  104. package/dist/framework/__tests__/resolve-metric.test.d.ts +12 -0
  105. package/dist/framework/__tests__/resolve-metric.test.d.ts.map +1 -0
  106. package/dist/framework/__tests__/resolve-metric.test.js +124 -0
  107. package/dist/framework/__tests__/resolve-metric.test.js.map +1 -0
  108. package/dist/framework/__tests__/result-builder.test.d.ts +2 -0
  109. package/dist/framework/__tests__/result-builder.test.d.ts.map +1 -0
  110. package/dist/framework/__tests__/result-builder.test.js +180 -0
  111. package/dist/framework/__tests__/result-builder.test.js.map +1 -0
  112. package/dist/framework/__tests__/scenario-logger.test.d.ts +9 -0
  113. package/dist/framework/__tests__/scenario-logger.test.d.ts.map +1 -0
  114. package/dist/framework/__tests__/scenario-logger.test.js +110 -0
  115. package/dist/framework/__tests__/scenario-logger.test.js.map +1 -0
  116. package/dist/framework/__tests__/validation.test.d.ts +9 -0
  117. package/dist/framework/__tests__/validation.test.d.ts.map +1 -0
  118. package/dist/framework/__tests__/validation.test.js +126 -0
  119. package/dist/framework/__tests__/validation.test.js.map +1 -0
  120. package/dist/framework/assertions.d.ts +106 -0
  121. package/dist/framework/assertions.d.ts.map +1 -0
  122. package/dist/framework/assertions.js +256 -0
  123. package/dist/framework/assertions.js.map +1 -0
  124. package/dist/framework/execution/__tests__/execution-engine.test.d.ts +9 -0
  125. package/dist/framework/execution/__tests__/execution-engine.test.d.ts.map +1 -0
  126. package/dist/framework/execution/__tests__/execution-engine.test.js +138 -0
  127. package/dist/framework/execution/__tests__/execution-engine.test.js.map +1 -0
  128. package/dist/framework/execution/__tests__/fault-builders.test.d.ts +5 -0
  129. package/dist/framework/execution/__tests__/fault-builders.test.d.ts.map +1 -0
  130. package/dist/framework/execution/__tests__/fault-builders.test.js +23 -0
  131. package/dist/framework/execution/__tests__/fault-builders.test.js.map +1 -0
  132. package/dist/framework/execution/__tests__/fault-model.test.d.ts +6 -0
  133. package/dist/framework/execution/__tests__/fault-model.test.d.ts.map +1 -0
  134. package/dist/framework/execution/__tests__/fault-model.test.js +64 -0
  135. package/dist/framework/execution/__tests__/fault-model.test.js.map +1 -0
  136. package/dist/framework/execution/__tests__/http-target.test.d.ts +5 -0
  137. package/dist/framework/execution/__tests__/http-target.test.d.ts.map +1 -0
  138. package/dist/framework/execution/__tests__/http-target.test.js +36 -0
  139. package/dist/framework/execution/__tests__/http-target.test.js.map +1 -0
  140. package/dist/framework/execution/__tests__/run-load-window.test.d.ts +7 -0
  141. package/dist/framework/execution/__tests__/run-load-window.test.d.ts.map +1 -0
  142. package/dist/framework/execution/__tests__/run-load-window.test.js +89 -0
  143. package/dist/framework/execution/__tests__/run-load-window.test.js.map +1 -0
  144. package/dist/framework/execution/execution-engine.d.ts +55 -0
  145. package/dist/framework/execution/execution-engine.d.ts.map +1 -0
  146. package/dist/framework/execution/execution-engine.js +111 -0
  147. package/dist/framework/execution/execution-engine.js.map +1 -0
  148. package/dist/framework/execution/fault-builders.d.ts +26 -0
  149. package/dist/framework/execution/fault-builders.d.ts.map +1 -0
  150. package/dist/framework/execution/fault-builders.js +24 -0
  151. package/dist/framework/execution/fault-builders.js.map +1 -0
  152. package/dist/framework/execution/fault-model.d.ts +49 -0
  153. package/dist/framework/execution/fault-model.d.ts.map +1 -0
  154. package/dist/framework/execution/fault-model.js +108 -0
  155. package/dist/framework/execution/fault-model.js.map +1 -0
  156. package/dist/framework/execution/fault-spec.d.ts +40 -0
  157. package/dist/framework/execution/fault-spec.d.ts.map +1 -0
  158. package/dist/framework/execution/fault-spec.js +23 -0
  159. package/dist/framework/execution/fault-spec.js.map +1 -0
  160. package/dist/framework/execution/http-target.d.ts +34 -0
  161. package/dist/framework/execution/http-target.d.ts.map +1 -0
  162. package/dist/framework/execution/http-target.js +41 -0
  163. package/dist/framework/execution/http-target.js.map +1 -0
  164. package/dist/framework/execution/latency-tracker.d.ts +44 -0
  165. package/dist/framework/execution/latency-tracker.d.ts.map +1 -0
  166. package/dist/framework/execution/latency-tracker.js +76 -0
  167. package/dist/framework/execution/latency-tracker.js.map +1 -0
  168. package/dist/framework/execution/run-load-window.d.ts +45 -0
  169. package/dist/framework/execution/run-load-window.d.ts.map +1 -0
  170. package/dist/framework/execution/run-load-window.js +136 -0
  171. package/dist/framework/execution/run-load-window.js.map +1 -0
  172. package/dist/framework/execution/scenario-aborted-error.d.ts +14 -0
  173. package/dist/framework/execution/scenario-aborted-error.d.ts.map +1 -0
  174. package/dist/framework/execution/scenario-aborted-error.js +24 -0
  175. package/dist/framework/execution/scenario-aborted-error.js.map +1 -0
  176. package/dist/framework/execution/target.d.ts +35 -0
  177. package/dist/framework/execution/target.d.ts.map +1 -0
  178. package/dist/framework/execution/target.js +21 -0
  179. package/dist/framework/execution/target.js.map +1 -0
  180. package/dist/framework/registry.d.ts +67 -0
  181. package/dist/framework/registry.d.ts.map +1 -0
  182. package/dist/framework/registry.js +113 -0
  183. package/dist/framework/registry.js.map +1 -0
  184. package/dist/framework/resolve-metric.d.ts +79 -0
  185. package/dist/framework/resolve-metric.d.ts.map +1 -0
  186. package/dist/framework/resolve-metric.js +135 -0
  187. package/dist/framework/resolve-metric.js.map +1 -0
  188. package/dist/framework/result-builder.d.ts +72 -0
  189. package/dist/framework/result-builder.d.ts.map +1 -0
  190. package/dist/framework/result-builder.js +214 -0
  191. package/dist/framework/result-builder.js.map +1 -0
  192. package/dist/framework/result-renderers.d.ts +37 -0
  193. package/dist/framework/result-renderers.d.ts.map +1 -0
  194. package/dist/framework/result-renderers.js +62 -0
  195. package/dist/framework/result-renderers.js.map +1 -0
  196. package/dist/framework/runnable-scenario.d.ts +37 -0
  197. package/dist/framework/runnable-scenario.d.ts.map +1 -0
  198. package/dist/framework/runnable-scenario.js +9 -0
  199. package/dist/framework/runnable-scenario.js.map +1 -0
  200. package/dist/framework/scenario-executor-result.d.ts +44 -0
  201. package/dist/framework/scenario-executor-result.d.ts.map +1 -0
  202. package/dist/framework/scenario-executor-result.js +13 -0
  203. package/dist/framework/scenario-executor-result.js.map +1 -0
  204. package/dist/framework/scenario-logger.d.ts +18 -0
  205. package/dist/framework/scenario-logger.d.ts.map +1 -0
  206. package/dist/framework/scenario-logger.js +39 -0
  207. package/dist/framework/scenario-logger.js.map +1 -0
  208. package/dist/framework/scenario-metric-key.d.ts +24 -0
  209. package/dist/framework/scenario-metric-key.d.ts.map +1 -0
  210. package/dist/framework/scenario-metric-key.js +17 -0
  211. package/dist/framework/scenario-metric-key.js.map +1 -0
  212. package/dist/framework/validation.d.ts +83 -0
  213. package/dist/framework/validation.d.ts.map +1 -0
  214. package/dist/framework/validation.js +93 -0
  215. package/dist/framework/validation.js.map +1 -0
  216. package/dist/index.d.ts +35 -0
  217. package/dist/index.d.ts.map +1 -0
  218. package/dist/index.js +53 -0
  219. package/dist/index.js.map +1 -0
  220. package/dist/internal.d.ts +19 -0
  221. package/dist/internal.d.ts.map +1 -0
  222. package/dist/internal.js +16 -0
  223. package/dist/internal.js.map +1 -0
  224. package/dist/kinds/chaos/__tests__/executor.test.d.ts +6 -0
  225. package/dist/kinds/chaos/__tests__/executor.test.d.ts.map +1 -0
  226. package/dist/kinds/chaos/__tests__/executor.test.js +117 -0
  227. package/dist/kinds/chaos/__tests__/executor.test.js.map +1 -0
  228. package/dist/kinds/chaos/config.d.ts +48 -0
  229. package/dist/kinds/chaos/config.d.ts.map +1 -0
  230. package/dist/kinds/chaos/config.js +15 -0
  231. package/dist/kinds/chaos/config.js.map +1 -0
  232. package/dist/kinds/chaos/define.d.ts +32 -0
  233. package/dist/kinds/chaos/define.d.ts.map +1 -0
  234. package/dist/kinds/chaos/define.js +111 -0
  235. package/dist/kinds/chaos/define.js.map +1 -0
  236. package/dist/kinds/chaos/executor.d.ts +21 -0
  237. package/dist/kinds/chaos/executor.d.ts.map +1 -0
  238. package/dist/kinds/chaos/executor.js +107 -0
  239. package/dist/kinds/chaos/executor.js.map +1 -0
  240. package/dist/kinds/chaos/result.d.ts +43 -0
  241. package/dist/kinds/chaos/result.d.ts.map +1 -0
  242. package/dist/kinds/chaos/result.js +12 -0
  243. package/dist/kinds/chaos/result.js.map +1 -0
  244. package/dist/kinds/load/__tests__/executor.test.d.ts +6 -0
  245. package/dist/kinds/load/__tests__/executor.test.d.ts.map +1 -0
  246. package/dist/kinds/load/__tests__/executor.test.js +75 -0
  247. package/dist/kinds/load/__tests__/executor.test.js.map +1 -0
  248. package/dist/kinds/load/config.d.ts +30 -0
  249. package/dist/kinds/load/config.d.ts.map +1 -0
  250. package/dist/kinds/load/config.js +9 -0
  251. package/dist/kinds/load/config.js.map +1 -0
  252. package/dist/kinds/load/define.d.ts +47 -0
  253. package/dist/kinds/load/define.d.ts.map +1 -0
  254. package/dist/kinds/load/define.js +76 -0
  255. package/dist/kinds/load/define.js.map +1 -0
  256. package/dist/kinds/load/executor.d.ts +16 -0
  257. package/dist/kinds/load/executor.d.ts.map +1 -0
  258. package/dist/kinds/load/executor.js +90 -0
  259. package/dist/kinds/load/executor.js.map +1 -0
  260. package/dist/kinds/load/result.d.ts +21 -0
  261. package/dist/kinds/load/result.d.ts.map +1 -0
  262. package/dist/kinds/load/result.js +10 -0
  263. package/dist/kinds/load/result.js.map +1 -0
  264. package/dist/persistence/session-payload.d.ts +32 -0
  265. package/dist/persistence/session-payload.d.ts.map +1 -0
  266. package/dist/persistence/session-payload.js +46 -0
  267. package/dist/persistence/session-payload.js.map +1 -0
  268. package/dist/persistence/session-replay.d.ts +13 -0
  269. package/dist/persistence/session-replay.d.ts.map +1 -0
  270. package/dist/persistence/session-replay.js +76 -0
  271. package/dist/persistence/session-replay.js.map +1 -0
  272. package/dist/persistence/session-replay.test.d.ts +10 -0
  273. package/dist/persistence/session-replay.test.d.ts.map +1 -0
  274. package/dist/persistence/session-replay.test.js +169 -0
  275. package/dist/persistence/session-replay.test.js.map +1 -0
  276. package/dist/plugins/__tests__/loader-scenarios.test.d.ts +12 -0
  277. package/dist/plugins/__tests__/loader-scenarios.test.d.ts.map +1 -0
  278. package/dist/plugins/__tests__/loader-scenarios.test.js +61 -0
  279. package/dist/plugins/__tests__/loader-scenarios.test.js.map +1 -0
  280. package/dist/plugins/__tests__/scenario-package-discovery.test.d.ts +2 -0
  281. package/dist/plugins/__tests__/scenario-package-discovery.test.d.ts.map +1 -0
  282. package/dist/plugins/__tests__/scenario-package-discovery.test.js +43 -0
  283. package/dist/plugins/__tests__/scenario-package-discovery.test.js.map +1 -0
  284. package/dist/plugins/loader.d.ts +32 -0
  285. package/dist/plugins/loader.d.ts.map +1 -0
  286. package/dist/plugins/loader.js +119 -0
  287. package/dist/plugins/loader.js.map +1 -0
  288. package/dist/plugins/scenario-package-discovery.d.ts +23 -0
  289. package/dist/plugins/scenario-package-discovery.d.ts.map +1 -0
  290. package/dist/plugins/scenario-package-discovery.js +42 -0
  291. package/dist/plugins/scenario-package-discovery.js.map +1 -0
  292. package/dist/plugins/types.d.ts +24 -0
  293. package/dist/plugins/types.d.ts.map +1 -0
  294. package/dist/plugins/types.js +18 -0
  295. package/dist/plugins/types.js.map +1 -0
  296. package/dist/recipes/__tests__/recipes.test.d.ts +2 -0
  297. package/dist/recipes/__tests__/recipes.test.d.ts.map +1 -0
  298. package/dist/recipes/__tests__/recipes.test.js +515 -0
  299. package/dist/recipes/__tests__/recipes.test.js.map +1 -0
  300. package/dist/recipes/built-in-recipes.d.ts +16 -0
  301. package/dist/recipes/built-in-recipes.d.ts.map +1 -0
  302. package/dist/recipes/built-in-recipes.js +37 -0
  303. package/dist/recipes/built-in-recipes.js.map +1 -0
  304. package/dist/recipes/define-recipe.d.ts +29 -0
  305. package/dist/recipes/define-recipe.d.ts.map +1 -0
  306. package/dist/recipes/define-recipe.js +68 -0
  307. package/dist/recipes/define-recipe.js.map +1 -0
  308. package/dist/recipes/registry.d.ts +54 -0
  309. package/dist/recipes/registry.d.ts.map +1 -0
  310. package/dist/recipes/registry.js +89 -0
  311. package/dist/recipes/registry.js.map +1 -0
  312. package/dist/recipes/service.d.ts +61 -0
  313. package/dist/recipes/service.d.ts.map +1 -0
  314. package/dist/recipes/service.js +205 -0
  315. package/dist/recipes/service.js.map +1 -0
  316. package/dist/recipes/types.d.ts +62 -0
  317. package/dist/recipes/types.d.ts.map +1 -0
  318. package/dist/recipes/types.js +10 -0
  319. package/dist/recipes/types.js.map +1 -0
  320. package/dist/scaffold/examples.d.ts +22 -0
  321. package/dist/scaffold/examples.d.ts.map +1 -0
  322. package/dist/scaffold/examples.js +91 -0
  323. package/dist/scaffold/examples.js.map +1 -0
  324. package/dist/scope-augmentation.d.ts +70 -0
  325. package/dist/scope-augmentation.d.ts.map +1 -0
  326. package/dist/scope-augmentation.js +28 -0
  327. package/dist/scope-augmentation.js.map +1 -0
  328. package/dist/tool.d.ts +21 -0
  329. package/dist/tool.d.ts.map +1 -0
  330. package/dist/tool.js +347 -0
  331. package/dist/tool.js.map +1 -0
  332. package/dist/types/base-types.d.ts +35 -0
  333. package/dist/types/base-types.d.ts.map +1 -0
  334. package/dist/types/base-types.js +8 -0
  335. package/dist/types/base-types.js.map +1 -0
  336. package/dist/types/framework-types.d.ts +62 -0
  337. package/dist/types/framework-types.d.ts.map +1 -0
  338. package/dist/types/framework-types.js +15 -0
  339. package/dist/types/framework-types.js.map +1 -0
  340. package/dist/types/kind-types.d.ts +24 -0
  341. package/dist/types/kind-types.d.ts.map +1 -0
  342. package/dist/types/kind-types.js +22 -0
  343. package/dist/types/kind-types.js.map +1 -0
  344. package/dist/types/workload.d.ts +30 -0
  345. package/dist/types/workload.d.ts.map +1 -0
  346. package/dist/types/workload.js +20 -0
  347. package/dist/types/workload.js.map +1 -0
  348. package/package.json +120 -0
@@ -0,0 +1,256 @@
1
+ /**
2
+ * @fileoverview Pre-built assertions for simulation scenarios
3
+ *
4
+ * All assertion functions are pure (no side effects).
5
+ * Default thresholds are production-safe.
6
+ * Custom assertions allow escape hatch.
7
+ */
8
+ // =============================================================================
9
+ // ASSERTION BUILDERS
10
+ // =============================================================================
11
+ /**
12
+ * Pre-built assertions for common metrics.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * export const myScenario = defineLoadScenario({
17
+ * // ...
18
+ * assertions: [
19
+ * ASSERTIONS.lowErrorRate(),
20
+ * ASSERTIONS.lowLatency('p95', 500),
21
+ * ASSERTIONS.minThroughput(100),
22
+ * ],
23
+ * });
24
+ * ```
25
+ */
26
+ export const ASSERTIONS = {
27
+ // ===========================================================================
28
+ // ERROR RATE
29
+ // ===========================================================================
30
+ /**
31
+ * Assert that error rate is below threshold.
32
+ * @param threshold - Maximum error rate (0-1). Default: 0.05 (5%)
33
+ */
34
+ lowErrorRate: (threshold = 0.05) => ({
35
+ metric: 'error_rate',
36
+ operator: 'lt',
37
+ value: threshold,
38
+ message: `Error rate must be < ${(threshold * 100).toFixed(1)}%`,
39
+ }),
40
+ /**
41
+ * Assert zero errors.
42
+ */
43
+ zeroErrors: () => ({
44
+ metric: 'error_rate',
45
+ operator: 'eq',
46
+ value: 0,
47
+ message: 'Error rate must be 0%',
48
+ }),
49
+ // ===========================================================================
50
+ // LATENCY
51
+ // ===========================================================================
52
+ /**
53
+ * Assert that latency percentile is below threshold.
54
+ * @param percentile - Which percentile to check (p50, p95, p99)
55
+ * @param thresholdMs - Maximum latency in milliseconds
56
+ */
57
+ lowLatency: (percentile = 'p95', thresholdMs = 500) => ({
58
+ metric: `${percentile}_latency_ms`,
59
+ operator: 'lt',
60
+ value: thresholdMs,
61
+ message: `${percentile.toUpperCase()} latency must be < ${thresholdMs}ms`,
62
+ }),
63
+ /**
64
+ * Assert that average latency is below threshold.
65
+ * @param thresholdMs - Maximum average latency in milliseconds
66
+ */
67
+ avgLatency: (thresholdMs = 200) => ({
68
+ metric: 'avg_latency_ms',
69
+ operator: 'lt',
70
+ value: thresholdMs,
71
+ message: `Average latency must be < ${thresholdMs}ms`,
72
+ }),
73
+ /**
74
+ * Assert that max latency is below threshold.
75
+ * @param thresholdMs - Maximum latency in milliseconds
76
+ */
77
+ maxLatency: (thresholdMs = 2000) => ({
78
+ metric: 'max_latency_ms',
79
+ operator: 'lt',
80
+ value: thresholdMs,
81
+ message: `Max latency must be < ${thresholdMs}ms`,
82
+ }),
83
+ // ===========================================================================
84
+ // THROUGHPUT
85
+ // ===========================================================================
86
+ /**
87
+ * Assert minimum throughput.
88
+ * @param rps - Minimum requests per second
89
+ */
90
+ minThroughput: (rps) => ({
91
+ metric: 'requests_per_second',
92
+ operator: 'gte',
93
+ value: rps,
94
+ message: `Throughput must be >= ${rps} RPS`,
95
+ }),
96
+ /**
97
+ * Assert maximum throughput (useful for rate limiting tests).
98
+ * @param rps - Maximum requests per second
99
+ */
100
+ maxThroughput: (rps) => ({
101
+ metric: 'requests_per_second',
102
+ operator: 'lte',
103
+ value: rps,
104
+ message: `Throughput must be <= ${rps} RPS`,
105
+ }),
106
+ // ===========================================================================
107
+ // SUCCESS RATE
108
+ // ===========================================================================
109
+ /**
110
+ * Assert high success rate.
111
+ * @param threshold - Minimum success rate (0-1). Default: 0.95 (95%)
112
+ */
113
+ highSuccessRate: (threshold = 0.95) => ({
114
+ metric: 'success_rate',
115
+ operator: 'gte',
116
+ value: threshold,
117
+ message: `Success rate must be >= ${(threshold * 100).toFixed(1)}%`,
118
+ }),
119
+ /**
120
+ * Assert 100% success rate.
121
+ */
122
+ perfectSuccessRate: () => ({
123
+ metric: 'success_rate',
124
+ operator: 'eq',
125
+ value: 1,
126
+ message: 'Success rate must be 100%',
127
+ }),
128
+ // ===========================================================================
129
+ // RESOURCE USAGE
130
+ // ===========================================================================
131
+ /**
132
+ * Assert memory usage is below threshold.
133
+ * @param thresholdMb - Maximum memory in megabytes
134
+ */
135
+ memoryUsage: (thresholdMb) => ({
136
+ metric: 'memory_mb',
137
+ operator: 'lt',
138
+ value: thresholdMb,
139
+ message: `Memory usage must be < ${thresholdMb}MB`,
140
+ }),
141
+ /**
142
+ * Assert CPU usage is below threshold.
143
+ * @param threshold - Maximum CPU percentage (0-100)
144
+ */
145
+ cpuUsage: (threshold) => ({
146
+ metric: 'cpu_percent',
147
+ operator: 'lt',
148
+ value: threshold,
149
+ message: `CPU usage must be < ${threshold}%`,
150
+ }),
151
+ // ===========================================================================
152
+ // CUSTOM
153
+ // ===========================================================================
154
+ /**
155
+ * Create a custom assertion.
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * ASSERTIONS.custom('listing_creation_time_ms', 'lt', 1000, 'Listing creation must be < 1s')
160
+ * ```
161
+ */
162
+ custom: (metric, operator, value, message) => ({
163
+ metric,
164
+ operator,
165
+ value,
166
+ message: message ?? `${metric} ${operator} ${value}`,
167
+ }),
168
+ };
169
+ // =============================================================================
170
+ // ASSERTION EVALUATION
171
+ // =============================================================================
172
+ /**
173
+ * Evaluate an operator comparison (low-level).
174
+ */
175
+ export function evaluateOperator(actual, operator, expected) {
176
+ switch (operator) {
177
+ case 'lt': {
178
+ return actual < expected;
179
+ }
180
+ case 'lte': {
181
+ return actual <= expected;
182
+ }
183
+ case 'gt': {
184
+ return actual > expected;
185
+ }
186
+ case 'gte': {
187
+ return actual >= expected;
188
+ }
189
+ case 'eq': {
190
+ return actual === expected;
191
+ }
192
+ case 'neq': {
193
+ return actual !== expected;
194
+ }
195
+ default: {
196
+ return false;
197
+ }
198
+ }
199
+ }
200
+ /**
201
+ * Evaluate an assertion against an actual value.
202
+ */
203
+ export function evaluateAssertion(assertion, actual) {
204
+ switch (assertion.operator) {
205
+ case 'lt': {
206
+ return actual < assertion.value;
207
+ }
208
+ case 'lte': {
209
+ return actual <= assertion.value;
210
+ }
211
+ case 'gt': {
212
+ return actual > assertion.value;
213
+ }
214
+ case 'gte': {
215
+ return actual >= assertion.value;
216
+ }
217
+ case 'eq': {
218
+ return actual === assertion.value;
219
+ }
220
+ case 'neq': {
221
+ return actual !== assertion.value;
222
+ }
223
+ default: {
224
+ return false;
225
+ }
226
+ }
227
+ }
228
+ /**
229
+ * Get a human-readable description of an operator.
230
+ */
231
+ export function getOperatorDescription(operator) {
232
+ switch (operator) {
233
+ case 'lt': {
234
+ return 'less than';
235
+ }
236
+ case 'lte': {
237
+ return 'at most';
238
+ }
239
+ case 'gt': {
240
+ return 'greater than';
241
+ }
242
+ case 'gte': {
243
+ return 'at least';
244
+ }
245
+ case 'eq': {
246
+ return 'equal to';
247
+ }
248
+ case 'neq': {
249
+ return 'not equal to';
250
+ }
251
+ default: {
252
+ return operator;
253
+ }
254
+ }
255
+ }
256
+ //# sourceMappingURL=assertions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.js","sourceRoot":"","sources":["../../src/framework/assertions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @fileoverview Unit tests for execution-engine utilities.
3
+ *
4
+ * The orchestration loop is exercised by scenario-execution.test.ts;
5
+ * this file targets the helper functions that are exported as the
6
+ * public API of the engine.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=execution-engine.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-engine.test.d.ts","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/execution-engine.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * @fileoverview Unit tests for execution-engine utilities.
3
+ *
4
+ * The orchestration loop is exercised by scenario-execution.test.ts;
5
+ * this file targets the helper functions that are exported as the
6
+ * public API of the engine.
7
+ */
8
+ import { describe, expect, it } from 'vitest';
9
+ import { resolveMetric } from '../../resolve-metric.js';
10
+ import { createEmptyMetrics } from '../../result-builder.js';
11
+ import { ScenarioAbortedError, scenarioAborted, sleepWithAbort, updateLatencyMetrics, validateAssertions, } from '../execution-engine.js';
12
+ const baseMetrics = (overrides = {}) => ({
13
+ ...createEmptyMetrics(),
14
+ totalRequests: 100,
15
+ successfulRequests: 99,
16
+ failedRequests: 1,
17
+ avgLatencyMs: 50,
18
+ p50LatencyMs: 40,
19
+ p95LatencyMs: 80,
20
+ p99LatencyMs: 120,
21
+ ...overrides,
22
+ });
23
+ describe('validateAssertions', () => {
24
+ it('returns passed=true when every assertion holds', () => {
25
+ const assertions = [
26
+ { metric: 'error_rate', operator: 'lt', value: 0.5, message: 'low error rate' },
27
+ { metric: 'success_rate', operator: 'gt', value: 0.5, message: 'high success rate' },
28
+ ];
29
+ const out = validateAssertions(baseMetrics(), assertions);
30
+ expect(out.passed).toBe(true);
31
+ expect(out.failed).toEqual([]);
32
+ });
33
+ it('returns failed entries with the actual value', () => {
34
+ const assertions = [
35
+ { metric: 'error_rate', operator: 'lt', value: 0.001, message: 'extreme low error' },
36
+ ];
37
+ const out = validateAssertions(baseMetrics(), assertions);
38
+ expect(out.passed).toBe(false);
39
+ expect(out.failed).toHaveLength(1);
40
+ expect(out.failed[0]?.actual).toBeCloseTo(0.01);
41
+ });
42
+ it('returns passed=false / failed=[] when assertions is not an array', () => {
43
+ const out = validateAssertions(baseMetrics(), undefined);
44
+ expect(out.passed).toBe(false);
45
+ expect(out.failed).toEqual([]);
46
+ });
47
+ it('honors an empty assertion list as passing', () => {
48
+ expect(validateAssertions(baseMetrics(), []).passed).toBe(true);
49
+ });
50
+ });
51
+ describe('resolveMetric (via validateAssertions)', () => {
52
+ it.each([
53
+ ['error_rate', baseMetrics({ totalRequests: 100, failedRequests: 25 }), 0.25],
54
+ ['error_rate', baseMetrics({ totalRequests: 0 }), 0],
55
+ ['success_rate', baseMetrics({ totalRequests: 100, successfulRequests: 90 }), 0.9],
56
+ // Per resolve-metric.ts: success_rate is 0 when totalRequests === 0 (tightening choice).
57
+ ['success_rate', baseMetrics({ totalRequests: 0 }), 0],
58
+ ['recovery_rate', baseMetrics({ errorsGenerated: 10, failedRequests: 2 }), 0.8],
59
+ ['recovery_rate', baseMetrics({ errorsGenerated: 0 }), 1],
60
+ ['p50_latency', baseMetrics({ p50LatencyMs: 40 }), 40],
61
+ ['p50_latency_ms', baseMetrics({ p50LatencyMs: 40 }), 40],
62
+ ['p95_latency_ms', baseMetrics({ p95LatencyMs: 80 }), 80],
63
+ ['p99_latency_ms', baseMetrics({ p99LatencyMs: 120 }), 120],
64
+ ['avg_latency_ms', baseMetrics({ avgLatencyMs: 60 }), 60],
65
+ ['total_requests', baseMetrics({ totalRequests: 5 }), 5],
66
+ ['failed_requests', baseMetrics({ failedRequests: 3 }), 3],
67
+ ])('resolveMetric(%s)', (metric, metrics, expected) => {
68
+ expect(resolveMetric(metric, metrics)).toBeCloseTo(expected);
69
+ });
70
+ });
71
+ describe('updateLatencyMetrics', () => {
72
+ it('seeds all percentile fields on the first sample', () => {
73
+ const m = createEmptyMetrics();
74
+ updateLatencyMetrics(m, 100);
75
+ expect(m.avgLatencyMs).toBe(100);
76
+ expect(m.p50LatencyMs).toBe(100);
77
+ expect(m.p95LatencyMs).toBe(100);
78
+ expect(m.p99LatencyMs).toBe(100);
79
+ });
80
+ it('updates the running average on subsequent samples', () => {
81
+ const m = { ...createEmptyMetrics(), totalRequests: 1, avgLatencyMs: 100 };
82
+ // After: n=1, avg becomes (100*0 + sample)/1 — but the function expects
83
+ // `metrics.totalRequests` to be the count BEFORE incrementing.
84
+ updateLatencyMetrics(m, 200);
85
+ expect(m.avgLatencyMs).toBe(200);
86
+ });
87
+ it('approximates percentiles as multiples of the average for n>=1', () => {
88
+ const m = { ...createEmptyMetrics(), totalRequests: 2, avgLatencyMs: 100 };
89
+ updateLatencyMetrics(m, 200);
90
+ expect(m.p50LatencyMs).toBeCloseTo(m.avgLatencyMs * 0.9);
91
+ expect(m.p95LatencyMs).toBeCloseTo(m.avgLatencyMs * 1.5);
92
+ expect(m.p99LatencyMs).toBeCloseTo(m.avgLatencyMs * 2);
93
+ });
94
+ });
95
+ describe('sleepWithAbort', () => {
96
+ it('resolves after the specified delay', async () => {
97
+ const ac = new AbortController();
98
+ const start = Date.now();
99
+ await sleepWithAbort(20, ac.signal);
100
+ expect(Date.now() - start).toBeGreaterThanOrEqual(15);
101
+ });
102
+ it('rejects immediately when the signal is already aborted', async () => {
103
+ const ac = new AbortController();
104
+ ac.abort();
105
+ await expect(sleepWithAbort(1000, ac.signal)).rejects.toThrow(ScenarioAbortedError);
106
+ });
107
+ it('rejects when the signal is aborted mid-sleep', async () => {
108
+ const ac = new AbortController();
109
+ const promise = sleepWithAbort(10_000, ac.signal);
110
+ setTimeout(() => ac.abort(), 5);
111
+ await expect(promise).rejects.toThrow(ScenarioAbortedError);
112
+ });
113
+ });
114
+ describe('scenarioAborted', () => {
115
+ it('returns silently when signal is undefined', () => {
116
+ expect(() => scenarioAborted(undefined)).not.toThrow();
117
+ });
118
+ it('returns silently when signal is not aborted', () => {
119
+ const ac = new AbortController();
120
+ expect(() => scenarioAborted(ac.signal)).not.toThrow();
121
+ });
122
+ it('throws ScenarioAbortedError when signal is aborted', () => {
123
+ const ac = new AbortController();
124
+ ac.abort();
125
+ expect(() => scenarioAborted(ac.signal, 'sid')).toThrow(ScenarioAbortedError);
126
+ });
127
+ });
128
+ describe('ScenarioAbortedError', () => {
129
+ it('carries the scenario id when one is supplied', () => {
130
+ const err = new ScenarioAbortedError('s1');
131
+ expect(err.message).toContain('s1');
132
+ });
133
+ it('uses an unknown placeholder when no id is supplied', () => {
134
+ const err = new ScenarioAbortedError();
135
+ expect(err.message.length).toBeGreaterThan(0);
136
+ });
137
+ });
138
+ //# sourceMappingURL=execution-engine.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-engine.test.js","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/execution-engine.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @fileoverview Tests for the fault.* builders.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=fault-builders.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fault-builders.test.d.ts","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/fault-builders.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @fileoverview Tests for the fault.* builders.
3
+ */
4
+ import { describe, expect, it } from 'vitest';
5
+ import { fault } from '../fault-builders.js';
6
+ describe('fault builders', () => {
7
+ it('latency', () => {
8
+ expect(fault.latency({ ms: 5 })).toEqual({ kind: 'latency', ms: 5 });
9
+ });
10
+ it('abort', () => {
11
+ expect(fault.abort()).toEqual({ kind: 'abort' });
12
+ });
13
+ it('drop', () => {
14
+ expect(fault.drop()).toEqual({ kind: 'drop' });
15
+ });
16
+ it('of assembles a probability-gated spec', () => {
17
+ expect(fault.of([fault.drop(), fault.abort()], { probability: 0.3 })).toEqual({
18
+ faults: [{ kind: 'drop' }, { kind: 'abort' }],
19
+ probability: 0.3,
20
+ });
21
+ });
22
+ });
23
+ //# sourceMappingURL=fault-builders.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fault-builders.test.js","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/fault-builders.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QACjB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACf,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;QACd,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAC5E,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YAC7C,WAAW,EAAE,GAAG;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @fileoverview Behaviour tests for the client-side fault model. Determinism
3
+ * comes from an injected RNG sequence so perturbed counts are exact.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=fault-model.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fault-model.test.d.ts","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/fault-model.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @fileoverview Behaviour tests for the client-side fault model. Determinism
3
+ * comes from an injected RNG sequence so perturbed counts are exact.
4
+ */
5
+ import { describe, expect, it } from 'vitest';
6
+ import { countingTarget, noopTarget } from '../../../__tests__/test-utils/targets.js';
7
+ import { fault } from '../fault-builders.js';
8
+ import { createFaultModel } from '../fault-model.js';
9
+ const ctx = { signal: new AbortController().signal, correlationId: 'c' };
10
+ /** RNG that walks a fixed sequence (wraps). */
11
+ const seq = (vals) => {
12
+ let i = 0;
13
+ return () => vals[i++ % vals.length] ?? 0;
14
+ };
15
+ describe('createFaultModel', () => {
16
+ it('perturbs exactly the requests whose draw < probability', async () => {
17
+ const ct = countingTarget();
18
+ const fm = createFaultModel(fault.of([fault.drop()], { probability: 0.5 }), {
19
+ rng: seq([0.4, 0.6, 0.4, 0.6]),
20
+ });
21
+ const wrapped = fm.wrap(ct.target);
22
+ const results = await Promise.allSettled([
23
+ wrapped(ctx),
24
+ wrapped(ctx),
25
+ wrapped(ctx),
26
+ wrapped(ctx),
27
+ ]);
28
+ // Draws 0.4 and 0.4 (< 0.5) → dropped (rejected); 0.6 and 0.6 → passed through.
29
+ expect(results.filter((r) => r.status === 'rejected')).toHaveLength(2);
30
+ expect(ct.calls()).toBe(2); // dropped requests never reach the target
31
+ expect(fm.drained()).toHaveLength(2);
32
+ expect(fm.drained().every((f) => f.kind === 'drop')).toBe(true);
33
+ });
34
+ it('latency fault delays the real call (target still runs)', async () => {
35
+ const ct = countingTarget();
36
+ const fm = createFaultModel(fault.of([fault.latency({ ms: 50 })], { probability: 1 }), {
37
+ rng: () => 0,
38
+ });
39
+ const start = Date.now();
40
+ await fm.wrap(ct.target)(ctx);
41
+ expect(Date.now() - start).toBeGreaterThanOrEqual(45);
42
+ expect(ct.calls()).toBe(1);
43
+ });
44
+ it('abort fault fails even when the target ignores the signal', async () => {
45
+ const fm = createFaultModel(fault.of([fault.abort()], { probability: 1 }), { rng: () => 0 });
46
+ await expect(fm.wrap(noopTarget)(ctx)).rejects.toThrow();
47
+ expect(fm.drained()).toHaveLength(1);
48
+ expect(fm.drained()[0]?.kind).toBe('abort');
49
+ });
50
+ it('does not perturb when probability is 0', async () => {
51
+ const ct = countingTarget();
52
+ const fm = createFaultModel(fault.of([fault.drop()], { probability: 0 }), { rng: () => 0 });
53
+ await fm.wrap(ct.target)(ctx);
54
+ expect(ct.calls()).toBe(1);
55
+ expect(fm.drained()).toHaveLength(0);
56
+ });
57
+ it('round-robins across multiple fault kinds deterministically', async () => {
58
+ const fm = createFaultModel(fault.of([fault.drop(), fault.latency({ ms: 1 })], { probability: 1 }), { rng: () => 0 });
59
+ const wrapped = fm.wrap(noopTarget);
60
+ await Promise.allSettled([wrapped(ctx), wrapped(ctx), wrapped(ctx)]);
61
+ expect(fm.drained().map((f) => f.kind)).toEqual(['drop', 'latency', 'drop']);
62
+ });
63
+ });
64
+ //# sourceMappingURL=fault-model.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fault-model.test.js","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/fault-model.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @fileoverview Tests for the httpTarget helper (fetch stubbed).
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=http-target.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-target.test.d.ts","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/http-target.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @fileoverview Tests for the httpTarget helper (fetch stubbed).
3
+ */
4
+ import { afterEach, describe, expect, it, vi } from 'vitest';
5
+ import { httpTarget } from '../http-target.js';
6
+ const ctx = { signal: new AbortController().signal, correlationId: 'c' };
7
+ const respond = (body, status) => () => Promise.resolve(new Response(body, { status }));
8
+ afterEach(() => {
9
+ vi.restoreAllMocks();
10
+ });
11
+ describe('httpTarget', () => {
12
+ it('resolves on a 2xx', async () => {
13
+ vi.stubGlobal('fetch', vi.fn(respond('ok', 200)));
14
+ await expect(httpTarget({ url: 'https://x.test' })(ctx)).resolves.toBeUndefined();
15
+ });
16
+ it('throws on a non-2xx, carrying the status', async () => {
17
+ vi.stubGlobal('fetch', vi.fn(respond('no', 503)));
18
+ await expect(httpTarget({ url: 'https://x.test' })(ctx)).rejects.toThrow(/503/);
19
+ });
20
+ it('forwards method, headers, body, and the abort signal', async () => {
21
+ const f = vi.fn(respond('ok', 200));
22
+ vi.stubGlobal('fetch', f);
23
+ await httpTarget({ url: 'https://x.test', method: 'POST', headers: { a: 'b' }, body: 'p' })(ctx);
24
+ expect(f).toHaveBeenCalledWith('https://x.test', expect.objectContaining({
25
+ method: 'POST',
26
+ headers: { a: 'b' },
27
+ body: 'p',
28
+ signal: ctx.signal,
29
+ }));
30
+ });
31
+ it('honours a custom okStatus predicate', async () => {
32
+ vi.stubGlobal('fetch', vi.fn(respond('nope', 404)));
33
+ await expect(httpTarget({ url: 'https://x.test', okStatus: (s) => s === 404 })(ctx)).resolves.toBeUndefined();
34
+ });
35
+ });
36
+ //# sourceMappingURL=http-target.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-target.test.js","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/http-target.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE7D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI/C,MAAM,GAAG,GAAkB,EAAE,MAAM,EAAE,IAAI,eAAe,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;AAExF,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,MAAc,EAAE,EAAE,CAAC,GAAG,EAAE,CACrD,OAAO,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAElD,SAAS,CAAC,GAAG,EAAE;IACb,EAAE,CAAC,eAAe,EAAE,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACjC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACpC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC1B,MAAM,UAAU,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CACzF,GAAG,CACJ,CAAC;QACF,MAAM,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAC5B,gBAAgB,EAChB,MAAM,CAAC,gBAAgB,CAAC;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE;YACnB,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,MAAM,CACV,UAAU,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CACvE,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,7 @@
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
+ export {};
7
+ //# sourceMappingURL=run-load-window.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-load-window.test.d.ts","sourceRoot":"","sources":["../../../../src/framework/execution/__tests__/run-load-window.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}