as-test 1.1.0 → 1.1.2
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/CHANGELOG.md +17 -3
- package/README.md +14 -7
- package/as-test.config.schema.json +142 -142
- package/assembly/__fuzz__/math.fuzz.ts +22 -0
- package/assembly/__fuzz__/seed-perf.fuzz.ts +4 -2
- package/assembly/__fuzz__/string.fuzz.ts +31 -0
- package/assembly/index.ts +6 -9
- package/assembly/src/expectation.ts +99 -42
- package/assembly/src/fuzz.ts +44 -23
- package/assembly/util/format.ts +113 -0
- package/assembly/util/helpers.ts +7 -13
- package/assembly/util/json.ts +2 -2
- package/assembly/util/wipc.ts +5 -3
- package/bin/build-worker-pool.js +7 -1
- package/bin/commands/build-core.js +6 -1
- package/bin/commands/build.js +1 -1
- package/bin/commands/clean-core.js +61 -16
- package/bin/commands/clean.js +11 -3
- package/bin/commands/fuzz-core.js +2 -2
- package/bin/commands/run-core.js +35 -24
- package/bin/commands/web-runner-source.js +14 -14
- package/bin/commands/web-session.js +6 -1
- package/bin/crash-store.js +3 -1
- package/bin/index.js +303 -124
- package/bin/reporters/default.js +175 -33
- package/bin/util.js +36 -11
- package/bin/wipc.js +7 -2
- package/lib/build/index.js +93 -25
- package/lib/src/index.ts +115 -36
- package/package.json +1 -3
- package/transform/lib/coverage.js +3 -1
package/bin/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import { build, formatInvocation as formatBuildInvocation, getBuildInvocationPreview, } from "./commands/build.js";
|
|
3
|
+
import { build, BuildFailureError, formatInvocation as formatBuildInvocation, getBuildInvocationPreview, } from "./commands/build.js";
|
|
4
4
|
import { createRunReporter, run } from "./commands/run.js";
|
|
5
5
|
import { executeBuildCommand } from "./commands/build.js";
|
|
6
6
|
import { executeRunCommand } from "./commands/run.js";
|
|
@@ -10,7 +10,7 @@ import { executeInitCommand } from "./commands/init.js";
|
|
|
10
10
|
import { executeDoctorCommand } from "./commands/doctor.js";
|
|
11
11
|
import { executeCleanCommand } from "./commands/clean.js";
|
|
12
12
|
import { fuzz } from "./commands/fuzz-core.js";
|
|
13
|
-
import { applyMode,
|
|
13
|
+
import { applyMode, formatTime, formatSpecDisplayPath, getDefaultModeNames, getCliVersion, loadConfig, resolveModeNames, } from "./util.js";
|
|
14
14
|
import * as path from "path";
|
|
15
15
|
import { spawnSync } from "child_process";
|
|
16
16
|
import { glob } from "glob";
|
|
@@ -134,7 +134,7 @@ else if (COMMANDS.includes(args[0])) {
|
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
136
|
else if (command === "clean") {
|
|
137
|
-
executeCleanCommand(configPath, selectedModes, resolveExecutionModes).catch((error) => {
|
|
137
|
+
executeCleanCommand(_args, configPath, selectedModes, resolveExecutionModes).catch((error) => {
|
|
138
138
|
printCliError(error);
|
|
139
139
|
process.exit(1);
|
|
140
140
|
});
|
|
@@ -370,7 +370,7 @@ function printCommandHelp(command) {
|
|
|
370
370
|
}
|
|
371
371
|
if (command == "clean") {
|
|
372
372
|
process.stdout.write(chalk.bold("Usage: ast clean [flags]\n\n"));
|
|
373
|
-
process.stdout.write("Remove configured build outputs, crash reports, and logs
|
|
373
|
+
process.stdout.write("Remove configured build outputs, crash reports, and logs.\n\n");
|
|
374
374
|
process.stdout.write(chalk.bold("Flags:\n"));
|
|
375
375
|
process.stdout.write(" --config <path> Use a specific config file\n");
|
|
376
376
|
process.stdout.write(" --mode <name[,name...]> Clean one or multiple named modes\n");
|
|
@@ -1069,10 +1069,12 @@ function resolveCommandTokens(rawArgs, command) {
|
|
|
1069
1069
|
}
|
|
1070
1070
|
async function buildFileForMode(args) {
|
|
1071
1071
|
if (args.buildPool) {
|
|
1072
|
+
const buildInvocation = await getBuildInvocationPreview(args.configPath, args.file, args.modeName, args.buildFeatureToggles);
|
|
1072
1073
|
await args.buildPool.buildFileMode({
|
|
1073
1074
|
configPath: args.configPath,
|
|
1074
1075
|
file: args.file,
|
|
1075
1076
|
modeName: args.modeName,
|
|
1077
|
+
buildCommand: formatBuildInvocation(buildInvocation),
|
|
1076
1078
|
featureToggles: args.buildFeatureToggles,
|
|
1077
1079
|
});
|
|
1078
1080
|
}
|
|
@@ -1103,21 +1105,30 @@ async function runTestSequential(runFlags, configPath, selectors, suiteSelectors
|
|
|
1103
1105
|
const duplicateSpecBasenames = resolveDuplicateSpecBasenames(files);
|
|
1104
1106
|
for (const file of files) {
|
|
1105
1107
|
const buildStartedAt = Date.now();
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1108
|
+
let result;
|
|
1109
|
+
try {
|
|
1110
|
+
await build(configPath, [file], modeName, buildFeatureToggles);
|
|
1111
|
+
buildIntervals.push({ start: buildStartedAt, end: Date.now() });
|
|
1112
|
+
const buildInvocation = await getBuildInvocationPreview(configPath, file, modeName, buildFeatureToggles);
|
|
1113
|
+
const artifactKey = resolvePerFileArtifactKey(file, duplicateSpecBasenames);
|
|
1114
|
+
result = await run(runFlags, configPath, [file], false, {
|
|
1115
|
+
reporter,
|
|
1116
|
+
webSession,
|
|
1117
|
+
suiteSelectors,
|
|
1118
|
+
emitRunStart: false,
|
|
1119
|
+
emitRunComplete: false,
|
|
1120
|
+
logFileName: `test.${artifactKey}.log.json`,
|
|
1121
|
+
coverageFileName: `coverage.${artifactKey}.log.json`,
|
|
1122
|
+
buildCommand: formatBuildInvocation(buildInvocation),
|
|
1123
|
+
modeName,
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
catch (error) {
|
|
1127
|
+
const buildFailure = getBuildFailureErrorLike(error);
|
|
1128
|
+
if (!buildFailure)
|
|
1129
|
+
throw error;
|
|
1130
|
+
result = createBuildFailureRunResult(buildFailure);
|
|
1131
|
+
}
|
|
1121
1132
|
results.push(result);
|
|
1122
1133
|
if (result?.failed)
|
|
1123
1134
|
failed = true;
|
|
@@ -1304,7 +1315,7 @@ async function runRuntimeMatrix(runFlags, configPath, selectors, suiteSelectors,
|
|
|
1304
1315
|
const buildIntervals = [];
|
|
1305
1316
|
for (let fileIndex = 0; fileIndex < files.length; fileIndex++) {
|
|
1306
1317
|
const file = files[fileIndex];
|
|
1307
|
-
const fileName =
|
|
1318
|
+
const fileName = formatSpecDisplayPath(file);
|
|
1308
1319
|
const fileResults = [];
|
|
1309
1320
|
const modeTimes = modes.map(() => "...");
|
|
1310
1321
|
if (liveMatrix) {
|
|
@@ -1480,7 +1491,7 @@ async function runTestMatrix(runFlags, configPath, selectors, suiteSelectors, fu
|
|
|
1480
1491
|
const buildIntervals = [];
|
|
1481
1492
|
for (let fileIndex = 0; fileIndex < files.length; fileIndex++) {
|
|
1482
1493
|
const file = files[fileIndex];
|
|
1483
|
-
const fileName =
|
|
1494
|
+
const fileName = formatSpecDisplayPath(file);
|
|
1484
1495
|
const fileResults = [];
|
|
1485
1496
|
const modeTimes = modes.map(() => "...");
|
|
1486
1497
|
if (liveMatrix) {
|
|
@@ -1488,6 +1499,7 @@ async function runTestMatrix(runFlags, configPath, selectors, suiteSelectors, fu
|
|
|
1488
1499
|
}
|
|
1489
1500
|
for (let i = 0; i < modes.length; i++) {
|
|
1490
1501
|
const modeName = modes[i];
|
|
1502
|
+
let result;
|
|
1491
1503
|
try {
|
|
1492
1504
|
const buildStartedAt = Date.now();
|
|
1493
1505
|
await buildFileForMode({
|
|
@@ -1499,7 +1511,7 @@ async function runTestMatrix(runFlags, configPath, selectors, suiteSelectors, fu
|
|
|
1499
1511
|
buildIntervals.push({ start: buildStartedAt, end: Date.now() });
|
|
1500
1512
|
const buildInvocation = await getBuildInvocationPreview(configPath, file, modeName, buildFeatureToggles);
|
|
1501
1513
|
const artifactKey = resolvePerFileArtifactKey(file, duplicateSpecBasenames);
|
|
1502
|
-
|
|
1514
|
+
result = await run(runFlags, configPath, [file], false, {
|
|
1503
1515
|
reporter: silentReporter,
|
|
1504
1516
|
reporterKind: "default",
|
|
1505
1517
|
emitRunStart: false,
|
|
@@ -1509,23 +1521,27 @@ async function runTestMatrix(runFlags, configPath, selectors, suiteSelectors, fu
|
|
|
1509
1521
|
buildCommand: formatBuildInvocation(buildInvocation),
|
|
1510
1522
|
modeName,
|
|
1511
1523
|
});
|
|
1512
|
-
modeTimes[i] = formatMatrixModeTime(result.stats.time);
|
|
1513
|
-
if (liveMatrix) {
|
|
1514
|
-
renderMatrixLiveLine(fileName, modeLabels, modeTimes, showPerModeTimes);
|
|
1515
|
-
}
|
|
1516
|
-
if (result.failed) {
|
|
1517
|
-
modeState[i].failed = true;
|
|
1518
|
-
}
|
|
1519
|
-
else if (result.stats.passedFiles > 0) {
|
|
1520
|
-
modeState[i].passed = true;
|
|
1521
|
-
}
|
|
1522
|
-
fileResults.push(result);
|
|
1523
|
-
allResults.push(result);
|
|
1524
1524
|
}
|
|
1525
1525
|
catch (error) {
|
|
1526
|
-
|
|
1527
|
-
|
|
1526
|
+
const buildFailure = getBuildFailureErrorLike(error);
|
|
1527
|
+
if (!buildFailure) {
|
|
1528
|
+
clearLiveLine();
|
|
1529
|
+
throw error;
|
|
1530
|
+
}
|
|
1531
|
+
result = createBuildFailureRunResult(buildFailure);
|
|
1532
|
+
}
|
|
1533
|
+
modeTimes[i] = formatMatrixModeTime(result.stats.time);
|
|
1534
|
+
if (liveMatrix) {
|
|
1535
|
+
renderMatrixLiveLine(fileName, modeLabels, modeTimes, showPerModeTimes);
|
|
1536
|
+
}
|
|
1537
|
+
if (result.failed) {
|
|
1538
|
+
modeState[i].failed = true;
|
|
1528
1539
|
}
|
|
1540
|
+
else if (result.stats.passedFiles > 0) {
|
|
1541
|
+
modeState[i].passed = true;
|
|
1542
|
+
}
|
|
1543
|
+
fileResults.push(result);
|
|
1544
|
+
allResults.push(result);
|
|
1529
1545
|
}
|
|
1530
1546
|
if (reporterSession.reporterKind == "default") {
|
|
1531
1547
|
renderMatrixFileResult(fileName, modeLabels, fileResults, modeTimes, liveMatrix, showPerModeTimes);
|
|
@@ -1610,22 +1626,31 @@ async function runRuntimeSingleParallel(runFlags, configPath, selectors, suiteSe
|
|
|
1610
1626
|
const poolWidth = Math.max(runFlags.buildJobs, runFlags.runJobs);
|
|
1611
1627
|
await runOrderedPool(files, poolWidth, async (file, index) => {
|
|
1612
1628
|
const token = useQueueDisplay
|
|
1613
|
-
? renderQueuedFileStart(queueDisplay,
|
|
1629
|
+
? renderQueuedFileStart(queueDisplay, formatSpecDisplayPath(file))
|
|
1614
1630
|
: null;
|
|
1615
1631
|
const buffered = useQueueDisplay
|
|
1616
1632
|
? await createBufferedReporter(configPath, runFlags.reporterPath, modeName)
|
|
1617
1633
|
: null;
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1634
|
+
let result;
|
|
1635
|
+
try {
|
|
1636
|
+
result = await runLimit(() => run({ ...runFlags, clean: true }, configPath, [file], false, {
|
|
1637
|
+
reporter: buffered?.reporter,
|
|
1638
|
+
reporterKind: buffered?.reporterKind,
|
|
1639
|
+
modeName,
|
|
1640
|
+
suiteSelectors,
|
|
1641
|
+
emitRunComplete: false,
|
|
1642
|
+
fileSummaryTotal: 1,
|
|
1643
|
+
modeSummaryTotal,
|
|
1644
|
+
modeSummaryExecuted: 1,
|
|
1645
|
+
buildCommandsByFile: { [file]: buildCommandsByFile[file] ?? "" },
|
|
1646
|
+
}));
|
|
1647
|
+
}
|
|
1648
|
+
catch (error) {
|
|
1649
|
+
const buildFailure = getBuildFailureErrorLike(error);
|
|
1650
|
+
if (!buildFailure)
|
|
1651
|
+
throw error;
|
|
1652
|
+
result = createBuildFailureRunResult(buildFailure);
|
|
1653
|
+
}
|
|
1629
1654
|
buffered?.reporter.flush?.();
|
|
1630
1655
|
results[index] = result;
|
|
1631
1656
|
if (buffered && token != null) {
|
|
@@ -1676,7 +1701,7 @@ async function runRuntimeMatrixParallel(runFlags, configPath, selectors, suiteSe
|
|
|
1676
1701
|
const buildIntervals = [];
|
|
1677
1702
|
try {
|
|
1678
1703
|
await runOrderedPool(files, poolWidth, async (file, fileIndex) => {
|
|
1679
|
-
const fileName =
|
|
1704
|
+
const fileName = formatSpecDisplayPath(file);
|
|
1680
1705
|
const token = useQueueDisplay
|
|
1681
1706
|
? renderQueuedFileStart(queueDisplay, fileName)
|
|
1682
1707
|
: null;
|
|
@@ -1684,28 +1709,37 @@ async function runRuntimeMatrixParallel(runFlags, configPath, selectors, suiteSe
|
|
|
1684
1709
|
const modeTimes = modes.map(() => "...");
|
|
1685
1710
|
for (let i = 0; i < modes.length; i++) {
|
|
1686
1711
|
const modeName = modes[i];
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1712
|
+
let result;
|
|
1713
|
+
try {
|
|
1714
|
+
const buildStartedAt = Date.now();
|
|
1715
|
+
await buildFileForMode({
|
|
1716
|
+
configPath,
|
|
1717
|
+
file,
|
|
1718
|
+
modeName,
|
|
1719
|
+
buildFeatureToggles: {},
|
|
1720
|
+
buildPool,
|
|
1721
|
+
});
|
|
1722
|
+
buildIntervals.push({ start: buildStartedAt, end: Date.now() });
|
|
1723
|
+
const buildInvocation = await getBuildInvocationPreview(configPath, file, modeName, {});
|
|
1724
|
+
const artifactKey = resolvePerFileArtifactKey(file, duplicateSpecBasenames);
|
|
1725
|
+
result = await run(runFlags, configPath, [file], false, {
|
|
1726
|
+
reporter: silentReporter,
|
|
1727
|
+
reporterKind: "default",
|
|
1728
|
+
suiteSelectors,
|
|
1729
|
+
emitRunStart: false,
|
|
1730
|
+
emitRunComplete: false,
|
|
1731
|
+
logFileName: `run.${artifactKey}.log.json`,
|
|
1732
|
+
coverageFileName: `coverage.${artifactKey}.log.json`,
|
|
1733
|
+
buildCommand: formatBuildInvocation(buildInvocation),
|
|
1734
|
+
modeName,
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
catch (error) {
|
|
1738
|
+
const buildFailure = getBuildFailureErrorLike(error);
|
|
1739
|
+
if (!buildFailure)
|
|
1740
|
+
throw error;
|
|
1741
|
+
result = createBuildFailureRunResult(buildFailure);
|
|
1742
|
+
}
|
|
1709
1743
|
modeTimes[i] = formatMatrixModeTime(result.stats.time);
|
|
1710
1744
|
fileResults.push(result);
|
|
1711
1745
|
}
|
|
@@ -1780,32 +1814,41 @@ async function runTestSingleParallel(runFlags, configPath, selectors, suiteSelec
|
|
|
1780
1814
|
try {
|
|
1781
1815
|
await runOrderedPool(files, poolWidth, async (file, index) => {
|
|
1782
1816
|
const token = useQueueDisplay
|
|
1783
|
-
? renderQueuedFileStart(queueDisplay,
|
|
1817
|
+
? renderQueuedFileStart(queueDisplay, formatSpecDisplayPath(file))
|
|
1784
1818
|
: null;
|
|
1785
|
-
const buildStartedAt = Date.now();
|
|
1786
|
-
await buildFileForMode({
|
|
1787
|
-
configPath,
|
|
1788
|
-
file,
|
|
1789
|
-
modeName,
|
|
1790
|
-
buildFeatureToggles,
|
|
1791
|
-
buildPool,
|
|
1792
|
-
});
|
|
1793
|
-
buildIntervals.push({ start: buildStartedAt, end: Date.now() });
|
|
1794
|
-
const buildInvocation = await getBuildInvocationPreview(configPath, file, modeName, buildFeatureToggles);
|
|
1795
|
-
const artifactKey = resolvePerFileArtifactKey(file, duplicateSpecBasenames);
|
|
1796
1819
|
const buffered = useQueueDisplay
|
|
1797
1820
|
? await createBufferedReporter(configPath, runFlags.reporterPath, modeName)
|
|
1798
1821
|
: null;
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1822
|
+
let result;
|
|
1823
|
+
try {
|
|
1824
|
+
const buildStartedAt = Date.now();
|
|
1825
|
+
await buildFileForMode({
|
|
1826
|
+
configPath,
|
|
1827
|
+
file,
|
|
1828
|
+
modeName,
|
|
1829
|
+
buildFeatureToggles,
|
|
1830
|
+
buildPool,
|
|
1831
|
+
});
|
|
1832
|
+
buildIntervals.push({ start: buildStartedAt, end: Date.now() });
|
|
1833
|
+
const buildInvocation = await getBuildInvocationPreview(configPath, file, modeName, buildFeatureToggles);
|
|
1834
|
+
const artifactKey = resolvePerFileArtifactKey(file, duplicateSpecBasenames);
|
|
1835
|
+
result = await run({ ...runFlags, clean: true }, configPath, [file], false, {
|
|
1836
|
+
reporter: buffered?.reporter,
|
|
1837
|
+
reporterKind: buffered?.reporterKind,
|
|
1838
|
+
suiteSelectors,
|
|
1839
|
+
emitRunComplete: false,
|
|
1840
|
+
logFileName: `test.${artifactKey}.log.json`,
|
|
1841
|
+
coverageFileName: `coverage.${artifactKey}.log.json`,
|
|
1842
|
+
buildCommand: formatBuildInvocation(buildInvocation),
|
|
1843
|
+
modeName,
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
catch (error) {
|
|
1847
|
+
const buildFailure = getBuildFailureErrorLike(error);
|
|
1848
|
+
if (!buildFailure)
|
|
1849
|
+
throw error;
|
|
1850
|
+
result = createBuildFailureRunResult(buildFailure);
|
|
1851
|
+
}
|
|
1809
1852
|
buffered?.reporter.flush?.();
|
|
1810
1853
|
results[index] = result;
|
|
1811
1854
|
if (buffered && token != null) {
|
|
@@ -1881,7 +1924,7 @@ async function runTestMatrixParallel(runFlags, configPath, selectors, suiteSelec
|
|
|
1881
1924
|
const buildIntervals = [];
|
|
1882
1925
|
try {
|
|
1883
1926
|
await runOrderedPool(files, poolWidth, async (file, fileIndex) => {
|
|
1884
|
-
const fileName =
|
|
1927
|
+
const fileName = formatSpecDisplayPath(file);
|
|
1885
1928
|
const token = useQueueDisplay
|
|
1886
1929
|
? renderQueuedFileStart(queueDisplay, fileName)
|
|
1887
1930
|
: null;
|
|
@@ -1889,28 +1932,37 @@ async function runTestMatrixParallel(runFlags, configPath, selectors, suiteSelec
|
|
|
1889
1932
|
const modeTimes = modes.map(() => "...");
|
|
1890
1933
|
for (let i = 0; i < modes.length; i++) {
|
|
1891
1934
|
const modeName = modes[i];
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1935
|
+
let result;
|
|
1936
|
+
try {
|
|
1937
|
+
const buildStartedAt = Date.now();
|
|
1938
|
+
await buildFileForMode({
|
|
1939
|
+
configPath,
|
|
1940
|
+
file,
|
|
1941
|
+
modeName,
|
|
1942
|
+
buildFeatureToggles,
|
|
1943
|
+
buildPool,
|
|
1944
|
+
});
|
|
1945
|
+
buildIntervals.push({ start: buildStartedAt, end: Date.now() });
|
|
1946
|
+
const buildInvocation = await getBuildInvocationPreview(configPath, file, modeName, buildFeatureToggles);
|
|
1947
|
+
const artifactKey = resolvePerFileArtifactKey(file, duplicateSpecBasenames);
|
|
1948
|
+
result = await run(runFlags, configPath, [file], false, {
|
|
1949
|
+
reporter: silentReporter,
|
|
1950
|
+
reporterKind: "default",
|
|
1951
|
+
suiteSelectors,
|
|
1952
|
+
emitRunStart: false,
|
|
1953
|
+
emitRunComplete: false,
|
|
1954
|
+
logFileName: `test.${artifactKey}.log.json`,
|
|
1955
|
+
coverageFileName: `coverage.${artifactKey}.log.json`,
|
|
1956
|
+
buildCommand: formatBuildInvocation(buildInvocation),
|
|
1957
|
+
modeName,
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
catch (error) {
|
|
1961
|
+
const buildFailure = getBuildFailureErrorLike(error);
|
|
1962
|
+
if (!buildFailure)
|
|
1963
|
+
throw error;
|
|
1964
|
+
result = createBuildFailureRunResult(buildFailure);
|
|
1965
|
+
}
|
|
1914
1966
|
modeTimes[i] = formatMatrixModeTime(result.stats.time);
|
|
1915
1967
|
fileResults.push(result);
|
|
1916
1968
|
}
|
|
@@ -2005,7 +2057,9 @@ async function runFuzzMatrixResultsParallel(configPath, selectors, fuzzerSelecto
|
|
|
2005
2057
|
async function runFuzzMatrixResults(configPath, selectors, fuzzerSelectors, modes, overrides, reporter) {
|
|
2006
2058
|
const results = [];
|
|
2007
2059
|
for (const modeName of modes) {
|
|
2008
|
-
const files = await resolveSelectedFuzzFiles(configPath, selectors, [
|
|
2060
|
+
const files = await resolveSelectedFuzzFiles(configPath, selectors, [
|
|
2061
|
+
modeName,
|
|
2062
|
+
]);
|
|
2009
2063
|
if (!files.length) {
|
|
2010
2064
|
continue;
|
|
2011
2065
|
}
|
|
@@ -2211,6 +2265,133 @@ function buildSingleModeSummary(stats, snapshotSummary, totalModes) {
|
|
|
2211
2265
|
total,
|
|
2212
2266
|
};
|
|
2213
2267
|
}
|
|
2268
|
+
function createBuildFailureRunResult(error) {
|
|
2269
|
+
const message = formatBuildFailureMessage(error);
|
|
2270
|
+
const report = {
|
|
2271
|
+
file: error.file,
|
|
2272
|
+
modeName: error.mode,
|
|
2273
|
+
suites: [
|
|
2274
|
+
{
|
|
2275
|
+
file: error.file,
|
|
2276
|
+
description: formatSpecDisplayPath(error.file),
|
|
2277
|
+
depth: 0,
|
|
2278
|
+
kind: "build-error",
|
|
2279
|
+
verdict: "fail",
|
|
2280
|
+
time: {
|
|
2281
|
+
start: 0,
|
|
2282
|
+
end: 0,
|
|
2283
|
+
},
|
|
2284
|
+
suites: [],
|
|
2285
|
+
logs: [],
|
|
2286
|
+
tests: [
|
|
2287
|
+
{
|
|
2288
|
+
order: 0,
|
|
2289
|
+
type: "build-error",
|
|
2290
|
+
verdict: "fail",
|
|
2291
|
+
left: null,
|
|
2292
|
+
right: null,
|
|
2293
|
+
instr: "build failed before the test could run",
|
|
2294
|
+
message,
|
|
2295
|
+
location: "",
|
|
2296
|
+
},
|
|
2297
|
+
],
|
|
2298
|
+
modeName: error.mode,
|
|
2299
|
+
buildCommand: formatBuildInvocation(error.invocation),
|
|
2300
|
+
runCommand: "",
|
|
2301
|
+
},
|
|
2302
|
+
],
|
|
2303
|
+
coverage: {
|
|
2304
|
+
total: 0,
|
|
2305
|
+
covered: 0,
|
|
2306
|
+
uncovered: 0,
|
|
2307
|
+
percent: 100,
|
|
2308
|
+
points: [],
|
|
2309
|
+
},
|
|
2310
|
+
runCommand: "",
|
|
2311
|
+
buildCommand: formatBuildInvocation(error.invocation),
|
|
2312
|
+
snapshotSummary: {
|
|
2313
|
+
matched: 0,
|
|
2314
|
+
created: 0,
|
|
2315
|
+
updated: 0,
|
|
2316
|
+
failed: 0,
|
|
2317
|
+
},
|
|
2318
|
+
};
|
|
2319
|
+
return {
|
|
2320
|
+
failed: true,
|
|
2321
|
+
buildTime: 0,
|
|
2322
|
+
stats: {
|
|
2323
|
+
passedFiles: 0,
|
|
2324
|
+
failedFiles: 1,
|
|
2325
|
+
skippedFiles: 0,
|
|
2326
|
+
passedSuites: 0,
|
|
2327
|
+
failedSuites: 1,
|
|
2328
|
+
skippedSuites: 0,
|
|
2329
|
+
passedTests: 0,
|
|
2330
|
+
failedTests: 1,
|
|
2331
|
+
skippedTests: 0,
|
|
2332
|
+
time: 0,
|
|
2333
|
+
failedEntries: [
|
|
2334
|
+
{
|
|
2335
|
+
...report.suites[0],
|
|
2336
|
+
file: error.file,
|
|
2337
|
+
modeName: error.mode,
|
|
2338
|
+
buildCommand: report.buildCommand,
|
|
2339
|
+
runCommand: "",
|
|
2340
|
+
},
|
|
2341
|
+
],
|
|
2342
|
+
},
|
|
2343
|
+
snapshotSummary: report.snapshotSummary,
|
|
2344
|
+
coverageSummary: {
|
|
2345
|
+
enabled: false,
|
|
2346
|
+
showPoints: false,
|
|
2347
|
+
total: 0,
|
|
2348
|
+
covered: 0,
|
|
2349
|
+
uncovered: 0,
|
|
2350
|
+
percent: 100,
|
|
2351
|
+
files: [],
|
|
2352
|
+
},
|
|
2353
|
+
reports: [report],
|
|
2354
|
+
};
|
|
2355
|
+
}
|
|
2356
|
+
function formatBuildFailureMessage(error) {
|
|
2357
|
+
const parts = [];
|
|
2358
|
+
const stderr = error.stderr.trim();
|
|
2359
|
+
const stdout = error.stdout.trim();
|
|
2360
|
+
if (stderr.length) {
|
|
2361
|
+
parts.push(`stderr:\n${stderr}`);
|
|
2362
|
+
}
|
|
2363
|
+
if (stdout.length) {
|
|
2364
|
+
parts.push(`stdout:\n${stdout}`);
|
|
2365
|
+
}
|
|
2366
|
+
if (error.crashLogPath.length) {
|
|
2367
|
+
parts.push(`Crash log:\n${error.crashLogPath}`);
|
|
2368
|
+
}
|
|
2369
|
+
return parts.join("\n\n") || "build failed with no compiler output";
|
|
2370
|
+
}
|
|
2371
|
+
function getBuildFailureErrorLike(error) {
|
|
2372
|
+
if (error instanceof BuildFailureError) {
|
|
2373
|
+
return error;
|
|
2374
|
+
}
|
|
2375
|
+
if (!error || typeof error != "object") {
|
|
2376
|
+
return null;
|
|
2377
|
+
}
|
|
2378
|
+
const candidate = error;
|
|
2379
|
+
if (candidate.name != "BuildFailureError") {
|
|
2380
|
+
return null;
|
|
2381
|
+
}
|
|
2382
|
+
if (typeof candidate.file != "string" ||
|
|
2383
|
+
typeof candidate.mode != "string" ||
|
|
2384
|
+
typeof candidate.stdout != "string" ||
|
|
2385
|
+
typeof candidate.stderr != "string" ||
|
|
2386
|
+
typeof candidate.crashLogPath != "string" ||
|
|
2387
|
+
!candidate.invocation ||
|
|
2388
|
+
typeof candidate.invocation != "object" ||
|
|
2389
|
+
typeof candidate.invocation.command != "string" ||
|
|
2390
|
+
!Array.isArray(candidate.invocation.args)) {
|
|
2391
|
+
return null;
|
|
2392
|
+
}
|
|
2393
|
+
return candidate;
|
|
2394
|
+
}
|
|
2214
2395
|
function applyConfiguredFileTotalToStats(stats, fileSummaryTotal) {
|
|
2215
2396
|
const total = Math.max(fileSummaryTotal, 0);
|
|
2216
2397
|
const executed = stats.failedFiles + stats.passedFiles + stats.skippedFiles;
|
|
@@ -2319,7 +2500,7 @@ async function buildNoTestFilesMatchedError(configPath, selectors, includeFuzz =
|
|
|
2319
2500
|
if (configuredFiles.length) {
|
|
2320
2501
|
const sample = configuredFiles
|
|
2321
2502
|
.slice(0, 5)
|
|
2322
|
-
.map((file) =>
|
|
2503
|
+
.map((file) => formatSpecDisplayPath(file))
|
|
2323
2504
|
.join(", ");
|
|
2324
2505
|
lines.push(`Configured specs (${configuredFiles.length}): ${sample}${configuredFiles.length > 5 ? ", ..." : ""}`);
|
|
2325
2506
|
}
|
|
@@ -2627,7 +2808,7 @@ async function handleMissingWebBrowsers(missing) {
|
|
|
2627
2808
|
const details = "no web-capable browser was found in PATH, BROWSER, or Playwright cache";
|
|
2628
2809
|
const selected = choosePreferredBrowserInstall(missing);
|
|
2629
2810
|
const installCommand = selected == "webkit"
|
|
2630
|
-
?
|
|
2811
|
+
? "npx -y playwright install webkit"
|
|
2631
2812
|
: `npx -y playwright install ${selected}`;
|
|
2632
2813
|
if (!canPromptForWebInstall()) {
|
|
2633
2814
|
throw new Error(`web target requires a browser for mode(s) ${scope}; ${details}. Export BROWSER or install one with "${installCommand}".`);
|
|
@@ -2747,10 +2928,10 @@ function isPlaywrightBrowserExecutable(browser) {
|
|
|
2747
2928
|
function extractPlaywrightDepsSummary(result) {
|
|
2748
2929
|
const stdout = typeof result.stdout == "string"
|
|
2749
2930
|
? result.stdout
|
|
2750
|
-
: result.stdout?.toString("utf8") ?? "";
|
|
2931
|
+
: (result.stdout?.toString("utf8") ?? "");
|
|
2751
2932
|
const stderr = typeof result.stderr == "string"
|
|
2752
2933
|
? result.stderr
|
|
2753
|
-
: result.stderr?.toString("utf8") ?? "";
|
|
2934
|
+
: (result.stderr?.toString("utf8") ?? "");
|
|
2754
2935
|
return [stdout.trim(), stderr.trim()].filter(Boolean).join("\n");
|
|
2755
2936
|
}
|
|
2756
2937
|
function canPromptForWebInstall() {
|
|
@@ -2885,9 +3066,7 @@ function resolveSystemBrowserExecutable(browser) {
|
|
|
2885
3066
|
"Firefox.app/Contents/MacOS/firefox",
|
|
2886
3067
|
"Firefox Developer Edition.app/Contents/MacOS/firefox",
|
|
2887
3068
|
],
|
|
2888
|
-
msedge: [
|
|
2889
|
-
"Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
|
|
2890
|
-
],
|
|
3069
|
+
msedge: ["Microsoft Edge.app/Contents/MacOS/Microsoft Edge"],
|
|
2891
3070
|
webkit: [],
|
|
2892
3071
|
};
|
|
2893
3072
|
for (const root of macSearchRoots) {
|