Skip to content

Commit 25d7928

Browse files
committed
Add helper to baseline serialized invocations of tsc on incremental edits
1 parent fc82093 commit 25d7928

File tree

91 files changed

+4177
-3798
lines changed

Some content is hidden

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

91 files changed

+4177
-3798
lines changed

src/testRunner/unittests/tsbuild/containerOnlyReferenced.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace ts {
22
describe("unittests:: tsbuild:: when containerOnly project is referenced", () => {
3-
verifyTscIncrementalEdits({
3+
verifyTscSerializedIncrementalEdits({
44
scenario: "containerOnlyReferenced",
55
subScenario: "verify that subsequent builds after initial build doesnt build anything",
66
fs: () => loadProjectFromDisk("tests/projects/containerOnlyReferenced"),

src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace ts {
99
});
1010

1111
function verifyEmitDeclarationOnly(disableMap?: true) {
12-
verifyTscIncrementalEdits({
12+
verifyTscSerializedIncrementalEdits({
1313
subScenario: `only dts output in circular import project with emitDeclarationOnly${disableMap ? "" : " and declarationMap"}`,
1414
fs: () => projFs,
1515
scenario: "emitDeclarationOnly",
@@ -26,7 +26,7 @@ namespace ts {
2626
verifyEmitDeclarationOnly();
2727
verifyEmitDeclarationOnly(/*disableMap*/ true);
2828

29-
verifyTscIncrementalEdits({
29+
verifyTscSerializedIncrementalEdits({
3030
subScenario: `only dts output in non circular imports project with emitDeclarationOnly`,
3131
fs: () => projFs,
3232
scenario: "emitDeclarationOnly",
@@ -36,17 +36,17 @@ namespace ts {
3636
replaceText(fs, "/src/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`);
3737
},
3838
incrementalScenarios: [
39-
{
40-
buildKind: BuildKind.IncrementalDtsChange,
41-
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
42-
43-
},
4439
{
4540
buildKind: BuildKind.IncrementalDtsUnchanged,
4641
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "export interface A {", `class C { }
4742
export interface A {`),
4843

4944
},
45+
{
46+
buildKind: BuildKind.IncrementalDtsChange,
47+
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
48+
49+
},
5050
],
5151
});
5252
});

src/testRunner/unittests/tsbuild/helpers.ts

Lines changed: 145 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,42 @@ interface Symbol {
260260
sys.writeFile(`${buildInfoPath}.baseline.txt`, text);
261261
}
262262

263+
interface VerifyIncrementalCorrectness {
264+
scenario: TscCompile["scenario"];
265+
subScenario: TscCompile["subScenario"];
266+
commandLineArgs: TscCompile["commandLineArgs"];
267+
modifyFs: TscCompile["modifyFs"];
268+
incrementalModifyFs: TscIncremental["modifyFs"];
269+
tick: () => void;
270+
baseFs: vfs.FileSystem;
271+
newSys: TscCompileSystem;
272+
}
273+
function verifyIncrementalCorrectness(input: () => VerifyIncrementalCorrectness) {
274+
it(`Verify emit output file text is same when built clean`, () => {
275+
const {
276+
scenario, subScenario, commandLineArgs,
277+
modifyFs, incrementalModifyFs,
278+
tick, baseFs, newSys
279+
} = input();
280+
const sys = tscCompile({
281+
scenario,
282+
subScenario,
283+
fs: () => baseFs.makeReadonly(),
284+
commandLineArgs,
285+
modifyFs: fs => {
286+
tick();
287+
if (modifyFs) modifyFs(fs);
288+
incrementalModifyFs(fs);
289+
},
290+
});
291+
for (const outputFile of arrayFrom(sys.writtenFiles.keys())) {
292+
const expectedText = sys.readFile(outputFile);
293+
const actualText = newSys.readFile(outputFile);
294+
assert.equal(actualText, expectedText, `File: ${outputFile}`);
295+
}
296+
});
297+
}
298+
263299
export interface TscIncremental {
264300
buildKind: BuildKind;
265301
modifyFs: (fs: vfs.FileSystem) => void;
@@ -351,30 +387,120 @@ interface Symbol {
351387
newSys = undefined!;
352388
});
353389
verifyTscBaseline(() => newSys);
354-
it(`Verify emit output file text is same when built clean`, () => {
355-
const sys = tscCompile({
356-
scenario,
357-
subScenario,
358-
fs: () => baseFs.makeReadonly(),
359-
commandLineArgs,
360-
modifyFs: fs => {
361-
tick();
362-
if (modifyFs) modifyFs(fs);
363-
incrementalModifyFs(fs);
364-
},
365-
});
366-
367-
for (const outputFile of arrayFrom(sys.writtenFiles.keys())) {
368-
const expectedText = sys.readFile(outputFile);
369-
const actualText = newSys.readFile(outputFile);
370-
assert.equal(actualText, expectedText, `File: ${outputFile}`);
371-
}
372-
});
390+
verifyIncrementalCorrectness(() => ({
391+
scenario,
392+
subScenario,
393+
baseFs,
394+
newSys,
395+
commandLineArgs,
396+
incrementalModifyFs,
397+
modifyFs,
398+
tick
399+
}));
373400
});
374401
}
375402
});
376403
}
377404

405+
export function verifyTscSerializedIncrementalEdits(input: VerifyTsBuildInput) {
406+
verifyTscSerializedIncrementalEditsWorker(input);
407+
if (input.baselineIncremental) {
408+
verifyTscSerializedIncrementalEditsWorker({
409+
...input,
410+
subScenario: `${input.subScenario} with incremental`,
411+
commandLineArgs: [...input.commandLineArgs, "--incremental"],
412+
});
413+
}
414+
}
415+
function verifyTscSerializedIncrementalEditsWorker({
416+
subScenario, fs, scenario, commandLineArgs,
417+
baselineSourceMap, modifyFs, baselineReadFileCalls, baselinePrograms,
418+
incrementalScenarios
419+
}: VerifyTsBuildInputWorker) {
420+
describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario} serializedEdits`, () => {
421+
Debug.assert(!!incrementalScenarios.length, `${scenario}/${subScenario}:: No incremental scenarios, you probably want to use verifyTsc instead.`);
422+
let tick: () => void;
423+
let sys: TscCompileSystem;
424+
let baseFs: vfs.FileSystem;
425+
let incrementalSys: TscCompileSystem[];
426+
before(() => {
427+
({ fs: baseFs, tick } = getFsWithTime(fs()));
428+
sys = tscCompile({
429+
scenario,
430+
subScenario,
431+
fs: () => baseFs.makeReadonly(),
432+
commandLineArgs,
433+
modifyFs: fs => {
434+
if (modifyFs) modifyFs(fs);
435+
tick();
436+
},
437+
baselineSourceMap,
438+
baselineReadFileCalls,
439+
baselinePrograms
440+
});
441+
incrementalScenarios.forEach((
442+
{ buildKind, modifyFs, subScenario: incrementalSubScenario, commandLineArgs: incrementalCommandLineArgs },
443+
index
444+
) => {
445+
Debug.assert(buildKind !== BuildKind.Initial, "Incremental edit cannot be initial compilation");
446+
tick();
447+
(incrementalSys || (incrementalSys = [])).push(tscCompile({
448+
scenario,
449+
subScenario: incrementalSubScenario || subScenario,
450+
buildKind,
451+
fs: () => index === 0 ? sys.vfs : incrementalSys[index - 1].vfs,
452+
commandLineArgs: incrementalCommandLineArgs || commandLineArgs,
453+
modifyFs: fs => {
454+
tick();
455+
modifyFs(fs);
456+
tick();
457+
},
458+
baselineSourceMap,
459+
baselineReadFileCalls,
460+
baselinePrograms
461+
}));
462+
});
463+
});
464+
after(() => {
465+
baseFs = undefined!;
466+
sys = undefined!;
467+
tick = undefined!;
468+
incrementalSys = undefined!;
469+
});
470+
describe("serializedBuilde", () => {
471+
verifyTscBaseline(() => ({
472+
baseLine: () => {
473+
const { file, text } = sys.baseLine();
474+
const texts: string[] = [text];
475+
incrementalSys.forEach((sys, index) => {
476+
const incrementalScenario = incrementalScenarios[index];
477+
texts.push("");
478+
texts.push(`Change:: ${incrementalScenario.subScenario || incrementalScenario.buildKind}`);
479+
texts.push(sys.baseLine().text);
480+
});
481+
return { file, text: texts.join("\r\n") };
482+
}
483+
}));
484+
});
485+
describe("incremental correctness", () => {
486+
incrementalScenarios.forEach((_, index) => verifyIncrementalCorrectness(() => ({
487+
scenario,
488+
subScenario,
489+
baseFs,
490+
newSys: incrementalSys[index],
491+
commandLineArgs,
492+
incrementalModifyFs: fs => {
493+
for (let i = 0; i <= index; i++) {
494+
incrementalScenarios[i].modifyFs(fs);
495+
}
496+
},
497+
modifyFs,
498+
tick
499+
})));
500+
});
501+
});
502+
}
503+
378504
export function enableStrict(fs: vfs.FileSystem, path: string) {
379505
replaceText(fs, path, `"strict": false`, `"strict": true`);
380506
}

src/testRunner/unittests/tsbuild/inferredTypeFromTransitiveModule.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace ts {
88
projFs = undefined!;
99
});
1010

11-
verifyTscIncrementalEdits({
11+
verifyTscSerializedIncrementalEdits({
1212
scenario: "inferredTypeFromTransitiveModule",
1313
subScenario: "inferred type from transitive module",
1414
fs: () => projFs,
@@ -19,7 +19,7 @@ namespace ts {
1919
}],
2020
});
2121

22-
verifyTscIncrementalEdits({
22+
verifyTscSerializedIncrementalEdits({
2323
subScenario: "inferred type from transitive module with isolatedModules",
2424
fs: () => projFs,
2525
scenario: "inferredTypeFromTransitiveModule",
@@ -31,7 +31,7 @@ namespace ts {
3131
}]
3232
});
3333

34-
verifyTscIncrementalEdits({
34+
verifyTscSerializedIncrementalEdits({
3535
scenario: "inferredTypeFromTransitiveModule",
3636
subScenario: "reports errors in files affected by change in signature with isolatedModules",
3737
fs: () => projFs,

src/testRunner/unittests/tsbuild/javascriptProjectEmit.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ namespace ts {
183183
fs: () => projFs,
184184
commandLineArgs: ["-b", "/src"]
185185
});
186-
verifyTscIncrementalEdits({
186+
verifyTscSerializedIncrementalEdits({
187187
scenario: "javascriptProjectEmit",
188188
subScenario: `modifies outfile js projects and concatenates them correctly`,
189189
fs: () => projFs,

src/testRunner/unittests/tsbuild/lateBoundSymbol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace ts {
22
describe("unittests:: tsbuild:: lateBoundSymbol:: interface is merged and contains late bound member", () => {
3-
verifyTscIncrementalEdits({
3+
verifyTscSerializedIncrementalEdits({
44
subScenario: "interface is merged and contains late bound member",
55
fs: () => loadProjectFromDisk("tests/projects/lateBoundSymbol"),
66
scenario: "lateBoundSymbol",

src/testRunner/unittests/tsbuild/noEmitOnError.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,41 @@ namespace ts {
88
projFs = undefined!;
99
});
1010

11-
function verifyNoEmitOnError(subScenario: string, incrementalScenario: TscIncremental, modifyFs?: TscIncremental["modifyFs"]) {
12-
verifyTscIncrementalEdits({
11+
function verifyNoEmitOnError(subScenario: string, fixModifyFs: TscIncremental["modifyFs"], modifyFs?: TscIncremental["modifyFs"]) {
12+
verifyTscSerializedIncrementalEdits({
1313
scenario: "noEmitOnError",
1414
subScenario,
1515
fs: () => projFs,
1616
modifyFs,
1717
commandLineArgs: ["--b", "/src/tsconfig.json"],
1818
incrementalScenarios: [
19-
incrementalScenario,
19+
noChangeRun,
20+
{
21+
subScenario: "Fix error",
22+
buildKind: BuildKind.IncrementalDtsChange,
23+
modifyFs: fixModifyFs,
24+
},
2025
noChangeRun,
2126
],
2227
baselinePrograms: true,
2328
baselineIncremental: true
2429
});
2530
}
2631

27-
verifyNoEmitOnError("syntax errors", {
28-
buildKind: BuildKind.IncrementalDtsUnchanged,
29-
modifyFs: fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";
32+
verifyNoEmitOnError(
33+
"syntax errors",
34+
fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";
3035
const a = {
3136
lastName: 'sdsd'
3237
};`, "utf-8")
33-
});
38+
);
3439

35-
verifyNoEmitOnError("semantic errors", {
36-
buildKind: BuildKind.IncrementalDtsUnchanged,
37-
modifyFs: fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";
38-
const a: string = "hello";`, "utf-8")
39-
}, fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";
40-
const a: string = 10;`, "utf-8"));
40+
verifyNoEmitOnError(
41+
"semantic errors",
42+
fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";
43+
const a: string = "hello";`, "utf-8"),
44+
fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";
45+
const a: string = 10;`, "utf-8")
46+
);
4147
});
4248
}

