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

Fast test/surfaces-adversarial.test.ts: chop and rewrite under the budget (1 s a test, 10 s a file) #12064

Merged opened this

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

Merged

scout/forge:scout/1338-fast-test-surfaces-adversarial-test-ts-c → main 1 commit fork

  • Merged. scout/1338-fast-test-surfaces-adversarial-test-ts-c was merged into main as 73c7b92.

Review

Sign in to review this change.
1 file changed +24 −51
test/surfaces-adversarial.test.ts +24 −51
@@ -23,6 +23,7 @@ import { openPull } from "../src/actions/pulls.ts";
2323 import { createApp, type App as Forge } from "../src/app.ts";
2424 import { addTeamMember, createOrg, createTeam } from "../src/core/orgs.ts";
2525 import type { Repo } from "../src/core/repos.ts";
26 import { createSession } from "../src/core/sessions.ts";
2627 import { createUser, getUserByName, type User } from "../src/core/users.ts";
2728 import { serve, type Servers } from "../src/http/server.ts";
2829 import { id } from "../src/kernel/id.ts";
@@ -52,7 +53,6 @@ describe("surfaces adversarial: web", () => {
5253 let servers: Servers;
5354 let base = "";
5455 let alice = "";
55 let alicePassword = "alice-adversarial-pass";
5656
5757 const web = (
5858 cookie: string,
@@ -81,29 +81,13 @@ describe("surfaces adversarial: web", () => {
8181 return await response.text();
8282 };
8383
84 const signUp = async (
85 username: string,
86 password = "a-good-passphrase-1",
87 ): Promise<string> => {
88 const response = await fetch(`${base}/signup`, {
89 method: "POST",
90 body: new URLSearchParams({
91 username,
92 email: `${username}@forge.test`,
93 password,
94 }),
95 redirect: "manual",
96 });
97 return `${(response.headers.get("set-cookie") ?? "").split(";")[0]!}; forge_mode=dev`;
98 };
99
10084 beforeAll(async () => {
10185 dataDir = await mkdtemp(join(tmpdir(), "forge-surfaces-adv-"));
10286 // The standing sweep queries on a timer; the N+1 counts are of requests alone.
10387 app = createApp({ dataDir, port: 0, standingSweepMs: 3_600_000 });
10488 servers = await serve(app);
10589 base = servers.url;
106 alice = `${await adminCookie(app, { username: "alice", email: "[email protected]", password: alicePassword })}; forge_mode=dev`;
90 alice = `${await adminCookie(app, { username: "alice", email: "[email protected]", password: "alice-adversarial-pass" })}; forge_mode=dev`;
10791 }, 30_000);
10892
10993 afterAll(async () => {
@@ -325,6 +309,7 @@ describe("surfaces adversarial: web", () => {
325309 // ---- 5. N+1 ----
326310
327311 test("N+1: /apps does not cost more queries as private, org-visible apps grow", async () => {
312 // Invariant: a listing of private org apps costs the same statements at 30 apps as at 5. Users here are passwordless with a session row (no argon2); 2 measured runs.
328313 const org = createOrg(app.db, "acme-apps", aliceUser().id);
329314 expect(org.ok).toBe(true);
330315 if (!org.ok) return;
@@ -334,14 +319,11 @@ describe("surfaces adversarial: web", () => {
334319 const viewer = await createUser(app.db, { origin: "seed", trusted: true,
335320 username: "viewer1",
336321 email: "[email protected]",
337 password: "viewer-pass-1234",
338322 });
339323 expect(viewer.ok).toBe(true);
340324 if (!viewer.ok) return;
341325 expect(addTeamMember(app.db, team.value, viewer.value.id)).toBe(true);
342 const viewerCookie = await signUp("viewer1-cookie"); // unused path, just to reuse signUp's cookie header shape
343 void viewerCookie;
344 const cookie = await loginAs(base, "viewer1", "viewer-pass-1234");
326 const cookie = sessionFor(viewer.value.id);
345327
346328 const seedApps = (n: number): void => {
347329 for (let i = 0; i < n; i++) {
@@ -367,20 +349,20 @@ describe("surfaces adversarial: web", () => {
367349 const small = await statements(app.db, async () => {
368350 const response = await web(cookie, "/apps");
369351 expect(response.status).toBe(200);
370 });
352 }, 2);
371353 seedApps(25); // 30 total now
372354 const large = await statements(app.db, async () => {
373355 const response = await web(cookie, "/apps");
374356 expect(response.status).toBe(200);
375 });
357 }, 2);
376358 expect(large).toBe(small);
377359 });
378360
379361 test("N+1: the dashboard's Apps and On-you cards stay flat with 30 apps and 30 assigned issues", async () => {
362 // Invariant: the dashboard cards cost the same statements at 30 apps and 30 assigned issues as at 5. Users here are passwordless with a session row (no argon2); 2 measured runs.
380363 const owner = await createUser(app.db, { origin: "seed", trusted: true,
381364 username: "dashowner",
382365 email: "[email protected]",
383 password: "dashowner-pass-123",
384366 });
385367 expect(owner.ok).toBe(true);
386368 if (!owner.ok) return;
@@ -393,12 +375,11 @@ describe("surfaces adversarial: web", () => {
393375 const viewer = await createUser(app.db, { origin: "seed", trusted: true,
394376 username: "dashviewer",
395377 email: "[email protected]",
396 password: "dashviewer-pass-1",
397378 });
398379 expect(viewer.ok).toBe(true);
399380 if (!viewer.ok) return;
400381 expect(addTeamMember(app.db, team.value, viewer.value.id)).toBe(true);
401 const cookie = await loginAs(base, "dashviewer", "dashviewer-pass-1");
382 const cookie = sessionFor(viewer.value.id);
402383
403384 const seed = (n: number, offset: number): void => {
404385 for (let i = 0; i < n; i++) {
@@ -438,12 +419,12 @@ describe("surfaces adversarial: web", () => {
438419 const small = await statements(app.db, async () => {
439420 const response = await web(cookie, "/");
440421 expect(response.status).toBe(200);
441 });
422 }, 2);
442423 seed(25, 5); // 30 total of each
443424 const large = await statements(app.db, async () => {
444425 const response = await web(cookie, "/");
445426 expect(response.status).toBe(200);
446 });
427 }, 2);
447428 expect(large).toBe(small);
448429 });
449430
@@ -453,10 +434,10 @@ describe("surfaces adversarial: web", () => {
453434 // `writableRepoIds` query (`REPO_WRITABLE`, the SQL twin of `canWrite`),
454435 // so the count must not move with the number of distinct repositories.
455436 test("N+1: needsYouCard does not cost more as agent pulls span more distinct repos", async () => {
437 // Invariant: needsYouCard costs the same statements at 30 distinct repos as at 5. Users here are passwordless with a session row (no argon2); 2 measured runs.
456438 const owner = await createUser(app.db, { origin: "seed", trusted: true,
457439 username: "needsowner",
458440 email: "[email protected]",
459 password: "needsowner-pass-1",
460441 });
461442 if (!owner.ok) return;
462443 const org = createOrg(app.db, "acme-needs", owner.value.id);
@@ -466,7 +447,6 @@ describe("surfaces adversarial: web", () => {
466447 const viewer = await createUser(app.db, { origin: "seed", trusted: true,
467448 username: "needsviewer",
468449 email: "[email protected]",
469 password: "needsviewer-pass-1",
470450 });
471451 if (!viewer.ok) return;
472452 addTeamMember(app.db, team.value, viewer.value.id);
@@ -474,7 +454,7 @@ describe("surfaces adversarial: web", () => {
474454 username: "needsbot",
475455 });
476456 if (!agent.ok) return;
477 const cookie = await loginAs(base, "needsviewer", "needsviewer-pass-1");
457 const cookie = sessionFor(viewer.value.id);
478458
479459 const seed = (n: number, offset: number): void => {
480460 for (let i = 0; i < n; i++) {
@@ -501,15 +481,16 @@ describe("surfaces adversarial: web", () => {
501481 await web(cookie, "/");
502482 const small = await statements(app.db, async () => {
503483 await web(cookie, "/");
504 });
484 }, 2);
505485 seed(25, 5);
506486 const large = await statements(app.db, async () => {
507487 await web(cookie, "/");
508 });
488 }, 2);
509489 expect(large).toBe(small);
510490 });
511491
512492 test("N+1: the runs list does not cost more at 50 rows than at 5", async () => {
493 // Invariant: the runs list costs the same statements at 50 rows as at 5. Users here are passwordless with a session row (no argon2); 2 measured runs.
513494 const madeRepo = await createRepo(app, aliceUser(), {
514495 name: "runs-n1",
515496 visibility: "public",
@@ -530,16 +511,17 @@ describe("surfaces adversarial: web", () => {
530511 const small = await statements(app.db, async () => {
531512 const response = await web(alice, "/alice/runs-n1/runs");
532513 expect(response.status).toBe(200);
533 });
514 }, 2);
534515 seedRuns(45); // 50 total
535516 const large = await statements(app.db, async () => {
536517 const response = await web(alice, "/alice/runs-n1/runs");
537518 expect(response.status).toBe(200);
538 });
519 }, 2);
539520 expect(large).toBe(small);
540521 });
541522
542523 test("N+1: a pull's crew activity does not cost more as its agent runs grow", async () => {
524 // Invariant: a pull page costs the same statements however many agent runs it has. Users here are passwordless with a session row (no argon2); 2 measured runs.
543525 const agent = await createAgent(app, aliceUser(), {
544526 username: "crewn1bot",
545527 });
@@ -598,7 +580,7 @@ describe("surfaces adversarial: web", () => {
598580 `/alice/crew-n1/pulls/${opened.value.number}`,
599581 );
600582 expect(response.status).toBe(200);
601 });
583 }, 2);
602584 seedActivity(20);
603585 const large = await statements(app.db, async () => {
604586 const response = await web(
@@ -606,7 +588,7 @@ describe("surfaces adversarial: web", () => {
606588 `/alice/crew-n1/pulls/${opened.value.number}`,
607589 );
608590 expect(response.status).toBe(200);
609 });
591 }, 2);
610592 expect(large).toBe(small);
611593 });
612594
@@ -630,24 +612,15 @@ describe("surfaces adversarial: web", () => {
630612 expect(wide).toEqual([]);
631613 });
632614
615 // A passwordless seeded user signed in by session row: no argon2 per user.
616 const sessionFor = (userId: string): string =>
617 `forge_session=${createSession(app.db, userId).token}; forge_mode=dev`;
618
633619 function aliceUser(): User {
634620 return getUserByName(app.db, "alice")!;
635621 }
636622 });
637623
638 /** Sign in over the API and return the session cookie's `cookie:` value. */
639 async function loginAs(
640 base: string,
641 username: string,
642 password: string,
643 ): Promise<string> {
644 const response = await fetch(`${base}/signin`, {
645 method: "POST",
646 body: new URLSearchParams({ username, password }),
647 redirect: "manual",
648 });
649 return `${(response.headers.get("set-cookie") ?? "").split(";")[0]!}; forge_mode=dev`;
650 }
651624
652625 // ============================================================================
653626 // TUI

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs