@flemist/test-variants 2.0.5 → 3.0.1
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/dist/bundle/browser.js +605 -524
- package/dist/lib/index.cjs +2 -1
- package/dist/lib/index.d.ts +2 -1
- package/dist/lib/index.mjs +1 -1
- package/dist/lib/test-variants/createTestVariants.cjs +7 -2
- package/dist/lib/test-variants/createTestVariants.mjs +7 -2
- package/dist/lib/test-variants/createTestVariants.perf.cjs +1 -1
- package/dist/lib/test-variants/createTestVariants.perf.mjs +1 -1
- package/dist/lib/test-variants/testVariantsIterable.cjs +3 -0
- package/dist/lib/test-variants/testVariantsIterable.d.ts +3 -0
- package/dist/lib/test-variants/testVariantsIterable.mjs +3 -0
- package/dist/lib/test-variants/testVariantsIterator.cjs +357 -0
- package/dist/lib/test-variants/testVariantsIterator.d.ts +67 -0
- package/dist/lib/test-variants/testVariantsIterator.mjs +353 -0
- package/dist/lib/test-variants/testVariantsRun.cjs +155 -191
- package/dist/lib/test-variants/testVariantsRun.d.ts +13 -15
- package/dist/lib/test-variants/testVariantsRun.mjs +155 -191
- package/dist/lib/test-variants/types.d.ts +2 -0
- package/package.json +20 -19
|
@@ -48,23 +48,11 @@ function testVariantsRun(testRun, variants, options = {}) {
|
|
|
48
48
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
49
49
|
const saveErrorVariants = options.saveErrorVariants;
|
|
50
50
|
const retriesPerVariant = (_a = saveErrorVariants === null || saveErrorVariants === void 0 ? void 0 : saveErrorVariants.retriesPerVariant) !== null && _a !== void 0 ? _a : 1;
|
|
51
|
+
const useToFindBestError = saveErrorVariants === null || saveErrorVariants === void 0 ? void 0 : saveErrorVariants.useToFindBestError;
|
|
51
52
|
const sessionDate = new Date();
|
|
52
53
|
const errorVariantFilePath = saveErrorVariants
|
|
53
54
|
? path__namespace.resolve(saveErrorVariants.dir, (_c = (_b = saveErrorVariants.getFilePath) === null || _b === void 0 ? void 0 : _b.call(saveErrorVariants, { sessionDate })) !== null && _c !== void 0 ? _c : testVariants_saveErrorVariants.generateErrorVariantFilePath({ sessionDate }))
|
|
54
55
|
: null;
|
|
55
|
-
// Replay phase: run previously saved error variants before normal iteration
|
|
56
|
-
if (saveErrorVariants) {
|
|
57
|
-
const files = yield testVariants_saveErrorVariants.readErrorVariantFiles(saveErrorVariants.dir);
|
|
58
|
-
for (const filePath of files) {
|
|
59
|
-
const args = yield testVariants_saveErrorVariants.parseErrorVariantFile(filePath, saveErrorVariants.jsonToArgs);
|
|
60
|
-
for (let retry = 0; retry < retriesPerVariant; retry++) {
|
|
61
|
-
const promiseOrResult = testRun(args, -1, null);
|
|
62
|
-
if (asyncUtils.isPromiseLike(promiseOrResult)) {
|
|
63
|
-
yield promiseOrResult;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
56
|
const GC_Iterations = (_d = options.GC_Iterations) !== null && _d !== void 0 ? _d : 1000000;
|
|
69
57
|
const GC_IterationsAsync = (_e = options.GC_IterationsAsync) !== null && _e !== void 0 ? _e : 10000;
|
|
70
58
|
const GC_Interval = (_f = options.GC_Interval) !== null && _f !== void 0 ? _f : 1000;
|
|
@@ -72,85 +60,49 @@ function testVariantsRun(testRun, variants, options = {}) {
|
|
|
72
60
|
const logCompleted = (_h = options.logCompleted) !== null && _h !== void 0 ? _h : true;
|
|
73
61
|
const abortSignalExternal = options.abortSignal;
|
|
74
62
|
const findBestError = options.findBestError;
|
|
63
|
+
const cycles = (_j = findBestError === null || findBestError === void 0 ? void 0 : findBestError.cycles) !== null && _j !== void 0 ? _j : 1;
|
|
64
|
+
const dontThrowIfError = findBestError === null || findBestError === void 0 ? void 0 : findBestError.dontThrowIfError;
|
|
65
|
+
const limitTime = options.limitTime;
|
|
75
66
|
const parallel = options.parallel === true
|
|
76
67
|
? Math.pow(2, 31)
|
|
77
68
|
: !options.parallel || options.parallel <= 0
|
|
78
69
|
? 1
|
|
79
70
|
: options.parallel;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
let cycleIndex = 0;
|
|
84
|
-
let repeatIndex = 0;
|
|
85
|
-
const startTime = Date.now();
|
|
86
|
-
let cycleStartTime = startTime;
|
|
87
|
-
let seed = void 0;
|
|
88
|
-
let bestError = null;
|
|
89
|
-
let index = -1;
|
|
90
|
-
let args = {};
|
|
91
|
-
let variantsIterator = variants[Symbol.iterator]();
|
|
92
|
-
function getLimitVariantsCount() {
|
|
93
|
-
if (limitVariantsCount != null && bestError != null) {
|
|
94
|
-
return Math.min(limitVariantsCount, bestError.index);
|
|
95
|
-
}
|
|
96
|
-
if (limitVariantsCount != null) {
|
|
97
|
-
return limitVariantsCount;
|
|
98
|
-
}
|
|
99
|
-
if (bestError != null) {
|
|
100
|
-
return bestError.index;
|
|
101
|
-
}
|
|
102
|
-
return null;
|
|
71
|
+
// Apply initial limits
|
|
72
|
+
if (options.limitVariantsCount != null) {
|
|
73
|
+
variants.addLimit({ index: options.limitVariantsCount });
|
|
103
74
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
});
|
|
116
|
-
return true;
|
|
75
|
+
// Replay phase: run previously saved error variants before normal iteration
|
|
76
|
+
if (saveErrorVariants) {
|
|
77
|
+
const files = yield testVariants_saveErrorVariants.readErrorVariantFiles(saveErrorVariants.dir);
|
|
78
|
+
for (const filePath of files) {
|
|
79
|
+
const args = yield testVariants_saveErrorVariants.parseErrorVariantFile(filePath, saveErrorVariants.jsonToArgs);
|
|
80
|
+
for (let retry = 0; retry < retriesPerVariant; retry++) {
|
|
81
|
+
try {
|
|
82
|
+
const promiseOrResult = testRun(args, -1, null);
|
|
83
|
+
if (asyncUtils.isPromiseLike(promiseOrResult)) {
|
|
84
|
+
yield promiseOrResult;
|
|
85
|
+
}
|
|
117
86
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const result = variantsIterator.next();
|
|
127
|
-
if (!result.done) {
|
|
128
|
-
args = result.value;
|
|
129
|
-
if (findBestError) {
|
|
130
|
-
seed = findBestError.getSeed({
|
|
131
|
-
variantIndex: index,
|
|
132
|
-
cycleIndex,
|
|
133
|
-
repeatIndex,
|
|
134
|
-
totalIndex: cycleIndex * findBestError.repeatsPerVariant + repeatIndex,
|
|
135
|
-
});
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (useToFindBestError && findBestError) {
|
|
89
|
+
// Store as pending limit for findBestError cycle
|
|
90
|
+
variants.addLimit({ args, error });
|
|
91
|
+
break; // Exit retry loop, continue to next file
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
throw error;
|
|
136
95
|
}
|
|
137
|
-
return true;
|
|
138
96
|
}
|
|
139
97
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
prevCycleVariantsCount = index;
|
|
144
|
-
prevCycleDuration = Date.now() - cycleStartTime;
|
|
145
|
-
cycleIndex++;
|
|
146
|
-
cycleStartTime = Date.now();
|
|
147
|
-
if (cycleIndex >= findBestError.cycles) {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
index = -1;
|
|
151
|
-
variantsIterator = variants[Symbol.iterator]();
|
|
98
|
+
// If no error occurred during replays, the saved variant is no longer reproducible
|
|
99
|
+
// (templates may have changed) - silently skip
|
|
152
100
|
}
|
|
153
101
|
}
|
|
102
|
+
let prevCycleVariantsCount = null;
|
|
103
|
+
let prevCycleDuration = null;
|
|
104
|
+
const startTime = Date.now();
|
|
105
|
+
let cycleStartTime = startTime;
|
|
154
106
|
const abortControllerParallel = new abortControllerFast.AbortControllerFast();
|
|
155
107
|
const abortSignalParallel = asyncUtils.combineAbortSignals(abortSignalExternal, abortControllerParallel.signal);
|
|
156
108
|
const abortSignalAll = abortSignalParallel;
|
|
@@ -166,67 +118,110 @@ function testVariantsRun(testRun, variants, options = {}) {
|
|
|
166
118
|
: new timeLimits.Pool(parallel);
|
|
167
119
|
function onCompleted() {
|
|
168
120
|
if (logCompleted) {
|
|
169
|
-
console.log(`[test-variants] variants: ${index}, iterations: ${iterations}, async: ${iterationsAsync}`);
|
|
121
|
+
console.log(`[test-variants] variants: ${variants.index}, iterations: ${iterations}, async: ${iterationsAsync}`);
|
|
170
122
|
}
|
|
171
123
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
124
|
+
// Main iteration using iterator
|
|
125
|
+
let timeLimitExceeded = false;
|
|
126
|
+
variants.start();
|
|
127
|
+
while (variants.cycleIndex < cycles && !timeLimitExceeded) {
|
|
128
|
+
let args;
|
|
129
|
+
while (!(abortSignalExternal === null || abortSignalExternal === void 0 ? void 0 : abortSignalExternal.aborted) && (debug || (args = variants.next()) != null)) {
|
|
130
|
+
const _index = variants.index;
|
|
131
|
+
const _args = args;
|
|
132
|
+
const now = (logInterval || GC_Interval || limitTime) && Date.now();
|
|
133
|
+
if (limitTime && now - startTime >= limitTime) {
|
|
134
|
+
timeLimitExceeded = true;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
if (logInterval && now - prevLogTime >= logInterval) {
|
|
138
|
+
// the log is required to prevent the karma browserNoActivityTimeout
|
|
139
|
+
let log = '';
|
|
140
|
+
const cycleElapsed = now - cycleStartTime;
|
|
141
|
+
const totalElapsed = now - startTime;
|
|
142
|
+
if (findBestError) {
|
|
143
|
+
log += `cycle: ${variants.cycleIndex}, variant: ${variants.index}`;
|
|
144
|
+
let max = variants.count;
|
|
145
|
+
if (max != null) {
|
|
146
|
+
if (prevCycleVariantsCount != null && prevCycleVariantsCount < max) {
|
|
147
|
+
max = prevCycleVariantsCount;
|
|
190
148
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
else {
|
|
202
|
-
estimatedCycleTime = cycleElapsed * max / index;
|
|
203
|
-
}
|
|
204
|
-
log += `/${max} (${formatDuration(cycleElapsed)}/${formatDuration(estimatedCycleTime)})`;
|
|
149
|
+
}
|
|
150
|
+
if (max != null && variants.index > 0) {
|
|
151
|
+
let estimatedCycleTime;
|
|
152
|
+
if (prevCycleDuration != null && prevCycleVariantsCount != null
|
|
153
|
+
&& variants.index < prevCycleVariantsCount && cycleElapsed < prevCycleDuration) {
|
|
154
|
+
const adjustedDuration = prevCycleDuration - cycleElapsed;
|
|
155
|
+
const adjustedCount = prevCycleVariantsCount - variants.index;
|
|
156
|
+
const speedForRemaining = adjustedDuration / adjustedCount;
|
|
157
|
+
const remainingTime = (max - variants.index) * speedForRemaining;
|
|
158
|
+
estimatedCycleTime = cycleElapsed + remainingTime;
|
|
205
159
|
}
|
|
206
160
|
else {
|
|
207
|
-
|
|
161
|
+
estimatedCycleTime = cycleElapsed * max / variants.index;
|
|
208
162
|
}
|
|
163
|
+
log += `/${max} (${formatDuration(cycleElapsed)}/${formatDuration(estimatedCycleTime)})`;
|
|
209
164
|
}
|
|
210
165
|
else {
|
|
211
|
-
log += `
|
|
166
|
+
log += ` (${formatDuration(cycleElapsed)})`;
|
|
212
167
|
}
|
|
213
|
-
log += `, total: ${iterations} (${formatDuration(totalElapsed)})`;
|
|
214
|
-
console.log(log);
|
|
215
|
-
prevLogTime = now;
|
|
216
168
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|| GC_Interval && now - prevGC_Time >= GC_Interval) {
|
|
220
|
-
prevGC_Iterations = iterations;
|
|
221
|
-
prevGC_IterationsAsync = iterationsAsync;
|
|
222
|
-
prevGC_Time = now;
|
|
223
|
-
yield garbageCollect_garbageCollect.garbageCollect(1);
|
|
169
|
+
else {
|
|
170
|
+
log += `variant: ${variants.index} (${formatDuration(cycleElapsed)})`;
|
|
224
171
|
}
|
|
225
|
-
|
|
226
|
-
|
|
172
|
+
log += `, total: ${iterations} (${formatDuration(totalElapsed)})`;
|
|
173
|
+
console.log(log);
|
|
174
|
+
prevLogTime = now;
|
|
175
|
+
}
|
|
176
|
+
if (GC_Iterations && iterations - prevGC_Iterations >= GC_Iterations
|
|
177
|
+
|| GC_IterationsAsync && iterationsAsync - prevGC_IterationsAsync >= GC_IterationsAsync
|
|
178
|
+
|| GC_Interval && now - prevGC_Time >= GC_Interval) {
|
|
179
|
+
prevGC_Iterations = iterations;
|
|
180
|
+
prevGC_IterationsAsync = iterationsAsync;
|
|
181
|
+
prevGC_Time = now;
|
|
182
|
+
yield garbageCollect_garbageCollect.garbageCollect(1);
|
|
183
|
+
}
|
|
184
|
+
if (abortSignalExternal === null || abortSignalExternal === void 0 ? void 0 : abortSignalExternal.aborted) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (!pool || abortSignalParallel.aborted) {
|
|
188
|
+
try {
|
|
189
|
+
let promiseOrIterations = testRun(_args, _index, abortSignalParallel);
|
|
190
|
+
if (asyncUtils.isPromiseLike(promiseOrIterations)) {
|
|
191
|
+
promiseOrIterations = yield promiseOrIterations;
|
|
192
|
+
}
|
|
193
|
+
if (!promiseOrIterations) {
|
|
194
|
+
debug = true;
|
|
195
|
+
abortControllerParallel.abort();
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const { iterationsAsync: _iterationsAsync, iterationsSync: _iterationsSync } = promiseOrIterations;
|
|
199
|
+
iterationsAsync += _iterationsAsync;
|
|
200
|
+
iterations += _iterationsSync + _iterationsAsync;
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
if (errorVariantFilePath) {
|
|
204
|
+
yield testVariants_saveErrorVariants.saveErrorVariantFile(_args, errorVariantFilePath, saveErrorVariants.argsToJson);
|
|
205
|
+
}
|
|
206
|
+
if (findBestError) {
|
|
207
|
+
variants.addLimit({ error: err });
|
|
208
|
+
debug = false;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
throw err;
|
|
212
|
+
}
|
|
227
213
|
}
|
|
228
|
-
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
if (!pool.hold(1)) {
|
|
217
|
+
yield pool.holdWait(1);
|
|
218
|
+
}
|
|
219
|
+
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
220
|
+
void (() => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
229
221
|
try {
|
|
222
|
+
if (abortSignalParallel === null || abortSignalParallel === void 0 ? void 0 : abortSignalParallel.aborted) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
230
225
|
let promiseOrIterations = testRun(_args, _index, abortSignalParallel);
|
|
231
226
|
if (asyncUtils.isPromiseLike(promiseOrIterations)) {
|
|
232
227
|
promiseOrIterations = yield promiseOrIterations;
|
|
@@ -234,7 +229,7 @@ function testVariantsRun(testRun, variants, options = {}) {
|
|
|
234
229
|
if (!promiseOrIterations) {
|
|
235
230
|
debug = true;
|
|
236
231
|
abortControllerParallel.abort();
|
|
237
|
-
|
|
232
|
+
return;
|
|
238
233
|
}
|
|
239
234
|
const { iterationsAsync: _iterationsAsync, iterationsSync: _iterationsSync } = promiseOrIterations;
|
|
240
235
|
iterationsAsync += _iterationsAsync;
|
|
@@ -245,78 +240,47 @@ function testVariantsRun(testRun, variants, options = {}) {
|
|
|
245
240
|
yield testVariants_saveErrorVariants.saveErrorVariantFile(_args, errorVariantFilePath, saveErrorVariants.argsToJson);
|
|
246
241
|
}
|
|
247
242
|
if (findBestError) {
|
|
248
|
-
|
|
249
|
-
error: err,
|
|
250
|
-
args: _args,
|
|
251
|
-
index: _index,
|
|
252
|
-
};
|
|
243
|
+
variants.addLimit({ error: err });
|
|
253
244
|
debug = false;
|
|
254
245
|
}
|
|
255
246
|
else {
|
|
256
247
|
throw err;
|
|
257
248
|
}
|
|
258
249
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (!pool.hold(1)) {
|
|
262
|
-
yield pool.holdWait(1);
|
|
250
|
+
finally {
|
|
251
|
+
void pool.release(1);
|
|
263
252
|
}
|
|
264
|
-
|
|
265
|
-
void (() => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
266
|
-
try {
|
|
267
|
-
if (abortSignalParallel === null || abortSignalParallel === void 0 ? void 0 : abortSignalParallel.aborted) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
let promiseOrIterations = testRun(_args, _index, abortSignalParallel);
|
|
271
|
-
if (asyncUtils.isPromiseLike(promiseOrIterations)) {
|
|
272
|
-
promiseOrIterations = yield promiseOrIterations;
|
|
273
|
-
}
|
|
274
|
-
if (!promiseOrIterations) {
|
|
275
|
-
debug = true;
|
|
276
|
-
abortControllerParallel.abort();
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
const { iterationsAsync: _iterationsAsync, iterationsSync: _iterationsSync } = promiseOrIterations;
|
|
280
|
-
iterationsAsync += _iterationsAsync;
|
|
281
|
-
iterations += _iterationsSync + _iterationsAsync;
|
|
282
|
-
}
|
|
283
|
-
catch (err) {
|
|
284
|
-
if (errorVariantFilePath) {
|
|
285
|
-
yield testVariants_saveErrorVariants.saveErrorVariantFile(_args, errorVariantFilePath, saveErrorVariants.argsToJson);
|
|
286
|
-
}
|
|
287
|
-
if (findBestError) {
|
|
288
|
-
bestError = {
|
|
289
|
-
error: err,
|
|
290
|
-
args: _args,
|
|
291
|
-
index: _index,
|
|
292
|
-
};
|
|
293
|
-
debug = false;
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
throw err;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
finally {
|
|
300
|
-
void pool.release(1);
|
|
301
|
-
}
|
|
302
|
-
}))();
|
|
303
|
-
}
|
|
253
|
+
}))();
|
|
304
254
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
255
|
+
}
|
|
256
|
+
// Track cycle metrics for logging
|
|
257
|
+
prevCycleVariantsCount = variants.count;
|
|
258
|
+
prevCycleDuration = Date.now() - cycleStartTime;
|
|
259
|
+
cycleStartTime = Date.now();
|
|
260
|
+
variants.start();
|
|
261
|
+
}
|
|
262
|
+
if (pool) {
|
|
263
|
+
yield pool.holdWait(parallel);
|
|
264
|
+
void pool.release(parallel);
|
|
265
|
+
}
|
|
266
|
+
if (abortSignalAll === null || abortSignalAll === void 0 ? void 0 : abortSignalAll.aborted) {
|
|
267
|
+
throw abortSignalAll.reason;
|
|
268
|
+
}
|
|
269
|
+
onCompleted();
|
|
270
|
+
yield garbageCollect_garbageCollect.garbageCollect(1);
|
|
271
|
+
// Construct bestError from iterator state
|
|
272
|
+
const bestError = variants.limit
|
|
273
|
+
? {
|
|
274
|
+
error: variants.limit.error,
|
|
275
|
+
args: variants.limit.args,
|
|
276
|
+
index: variants.count,
|
|
277
|
+
}
|
|
278
|
+
: null;
|
|
279
|
+
if (bestError && !dontThrowIfError) {
|
|
280
|
+
throw bestError.error;
|
|
316
281
|
}
|
|
317
|
-
const result = yield next();
|
|
318
282
|
return {
|
|
319
|
-
iterations
|
|
283
|
+
iterations,
|
|
320
284
|
bestError,
|
|
321
285
|
};
|
|
322
286
|
});
|
|
@@ -1,25 +1,21 @@
|
|
|
1
1
|
import { TestVariantsTestRun } from './testVariantsCreateTestRun';
|
|
2
2
|
import { type IAbortSignalFast } from '@flemist/abort-controller-fast';
|
|
3
3
|
import { Obj, type SaveErrorVariantsOptions } from "./types";
|
|
4
|
-
|
|
5
|
-
export declare type GetSeedParams = {
|
|
6
|
-
/** Index of current variant/parameter-combination being tested */
|
|
7
|
-
variantIndex: number;
|
|
8
|
-
/** Index of current cycle - full pass through all variants (0..cycles-1) */
|
|
9
|
-
cycleIndex: number;
|
|
10
|
-
/** Index of repeat for current variant within this cycle (0..repeatsPerVariant-1) */
|
|
11
|
-
repeatIndex: number;
|
|
12
|
-
/** Total index across all cycles: cycleIndex × repeatsPerVariant + repeatIndex */
|
|
13
|
-
totalIndex: number;
|
|
14
|
-
};
|
|
4
|
+
import { TestVariantsIterator, type GetSeedParams, type LimitArgOnError } from './testVariantsIterator';
|
|
15
5
|
/** Options for finding the earliest failing variant across multiple test runs */
|
|
16
6
|
export declare type TestVariantsFindBestErrorOptions = {
|
|
17
|
-
/** Function to generate seed based on current iteration state */
|
|
18
|
-
getSeed: (params: GetSeedParams) => any;
|
|
19
7
|
/** Number of full passes through all variants */
|
|
20
8
|
cycles: number;
|
|
9
|
+
/** Generates seed for reproducible randomized testing; seed is added to args */
|
|
10
|
+
getSeed?: null | ((params: GetSeedParams) => any);
|
|
21
11
|
/** Number of repeat tests per variant within each cycle */
|
|
22
|
-
repeatsPerVariant
|
|
12
|
+
repeatsPerVariant?: null | number;
|
|
13
|
+
/** Custom equality for comparing arg values when finding indexes */
|
|
14
|
+
equals?: null | ((a: any, b: any) => boolean);
|
|
15
|
+
/** Limit per-arg indexes on error; boolean enables/disables, function for custom per-arg logic */
|
|
16
|
+
limitArgOnError?: null | boolean | LimitArgOnError;
|
|
17
|
+
/** Return found error instead of throwing after all cycles complete */
|
|
18
|
+
dontThrowIfError?: null | boolean;
|
|
23
19
|
};
|
|
24
20
|
export declare type TestVariantsRunOptions<Args extends Obj = Obj, SavedArgs = Args> = {
|
|
25
21
|
/** Wait for garbage collection after iterations */
|
|
@@ -39,6 +35,8 @@ export declare type TestVariantsRunOptions<Args extends Obj = Obj, SavedArgs = A
|
|
|
39
35
|
saveErrorVariants?: null | SaveErrorVariantsOptions<Args, SavedArgs>;
|
|
40
36
|
/** Tests only first N variants, ignores the rest. If null or not specified, tests all variants */
|
|
41
37
|
limitVariantsCount?: null | number;
|
|
38
|
+
/** Maximum test run duration in milliseconds; when exceeded, iteration stops and current results are returned */
|
|
39
|
+
limitTime?: null | number;
|
|
42
40
|
};
|
|
43
41
|
export declare type TestVariantsBestError<Args extends Obj> = {
|
|
44
42
|
error: any;
|
|
@@ -49,4 +47,4 @@ export declare type TestVariantsRunResult<Arg extends Obj> = {
|
|
|
49
47
|
iterations: number;
|
|
50
48
|
bestError: null | TestVariantsBestError<Arg>;
|
|
51
49
|
};
|
|
52
|
-
export declare function testVariantsRun<Args extends Obj, SavedArgs = Args>(testRun: TestVariantsTestRun<Args>, variants:
|
|
50
|
+
export declare function testVariantsRun<Args extends Obj, SavedArgs = Args>(testRun: TestVariantsTestRun<Args>, variants: TestVariantsIterator<Args>, options?: TestVariantsRunOptions<Args, SavedArgs>): Promise<TestVariantsRunResult<Args>>;
|