@flemist/test-variants 5.0.11 → 5.0.12
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 +16 -0
- 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/types.d.ts +5 -3
- package/build/common/test-variants/types.d.ts +23 -0
- package/build/createTestVariants-DlP_jc3m.js +4 -0
- package/build/{createTestVariants-DHWt92RI.mjs → createTestVariants-DxolnPmm.mjs} +317 -308
- package/build/node/index.cjs +1 -1
- package/build/node/index.mjs +1 -1
- package/package.json +1 -1
- package/build/createTestVariants-6NbYYHA7.js +0 -4
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: ({
|
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-DlP_jc3m.js");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-DlP_jc3m.js");exports.createTestVariants=e.createTestVariants;
|
package/build/common/index.mjs
CHANGED
|
@@ -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,6 +49,8 @@ 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>;
|
|
@@ -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 */
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";const Y=require("@flemist/time-controller"),ee=require("@flemist/simple-utils"),S=require("@flemist/async-utils"),z=require("@flemist/abort-controller-fast"),H=require("@flemist/time-limits");function te(){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,_=[];function Je(e){return ee.formatAny(e,{pretty:!0,maxDepth:5,maxItems:50})}function Xe(...e){const n=e.map(t=>typeof t=="string"?t:Je(t)).join(" ");_.push(n),_.length>He&&_.shift(),console.log(n)}function Ze(){return _.join(`
|
|
2
|
+
`)}globalThis.__getStressTestLogLast=Ze;const de=(e,n)=>{Xe(n)},me=e=>ee.formatAny(e,{pretty:!0,maxDepth:20,maxItems:100,maxStringLength:5e3,dontExpandClassInstances:!0,dontExpandFunctions:!0}),x={start:!0,progress:5e3,completed:!0,error:!0,modeChange:!0,debug:!1,func:de,format:me},Ke={start:!1,progress:!1,completed:!1,error:!1,modeChange:!1,debug:!1,func:de,format:me};function ge(e){return e===!1?Ke:e===!0||!e?x:{start:e.start??x.start,progress:e.progress??x.progress,completed:e.completed??x.completed,error:e.error??x.error,modeChange:e.modeChange??x.modeChange,debug:e.debug??x.debug,func:e.func??x.func,format:e.format??x.format}}function Qe(e,n){const t=e.now();return{startTime:t,startMemory:n,debugMode:!1,tests:0,iterations:0,iterationsAsync:0,prevLogTime:t,prevLogMemory:n,pendingModeChange:null,prevGcTime:t,prevGcIterations:0,prevGcIterationsAsync:0}}class T extends z.AbortError{}const Ye=50,et=5;function ae(e,n){return typeof e=="number"?{iterationsAsync:0,iterationsSync:e}:e!=null&&typeof e=="object"?e:n?{iterationsAsync:1,iterationsSync:0}:{iterationsAsync:0,iterationsSync:1}}function tt(e,n){const t=n.log,i=n.pauseDebuggerOnError??!0,o=n.onStart,s=n.onEnd;let r=null,l=0;function c(m,f,b){r==null&&(r={error:m,args:f,tests:b},t.error&&t.func("error",`[test-variants] error variant: ${t.format(f)}
|
|
3
|
+
tests: ${b}
|
|
4
|
+
${t.format(m)}`));const y=Date.now();if(i)debugger;if(Date.now()-y>Ye&&l<et){t.func("debug",`[test-variants] debug iteration: ${l}`),l++;return}const h=r;throw r=null,n.onError&&n.onError(h),h.error}return function(f,b,y){o&&o({args:f,tests:b});try{const d=e(f,y);if(S.isPromiseLike(d))return d.then(v=>{const w=ae(v,!0);return s&&s({args:f,tests:b,result:w}),w},v=>(s&&!(v instanceof T)&&s({args:f,tests:b,error:v}),c(v,f,b)));const h=ae(d,!1);return s&&s({args:f,tests:b,result:h}),h}catch(d){return d instanceof T?void 0:(s&&s({args:f,tests:b,error:d}),c(d,f,b))}}}function k(e,n,t){for(let i=0,o=e.length;i<o;i++)if(t?t(e[i],n):e[i]===n)return i;return-1}function le(e,n,t,i){const o=Object.keys(e.templates),s={},r=[],l=[],c=[],m=o.length;for(let f=0;f<m;f++){const b=o[f];s[b]=void 0,r.push(-1),l.push(void 0),c.push(null)}return{args:s,argsNames:o,indexes:r,argValues:l,argLimits:c,attempts:0,templates:e,limitArgOnError:t,equals:n,includeErrorVariant:i??!1}}function O(e,n){const t=e.templates.templates[n],i=e.templates.extra[n];let o;if(typeof t=="function"?o=t(e.args):o=t,i==null)return o;let s=null;const r=i.length;for(let l=0;l<r;l++){const c=i[l];k(o,c,e.equals)<0&&(s==null?s=[...o,c]:s.push(c))}return s??o}function I(e,n,t){const i=e.argValues[n].length;if(i===0)return-1;const o=e.argLimits[n];if(o==null)return i-1;let s=e.limitArgOnError;if(typeof s=="function"){const r=e.argsNames[n];s=s({name:r,values:e.argValues[n],maxValueIndex:o})}return!t||s?Math.min(o,i-1):i-1}function V(e){const n=e.indexes.length;for(let t=0;t<n;t++){const i=e.argLimits[t];if(i==null)return!1;const o=e.indexes[t];if(o>i)return!0;if(o<i)return!1}return!e.includeErrorVariant}function L(e){const n=e.indexes.length;for(let t=0;t<n;t++)e.indexes[t]=-1,e.argValues[t]=void 0,e.args[e.argsNames[t]]=void 0}function pe(e){let n=!1,t=!0;const i=e.indexes.length;let o=i,s=!1,r=0;for(;r<i;r++){const l=e.argValues[r]==null;(l||s)&&(l&&(n=!0),e.argValues[r]=O(e,e.argsNames[r]));const c=I(e,r,r>o);if(c<0){t=!1,e.indexes[r]=-1;break}l&&(e.indexes[r]=0,e.args[e.argsNames[r]]=e.argValues[r][0]),(s||e.indexes[r]>c)&&(e.indexes[r]=c,e.args[e.argsNames[r]]=e.argValues[r][c],s=!0),o===i&&e.indexes[r]<c&&(o=r)}if(V(e))return L(e),!1;if(n&&t)return!0;for(r--;r>=0;r--){if(e.argValues[r]==null)continue;let l=r>o;const c=I(e,r,l),m=e.indexes[r]+1;if(m<=c){e.indexes[r]=m,e.args[e.argsNames[r]]=e.argValues[r][m],m<c&&(l=!0);for(let f=r+1;f<i;f++)e.args[e.argsNames[f]]=void 0;for(r++;r<i;r++){e.argValues[r]=O(e,e.argsNames[r]);const f=I(e,r,l);if(f<0)break;e.indexes[r]=0,e.args[e.argsNames[r]]=e.argValues[r][0],f>0&&(l=!0)}if(r>=i)return V(e)?(L(e),!1):!0}}return L(e),!1}function J(e){V(e)&&L(e);let n=!1,t=!0;const i=e.indexes.length;let o=i,s=!1,r=0;for(;r<i;r++){const l=e.argValues[r]==null;(l||s)&&(l&&(n=!0),e.argValues[r]=O(e,e.argsNames[r]));const c=I(e,r,r>o);if(c<0){t=!1,e.indexes[r]=-1;break}l&&(e.indexes[r]=c,e.args[e.argsNames[r]]=e.argValues[r][c]),(s||e.indexes[r]>c)&&(e.indexes[r]=c,e.args[e.argsNames[r]]=e.argValues[r][c],s=!0),o===i&&e.indexes[r]<c&&(o=r)}if((n||s)&&t&&!V(e))return!0;for(r--;r>=0;r--){if(e.argValues[r]==null)continue;let l=r>o;const c=I(e,r,l);let m=e.indexes[r]-1;if(m>c&&(m=c),m>=0){e.indexes[r]=m,e.args[e.argsNames[r]]=e.argValues[r][m],m<c&&(l=!0);for(let f=r+1;f<i;f++)e.args[e.argsNames[f]]=void 0;for(r++;r<i;r++){e.argValues[r]=O(e,e.argsNames[r]);const f=I(e,r,l);if(f<0)break;e.indexes[r]=f,e.args[e.argsNames[r]]=e.argValues[r][f],f>0&&(l=!0)}if(r>=i)return!0}}return L(e),!1}function rt(e,n){L(e);const t=e.argsNames,i=t.length;let o=!1;for(let s=0;s<i;s++){const r=t[s],l=n[r];if(l===void 0)return null;e.argValues[s]=O(e,r);const c=I(e,s,o);if(c<0)return null;const m=k(e.argValues[s],l,e.equals);if(m<0||m>c)return null;e.indexes[s]=m,e.args[e.argsNames[s]]=e.argValues[s][m],e.indexes[s]<c&&(o=!0)}return V(e)?null:e.indexes.slice()}function nt(e){const n=e.indexes.length;if(n===0)return!1;let t=!1;for(let i=0;i<n;i++){e.argValues[i]=O(e,e.argsNames[i]);const o=I(e,i,t);if(o<0)return Math.random()<.5?pe(e):J(e);e.indexes[i]=Math.floor(Math.random()*(o+1)),e.args[e.argsNames[i]]=e.argValues[i][e.indexes[i]],e.indexes[i]<o&&(t=!0)}return V(e)?J(e):!0}function D(e){return e.mode==="forward"||e.mode==="backward"}function ot(e,n,t,i){const o=n[t],s=e.templates[t];if(typeof s!="function"){if(k(s,o,i)>=0)return;s.push(o);return}const r=e.extra[t];if(r==null){e.extra[t]=[o];return}k(r,o,i)>=0||r.push(o)}function it(e,n,t){for(const i in n)if(Object.prototype.hasOwnProperty.call(n,i)){if(i==="seed")continue;ot(e,n,i,t)}}function ue(e,n){for(const t in n)if(Object.prototype.hasOwnProperty.call(n,t)){if(t==="seed")continue;if(!e[t])return!1}return!0}const st=[{mode:"forward"}];function at(e){const{argsTemplates:n,equals:t,limitArgOnError:i,includeErrorVariant:o,getSeed:s,iterationModes:r,onModeChange:l,limitCompletionCount:c,limitTests:m,limitTime:f}=e,b=e.timeController??Y.timeControllerDefault,y={templates:ee.deepCloneJsonLike(n),extra:{}},d=r==null||r.length===0?st:r,h=[];let v=null,w=null,p=0,M=0,A=!1,N=0;function $(){A||(A=!0,N=b.now(),Ee(),p=0,oe(),xe())}function Ee(){for(let a=0,u=d.length;a<u;a++)h.push(Se())}function Se(){return{navigationState:le(y,t??null,i??null,o??null),cycleCount:0,completedCount:0,testsInLastTurn:0,tryNextVariantAttempts:0,startTime:null}}function xe(){v=le(y,t??null,!1,!1)}function oe(){l?.({mode:d[p],modeIndex:p,tests:M})}function we(a){$(),ue(y.templates,a)&&it(y,a,t)}function ie(a,u){return $(),ue(y.templates,a)?(v.limitArgOnError=u?.limitArg??i??null,v.includeErrorVariant=u?.includeLimit??o??!1,rt(v,a)):null}function Me(a){const u=a?.args;if(u==null)return;$();const g=ie(u);if(g!=null){w={args:u,error:a?.error,tests:a?.tests??M},v.argLimits=g;for(let E=0,q=h.length;E<q;E++){const j=h[E].navigationState;j.argLimits=g}}}function Ie(){return $(),Te()}function Te(){for(;;){if(!Ve())return null;for(;;){const a=De();if(a!=null)return h[p].testsInLastTurn++,M++,a;if(Ne()){if(!$e())return null;qe();break}}}}function Ve(){return!(Ae()||Ce()||G()&&(Le()||!Oe())||!Pe())}function Ae(){return m!=null&&M>=m}function Ce(){return f!=null&&b.now()-N>=f}function Le(){if(!G())throw new Error("Unexpected behavior");return c!=null&&c<=0}function Oe(){if(!G())throw new Error("Unexpected behavior");for(let a=0,u=d.length;a<u;a++)if(C(d[a])&&R(a))return!0;return!1}function Pe(){for(let a=0,u=d.length;a<u;a++)if(R(a))return!0;return!1}function Ne(){p++;const a=p>=d.length;return a&&(p=0),oe(),a}function $e(){if(G()){const a=Ge();if(c!=null&&a>=c)return!1}return!0}function G(){for(let a=0,u=d.length;a<u;a++)if(D(d[a]))return!0;return!1}function Ge(){let a=!1,u=1/0;for(let g=0,E=h.length;g<E;g++){const q=h[g],j=d[g];D(j)&&(a=!0,R(g)&&q.completedCount<u&&(u=q.completedCount))}if(!a)throw new Error("Unexpected behavior");return u}function R(a){const u=d[a],g=h[a];return u.limitTests!=null&&u.limitTests<=0||C(u)&&(u.cycles!=null&&u.cycles<=0||u.attemptsPerVariant!=null&&u.attemptsPerVariant<=0)?!1:g.tryNextVariantAttempts<2}function qe(){p=0;for(let a=0,u=h.length;a<u;a++){const g=h[a];g.testsInLastTurn=0,g.startTime=null}}function De(){let a=0;for(;a<2;){if(!_e())return null;const u=Fe();if(u!=null)return u;if(C(d[p])&&Re())return null;a++}return null}function _e(){const a=d[p];return!(ke()||Ue()||C(a)&&!Be(p))}function ke(){const a=d[p],u=h[p];return a.limitTests!=null&&u.testsInLastTurn>=a.limitTests}function Ue(){const a=d[p],u=h[p];return a.limitTime!=null&&u.startTime!=null&&b.now()-u.startTime>=a.limitTime}function C(a){return D(a)}function Be(a){const u=d[a],g=h[a];if(!C(u))throw new Error("Unexpected behavior");return g.cycleCount<(u.cycles??1)}function Re(){const a=d[p],u=h[p];if(!C(a))throw new Error("Unexpected behavior");return u.cycleCount++,u.cycleCount>=(a.cycles??1)?(u.cycleCount=0,u.completedCount++,!0):!1}function Fe(){const a=d[p],u=h[p],g=u.navigationState;if(P(a)){if(F())return null;const E=je();if(E!=null)return u.startTime==null&&(u.startTime=b.now()),E}return ze()?(u.tryNextVariantAttempts=0,P(a)&&We(),u.startTime==null&&(u.startTime=b.now()),se(g.args)):(u.tryNextVariantAttempts++,null)}function je(){const a=d[p],g=h[p].navigationState;if(!P(a))throw new Error("Unexpected behavior");if(F())throw new Error("Unexpected behavior");const E=a.attemptsPerVariant??1;return g.attempts>0&&g.attempts<E?V(g)?null:(g.attempts++,se(g.args)):null}function We(){const a=d[p],g=h[p].navigationState;if(!P(a))throw new Error("Unexpected behavior");if(F())throw new Error("Unexpected behavior");g.attempts=1}function P(a){return D(a)}function F(){const a=d[p];if(!P(a))throw new Error("Unexpected behavior");return(a.attemptsPerVariant??1)<=0}function ze(){const a=d[p],g=h[p].navigationState;switch(a.mode){case"forward":return pe(g);case"backward":return J(g);case"random":return nt(g);default:throw new Error(`Unknown mode: ${a.mode}`)}}function se(a){const u={...a};return s!=null&&(u.seed=s({tests:M})),u}return{get limit(){return w},get modeIndex(){return p},get modeConfigs(){return d},get modeStates(){return h},get tests(){return M},calcIndexes:ie,extendTemplates:we,addLimit:Me,next:Ie}}function re(e){if(e==null||e<=0)throw new Error(`Iterations = ${e}`);e--;const n=S.waitMicrotasks().then(()=>e);return e<=0?n:n.then(re)}function lt(e,n,t){const i=n.limit?{error:n.limit.error,args:n.limit.args,tests:n.limit.tests}:null;if(i&&!t)throw i.error;return{iterations:e.iterations,bestError:i}}const ce=2**31;function ut(e){if(e==null)return{parallel:1,sequentialOnError:!1};if(typeof e=="boolean")return{parallel:e?ce:1,sequentialOnError:!1};if(typeof e=="number")return{parallel:e>0?e:1,sequentialOnError:!1};const n=e.count;let t=1;return n===!0?t=ce:typeof n=="number"&&n>0&&(t=n),{parallel:t,sequentialOnError:e.sequentialOnError??!1}}function ct(e){const n=e?.saveErrorVariants,t=n&&e.createSaveErrorVariantsStore?e.createSaveErrorVariantsStore(n):null,i=e?.findBestError,{parallel:o,sequentialOnError:s}=ut(e?.parallel);return{store:t,GC_Iterations:e?.GC_Iterations??1e6,GC_IterationsAsync:e?.GC_IterationsAsync??1e4,GC_Interval:e?.GC_Interval??1e3,logOptions:ge(e?.log),abortSignalExternal:e?.abortSignal,findBestError:i,dontThrowIfError:i?.dontThrowIfError,timeController:e?.timeController??Y.timeControllerDefault,parallel:o,sequentialOnError:s}}function U(e,n,t){const{options:i,variantsIterator:o}=e,s=o.limit?.args??n;if(!i.store)return;const r=i.store.save(s);if(t)return r}function ft(e,n,t,i){const{abortControllerParallel:o,state:s,options:r}=e,{logOptions:l}=r;if(e.options.findBestError)e.variantsIterator.addLimit({args:n,error:t,tests:i}),s.debugMode=!1,U(e,n,!1),r.sequentialOnError&&!o.signal.aborted?(l.debug&&l.func("debug","[test-variants] sequentialOnError: aborting parallel, switching to sequential"),o.abort(new T)):l.debug&&l.func("debug","[test-variants] parallel error in findBestError mode, continuing with new limits");else{if(o.signal.aborted)return;U(e,n,!1),o.abort(t)}}function fe(e,n,t,i){const{state:o}=e;if(e.options.findBestError){e.variantsIterator.addLimit({args:n,error:t,tests:i});const r=U(e,n,!0);if(r)return r.then(()=>{o.debugMode=!1});o.debugMode=!1;return}const s=U(e,n,!0);if(s)return s.then(()=>{throw t});throw t}function dt(e,n){const{GC_Iterations:t,GC_IterationsAsync:i,GC_Interval:o}=e.options;return t>0&&e.state.iterations-e.state.prevGcIterations>=t||i>0&&e.state.iterationsAsync-e.state.prevGcIterationsAsync>=i||o>0&&n-e.state.prevGcTime>=o}async function mt(e,n){e.prevGcIterations=e.iterations,e.prevGcIterationsAsync=e.iterationsAsync,e.prevGcTime=n,await re(1)}function ne(e){const n=e/1e3;if(n<60)return`${n.toFixed(1)}s`;const t=n/60;return t<60?`${t.toFixed(1)}m`:`${(t/60).toFixed(1)}h`}function X(e){const n=e/1073741824;if(n>=1)return n>=10?`${Math.round(n)}GB`:`${n.toFixed(1)}GB`;const t=e/(1024*1024);return t>=10?`${Math.round(t)}MB`:`${t.toFixed(1)}MB`}function gt(e,n){if(!e)return`mode[${n}]: null`;let t=`mode[${n}]: ${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=${ne(e.limitTime)}`),e.limitTests!=null&&(t+=`, limitTests=${e.limitTests}`),t}function he(e,n){const t=e-n,i=t>=0?"+":"";return`${X(e)} (${i}${X(t)})`}function pt(e,n){if(!e.start)return;let t="[test-variants] start";n!=null&&(t+=`, memory: ${X(n)}`),e.func("start",t)}function ht(e){const{options:n,state:t}=e,{logOptions:i,timeController:o}=n;if(!i.completed)return;const s=o.now()-t.startTime;let r=`[test-variants] end, tests: ${t.tests} (${ne(s)}), async: ${t.iterationsAsync}`;if(t.startMemory!=null){const l=te();l!=null&&(r+=`, memory: ${he(l,t.startMemory)}`)}i.func("completed",r)}function be(e){const{options:n,state:t}=e,{logOptions:i}=n,o=t.pendingModeChange;!i.modeChange||o==null||(i.func("modeChange",`[test-variants] ${gt(o.mode,o.modeIndex)}`),t.pendingModeChange=null)}function bt(e){const{options:n,state:t}=e,{logOptions:i,timeController:o}=n,s=o.now();if(!i.progress||s-t.prevLogTime<i.progress)return!1;be(e);const r=s-t.startTime;let l=`[test-variants] tests: ${t.tests} (${ne(r)}), async: ${t.iterationsAsync}`;if(t.prevLogMemory!=null){const c=te();c!=null&&(l+=`, memory: ${he(c,t.prevLogMemory)}`,t.prevLogMemory=c)}return i.func("progress",l),t.prevLogTime=s,!0}function Z(e,n){e.debugMode=!1,n&&(e.iterationsAsync+=n.iterationsAsync,e.iterations+=n.iterationsSync+n.iterationsAsync)}function K(e){e.state.debugMode=!0,e.abortControllerParallel.abort(new T)}function ye(e,n){const{testRun:t,testOptions:i,state:o}=e,s=o.tests;o.tests++;try{const r=t(n,s,i);if(S.isPromiseLike(r))return r.then(l=>{if(!l){K(e);return}Z(o,l)},l=>fe(e,n,l,s));if(!r){K(e);return}Z(o,r)}catch(r){return r instanceof T?void 0:fe(e,n,r,s)}}function yt(e,n){const{pool:t,abortSignal:i,testRun:o,testOptionsParallel:s,state:r}=e;if(!t)return;const l=r.tests;r.tests++,(async()=>{try{if(i.aborted)return;let c=o(n,l,s);if(S.isPromiseLike(c)&&(c=await c),!c){K(e);return}Z(r,c)}catch(c){if(c instanceof T)return;ft(e,n,c,l)}finally{t.release(1)}})()}function ve(e){const{options:n,state:t}=e,{logOptions:i,timeController:o,GC_Interval:s}=n;if(!i.progress&&!s)return;bt(e);const r=o.now();if(dt(e,r))return mt(t,r)}function B(e){return e.options.abortSignalExternal?.aborted??!1}function Q(e){return e.abortSignal.aborted}async function W(e,n){const{pool:t,state:i,options:o}=e,{parallel:s,logOptions:r}=o;let l=null;for(;!B(e);){const c=t&&!Q(e);let m=!1;c&&(t.hold(1)||await H.poolWait({pool:t,count:1,hold:!0}),m=!0);try{if(n!=null?(l=n,n=null):e.state.debugMode||(l=e.variantsIterator.next()),l==null)break;const f=ve(e);if(S.isPromiseLike(f)&&await f,B(e))continue;if(c)yt(e,l),m=!1;else{r.debug&&t&&Q(e)&&r.func("debug",`[test-variants] parallel aborted, running sequential: tests=${i.tests}`);const b=ye(e,l);S.isPromiseLike(b)&&await b}}finally{m&&t.release(1)}}t&&(await H.poolWait({pool:t,count:s,hold:!0}),t.release(s))}function vt(e){const{pool:n,state:t,options:i}=e,{logOptions:o}=i;if(n)return W(e);let s=null;for(;!B(e)&&(e.state.debugMode||(s=e.variantsIterator.next()),s!=null);){const r=ve(e);if(S.isPromiseLike(r))return r.then(()=>W(e,s));if(B(e))continue;o.debug&&Q(e)&&o.func("debug",`[test-variants] parallel aborted, running sequential: tests=${t.tests}`);const l=ye(e,s);if(S.isPromiseLike(l))return l.then(()=>W(e))}}async function Et(e,n,t,i){const o=ct(i),{store:s,logOptions:r,abortSignalExternal:l,findBestError:c,dontThrowIfError:m,timeController:f,parallel:b}=o,y=new z.AbortControllerFast,d=new z.AbortControllerFast,h=S.combineAbortSignals(l,y.signal),v=S.combineAbortSignals(h,d.signal),w={abortSignal:h,timeController:f},p={abortSignal:v,timeController:f};s&&await s.replay({testRun:e,variantsIterator:n,testOptions:w,findBestErrorEnabled:!!c});const M=b<=1?null:new H.Pool(b);pt(r,t.startMemory);const A={options:o,testRun:e,variantsIterator:n,testOptions:w,testOptionsParallel:p,abortControllerGlobal:y,abortControllerParallel:d,abortSignal:v,pool:M,state:t};be(A);try{await vt(A),v.throwIfAborted()}catch(N){throw y.abort(new T),N}return h.throwIfAborted(),y.abort(new T),ht(A),await re(1),lt(t,n,m)}function St(e){return function(t){return async function(o){const s=ge(o?.log),r=tt(e,{onStart:o?.onStart,onEnd:o?.onEnd,onError:o?.onError,log:s,pauseDebuggerOnError:o?.pauseDebuggerOnError}),l=o?.timeController??Y.timeControllerDefault,c=te(),m=Qe(l,c),f=o?.onModeChange;function b(d){m.pendingModeChange=d,f?.(d)}const y=at({argsTemplates:t,getSeed:o?.getSeed,iterationModes:o?.iterationModes,equals:o?.findBestError?.equals,limitArgOnError:o?.findBestError?.limitArgOnError,includeErrorVariant:o?.findBestError?.includeErrorVariant,timeController:l,onModeChange:b,limitCompletionCount:o?.cycles??1,limitTests:o?.limitTests,limitTime:o?.limitTime});return Et(r,y,m,o)}}}exports.createTestVariants=St;
|