@flemist/test-variants 5.0.14 → 5.0.15
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 +7 -3
- package/build/browser/index.cjs +1 -1
- package/build/browser/index.mjs +1 -1
- package/build/common/index.cjs +1 -1
- package/build/common/index.mjs +1 -1
- package/build/common/test-variants/run/createRunState.d.ts +2 -0
- package/build/common/test-variants/run/types.d.ts +6 -1
- package/build/common/test-variants/types.d.ts +3 -3
- package/build/createTestVariants-C2AcN9Rj.js +4 -0
- package/build/{createTestVariants-DGrAba6p.mjs → createTestVariants-MkSgLExA.mjs} +395 -391
- package/build/node/index.cjs +1 -1
- package/build/node/index.mjs +67 -59
- package/package.json +1 -1
- package/build/createTestVariants-DHZ0gEE2.js +0 -4
package/README.md
CHANGED
|
@@ -119,6 +119,9 @@ const result = await testVariants({
|
|
|
119
119
|
// Maximum total number of tests run (including attemptsPerVariant)
|
|
120
120
|
limitTests: number, // default: null - unlimited
|
|
121
121
|
// Maximum total runtime of testVariants
|
|
122
|
+
// Does not interrupt a running test, only prevents starting the next iteration
|
|
123
|
+
// Use timeout to interrupt individual tests
|
|
124
|
+
// Not applied during saveErrorVariants replay to ensure all previously failing variants are verified
|
|
122
125
|
limitTime: number, // default: null - unlimited, (milliseconds)
|
|
123
126
|
// Test terminates when min(completedCount) across sequential modes (forward/backward) >= cycles
|
|
124
127
|
// Random mode is excluded from this calculation - it is limited only by global limits
|
|
@@ -143,6 +146,7 @@ const result = await testVariants({
|
|
|
143
146
|
// maximum number of attempted full passes of all variants, before mode switch
|
|
144
147
|
cycles: number, // default: 1
|
|
145
148
|
// maximum runtime before mode switch
|
|
149
|
+
// does not interrupt a running test, only prevents starting the next iteration
|
|
146
150
|
limitTime: number, // default: null - unlimited, (milliseconds)
|
|
147
151
|
// maximum number of tests run before mode switch (including attemptsPerVariant)
|
|
148
152
|
limitTests: number, // default: null - unlimited
|
|
@@ -321,11 +325,11 @@ The internal implementation operates in a faster synchronous mode (without await
|
|
|
321
325
|
```
|
|
322
326
|
[test-variants] start, memory: 139MB
|
|
323
327
|
[test-variants] mode[0]: random
|
|
324
|
-
[test-variants] cycle: 3, variant: 65 (1.0s), tests: 615 (5.0s), async: 12, memory: 148MB (+8.8MB)
|
|
328
|
+
[test-variants] cycle: 3, variant: 65 (1.0s), tests: 615 (5.0s), maxTime: 0.1s, async: 12, memory: 148MB (+8.8MB)
|
|
325
329
|
[test-variants] mode[1]: backward, limitTests=10
|
|
326
|
-
[test-variants] cycle: 5, variant: 65/100 (2.0s), tests: 615 (6.0s), async: 123, memory: 139MB (-8.8MB)
|
|
330
|
+
[test-variants] cycle: 5, variant: 65/100 (2.0s), tests: 615 (6.0s), maxTime: 0.2s, async: 123, memory: 139MB (-8.8MB)
|
|
327
331
|
[test-variants] mode[2]: forward, limitTests=100, limitTime=10.9m
|
|
328
|
-
[test-variants] end, tests: 815 (7.0s), async: 123, memory: 138MB (-1.0MB)
|
|
332
|
+
[test-variants] end, tests: 815 (7.0s), maxTime: 0.2s, async: 123, memory: 138MB (-1.0MB)
|
|
329
333
|
...
|
|
330
334
|
```
|
|
331
335
|
|
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-C2AcN9Rj.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-C2AcN9Rj.js");exports.TimeoutError=e.TimeoutError;exports.createTestVariants=e.createTestVariants;
|
package/build/common/index.mjs
CHANGED
|
@@ -11,6 +11,8 @@ export type RunState = {
|
|
|
11
11
|
/** Sum of iterationsSync + iterationsAsync from test results */
|
|
12
12
|
iterations: number;
|
|
13
13
|
iterationsAsync: number;
|
|
14
|
+
/** Maximum duration of a single test run in ms */
|
|
15
|
+
maxTestDuration: number;
|
|
14
16
|
prevLogTime: number;
|
|
15
17
|
prevLogMemory: number | null;
|
|
16
18
|
/** Mode change event waiting to be logged with next progress */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Obj, PromiseOrValue, RequiredNonNullable } from '@flemist/simple-utils';
|
|
2
2
|
import { TestVariantsTemplatesExt, VariantsIterator } from '../iterator/types';
|
|
3
3
|
import { ArgsWithSeed, OnErrorCallback, OnTestEndCallback, OnTestStartCallback, SaveErrorVariantsOptions, TestVariantsState, TestVariantsLogOptions, TestVariantsResult, TestVariantsRunOptions } from '../types';
|
|
4
|
+
import { RunState } from './createRunState';
|
|
4
5
|
/** Result of test run (internal format with separate sync/async counts) */
|
|
5
6
|
export type TestFuncResult = {
|
|
6
7
|
iterationsAsync: number;
|
|
@@ -40,6 +41,8 @@ export type SaveErrorVariantsStoreReplayOptions<Args extends Obj> = {
|
|
|
40
41
|
testOptions: TestVariantsState;
|
|
41
42
|
/** Whether findBestError is enabled */
|
|
42
43
|
findBestErrorEnabled?: null | boolean;
|
|
44
|
+
/** Mutable run state for tracking test count during replay */
|
|
45
|
+
state: RunState;
|
|
43
46
|
};
|
|
44
47
|
/** Factory function for creating SaveErrorVariantsStore */
|
|
45
48
|
export type CreateSaveErrorVariantsStore<Args extends Obj, SavedArgs = Args> = (options: SaveErrorVariantsOptions<Args, SavedArgs>) => SaveErrorVariantsStore<Args> | null;
|
|
@@ -55,8 +58,10 @@ export type TestVariantsCreateTestRunOptions<Args extends Obj> = {
|
|
|
55
58
|
log: RequiredNonNullable<TestVariantsLogOptions>;
|
|
56
59
|
/** Pause debugger on error */
|
|
57
60
|
pauseDebuggerOnError?: null | boolean;
|
|
58
|
-
/** Throws TimeoutError if single test run exceeds this timeout
|
|
61
|
+
/** Throws TimeoutError if single test run exceeds this timeout */
|
|
59
62
|
timeout?: null | number | ((args: Args) => number | null | undefined);
|
|
63
|
+
/** Mutable run state for tracking statistics across all test calls */
|
|
64
|
+
state: RunState;
|
|
60
65
|
};
|
|
61
66
|
export type TestVariantsCall<Args extends Obj> = <SavedArgs = Args>(options?: null | TestVariantsRunOptionsInternal<Args, SavedArgs>) => PromiseOrValue<TestVariantsResult<Args>>;
|
|
62
67
|
export type TestVariantsSetArgs<Args extends Obj> = <ArgsExtra extends Obj>(args: TestVariantsTemplatesExt<Omit<Args, 'seed'>, ArgsExtra>) => TestVariantsCall<Args>;
|
|
@@ -11,7 +11,7 @@ export type ArgsWithSeed<Args extends Obj> = Args & {
|
|
|
11
11
|
};
|
|
12
12
|
/** Base mode configuration shared by all modes */
|
|
13
13
|
export type BaseModeConfig = {
|
|
14
|
-
/** Maximum time in ms for this phase */
|
|
14
|
+
/** Maximum time in ms for this phase; does not interrupt a running test, only prevents starting the next iteration */
|
|
15
15
|
limitTime?: null | number;
|
|
16
16
|
/** Maximum total picks in this phase */
|
|
17
17
|
limitTests?: null | number;
|
|
@@ -208,11 +208,11 @@ export type TestVariantsRunOptions<Args extends Obj = Obj, SavedArgs = Args> = {
|
|
|
208
208
|
saveErrorVariants?: null | SaveErrorVariantsOptions<Args, SavedArgs>;
|
|
209
209
|
/** Tests only first N variants, ignores the rest. If null or not specified, tests all variants */
|
|
210
210
|
limitTests?: null | number;
|
|
211
|
-
/** Maximum
|
|
211
|
+
/** 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
212
|
limitTime?: null | number;
|
|
213
213
|
/** Time controller for testable time-dependent operations; null uses timeControllerDefault */
|
|
214
214
|
timeController?: null | ITimeController;
|
|
215
|
-
/** Throws TimeoutError if single test run exceeds this timeout
|
|
215
|
+
/** Throws TimeoutError if single test run exceeds this timeout */
|
|
216
216
|
timeout?: null | number | ((args: Args) => number | null | undefined);
|
|
217
217
|
};
|
|
218
218
|
export declare class TimeoutError extends Error {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";const z=require("@flemist/time-controller"),E=require("@flemist/simple-utils"),R=require("@flemist/abort-controller-fast"),K=require("@flemist/time-limits");class de 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 He=1e3,B=[];function Je(e){return E.formatAny(e,{pretty:!0,maxDepth:5,maxItems:50})}function Xe(...e){const r=e.map(t=>typeof t=="string"?t:Je(t)).join(" ");B.push(r),B.length>He&&B.shift(),console.log(r)}function Ze(){return B.join(`
|
|
2
|
+
`)}globalThis.__getStressTestLogLast=Ze;const ge=(e,r)=>{Xe(r)},pe=e=>E.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:ge,format:pe},Ke={start:!1,progress:!1,completed:!1,error:!1,modeChange:!1,debug:!1,func:ge,format:pe};function he(e){return e===!1?Ke: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 Qe(e,r){const t=e.now();return{startTime:t,startMemory:r,debugMode:!1,tests:0,iterations:0,iterationsAsync:0,maxTestDuration:0,prevLogTime:t,prevLogMemory:r,pendingModeChange:null,prevGcTime:t,prevGcIterations:0,prevGcIterationsAsync:0}}class V extends R.AbortError{}class Ye{_timeController;_subject;_interval;_timer;constructor(r,t){this._interval=r,this._timeController=t??z.timeControllerDefault,this._subject=new E.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 et=50,tt=5;function rt(e,r){return e==null?null:typeof e=="number"?e:e(r)??null}function ae(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 nt(e,r){const t=r.log,o=r.pauseDebuggerOnError??!0,i=r.onStart,s=r.onEnd;r.state;let n=null,a=0;function u(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>et&&a<tt){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 Ye(100);return function(h,y,d){i&&i({args:h,tests:y});const b=rt(r.timeout,h);let v=null,M=d,f=null;b&&(v=Date.now(),f=new R.AbortControllerFast,M={abortSignal:E.combineAbortSignals(d.abortSignal,f.signal),timeController:d.timeController});function x(){f.abort(new de(`[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&&(x(),T())}),S=Promise.race([S,E.abortSignalToPromise(f.signal)])),S.then(O=>{T?.();const G=ae(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}),u(O,h,y)))}v!=null&&Date.now()-v>b&&(x(),f.signal.throwIfAborted());const A=ae(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}),u(S,h,y))}}}function F(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 ue(e,r,t,o){const i=Object.keys(e.templates),s={},n=[],a=[],u=[],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),u.push(null)}return{args:s,argsNames:i,indexes:n,argValues:a,argLimits:u,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 u=o[a];F(i,u,e.equals)<0&&(s==null?s=[...i,u]:s.push(u))}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 be(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 u=I(e,n,n>i);if(u<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]>u)&&(e.indexes[n]=u,e.args[e.argsNames[n]]=e.argValues[n][u],s=!0),i===o&&e.indexes[n]<u&&(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 u=I(e,n,a),g=e.indexes[n]+1;if(g<=u){e.indexes[n]=g,e.args[e.argsNames[n]]=e.argValues[n][g],g<u&&(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 u=I(e,n,n>i);if(u<0){t=!1,e.indexes[n]=-1;break}a&&(e.indexes[n]=u,e.args[e.argsNames[n]]=e.argValues[n][u]),(s||e.indexes[n]>u)&&(e.indexes[n]=u,e.args[e.argsNames[n]]=e.argValues[n][u],s=!0),i===o&&e.indexes[n]<u&&(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 u=I(e,n,a);let g=e.indexes[n]-1;if(g>u&&(g=u),g>=0){e.indexes[n]=g,e.args[e.argsNames[n]]=e.argValues[n][g],g<u&&(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 it(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 u=I(e,s,i);if(u<0)return null;const g=F(e.argValues[s],a,e.equals);if(g<0||g>u)return null;e.indexes[s]=g,e.args[e.argsNames[s]]=e.argValues[s][g],e.indexes[s]<u&&(i=!0)}return L(e)?null:e.indexes.slice()}function ot(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?be(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 U(e){return e.mode==="forward"||e.mode==="backward"}function st(e,r,t,o){const i=r[t],s=e.templates[t];if(typeof s!="function"){if(F(s,i,o)>=0)return;s.push(i);return}const n=e.extra[t];if(n==null){e.extra[t]=[i];return}F(n,i,o)>=0||n.push(i)}function lt(e,r,t){for(const o in r)if(Object.prototype.hasOwnProperty.call(r,o)){if(o==="seed")continue;st(e,r,o,t)}}function ce(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 at=[{mode:"forward"}];function ut(e){const{argsTemplates:r,equals:t,limitArgOnError:o,includeErrorVariant:i,getSeed:s,iterationModes:n,onModeChange:a,limitCompletionCount:u,limitTests:g,limitTime:m}=e,h=e.timeController??z.timeControllerDefault,y={templates:E.deepCloneJsonLike(r),extra:{}},d=n==null||n.length===0?at:n,b=[];let v=null,M=null,f=0,x=0,S=!1,A=0;function T(){S||(S=!0,A=h.now(),O(),f=0,oe(),xe())}function O(){for(let l=0,c=d.length;l<c;l++)b.push(G())}function G(){return{navigationState:ue(y,t??null,o??null,i??null),cycleCount:0,completedCount:0,testsInLastTurn:0,tryNextVariantAttempts:0,startTime:null}}function xe(){v=ue(y,t??null,!1,!1)}function oe(){a?.({mode:d[f],modeIndex:f,tests:x})}function we(l){T(),ce(y.templates,l)&<(y,l,t)}function se(l,c){return T(),ce(y.templates,l)?(v.limitArgOnError=c?.limitArg??o??null,v.includeErrorVariant=c?.includeLimit??i??!1,it(v,l)):null}function Te(l){const c=l?.args;if(c==null)return;T();const p=se(c);if(p!=null){M={args:c,error:l?.error,tests:l?.tests??x},v.argLimits=p;for(let w=0,k=b.length;w<k;w++){const X=b[w].navigationState;X.argLimits=p}}}function Ce(){return T(),Me()}function Me(){for(;;){if(!Ie())return null;for(;;){const l=Ge();if(l!=null)return b[f].testsInLastTurn++,x++,l;if(_e()){if(!Ne())return null;De();break}}}}function Ie(){return!(Ve()||Ae()||q()&&(Oe()||!Le())||!Pe())}function Ve(){return g!=null&&x>=g}function Ae(){return m!=null&&h.now()-A>=m}function Oe(){if(!q())throw new Error("Unexpected behavior");return u!=null&&u<=0}function Le(){if(!q())throw new Error("Unexpected behavior");for(let l=0,c=d.length;l<c;l++)if(P(d[l])&&H(l))return!0;return!1}function Pe(){for(let l=0,c=d.length;l<c;l++)if(H(l))return!0;return!1}function _e(){f++;const l=f>=d.length;return l&&(f=0),oe(),l}function Ne(){if(q()){const l=$e();if(u!=null&&l>=u)return!1}return!0}function q(){for(let l=0,c=d.length;l<c;l++)if(U(d[l]))return!0;return!1}function $e(){let l=!1,c=1/0;for(let p=0,w=b.length;p<w;p++){const k=b[p],X=d[p];U(X)&&(l=!0,H(p)&&k.completedCount<c&&(c=k.completedCount))}if(!l)throw new Error("Unexpected behavior");return c}function H(l){const c=d[l],p=b[l];return c.limitTests!=null&&c.limitTests<=0||P(c)&&(c.cycles!=null&&c.cycles<=0||c.attemptsPerVariant!=null&&c.attemptsPerVariant<=0)?!1:p.tryNextVariantAttempts<2}function De(){f=0;for(let l=0,c=b.length;l<c;l++){const p=b[l];p.testsInLastTurn=0,p.startTime=null}}function Ge(){let l=0;for(;l<2;){if(!qe())return null;const c=Fe();if(c!=null)return c;if(P(d[f])&&Re())return null;l++}return null}function qe(){const l=d[f];return!(ke()||Ue()||P(l)&&!Be(f))}function ke(){const l=d[f],c=b[f];return l.limitTests!=null&&c.testsInLastTurn>=l.limitTests}function Ue(){const l=d[f],c=b[f];return l.limitTime!=null&&c.startTime!=null&&h.now()-c.startTime>=l.limitTime}function P(l){return U(l)}function Be(l){const c=d[l],p=b[l];if(!P(c))throw new Error("Unexpected behavior");return p.cycleCount<(c.cycles??1)}function Re(){const l=d[f],c=b[f];if(!P(l))throw new Error("Unexpected behavior");return c.cycleCount++,c.cycleCount>=(l.cycles??1)?(c.cycleCount=0,c.completedCount++,!0):!1}function Fe(){const l=d[f],c=b[f],p=c.navigationState;if($(l)){if(J())return null;const w=je();if(w!=null)return c.startTime==null&&(c.startTime=h.now()),w}return ze()?(c.tryNextVariantAttempts=0,$(l)&&We(),c.startTime==null&&(c.startTime=h.now()),le(p.args)):(c.tryNextVariantAttempts++,null)}function je(){const l=d[f],p=b[f].navigationState;if(!$(l))throw new Error("Unexpected behavior");if(J())throw new Error("Unexpected behavior");const w=l.attemptsPerVariant??1;return p.attempts>0&&p.attempts<w?L(p)?null:(p.attempts++,le(p.args)):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");p.attempts=1}function $(l){return U(l)}function J(){const l=d[f];if(!$(l))throw new Error("Unexpected behavior");return(l.attemptsPerVariant??1)<=0}function ze(){const l=d[f],p=b[f].navigationState;switch(l.mode){case"forward":return be(p);case"backward":return Q(p);case"random":return ot(p);default:throw new Error(`Unknown mode: ${l.mode}`)}}function le(l){const c={...l};return s!=null&&(c.seed=s({tests:x})),c}return{get limit(){return M},get modeIndex(){return f},get modeConfigs(){return d},get modeStates(){return b},get tests(){return x},calcIndexes:se,extendTemplates:we,addLimit:Te,next:Ce}}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 ct(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 fe=2**31;function ft(e){if(e==null)return{parallel:1,sequentialOnError:!1};if(typeof e=="boolean")return{parallel:e?fe: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=fe:typeof r=="number"&&r>0&&(t=r),{parallel:t,sequentialOnError:e.sequentialOnError??!1}}function mt(e){const r=e?.saveErrorVariants,t=r&&e.createSaveErrorVariantsStore?e.createSaveErrorVariantsStore(r):null,o=e?.findBestError,{parallel:i,sequentialOnError:s}=ft(e?.parallel);return{store:t,GC_Iterations:e?.GC_Iterations??1e6,GC_IterationsAsync:e?.GC_IterationsAsync??1e4,GC_Interval:e?.GC_Interval??1e3,logOptions:he(e?.log),abortSignalExternal:e?.abortSignal,findBestError:o,dontThrowIfError:o?.dontThrowIfError,timeController:e?.timeController??z.timeControllerDefault,parallel:i,sequentialOnError:s}}function j(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 dt(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,j(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;j(e,r,!1),i.abort(t)}}function me(e,r,t,o){const{state:i}=e;if(e.options.findBestError){e.variantsIterator.addLimit({args:r,error:t,tests:o});const n=j(e,r,!0);if(n)return n.then(()=>{i.debugMode=!1});i.debugMode=!1;return}const s=j(e,r,!0);if(s)return s.then(()=>{throw t});throw t}function gt(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 pt(e,r){e.prevGcIterations=e.iterations,e.prevGcIterationsAsync=e.iterationsAsync,e.prevGcTime=r,await ie(1)}function D(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 ht(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=${D(e.limitTime)}`),e.limitTests!=null&&(t+=`, limitTests=${e.limitTests}`),t}function ye(e,r){const t=e-r,o=t>=0?"+":"";return`${Y(e)} (${o}${Y(t)})`}function bt(e,r){if(!e.start)return;let t="[test-variants] start";r!=null&&(t+=`, memory: ${Y(r)}`),e.func("start",t)}function yt(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} (${D(s)}), maxTime: ${D(t.maxTestDuration)}, async: ${t.iterationsAsync}`;if(t.startMemory!=null){const a=ne();a!=null&&(n+=`, memory: ${ye(a,t.startMemory)}`)}o.func("completed",n)}function ve(e){const{options:r,state:t}=e,{logOptions:o}=r,i=t.pendingModeChange;!o.modeChange||i==null||(o.func("modeChange",`[test-variants] ${ht(i.mode,i.modeIndex)}`),t.pendingModeChange=null)}function vt(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;ve(e);const n=s-t.startTime;let a=`[test-variants] tests: ${t.tests} (${D(n)}), maxTime: ${D(t.maxTestDuration)}, async: ${t.iterationsAsync}`;if(t.prevLogMemory!=null){const u=ne();u!=null&&(a+=`, memory: ${ye(u,t.prevLogMemory)}`,t.prevLogMemory=u)}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 Se(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=>me(e,r,a,s));if(!n){te(e);return}ee(i,n)}catch(n){return n instanceof V?void 0:me(e,r,n,s)}}function St(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 u=i(r,a,s);if(E.isPromiseLike(u)&&(u=await u),!u){te(e);return}ee(n,u)}catch(u){if(u instanceof V)return;dt(e,r,u,a)}finally{t.release(1)}})()}function Ee(e){const{options:r,state:t}=e,{logOptions:o,timeController:i,GC_Interval:s}=r;if(!o.progress&&!s)return;vt(e);const n=i.now();if(gt(e,n))return pt(t,n)}function W(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(;!W(e);){const u=t&&!re(e);let g=!1;u&&(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=Ee(e);if(E.isPromiseLike(m)&&await m,W(e))continue;if(u)St(e,a),g=!1;else{n.debug&&t&&re(e)&&n.func("debug",`[test-variants] parallel aborted, running sequential: tests=${o.tests}`);const h=Se(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 Et(e){const{pool:r,state:t,options:o}=e,{logOptions:i}=o;if(r)return Z(e);let s=null;for(;!W(e)&&(e.state.debugMode||(s=e.variantsIterator.next()),s!=null);){const n=Ee(e);if(E.isPromiseLike(n))return n.then(()=>Z(e,s));if(W(e))continue;i.debug&&re(e)&&i.func("debug",`[test-variants] parallel aborted, running sequential: tests=${t.tests}`);const a=Se(e,s);if(E.isPromiseLike(a))return a.then(()=>Z(e))}}async function xt(e,r,t,o){const i=mt(o),{store:s,logOptions:n,abortSignalExternal:a,findBestError:u,dontThrowIfError:g,timeController:m,parallel:h}=i,y=new R.AbortControllerFast,d=new R.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:!!u,state:t});const x=h<=1?null:new K.Pool(h);bt(n,t.startMemory);const S={options:i,testRun:e,variantsIterator:r,testOptions:M,testOptionsParallel:f,abortControllerGlobal:y,abortControllerParallel:d,abortSignal:v,pool:x,state:t};ve(S);try{await Et(S),v.throwIfAborted()}catch(A){throw y.abort(new V),A}return b.throwIfAborted(),y.abort(new V),yt(S),await ie(1),ct(t,r,g)}function wt(e){return function(t){return async function(i){const s=he(i?.log),n=i?.timeController??z.timeControllerDefault,a=ne(),u=Qe(n,a),g=nt(e,{onStart:i?.onStart,onEnd:i?.onEnd,onError:i?.onError,log:s,pauseDebuggerOnError:i?.pauseDebuggerOnError,timeout:i?.timeout,state:u}),m=i?.onModeChange;function h(d){u.pendingModeChange=d,m?.(d)}const y=ut({argsTemplates:t,getSeed:i?.getSeed,iterationModes:i?.iterationModes,equals:i?.findBestError?.equals,limitArgOnError:i?.findBestError?.limitArgOnError,includeErrorVariant:i?.findBestError?.includeErrorVariant,timeController:n,onModeChange:h,limitCompletionCount:i?.cycles??1,limitTests:i?.limitTests,limitTime:i?.limitTime});return xt(g,y,u,i)}}}exports.TimeoutError=de;exports.createTestVariants=wt;
|