Skip to content

Commit a5fa75a

Browse files
committed
DefinitelyTypedRunner skips ExpectErrors
If all errors were ExpectErrors, then it does not fail.
1 parent a1014b2 commit a5fa75a

File tree

1 file changed

+75
-16
lines changed

1 file changed

+75
-16
lines changed

src/harness/externalCompileRunner.ts

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
/// <reference path="harness.ts"/>
22
/// <reference path="runnerbase.ts" />
3+
const fs = require("fs");
4+
const path = require("path");
35
abstract class ExternalCompileRunnerBase extends RunnerBase {
46
abstract testDir: string;
5-
public enumerateTestFiles() {
7+
abstract report(result: any, cwd: string): string;
8+
enumerateTestFiles() {
69
return Harness.IO.getDirectories(this.testDir);
710
}
811
/** Setup the runner's tests so that they are ready to be executed by the harness
912
* The first test should be a describe/it block that sets up the harness's compiler instance appropriately
1013
*/
11-
public initializeTests(): void {
14+
initializeTests(): void {
1215
// Read in and evaluate the test list
1316
const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles();
1417

@@ -36,32 +39,88 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
3639
if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`);
3740
}
3841
Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => {
39-
const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true });
40-
// tslint:disable-next-line:no-null-keyword
41-
return result.status === 0 && !result.stdout.length && !result.stderr.length ? null : `Exit Code: ${result.status}
42-
Standard output:
43-
${result.stdout.toString().replace(/\r\n/g, "\n")}
44-
45-
46-
Standard error:
47-
${result.stderr.toString().replace(/\r\n/g, "\n")}`;
42+
return this.report(cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }), cwd);
4843
});
4944
});
5045
});
5146
}
5247
}
5348

5449
class UserCodeRunner extends ExternalCompileRunnerBase {
55-
public readonly testDir = "tests/cases/user/";
56-
public kind(): TestRunnerKind {
50+
readonly testDir = "tests/cases/user/";
51+
kind(): TestRunnerKind {
5752
return "user";
5853
}
54+
report(result: any) {
55+
// tslint:disable-next-line:no-null-keyword
56+
return result.status === 0 && !result.stdout.length && !result.stderr.length ? null : `Exit Code: ${result.status}
57+
Standard output:
58+
${result.stdout.toString().replace(/\r\n/g, "\n")}
59+
60+
61+
Standard error:
62+
${result.stderr.toString().replace(/\r\n/g, "\n")}`;
63+
}
5964
}
6065

6166
class DefinitelyTypedRunner extends ExternalCompileRunnerBase {
62-
public readonly testDir = "../DefinitelyTyped/types/";
63-
public workingDirectory = this.testDir;
64-
public kind(): TestRunnerKind {
67+
readonly testDir = "../DefinitelyTyped/types/";
68+
workingDirectory = this.testDir;
69+
kind(): TestRunnerKind {
6570
return "dt";
6671
}
72+
report(result: any, cwd: string) {
73+
const stdout = filterExpectedErrors(result.stdout.toString(), cwd)
74+
const stderr = result.stderr.toString()
75+
// tslint:disable-next-line:no-null-keyword
76+
return !stdout.length && !stderr.length ? null : `Exit Code: ${result.status}
77+
Standard output:
78+
${stdout.replace(/\r\n/g, "\n")}
79+
80+
81+
Standard error:
82+
${stderr.replace(/\r\n/g, "\n")}`;
83+
}
84+
}
85+
86+
function filterExpectedErrors(errors: string, cwd: string): string {
87+
return breaks(errors.split("\n"), s => /^\w+/.test(s)).filter(isExpectedError(cwd)).map(lines => lines.join("\n")).join("\n");
88+
}
89+
function isExpectedError(cwd: string) {
90+
return (error: string[]) => {
91+
if (error.length === 0) {
92+
return true;
93+
}
94+
const match = error[0].match(/(.+\.ts)\((\d+),\d+\): error TS/);
95+
if (!match) {
96+
return true;
97+
}
98+
const errlines = fs.readFileSync(path.join(cwd, match[1]), { encoding: "utf8" }).split("\n");
99+
const index = parseInt(match[2]);
100+
const errline = index < errlines.length ? errlines[index] : "";
101+
const prevline = index - 1 < errlines.length && index > 0 ? errlines[index - 1] : "";
102+
if (errline.indexOf("$ExpectError") > -1 || prevline.indexOf("$ExpectError") > -1) {
103+
return false;
104+
}
105+
return true;
106+
}
107+
}
108+
function breaks<T>(xs: T[], isStart: (T: any) => boolean): T[][] {
109+
const result = [];
110+
let group: T[] = [];
111+
for (const x of xs) {
112+
if (isStart(x)) {
113+
if (group.length) {
114+
result.push(group);
115+
}
116+
group = [x];
117+
}
118+
else {
119+
group.push(x);
120+
}
121+
}
122+
if (group.length) {
123+
result.push(group);
124+
}
125+
return result;
67126
}

0 commit comments

Comments
 (0)