@flemist/test-variants 5.0.11 → 5.0.13
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 +21 -0
- package/build/browser/index.cjs +1 -1
- package/build/browser/index.mjs +3 -2
- package/build/common/index.cjs +1 -1
- package/build/common/index.mjs +3 -2
- package/build/common/test-variants/NowObservable.d.ts +13 -0
- package/build/common/test-variants/run/types.d.ts +7 -3
- package/build/common/test-variants/types.d.ts +27 -0
- package/build/createTestVariants-B34VFl9m.js +4 -0
- package/build/createTestVariants-Bbto3Xye.mjs +1103 -0
- package/build/node/index.cjs +1 -1
- package/build/node/index.mjs +1 -1
- package/package.json +2 -2
- package/build/createTestVariants-6NbYYHA7.js +0 -4
- package/build/createTestVariants-DHWt92RI.mjs +0 -1033
package/README.md
CHANGED
|
@@ -235,6 +235,22 @@ const result = await testVariants({
|
|
|
235
235
|
extendTemplates: boolean, // default: false
|
|
236
236
|
},
|
|
237
237
|
|
|
238
|
+
// Called before each single test run
|
|
239
|
+
onStart: ({
|
|
240
|
+
args, // test parameters of the variant about to run (includes seed if getSeed is set)
|
|
241
|
+
tests, // index of this test run; equals total tests run before this one (including attemptsPerVariant)
|
|
242
|
+
}) => void | Promise<void>,
|
|
243
|
+
|
|
244
|
+
// Called after each single test run, on both success and error
|
|
245
|
+
// On success: result is set, error is absent
|
|
246
|
+
// On error: error is set, result is absent
|
|
247
|
+
onEnd: ({
|
|
248
|
+
args, // test parameters of the variant that just ran (includes seed if getSeed is set)
|
|
249
|
+
tests, // index of this test run; same value as in the matching onStart event
|
|
250
|
+
result, // { iterationsSync, iterationsAsync } returned by the test; absent on error
|
|
251
|
+
error, // the error caught via try..catch; absent on success
|
|
252
|
+
}) => void | Promise<void>,
|
|
253
|
+
|
|
238
254
|
// Called when an error occurs in the test
|
|
239
255
|
// before logging and throwing exception
|
|
240
256
|
onError: ({
|
|
@@ -259,6 +275,11 @@ const result = await testVariants({
|
|
|
259
275
|
// Used inside testVariants instead of direct setTimeout, Date.now calls, etc
|
|
260
276
|
// Intended only for testing and debugging the test-variants library itself
|
|
261
277
|
timeController: ITimeController, // default: null - use timeControllerDefault
|
|
278
|
+
|
|
279
|
+
// Maximum duration for a single test run (milliseconds)
|
|
280
|
+
// Throws TimeoutError if exceeded
|
|
281
|
+
// Function form returns timeout per variant; null/undefined disables for that variant
|
|
282
|
+
timeout: number | ((args: Args) => number | null | undefined), // default: null - no timeout
|
|
262
283
|
})
|
|
263
284
|
|
|
264
285
|
// Result:
|
package/build/browser/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../createTestVariants-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../createTestVariants-B34VFl9m.js");exports.TimeoutError=e.TimeoutError;exports.createTestVariants=e.createTestVariants;
|
package/build/browser/index.mjs
CHANGED
package/build/common/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../createTestVariants-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../createTestVariants-B34VFl9m.js");exports.TimeoutError=e.TimeoutError;exports.createTestVariants=e.createTestVariants;
|
package/build/common/index.mjs
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IObservable } from '@flemist/simple-utils';
|
|
2
|
+
import { ITimeController } from '@flemist/time-controller';
|
|
3
|
+
export declare class NowObservable implements IObservable<number> {
|
|
4
|
+
private readonly _timeController;
|
|
5
|
+
private readonly _subject;
|
|
6
|
+
private _interval;
|
|
7
|
+
private _timer;
|
|
8
|
+
constructor(interval: number, timeController?: null | ITimeController);
|
|
9
|
+
private update;
|
|
10
|
+
get interval(): number;
|
|
11
|
+
set interval(value: number);
|
|
12
|
+
subscribe(callback: (value: number) => void): () => void;
|
|
13
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { PromiseOrValue } from '@flemist/async-utils';
|
|
2
2
|
import { Obj, RequiredNonNullable } from '@flemist/simple-utils';
|
|
3
3
|
import { TestVariantsTemplatesExt, VariantsIterator } from '../iterator/types';
|
|
4
|
-
import { ArgsWithSeed, OnErrorCallback, SaveErrorVariantsOptions, TestVariantsState, TestVariantsLogOptions, TestVariantsResult, TestVariantsRunOptions } from '../types';
|
|
4
|
+
import { ArgsWithSeed, OnErrorCallback, OnTestEndCallback, OnTestStartCallback, SaveErrorVariantsOptions, TestVariantsState, TestVariantsLogOptions, TestVariantsResult, TestVariantsRunOptions } from '../types';
|
|
5
5
|
/** Result of test run (internal format with separate sync/async counts) */
|
|
6
|
-
export type TestFuncResult =
|
|
6
|
+
export type TestFuncResult = {
|
|
7
7
|
iterationsAsync: number;
|
|
8
8
|
iterationsSync: number;
|
|
9
9
|
};
|
|
10
10
|
/** Test run function (internal - wraps user's test with error handling) */
|
|
11
|
-
export type TestVariantsTestRun<Args extends Obj> = (args: ArgsWithSeed<Args>, tests: number, options: TestVariantsState) => PromiseOrValue<TestFuncResult>;
|
|
11
|
+
export type TestVariantsTestRun<Args extends Obj> = (args: ArgsWithSeed<Args>, tests: number, options: TestVariantsState) => PromiseOrValue<void | TestFuncResult>;
|
|
12
12
|
/** Result of user's test function (number treated as iterationsSync) */
|
|
13
13
|
export type TestVariantsTestResult = number | void | TestFuncResult;
|
|
14
14
|
/** User's test function */
|
|
@@ -49,11 +49,15 @@ export type TestVariantsRunOptionsInternal<Args extends Obj = Obj, SavedArgs = A
|
|
|
49
49
|
createSaveErrorVariantsStore?: null | CreateSaveErrorVariantsStore<Args, SavedArgs>;
|
|
50
50
|
};
|
|
51
51
|
export type TestVariantsCreateTestRunOptions<Args extends Obj> = {
|
|
52
|
+
onStart?: null | OnTestStartCallback<Args>;
|
|
53
|
+
onEnd?: null | OnTestEndCallback<Args>;
|
|
52
54
|
onError?: null | OnErrorCallback<Args>;
|
|
53
55
|
/** Resolved logging options */
|
|
54
56
|
log: RequiredNonNullable<TestVariantsLogOptions>;
|
|
55
57
|
/** Pause debugger on error */
|
|
56
58
|
pauseDebuggerOnError?: null | boolean;
|
|
59
|
+
/** Throws TimeoutError if single test run exceeds this timeout. Minimum is 100ms */
|
|
60
|
+
timeout?: null | number | ((args: Args) => number | null | undefined);
|
|
57
61
|
};
|
|
58
62
|
export type TestVariantsCall<Args extends Obj> = <SavedArgs = Args>(options?: null | TestVariantsRunOptionsInternal<Args, SavedArgs>) => PromiseOrValue<TestVariantsResult<Args>>;
|
|
59
63
|
export type TestVariantsSetArgs<Args extends Obj> = <ArgsExtra extends Obj>(args: TestVariantsTemplatesExt<Omit<Args, 'seed'>, ArgsExtra>) => TestVariantsCall<Args>;
|
|
@@ -2,6 +2,7 @@ import { IAbortSignalFast } from '@flemist/abort-controller-fast';
|
|
|
2
2
|
import { PromiseOrValue } from '@flemist/async-utils';
|
|
3
3
|
import { Obj } from '@flemist/simple-utils';
|
|
4
4
|
import { ITimeController } from '@flemist/time-controller';
|
|
5
|
+
import { TestFuncResult } from './run/types';
|
|
5
6
|
export type { TestVariantsTemplatesExt } from './iterator/types';
|
|
6
7
|
export type { TestVariantsCall, TestVariantsSetArgs, TestVariantsTestResult, } from './run/types';
|
|
7
8
|
export type Equals = (a: any, b: any) => boolean;
|
|
@@ -139,6 +140,24 @@ export type ErrorEvent<Args extends Obj> = {
|
|
|
139
140
|
};
|
|
140
141
|
/** Callback invoked when a test variant throws an error */
|
|
141
142
|
export type OnErrorCallback<Args extends Obj> = (event: ErrorEvent<Args>) => PromiseOrValue<void>;
|
|
143
|
+
/** Test start event passed to onStart callback */
|
|
144
|
+
export type TestStartEvent<Args extends Obj> = {
|
|
145
|
+
/** Args of the variant about to run (including seed if getSeed provided) */
|
|
146
|
+
args: Args;
|
|
147
|
+
/** Index of this test run; equals total tests run before this one (including attemptsPerVariant) */
|
|
148
|
+
tests: number;
|
|
149
|
+
};
|
|
150
|
+
/** Callback invoked before each single test run */
|
|
151
|
+
export type OnTestStartCallback<Args extends Obj> = (event: TestStartEvent<Args>) => PromiseOrValue<void>;
|
|
152
|
+
/** Test end event passed to onEnd callback */
|
|
153
|
+
export type TestEndEvent<Args extends Obj> = TestStartEvent<Args> & {
|
|
154
|
+
/** Iteration counts returned by the test; absent when the test threw */
|
|
155
|
+
result?: TestFuncResult;
|
|
156
|
+
/** Error thrown by the test; absent on success */
|
|
157
|
+
error?: any;
|
|
158
|
+
};
|
|
159
|
+
/** Callback invoked after each single test run, on both success and error */
|
|
160
|
+
export type OnTestEndCallback<Args extends Obj> = (event: TestEndEvent<Args>) => PromiseOrValue<void>;
|
|
142
161
|
/** Mode change event passed to onModeChange callback */
|
|
143
162
|
export type ModeChangeEvent = {
|
|
144
163
|
/** Current mode configuration */
|
|
@@ -158,6 +177,10 @@ export type ParallelOptions = {
|
|
|
158
177
|
sequentialOnError?: null | boolean;
|
|
159
178
|
};
|
|
160
179
|
export type TestVariantsRunOptions<Args extends Obj = Obj, SavedArgs = Args> = {
|
|
180
|
+
/** Callback invoked before each single test run */
|
|
181
|
+
onStart?: null | OnTestStartCallback<Args>;
|
|
182
|
+
/** Callback invoked after each single test run, on both success and error */
|
|
183
|
+
onEnd?: null | OnTestEndCallback<Args>;
|
|
161
184
|
/** Callback invoked when a test variant throws an error */
|
|
162
185
|
onError?: null | OnErrorCallback<Args>;
|
|
163
186
|
/** Callback invoked when iteration mode changes */
|
|
@@ -190,4 +213,8 @@ export type TestVariantsRunOptions<Args extends Obj = Obj, SavedArgs = Args> = {
|
|
|
190
213
|
limitTime?: null | number;
|
|
191
214
|
/** Time controller for testable time-dependent operations; null uses timeControllerDefault */
|
|
192
215
|
timeController?: null | ITimeController;
|
|
216
|
+
/** Throws TimeoutError if single test run exceeds this timeout. Minimum is 100ms */
|
|
217
|
+
timeout?: null | number | ((args: Args) => number | null | undefined);
|
|
193
218
|
};
|
|
219
|
+
export declare class TimeoutError extends Error {
|
|
220
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";const W=require("@flemist/time-controller"),z=require("@flemist/simple-utils"),E=require("@flemist/async-utils"),B=require("@flemist/abort-controller-fast"),K=require("@flemist/time-limits");class ge extends Error{}function ne(){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 Je=1e3,U=[];function Xe(e){return z.formatAny(e,{pretty:!0,maxDepth:5,maxItems:50})}function Ze(...e){const r=e.map(t=>typeof t=="string"?t:Xe(t)).join(" ");U.push(r),U.length>Je&&U.shift(),console.log(r)}function Ke(){return U.join(`
|
|
2
|
+
`)}globalThis.__getStressTestLogLast=Ke;const pe=(e,r)=>{Ze(r)},he=e=>z.formatAny(e,{pretty:!0,maxDepth:20,maxItems:100,maxStringLength:5e3,dontExpandClassInstances:!0,dontExpandFunctions:!0}),C={start:!0,progress:5e3,completed:!0,error:!0,modeChange:!0,debug:!1,func:pe,format:he},Qe={start:!1,progress:!1,completed:!1,error:!1,modeChange:!1,debug:!1,func:pe,format:he};function be(e){return e===!1?Qe:e===!0||!e?C:{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 Ye(e,r){const t=e.now();return{startTime:t,startMemory:r,debugMode:!1,tests:0,iterations:0,iterationsAsync:0,prevLogTime:t,prevLogMemory:r,pendingModeChange:null,prevGcTime:t,prevGcIterations:0,prevGcIterationsAsync:0}}class V extends B.AbortError{}class et{_timeController;_subject;_interval;_timer;constructor(r,t){this._interval=r,this._timeController=t??W.timeControllerDefault,this._subject=new z.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(r){this._interval=r,this._timer&&(this._timeController.clearTimeout(this._timer),this.update())}subscribe(r){return this._subject.subscribe(r)}}const tt=50,rt=5;function nt(e,r){return e==null?null:typeof e=="number"?e:e(r)??null}function ue(e,r){return typeof e=="number"?{iterationsAsync:0,iterationsSync:e}:e!=null&&typeof e=="object"?e:r?{iterationsAsync:1,iterationsSync:0}:{iterationsAsync:0,iterationsSync:1}}function it(e,r){const t=r.log,o=r.pauseDebuggerOnError??!0,i=r.onStart,s=r.onEnd;let n=null,a=0;function c(m,h,y){n==null&&(n={error:m,args:h,tests:y},t.error&&t.func("error",`[test-variants] error variant: ${t.format(h)}
|
|
3
|
+
tests: ${y}
|
|
4
|
+
${t.format(m)}`));const d=Date.now();if(o)debugger;if(Date.now()-d>tt&&a<rt){t.func("debug",`[test-variants] debug iteration: ${a}`),a++;return}const v=n;throw n=null,r.onError&&r.onError(v),v.error}const g=new et(100);return function(h,y,d){i&&i({args:h,tests:y});const b=nt(r.timeout,h);let v=null,M=d,f=null;b&&(v=Date.now(),f=new B.AbortControllerFast,M={abortSignal:E.combineAbortSignals(d.abortSignal,f.signal),timeController:d.timeController});function w(){f.abort(new ge(`[test-variants] test timeout ${b}ms exceeded`))}try{let S=e(h,M);if(E.isPromiseLike(S)){let T=null;return f&&(T=g.subscribe(()=>{Date.now()-v>=b&&(w(),T())}),S=Promise.race([S,E.abortSignalToPromise(f.signal)])),S.then(O=>{T?.();const G=ue(O,!0);return s&&s({args:h,tests:y,result:G}),G},O=>(T?.(),s&&!(O instanceof V)&&s({args:h,tests:y,error:O}),c(O,h,y)))}v!=null&&Date.now()-v>=b&&(w(),f.signal.throwIfAborted());const A=ue(S,!1);return s&&s({args:h,tests:y,result:A}),A}catch(S){return S instanceof V?void 0:(s&&s({args:h,tests:y,error:S}),c(S,h,y))}}}function R(e,r,t){for(let o=0,i=e.length;o<i;o++)if(t?t(e[o],r):e[o]===r)return o;return-1}function ce(e,r,t,o){const i=Object.keys(e.templates),s={},n=[],a=[],c=[],g=i.length;for(let m=0;m<g;m++){const h=i[m];s[h]=void 0,n.push(-1),a.push(void 0),c.push(null)}return{args:s,argsNames:i,indexes:n,argValues:a,argLimits:c,attempts:0,templates:e,limitArgOnError:t,equals:r,includeErrorVariant:o??!1}}function N(e,r){const t=e.templates.templates[r],o=e.templates.extra[r];let i;if(typeof t=="function"?i=t(e.args):i=t,o==null)return i;let s=null;const n=o.length;for(let a=0;a<n;a++){const c=o[a];R(i,c,e.equals)<0&&(s==null?s=[...i,c]:s.push(c))}return s??i}function I(e,r,t){const o=e.argValues[r].length;if(o===0)return-1;const i=e.argLimits[r];if(i==null)return o-1;let s=e.limitArgOnError;if(typeof s=="function"){const n=e.argsNames[r];s=s({name:n,values:e.argValues[r],maxValueIndex:i})}return!t||s?Math.min(i,o-1):o-1}function L(e){const r=e.indexes.length;for(let t=0;t<r;t++){const o=e.argLimits[t];if(o==null)return!1;const i=e.indexes[t];if(i>o)return!0;if(i<o)return!1}return!e.includeErrorVariant}function _(e){const r=e.indexes.length;for(let t=0;t<r;t++)e.indexes[t]=-1,e.argValues[t]=void 0,e.args[e.argsNames[t]]=void 0}function ye(e){let r=!1,t=!0;const o=e.indexes.length;let i=o,s=!1,n=0;for(;n<o;n++){const a=e.argValues[n]==null;(a||s)&&(a&&(r=!0),e.argValues[n]=N(e,e.argsNames[n]));const c=I(e,n,n>i);if(c<0){t=!1,e.indexes[n]=-1;break}a&&(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 _(e),!1;if(r&&t)return!0;for(n--;n>=0;n--){if(e.argValues[n]==null)continue;let a=n>i;const c=I(e,n,a),g=e.indexes[n]+1;if(g<=c){e.indexes[n]=g,e.args[e.argsNames[n]]=e.argValues[n][g],g<c&&(a=!0);for(let m=n+1;m<o;m++)e.args[e.argsNames[m]]=void 0;for(n++;n<o;n++){e.argValues[n]=N(e,e.argsNames[n]);const m=I(e,n,a);if(m<0)break;e.indexes[n]=0,e.args[e.argsNames[n]]=e.argValues[n][0],m>0&&(a=!0)}if(n>=o)return L(e)?(_(e),!1):!0}}return _(e),!1}function Q(e){L(e)&&_(e);let r=!1,t=!0;const o=e.indexes.length;let i=o,s=!1,n=0;for(;n<o;n++){const a=e.argValues[n]==null;(a||s)&&(a&&(r=!0),e.argValues[n]=N(e,e.argsNames[n]));const c=I(e,n,n>i);if(c<0){t=!1,e.indexes[n]=-1;break}a&&(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((r||s)&&t&&!L(e))return!0;for(n--;n>=0;n--){if(e.argValues[n]==null)continue;let a=n>i;const c=I(e,n,a);let g=e.indexes[n]-1;if(g>c&&(g=c),g>=0){e.indexes[n]=g,e.args[e.argsNames[n]]=e.argValues[n][g],g<c&&(a=!0);for(let m=n+1;m<o;m++)e.args[e.argsNames[m]]=void 0;for(n++;n<o;n++){e.argValues[n]=N(e,e.argsNames[n]);const m=I(e,n,a);if(m<0)break;e.indexes[n]=m,e.args[e.argsNames[n]]=e.argValues[n][m],m>0&&(a=!0)}if(n>=o)return!0}}return _(e),!1}function ot(e,r){_(e);const t=e.argsNames,o=t.length;let i=!1;for(let s=0;s<o;s++){const n=t[s],a=r[n];if(a===void 0)return null;e.argValues[s]=N(e,n);const c=I(e,s,i);if(c<0)return null;const g=R(e.argValues[s],a,e.equals);if(g<0||g>c)return null;e.indexes[s]=g,e.args[e.argsNames[s]]=e.argValues[s][g],e.indexes[s]<c&&(i=!0)}return L(e)?null:e.indexes.slice()}function st(e){const r=e.indexes.length;if(r===0)return!1;let t=!1;for(let o=0;o<r;o++){e.argValues[o]=N(e,e.argsNames[o]);const i=I(e,o,t);if(i<0)return Math.random()<.5?ye(e):Q(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&&(t=!0)}return L(e)?Q(e):!0}function k(e){return e.mode==="forward"||e.mode==="backward"}function lt(e,r,t,o){const i=r[t],s=e.templates[t];if(typeof s!="function"){if(R(s,i,o)>=0)return;s.push(i);return}const n=e.extra[t];if(n==null){e.extra[t]=[i];return}R(n,i,o)>=0||n.push(i)}function at(e,r,t){for(const o in r)if(Object.prototype.hasOwnProperty.call(r,o)){if(o==="seed")continue;lt(e,r,o,t)}}function fe(e,r){for(const t in r)if(Object.prototype.hasOwnProperty.call(r,t)){if(t==="seed")continue;if(!e[t])return!1}return!0}const ut=[{mode:"forward"}];function ct(e){const{argsTemplates:r,equals:t,limitArgOnError:o,includeErrorVariant:i,getSeed:s,iterationModes:n,onModeChange:a,limitCompletionCount:c,limitTests:g,limitTime:m}=e,h=e.timeController??W.timeControllerDefault,y={templates:z.deepCloneJsonLike(r),extra:{}},d=n==null||n.length===0?ut:n,b=[];let v=null,M=null,f=0,w=0,S=!1,A=0;function T(){S||(S=!0,A=h.now(),O(),f=0,se(),xe())}function O(){for(let l=0,u=d.length;l<u;l++)b.push(G())}function G(){return{navigationState:ce(y,t??null,o??null,i??null),cycleCount:0,completedCount:0,testsInLastTurn:0,tryNextVariantAttempts:0,startTime:null}}function xe(){v=ce(y,t??null,!1,!1)}function se(){a?.({mode:d[f],modeIndex:f,tests:w})}function Te(l){T(),fe(y.templates,l)&&at(y,l,t)}function le(l,u){return T(),fe(y.templates,l)?(v.limitArgOnError=u?.limitArg??o??null,v.includeErrorVariant=u?.includeLimit??i??!1,ot(v,l)):null}function Ce(l){const u=l?.args;if(u==null)return;T();const p=le(u);if(p!=null){M={args:u,error:l?.error,tests:l?.tests??w},v.argLimits=p;for(let x=0,q=b.length;x<q;x++){const X=b[x].navigationState;X.argLimits=p}}}function Me(){return T(),Ie()}function Ie(){for(;;){if(!Ve())return null;for(;;){const l=qe();if(l!=null)return b[f].testsInLastTurn++,w++,l;if(Ne()){if(!$e())return null;De();break}}}}function Ve(){return!(Ae()||Oe()||D()&&(Le()||!Pe())||!_e())}function Ae(){return g!=null&&w>=g}function Oe(){return m!=null&&h.now()-A>=m}function Le(){if(!D())throw new Error("Unexpected behavior");return c!=null&&c<=0}function Pe(){if(!D())throw new Error("Unexpected behavior");for(let l=0,u=d.length;l<u;l++)if(P(d[l])&&H(l))return!0;return!1}function _e(){for(let l=0,u=d.length;l<u;l++)if(H(l))return!0;return!1}function Ne(){f++;const l=f>=d.length;return l&&(f=0),se(),l}function $e(){if(D()){const l=Ge();if(c!=null&&l>=c)return!1}return!0}function D(){for(let l=0,u=d.length;l<u;l++)if(k(d[l]))return!0;return!1}function Ge(){let l=!1,u=1/0;for(let p=0,x=b.length;p<x;p++){const q=b[p],X=d[p];k(X)&&(l=!0,H(p)&&q.completedCount<u&&(u=q.completedCount))}if(!l)throw new Error("Unexpected behavior");return u}function H(l){const u=d[l],p=b[l];return u.limitTests!=null&&u.limitTests<=0||P(u)&&(u.cycles!=null&&u.cycles<=0||u.attemptsPerVariant!=null&&u.attemptsPerVariant<=0)?!1:p.tryNextVariantAttempts<2}function De(){f=0;for(let l=0,u=b.length;l<u;l++){const p=b[l];p.testsInLastTurn=0,p.startTime=null}}function qe(){let l=0;for(;l<2;){if(!ke())return null;const u=je();if(u!=null)return u;if(P(d[f])&&Fe())return null;l++}return null}function ke(){const l=d[f];return!(Ue()||Be()||P(l)&&!Re(f))}function Ue(){const l=d[f],u=b[f];return l.limitTests!=null&&u.testsInLastTurn>=l.limitTests}function Be(){const l=d[f],u=b[f];return l.limitTime!=null&&u.startTime!=null&&h.now()-u.startTime>=l.limitTime}function P(l){return k(l)}function Re(l){const u=d[l],p=b[l];if(!P(u))throw new Error("Unexpected behavior");return p.cycleCount<(u.cycles??1)}function Fe(){const l=d[f],u=b[f];if(!P(l))throw new Error("Unexpected behavior");return u.cycleCount++,u.cycleCount>=(l.cycles??1)?(u.cycleCount=0,u.completedCount++,!0):!1}function je(){const l=d[f],u=b[f],p=u.navigationState;if($(l)){if(J())return null;const x=We();if(x!=null)return u.startTime==null&&(u.startTime=h.now()),x}return He()?(u.tryNextVariantAttempts=0,$(l)&&ze(),u.startTime==null&&(u.startTime=h.now()),ae(p.args)):(u.tryNextVariantAttempts++,null)}function We(){const l=d[f],p=b[f].navigationState;if(!$(l))throw new Error("Unexpected behavior");if(J())throw new Error("Unexpected behavior");const x=l.attemptsPerVariant??1;return p.attempts>0&&p.attempts<x?L(p)?null:(p.attempts++,ae(p.args)):null}function ze(){const l=d[f],p=b[f].navigationState;if(!$(l))throw new Error("Unexpected behavior");if(J())throw new Error("Unexpected behavior");p.attempts=1}function $(l){return k(l)}function J(){const l=d[f];if(!$(l))throw new Error("Unexpected behavior");return(l.attemptsPerVariant??1)<=0}function He(){const l=d[f],p=b[f].navigationState;switch(l.mode){case"forward":return ye(p);case"backward":return Q(p);case"random":return st(p);default:throw new Error(`Unknown mode: ${l.mode}`)}}function ae(l){const u={...l};return s!=null&&(u.seed=s({tests:w})),u}return{get limit(){return M},get modeIndex(){return f},get modeConfigs(){return d},get modeStates(){return b},get tests(){return w},calcIndexes:le,extendTemplates:Te,addLimit:Ce,next:Me}}function ie(e){if(e==null||e<=0)throw new Error(`Iterations = ${e}`);e--;const r=E.waitMicrotasks().then(()=>e);return e<=0?r:r.then(ie)}function ft(e,r,t){const o=r.limit?{error:r.limit.error,args:r.limit.args,tests:r.limit.tests}:null;if(o&&!t)throw o.error;return{iterations:e.iterations,bestError:o}}const me=2**31;function mt(e){if(e==null)return{parallel:1,sequentialOnError:!1};if(typeof e=="boolean")return{parallel:e?me:1,sequentialOnError:!1};if(typeof e=="number")return{parallel:e>0?e:1,sequentialOnError:!1};const r=e.count;let t=1;return r===!0?t=me:typeof r=="number"&&r>0&&(t=r),{parallel:t,sequentialOnError:e.sequentialOnError??!1}}function dt(e){const r=e?.saveErrorVariants,t=r&&e.createSaveErrorVariantsStore?e.createSaveErrorVariantsStore(r):null,o=e?.findBestError,{parallel:i,sequentialOnError:s}=mt(e?.parallel);return{store:t,GC_Iterations:e?.GC_Iterations??1e6,GC_IterationsAsync:e?.GC_IterationsAsync??1e4,GC_Interval:e?.GC_Interval??1e3,logOptions:be(e?.log),abortSignalExternal:e?.abortSignal,findBestError:o,dontThrowIfError:o?.dontThrowIfError,timeController:e?.timeController??W.timeControllerDefault,parallel:i,sequentialOnError:s}}function F(e,r,t){const{options:o,variantsIterator:i}=e,s=i.limit?.args??r;if(!o.store)return;const n=o.store.save(s);if(t)return n}function gt(e,r,t,o){const{abortControllerParallel:i,state:s,options:n}=e,{logOptions:a}=n;if(e.options.findBestError)e.variantsIterator.addLimit({args:r,error:t,tests:o}),s.debugMode=!1,F(e,r,!1),n.sequentialOnError&&!i.signal.aborted?(a.debug&&a.func("debug","[test-variants] sequentialOnError: aborting parallel, switching to sequential"),i.abort(new V)):a.debug&&a.func("debug","[test-variants] parallel error in findBestError mode, continuing with new limits");else{if(i.signal.aborted)return;F(e,r,!1),i.abort(t)}}function de(e,r,t,o){const{state:i}=e;if(e.options.findBestError){e.variantsIterator.addLimit({args:r,error:t,tests:o});const n=F(e,r,!0);if(n)return n.then(()=>{i.debugMode=!1});i.debugMode=!1;return}const s=F(e,r,!0);if(s)return s.then(()=>{throw t});throw t}function pt(e,r){const{GC_Iterations:t,GC_IterationsAsync:o,GC_Interval:i}=e.options;return t>0&&e.state.iterations-e.state.prevGcIterations>=t||o>0&&e.state.iterationsAsync-e.state.prevGcIterationsAsync>=o||i>0&&r-e.state.prevGcTime>=i}async function ht(e,r){e.prevGcIterations=e.iterations,e.prevGcIterationsAsync=e.iterationsAsync,e.prevGcTime=r,await ie(1)}function oe(e){const r=e/1e3;if(r<60)return`${r.toFixed(1)}s`;const t=r/60;return t<60?`${t.toFixed(1)}m`:`${(t/60).toFixed(1)}h`}function Y(e){const r=e/1073741824;if(r>=1)return r>=10?`${Math.round(r)}GB`:`${r.toFixed(1)}GB`;const t=e/(1024*1024);return t>=10?`${Math.round(t)}MB`:`${t.toFixed(1)}MB`}function bt(e,r){if(!e)return`mode[${r}]: null`;let t=`mode[${r}]: ${e.mode}`;return(e.mode==="forward"||e.mode==="backward")&&(e.cycles!=null&&(t+=`, cycles=${e.cycles}`),e.attemptsPerVariant!=null&&(t+=`, attempts=${e.attemptsPerVariant}`)),e.limitTime!=null&&(t+=`, limitTime=${oe(e.limitTime)}`),e.limitTests!=null&&(t+=`, limitTests=${e.limitTests}`),t}function ve(e,r){const t=e-r,o=t>=0?"+":"";return`${Y(e)} (${o}${Y(t)})`}function yt(e,r){if(!e.start)return;let t="[test-variants] start";r!=null&&(t+=`, memory: ${Y(r)}`),e.func("start",t)}function vt(e){const{options:r,state:t}=e,{logOptions:o,timeController:i}=r;if(!o.completed)return;const s=i.now()-t.startTime;let n=`[test-variants] end, tests: ${t.tests} (${oe(s)}), async: ${t.iterationsAsync}`;if(t.startMemory!=null){const a=ne();a!=null&&(n+=`, memory: ${ve(a,t.startMemory)}`)}o.func("completed",n)}function Se(e){const{options:r,state:t}=e,{logOptions:o}=r,i=t.pendingModeChange;!o.modeChange||i==null||(o.func("modeChange",`[test-variants] ${bt(i.mode,i.modeIndex)}`),t.pendingModeChange=null)}function St(e){const{options:r,state:t}=e,{logOptions:o,timeController:i}=r,s=i.now();if(!o.progress||s-t.prevLogTime<o.progress)return!1;Se(e);const n=s-t.startTime;let a=`[test-variants] tests: ${t.tests} (${oe(n)}), async: ${t.iterationsAsync}`;if(t.prevLogMemory!=null){const c=ne();c!=null&&(a+=`, memory: ${ve(c,t.prevLogMemory)}`,t.prevLogMemory=c)}return o.func("progress",a),t.prevLogTime=s,!0}function ee(e,r){e.debugMode=!1,r&&(e.iterationsAsync+=r.iterationsAsync,e.iterations+=r.iterationsSync+r.iterationsAsync)}function te(e){e.state.debugMode=!0,e.abortControllerParallel.abort(new V)}function Ee(e,r){const{testRun:t,testOptions:o,state:i}=e,s=i.tests;i.tests++;try{const n=t(r,s,o);if(E.isPromiseLike(n))return n.then(a=>{if(!a){te(e);return}ee(i,a)},a=>de(e,r,a,s));if(!n){te(e);return}ee(i,n)}catch(n){return n instanceof V?void 0:de(e,r,n,s)}}function Et(e,r){const{pool:t,abortSignal:o,testRun:i,testOptionsParallel:s,state:n}=e;if(!t)return;const a=n.tests;n.tests++,(async()=>{try{if(o.aborted)return;let c=i(r,a,s);if(E.isPromiseLike(c)&&(c=await c),!c){te(e);return}ee(n,c)}catch(c){if(c instanceof V)return;gt(e,r,c,a)}finally{t.release(1)}})()}function we(e){const{options:r,state:t}=e,{logOptions:o,timeController:i,GC_Interval:s}=r;if(!o.progress&&!s)return;St(e);const n=i.now();if(pt(e,n))return ht(t,n)}function j(e){return e.options.abortSignalExternal?.aborted??!1}function re(e){return e.abortSignal.aborted}async function Z(e,r){const{pool:t,state:o,options:i}=e,{parallel:s,logOptions:n}=i;let a=null;for(;!j(e);){const c=t&&!re(e);let g=!1;c&&(t.hold(1)||await K.poolWait({pool:t,count:1,hold:!0}),g=!0);try{if(r!=null?(a=r,r=null):e.state.debugMode||(a=e.variantsIterator.next()),a==null)break;const m=we(e);if(E.isPromiseLike(m)&&await m,j(e))continue;if(c)Et(e,a),g=!1;else{n.debug&&t&&re(e)&&n.func("debug",`[test-variants] parallel aborted, running sequential: tests=${o.tests}`);const h=Ee(e,a);E.isPromiseLike(h)&&await h}}finally{g&&t.release(1)}}t&&(await K.poolWait({pool:t,count:s,hold:!0}),t.release(s))}function wt(e){const{pool:r,state:t,options:o}=e,{logOptions:i}=o;if(r)return Z(e);let s=null;for(;!j(e)&&(e.state.debugMode||(s=e.variantsIterator.next()),s!=null);){const n=we(e);if(E.isPromiseLike(n))return n.then(()=>Z(e,s));if(j(e))continue;i.debug&&re(e)&&i.func("debug",`[test-variants] parallel aborted, running sequential: tests=${t.tests}`);const a=Ee(e,s);if(E.isPromiseLike(a))return a.then(()=>Z(e))}}async function xt(e,r,t,o){const i=dt(o),{store:s,logOptions:n,abortSignalExternal:a,findBestError:c,dontThrowIfError:g,timeController:m,parallel:h}=i,y=new B.AbortControllerFast,d=new B.AbortControllerFast,b=E.combineAbortSignals(a,y.signal),v=E.combineAbortSignals(b,d.signal),M={abortSignal:b,timeController:m},f={abortSignal:v,timeController:m};s&&await s.replay({testRun:e,variantsIterator:r,testOptions:M,findBestErrorEnabled:!!c});const w=h<=1?null:new K.Pool(h);yt(n,t.startMemory);const S={options:i,testRun:e,variantsIterator:r,testOptions:M,testOptionsParallel:f,abortControllerGlobal:y,abortControllerParallel:d,abortSignal:v,pool:w,state:t};Se(S);try{await wt(S),v.throwIfAborted()}catch(A){throw y.abort(new V),A}return b.throwIfAborted(),y.abort(new V),vt(S),await ie(1),ft(t,r,g)}function Tt(e){return function(t){return async function(i){const s=be(i?.log),n=it(e,{onStart:i?.onStart,onEnd:i?.onEnd,onError:i?.onError,log:s,pauseDebuggerOnError:i?.pauseDebuggerOnError,timeout:i?.timeout}),a=i?.timeController??W.timeControllerDefault,c=ne(),g=Ye(a,c),m=i?.onModeChange;function h(d){g.pendingModeChange=d,m?.(d)}const y=ct({argsTemplates:t,getSeed:i?.getSeed,iterationModes:i?.iterationModes,equals:i?.findBestError?.equals,limitArgOnError:i?.findBestError?.limitArgOnError,includeErrorVariant:i?.findBestError?.includeErrorVariant,timeController:a,onModeChange:h,limitCompletionCount:i?.cycles??1,limitTests:i?.limitTests,limitTime:i?.limitTime});return xt(n,y,g,i)}}}exports.TimeoutError=ge;exports.createTestVariants=Tt;
|