SysDeck/klanker-gate/apps/gateway/routes/advanced_test.ts

139 lines
5.6 KiB
TypeScript
Executable File

// The two pure quantity readers behind the media accounting channel. The route
// halves of these cases (and the in-flight budget, which needs a real provider
// to hold a reservation open) live in tests/integration/media_billing_test.ts.
import { assertEquals } from "@std/assert";
import { countUnits, tokensFrom } from "./advanced.ts";
// -- countUnits: the pathname gate -----------------------------------------
// D1-T2, unit half. `data: [...]` is not an image marker: /v1/embeddings answers
// with exactly that shape, so a shape-driven count bills embeddings as images.
// This assertion CANNOT fail on unmodified code by accident - it is the direct
// probe of the gate, and it is what the M-PATH mutant (gate on `Array.isArray`
// instead of the pathname) kills.
Deno.test("D1-T2: countUnits is gated on the pathname, never the shape", () => {
const embeddingShaped = {
object: "list",
data: [{ embedding: [0.1] }, { embedding: [0.2] }, { embedding: [0.3] }],
};
assertEquals(countUnits("/v1/embeddings", embeddingShaped), {});
assertEquals(countUnits("/v1/chat/completions", embeddingShaped), {});
assertEquals(countUnits("/v1/files", embeddingShaped), {});
// The same body on the image pathname does count.
assertEquals(countUnits("/v1/images/generations", embeddingShaped), {
imageCount: 3,
});
});
Deno.test("countUnits: imageCount comes from data.length, clamped", () => {
assertEquals(
countUnits("/v1/images/generations", { data: [{ url: "a" }] }),
{ imageCount: 1 },
);
assertEquals(countUnits("/v1/images/generations", { data: [] }), {
imageCount: 0,
});
// Absence of `data`, a non-array `data`, and a non-object body are all
// "not counted" rather than zero.
assertEquals(countUnits("/v1/images/generations", { created: 1 }), {});
assertEquals(countUnits("/v1/images/generations", { data: "nope" }), {});
assertEquals(countUnits("/v1/images/generations", undefined), {});
assertEquals(countUnits("/v1/images/generations", "not json at all"), {});
});
// D1-T4, unit half: usage.seconds wins, duration is the fallback, and neither
// records nothing at all rather than a billable zero.
Deno.test("D1-T4: audioSeconds prefers usage.seconds, falls back to duration", () => {
const p = "/v1/audio/transcriptions";
assertEquals(countUnits(p, { usage: { seconds: 3.5 }, duration: 9 }), {
audioSeconds: 3.5,
});
assertEquals(countUnits(p, { duration: 9 }), { audioSeconds: 9 });
assertEquals(countUnits(p, { usage: { seconds: 0 } }), { audioSeconds: 0 });
assertEquals(countUnits(p, { text: "words" }), {});
// A token-shaped transcription usage carries no `seconds`; that must not be
// read as zero seconds.
assertEquals(
countUnits(p, { usage: { type: "tokens", input_tokens: 5 } }),
{},
);
// Hostile / broken values are dropped, never billed.
assertEquals(countUnits(p, { duration: -1 }), {});
assertEquals(countUnits(p, { duration: Infinity }), {});
assertEquals(countUnits(p, { duration: NaN }), {});
assertEquals(countUnits(p, { duration: "12" }), {});
assertEquals(countUnits(p, { usage: "duration" }), {});
});
// -- tokensFrom ------------------------------------------------------------
Deno.test("tokensFrom: reads usage and usageMetadata through normalizeUsage", () => {
assertEquals(
tokensFrom({ usage: { input_tokens: 12, output_tokens: 3 } }),
{ prompt: 12, completion: 3, cached: 0, cacheCreation: 0 },
);
assertEquals(
tokensFrom({ usage: { prompt_tokens: 7, completion_tokens: 2 } }),
{ prompt: 7, completion: 2, cached: 0, cacheCreation: 0 },
);
// Gemini's native block, under its own key.
assertEquals(
tokensFrom({
usageMetadata: { promptTokenCount: 4, candidatesTokenCount: 6 },
}),
{ prompt: 4, completion: 6, cached: 0, cacheCreation: 0 },
);
// `usage` wins when both are present.
assertEquals(
tokensFrom({
usage: { prompt_tokens: 1 },
usageMetadata: { promptTokenCount: 99 },
}),
{ prompt: 1, completion: 0, cached: 0, cacheCreation: 0 },
);
});
// Absence must not become a billed zero (decision-log 56). A duration-shaped
// transcription usage carries no token fields at all, and it is the shape that
// makes this rule load-bearing rather than theoretical.
Deno.test("tokensFrom: a body with no token fields reports ABSENT, not zeros", () => {
assertEquals(tokensFrom({ text: "words" }), undefined);
assertEquals(tokensFrom({}), undefined);
assertEquals(tokensFrom(undefined), undefined);
assertEquals(tokensFrom({ usage: null }), undefined);
assertEquals(tokensFrom({ usage: "tokens" }), undefined);
assertEquals(
tokensFrom({ usage: { type: "duration", seconds: 12 } }),
undefined,
);
// An explicitly zero usage block is also reported absent: it prices to the
// same figure either way, so nothing is lost by not inventing a row.
assertEquals(
tokensFrom({ usage: { prompt_tokens: 0, completion_tokens: 0 } }),
undefined,
);
});
Deno.test("tokensFrom: hostile numbers are clamped, not propagated", () => {
assertEquals(
tokensFrom({ usage: { prompt_tokens: -5, completion_tokens: 2.7 } }),
{ prompt: 0, completion: 2, cached: 0, cacheCreation: 0 },
);
assertEquals(
tokensFrom({ usage: { prompt_tokens: Infinity, completion_tokens: 1 } }),
{ prompt: 0, completion: 1, cached: 0, cacheCreation: 0 },
);
assertEquals(
tokensFrom({ usage: { prompt_tokens: 1e308, completion_tokens: 1 } }),
{
prompt: Number.MAX_SAFE_INTEGER,
completion: 1,
cached: 0,
cacheCreation: 0,
},
);
// NaN in every bucket collapses to "no tokens at all", not to NaN rows.
assertEquals(tokensFrom({ usage: { prompt_tokens: NaN } }), undefined);
});