Skip to content

Commit b762770

Browse files
committed
Add test to verify tsc like command line input
1 parent 4786279 commit b762770

File tree

140 files changed

+3836
-1522
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

140 files changed

+3836
-1522
lines changed

src/compiler/sys.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,8 @@ namespace ts {
651651
base64decode?(input: string): string;
652652
base64encode?(input: string): string;
653653
/*@internal*/ bufferFrom?(input: string, encoding?: string): Buffer;
654+
// For testing
655+
/*@internal*/ now?(): Date;
654656
}
655657

656658
export interface FileWatcher {

src/compiler/tsbuild.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ namespace ts {
316316
*/
317317
export function createBuilderStatusReporter(system: System, pretty?: boolean): DiagnosticReporter {
318318
return diagnostic => {
319-
let output = pretty ? `[${formatColorAndReset(new Date().toLocaleTimeString(), ForegroundColorEscapeSequences.Grey)}] ` : `${new Date().toLocaleTimeString()} - `;
319+
let output = pretty ? `[${formatColorAndReset((system.now ? system.now() : new Date()).toLocaleTimeString(), ForegroundColorEscapeSequences.Grey)}] ` : `${(system.now ? system.now() : new Date()).toLocaleTimeString()} - `;
320320
output += `${flattenDiagnosticMessageText(diagnostic.messageText, system.newLine)}${system.newLine + system.newLine}`;
321321
system.write(output);
322322
};

src/harness/fakes.ts

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ namespace fakes {
140140
}
141141

142142
public createHash(data: string): string {
143-
return data;
143+
return `${ts.generateDjb2Hash(data)}-${data}`;
144144
}
145145

146146
public realpath(path: string) {
@@ -164,6 +164,10 @@ namespace fakes {
164164
return undefined;
165165
}
166166
}
167+
168+
now() {
169+
return new Date(this.vfs.time());
170+
}
167171
}
168172

169173
/**
@@ -520,39 +524,51 @@ ${indentText}${text}`;
520524

521525
export const version = "FakeTSVersion";
522526

523-
export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuilderHost<ts.BuilderProgram> {
524-
createProgram: ts.CreateProgram<ts.BuilderProgram>;
525-
526-
constructor(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram<ts.BuilderProgram>) {
527-
super(sys, options, setParentNodes);
528-
this.createProgram = createProgram || ts.createEmitAndSemanticDiagnosticsBuilderProgram;
529-
}
530-
531-
readFile(path: string) {
532-
const value = super.readFile(path);
527+
export function patchSolutionBuilderHost(host: ts.SolutionBuilderHost<ts.BuilderProgram>, sys: System) {
528+
const originalReadFile = host.readFile;
529+
host.readFile = (path, encoding) => {
530+
const value = originalReadFile.call(host, path, encoding);
533531
if (!value || !ts.isBuildInfoFile(path)) return value;
534532
const buildInfo = ts.getBuildInfo(value);
535533
ts.Debug.assert(buildInfo.version === version);
536534
buildInfo.version = ts.version;
537535
return ts.getBuildInfoText(buildInfo);
536+
};
537+
538+
if (host.writeFile) {
539+
const originalWriteFile = host.writeFile;
540+
host.writeFile = (fileName, content, writeByteOrderMark) => {
541+
if (!ts.isBuildInfoFile(fileName)) return originalWriteFile.call(host, fileName, content, writeByteOrderMark);
542+
const buildInfo = ts.getBuildInfo(content);
543+
sanitizeBuildInfoProgram(buildInfo);
544+
buildInfo.version = version;
545+
originalWriteFile.call(host, fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark);
546+
};
547+
}
548+
549+
ts.Debug.assert(host.now === undefined);
550+
host.now = () => new Date(sys.vfs.time());
551+
ts.Debug.assertDefined(host.createHash);
552+
}
553+
554+
export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuilderHost<ts.BuilderProgram> {
555+
createProgram: ts.CreateProgram<ts.BuilderProgram>;
556+
557+
private constructor(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram<ts.BuilderProgram>) {
558+
super(sys, options, setParentNodes);
559+
this.createProgram = createProgram || ts.createEmitAndSemanticDiagnosticsBuilderProgram;
538560
}
539561

540-
public writeFile(fileName: string, content: string, writeByteOrderMark: boolean) {
541-
if (!ts.isBuildInfoFile(fileName)) return super.writeFile(fileName, content, writeByteOrderMark);
542-
const buildInfo = ts.getBuildInfo(content);
543-
sanitizeBuildInfoProgram(buildInfo);
544-
buildInfo.version = version;
545-
super.writeFile(fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark);
562+
static create(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram<ts.BuilderProgram>) {
563+
const host = new SolutionBuilderHost(sys, options, setParentNodes, createProgram);
564+
patchSolutionBuilderHost(host, host.sys);
565+
return host;
546566
}
547567

548568
createHash(data: string) {
549569
return `${ts.generateDjb2Hash(data)}-${data}`;
550570
}
551571

552-
now() {
553-
return new Date(this.sys.vfs.time());
554-
}
555-
556572
diagnostics: SolutionBuilderDiagnostic[] = [];
557573

558574
reportDiagnostic(diagnostic: ts.Diagnostic) {

src/testRunner/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
"unittests/services/extract/helpers.ts",
4040
"unittests/tsbuild/helpers.ts",
41+
"unittests/tsc/helpers.ts",
4142
"unittests/tscWatch/helpers.ts",
4243
"unittests/tsserver/helpers.ts",
4344

src/testRunner/unittests/tsbuild/amdModulesWithOut.ts

Lines changed: 31 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,47 +32,46 @@ namespace ts {
3232
});
3333

3434
interface VerifyOutFileScenarioInput {
35-
scenario: string;
36-
modifyFs: (fs: vfs.FileSystem) => void;
35+
subScenario: string;
36+
modifyFs?: (fs: vfs.FileSystem) => void;
3737
modifyAgainFs?: (fs: vfs.FileSystem) => void;
3838
}
3939

4040
function verifyOutFileScenario({
41-
scenario,
41+
subScenario,
4242
modifyFs,
4343
modifyAgainFs
4444
}: VerifyOutFileScenarioInput) {
45-
verifyTsbuildOutput({
46-
scenario,
47-
projFs: () => outFileFs,
48-
time,
45+
verifyTscIncrementalEdits({
46+
scenario: "amdModulesWithOut",
47+
subScenario,
48+
fs: () => outFileFs,
4949
tick,
50-
proj: "amdModulesWithOut",
51-
rootNames: ["/src/app"],
50+
commandLineArgs: ["--b", "/src/app", "--verbose"],
5251
baselineSourceMap: true,
53-
initialBuild: {
54-
modifyFs
55-
},
56-
incrementalDtsUnchangedBuild: {
57-
modifyFs: fs => appendText(fs, relName(sources[project.lib][source.ts][1]), "console.log(x);")
58-
},
59-
incrementalHeaderChangedBuild: modifyAgainFs ? {
60-
modifyFs: modifyAgainFs
61-
} : undefined,
62-
baselineOnly: true
52+
modifyFs,
53+
incrementalScenarios: [
54+
{
55+
buildKind: BuildKind.IncrementalDtsUnchanged,
56+
modifyFs: fs => appendText(fs, relName(sources[project.lib][source.ts][1]), "console.log(x);")
57+
},
58+
...(modifyAgainFs ? [{
59+
buildKind: BuildKind.IncrementalHeadersChange,
60+
modifyFs: modifyAgainFs
61+
}] : emptyArray),
62+
]
6363
});
6464
}
6565

6666
describe("Prepend output with .tsbuildinfo", () => {
6767
verifyOutFileScenario({
68-
scenario: "modules and globals mixed in amd",
69-
modifyFs: noop
68+
subScenario: "modules and globals mixed in amd",
7069
});
7170

7271
// Prologues
7372
describe("Prologues", () => {
7473
verifyOutFileScenario({
75-
scenario: "multiple prologues in all projects",
74+
subScenario: "multiple prologues in all projects",
7675
modifyFs: fs => {
7776
enableStrict(fs, sources[project.lib][source.config]);
7877
addTestPrologue(fs, sources[project.lib][source.ts][0], `"myPrologue"`);
@@ -90,7 +89,7 @@ namespace ts {
9089
describe("Shebang", () => {
9190
// changes declaration because its emitted in .d.ts file
9291
verifyOutFileScenario({
93-
scenario: "shebang in all projects",
92+
subScenario: "shebang in all projects",
9493
modifyFs: fs => {
9594
addShebang(fs, "lib", "file0");
9695
addShebang(fs, "lib", "file1");
@@ -102,7 +101,7 @@ namespace ts {
102101
// emitHelpers
103102
describe("emitHelpers", () => {
104103
verifyOutFileScenario({
105-
scenario: "multiple emitHelpers in all projects",
104+
subScenario: "multiple emitHelpers in all projects",
106105
modifyFs: fs => {
107106
addSpread(fs, "lib", "file0");
108107
addRest(fs, "lib", "file1");
@@ -117,7 +116,7 @@ namespace ts {
117116
describe("triple slash refs", () => {
118117
// changes declaration because its emitted in .d.ts file
119118
verifyOutFileScenario({
120-
scenario: "triple slash refs in all projects",
119+
subScenario: "triple slash refs in all projects",
121120
modifyFs: fs => {
122121
addTripleSlashRef(fs, "lib", "file0");
123122
addTripleSlashRef(fs, "app", "file4");
@@ -161,7 +160,7 @@ ${internal} export enum internalEnum { a, b, c }`);
161160

162161
// Verify initial + incremental edits
163162
verifyOutFileScenario({
164-
scenario: "stripInternal",
163+
subScenario: "stripInternal",
165164
modifyFs: stripInternalScenario,
166165
modifyAgainFs: fs => replaceText(fs, sources[project.lib][source.ts][1], `export const`, `/*@internal*/ export const`),
167166
});
@@ -175,26 +174,13 @@ ${internal} export enum internalEnum { a, b, c }`);
175174
replaceText(fs, sources[project.app][source.ts][0], "file1", "lib/file1");
176175
}
177176

