Handles time on vfs and write non empty shadowed files in baseline even if they were not read (#48703)

* Use fixed time for vfs so baselining is consistent

* Baseline buildinfos

* Write new file text in baseline even if the file wasnt read on the shadow

* Remove unnecessary debugger statement
This commit is contained in:
Sheetal Nandi
2022-04-21 11:50:28 -07:00
committed by GitHub
parent 7a59e45f48
commit ab2523bbe0
130 changed files with 5601 additions and 1696 deletions

View File

@@ -55,12 +55,12 @@ namespace vfs {
} = {};
private _cwd: string; // current working directory
private _time: number | Date | (() => number | Date);
private _time: number;
private _shadowRoot: FileSystem | undefined;
private _dirStack: string[] | undefined;
constructor(ignoreCase: boolean, options: FileSystemOptions = {}) {
const { time = -1, files, meta } = options;
const { time = ts.TestFSWithWatch.timeIncrements, files, meta } = options;
this.ignoreCase = ignoreCase;
this.stringComparer = this.ignoreCase ? vpath.compareCaseInsensitive : vpath.compareCaseSensitive;
this._time = time;
@@ -167,16 +167,15 @@ namespace vfs {
*
* @link http://pubs.opengroup.org/onlinepubs/9699919799/functions/time.html
*/
public time(value?: number | Date | (() => number | Date)): number {
if (value !== undefined && this.isReadonly) throw createIOError("EPERM");
let result = this._time;
if (typeof result === "function") result = result();
if (typeof result === "object") result = result.getTime();
if (result === -1) result = Date.now();
public time(value?: number): number {
if (value !== undefined) {
if (this.isReadonly) throw createIOError("EPERM");
this._time = value;
}
return result;
else if (!this.isReadonly) {
this._time += ts.TestFSWithWatch.timeIncrements;
}
return this._time;
}
/**
@@ -843,7 +842,7 @@ namespace vfs {
container[basename] = new Symlink(node.symlink);
}
else {
container[basename] = new File(node.buffer || "");
container[basename] = new File(changed._getBuffer(node));
}
return true;
}
@@ -1172,9 +1171,8 @@ namespace vfs {
}
export interface FileSystemOptions {
// Sets the initial timestamp for new files and directories, or the function used
// to calculate timestamps.
time?: number | Date | (() => number | Date);
// Sets the initial timestamp for new files and directories
time?: number;
// A set of file system entries to initially add to the file system.
files?: FileSet;

View File

@@ -360,7 +360,7 @@ interface Array<T> { length: number; [n: number]: T; }`
DynamicPolling = "RecursiveDirectoryUsingDynamicPriorityPolling"
}
const timeIncrements = 1000;
export const timeIncrements = 1000;
export interface TestServerHostOptions {
useCaseSensitiveFileNames: boolean;
executingFilePath: string;

View File

@@ -78,26 +78,6 @@ namespace ts {
};
}
export function getTime() {
let currentTime = 100;
return { tick, time, touch };
function tick() {
currentTime += 60_000;
}
function time() {
return currentTime;
}
function touch(fs: vfs.FileSystem, path: string) {
if (!fs.statSync(path).isFile()) {
throw new Error(`File ${path} does not exist`);
}
fs.utimesSync(path, new Date(time()), new Date(time()));
}
}
export const libContent = `${TestFSWithWatch.libFile.content}
interface ReadonlyArray<T> {}
declare const console: { log(msg: any): void; };`;
@@ -154,26 +134,6 @@ interface Symbol {
fs.makeReadonly();
}
/**
* Gets the FS mountuing existing fs's /src and /lib folder
*/
export function getFsWithTime(baseFs: vfs.FileSystem) {
const { time, tick } = getTime();
const host = new fakes.System(baseFs) as any as vfs.FileSystemResolverHost;
host.getWorkspaceRoot = notImplemented;
const resolver = vfs.createResolver(host);
const fs = new vfs.FileSystem(/*ignoreCase*/ true, {
files: {
["/src"]: new vfs.Mount("/src", resolver),
["/lib"]: new vfs.Mount("/lib", resolver)
},
cwd: "/",
meta: { defaultLibLocation: "/lib" },
time
});
return { fs, time, tick };
}
export function verifyOutputsPresent(fs: vfs.FileSystem, outputs: readonly string[]) {
for (const output of outputs) {
assert(fs.existsSync(output), `Expect file ${output} to exist`);
@@ -336,7 +296,6 @@ interface Symbol {
commandLineArgs: TestTscCompile["commandLineArgs"];
modifyFs: TestTscCompile["modifyFs"];
editFs: TestTscEdit["modifyFs"];
tick: () => void;
baseFs: vfs.FileSystem;
newSys: TscCompileSystem;
cleanBuildDiscrepancies: TestTscEdit["cleanBuildDiscrepancies"];
@@ -347,7 +306,7 @@ interface Symbol {
const {
scenario, commandLineArgs, cleanBuildDiscrepancies,
modifyFs, editFs,
tick, baseFs, newSys
baseFs, newSys
} = input();
const sys = testTscCompile({
scenario,
@@ -355,7 +314,6 @@ interface Symbol {
fs: () => baseFs.makeReadonly(),
commandLineArgs,
modifyFs: fs => {
tick();
if (modifyFs) modifyFs(fs);
editFs(fs);
},
@@ -532,22 +490,18 @@ interface Symbol {
edits
}: VerifyTscWithEditsWorkerInput) {
describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario} serializedEdits`, () => {
let tick: () => void;
let sys: TscCompileSystem;
let baseFs: vfs.FileSystem;
let editsSys: TscCompileSystem[];
before(() => {
Debug.assert(!!edits.length, `${scenario}/${subScenario}:: No incremental scenarios, you probably want to use verifyTsc instead.`);
({ fs: baseFs, tick } = getFsWithTime(fs()));
baseFs = fs().makeReadonly();
sys = testTscCompile({
scenario,
subScenario,
fs: () => baseFs.makeReadonly(),
fs: () => baseFs,
commandLineArgs,
modifyFs: fs => {
if (modifyFs) modifyFs(fs);
tick();
},
modifyFs,
baselineSourceMap,
baselineReadFileCalls,
baselinePrograms
@@ -556,18 +510,13 @@ interface Symbol {
{ modifyFs, subScenario: editScenario, commandLineArgs: editCommandLineArgs },
index
) => {
tick();
(editsSys || (editsSys = [])).push(testTscCompile({
scenario,
subScenario: editScenario || subScenario,
diffWithInitial: true,
fs: () => index === 0 ? sys.vfs : editsSys[index - 1].vfs,
commandLineArgs: editCommandLineArgs || commandLineArgs,
modifyFs: fs => {
tick();
modifyFs(fs);
tick();
},
modifyFs,
baselineSourceMap,
baselineReadFileCalls,
baselinePrograms
@@ -577,7 +526,6 @@ interface Symbol {
after(() => {
baseFs = undefined!;
sys = undefined!;
tick = undefined!;
editsSys = undefined!;
});
describe("tsc invocation after edit", () => {
@@ -608,7 +556,6 @@ interface Symbol {
}
},
modifyFs,
tick
}), index, subScenario));
});
});

View File

@@ -10,10 +10,6 @@ namespace ts {
outFileWithBuildFs = undefined!;
});
function createSolutionBuilder(host: fakes.SolutionBuilderHost, baseOptions?: BuildOptions) {
return ts.createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: true, ...(baseOptions || {}) });
}
interface VerifyOutFileScenarioInput {
subScenario: string;
modifyFs?: (fs: vfs.FileSystem) => void;
@@ -108,8 +104,9 @@ namespace ts {
function getOutFileFsAfterBuild() {
if (outFileWithBuildFs) return outFileWithBuildFs;
const fs = outFileFs.shadow();
const host = fakes.SolutionBuilderHost.create(fs);
const builder = createSolutionBuilder(host);
const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc" });
const host = createSolutionBuilderHostForBaseline(sys as TscCompileSystem);
const builder = createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: true });
builder.build();
fs.makeReadonly();
return outFileWithBuildFs = fs;
@@ -147,7 +144,7 @@ namespace ts {
compile: sys => {
// Buildinfo will have version which does not match with current ts version
const buildHost = createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion");
const builder = ts.createSolutionBuilder(buildHost, ["/src/third"], { verbose: true });
const builder = createSolutionBuilder(buildHost, ["/src/third"], { verbose: true });
sys.exit(builder.build());
}
});
@@ -181,7 +178,7 @@ namespace ts {
commandLineArgs: ["--build", "/src/second/tsconfig.json"],
compile: sys => {
const buildHost = createSolutionBuilderHostForBaseline(sys);
const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {});
const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {});
sys.exit(builder.build("/src/second/tsconfig.json"));
}
});
@@ -193,7 +190,7 @@ namespace ts {
commandLineArgs: ["--build", "--clean", "/src/second/tsconfig.json"],
compile: sys => {
const buildHost = createSolutionBuilderHostForBaseline(sys);
const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], { verbose: true });
const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], { verbose: true });
sys.exit(builder.clean("/src/second/tsconfig.json"));
}
});

View File

@@ -2,7 +2,7 @@ namespace ts {
describe("unittests:: tsbuild:: Public API with custom transformers when passed to build", () => {
let sys: TscCompileSystem;
before(() => {
const initialFs = getFsWithTime(loadProjectFromFiles({
const inputFs = loadProjectFromFiles({
"/src/tsconfig.json": JSON.stringify({
references: [
{ path: "./shared/tsconfig.json" },
@@ -29,9 +29,7 @@ export class c2 { }
export enum e2 { }
// leading
export function f22() { } // trailing`,
})).fs.makeReadonly();
const inputFs = initialFs.shadow();
inputFs.makeReadonly();
}).makeReadonly();
const fs = inputFs.shadow();
// Create system

View File

@@ -21,7 +21,8 @@ namespace ts {
function getSampleFsAfterBuild() {
if (projFsWithBuild) return projFsWithBuild;
const fs = projFs.shadow();
const host = fakes.SolutionBuilderHost.create(fs);
const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc" });
const host = createSolutionBuilderHostForBaseline(sys as TscCompileSystem);
const builder = createSolutionBuilder(host, ["/src/tests"], {});
builder.build();
fs.makeReadonly();

View File

@@ -214,7 +214,7 @@ ${patch ? vfs.formatPatch(patch) : ""}`
describe(input.subScenario, () => {
verifyTscBaseline(() => verifier({
...input,
fs: () => getFsWithTime(input.fs()).fs.makeReadonly()
fs: () => input.fs().makeReadonly()
}));
});
});