namespace Harness { // In harness baselines, null is different than undefined. See `generateActual` in `harness.ts`. export class Test262BaselineRunner extends RunnerBase { private static readonly basePath = "internal/cases/test262"; private static readonly helpersFilePath = "tests/cases/test262-harness/helpers.d.ts"; private static readonly helperFile: Compiler.TestFile = { unitName: Test262BaselineRunner.helpersFilePath, content: IO.readFile(Test262BaselineRunner.helpersFilePath)!, }; private static readonly testFileExtensionRegex = /\.js$/; private static readonly options: ts.CompilerOptions = { allowNonTsExtensions: true, target: ts.ScriptTarget.Latest, module: ts.ModuleKind.CommonJS }; private static readonly baselineOptions: Baseline.BaselineOptions = { Subfolder: "test262", Baselinefolder: "internal/baselines" }; private static getTestFilePath(filename: string): string { return Test262BaselineRunner.basePath + "/" + filename; } private runTest(filePath: string) { describe("test262 test for " + filePath, () => { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. let testState: { filename: string; compilerResult: compiler.CompilationResult; inputFiles: Compiler.TestFile[]; }; before(() => { const content = IO.readFile(filePath)!; const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test"; const testCaseContent = TestCaseParser.makeUnitsFromTest(content, testFilename); const inputFiles: Compiler.TestFile[] = testCaseContent.testUnitData.map(unit => { const unitName = Test262BaselineRunner.getTestFilePath(unit.name); return { unitName, content: unit.content }; }); // Emit the results testState = { filename: testFilename, inputFiles, compilerResult: undefined!, // TODO: GH#18217 }; testState.compilerResult = Compiler.compileFiles( [Test262BaselineRunner.helperFile].concat(inputFiles), /*otherFiles*/ [], /* harnessOptions */ undefined, Test262BaselineRunner.options, /* currentDirectory */ undefined); }); after(() => { testState = undefined!; }); it("has the expected emitted code", () => { const files = Array.from(testState.compilerResult.js.values()).filter(f => f.file !== Test262BaselineRunner.helpersFilePath); Baseline.runBaseline(testState.filename + ".output.js", Compiler.collateOutputs(files), Test262BaselineRunner.baselineOptions); }); it("has the expected errors", () => { const errors = testState.compilerResult.diagnostics; // eslint-disable-next-line no-null/no-null const baseline = errors.length === 0 ? null : Compiler.getErrorBaseline(testState.inputFiles, errors); Baseline.runBaseline(testState.filename + ".errors.txt", baseline, Test262BaselineRunner.baselineOptions); }); it("satisfies invariants", () => { const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); Utils.assertInvariants(sourceFile, /*parent:*/ undefined); }); it("has the expected AST", () => { const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename))!; Baseline.runBaseline(testState.filename + ".AST.txt", Utils.sourceFileToJSON(sourceFile), Test262BaselineRunner.baselineOptions); }); }); } public kind(): TestRunnerKind { return "test262"; } public enumerateTestFiles() { // see also: `enumerateTestFiles` in tests/webTestServer.ts return ts.map(this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true }), ts.normalizePath); } public initializeTests() { // this will set up a series of describe/it blocks to run between the setup and cleanup phases if (this.tests.length === 0) { const testFiles = this.getTestFiles(); testFiles.forEach(fn => { this.runTest(fn); }); } else { this.tests.forEach(test => this.runTest(typeof test === "string" ? test : test.file)); } } } }