178-
verifyTsbuildOutput({
179-
scenario: "when the module resolution finds original source file",
180-
projFs: () => outFileFs,
181-
time,
182-
tick,
183-
proj: "amdModulesWithOut",
184-
rootNames: ["/src/app"],
177+
verifyTsc({
178+
scenario: "amdModulesWithOut",
179+
subScenario: "when the module resolution finds original source file",
180+
fs: () => outFileFs,
181+
commandLineArgs: ["-b", "/src/app", "--verbose"],
182+
modifyFs,
185183
baselineSourceMap: true,
186-
initialBuild: {
187-
modifyFs,
188-
expectedDiagnostics: [
189-
getExpectedDiagnosticForProjectsInBuild("src/lib/tsconfig.json", "src/app/tsconfig.json"),
190-
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/lib/tsconfig.json", "src/module.js"],
191-
[Diagnostics.Building_project_0, sources[project.lib][source.config]],
192-
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/app/tsconfig.json", "src/app/module.js"],
193-
[Diagnostics.Building_project_0, sources[project.app][source.config]],
194-
]
195-
},
196-
baselineOnly: true,
197-
verifyDiagnostics: true
198184
});
199185
});
200186
});

src/testRunner/unittests/tsbuild/containerOnlyReferenced.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace ts {
1919

2020
it("verify that subsequent builds after initial build doesnt build anything", () => {
2121
const fs = projFs.shadow();
22-
const host = new fakes.SolutionBuilderHost(fs);
22+
const host = fakes.SolutionBuilderHost.create(fs);
2323
createSolutionBuilder(host, ["/src"], { verbose: true }).build();
2424
host.assertDiagnosticMessages(
2525
getExpectedDiagnosticForProjectsInBuild("src/src/folder/tsconfig.json", "src/src/folder2/tsconfig.json", "src/src/tsconfig.json", "src/tests/tsconfig.json", "src/tsconfig.json"),

src/testRunner/unittests/tsbuild/demo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ namespace ts {
4949

5050
function verifyBuild({ modifyDiskLayout, expectedExitStatus, expectedDiagnostics, expectedOutputs, notExpectedOutputs }: VerifyBuild) {
5151
const fs = projFs.shadow();
52-
const host = new fakes.SolutionBuilderHost(fs);
52+
const host = fakes.SolutionBuilderHost.create(fs);
5353
modifyDiskLayout(fs);
5454
const builder = createSolutionBuilder(host, ["/src/tsconfig.json"], { verbose: true });
5555
const exitStatus = builder.build();

src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts

Lines changed: 31 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -10,76 +10,47 @@ namespace ts {
1010
});
1111

1212
function verifyEmitDeclarationOnly(disableMap?: true) {
13-
verifyTsbuildOutput({
14-
scenario: `only dts output in circular import project with emitDeclarationOnly${disableMap ? "" : " and declarationMap"}`,
15-
projFs: () => projFs,
16-
time,
13+
verifyTscIncrementalEdits({
14+
subScenario: `only dts output in circular import project with emitDeclarationOnly${disableMap ? "" : " and declarationMap"}`,
15+
fs: () => projFs,
1716
tick,
18-
proj: "emitDeclarationOnly",
19-
rootNames: ["/src"],
20-
initialBuild: {
21-
modifyFs: disableMap ?
22-
(fs => replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) :
23-
noop,
24-
expectedDiagnostics: [
25-
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
26-
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tsconfig.json", "src/lib/a.d.ts"],
27-
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
28-
]
29-
},
30-
incrementalDtsChangedBuild: {
17+
scenario: "emitDeclarationOnly",
18+
commandLineArgs: ["--b", "/src", "--verbose"],
19+
modifyFs: disableMap ?
20+
(fs => replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) :
21+
undefined,
22+
incrementalScenarios: [{
23+
buildKind: BuildKind.IncrementalDtsChange,
3124
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
32-
expectedDiagnostics: [
33-
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
34-
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tsconfig.json", "src/lib/a.d.ts", "src/src/a.ts"],
35-
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
36-
]
37-
},
38-
baselineOnly: true,
39-
verifyDiagnostics: true
25+
}],
4026
});
4127
}
4228
verifyEmitDeclarationOnly();
4329
verifyEmitDeclarationOnly(/*disableMap*/ true);
4430

45-
verifyTsbuildOutput({
46-
scenario: `only dts output in non circular imports project with emitDeclarationOnly`,
47-
projFs: () => projFs,
48-
time,
31+
verifyTscIncrementalEdits({
32+
subScenario: `only dts output in non circular imports project with emitDeclarationOnly`,
33+
fs: () => projFs,
4934
tick,
50-
proj: "emitDeclarationOnly",
51-
rootNames: ["/src"],
52-
initialBuild: {
53-
modifyFs: fs => {
54-
fs.rimrafSync("/src/src/index.ts");
55-
replaceText(fs, "/src/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`);
56-
},
57-
expectedDiagnostics: [
58-
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
59-
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tsconfig.json", "src/lib/a.d.ts"],
60-
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
61-
]
35+
scenario: "emitDeclarationOnly",
36+
commandLineArgs: ["--b", "/src", "--verbose"],
37+
modifyFs: fs => {
38+
fs.rimrafSync("/src/src/index.ts");
39+
replaceText(fs, "/src/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`);
6240
},
63-
incrementalDtsChangedBuild: {
64-
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
65-
expectedDiagnostics: [
66-
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
67-
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tsconfig.json", "src/lib/a.d.ts", "src/src/a.ts"],
68-
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
69-
]
70-
},
71-
incrementalDtsUnchangedBuild: {
72-
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "export interface A {", `class C { }
41+
incrementalScenarios: [
42+
{
43+
buildKind: BuildKind.IncrementalDtsChange,
44+
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
45+
46+
},
47+
{
48+
buildKind: BuildKind.IncrementalDtsUnchanged,
49+
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "export interface A {", `class C { }
7350
export interface A {`),
74-
expectedDiagnostics: [
75-
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
76-
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tsconfig.json", "src/lib/a.d.ts", "src/src/a.ts"],
77-
[Diagnostics.Building_project_0, "/src/tsconfig.json"],
78-
[Diagnostics.Updating_unchanged_output_timestamps_of_project_0, "/src/tsconfig.json"]
79-
]
80-
},
81-
baselineOnly: true,
82-
verifyDiagnostics: true
51+
52+
},
53+
],
8354
});
8455
});
8556
}

src/testRunner/unittests/tsbuild/emptyFiles.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace ts {
1010
describe("unittests:: tsbuild - empty files option in tsconfig", () => {
1111
it("has empty files diagnostic when files is empty and no references are provided", () => {
1212
const fs = projFs.shadow();
13-
const host = new fakes.SolutionBuilderHost(fs);
13+
const host = fakes.SolutionBuilderHost.create(fs);
1414
const builder = createSolutionBuilder(host, ["/src/no-references"], { dry: false, force: false, verbose: false });
1515

1616
host.clearDiagnostics();
@@ -26,7 +26,7 @@ namespace ts {
2626

2727
it("does not have empty files diagnostic when files is empty and references are provided", () => {
2828
const fs = projFs.shadow();
29-
const host = new fakes.SolutionBuilderHost(fs);
29+
const host = fakes.SolutionBuilderHost.create(fs);
3030
const builder = createSolutionBuilder(host, ["/src/with-references"], { dry: false, force: false, verbose: false });
3131

3232
host.clearDiagnostics();

0 commit comments

Comments
 (0)