Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/filesystem/node/test/mockFileSystemService.ts
13405 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import type { FileStat, FileSystemWatcher } from 'vscode';
7
import { basename, dirname } from '../../../../util/vs/base/common/resources';
8
import { URI } from '../../../../util/vs/base/common/uri';
9
import { IFileSystemService } from '../../common/fileSystemService';
10
import { FileType } from '../../common/fileTypes';
11
12
export class MockFileSystemService implements IFileSystemService {
13
_serviceBrand: undefined;
14
15
private mockDirs = new Map<string, [string, FileType][]>();
16
private mockFiles = new Map<string, string>();
17
private mockErrors = new Map<string, Error>();
18
private mockMtimes = new Map<string, number>();
19
private statCalls = 0;
20
21
mockDirectory(uri: URI | string, entries: [string, FileType][]) {
22
const uriString = typeof uri === 'string' ? uri : uri.toString();
23
this.mockDirs.set(uriString, entries);
24
}
25
26
mockFile(uri: URI | string, contents: string, mtime?: number) {
27
const uriString = typeof uri === 'string' ? uri : uri.toString();
28
this.mockFiles.set(uriString, contents);
29
if (mtime !== undefined) {
30
this.mockMtimes.set(uriString, mtime);
31
}
32
}
33
34
mockError(uri: URI | string, error: Error) {
35
const uriString = typeof uri === 'string' ? uri : uri.toString();
36
this.mockErrors.set(uriString, error);
37
}
38
39
getStatCallCount(): number {
40
return this.statCalls;
41
}
42
43
resetStatCallCount(): void {
44
this.statCalls = 0;
45
}
46
47
async readDirectory(uri: URI): Promise<[string, FileType][]> {
48
const uriString = uri.toString();
49
if (this.mockErrors.has(uriString)) {
50
throw this.mockErrors.get(uriString);
51
}
52
return this.mockDirs.get(uriString) || [];
53
}
54
55
async readFile(uri: URI, disableLimit?: boolean): Promise<Uint8Array> {
56
const uriString = uri.toString();
57
if (this.mockErrors.has(uriString)) {
58
throw this.mockErrors.get(uriString);
59
}
60
const contents = this.mockFiles.get(uriString);
61
if (contents === undefined) {
62
throw new Error('ENOENT');
63
}
64
return new TextEncoder().encode(contents);
65
}
66
67
async stat(uri: URI): Promise<FileStat> {
68
this.statCalls++; // Track stat calls to verify caching
69
const uriString = uri.toString();
70
if (this.mockErrors.has(uriString)) {
71
throw this.mockErrors.get(uriString);
72
}
73
if (this.mockFiles.has(uriString)) {
74
const contents = this.mockFiles.get(uriString)!;
75
const mtime = this.mockMtimes.get(uriString) ?? Date.now();
76
return { type: FileType.File as unknown as FileType, ctime: Date.now() - 1000, mtime, size: contents.length };
77
}
78
if (this.mockDirs.has(uriString)) {
79
const mtime = this.mockMtimes.get(uriString) ?? Date.now();
80
return { type: FileType.Directory as unknown as FileType, ctime: Date.now() - 1000, mtime, size: 0 };
81
}
82
throw new Error('ENOENT');
83
}
84
85
// Required interface methods
86
isWritableFileSystem(): boolean | undefined { return true; }
87
createFileSystemWatcher(): FileSystemWatcher { throw new Error('not implemented'); }
88
89
async createDirectory(uri: URI): Promise<void> {
90
const uriString = uri.toString();
91
92
// Recursively ensure parent directories exist first
93
const parentUri = dirname(uri);
94
if (parentUri && parentUri.toString() !== uriString) {
95
if (!this.mockDirs.has(parentUri.toString())) {
96
await this.createDirectory(parentUri);
97
}
98
99
const entries = this.mockDirs.get(parentUri.toString())!;
100
const bname = basename(uri);
101
if (!entries.find(e => e[0] === bname)) {
102
entries.push([bname, FileType.Directory]);
103
}
104
}
105
106
// Mark as directory by adding empty entry list
107
if (!this.mockDirs.has(uriString)) {
108
this.mockDirs.set(uriString, []);
109
// Store creation time for stat() calls
110
this.mockMtimes.set(uriString, Date.now());
111
}
112
}
113
114
async writeFile(uri: URI, content: Uint8Array): Promise<void> {
115
const uriString = uri.toString();
116
const text = new TextDecoder().decode(content);
117
this.mockFiles.set(uriString, text);
118
// Store write time for stat() calls
119
this.mockMtimes.set(uriString, Date.now());
120
121
// add the file to the mock directory listing of its parent directory
122
const parentUri = uriString.substring(0, uriString.lastIndexOf('/'));
123
if (this.mockDirs.has(parentUri)) {
124
const entries = this.mockDirs.get(parentUri)!;
125
const fileName = uriString.substring(uriString.lastIndexOf('/') + 1);
126
if (!entries.find(e => e[0] === fileName)) {
127
entries.push([fileName, FileType.File]);
128
}
129
} else {
130
this.mockDirs.set(parentUri, [[uriString.substring(uriString.lastIndexOf('/') + 1), FileType.File]]);
131
}
132
}
133
134
async delete(uri: URI, options?: { recursive?: boolean; useTrash?: boolean }): Promise<void> {
135
const uriString = uri.toString();
136
this.mockFiles.delete(uriString);
137
this.mockDirs.delete(uriString);
138
this.mockErrors.delete(uriString);
139
this.mockMtimes.delete(uriString);
140
141
const parentUri = dirname(uri);
142
if (parentUri && this.mockDirs.has(parentUri.toString())) {
143
const entries = this.mockDirs.get(parentUri.toString())!;
144
const bname = basename(uri);
145
this.mockDirs.set(parentUri.toString(), entries.filter(e => e[0] !== bname));
146
}
147
}
148
149
async rename(oldURI: URI, newURI: URI, options?: { overwrite?: boolean }): Promise<void> {
150
const oldUriString = oldURI.toString();
151
const newUriString = newURI.toString();
152
153
// Check if target exists and overwrite is not allowed
154
if (!options?.overwrite && (this.mockFiles.has(newUriString) || this.mockDirs.has(newUriString))) {
155
throw new Error('EEXIST: File exists');
156
}
157
158
// Move file or directory
159
if (this.mockFiles.has(oldUriString)) {
160
const content = this.mockFiles.get(oldUriString)!;
161
this.mockFiles.set(newUriString, content);
162
this.mockFiles.delete(oldUriString);
163
164
if (this.mockMtimes.has(oldUriString)) {
165
const mtime = this.mockMtimes.get(oldUriString)!;
166
this.mockMtimes.set(newUriString, mtime);
167
this.mockMtimes.delete(oldUriString);
168
}
169
} else if (this.mockDirs.has(oldUriString)) {
170
const entries = this.mockDirs.get(oldUriString)!;
171
this.mockDirs.set(newUriString, entries);
172
this.mockDirs.delete(oldUriString);
173
} else {
174
throw new Error('ENOENT: File not found');
175
}
176
}
177
copy(source: URI, destination: URI, options?: { overwrite?: boolean }): Promise<void> {
178
throw new Error('Method not implemented.');
179
}
180
}
181
182