@flemist/test-variants 5.0.15 → 5.0.17

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/README.md CHANGED
@@ -83,6 +83,8 @@ const result = await testVariants({
83
83
  // Console output parameters, default: true
84
84
  log: true, // all console output parameters default
85
85
  log: boolean | {
86
+ // saved error variants replay logging; default true
87
+ replay: boolean, // default: true
86
88
  // message about test start
87
89
  start: boolean, // default: true
88
90
  // every N milliseconds shows progress info and statistics; false/0 to disable
@@ -96,7 +98,7 @@ const result = await testVariants({
96
98
  // debug logging for internal behavior
97
99
  debug: boolean, // default: false
98
100
  // custom log function; receives log type and formatted message
99
- func: (type: 'start' | 'progress' | 'completed' | 'error' | 'modeChange' | 'debug', message: string) => void,
101
+ func: (type: 'replay' | 'start' | 'progress' | 'completed' | 'error' | 'modeChange' | 'debug', message: string) => void,
100
102
  // custom formatter for objects in log messages (args, errors, etc)
101
103
  // default uses formatAny with pretty printing
102
104
  format: (obj: any) => string,
@@ -275,11 +277,14 @@ const result = await testVariants({
275
277
  // Repeats failing variant up to 5 times in debug mode
276
278
  pauseDebuggerOnError: boolean | null, // default: true
277
279
 
278
- // Time controller for all internal delays, timeouts and getting current time
279
- // Used inside testVariants instead of direct setTimeout, Date.now calls, etc
280
- // Intended only for testing and debugging the test-variants library itself
280
+ // Time controller for time-dependent operations inside user tests
281
+ // Passed to test function via testOptions.timeController
281
282
  timeController: ITimeController, // default: null - use timeControllerDefault
282
283
 
284
+ // Time controller for internal library timing instead of direct setTimeout, Date.now calls, etc
285
+ // Intended only for testing and debugging the test-variants library itself
286
+ timeControllerInternal: ITimeController, // default: null - use timeControllerDefault
287
+
283
288
  // Maximum duration for a single test run (milliseconds)
284
289
  // Throws TimeoutError if exceeded
285
290
  // Function form returns timeout per variant; null/undefined disables for that variant
@@ -323,11 +328,14 @@ The internal implementation operates in a faster synchronous mode (without await
323
328
 
324
329
  ### Logs format
325
330
  ```
331
+ [test-variants] replay skipped, args not in template; file: tmp/test/variants/2025-01-01_10-00-00.json
332
+ [test-variants] replay, files: 2/3, memory: 139MB
333
+ [test-variants] replay end, tests: 20 (1.5s), maxTime: 0.1s, async: 0, memory: 148MB (+8.8MB)
326
334
  [test-variants] start, memory: 139MB
327
335
  [test-variants] mode[0]: random
328
- [test-variants] cycle: 3, variant: 65 (1.0s), tests: 615 (5.0s), maxTime: 0.1s, async: 12, memory: 148MB (+8.8MB)
336
+ [test-variants] tests: 615 (5.0s), maxTime: 0.1s, async: 12, memory: 148MB (+8.8MB)
329
337
  [test-variants] mode[1]: backward, limitTests=10
330
- [test-variants] cycle: 5, variant: 65/100 (2.0s), tests: 615 (6.0s), maxTime: 0.2s, async: 123, memory: 139MB (-8.8MB)
338
+ [test-variants] tests: 615 (6.0s), maxTime: 0.2s, async: 123, memory: 139MB (-8.8MB)
331
339
  [test-variants] mode[2]: forward, limitTests=100, limitTime=10.9m
332
340
  [test-variants] end, tests: 815 (7.0s), maxTime: 0.2s, async: 123, memory: 138MB (-1.0MB)
333
341
  ...
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../createTestVariants-C2AcN9Rj.js");exports.TimeoutError=e.TimeoutError;exports.createTestVariants=e.createTestVariants;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../createTestVariants-B-tIuCMH.js");exports.TimeoutError=e.TimeoutError;exports.createTestVariants=e.createTestVariants;
@@ -1,4 +1,4 @@
1
- import { T as e, c as t } from "../createTestVariants-MkSgLExA.mjs";
1
+ import { T as e, c as t } from "../createTestVariants-CHmhRbUZ.mjs";
2
2
  export {
3
3
  e as TimeoutError,
4
4
  t as createTestVariants
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../createTestVariants-C2AcN9Rj.js");exports.TimeoutError=e.TimeoutError;exports.createTestVariants=e.createTestVariants;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../createTestVariants-B-tIuCMH.js");exports.TimeoutError=e.TimeoutError;exports.createTestVariants=e.createTestVariants;
@@ -1,4 +1,4 @@
1
- import { T as e, c as t } from "../createTestVariants-MkSgLExA.mjs";
1
+ import { T as e, c as t } from "../createTestVariants-CHmhRbUZ.mjs";
2
2
  export {
3
3
  e as TimeoutError,
4
4
  t as createTestVariants
@@ -75,6 +75,7 @@ export declare class LogInvariant {
75
75
  private _logModeChangeCount;
76
76
  private _logErrorCount;
77
77
  private _logDebugCount;
78
+ private _logReplayCount;
78
79
  private _anyLogAfterCompleted;
79
80
  /** Stores expected mode info for validation when modeChange log is received */
80
81
  private _pendingModeInfo;
@@ -110,6 +111,7 @@ export declare class LogInvariant {
110
111
  */
111
112
  private _validateErrorLog;
112
113
  private _validateDebugLog;
114
+ private _validateReplayLog;
113
115
  /**
114
116
  * Run after test variants completion
115
117
  *
@@ -123,4 +125,5 @@ export declare class LogInvariant {
123
125
  get logModeChangeCount(): number;
124
126
  get logErrorCount(): number;
125
127
  get logDebugCount(): number;
128
+ get logReplayCount(): number;
126
129
  }
@@ -35,8 +35,8 @@ export type VariantsIteratorOptions<Args extends Obj> = {
35
35
  getSeed?: null | ((params: GetSeedParams) => any);
36
36
  /** Iteration modes (variant traversal methods); each mode runs until its limits are reached */
37
37
  iterationModes?: null | readonly ModeConfig[];
38
- /** Time controller for testable time-dependent operations; null uses timeControllerDefault */
39
- timeController?: null | ITimeController;
38
+ /** Time controller for internal library timing; null uses timeControllerDefault */
39
+ timeControllerInternal?: null | ITimeController;
40
40
  /** Callback invoked when iteration mode changes */
41
41
  onModeChange?: null | OnModeChangeCallback;
42
42
  /** Global completion count limit; default 1 */
@@ -3,5 +3,11 @@ import { ModeConfig } from '../types';
3
3
  export declare function formatDuration(ms: number): string;
4
4
  /** Format bytes in human-readable form */
5
5
  export declare function formatBytes(bytes: number): string;
6
+ export declare function formatMemoryDiff(current: number, previous: number): string;
7
+ export type TestStatsResult = {
8
+ message: string;
9
+ memory: number | null;
10
+ };
11
+ export declare function formatTestStats(tests: number, elapsed: number, maxTestDuration: number, iterationsAsync: number, prevMemory?: null | number): TestStatsResult;
6
12
  /** Format mode config for logging */
7
13
  export declare function formatModeConfig(modeConfig: ModeConfig | null, modeIndex: number): string;
@@ -22,4 +22,4 @@ export type RunState = {
22
22
  prevGcIterationsAsync: number;
23
23
  };
24
24
  /** Create initial run state */
25
- export declare function createRunState(timeController: ITimeController, startMemory: number | null): RunState;
25
+ export declare function createRunState(timeControllerInternal: ITimeController, startMemory: number | null): RunState;
@@ -14,6 +14,7 @@ export type RunOptionsResolved<Args extends Obj> = {
14
14
  findBestError: FindBestErrorOptions | null | undefined;
15
15
  dontThrowIfError: boolean | null | undefined;
16
16
  timeController: ITimeController;
17
+ timeControllerInternal: ITimeController;
17
18
  /** Maximum number of parallel threads */
18
19
  parallel: number;
19
20
  /** Switch to sequential mode after first error in findBestError mode */
@@ -1,4 +1,5 @@
1
1
  import { Obj, PromiseOrValue, RequiredNonNullable } from '@flemist/simple-utils';
2
+ import { ITimeController } from '@flemist/time-controller';
2
3
  import { TestVariantsTemplatesExt, VariantsIterator } from '../iterator/types';
3
4
  import { ArgsWithSeed, OnErrorCallback, OnTestEndCallback, OnTestStartCallback, SaveErrorVariantsOptions, TestVariantsState, TestVariantsLogOptions, TestVariantsResult, TestVariantsRunOptions } from '../types';
4
5
  import { RunState } from './createRunState';
@@ -43,6 +44,10 @@ export type SaveErrorVariantsStoreReplayOptions<Args extends Obj> = {
43
44
  findBestErrorEnabled?: null | boolean;
44
45
  /** Mutable run state for tracking test count during replay */
45
46
  state: RunState;
47
+ /** Resolved logging options */
48
+ logOptions: RequiredNonNullable<TestVariantsLogOptions>;
49
+ /** Time controller for internal library timing */
50
+ timeControllerInternal: ITimeController;
46
51
  };
47
52
  /** Factory function for creating SaveErrorVariantsStore */
48
53
  export type CreateSaveErrorVariantsStore<Args extends Obj, SavedArgs = Args> = (options: SaveErrorVariantsOptions<Args, SavedArgs>) => SaveErrorVariantsStore<Args> | null;
@@ -62,6 +62,8 @@ export type TestVariantsLogFunc = (type: TestVariantsLogType, message: string) =
62
62
  export type TestVariantsLogFormat = (obj: any) => string;
63
63
  /** Logging options for test-variants */
64
64
  export type TestVariantsLogOptions = {
65
+ /** Log saved error variants replay; default true */
66
+ replay?: null | boolean;
65
67
  /** Log at test start with memory info; default true */
66
68
  start?: null | boolean;
67
69
  /** Progress log interval in ms; false/0 to disable; default 5000 */
@@ -105,6 +107,7 @@ export type SaveErrorVariantsOptions<Args extends Obj, SavedArgs = Args> = {
105
107
  /** Options passed to test function */
106
108
  export type TestVariantsState = {
107
109
  abortSignal: IAbortSignalFast;
110
+ /** For time-dependent operations inside user tests; same instance as timeController run option */
108
111
  timeController: ITimeController;
109
112
  };
110
113
  /** Options for finding the earliest failing variant across multiple test runs */
@@ -210,8 +213,10 @@ export type TestVariantsRunOptions<Args extends Obj = Obj, SavedArgs = Args> = {
210
213
  limitTests?: null | number;
211
214
  /** Maximum total duration in milliseconds; does not interrupt a running test, only prevents starting the next iteration; use timeout to interrupt individual tests; not applied during saveErrorVariants replay to ensure all previously failing variants are verified */
212
215
  limitTime?: null | number;
213
- /** Time controller for testable time-dependent operations; null uses timeControllerDefault */
216
+ /** Time controller for time-dependent operations inside user tests; null uses timeControllerDefault */
214
217
  timeController?: null | ITimeController;
218
+ /** Time controller for internal library timing; null uses timeControllerDefault */
219
+ timeControllerInternal?: null | ITimeController;
215
220
  /** Throws TimeoutError if single test run exceeds this timeout */
216
221
  timeout?: null | number | ((args: Args) => number | null | undefined);
217
222
  };
@@ -0,0 +1,4 @@
1
+ "use strict";const q=require("@flemist/time-controller"),S=require("@flemist/simple-utils"),j=require("@flemist/abort-controller-fast"),Y=require("@flemist/time-limits");class pe extends Error{}function oe(){if(typeof process<"u"&&process.memoryUsage)try{return process.memoryUsage.rss()}catch{}if(typeof performance<"u"){const e=performance.memory;if(e)try{return e.usedJSHeapSize}catch{}}return null}const He=1e3,R=[];function Je(e){return S.formatAny(e,{pretty:!0,maxDepth:5,maxItems:50})}function Xe(...e){const t=e.map(r=>typeof r=="string"?r:Je(r)).join(" ");R.push(t),R.length>He&&R.shift(),console.log(t)}function Ze(){return R.join(`
2
+ `)}globalThis.__getStressTestLogLast=Ze;const he=(e,t)=>{Xe(t)},be=e=>S.formatAny(e,{pretty:!0,maxDepth:20,maxItems:100,maxStringLength:5e3,dontExpandClassInstances:!0,dontExpandFunctions:!0}),C={replay:!0,start:!0,progress:5e3,completed:!0,error:!0,modeChange:!0,debug:!1,func:he,format:be},Ke={replay:!1,start:!1,progress:!1,completed:!1,error:!1,modeChange:!1,debug:!1,func:he,format:be};function ye(e){return e===!1?Ke:e===!0||!e?C:{replay:e.replay??C.replay,start:e.start??C.start,progress:e.progress??C.progress,completed:e.completed??C.completed,error:e.error??C.error,modeChange:e.modeChange??C.modeChange,debug:e.debug??C.debug,func:e.func??C.func,format:e.format??C.format}}function Qe(e,t){const r=e.now();return{startTime:r,startMemory:t,debugMode:!1,tests:0,iterations:0,iterationsAsync:0,maxTestDuration:0,prevLogTime:r,prevLogMemory:t,pendingModeChange:null,prevGcTime:r,prevGcIterations:0,prevGcIterationsAsync:0}}class V extends j.AbortError{}class Ye{_timeController;_subject;_interval;_timer;constructor(t,r){this._interval=t,this._timeController=r??q.timeControllerDefault,this._subject=new S.Subject({startStopNotifier:()=>(this.update(),()=>{this._timeController.clearTimeout(this._timer)})})}update(){this._subject.emit(this._timeController.now()),this._timer=this._timeController.setTimeout(()=>this.update(),this._interval)}get interval(){return this._interval}set interval(t){this._interval=t,this._timer&&(this._timeController.clearTimeout(this._timer),this.update())}subscribe(t){return this._subject.subscribe(t)}}const et=50,tt=5;function rt(e,t){return e==null?null:typeof e=="number"?e:e(t)??null}function ce(e,t){return typeof e=="number"?{iterationsAsync:0,iterationsSync:e}:e!=null&&typeof e=="object"?e:t?{iterationsAsync:1,iterationsSync:0}:{iterationsAsync:0,iterationsSync:1}}function nt(e,t){const r=t.log,o=t.pauseDebuggerOnError??!0,i=t.onStart,s=t.onEnd,n=t.state;let l=null,c=0;function d(v,b,f){l==null&&(l={error:v,args:b,tests:f},r.error&&r.func("error",`[test-variants] error variant: ${r.format(b)}
3
+ tests: ${f}
4
+ ${r.format(v)}`));const h=Date.now();if(o)debugger;if(Date.now()-h>et&&c<tt){r.func("debug",`[test-variants] debug iteration: ${c}`),c++;return}const T=l;throw l=null,t.onError&&t.onError(T),T.error}const g=new Ye(100);return function(b,f,h){i&&i({args:b,tests:f});const E=rt(t.timeout,b),T=Date.now();let m=h,x=null;E&&(x=new j.AbortControllerFast,m={abortSignal:S.combineAbortSignals(h.abortSignal,x.signal),timeController:h.timeController});function A(){x.abort(new pe(`[test-variants] test timeout ${E}ms exceeded`))}function w(){const y=Date.now()-T;y>n.maxTestDuration&&(n.maxTestDuration=y)}try{let y=e(b,m);if(S.isPromiseLike(y)){let P=null;return x&&(P=g.subscribe(()=>{Date.now()-T>E&&(A(),P())}),y=Promise.race([y,S.abortSignalToPromise(x.signal)])),y.then(O=>{P?.(),w();const D=ce(O,!0);return s&&s({args:b,tests:f,result:D}),D},O=>(P?.(),w(),s&&!(O instanceof V)&&s({args:b,tests:f,error:O}),d(O,b,f)))}w(),x&&Date.now()-T>E&&(A(),x.signal.throwIfAborted());const k=ce(y,!1);return s&&s({args:b,tests:f,result:k}),k}catch(y){return w(),y instanceof V?void 0:(s&&s({args:b,tests:f,error:y}),d(y,b,f))}}}function W(e,t,r){for(let o=0,i=e.length;o<i;o++)if(r?r(e[o],t):e[o]===t)return o;return-1}function fe(e,t,r,o){const i=Object.keys(e.templates),s={},n=[],l=[],c=[],d=i.length;for(let g=0;g<d;g++){const v=i[g];s[v]=void 0,n.push(-1),l.push(void 0),c.push(null)}return{args:s,argsNames:i,indexes:n,argValues:l,argLimits:c,attempts:0,templates:e,limitArgOnError:r,equals:t,includeErrorVariant:o??!1}}function $(e,t){const r=e.templates.templates[t],o=e.templates.extra[t];let i;if(typeof r=="function"?i=r(e.args):i=r,o==null)return i;let s=null;const n=o.length;for(let l=0;l<n;l++){const c=o[l];W(i,c,e.equals)<0&&(s==null?s=[...i,c]:s.push(c))}return s??i}function M(e,t,r){const o=e.argValues[t].length;if(o===0)return-1;const i=e.argLimits[t];if(i==null)return o-1;let s=e.limitArgOnError;if(typeof s=="function"){const n=e.argsNames[t];s=s({name:n,values:e.argValues[t],maxValueIndex:i})}return!r||s?Math.min(i,o-1):o-1}function L(e){const t=e.indexes.length;for(let r=0;r<t;r++){const o=e.argLimits[r];if(o==null)return!1;const i=e.indexes[r];if(i>o)return!0;if(i<o)return!1}return!e.includeErrorVariant}function N(e){const t=e.indexes.length;for(let r=0;r<t;r++)e.indexes[r]=-1,e.argValues[r]=void 0,e.args[e.argsNames[r]]=void 0}function ve(e){let t=!1,r=!0;const o=e.indexes.length;let i=o,s=!1,n=0;for(;n<o;n++){const l=e.argValues[n]==null;(l||s)&&(l&&(t=!0),e.argValues[n]=$(e,e.argsNames[n]));const c=M(e,n,n>i);if(c<0){r=!1,e.indexes[n]=-1;break}l&&(e.indexes[n]=0,e.args[e.argsNames[n]]=e.argValues[n][0]),(s||e.indexes[n]>c)&&(e.indexes[n]=c,e.args[e.argsNames[n]]=e.argValues[n][c],s=!0),i===o&&e.indexes[n]<c&&(i=n)}if(L(e))return N(e),!1;if(t&&r)return!0;for(n--;n>=0;n--){if(e.argValues[n]==null)continue;let l=n>i;const c=M(e,n,l),d=e.indexes[n]+1;if(d<=c){e.indexes[n]=d,e.args[e.argsNames[n]]=e.argValues[n][d],d<c&&(l=!0);for(let g=n+1;g<o;g++)e.args[e.argsNames[g]]=void 0;for(n++;n<o;n++){e.argValues[n]=$(e,e.argsNames[n]);const g=M(e,n,l);if(g<0)break;e.indexes[n]=0,e.args[e.argsNames[n]]=e.argValues[n][0],g>0&&(l=!0)}if(n>=o)return L(e)?(N(e),!1):!0}}return N(e),!1}function ee(e){L(e)&&N(e);let t=!1,r=!0;const o=e.indexes.length;let i=o,s=!1,n=0;for(;n<o;n++){const l=e.argValues[n]==null;(l||s)&&(l&&(t=!0),e.argValues[n]=$(e,e.argsNames[n]));const c=M(e,n,n>i);if(c<0){r=!1,e.indexes[n]=-1;break}l&&(e.indexes[n]=c,e.args[e.argsNames[n]]=e.argValues[n][c]),(s||e.indexes[n]>c)&&(e.indexes[n]=c,e.args[e.argsNames[n]]=e.argValues[n][c],s=!0),i===o&&e.indexes[n]<c&&(i=n)}if((t||s)&&r&&!L(e))return!0;for(n--;n>=0;n--){if(e.argValues[n]==null)continue;let l=n>i;const c=M(e,n,l);let d=e.indexes[n]-1;if(d>c&&(d=c),d>=0){e.indexes[n]=d,e.args[e.argsNames[n]]=e.argValues[n][d],d<c&&(l=!0);for(let g=n+1;g<o;g++)e.args[e.argsNames[g]]=void 0;for(n++;n<o;n++){e.argValues[n]=$(e,e.argsNames[n]);const g=M(e,n,l);if(g<0)break;e.indexes[n]=g,e.args[e.argsNames[n]]=e.argValues[n][g],g>0&&(l=!0)}if(n>=o)return!0}}return N(e),!1}function it(e,t){N(e);const r=e.argsNames,o=r.length;let i=!1;for(let s=0;s<o;s++){const n=r[s],l=t[n];if(l===void 0)return null;e.argValues[s]=$(e,n);const c=M(e,s,i);if(c<0)return null;const d=W(e.argValues[s],l,e.equals);if(d<0||d>c)return null;e.indexes[s]=d,e.args[e.argsNames[s]]=e.argValues[s][d],e.indexes[s]<c&&(i=!0)}return L(e)?null:e.indexes.slice()}function ot(e){const t=e.indexes.length;if(t===0)return!1;let r=!1;for(let o=0;o<t;o++){e.argValues[o]=$(e,e.argsNames[o]);const i=M(e,o,r);if(i<0)return Math.random()<.5?ve(e):ee(e);e.indexes[o]=Math.floor(Math.random()*(i+1)),e.args[e.argsNames[o]]=e.argValues[o][e.indexes[o]],e.indexes[o]<i&&(r=!0)}return L(e)?ee(e):!0}function B(e){return e.mode==="forward"||e.mode==="backward"}function st(e,t,r,o){const i=t[r],s=e.templates[r];if(typeof s!="function"){if(W(s,i,o)>=0)return;s.push(i);return}const n=e.extra[r];if(n==null){e.extra[r]=[i];return}W(n,i,o)>=0||n.push(i)}function at(e,t,r){for(const o in t)if(Object.prototype.hasOwnProperty.call(t,o)){if(o==="seed")continue;st(e,t,o,r)}}function me(e,t){for(const r in t)if(Object.prototype.hasOwnProperty.call(t,r)){if(r==="seed")continue;if(!e[r])return!1}return!0}const lt=[{mode:"forward"}];function ut(e){const{argsTemplates:t,equals:r,limitArgOnError:o,includeErrorVariant:i,getSeed:s,iterationModes:n,onModeChange:l,limitCompletionCount:c,limitTests:d,limitTime:g}=e,v=e.timeControllerInternal??q.timeControllerDefault,b={templates:S.deepCloneJsonLike(t),extra:{}},f=n==null||n.length===0?lt:n,h=[];let E=null,T=null,m=0,x=0,A=!1,w=0;function y(){A||(A=!0,w=v.now(),k(),m=0,D(),O())}function k(){for(let a=0,u=f.length;a<u;a++)h.push(P())}function P(){return{navigationState:fe(b,r??null,o??null,i??null),cycleCount:0,completedCount:0,testsInLastTurn:0,tryNextVariantAttempts:0,startTime:null}}function O(){E=fe(b,r??null,!1,!1)}function D(){l?.({mode:f[m],modeIndex:m,tests:x})}function Te(a){y(),me(b.templates,a)&&at(b,a,r)}function le(a,u){return y(),me(b.templates,a)?(E.limitArgOnError=u?.limitArg??o??null,E.includeErrorVariant=u?.includeLimit??i??!1,it(E,a)):null}function we(a){const u=a?.args;if(u==null)return;y();const p=le(u);if(p!=null){T={args:u,error:a?.error,tests:a?.tests??x},E.argLimits=p;for(let I=0,F=h.length;I<F;I++){const K=h[I].navigationState;K.argLimits=p}}}function Ie(){return y(),Ce()}function Ce(){for(;;){if(!Me())return null;for(;;){const a=Ge();if(a!=null)return h[m].testsInLastTurn++,x++,a;if(_e()){if(!Ne())return null;De();break}}}}function Me(){return!(Ve()||Ae()||U()&&(Oe()||!Le())||!Pe())}function Ve(){return d!=null&&x>=d}function Ae(){return g!=null&&v.now()-w>=g}function Oe(){if(!U())throw new Error("Unexpected behavior");return c!=null&&c<=0}function Le(){if(!U())throw new Error("Unexpected behavior");for(let a=0,u=f.length;a<u;a++)if(_(f[a])&&X(a))return!0;return!1}function Pe(){for(let a=0,u=f.length;a<u;a++)if(X(a))return!0;return!1}function _e(){m++;const a=m>=f.length;return a&&(m=0),D(),a}function Ne(){if(U()){const a=$e();if(c!=null&&a>=c)return!1}return!0}function U(){for(let a=0,u=f.length;a<u;a++)if(B(f[a]))return!0;return!1}function $e(){let a=!1,u=1/0;for(let p=0,I=h.length;p<I;p++){const F=h[p],K=f[p];B(K)&&(a=!0,X(p)&&F.completedCount<u&&(u=F.completedCount))}if(!a)throw new Error("Unexpected behavior");return u}function X(a){const u=f[a],p=h[a];return u.limitTests!=null&&u.limitTests<=0||_(u)&&(u.cycles!=null&&u.cycles<=0||u.attemptsPerVariant!=null&&u.attemptsPerVariant<=0)?!1:p.tryNextVariantAttempts<2}function De(){m=0;for(let a=0,u=h.length;a<u;a++){const p=h[a];p.testsInLastTurn=0,p.startTime=null}}function Ge(){let a=0;for(;a<2;){if(!qe())return null;const u=Re();if(u!=null)return u;if(_(f[m])&&Be())return null;a++}return null}function qe(){const a=f[m];return!(ke()||Ue()||_(a)&&!Fe(m))}function ke(){const a=f[m],u=h[m];return a.limitTests!=null&&u.testsInLastTurn>=a.limitTests}function Ue(){const a=f[m],u=h[m];return a.limitTime!=null&&u.startTime!=null&&v.now()-u.startTime>=a.limitTime}function _(a){return B(a)}function Fe(a){const u=f[a],p=h[a];if(!_(u))throw new Error("Unexpected behavior");return p.cycleCount<(u.cycles??1)}function Be(){const a=f[m],u=h[m];if(!_(a))throw new Error("Unexpected behavior");return u.cycleCount++,u.cycleCount>=(a.cycles??1)?(u.cycleCount=0,u.completedCount++,!0):!1}function Re(){const a=f[m],u=h[m],p=u.navigationState;if(G(a)){if(Z())return null;const I=je();if(I!=null)return u.startTime==null&&(u.startTime=v.now()),I}return ze()?(u.tryNextVariantAttempts=0,G(a)&&We(),u.startTime==null&&(u.startTime=v.now()),ue(p.args)):(u.tryNextVariantAttempts++,null)}function je(){const a=f[m],p=h[m].navigationState;if(!G(a))throw new Error("Unexpected behavior");if(Z())throw new Error("Unexpected behavior");const I=a.attemptsPerVariant??1;return p.attempts>0&&p.attempts<I?L(p)?null:(p.attempts++,ue(p.args)):null}function We(){const a=f[m],p=h[m].navigationState;if(!G(a))throw new Error("Unexpected behavior");if(Z())throw new Error("Unexpected behavior");p.attempts=1}function G(a){return B(a)}function Z(){const a=f[m];if(!G(a))throw new Error("Unexpected behavior");return(a.attemptsPerVariant??1)<=0}function ze(){const a=f[m],p=h[m].navigationState;switch(a.mode){case"forward":return ve(p);case"backward":return ee(p);case"random":return ot(p);default:throw new Error(`Unknown mode: ${a.mode}`)}}function ue(a){const u={...a};return s!=null&&(u.seed=s({tests:x})),u}return{get limit(){return T},get modeIndex(){return m},get modeConfigs(){return f},get modeStates(){return h},get tests(){return x},calcIndexes:le,extendTemplates:Te,addLimit:we,next:Ie}}function se(e){if(e==null||e<=0)throw new Error(`Iterations = ${e}`);e--;const t=S.waitMicrotasks().then(()=>e);return e<=0?t:t.then(se)}function ct(e,t,r){const o=t.limit?{error:t.limit.error,args:t.limit.args,tests:t.limit.tests}:null;if(o&&!r)throw o.error;return{iterations:e.iterations,bestError:o}}const de=2**31;function ft(e){if(e==null)return{parallel:1,sequentialOnError:!1};if(typeof e=="boolean")return{parallel:e?de:1,sequentialOnError:!1};if(typeof e=="number")return{parallel:e>0?e:1,sequentialOnError:!1};const t=e.count;let r=1;return t===!0?r=de:typeof t=="number"&&t>0&&(r=t),{parallel:r,sequentialOnError:e.sequentialOnError??!1}}function mt(e){const t=e?.saveErrorVariants,r=t&&e.createSaveErrorVariantsStore?e.createSaveErrorVariantsStore(t):null,o=e?.findBestError,{parallel:i,sequentialOnError:s}=ft(e?.parallel);return{store:r,GC_Iterations:e?.GC_Iterations??1e6,GC_IterationsAsync:e?.GC_IterationsAsync??1e4,GC_Interval:e?.GC_Interval??1e3,logOptions:ye(e?.log),abortSignalExternal:e?.abortSignal,findBestError:o,dontThrowIfError:o?.dontThrowIfError,timeController:e?.timeController??q.timeControllerDefault,timeControllerInternal:e?.timeControllerInternal??q.timeControllerDefault,parallel:i,sequentialOnError:s}}function z(e,t,r){const{options:o,variantsIterator:i}=e,s=i.limit?.args??t;if(!o.store)return;const n=o.store.save(s);if(r)return n}function dt(e,t,r,o){const{abortControllerParallel:i,state:s,options:n}=e,{logOptions:l}=n;if(e.options.findBestError)e.variantsIterator.addLimit({args:t,error:r,tests:o}),s.debugMode=!1,z(e,t,!1),n.sequentialOnError&&!i.signal.aborted?(l.debug&&l.func("debug","[test-variants] sequentialOnError: aborting parallel, switching to sequential"),i.abort(new V)):l.debug&&l.func("debug","[test-variants] parallel error in findBestError mode, continuing with new limits");else{if(i.signal.aborted)return;z(e,t,!1),i.abort(r)}}function ge(e,t,r,o){const{state:i}=e;if(e.options.findBestError){e.variantsIterator.addLimit({args:t,error:r,tests:o});const n=z(e,t,!0);if(n)return n.then(()=>{i.debugMode=!1});i.debugMode=!1;return}const s=z(e,t,!0);if(s)return s.then(()=>{throw r});throw r}function gt(e,t){const{GC_Iterations:r,GC_IterationsAsync:o,GC_Interval:i}=e.options;return r>0&&e.state.iterations-e.state.prevGcIterations>=r||o>0&&e.state.iterationsAsync-e.state.prevGcIterationsAsync>=o||i>0&&t-e.state.prevGcTime>=i}async function pt(e,t){e.prevGcIterations=e.iterations,e.prevGcIterationsAsync=e.iterationsAsync,e.prevGcTime=t,await se(1)}function te(e){const t=e/1e3;if(t<.1)return`${t.toFixed(3)}s`;if(t<1)return`${t.toFixed(2)}s`;if(t<10)return`${t.toFixed(1)}s`;if(t<60)return`${t.toFixed(0)}s`;const r=t/60;if(r<10)return`${r.toFixed(1)}m`;if(r<60)return`${r.toFixed(0)}m`;const o=r/60;return o<10?`${o.toFixed(1)}h`:`${o.toFixed(0)}h`}function H(e){const t=e/1073741824;if(t>=1)return t>=10?`${Math.round(t)}GB`:`${t.toFixed(1)}GB`;const r=e/(1024*1024);return r>=10?`${Math.round(r)}MB`:`${r.toFixed(1)}MB`}function ht(e,t){const r=e-t,o=r>=0?"+":"";return`${H(e)} (${o}${H(r)})`}function ae(e,t,r,o,i){let s=`tests: ${e} (${te(t)}), maxTime: ${te(r)}, async: ${o}`,n=null;return i!=null&&(n=oe(),n!=null&&(s+=`, memory: ${ht(n,i)}`)),{message:s,memory:n}}function bt(e,t){if(!e)return`mode[${t}]: null`;let r=`mode[${t}]: ${e.mode}`;return(e.mode==="forward"||e.mode==="backward")&&(e.cycles!=null&&(r+=`, cycles=${e.cycles}`),e.attemptsPerVariant!=null&&(r+=`, attempts=${e.attemptsPerVariant}`)),e.limitTime!=null&&(r+=`, limitTime=${te(e.limitTime)}`),e.limitTests!=null&&(r+=`, limitTests=${e.limitTests}`),r}function yt(e,t){if(!e.start)return;let r="[test-variants] start";t!=null&&(r+=`, memory: ${H(t)}`),e.func("start",r)}function vt(e){const{options:t,state:r}=e,{logOptions:o,timeControllerInternal:i}=t;if(!o.completed)return;const s=i.now()-r.startTime,n=ae(r.tests,s,r.maxTestDuration,r.iterationsAsync,r.startMemory);o.func("completed",`[test-variants] end, ${n.message}`)}function xe(e){const{options:t,state:r}=e,{logOptions:o}=t,i=r.pendingModeChange;!o.modeChange||i==null||(o.func("modeChange",`[test-variants] ${bt(i.mode,i.modeIndex)}`),r.pendingModeChange=null)}function xt(e){const{options:t,state:r}=e,{logOptions:o,timeControllerInternal:i}=t,s=i.now();if(!o.progress||s-r.prevLogTime<o.progress)return!1;xe(e);const n=s-r.startTime,l=ae(r.tests,n,r.maxTestDuration,r.iterationsAsync,r.prevLogMemory);return l.memory!=null&&(r.prevLogMemory=l.memory),o.func("progress",`[test-variants] ${l.message}`),r.prevLogTime=s,!0}function re(e,t){e.debugMode=!1,t&&(e.iterationsAsync+=t.iterationsAsync,e.iterations+=t.iterationsSync+t.iterationsAsync)}function ne(e){e.state.debugMode=!0,e.abortControllerParallel.abort(new V)}function Se(e,t){const{testRun:r,testOptions:o,state:i}=e,s=i.tests;i.tests++;try{const n=r(t,s,o);if(S.isPromiseLike(n))return n.then(l=>{if(!l){ne(e);return}re(i,l)},l=>ge(e,t,l,s));if(!n){ne(e);return}re(i,n)}catch(n){return n instanceof V?void 0:ge(e,t,n,s)}}function St(e,t){const{pool:r,abortSignal:o,testRun:i,testOptionsParallel:s,state:n}=e;if(!r)return;const l=n.tests;n.tests++,(async()=>{try{if(o.aborted)return;let c=i(t,l,s);if(S.isPromiseLike(c)&&(c=await c),!c){ne(e);return}re(n,c)}catch(c){if(c instanceof V)return;dt(e,t,c,l)}finally{r.release(1)}})()}function Ee(e){const{options:t,state:r}=e,{logOptions:o,timeControllerInternal:i,GC_Interval:s}=t;if(!o.progress&&!s)return;xt(e);const n=i.now();if(gt(e,n))return pt(r,n)}function J(e){return e.options.abortSignalExternal?.aborted??!1}function ie(e){return e.abortSignal.aborted}async function Q(e,t){const{pool:r,state:o,options:i}=e,{parallel:s,logOptions:n}=i;let l=null;for(;!J(e);){const c=r&&!ie(e);let d=!1;c&&(r.hold(1)||await Y.poolWait({pool:r,count:1,hold:!0}),d=!0);try{if(t!=null?(l=t,t=null):e.state.debugMode||(l=e.variantsIterator.next()),l==null)break;const g=Ee(e);if(S.isPromiseLike(g)&&await g,J(e))continue;if(c)St(e,l),d=!1;else{n.debug&&r&&ie(e)&&n.func("debug",`[test-variants] parallel aborted, running sequential: tests=${o.tests}`);const v=Se(e,l);S.isPromiseLike(v)&&await v}}finally{d&&r.release(1)}}r&&(await Y.poolWait({pool:r,count:s,hold:!0}),r.release(s))}function Et(e){const{pool:t,state:r,options:o}=e,{logOptions:i}=o;if(t)return Q(e);let s=null;for(;!J(e)&&(e.state.debugMode||(s=e.variantsIterator.next()),s!=null);){const n=Ee(e);if(S.isPromiseLike(n))return n.then(()=>Q(e,s));if(J(e))continue;i.debug&&ie(e)&&i.func("debug",`[test-variants] parallel aborted, running sequential: tests=${r.tests}`);const l=Se(e,s);if(S.isPromiseLike(l))return l.then(()=>Q(e))}}async function Tt(e,t,r,o){const i=mt(o),{store:s,logOptions:n,abortSignalExternal:l,findBestError:c,dontThrowIfError:d,timeController:g,timeControllerInternal:v,parallel:b}=i,f=new j.AbortControllerFast,h=new j.AbortControllerFast,E=S.combineAbortSignals(l,f.signal),T=S.combineAbortSignals(E,h.signal),m={abortSignal:E,timeController:g},x={abortSignal:T,timeController:g};s&&await s.replay({testRun:e,variantsIterator:t,testOptions:m,findBestErrorEnabled:!!c,state:r,logOptions:n,timeControllerInternal:v});const A=b<=1?null:new Y.Pool(b);yt(n,r.startMemory);const w={options:i,testRun:e,variantsIterator:t,testOptions:m,testOptionsParallel:x,abortControllerGlobal:f,abortControllerParallel:h,abortSignal:T,pool:A,state:r};xe(w);try{await Et(w),T.throwIfAborted()}catch(y){throw f.abort(new V),y}return E.throwIfAborted(),f.abort(new V),vt(w),await se(1),ct(r,t,d)}function wt(e){return function(r){return async function(i){const s=ye(i?.log),n=i?.timeControllerInternal??q.timeControllerDefault,l=oe(),c=Qe(n,l),d=nt(e,{onStart:i?.onStart,onEnd:i?.onEnd,onError:i?.onError,log:s,pauseDebuggerOnError:i?.pauseDebuggerOnError,timeout:i?.timeout,state:c}),g=i?.onModeChange;function v(f){c.pendingModeChange=f,g?.(f)}const b=ut({argsTemplates:r,getSeed:i?.getSeed,iterationModes:i?.iterationModes,equals:i?.findBestError?.equals,limitArgOnError:i?.findBestError?.limitArgOnError,includeErrorVariant:i?.findBestError?.includeErrorVariant,timeControllerInternal:n,onModeChange:v,limitCompletionCount:i?.cycles??1,limitTests:i?.limitTests,limitTime:i?.limitTime});return Tt(d,b,c,i)}}}exports.TimeoutError=pe;exports.createTestVariants=wt;exports.formatBytes=H;exports.formatTestStats=ae;exports.getMemoryUsage=oe;