forked from zed-industries/zed
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrandomized-test-minimize
More file actions
executable file
·135 lines (117 loc) · 3.65 KB
/
randomized-test-minimize
File metadata and controls
executable file
·135 lines (117 loc) · 3.65 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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env node --redirect-warnings=/dev/null
const fs = require("fs");
const path = require("path");
const { spawnSync } = require("child_process");
const FAILING_SEED_REGEX = /failing seed: (\d+)/gi;
const CARGO_TEST_ARGS = ["--release", "--lib", "--package", "collab"];
if (require.main === module) {
if (process.argv.length < 4) {
process.stderr.write(
"usage: script/randomized-test-minimize <input-plan> <output-plan> [start-index]\n",
);
process.exit(1);
}
minimizeTestPlan(
process.argv[2],
process.argv[3],
parseInt(process.argv[4]) || 0,
);
}
function minimizeTestPlan(inputPlanPath, outputPlanPath, startIndex = 0) {
const tempPlanPath = inputPlanPath + ".try";
fs.copyFileSync(inputPlanPath, outputPlanPath);
let testPlan = JSON.parse(fs.readFileSync(outputPlanPath, "utf8"));
process.stderr.write("minimizing failing test plan...\n");
for (let ix = startIndex; ix < testPlan.length; ix++) {
// Skip 'MutateClients' entries, since they themselves are not single operations.
if (testPlan[ix].MutateClients) {
continue;
}
// Remove a row from the test plan
const newTestPlan = testPlan.slice();
newTestPlan.splice(ix, 1);
fs.writeFileSync(tempPlanPath, serializeTestPlan(newTestPlan), "utf8");
process.stderr.write(
`${ix}/${testPlan.length}: ${JSON.stringify(testPlan[ix])}`,
);
const failingSeed = runTests({
SEED: "0",
LOAD_PLAN: tempPlanPath,
SAVE_PLAN: tempPlanPath,
ITERATIONS: "500",
});
// If the test failed, keep the test plan with the removed row. Reload the test
// plan from the JSON file, since the test itself will remove any operations
// which are no longer valid before saving the test plan.
if (failingSeed != null) {
process.stderr.write(` - remove. failing seed: ${failingSeed}.\n`);
fs.copyFileSync(tempPlanPath, outputPlanPath);
testPlan = JSON.parse(fs.readFileSync(outputPlanPath, "utf8"));
ix--;
} else {
process.stderr.write(` - keep.\n`);
}
}
fs.unlinkSync(tempPlanPath);
// Re-run the final minimized plan to get the correct failing seed.
// This is a workaround for the fact that the execution order can
// slightly change when replaying a test plan after it has been
// saved and loaded.
const failingSeed = runTests({
SEED: "0",
ITERATIONS: "5000",
LOAD_PLAN: outputPlanPath,
});
process.stderr.write(`final test plan: ${outputPlanPath}\n`);
process.stderr.write(`final seed: ${failingSeed}\n`);
return failingSeed;
}
function buildTests() {
const { status } = spawnSync(
"cargo",
["test", "--no-run", ...CARGO_TEST_ARGS],
{
stdio: "inherit",
encoding: "utf8",
env: {
...process.env,
},
},
);
if (status !== 0) {
throw new Error("build failed");
}
}
function runTests(env) {
const { status, stdout } = spawnSync(
"cargo",
["test", ...CARGO_TEST_ARGS, "random_project_collaboration"],
{
stdio: "pipe",
encoding: "utf8",
env: {
...process.env,
...env,
},
},
);
if (status !== 0) {
FAILING_SEED_REGEX.lastIndex = 0;
const match = FAILING_SEED_REGEX.exec(stdout);
if (!match) {
process.stderr.write("test failed, but no failing seed found:\n");
process.stderr.write(stdout);
process.stderr.write("\n");
process.exit(1);
}
return match[1];
} else {
return null;
}
}
function serializeTestPlan(plan) {
return "[\n" + plan.map((row) => JSON.stringify(row)).join(",\n") + "\n]\n";
}
exports.buildTests = buildTests;
exports.runTests = runTests;
exports.minimizeTestPlan = minimizeTestPlan;