@jsenv/test 1.8.0 → 1.8.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/jsenv_test.js +122 -59
- package/package.json +3 -3
- package/src/execution/execute_test_plan.js +78 -59
- package/src/helpers/call_orderer.js +39 -0
package/dist/jsenv_test.js
CHANGED
|
@@ -2515,6 +2515,7 @@ const createLog = ({
|
|
|
2515
2515
|
const { columns = 80, rows = 24 } = stream;
|
|
2516
2516
|
|
|
2517
2517
|
const log = {
|
|
2518
|
+
destroyed: false,
|
|
2518
2519
|
onVerticalOverflow: () => {},
|
|
2519
2520
|
};
|
|
2520
2521
|
|
|
@@ -2579,6 +2580,9 @@ const createLog = ({
|
|
|
2579
2580
|
};
|
|
2580
2581
|
|
|
2581
2582
|
const write = (string, outputFromOutside = streamOutputSpy()) => {
|
|
2583
|
+
if (log.destroyed) {
|
|
2584
|
+
throw new Error("Cannot write log after destroy");
|
|
2585
|
+
}
|
|
2582
2586
|
if (!lastOutput) {
|
|
2583
2587
|
doWrite(string);
|
|
2584
2588
|
return;
|
|
@@ -2599,6 +2603,7 @@ const createLog = ({
|
|
|
2599
2603
|
};
|
|
2600
2604
|
|
|
2601
2605
|
const destroy = () => {
|
|
2606
|
+
log.destroyed = true;
|
|
2602
2607
|
if (streamOutputSpy) {
|
|
2603
2608
|
streamOutputSpy(); // this uninstalls the spy
|
|
2604
2609
|
streamOutputSpy = null;
|
|
@@ -2724,6 +2729,46 @@ const createTeardown = () => {
|
|
|
2724
2729
|
};
|
|
2725
2730
|
};
|
|
2726
2731
|
|
|
2732
|
+
const createCallOrderer = () => {
|
|
2733
|
+
const queue = [];
|
|
2734
|
+
const callWhenPreviousExecutionAreDone = (executionIndex, callback) => {
|
|
2735
|
+
if (queue[executionIndex]) {
|
|
2736
|
+
throw new Error(`${executionIndex} already used`);
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
let allBeforeAreDone = true;
|
|
2740
|
+
if (executionIndex > 0) {
|
|
2741
|
+
let beforeIndex = executionIndex - 1;
|
|
2742
|
+
do {
|
|
2743
|
+
const value = queue[beforeIndex];
|
|
2744
|
+
if (!value) {
|
|
2745
|
+
allBeforeAreDone = false;
|
|
2746
|
+
break;
|
|
2747
|
+
}
|
|
2748
|
+
} while (beforeIndex--);
|
|
2749
|
+
}
|
|
2750
|
+
if (!allBeforeAreDone) {
|
|
2751
|
+
queue[executionIndex] = callback;
|
|
2752
|
+
return;
|
|
2753
|
+
}
|
|
2754
|
+
queue[executionIndex] = true;
|
|
2755
|
+
callback();
|
|
2756
|
+
let afterIndex = executionIndex + 1;
|
|
2757
|
+
while (afterIndex < queue.length) {
|
|
2758
|
+
const value = queue[afterIndex];
|
|
2759
|
+
if (value === undefined) {
|
|
2760
|
+
break;
|
|
2761
|
+
}
|
|
2762
|
+
if (typeof value === "function") {
|
|
2763
|
+
queue[afterIndex] = true;
|
|
2764
|
+
value();
|
|
2765
|
+
}
|
|
2766
|
+
afterIndex++;
|
|
2767
|
+
}
|
|
2768
|
+
};
|
|
2769
|
+
return callWhenPreviousExecutionAreDone;
|
|
2770
|
+
};
|
|
2771
|
+
|
|
2727
2772
|
const readNodeV8CoverageDirectory = async ({
|
|
2728
2773
|
logger,
|
|
2729
2774
|
signal,
|
|
@@ -4686,6 +4731,13 @@ const executeTestPlan = async ({
|
|
|
4686
4731
|
}) => {
|
|
4687
4732
|
const teardown = createTeardown();
|
|
4688
4733
|
|
|
4734
|
+
const beforeExecutionCallbackSet = new Set();
|
|
4735
|
+
const afterExecutionCallbackSet = new Set();
|
|
4736
|
+
const afterAllExecutionCallbackSet = new Set();
|
|
4737
|
+
beforeExecutionCallbackSet.add(beforeExecutionCallback);
|
|
4738
|
+
afterExecutionCallbackSet.add(afterExecutionCallback);
|
|
4739
|
+
afterAllExecutionCallbackSet.add(afterAllExecutionCallback);
|
|
4740
|
+
|
|
4689
4741
|
const operation = Abort.startOperation();
|
|
4690
4742
|
operation.addAbortSignal(signal);
|
|
4691
4743
|
if (handleSIGINT) {
|
|
@@ -4943,9 +4995,7 @@ To fix this warning:
|
|
|
4943
4995
|
checkSummary: `${executionSteps.length} files will be executed`,
|
|
4944
4996
|
});
|
|
4945
4997
|
const annotations = [];
|
|
4946
|
-
|
|
4947
|
-
afterExecutionCallback = (afterExecutionInfo) => {
|
|
4948
|
-
afterExecutionCallbackPrevious(afterExecutionInfo);
|
|
4998
|
+
afterExecutionCallbackSet.add((afterExecutionInfo) => {
|
|
4949
4999
|
const { executionResult } = afterExecutionInfo;
|
|
4950
5000
|
const { errors = [] } = executionResult;
|
|
4951
5001
|
for (const error of errors) {
|
|
@@ -4955,10 +5005,8 @@ To fix this warning:
|
|
|
4955
5005
|
});
|
|
4956
5006
|
annotations.push(annotation);
|
|
4957
5007
|
}
|
|
4958
|
-
};
|
|
4959
|
-
|
|
4960
|
-
afterAllExecutionCallback = async (returnValue) => {
|
|
4961
|
-
afterAllExecutionCallbackPrevious(returnValue);
|
|
5008
|
+
});
|
|
5009
|
+
afterAllExecutionCallbackSet.add(async (returnValue) => {
|
|
4962
5010
|
const { summary } = returnValue;
|
|
4963
5011
|
const title = "Jsenv test results";
|
|
4964
5012
|
const summaryText = stripAnsi(formatSummary(summary));
|
|
@@ -4975,7 +5023,7 @@ To fix this warning:
|
|
|
4975
5023
|
summary: summaryText,
|
|
4976
5024
|
annotations,
|
|
4977
5025
|
});
|
|
4978
|
-
};
|
|
5026
|
+
});
|
|
4979
5027
|
}
|
|
4980
5028
|
|
|
4981
5029
|
executionSteps = executionSteps.filter(
|
|
@@ -5059,6 +5107,7 @@ To fix this warning:
|
|
|
5059
5107
|
const executionLogsEnabled = logger.levels.info;
|
|
5060
5108
|
const executionSpinner =
|
|
5061
5109
|
logRefresh &&
|
|
5110
|
+
maxExecutionsInParallel === 1 &&
|
|
5062
5111
|
!debugLogsEnabled &&
|
|
5063
5112
|
executionLogsEnabled &&
|
|
5064
5113
|
process.stdout.isTTY &&
|
|
@@ -5078,6 +5127,9 @@ To fix this warning:
|
|
|
5078
5127
|
completed: 0,
|
|
5079
5128
|
done: 0,
|
|
5080
5129
|
};
|
|
5130
|
+
|
|
5131
|
+
const callWhenPreviousExecutionAreDone = createCallOrderer();
|
|
5132
|
+
|
|
5081
5133
|
await executeInParallel({
|
|
5082
5134
|
multipleExecutionsOperation,
|
|
5083
5135
|
maxExecutionsInParallel,
|
|
@@ -5133,8 +5185,9 @@ To fix this warning:
|
|
|
5133
5185
|
},
|
|
5134
5186
|
});
|
|
5135
5187
|
}
|
|
5136
|
-
beforeExecutionCallback
|
|
5137
|
-
|
|
5188
|
+
for (const beforeExecutionCallback of beforeExecutionCallbackSet) {
|
|
5189
|
+
beforeExecutionCallback(beforeExecutionInfo);
|
|
5190
|
+
}
|
|
5138
5191
|
const fileUrl = `${rootDirectoryUrl}${fileRelativeUrl}`;
|
|
5139
5192
|
let executionResult;
|
|
5140
5193
|
if (existsSync(new URL(fileUrl))) {
|
|
@@ -5143,7 +5196,7 @@ To fix this warning:
|
|
|
5143
5196
|
logger,
|
|
5144
5197
|
allocatedMs: executionParams.allocatedMs,
|
|
5145
5198
|
keepRunning,
|
|
5146
|
-
mirrorConsole: false, //
|
|
5199
|
+
mirrorConsole: false, // might be executed in parallel: log would be a mess to read
|
|
5147
5200
|
collectConsole: executionParams.collectConsole,
|
|
5148
5201
|
coverageEnabled,
|
|
5149
5202
|
coverageTempDirectoryUrl,
|
|
@@ -5163,7 +5216,6 @@ To fix this warning:
|
|
|
5163
5216
|
],
|
|
5164
5217
|
};
|
|
5165
5218
|
}
|
|
5166
|
-
counters.done++;
|
|
5167
5219
|
const fileReport = report[fileRelativeUrl];
|
|
5168
5220
|
if (fileReport) {
|
|
5169
5221
|
fileReport[executionName] = executionResult;
|
|
@@ -5180,58 +5232,65 @@ To fix this warning:
|
|
|
5180
5232
|
executionResult,
|
|
5181
5233
|
};
|
|
5182
5234
|
|
|
5183
|
-
if (executionResult.status === "aborted") {
|
|
5184
|
-
counters.aborted++;
|
|
5185
|
-
} else if (executionResult.status === "timedout") {
|
|
5186
|
-
counters.timedout++;
|
|
5187
|
-
} else if (executionResult.status === "failed") {
|
|
5188
|
-
counters.failed++;
|
|
5189
|
-
} else if (executionResult.status === "completed") {
|
|
5190
|
-
counters.completed++;
|
|
5191
|
-
}
|
|
5192
5235
|
if (gcBetweenExecutions) {
|
|
5193
5236
|
global.gc();
|
|
5194
5237
|
}
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
}
|
|
5209
|
-
|
|
5210
|
-
if (
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5238
|
+
|
|
5239
|
+
const timeEllapsed = Date.now() - startMs;
|
|
5240
|
+
const memoryHeap = memoryUsage().heapUsed;
|
|
5241
|
+
callWhenPreviousExecutionAreDone(executionIndex, () => {
|
|
5242
|
+
counters.done++;
|
|
5243
|
+
if (executionResult.status === "aborted") {
|
|
5244
|
+
counters.aborted++;
|
|
5245
|
+
} else if (executionResult.status === "timedout") {
|
|
5246
|
+
counters.timedout++;
|
|
5247
|
+
} else if (executionResult.status === "failed") {
|
|
5248
|
+
counters.failed++;
|
|
5249
|
+
} else if (executionResult.status === "completed") {
|
|
5250
|
+
counters.completed++;
|
|
5251
|
+
}
|
|
5252
|
+
|
|
5253
|
+
if (executionLogsEnabled) {
|
|
5254
|
+
// replace spinner with this execution result
|
|
5255
|
+
if (spinner) {
|
|
5256
|
+
spinner.stop();
|
|
5257
|
+
spinner = null;
|
|
5258
|
+
}
|
|
5259
|
+
|
|
5260
|
+
const log = createExecutionLog(afterExecutionInfo, {
|
|
5261
|
+
logShortForCompletedExecutions,
|
|
5262
|
+
logRuntime,
|
|
5263
|
+
logEachDuration,
|
|
5264
|
+
...(logTimeUsage ? { timeEllapsed } : {}),
|
|
5265
|
+
...(logMemoryHeapUsage ? { memoryHeap } : {}),
|
|
5266
|
+
});
|
|
5267
|
+
|
|
5268
|
+
executionLog.write(log);
|
|
5269
|
+
rawOutput += stripAnsi(log);
|
|
5270
|
+
const canOverwriteLog = canOverwriteLogGetter({
|
|
5271
|
+
logMergeForCompletedExecutions,
|
|
5272
|
+
executionResult,
|
|
5273
|
+
});
|
|
5274
|
+
if (canOverwriteLog) {
|
|
5275
|
+
// nothing to do, we reuse the current executionLog object
|
|
5276
|
+
} else {
|
|
5277
|
+
executionLog.destroy();
|
|
5278
|
+
executionLog = createLog({ newLine: "" });
|
|
5279
|
+
}
|
|
5280
|
+
const isLastExecutionLog =
|
|
5281
|
+
executionIndex === executionSteps.length - 1;
|
|
5282
|
+
if (isLastExecutionLog && logger.levels.info) {
|
|
5283
|
+
executionLog.write("\n");
|
|
5284
|
+
}
|
|
5223
5285
|
}
|
|
5286
|
+
});
|
|
5287
|
+
for (const afterExecutionCallback of afterExecutionCallbackSet) {
|
|
5288
|
+
afterExecutionCallback(afterExecutionInfo);
|
|
5224
5289
|
}
|
|
5225
|
-
afterExecutionCallback(afterExecutionInfo);
|
|
5226
|
-
const isLastExecutionLog = executionIndex === executionSteps.length - 1;
|
|
5227
5290
|
const cancelRemaining =
|
|
5228
5291
|
failFast &&
|
|
5229
5292
|
executionResult.status !== "completed" &&
|
|
5230
5293
|
counters.done < counters.total;
|
|
5231
|
-
if (isLastExecutionLog && logger.levels.info) {
|
|
5232
|
-
executionLog.write("\n");
|
|
5233
|
-
}
|
|
5234
|
-
|
|
5235
5294
|
if (cancelRemaining) {
|
|
5236
5295
|
logger.info(`"failFast" enabled -> cancel remaining executions`);
|
|
5237
5296
|
failFastAbortController.abort();
|
|
@@ -5320,7 +5379,9 @@ To fix this warning:
|
|
|
5320
5379
|
await Promise.all(promises);
|
|
5321
5380
|
}
|
|
5322
5381
|
|
|
5323
|
-
|
|
5382
|
+
for (const afterAllExecutionCallback of afterAllExecutionCallbackSet) {
|
|
5383
|
+
await afterAllExecutionCallback(returnValue);
|
|
5384
|
+
}
|
|
5324
5385
|
return returnValue;
|
|
5325
5386
|
};
|
|
5326
5387
|
|
|
@@ -5360,12 +5421,14 @@ const executeInParallel = async ({
|
|
|
5360
5421
|
return;
|
|
5361
5422
|
}
|
|
5362
5423
|
const outputPromiseArray = [];
|
|
5424
|
+
let previousExecPromise = Promise.resolve();
|
|
5363
5425
|
while (
|
|
5364
5426
|
remainingExecutionCount > 0 &&
|
|
5365
5427
|
outputPromiseArray.length < maxExecutionsInParallel
|
|
5366
5428
|
) {
|
|
5367
5429
|
remainingExecutionCount--;
|
|
5368
|
-
const outputPromise = executeOne(progressionIndex);
|
|
5430
|
+
const outputPromise = executeOne(progressionIndex, previousExecPromise);
|
|
5431
|
+
previousExecPromise = outputPromise;
|
|
5369
5432
|
progressionIndex++;
|
|
5370
5433
|
outputPromiseArray.push(outputPromise);
|
|
5371
5434
|
}
|
|
@@ -5377,9 +5440,9 @@ const executeInParallel = async ({
|
|
|
5377
5440
|
}
|
|
5378
5441
|
};
|
|
5379
5442
|
|
|
5380
|
-
const executeOne = async (index) => {
|
|
5443
|
+
const executeOne = async (index, previousExecPromise) => {
|
|
5381
5444
|
const input = executionSteps[index];
|
|
5382
|
-
const output = await start(input);
|
|
5445
|
+
const output = await start(input, previousExecPromise);
|
|
5383
5446
|
if (!multipleExecutionsOperation.signal.aborted) {
|
|
5384
5447
|
executionResults[index] = output;
|
|
5385
5448
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/test",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"@jsenv/abort": "4.2.4",
|
|
37
37
|
"@jsenv/ast": "6.0.1",
|
|
38
38
|
"@jsenv/filesystem": "4.3.2",
|
|
39
|
-
"@jsenv/log": "3.4.
|
|
39
|
+
"@jsenv/log": "3.4.3",
|
|
40
40
|
"@jsenv/plugin-supervisor": "1.3.9",
|
|
41
41
|
"@jsenv/urls": "2.2.1",
|
|
42
42
|
"@jsenv/url-meta": "8.1.0",
|
|
43
43
|
"@jsenv/utils": "2.0.1",
|
|
44
|
-
"@jsenv/github-check-run": "0.1.
|
|
44
|
+
"@jsenv/github-check-run": "0.1.4",
|
|
45
45
|
"v8-to-istanbul": "9.1.3",
|
|
46
46
|
"istanbul-lib-coverage": "3.2.2",
|
|
47
47
|
"istanbul-lib-instrument": "6.0.1",
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
} from "@jsenv/github-check-run";
|
|
25
25
|
|
|
26
26
|
import { createTeardown } from "../helpers/teardown.js";
|
|
27
|
+
import { createCallOrderer } from "../helpers/call_orderer.js";
|
|
27
28
|
import { reportToCoverage } from "../coverage/report_to_coverage.js";
|
|
28
29
|
import { generateCoverageJsonFile } from "../coverage/coverage_reporter_json_file.js";
|
|
29
30
|
import { generateCoverageHtmlDirectory } from "../coverage/coverage_reporter_html_directory.js";
|
|
@@ -142,6 +143,13 @@ export const executeTestPlan = async ({
|
|
|
142
143
|
}) => {
|
|
143
144
|
const teardown = createTeardown();
|
|
144
145
|
|
|
146
|
+
const beforeExecutionCallbackSet = new Set();
|
|
147
|
+
const afterExecutionCallbackSet = new Set();
|
|
148
|
+
const afterAllExecutionCallbackSet = new Set();
|
|
149
|
+
beforeExecutionCallbackSet.add(beforeExecutionCallback);
|
|
150
|
+
afterExecutionCallbackSet.add(afterExecutionCallback);
|
|
151
|
+
afterAllExecutionCallbackSet.add(afterAllExecutionCallback);
|
|
152
|
+
|
|
145
153
|
const operation = Abort.startOperation();
|
|
146
154
|
operation.addAbortSignal(signal);
|
|
147
155
|
if (handleSIGINT) {
|
|
@@ -399,9 +407,7 @@ To fix this warning:
|
|
|
399
407
|
checkSummary: `${executionSteps.length} files will be executed`,
|
|
400
408
|
});
|
|
401
409
|
const annotations = [];
|
|
402
|
-
|
|
403
|
-
afterExecutionCallback = (afterExecutionInfo) => {
|
|
404
|
-
afterExecutionCallbackPrevious(afterExecutionInfo);
|
|
410
|
+
afterExecutionCallbackSet.add((afterExecutionInfo) => {
|
|
405
411
|
const { executionResult } = afterExecutionInfo;
|
|
406
412
|
const { errors = [] } = executionResult;
|
|
407
413
|
for (const error of errors) {
|
|
@@ -411,10 +417,8 @@ To fix this warning:
|
|
|
411
417
|
});
|
|
412
418
|
annotations.push(annotation);
|
|
413
419
|
}
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
afterAllExecutionCallback = async (returnValue) => {
|
|
417
|
-
afterAllExecutionCallbackPrevious(returnValue);
|
|
420
|
+
});
|
|
421
|
+
afterAllExecutionCallbackSet.add(async (returnValue) => {
|
|
418
422
|
const { summary } = returnValue;
|
|
419
423
|
const title = "Jsenv test results";
|
|
420
424
|
const summaryText = stripAnsi(formatSummary(summary));
|
|
@@ -431,7 +435,7 @@ To fix this warning:
|
|
|
431
435
|
summary: summaryText,
|
|
432
436
|
annotations,
|
|
433
437
|
});
|
|
434
|
-
};
|
|
438
|
+
});
|
|
435
439
|
}
|
|
436
440
|
|
|
437
441
|
executionSteps = executionSteps.filter(
|
|
@@ -515,6 +519,7 @@ To fix this warning:
|
|
|
515
519
|
const executionLogsEnabled = logger.levels.info;
|
|
516
520
|
const executionSpinner =
|
|
517
521
|
logRefresh &&
|
|
522
|
+
maxExecutionsInParallel === 1 &&
|
|
518
523
|
!debugLogsEnabled &&
|
|
519
524
|
executionLogsEnabled &&
|
|
520
525
|
process.stdout.isTTY &&
|
|
@@ -534,6 +539,9 @@ To fix this warning:
|
|
|
534
539
|
completed: 0,
|
|
535
540
|
done: 0,
|
|
536
541
|
};
|
|
542
|
+
|
|
543
|
+
const callWhenPreviousExecutionAreDone = createCallOrderer();
|
|
544
|
+
|
|
537
545
|
await executeInParallel({
|
|
538
546
|
multipleExecutionsOperation,
|
|
539
547
|
maxExecutionsInParallel,
|
|
@@ -589,8 +597,9 @@ To fix this warning:
|
|
|
589
597
|
},
|
|
590
598
|
});
|
|
591
599
|
}
|
|
592
|
-
beforeExecutionCallback
|
|
593
|
-
|
|
600
|
+
for (const beforeExecutionCallback of beforeExecutionCallbackSet) {
|
|
601
|
+
beforeExecutionCallback(beforeExecutionInfo);
|
|
602
|
+
}
|
|
594
603
|
const fileUrl = `${rootDirectoryUrl}${fileRelativeUrl}`;
|
|
595
604
|
let executionResult;
|
|
596
605
|
if (existsSync(new URL(fileUrl))) {
|
|
@@ -599,7 +608,7 @@ To fix this warning:
|
|
|
599
608
|
logger,
|
|
600
609
|
allocatedMs: executionParams.allocatedMs,
|
|
601
610
|
keepRunning,
|
|
602
|
-
mirrorConsole: false, //
|
|
611
|
+
mirrorConsole: false, // might be executed in parallel: log would be a mess to read
|
|
603
612
|
collectConsole: executionParams.collectConsole,
|
|
604
613
|
coverageEnabled,
|
|
605
614
|
coverageTempDirectoryUrl,
|
|
@@ -619,7 +628,6 @@ To fix this warning:
|
|
|
619
628
|
],
|
|
620
629
|
};
|
|
621
630
|
}
|
|
622
|
-
counters.done++;
|
|
623
631
|
const fileReport = report[fileRelativeUrl];
|
|
624
632
|
if (fileReport) {
|
|
625
633
|
fileReport[executionName] = executionResult;
|
|
@@ -636,58 +644,65 @@ To fix this warning:
|
|
|
636
644
|
executionResult,
|
|
637
645
|
};
|
|
638
646
|
|
|
639
|
-
if (executionResult.status === "aborted") {
|
|
640
|
-
counters.aborted++;
|
|
641
|
-
} else if (executionResult.status === "timedout") {
|
|
642
|
-
counters.timedout++;
|
|
643
|
-
} else if (executionResult.status === "failed") {
|
|
644
|
-
counters.failed++;
|
|
645
|
-
} else if (executionResult.status === "completed") {
|
|
646
|
-
counters.completed++;
|
|
647
|
-
}
|
|
648
647
|
if (gcBetweenExecutions) {
|
|
649
648
|
global.gc();
|
|
650
649
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
});
|
|
665
|
-
// replace spinner with this execution result
|
|
666
|
-
if (spinner) spinner.stop();
|
|
667
|
-
executionLog.write(log);
|
|
668
|
-
rawOutput += stripAnsi(log);
|
|
669
|
-
|
|
670
|
-
const canOverwriteLog = canOverwriteLogGetter({
|
|
671
|
-
logMergeForCompletedExecutions,
|
|
672
|
-
executionResult,
|
|
673
|
-
});
|
|
674
|
-
if (canOverwriteLog) {
|
|
675
|
-
// nothing to do, we reuse the current executionLog object
|
|
676
|
-
} else {
|
|
677
|
-
executionLog.destroy();
|
|
678
|
-
executionLog = createLog({ newLine: "" });
|
|
650
|
+
|
|
651
|
+
const timeEllapsed = Date.now() - startMs;
|
|
652
|
+
const memoryHeap = memoryUsage().heapUsed;
|
|
653
|
+
callWhenPreviousExecutionAreDone(executionIndex, () => {
|
|
654
|
+
counters.done++;
|
|
655
|
+
if (executionResult.status === "aborted") {
|
|
656
|
+
counters.aborted++;
|
|
657
|
+
} else if (executionResult.status === "timedout") {
|
|
658
|
+
counters.timedout++;
|
|
659
|
+
} else if (executionResult.status === "failed") {
|
|
660
|
+
counters.failed++;
|
|
661
|
+
} else if (executionResult.status === "completed") {
|
|
662
|
+
counters.completed++;
|
|
679
663
|
}
|
|
664
|
+
|
|
665
|
+
if (executionLogsEnabled) {
|
|
666
|
+
// replace spinner with this execution result
|
|
667
|
+
if (spinner) {
|
|
668
|
+
spinner.stop();
|
|
669
|
+
spinner = null;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const log = createExecutionLog(afterExecutionInfo, {
|
|
673
|
+
logShortForCompletedExecutions,
|
|
674
|
+
logRuntime,
|
|
675
|
+
logEachDuration,
|
|
676
|
+
...(logTimeUsage ? { timeEllapsed } : {}),
|
|
677
|
+
...(logMemoryHeapUsage ? { memoryHeap } : {}),
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
executionLog.write(log);
|
|
681
|
+
rawOutput += stripAnsi(log);
|
|
682
|
+
const canOverwriteLog = canOverwriteLogGetter({
|
|
683
|
+
logMergeForCompletedExecutions,
|
|
684
|
+
executionResult,
|
|
685
|
+
});
|
|
686
|
+
if (canOverwriteLog) {
|
|
687
|
+
// nothing to do, we reuse the current executionLog object
|
|
688
|
+
} else {
|
|
689
|
+
executionLog.destroy();
|
|
690
|
+
executionLog = createLog({ newLine: "" });
|
|
691
|
+
}
|
|
692
|
+
const isLastExecutionLog =
|
|
693
|
+
executionIndex === executionSteps.length - 1;
|
|
694
|
+
if (isLastExecutionLog && logger.levels.info) {
|
|
695
|
+
executionLog.write("\n");
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
for (const afterExecutionCallback of afterExecutionCallbackSet) {
|
|
700
|
+
afterExecutionCallback(afterExecutionInfo);
|
|
680
701
|
}
|
|
681
|
-
afterExecutionCallback(afterExecutionInfo);
|
|
682
|
-
const isLastExecutionLog = executionIndex === executionSteps.length - 1;
|
|
683
702
|
const cancelRemaining =
|
|
684
703
|
failFast &&
|
|
685
704
|
executionResult.status !== "completed" &&
|
|
686
705
|
counters.done < counters.total;
|
|
687
|
-
if (isLastExecutionLog && logger.levels.info) {
|
|
688
|
-
executionLog.write("\n");
|
|
689
|
-
}
|
|
690
|
-
|
|
691
706
|
if (cancelRemaining) {
|
|
692
707
|
logger.info(`"failFast" enabled -> cancel remaining executions`);
|
|
693
708
|
failFastAbortController.abort();
|
|
@@ -776,7 +791,9 @@ To fix this warning:
|
|
|
776
791
|
await Promise.all(promises);
|
|
777
792
|
}
|
|
778
793
|
|
|
779
|
-
|
|
794
|
+
for (const afterAllExecutionCallback of afterAllExecutionCallbackSet) {
|
|
795
|
+
await afterAllExecutionCallback(returnValue);
|
|
796
|
+
}
|
|
780
797
|
return returnValue;
|
|
781
798
|
};
|
|
782
799
|
|
|
@@ -816,12 +833,14 @@ const executeInParallel = async ({
|
|
|
816
833
|
return;
|
|
817
834
|
}
|
|
818
835
|
const outputPromiseArray = [];
|
|
836
|
+
let previousExecPromise = Promise.resolve();
|
|
819
837
|
while (
|
|
820
838
|
remainingExecutionCount > 0 &&
|
|
821
839
|
outputPromiseArray.length < maxExecutionsInParallel
|
|
822
840
|
) {
|
|
823
841
|
remainingExecutionCount--;
|
|
824
|
-
const outputPromise = executeOne(progressionIndex);
|
|
842
|
+
const outputPromise = executeOne(progressionIndex, previousExecPromise);
|
|
843
|
+
previousExecPromise = outputPromise;
|
|
825
844
|
progressionIndex++;
|
|
826
845
|
outputPromiseArray.push(outputPromise);
|
|
827
846
|
}
|
|
@@ -833,9 +852,9 @@ const executeInParallel = async ({
|
|
|
833
852
|
}
|
|
834
853
|
};
|
|
835
854
|
|
|
836
|
-
const executeOne = async (index) => {
|
|
855
|
+
const executeOne = async (index, previousExecPromise) => {
|
|
837
856
|
const input = executionSteps[index];
|
|
838
|
-
const output = await start(input);
|
|
857
|
+
const output = await start(input, previousExecPromise);
|
|
839
858
|
if (!multipleExecutionsOperation.signal.aborted) {
|
|
840
859
|
executionResults[index] = output;
|
|
841
860
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const createCallOrderer = () => {
|
|
2
|
+
const queue = [];
|
|
3
|
+
const callWhenPreviousExecutionAreDone = (executionIndex, callback) => {
|
|
4
|
+
if (queue[executionIndex]) {
|
|
5
|
+
throw new Error(`${executionIndex} already used`);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let allBeforeAreDone = true;
|
|
9
|
+
if (executionIndex > 0) {
|
|
10
|
+
let beforeIndex = executionIndex - 1;
|
|
11
|
+
do {
|
|
12
|
+
const value = queue[beforeIndex];
|
|
13
|
+
if (!value) {
|
|
14
|
+
allBeforeAreDone = false;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
} while (beforeIndex--);
|
|
18
|
+
}
|
|
19
|
+
if (!allBeforeAreDone) {
|
|
20
|
+
queue[executionIndex] = callback;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
queue[executionIndex] = true;
|
|
24
|
+
callback();
|
|
25
|
+
let afterIndex = executionIndex + 1;
|
|
26
|
+
while (afterIndex < queue.length) {
|
|
27
|
+
const value = queue[afterIndex];
|
|
28
|
+
if (value === undefined) {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === "function") {
|
|
32
|
+
queue[afterIndex] = true;
|
|
33
|
+
value();
|
|
34
|
+
}
|
|
35
|
+
afterIndex++;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
return callWhenPreviousExecutionAreDone;
|
|
39
|
+
};
|