History

[codex] Structure workspace file system errors (#3274)

Julius Marminge committed 4 months ago

Commit cdfecb31 parent f4ef3568 files · +707 −119Browse files

Showing the changes to apps/server/src/workspace/WorkspaceFileSystem.test.ts (1 of 8 files). Show all

Unified · Split

apps/server/src/workspace/WorkspaceFileSystem.test.ts+81−6
@@ -104,14 +104,89 @@ it.layer(TestLayer, { excludeTestServices: true })("WorkspaceFileSystemLive", (i · 103 unmodified lines
104 const error = yield* workspaceFileSystem104 const error = yield* workspaceFileSystem
105 .readFile({ cwd, relativePath: "linked-secret.txt" })105 .readFile({ cwd, relativePath: "linked-secret.txt" })
106 .pipe(Effect.flip);106 .pipe(Effect.flip);
107 const resolvedWorkspaceRoot = yield* fileSystem.realPath(cwd);
108 const resolvedPath = yield* fileSystem.realPath(path.join(outsideDir, "secret.txt"));
107 109
108 expect(error.message).toBe(110 expect(error).toBeInstanceOf(WorkspaceFileSystem.WorkspaceFilePathEscapeError);
109 `Workspace file operation 'workspaceFileSystem.readFile' failed for 'linked-secret.txt' in '${cwd}'.`,111 expect(error).toMatchObject({
110 );112 workspaceRoot: cwd,
113 relativePath: "linked-secret.txt",
114 resolvedWorkspaceRoot,
115 resolvedPath,
116 });
117 expect("cause" in error).toBe(false);
118 }),
119 );
120
121 it.effect("rejects directories without manufacturing an I/O cause", () =>
122 Effect.gen(function* () {
123 const workspaceFileSystem = yield* WorkspaceFileSystem.WorkspaceFileSystem;
124 const fileSystem = yield* FileSystem.FileSystem;
125 const path = yield* Path.Path;
126 const cwd = yield* makeTempDir;
127 yield* fileSystem.makeDirectory(path.join(cwd, "src"));
128
129 const error = yield* workspaceFileSystem
130 .readFile({ cwd, relativePath: "src" })
131 .pipe(Effect.flip);
132 const resolvedPath = yield* fileSystem.realPath(path.join(cwd, "src"));
133
134 expect(error).toBeInstanceOf(WorkspaceFileSystem.WorkspacePathNotFileError);
135 expect(error).toMatchObject({
136 workspaceRoot: cwd,
137 relativePath: "src",
138 resolvedPath,
139 });
140 expect("cause" in error).toBe(false);
141 }),
142 );
143
144 it.effect("rejects binary files without leaking their contents into the error", () =>
145 Effect.gen(function* () {
146 const workspaceFileSystem = yield* WorkspaceFileSystem.WorkspaceFileSystem;
147 const fileSystem = yield* FileSystem.FileSystem;
148 const path = yield* Path.Path;
149 const cwd = yield* makeTempDir;
150 const absolutePath = path.join(cwd, "asset.bin");
151 yield* fileSystem.writeFile(absolutePath, Uint8Array.from([0x61, 0, 0x62]));
152
153 const error = yield* workspaceFileSystem
154 .readFile({ cwd, relativePath: "asset.bin" })
155 .pipe(Effect.flip);
156 const resolvedPath = yield* fileSystem.realPath(absolutePath);
157
158 expect(error).toBeInstanceOf(WorkspaceFileSystem.WorkspaceBinaryFileError);
159 expect(error).toMatchObject({
160 workspaceRoot: cwd,
161 relativePath: "asset.bin",
162 resolvedPath,
163 });
164 expect("cause" in error).toBe(false);
165 expect("contents" in error).toBe(false);
166 }),
167 );
168
169 it.effect("preserves the real cause and path for I/O failures", () =>
170 Effect.gen(function* () {
171 const workspaceFileSystem = yield* WorkspaceFileSystem.WorkspaceFileSystem;
172 const path = yield* Path.Path;
173 const cwd = yield* makeTempDir;
174 const resolvedPath = path.join(cwd, "missing.txt");
175
176 const error = yield* workspaceFileSystem
177 .readFile({ cwd, relativePath: "missing.txt" })
178 .pipe(Effect.flip);
179
180 expect(error).toBeInstanceOf(WorkspaceFileSystem.WorkspaceFileSystemOperationError);
181 expect(error).toMatchObject({
182 workspaceRoot: cwd,
183 relativePath: "missing.txt",
184 resolvedPath,
185 operationPath: resolvedPath,
186 operation: "realpath-target",
187 });
111 expect(error.cause).toBeInstanceOf(Error);188 expect(error.cause).toBeInstanceOf(Error);
112 expect((error.cause as Error).message).toBe(189 expect((error.cause as NodeJS.ErrnoException).code).toBe("ENOENT");
113 "Workspace file path resolves outside the project root.",
114 );
115 }),190 }),
116 );191 );
117 });192 });