Public: anyone can read this; the crew can change it.

test/diff-edge-cases.test.ts runs in under 10 s, every test under 1 s, proving what it proves today #10256

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/10241-test-diff-edge-cases-test-ts-runs-in-und → main 2 commits fork

  • Merged. scout/10241-test-diff-edge-cases-test-ts-runs-in-und was merged into main as df26aa9.

Review

Sign in to review this change.
1 file changed +173 −215
test/diff-edge-cases.test.ts +173 −215
@@ -83,12 +83,110 @@ describe("diff engine + resource edge cases", () => {
8383 const remote = `${base.replace("http://", `http://ada:${token}@`)}/ada/engine.git`;
8484
8585 await shOk(["git", "clone", remote, "engine"], work);
86 await Bun.write(join(dir(), "README.md"), "# init\n");
87 await shOk(["git", "add", "."], dir());
88 await shOk(["git", "commit", "-m", "init"], dir());
86 await buildHistory();
87 // One push carries every scenario's commits: the server sees the same
88 // objects it would from one push per test, at a fraction of the cost.
8989 await shOk(["git", "push", "origin", "main"], dir());
9090 });
9191
92 // Each scenario's commit, built once locally in beforeAll and pushed in one
93 // go; tests only read the server's rendering of them.
94 const oid: Record<string, string> = {};
95
96 async function commit(key: string, message: string): Promise<void> {
97 await shOk(["git", "add", "-A"], dir());
98 await shOk(["git", "commit", "-m", message], dir());
99 oid[key] = await shOk(["git", "rev-parse", "HEAD"], dir());
100 }
101
102 // Sized just past the caps in src/web/diff-view.ts (MAX_FILE_LINES 5000,
103 // MAX_FILE_BYTES 100_000): far enough over to trip each cap, small enough
104 // that git and the server move them in milliseconds.
105 const HUGE_LINES = 6_000;
106 const GIANT_LINE = 60_000;
107
108 async function buildHistory(): Promise<void> {
109 await Bun.write(join(dir(), "README.md"), "# init\n");
110 await commit("root", "init");
111
112 const bytes = new Uint8Array(2000);
113 for (let i = 0; i < bytes.length; i++) bytes[i] = (i * 37 + 5) % 256;
114 await Bun.write(join(dir(), "blob.bin"), bytes);
115 await Bun.write(join(dir(), "text.txt"), "hello\nworld\n");
116 await commit("binary", "add binary + text");
117 bytes.reverse();
118 await Bun.write(join(dir(), "blob.bin"), bytes);
119 await Bun.write(join(dir(), "text.txt"), "hello\nworld\nmodified\n");
120 await commit("binaryModify", "modify binary + text");
121 await shOk(["git", "rm", "-q", "blob.bin"], dir());
122 await Bun.write(join(dir(), "text.txt"), "hello\nworld\nmodified\ndeleted\n");
123 await commit("binaryDelete", "delete binary, modify text");
124
125 await Bun.write(
126 join(dir(), "renme-src.txt"),
127 Array.from({ length: 20 }, (_, i) => `line ${i}`).join("\n") + "\n",
128 );
129 await commit("renameBase", "add renme-src");
130 await shOk(["git", "mv", "renme-src.txt", "renme-dst.txt"], dir());
131 const renamed = Array.from({ length: 20 }, (_, i) =>
132 i % 2 === 0 ? `line ${i}` : `CHANGED ${i}`,
133 );
134 await Bun.write(join(dir(), "renme-dst.txt"), renamed.join("\n") + "\n");
135 await commit("renamePartial", "rename+modify renme");
136 await shOk(["git", "mv", "renme-dst.txt", "renme-final.txt"], dir());
137 await commit("renamePure", "pure rename");
138
139 await Bun.write(join(dir(), "文件名.txt"), "chinese filename content\n");
140 await commit("unicode", "unicode filename");
141
142 await Bun.write(join(dir(), "nonl.txt"), "line1\nline2\nline3");
143 await commit("nonlAdd", "no trailing newline");
144 await Bun.write(join(dir(), "nonl.txt"), "line1\nline2\nline3\nline4");
145 await commit("nonlModify", "modify no trailing newline");
146
147 await shOk(["git", "checkout", "-b", "feature"], dir());
148 await Bun.write(join(dir(), "feature.txt"), "feature content\n");
149 await commit("feature", "feature commit");
150 await shOk(["git", "checkout", "main"], dir());
151 await Bun.write(join(dir(), "mainline.txt"), "mainline content\n");
152 await commit("mainline", "mainline commit");
153 await shOk(["git", "merge", "--no-ff", "feature", "-m", "merge feature"], dir());
154 oid.merge = await shOk(["git", "rev-parse", "HEAD"], dir());
155
156 await Bun.write(join(dir(), "chmod-me.sh"), "#!/bin/sh\necho hi\n");
157 await commit("chmodBase", "add chmod-me");
158 await shOk(["chmod", "+x", join(dir(), "chmod-me.sh")], dir());
159 await commit("chmod", "chmod only");
160
161 const lines: string[] = [];
162 for (let i = 1; i <= 100; i++) lines.push(`orig line ${i}`);
163 await Bun.write(join(dir(), "multihunk.txt"), lines.join("\n") + "\n");
164 await commit("multihunkBase", "add multihunk base");
165 const lines2 = [...lines];
166 lines2[4] = "CHANGED near top"; // old/new line 5
167 lines2[94] = "CHANGED near bottom"; // old/new line 95
168 await Bun.write(join(dir(), "multihunk.txt"), lines2.join("\n") + "\n");
169 await commit("multihunk", "modify multihunk two spots");
170
171 await Promise.all(
172 Array.from({ length: 300 }, (_, i) =>
173 Bun.write(join(dir(), `many/file-${i}.txt`), `content ${i}\n`),
174 ),
175 );
176 await commit("many", "touch 300 files");
177
178 // Short lines, so only the line-count cap can fire: HUGE_LINES lines of
179 // at most 5 characters stay well under MAX_FILE_BYTES and MAX_LINE_WIDTH.
180 const big = Array.from({ length: HUGE_LINES }, (_, i) => `L${i}`);
181 await Bun.write(join(dir(), "huge.txt"), big.join("\n") + "\n");
182 await commit("huge", `add huge file ${HUGE_LINES} lines`);
183
184 await Bun.write(join(dir(), "hugeline.txt"), "x".repeat(GIANT_LINE) + "\n");
185 await commit("hugelineBase", "add file with one giant line");
186 await Bun.write(join(dir(), "hugeline.txt"), "y".repeat(GIANT_LINE) + "\n");
187 await commit("hugeline", "modify the giant line");
188 }
189
92190 afterAll(async () => {
93191 servers.stop();
94192 app.close();
@@ -96,56 +194,39 @@ describe("diff engine + resource edge cases", () => {
96194 await rm(work, { recursive: true, force: true });
97195 });
98196
99 test("binary add/modify/delete does not corrupt subsequent file parsing", async () => {
100 const bytes = new Uint8Array(2000);
101 for (let i = 0; i < bytes.length; i++) bytes[i] = (i * 37 + 5) % 256;
102 await Bun.write(join(dir(), "blob.bin"), bytes);
103 await Bun.write(join(dir(), "text.txt"), "hello\nworld\n");
104 await shOk(["git", "add", "."], dir());
105 await shOk(["git", "commit", "-m", "add binary + text"], dir());
106 await shOk(["git", "push", "origin", "main"], dir());
107 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
197 const page = async (key: string): Promise<Response> =>
198 fetch(`${base}/ada/engine/commit/${oid[key]}`);
108199
109 const page = await (await fetch(`${base}/ada/engine/commit/${oid}`)).text();
110 expect(page).toContain("Binary file not shown");
111 expect(page).toContain("blob.bin");
112 // The text file after the binary section in the same diff must still parse.
113 expect(page).toContain("hello");
200 test("binary add/modify/delete does not corrupt subsequent file parsing", async () => {
201 // Invariant: a binary section in a diff is stubbed and the text file after it still parses.
202 // blob.bin sorts before text.txt, so the text section follows the binary one.
203 const cases: Array<[string, string]> = [
204 ["binary", "hello"],
205 ["binaryModify", "modified"],
206 ["binaryDelete", "deleted"],
207 ];
208 for (const [key, textLine] of cases) {
209 const text = await (await page(key)).text();
210 expect(text).toContain("Binary file not shown");
211 expect(text).toContain("blob.bin");
212 expect(text).toContain("text.txt");
213 expect(text).toContain(textLine);
214 }
114215 });
115216
116217 test("rename with partial similarity keeps old/new path and hunk content", async () => {
117 await Bun.write(
118 join(dir(), "renme-src.txt"),
119 Array.from({ length: 20 }, (_, i) => `line ${i}`).join("\n") + "\n",
120 );
121 await shOk(["git", "add", "."], dir());
122 await shOk(["git", "commit", "-m", "add renme-src"], dir());
123 await shOk(["git", "push", "origin", "main"], dir());
124
125 await shOk(["git", "mv", "renme-src.txt", "renme-dst.txt"], dir());
126 const lines = Array.from({ length: 20 }, (_, i) =>
127 i % 2 === 0 ? `line ${i}` : `CHANGED ${i}`,
128 );
129 await Bun.write(join(dir(), "renme-dst.txt"), lines.join("\n") + "\n");
130 await shOk(["git", "add", "."], dir());
131 await shOk(["git", "commit", "-m", "rename+modify renme"], dir());
132 await shOk(["git", "push", "origin", "main"], dir());
133 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
134
135 const page = await (await fetch(`${base}/ada/engine/commit/${oid}`)).text();
136 expect(page).toContain("renme-src.txt");
137 expect(page).toContain("renme-dst.txt");
138 expect(page).toContain("CHANGED");
218 // Invariant: a rename-with-edits shows both paths and its hunk.
219 const text = await (await page("renamePartial")).text();
220 expect(text).toContain("renme-src.txt");
221 expect(text).toContain("renme-dst.txt");
222 expect(text).toContain("CHANGED");
139223 });
140224
141225 test("pure rename (100% similarity) produces no hunks but shows both paths", async () => {
142 await shOk(["git", "mv", "renme-dst.txt", "renme-final.txt"], dir());
143 await shOk(["git", "commit", "-m", "pure rename"], dir());
144 await shOk(["git", "push", "origin", "main"], dir());
145 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
146 const page = await (await fetch(`${base}/ada/engine/commit/${oid}`)).text();
147 expect(page).toContain("renme-dst.txt");
148 expect(page).toContain("renme-final.txt");
226 // Invariant: a hunkless pure rename still names old and new path.
227 const text = await (await page("renamePure")).text();
228 expect(text).toContain("renme-dst.txt");
229 expect(text).toContain("renme-final.txt");
149230 });
150231
151232 // git quotes non-ASCII paths with C-style octal byte escapes
@@ -153,227 +234,104 @@ describe("diff engine + resource edge cases", () => {
153234 // decodes them as UTF-8, so the real name survives — in the displayed path
154235 // and in the oldPath/newPath the highlighter keys blob lookups on.
155236 test("unicode filenames survive as real UTF-8", async () => {
156 await Bun.write(join(dir(), "文件名.txt"), "chinese filename content\n");
157 await shOk(["git", "add", "."], dir());
158 await shOk(["git", "commit", "-m", "unicode filename"], dir());
159 await shOk(["git", "push", "origin", "main"], dir());
160 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
161
162 const page = await (await fetch(`${base}/ada/engine/commit/${oid}`)).text();
163 expect(page).toContain("chinese filename content");
164 expect(page).toContain("文件名.txt"); // the real name, not mojibake
237 // Invariant: git's octal-quoted path decodes to the real UTF-8 name.
238 const text = await (await page("unicode")).text();
239 expect(text).toContain("chinese filename content");
240 expect(text).toContain("文件名.txt"); // the real name, not mojibake
165241 });
166242
167243 test("no-newline-at-eof marker on add and modify", async () => {
168 await Bun.write(join(dir(), "nonl.txt"), "line1\nline2\nline3");
169 await shOk(["git", "add", "."], dir());
170 await shOk(["git", "commit", "-m", "no trailing newline"], dir());
171 await shOk(["git", "push", "origin", "main"], dir());
172 const oid1 = await shOk(["git", "rev-parse", "HEAD"], dir());
173 const page1 = await (
174 await fetch(`${base}/ada/engine/commit/${oid1}`)
175 ).text();
176 expect(page1).toContain("nonl");
244 // Invariant: "\ No newline at end of file" neither crashes nor swallows the next line.
245 const page1 = await (await page("nonlAdd")).text();
177246 expect(page1).toContain("nonl"); // renders without crashing
178
179 await Bun.write(join(dir(), "nonl.txt"), "line1\nline2\nline3\nline4");
180 await shOk(["git", "add", "."], dir());
181 await shOk(["git", "commit", "-m", "modify no trailing newline"], dir());
182 await shOk(["git", "push", "origin", "main"], dir());
183 const oid2 = await shOk(["git", "rev-parse", "HEAD"], dir());
184 const resp2 = await fetch(`${base}/ada/engine/commit/${oid2}`);
247 const resp2 = await page("nonlModify");
185248 expect(resp2.status).toBe(200);
186 const page2 = await resp2.text();
187 expect(page2).toContain("line4");
249 expect(await resp2.text()).toContain("line4");
188250 });
189251
190252 test("root commit (no parent) diffs cleanly against the empty tree", async () => {
191 const rootOid = (
192 await shOk(["git", "rev-list", "--max-parents=0", "HEAD"], dir())
193 ).split("\n")[0]!;
194 const resp = await fetch(`${base}/ada/engine/commit/${rootOid}`);
253 // Invariant: a parentless commit diffs against the empty tree.
254 const resp = await page("root");
195255 expect(resp.status).toBe(200);
196 const page = await resp.text();
197 expect(page).toContain("init");
256 expect(await resp.text()).toContain("init");
198257 });
199258
200259 test("merge commit does not crash and returns 200", async () => {
201 await shOk(["git", "checkout", "-b", "feature"], dir());
202 await Bun.write(join(dir(), "feature.txt"), "feature content\n");
203 await shOk(["git", "add", "."], dir());
204 await shOk(["git", "commit", "-m", "feature commit"], dir());
205 await shOk(["git", "checkout", "main"], dir());
206 await Bun.write(join(dir(), "mainline.txt"), "mainline content\n");
207 await shOk(["git", "add", "."], dir());
208 await shOk(["git", "commit", "-m", "mainline commit"], dir());
209 await shOk(
210 ["git", "merge", "--no-ff", "feature", "-m", "merge feature"],
211 dir(),
212 );
213 await shOk(["git", "push", "origin", "main"], dir());
214 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
215 const resp = await fetch(`${base}/ada/engine/commit/${oid}`);
260 // Invariant: a two-parent commit renders.
261 const resp = await page("merge");
216262 expect(resp.status).toBe(200);
217263 });
218264
219265 test("mode-only change (chmod +x) with no content diff renders cleanly", async () => {
220 await Bun.write(join(dir(), "chmod-me.sh"), "#!/bin/sh\necho hi\n");
221 await shOk(["git", "add", "."], dir());
222 await shOk(["git", "commit", "-m", "add chmod-me"], dir());
223 await shOk(["git", "push", "origin", "main"], dir());
224 await shOk(["chmod", "+x", join(dir(), "chmod-me.sh")], dir());
225 await shOk(["git", "add", "."], dir());
226 await shOk(["git", "commit", "-m", "chmod only"], dir());
227 await shOk(["git", "push", "origin", "main"], dir());
228 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
229 const resp = await fetch(`${base}/ada/engine/commit/${oid}`);
266 // Invariant: a mode change with no hunks says so instead of rendering an empty table.
267 const resp = await page("chmod");
230268 expect(resp.status).toBe(200);
231 const page = await resp.text();
232 expect(page).toContain("No content changes");
269 expect(await resp.text()).toContain("No content changes");
233270 });
234271
235272 test("multi-hunk file: second hunk's line numbers are exactly correct (no off-by-one)", async () => {
236 const lines: string[] = [];
237 for (let i = 1; i <= 100; i++) lines.push(`orig line ${i}`);
238 await Bun.write(join(dir(), "multihunk.txt"), lines.join("\n") + "\n");
239 await shOk(["git", "add", "."], dir());
240 await shOk(["git", "commit", "-m", "add multihunk base"], dir());
241 await shOk(["git", "push", "origin", "main"], dir());
242
243 const lines2 = [...lines];
244 lines2[4] = "CHANGED near top"; // old/new line 5
245 lines2[94] = "CHANGED near bottom"; // old/new line 95
246 await Bun.write(join(dir(), "multihunk.txt"), lines2.join("\n") + "\n");
247 await shOk(["git", "add", "."], dir());
248 await shOk(["git", "commit", "-m", "modify multihunk two spots"], dir());
249 await shOk(["git", "push", "origin", "main"], dir());
250 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
251
252 const page = await (await fetch(`${base}/ada/engine/commit/${oid}`)).text();
273 // Invariant: each hunk's rows carry the line numbers from its own header.
274 const text = await (await page("multihunk")).text();
253275 // Word-diff highlighting splits row text into per-token <span>s, so we
254276 // can't search for the literal phrase; instead find each token and
255277 // check the nearest preceding `<td class="dn">N</td>` line-number cell.
256278 function lineNumberBefore(token: string): string {
257 const idx = page.indexOf(token);
279 const idx = text.indexOf(token);
258280 expect(idx).toBeGreaterThan(-1);
259 const before = page.slice(Math.max(0, idx - 600), idx);
281 const before = text.slice(Math.max(0, idx - 600), idx);
260282 const matches = [...before.matchAll(/<td class="dn">(\d+)<\/td>/g)];
261283 return matches[matches.length - 1]![1]!;
262284 }
263285 expect(lineNumberBefore(">CHANGED<")).toBeTruthy();
264286 // First hunk: the add row for "CHANGED near top" is new-line 5, in the
265287 // second <td class="dn"> column (old is empty for an add row).
266 const topIdx = page.indexOf("CHANGED");
267 const topSnippet = page.slice(Math.max(0, topIdx - 500), topIdx);
288 const topIdx = text.indexOf("CHANGED");
289 const topSnippet = text.slice(Math.max(0, topIdx - 500), topIdx);
268290 expect(topSnippet).toContain('<td class="dn">5</td>');
269 const bottomIdx = page.lastIndexOf("CHANGED");
270 const bottomSnippet = page.slice(Math.max(0, bottomIdx - 500), bottomIdx);
291 const bottomIdx = text.lastIndexOf("CHANGED");
292 const bottomSnippet = text.slice(Math.max(0, bottomIdx - 500), bottomIdx);
271293 expect(bottomSnippet).toContain('<td class="dn">95</td>');
272294 });
273295
274296 // ---- Resource / DoS ----
275297
276 // BUG (confirmed, HIGH severity): diffSyntax() in src/web/diff-syntax.ts
277 // loops over every file in the diff sequentially (`for (const file of
278 // diff.files)`) and, per file, calls blobForRender() which spawns a fresh
279 // `git cat-file` subprocess (up to 3 spawns per side: -t, -s, blob) rather
280 // than using the batched RepoReader. MAX_CHANGED (5000) bounds total
281 // changed *lines* but not the *number of files* in a commit. A commit
282 // touching many trivial files is therefore linear in file count at
283 // roughly 17-18ms/file with no concurrency, no cap, and no timeout
284 // shorter than the diff's own 60s spawn timeout.
285 //
286 // Measured on this machine (outside the regression run, see report):
287 // 200 files -> 3.47s
288 // 1000 files -> 18.2s
289 // 5200 files -> 95.2s (commit page request)
290 // A forge that should feel interactive (per docs/ARCHITECTURE.md) turns a
291 // single push into a 95-second synchronous request.
292 test("DOS: file count is NOT capped independent of changed-line count (perf regression sentinel)", async () => {
293 const nFiles = 300;
294 for (let i = 0; i < nFiles; i++) {
295 await Bun.write(join(dir(), `many/file-${i}.txt`), `content ${i}\n`);
296 }
297 await shOk(["git", "add", "."], dir());
298 await shOk(["git", "commit", "-m", `touch ${nFiles} files`], dir());
299 await shOk(["git", "push", "origin", "main"], dir());
300 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
301
302 const t0 = performance.now();
303 const resp = await fetch(`${base}/ada/engine/commit/${oid}`);
298 // A commit touching many trivial files once cost a `git cat-file` spawn per
299 // file in diffSyntax(); MAX_DIFF_FILES (100) in diff-view.ts now bounds the
300 // files rendered and highlighted, and says how many it left out.
301 test("MAX_DIFF_FILES: a 300-file commit page answers 200 rendering 100 files and naming the rest", async () => {
302 // Invariant: past MAX_DIFF_FILES the page renders exactly that many files and counts the hidden ones.
303 const resp = await page("many");
304304 const text = await resp.text();
305 const elapsed = performance.now() - t0;
306 console.log(
307 `[perf] ${nFiles}-file commit diff took ${elapsed.toFixed(0)}ms, ${text.length} bytes`,
308 );
309305 expect(resp.status).toBe(200);
310 // No clock is asserted: a bound in milliseconds measures the machine
311 // (currently ~17ms/file with no cap). The sentinel is this test's own
312 // timeout, far above what an interactive forge should take, and it is
313 // expected to keep passing until the file count is capped like the line
314 // count already is.
315 }, 90_000);
306 const shown = new Set(text.match(/many\/file-\d+\.txt/g) ?? []);
307 expect(shown.size).toBe(100);
308 expect(text).toContain("200 more files not");
309 });
316310
317 test("MAX_FILE_LINES caps a single huge file (200k+ changed lines) instead of rendering it", async () => {
318 const bigLines: string[] = [];
319 for (let i = 0; i < 210_000; i++)
320 bigLines.push(`line number ${i} of a huge file`);
321 await Bun.write(join(dir(), "huge.txt"), bigLines.join("\n") + "\n");
322 await shOk(["git", "add", "."], dir());
323 await shOk(["git", "commit", "-m", "add huge file 210k lines"], dir());
324 await shOk(["git", "push", "origin", "main"], dir());
325 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
326
327 const t0 = performance.now();
328 const resp = await fetch(`${base}/ada/engine/commit/${oid}`);
311 test("MAX_FILE_LINES caps a single huge file instead of rendering it", async () => {
312 // Invariant: a file over MAX_FILE_LINES changed lines is a stub naming its count, none of its lines on the wire.
313 const resp = await page("huge");
329314 const text = await resp.text();
330 const elapsed = performance.now() - t0;
331 console.log(
332 `[perf] 210k-line file diff took ${elapsed.toFixed(0)}ms, ${text.length} bytes`,
333 );
334315 expect(resp.status).toBe(200);
335316 expect(text).toContain("huge.txt");
336317 expect(text).toContain("Diff not shown");
337 expect(text).toContain("210,000 changed lines");
338 // The cap is what keeps this from being a resource sink, and the cap is
339 // what is checked: none of the file's lines are on the wire, and the
340 // page is small. How long it took is logged, not asserted.
341 expect(text).not.toContain("line number 209999 of a huge file");
318 expect(text).toContain(`${HUGE_LINES.toLocaleString()} changed lines`);
319 expect(text).not.toContain(`>L${HUGE_LINES - 1}<`);
342320 expect(text.length).toBeLessThan(500_000);
343 }, 60_000);
321 });
344322
345 test("CAP_BYTES bounds a file that is few lines but huge in bytes (single giant line)", async () => {
346 const hugeLine1 = "x".repeat(2_000_000);
347 await Bun.write(join(dir(), "hugeline.txt"), hugeLine1 + "\n");
348 await shOk(["git", "add", "."], dir());
349 await shOk(["git", "commit", "-m", "add file with one 2MB line"], dir());
350 await shOk(["git", "push", "origin", "main"], dir());
351
352 const hugeLine2 = "y".repeat(2_000_000);
353 await Bun.write(join(dir(), "hugeline.txt"), hugeLine2 + "\n");
354 await shOk(["git", "add", "."], dir());
355 await shOk(["git", "commit", "-m", "modify the 2MB line"], dir());
356 await shOk(["git", "push", "origin", "main"], dir());
357 const oid = await shOk(["git", "rev-parse", "HEAD"], dir());
358
359 const t0 = performance.now();
360 const resp = await fetch(`${base}/ada/engine/commit/${oid}`);
323 test("MAX_FILE_BYTES bounds a file that is few lines but huge in bytes (single giant line)", async () => {
324 // Invariant: a one-line change over MAX_FILE_BYTES of diff is a stub, and neither giant line reaches the page.
325 const resp = await page("hugeline");
361326 const text = await resp.text();
362 const elapsed = performance.now() - t0;
363 console.log(
364 `[perf] 2MB-single-line modify diff took ${elapsed.toFixed(0)}ms, ${text.length} bytes`,
365 );
366327 expect(resp.status).toBe(200);
367328 expect(text).toContain("hugeline.txt");
368329 expect(text).toContain("Diff not shown");
369330 expect(text).toContain("bytes of diff");
370 // The byte ceiling this issue asks for: a 4MB-of-diff single line must
371 // not put anywhere near that on the wire, and must not creep back up.
372331 expect(text.length).toBeLessThan(500_000);
373 // MAX_FILE_BYTES/MAX_LINE_WIDTH in diff-view.ts stub the file before it
374 // is ever tokenized or rendered as rows, though the changed-line count
375 // (1) is far under MAX_FILE_LINES: neither giant line reached the page.
332 // The changed-line count (1) is far under MAX_FILE_LINES: only the byte
333 // bound keeps either giant line off the page.
376334 expect(text).not.toContain("x".repeat(1_000));
377335 expect(text).not.toContain("y".repeat(1_000));
378 }, 60_000);
336 });
379337 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs