@flemist/test-variants 5.0.16 → 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 +14 -6
- 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/-test/invariants/LogInvariant.d.ts +3 -0
- package/build/common/test-variants/iterator/types.d.ts +2 -2
- package/build/common/test-variants/log/format.d.ts +6 -0
- package/build/common/test-variants/run/createRunState.d.ts +1 -1
- package/build/common/test-variants/run/resolveRunOptions.d.ts +1 -0
- package/build/common/test-variants/run/types.d.ts +5 -0
- package/build/common/test-variants/types.d.ts +6 -1
- package/build/createTestVariants-B-tIuCMH.js +4 -0
- package/build/createTestVariants-CHmhRbUZ.mjs +1124 -0
- package/build/node/index.cjs +1 -1
- package/build/node/index.mjs +86 -62
- package/package.json +1 -1
- package/build/createTestVariants-CHE7urh4.js +0 -4
- package/build/createTestVariants-o9_knZSz.mjs +0 -1109
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
|
|
279
|
-
//
|
|
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]
|
|
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]
|
|
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
|
...
|
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-B-tIuCMH.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-B-tIuCMH.js");exports.TimeoutError=e.TimeoutError;exports.createTestVariants=e.createTestVariants;
|
package/build/common/index.mjs
CHANGED
|
@@ -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
|
|
39
|
-
|
|
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(
|
|
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
|
|
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;
|