1namespace Harness { 2 // In harness baselines, null is different than undefined. See `generateActual` in `harness.ts`. 3 export class Test262BaselineRunner extends RunnerBase { 4 private static readonly basePath = "internal/cases/test262"; 5 private static readonly helpersFilePath = "tests/cases/test262-harness/helpers.d.ts"; 6 private static readonly helperFile: Compiler.TestFile = { 7 unitName: Test262BaselineRunner.helpersFilePath, 8 content: IO.readFile(Test262BaselineRunner.helpersFilePath)!, 9 }; 10 private static readonly testFileExtensionRegex = /\.js$/; 11 private static readonly options: ts.CompilerOptions = { 12 allowNonTsExtensions: true, 13 target: ts.ScriptTarget.Latest, 14 module: ts.ModuleKind.CommonJS 15 }; 16 private static readonly baselineOptions: Baseline.BaselineOptions = { 17 Subfolder: "test262", 18 Baselinefolder: "internal/baselines" 19 }; 20 21 private static getTestFilePath(filename: string): string { 22 return Test262BaselineRunner.basePath + "/" + filename; 23 } 24 25 private runTest(filePath: string) { 26 describe("test262 test for " + filePath, () => { 27 // Mocha holds onto the closure environment of the describe callback even after the test is done. 28 // Everything declared here should be cleared out in the "after" callback. 29 let testState: { 30 filename: string; 31 compilerResult: compiler.CompilationResult; 32 inputFiles: Compiler.TestFile[]; 33 }; 34 35 before(() => { 36 const content = IO.readFile(filePath)!; 37 const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test"; 38 const testCaseContent = TestCaseParser.makeUnitsFromTest(content, testFilename); 39 40 const inputFiles: Compiler.TestFile[] = testCaseContent.testUnitData.map(unit => { 41 const unitName = Test262BaselineRunner.getTestFilePath(unit.name); 42 return { unitName, content: unit.content }; 43 }); 44 45 // Emit the results 46 testState = { 47 filename: testFilename, 48 inputFiles, 49 compilerResult: undefined!, // TODO: GH#18217 50 }; 51 52 testState.compilerResult = Compiler.compileFiles( 53 [Test262BaselineRunner.helperFile].concat(inputFiles), 54 /*otherFiles*/ [], 55 /* harnessOptions */ undefined, 56 Test262BaselineRunner.options, 57 /* currentDirectory */ undefined); 58 }); 59 60 after(() => { 61 testState = undefined!; 62 }); 63 64 it("has the expected emitted code", () => { 65 const files = Array.from(testState.compilerResult.js.values()).filter(f => f.file !== Test262BaselineRunner.helpersFilePath); 66 Baseline.runBaseline(testState.filename + ".output.js", Compiler.collateOutputs(files), Test262BaselineRunner.baselineOptions); 67 }); 68 69 it("has the expected errors", () => { 70 const errors = testState.compilerResult.diagnostics; 71 // eslint-disable-next-line no-null/no-null 72 const baseline = errors.length === 0 ? null : Compiler.getErrorBaseline(testState.inputFiles, errors); 73 Baseline.runBaseline(testState.filename + ".errors.txt", baseline, Test262BaselineRunner.baselineOptions); 74 }); 75 76 it("satisfies invariants", () => { 77 const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); 78 Utils.assertInvariants(sourceFile, /*parent:*/ undefined); 79 }); 80 81 it("has the expected AST", () => { 82 const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename))!; 83 Baseline.runBaseline(testState.filename + ".AST.txt", Utils.sourceFileToJSON(sourceFile), Test262BaselineRunner.baselineOptions); 84 }); 85 }); 86 } 87 88 public kind(): TestRunnerKind { 89 return "test262"; 90 } 91 92 public enumerateTestFiles() { 93 // see also: `enumerateTestFiles` in tests/webTestServer.ts 94 return ts.map(this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true }), ts.normalizePath); 95 } 96 97 public initializeTests() { 98 // this will set up a series of describe/it blocks to run between the setup and cleanup phases 99 if (this.tests.length === 0) { 100 const testFiles = this.getTestFiles(); 101 testFiles.forEach(fn => { 102 this.runTest(fn); 103 }); 104 } 105 else { 106 this.tests.forEach(test => this.runTest(typeof test === "string" ? test : test.file)); 107 } 108 } 109 } 110}