flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/apps/status/src/probe.test.ts

67 lines3,625 bytesCodeBlame
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { combine, judgeStorage, runCheck, step } from "./probe.ts";
5
6const answer = (status: number) => async () => new Response("x", { status });
7
8test("a step works on 2xx, or on exactly the status it expects", async () => {
9 assert.equal((await step(answer(200), { url: "https://a/" })).ok, true);
10 const refused = await step(answer(502), { url: "https://a/" });
11 assert.deepEqual([refused.ok, refused.error], [false, "HTTP 502"]);
12 assert.equal((await step(answer(401), { url: "https://a/", expect: 401 })).ok, true);
13 assert.equal((await step(answer(200), { url: "https://a/", expect: 401 })).ok, false);
14});
15
16test("a step that cannot connect, or takes too long, fails with why", async () => {
17 const broken = await step(async () => Promise.reject(new TypeError("boom")), { url: "https://a/" });
18 assert.equal(broken.error, "could not connect");
19 const slow = await step(
20 (_url, init) => new Promise((_, reject) => init.signal?.addEventListener("abort", () => reject(new Error("aborted")))),
21 { url: "https://a/" },
22 20,
23 );
24 assert.equal(slow.error, "timed out");
25});
26
27test("a check's steps: all must work, and it takes as long as the slowest", () => {
28 assert.deepEqual(combine([{ ok: true, ms: 10 }, { ok: true, ms: 30 }]), { ok: true, ms: 30 });
29 assert.deepEqual(combine([{ ok: true, ms: 10 }, { ok: false, ms: 5, error: "HTTP 500" }]), { ok: false, ms: 10, error: "HTTP 500" });
30});
31
32test("runCheck: billing without a binding, and a part with no check, are null", async () => {
33 const probers = { fetch: answer(200), billing: null };
34 assert.equal(await runCheck({ kind: "billing" }, probers), null);
35 assert.equal(await runCheck({ kind: "none" }, probers), null);
36 assert.equal((await runCheck({ kind: "billing" }, { ...probers, billing: async () => ({ version: 1 }) }))!.ok, true);
37 assert.equal((await runCheck({ kind: "billing" }, { ...probers, billing: async () => null }))!.error, "no price book");
38 const mixed = await runCheck({ kind: "http", steps: [{ url: "https://a/" }, { url: "https://b/", expect: 401 }] }, probers);
39 assert.equal(mixed!.ok, false);
40});
41
42test("git storage is judged by how its calls went, and quiet is up", async () => {
43 const row = (calls: number, errors: number, rate_limited: number, rejected: number, ms_total: number) => ({
44 store: "g1t",
45 calls,
46 errors,
47 rate_limited,
48 rejected,
49 ms_total,
50 });
51 const report = (...stores: ReturnType<typeof row>[]) => ({ minutes: 5, stores });
52 assert.deepEqual(judgeStorage(report()), { ok: true, ms: 0 });
53 assert.deepEqual(judgeStorage(report(row(100, 1, 0, 0, 30_000))), { ok: true, ms: 300 });
54 // A quarter or more failing, at least five: down.
55 const down = judgeStorage(report(row(10, 3, 0, 0, 1_000), row(10, 2, 0, 0, 1_000)));
56 assert.deepEqual([down.ok, down.error], [false, "25% of calls failed"]);
57 // Too few to tell.
58 assert.equal(judgeStorage(report(row(4, 4, 0, 0, 400))).ok, true);
59 // Refused by an open breaker: down.
60 assert.equal(judgeStorage(report(row(0, 0, 0, 3, 0))).ok, false);
61 // Rate limited: degraded, not down.
62 const limited = judgeStorage(report(row(100, 2, 2, 0, 10_000)));
63 assert.deepEqual([limited.ok, limited.degraded], [true, "Rate limited 2 times in 5 minutes"]);
64 const viaCheck = await runCheck({ kind: "storage" }, { fetch: answer(200), billing: null, storage: async () => report(row(1, 0, 0, 0, 5)) });
65 assert.deepEqual(viaCheck, { ok: true, ms: 5 });
66 assert.equal(await runCheck({ kind: "storage" }, { fetch: answer(200), billing: null }), null);
67});