src/testRunner/unittests/tsbuild/outFile.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ namespace ts {
169169
return fs;
170170
}
171171

172-
verifyTscIncrementalEdits({
172+
verifyTscSerializedIncrementalEdits({
173173
scenario: "outFile",
174174
subScenario: "clean projects",
175175
fs: getOutFileFsAfterBuild,

src/testRunner/unittests/tsbuild/resolveJsonModule.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export default hello.hello`);
5151
commandLineArgs: ["--b", "/src/tsconfig_withIncludeAndFiles.json"],
5252
});
5353

54-
verifyTscIncrementalEdits({
54+
verifyTscSerializedIncrementalEdits({
5555
scenario: "resolveJsonModule",
5656
subScenario: "sourcemap",
5757
fs: () => projFs,
@@ -60,7 +60,7 @@ export default hello.hello`);
6060
incrementalScenarios: noChangeOnlyRuns
6161
});
6262

63-
verifyTscIncrementalEdits({
63+
verifyTscSerializedIncrementalEdits({
6464
scenario: "resolveJsonModule",
6565
subScenario: "without outDir",
6666
fs: () => projFs,
@@ -71,7 +71,7 @@ export default hello.hello`);
7171
});
7272

7373
describe("unittests:: tsbuild:: with resolveJsonModule option on project importJsonFromProjectReference", () => {
74-
verifyTscIncrementalEdits({
74+
verifyTscSerializedIncrementalEdits({
7575
scenario: "resolveJsonModule",
7676
subScenario: "importing json module from project reference",
7777
fs: () => loadProjectFromDisk("tests/projects/importJsonFromProjectReference"),

0 commit comments

Comments
 (0)