forked from rescript-lang/rescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinput.js
More file actions
97 lines (86 loc) · 2.95 KB
/
Copy pathinput.js
File metadata and controls
97 lines (86 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// @ts-check
import { readdirSync } from "node:fs";
import * as fs from "node:fs/promises";
import * as os from "node:os";
import * as path from "node:path";
import { setup } from "#dev/process";
import { normalizeNewlines } from "#dev/utils";
const { bsc } = setup(import.meta.dirname);
const expectedDir = path.join(import.meta.dirname, "expected");
const fixtures = readdirSync(path.join(import.meta.dirname, "fixtures"))
.filter(fileName => path.extname(fileName) === ".res")
.sort();
const prefix = ["-w", "+A", "-bs-jsx", "4"];
const updateTests = process.argv[2] === "update";
/**
* @param {string} output
* @return {string}
*/
function postProcessErrorOutput(output) {
let result = output;
result = result.trimEnd();
result = result.replace(
/(?:[A-Z]:)?[\\/][^ ]+?tests[\\/]build_tests[\\/]super_errors[\\/]([^:]+)/g,
(_match, path, _offset, _string) => "/.../" + path.replace("\\", "/"),
);
return normalizeNewlines(result);
}
/**
* @param {string} fileName
* @returns {Promise<{ fileName: string, failure: string | null }>}
*/
async function runFixture(fileName) {
const fullFilePath = path.join(import.meta.dirname, "fixtures", fileName);
const { stderr } = await bsc([...prefix, "-color", "always", fullFilePath]);
// careful of:
// - warning test that actually succeeded in compiling (warning's still in stderr, so the code path is shared here)
// - accidentally succeeding tests (not likely in this context),
// actual, correctly erroring test case
const actualErrorOutput = postProcessErrorOutput(stderr.toString());
const expectedFilePath = path.join(expectedDir, `${fileName}.expected`);
if (updateTests) {
await fs.writeFile(expectedFilePath, actualErrorOutput);
return { fileName, failure: null };
}
const expectedErrorOutput = postProcessErrorOutput(
await fs.readFile(expectedFilePath, "utf-8"),
);
if (expectedErrorOutput === actualErrorOutput) {
return { fileName, failure: null };
}
return {
fileName,
failure: [
`The old and new error output for the test ${fullFilePath} aren't the same`,
"\n=== Old:",
expectedErrorOutput,
"\n=== New:",
actualErrorOutput,
].join("\n"),
};
}
// Run fixtures in parallel with a worker-pool. Each fixture spawns a bsc
// process, so wall time is dominated by process startup; serialising the
// loop made the suite scale linearly with fixture count.
const concurrency = Math.max(1, os.availableParallelism());
let cursor = 0;
const results = new Array(fixtures.length);
await Promise.all(
Array.from({ length: Math.min(concurrency, fixtures.length) }, async () => {
while (true) {
const i = cursor++;
if (i >= fixtures.length) return;
results[i] = await runFixture(fixtures[i]);
}
}),
);
let atLeastOneTaskFailed = false;
for (const { failure } of results) {
if (failure !== null) {
console.error(failure);
atLeastOneTaskFailed = true;
}
}
if (atLeastOneTaskFailed) {
process.exit(1);
}