testBranchVerifiesDontWaitForEachOther

tcmts.cli.test.e2e.verify.testBranchVerifiesDontWaitForEachOther · #5jgb4dce · term

import { Codebase } from "#codebase/tcmts/cli/codebase";
import { fakeVerify } from "#codebase/tcmts/cli/test/e2e/verify";
import { nodeArgs, writeRunner } from "#codebase/tcmts/loader";
import assert from "node:assert/strict";
import { spawn } from "node:child_process";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";

export const testBranchVerifiesDontWaitForEachOther = async () => {
  const dist = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), "tcm dist ")));
  const log = path.join(dist, "log");
  // something else making its tcm the known-good one, as a verify of before did for its whole run
  const other = spawn(process.execPath, ["-e", "setInterval(() => {}, 1000)"], { stdio: "ignore" });
  fs.writeFileSync(path.join(dist, "verify.lock"), String(other.pid));
  const cb = Codebase.find(process.cwd());
  const hash = (fakeVerify as unknown as Record<symbol, string>)[Symbol.for("tcm.hash")]!;
  const runner = writeRunner(hash, cb.source(), cb.lay);
  const ended = new Map<string, number>();
  const start = (branch: string, name = branch) => {
    const c = spawn(process.execPath, [...nodeArgs(cb.lay), runner, dist, branch, "1500", log], {
      cwd: cb.lay.root,
      stdio: ["ignore", "ignore", "pipe"],
    });
    let err = "";
    c.stderr.setEncoding("utf8").on("data", (d: string) => (err += d));
    return new Promise<void>((resolve, reject) =>
      c.on("close", (code) => {
        ended.set(name, Date.now());
        if (code === 0) resolve();
        else reject(new Error(`${name} exited ${code}: ${err}`));
      }),
    );
  };
  const lines = () =>
    (fs.existsSync(log) ? fs.readFileSync(log, "utf8") : "")
      .trim()
      .split("\n")
      .filter(Boolean)
      .map((l) => l.split(" ") as [string, string, string]);
  const at = (branch: string, what: string, nth = 0) =>
    Number(lines().filter(([, b, w]) => b === branch && w === what)[nth]?.[0] ?? NaN);
  try {
    const runs = [
      start("session/a"),
      start("session/b"),
      start("main"),
      start("session/a", "session/a again"),
    ];
    while (lines().filter(([, , w]) => w === "ready").length < 4)
      await new Promise((r) => setTimeout(r, 50));
    fs.writeFileSync(`${log}.go`, "");
    await Promise.all(runs.slice(0, 2));
    // the two branches built side by side, and beside main's
    assert.ok(at("session/a", "build") < at("session/b", "built"));
    assert.ok(at("session/b", "build") < at("session/a", "built"));
    assert.ok(at("main", "build") < at("session/a", "built"));
    // each in its own place
    assert.deepEqual(fs.readdirSync(path.join(dist, "candidates")).sort().length, 3);
    // another verify of the same branch waits for the first
    await runs[3];
    assert.ok(at("session/a", "build", 1) >= at("session/a", "built", 0));
    // main's waits only to make its tcm the known-good one, for what else is
    await new Promise((r) => setTimeout(r, 300));
    assert.ok(
      Number.isNaN(at("main", "promote")),
      "main's verify promoted while another held dist/verify.lock",
    );
    other.kill("SIGKILL");
    await runs[2];
    assert.ok(at("main", "promote") >= at("main", "built"));
  } finally {
    other.kill("SIGKILL");
    fs.rmSync(dist, { recursive: true, force: true });
  }
}

uses