From e4223658705877fb357832729adb0110fad1998f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 23 Apr 2018 21:52:16 -0700 Subject: [PATCH] Fix issues with runtests-browser --- Gulpfile.js | 50 +- src/harness/externalCompileRunner.ts | 4 +- src/harness/harness.ts | 45 +- src/harness/projectsRunner.ts | 2 +- src/harness/unittests/publicApi.ts | 11 +- src/harness/vfs.ts | 13 +- tests/webTestResults.html | 4 +- tests/webTestServer.ts | 1248 ++++++++++++++------------ 8 files changed, 722 insertions(+), 655 deletions(-) diff --git a/Gulpfile.js b/Gulpfile.js index afa7e775dcd..2d19385d311 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -66,10 +66,10 @@ const cmdLineOptions = minimist(process.argv.slice(2), { const noop = () => {}; // tslint:disable-line no-empty /** - * @param {string} cmd - * @param {string[]} args - * @param {() => void} complete - * @param {(e: *, status: number) => void} error + * @param {string} cmd + * @param {string[]} args + * @param {() => void} complete + * @param {(e: *, status: number) => void} error */ function exec(cmd, args, complete = noop, error = noop) { console.log(`${cmd} ${args.join(" ")}`); @@ -82,7 +82,7 @@ function exec(cmd, args, complete = noop, error = noop) { } /** - * @param {string} cmd + * @param {string} cmd */ function possiblyQuote(cmd) { return cmd.indexOf(" ") >= 0 ? `"${cmd}"` : cmd; @@ -222,8 +222,8 @@ const packageJson = "package.json"; const versionFile = path.join(compilerDirectory, "core.ts"); /** - * @param {string | string[]} source - * @param {string | string[]} dest + * @param {string | string[]} source + * @param {string | string[]} dest * @returns {boolean} */ function needsUpdate(source, dest) { @@ -290,7 +290,7 @@ function needsUpdate(source, dest) { } /** - * @param {tsc.Settings} base + * @param {tsc.Settings} base * @param {boolean=} useBuiltCompiler * @returns {tsc.Settings} */ @@ -442,7 +442,7 @@ const nodeStandaloneDefinitionsFile = path.join(builtLocalDirectory, "typescript /** @type {string} */ let copyrightContent; /** - * @param {boolean} outputCopyright + * @param {boolean} outputCopyright */ function prependCopyright(outputCopyright = !useDebugMode) { return insert.prepend(outputCopyright ? (copyrightContent || (copyrightContent = fs.readFileSync(copyright).toString())) : ""); @@ -666,9 +666,9 @@ function restoreSavedNodeEnv() { } /** - * @param {string} defaultReporter - * @param {boolean} runInParallel - * @param {(e?: any) => void} done + * @param {string} defaultReporter + * @param {boolean} runInParallel + * @param {(e?: any) => void} done */ function runConsoleTests(defaultReporter, runInParallel, done) { const lintFlag = cmdLineOptions.lint; @@ -746,8 +746,8 @@ function runConsoleTests(defaultReporter, runInParallel, done) { }); /** - * @param {any=} err - * @param {number=} status + * @param {any=} err + * @param {number=} status */ function failWithStatus(err, status) { if (err || status) { @@ -766,8 +766,8 @@ function runConsoleTests(defaultReporter, runInParallel, done) { } /** - * @param {any=} error - * @param {number=} errorStatus + * @param {any=} error + * @param {number=} errorStatus */ function finish(error, errorStatus) { restoreSavedNodeEnv(); @@ -800,7 +800,7 @@ const nodeServerOutFile = "tests/webTestServer.js"; const nodeServerInFile = "tests/webTestServer.ts"; gulp.task(nodeServerOutFile, /*help*/ false, [servicesFile], () => { /** @type {tsc.Settings} */ - const settings = getCompilerSettings({ module: "commonjs" }, /*useBuiltCompiler*/ true); + const settings = getCompilerSettings({ module: "commonjs", target: "es2015" }, /*useBuiltCompiler*/ true); return gulp.src(nodeServerInFile) .pipe(newer(nodeServerOutFile)) .pipe(sourcemaps.init()) @@ -885,7 +885,7 @@ gulp.task("browserify", "Runs browserify on run.js to produce a file suitable fo }); /** - * @param {(e?: any) => void} done + * @param {(e?: any) => void} done */ function cleanTestDirs(done) { // Clean the local baselines & Rwc baselines directories @@ -905,13 +905,13 @@ function cleanTestDirs(done) { /** * used to pass data from jake command line directly to run.js - * @param {string} tests - * @param {string} runners - * @param {boolean} light - * @param {string=} taskConfigsFolder - * @param {number=} workerCount - * @param {string=} stackTraceLimit - * @param {number=} timeout + * @param {string} tests + * @param {string} runners + * @param {boolean} light + * @param {string=} taskConfigsFolder + * @param {number=} workerCount + * @param {string=} stackTraceLimit + * @param {number=} timeout */ function writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, timeout) { const testConfigContents = JSON.stringify({ diff --git a/src/harness/externalCompileRunner.ts b/src/harness/externalCompileRunner.ts index 3d07c69af85..1d45351114d 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -41,7 +41,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { const cp = require("child_process"); it("should build successfully", () => { - let cwd = path.join(__dirname, "../../", cls.testDir, directoryName); + let cwd = path.join(Harness.IO.getWorkspaceRoot(), cls.testDir, directoryName); const stdio = isWorker ? "pipe" : "inherit"; let types: string[]; if (fs.existsSync(path.join(cwd, "test.json"))) { @@ -69,7 +69,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { 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(__dirname, "tsc.js")]; + const args = [path.join(Harness.IO.getWorkspaceRoot(), "built/local/tsc.js")]; if (types) { args.push("--types", types.join(",")); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 55da2cfac6c..d7db8eb8cfe 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -522,6 +522,7 @@ namespace Harness { log(text: string): void; args(): string[]; getExecutingFilePath(): string; + getWorkspaceRoot(): string; exit(exitCode?: number): void; readDirectory(path: string, extension?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[]; getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries; @@ -645,6 +646,7 @@ namespace Harness { log: s => console.log(s), args: () => ts.sys.args, getExecutingFilePath: () => ts.sys.getExecutingFilePath(), + getWorkspaceRoot: () => vpath.resolve(__dirname, "../.."), exit: exitCode => ts.sys.exit(exitCode), readDirectory: (path, extension, exclude, include, depth) => ts.sys.readDirectory(path, extension, exclude, include, depth), getAccessibleFileSystemEntries, @@ -676,9 +678,9 @@ namespace Harness { function createBrowserIO(): IO { const serverRoot = new URL("http://localhost:8888/"); - class HttpHeaders extends Map { + class HttpHeaders extends core.SortedMap { constructor(template?: Record) { - super(); + super(core.compareStringsCaseInsensitive); if (template) { for (const key in template) { if (ts.hasProperty(template, key)) { @@ -854,9 +856,9 @@ namespace Harness { function send(request: HttpRequestMessage): HttpResponseMessage { const xhr = new XMLHttpRequest(); try { + xhr.open(request.method, request.url.toString(), /*async*/ false); request.writeRequestHeaders(xhr); xhr.setRequestHeader("Access-Control-Allow-Origin", "*"); - xhr.open(request.method, request.url.toString(), /*async*/ false); xhr.send(request.content && request.content.content); while (xhr.readyState !== 4); // block until ready return HttpResponseMessage.readResponseMessage(xhr); @@ -903,8 +905,7 @@ namespace Harness { function directoryExists(path: string): boolean { const response = send(HttpRequestMessage.post(new URL("/api/directoryExists", serverRoot), HttpContent.text(path))); - return HttpResponseMessage.hasSuccessStatusCode(response) - && (response.content && response.content.content) === "true"; + return hasJsonContent(response) && JSON.parse(response.content.content) as boolean; } function deleteFile(path: string) { @@ -929,31 +930,22 @@ namespace Harness { } const response = send(HttpRequestMessage.post(new URL("/api/listFiles", serverRoot), HttpContent.text(dirname))); - return HttpResponseMessage.hasSuccessStatusCode(response) - && response.content - && response.content.headers.get("Content-Type") === "application/json" - ? JSON.parse(response.content.content) - : []; + return hasJsonContent(response) ? JSON.parse(response.content.content) : []; } function readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[], depth?: number) { - const fs = new vfs.FileSystem(!useCaseSensitiveFileNames(), { cwd: path, files: { [path]: { } } }); - const sys = new fakes.System(fs); - for (const file of IO.listFiles(path)) { - fs.mkdirpSync(vpath.dirname(file)); - fs.writeFileSync(file, ""); - } - return sys.readDirectory(path, extension, exclude, include, depth); + return ts.matchFiles(path, extension, exclude, include, useCaseSensitiveFileNames(), "", depth, getAccessibleFileSystemEntries); } function getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries { - const fs = new vfs.FileSystem(!useCaseSensitiveFileNames(), { cwd: dirname, files: { [dirname]: {} } }); - const sys = new fakes.System(fs); - for (const file of IO.listFiles(path)) { - fs.mkdirpSync(vpath.dirname(file)); - fs.writeFileSync(file, ""); - } - return sys.getAccessibleFileSystemEntries(dirname); + const response = send(HttpRequestMessage.post(new URL("/api/getAccessibleFileSystemEntries", serverRoot), HttpContent.text(dirname))); + return hasJsonContent(response) ? JSON.parse(response.content.content) : { files: [], directories: [] }; + } + + function hasJsonContent(response: HttpResponseMessage): response is HttpResponseMessage & { content: HttpContent } { + return HttpResponseMessage.hasSuccessStatusCode(response) + && !!response.content + && /^application\/json(;.*)$/.test("" + response.content.headers.get("Content-Type")); } return { @@ -976,7 +968,8 @@ namespace Harness { getExecutingFilePath: () => "", exit: () => {}, // tslint:disable-line no-empty readDirectory, - getAccessibleFileSystemEntries + getAccessibleFileSystemEntries, + getWorkspaceRoot: () => "/" }; } @@ -2003,7 +1996,7 @@ namespace Harness { } const parentDirectory = IO.directoryName(dirName); - if (parentDirectory !== "") { + if (parentDirectory !== "" && parentDirectory !== dirName) { createDirectoryStructure(parentDirectory); } IO.createDirectory(dirName); diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index b7f738bdeb3..e7d9b387b46 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -194,7 +194,7 @@ namespace project { } const fs = vfs.FileSystem.createFromFileSystem(Harness.IO, /*ignoreCase*/ false); - fs.mountSync(vpath.resolve(__dirname, "../../tests"), vpath.combine(vfs.srcFolder, "tests"), vfs.createResolver(Harness.IO)); + fs.mountSync(vpath.resolve(Harness.IO.getWorkspaceRoot(), "tests"), vpath.combine(vfs.srcFolder, "tests"), vfs.createResolver(Harness.IO)); fs.mkdirpSync(vpath.combine(vfs.srcFolder, testCase.projectRoot)); fs.chdir(vpath.combine(vfs.srcFolder, testCase.projectRoot)); fs.makeReadonly(); diff --git a/src/harness/unittests/publicApi.ts b/src/harness/unittests/publicApi.ts index 4160d26ac6b..e1a0b6ef673 100644 --- a/src/harness/unittests/publicApi.ts +++ b/src/harness/unittests/publicApi.ts @@ -14,12 +14,11 @@ describe("Public APIs", () => { }); it("should compile", () => { - const testFile: Harness.Compiler.TestFile = { - unitName: builtFile, - content: fileContent - }; - const inputFiles = [testFile]; - const result = Harness.Compiler.compileFiles(inputFiles, [], /*harnessSettings*/ undefined, /*options*/ {}, /*currentDirectory*/ undefined); + const fs = vfs.FileSystem.createFromFileSystem(Harness.IO, /*ignoreCase*/ false); + fs.linkSync(`${vfs.builtFolder}/${fileName}`, `${vfs.srcFolder}/${fileName}`); + const sys = new fakes.System(fs); + const host = new fakes.CompilerHost(sys); + const result = compiler.compileFiles(host, [`${vfs.srcFolder}/${fileName}`], {}); assert(!result.diagnostics || !result.diagnostics.length, Harness.Compiler.minimalDiagnosticsToString(result.diagnostics, /*pretty*/ true)); }); } diff --git a/src/harness/vfs.ts b/src/harness/vfs.ts index b88e7842884..49c72bfde58 100644 --- a/src/harness/vfs.ts +++ b/src/harness/vfs.ts @@ -1009,6 +1009,7 @@ namespace vfs { fileExists(path: string): boolean; getFileSize(path: string): number; readFile(path: string): string; + getWorkspaceRoot(): string; } export function createResolver(host: FileSystemResolverHost): FileSystemResolver { @@ -1244,10 +1245,10 @@ namespace vfs { // This is only to make the PR for this change easier to read. A follow-up PR will // revert this change and accept the new baselines. // See https://github.com/Microsoft/TypeScript/pull/20763#issuecomment-352553264 - function patchResolver(io: FileSystemResolverHost, resolver: FileSystemResolver): FileSystemResolver { - const libFile = vpath.combine(__dirname, "lib.d.ts"); - const es5File = vpath.combine(__dirname, "lib.es5.d.ts"); - const stringComparer = io.useCaseSensitiveFileNames() ? vpath.compareCaseSensitive : vpath.compareCaseInsensitive; + function patchResolver(host: FileSystemResolverHost, resolver: FileSystemResolver): FileSystemResolver { + const libFile = vpath.combine(host.getWorkspaceRoot(), "built/local/lib.d.ts"); + const es5File = vpath.combine(host.getWorkspaceRoot(), "built/local/lib.es5.d.ts"); + const stringComparer = host.useCaseSensitiveFileNames() ? vpath.compareCaseSensitive : vpath.compareCaseInsensitive; return { readdirSync: path => resolver.readdirSync(path), statSync: path => resolver.statSync(fixPath(path)), @@ -1273,8 +1274,8 @@ namespace vfs { const resolver = createResolver(host); builtLocalCI = new FileSystem(/*ignoreCase*/ true, { files: { - [builtFolder]: new Mount(__dirname, patchResolver(host, resolver)), - [testLibFolder]: new Mount(vpath.resolve(__dirname, "../../tests/lib"), resolver), + [builtFolder]: new Mount(vpath.resolve(host.getWorkspaceRoot(), "built/local"), patchResolver(host, resolver)), + [testLibFolder]: new Mount(vpath.resolve(host.getWorkspaceRoot(), "tests/lib"), resolver), [srcFolder]: {} }, cwd: srcFolder, diff --git a/tests/webTestResults.html b/tests/webTestResults.html index f747cdfa75c..487abfc117d 100644 --- a/tests/webTestResults.html +++ b/tests/webTestResults.html @@ -21,8 +21,10 @@
+ + - +