-
Notifications
You must be signed in to change notification settings - Fork 12.9k
External runner fixes #24115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
External runner fixes #24115
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
/// <reference path="runnerbase.ts" /> | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
const del = require("del"); | ||
|
||
interface ExecResult { | ||
stdout: Buffer; | ||
|
@@ -27,9 +28,32 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { | |
const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles(); | ||
|
||
describe(`${this.kind()} code samples`, () => { | ||
const cwd = path.join(Harness.IO.getWorkspaceRoot(), this.testDir); | ||
const placeholderName = ".node_modules"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not just add a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They have one already. That only says which things get auto-included without even doing an |
||
const moduleDirName = "node_modules"; | ||
before(() => { | ||
ts.forEachAncestorDirectory(cwd, dir => { | ||
try { | ||
fs.renameSync(path.join(dir, moduleDirName), path.join(dir, placeholderName)); | ||
} | ||
catch { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why catch here, at least with nothing in the body? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't care if the rename fails (since it means the folder didn't exist or we didn't have permissions to rename - in either case we're just going to continue) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, as long as the failure is obvious (and linkable back to this line of code) some other way. I think in this case it will be obvious in the baselines. |
||
// empty | ||
} | ||
}); | ||
}); | ||
for (const test of testList) { | ||
this.runTest(typeof test === "string" ? test : test.file); | ||
} | ||
after(() => { | ||
ts.forEachAncestorDirectory(cwd, dir => { | ||
try { | ||
fs.renameSync(path.join(dir, placeholderName), path.join(dir, moduleDirName)); | ||
} | ||
catch { | ||
// empty | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
private runTest(directoryName: string) { | ||
|
@@ -42,6 +66,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { | |
|
||
it("should build successfully", () => { | ||
let cwd = path.join(Harness.IO.getWorkspaceRoot(), cls.testDir, directoryName); | ||
const originalCwd = cwd; | ||
const stdio = isWorker ? "pipe" : "inherit"; | ||
let types: string[]; | ||
if (fs.existsSync(path.join(cwd, "test.json"))) { | ||
|
@@ -64,14 +89,17 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { | |
fs.unlinkSync(path.join(cwd, "package-lock.json")); | ||
} | ||
if (fs.existsSync(path.join(cwd, "node_modules"))) { | ||
require("del").sync(path.join(cwd, "node_modules"), { force: true }); | ||
del.sync(path.join(cwd, "node_modules"), { force: true }); | ||
} | ||
const install = cp.spawnSync(`npm`, ["i", "--ignore-scripts"], { cwd, timeout: timeout / 2, shell: true, stdio }); // NPM shouldn't take the entire timeout - if it takes a long time, it should be terminated and we should log the failure | ||
if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed: ${install.stderr.toString()}`); | ||
} | ||
const args = [path.join(Harness.IO.getWorkspaceRoot(), "built/local/tsc.js")]; | ||
if (types) { | ||
args.push("--types", types.join(",")); | ||
// Also actually install those types (for, eg, the js projects which need node) | ||
const install = cp.spawnSync(`npm`, ["i", ...types.map(t => `@types/${t}`), "--no-save", "--ignore-scripts"], { cwd: originalCwd, timeout: timeout / 2, shell: true, stdio }); // NPM shouldn't take the entire timeout - if it takes a long time, it should be terminated and we should log the failure | ||
if (install.status !== 0) throw new Error(`NPM Install types for ${directoryName} failed: ${install.stderr.toString()}`); | ||
} | ||
args.push("--noEmit"); | ||
Harness.Baseline.runBaseline(`${cls.kind()}/${directoryName}.log`, () => { | ||
|
@@ -91,7 +119,7 @@ class UserCodeRunner extends ExternalCompileRunnerBase { | |
// tslint:disable-next-line:no-null-keyword | ||
return result.status === 0 && !result.stdout.length && !result.stderr.length ? null : `Exit Code: ${result.status} | ||
Standard output: | ||
${stripAbsoluteImportPaths(result.stdout.toString().replace(/\r\n/g, "\n"))} | ||
${sortErrors(stripAbsoluteImportPaths(result.stdout.toString().replace(/\r\n/g, "\n")))} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this change address the path changes (eg from E:/... to /opt/...)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They were already fixed by the |
||
|
||
|
||
Standard error: | ||
|
@@ -109,6 +137,29 @@ function stripAbsoluteImportPaths(result: string) { | |
.replace(/Module '".*?\/tests\/cases\/user\//g, `Module '"/`); | ||
} | ||
|
||
function sortErrors(result: string) { | ||
return ts.flatten(splitBy(result.split("\n"), s => /^\S+/.test(s)).sort(compareErrorStrings)).join("\n"); | ||
} | ||
|
||
const errorRegexp = /^(.+\.[tj]sx?)\((\d+),(\d+)\): error TS/; | ||
function compareErrorStrings(a: string[], b: string[]) { | ||
ts.Debug.assertGreaterThanOrEqual(a.length, 1); | ||
ts.Debug.assertGreaterThanOrEqual(b.length, 1); | ||
const matchA = a[0].match(errorRegexp); | ||
if (!matchA) { | ||
return -1; | ||
} | ||
const matchB = b[0].match(errorRegexp); | ||
if (!matchB) { | ||
return 1; | ||
} | ||
const [, errorFileA, lineNumberStringA, columnNumberStringA] = matchA; | ||
const [, errorFileB, lineNumberStringB, columnNumberStringB] = matchB; | ||
return ts.comparePathsCaseSensitive(errorFileA, errorFileB) || | ||
ts.compareValues(parseInt(lineNumberStringA), parseInt(lineNumberStringB)) || | ||
ts.compareValues(parseInt(columnNumberStringA), parseInt(columnNumberStringB)); | ||
} | ||
|
||
class DefinitelyTypedRunner extends ExternalCompileRunnerBase { | ||
readonly testDir = "../DefinitelyTyped/types/"; | ||
workingDirectory = this.testDir; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why change this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it's required before I renamed node_modules and make it unreachable.