Skip to content

Commit 0d5800a

Browse files
committed
Address PR comments
1 parent a5fa75a commit 0d5800a

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

src/harness/externalCompileRunner.ts

+39-23
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@
22
/// <reference path="runnerbase.ts" />
33
const fs = require("fs");
44
const path = require("path");
5+
6+
interface ExecResult {
7+
stdout: Buffer;
8+
stderr: Buffer;
9+
status: number;
10+
}
11+
512
abstract class ExternalCompileRunnerBase extends RunnerBase {
613
abstract testDir: string;
7-
abstract report(result: any, cwd: string): string;
14+
abstract report(result: ExecResult, cwd: string): string;
815
enumerateTestFiles() {
916
return Harness.IO.getDirectories(this.testDir);
1017
}
@@ -24,8 +31,6 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
2431
private runTest(directoryName: string) {
2532
describe(directoryName, () => {
2633
const cp = require("child_process");
27-
const path = require("path");
28-
const fs = require("fs");
2934

3035
it("should build successfully", () => {
3136
const cwd = path.join(__dirname, "../../", this.testDir, directoryName);
@@ -51,7 +56,7 @@ class UserCodeRunner extends ExternalCompileRunnerBase {
5156
kind(): TestRunnerKind {
5257
return "user";
5358
}
54-
report(result: any) {
59+
report(result: ExecResult) {
5560
// tslint:disable-next-line:no-null-keyword
5661
return result.status === 0 && !result.stdout.length && !result.stderr.length ? null : `Exit Code: ${result.status}
5762
Standard output:
@@ -69,9 +74,9 @@ class DefinitelyTypedRunner extends ExternalCompileRunnerBase {
6974
kind(): TestRunnerKind {
7075
return "dt";
7176
}
72-
report(result: any, cwd: string) {
73-
const stdout = filterExpectedErrors(result.stdout.toString(), cwd)
74-
const stderr = result.stderr.toString()
77+
report(result: ExecResult, cwd: string) {
78+
const stdout = removeExpectedErrors(result.stdout.toString(), cwd);
79+
const stderr = result.stderr.toString();
7580
// tslint:disable-next-line:no-null-keyword
7681
return !stdout.length && !stderr.length ? null : `Exit Code: ${result.status}
7782
Standard output:
@@ -83,29 +88,40 @@ ${stderr.replace(/\r\n/g, "\n")}`;
8388
}
8489
}
8590

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");
91+
function removeExpectedErrors(errors: string, cwd: string): string {
92+
return ts.flatten(splitBy(errors.split("\n"), s => /^\S+/.test(s)).filter(isUnexpectedError(cwd))).join("\n");
8893
}
89-
function isExpectedError(cwd: string) {
94+
/**
95+
* Returns true if the line that caused the error contains '$ExpectError',
96+
* or if the line before that one contains '$ExpectError'.
97+
* '$ExpectError' is a marker used in Definitely Typed tests,
98+
* meaning that the error should not contribute toward our error baslines.
99+
*/
100+
function isUnexpectedError(cwd: string) {
90101
return (error: string[]) => {
91-
if (error.length === 0) {
92-
return true;
93-
}
102+
ts.Debug.assertGreaterThanOrEqual(error.length, 1);
94103
const match = error[0].match(/(.+\.ts)\((\d+),\d+\): error TS/);
95104
if (!match) {
96105
return true;
97106
}
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+
const [, errorFile, lineNumberString] = match;
108+
const lines = fs.readFileSync(path.join(cwd, errorFile), { encoding: "utf8" }).split("\n");
109+
const lineNumber = parseInt(lineNumberString);
110+
ts.Debug.assertGreaterThanOrEqual(lineNumber, 0);
111+
ts.Debug.assertLessThan(lineNumber, lines.length);
112+
const previousLine = lineNumber - 1 > 0 ? lines[lineNumber - 1] : "";
113+
return lines[lineNumber].indexOf("$ExpectError") === -1 && previousLine.indexOf("$ExpectError") === -1;
114+
};
107115
}
108-
function breaks<T>(xs: T[], isStart: (T: any) => boolean): T[][] {
116+
/**
117+
* Split an array into multiple arrays whenever `isStart` returns true.
118+
* @example
119+
* splitBy([1,2,3,4,5,6], isOdd)
120+
* ==> [[1, 2], [3, 4], [5, 6]]
121+
* where
122+
* const isOdd = n => !!(n % 2)
123+
*/
124+
function splitBy<T>(xs: T[], isStart: (x: T) => boolean): T[][] {
109125
const result = [];
110126
let group: T[] = [];
111127
for (const x of xs) {

0 commit comments

Comments
 (0)