Files
rea/src/dotnet/ManagedDecodeBudget.test.ts
T
23d50ea3be fix(managed): bind row budget charges to metadata identities (#1897)
Charge fixed row bookkeeping once per table and row within an admitted
metadata layout. Repeated owner lookups no longer permanently consume
capacity for temporary cursors; distinct rows and failed admissions retain
the existing representation limit and typed failure behavior.

Verify repeated local attribute-constructor lookups through public CLI
metadata/member inspection and preserve the remaining capacity guards.

Closes #1878

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-12 00:33:51 +08:00

66 lines
2.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
admitManagedProjection,
ManagedDecodeBudget,
} from "./ManagedDecodeBudget.js";
import { ManagedReaderFailure } from "./ManagedReaderFailure.js";
describe("managed projection admission", () => {
it("charges decoded strings by their JSON bytes", () => {
const name = "a".repeat(12 * 1024 * 1024);
expect(admitManagedProjection({ name })).toEqual({ name });
});
it("charges escaped and multibyte characters at their encoded size", () => {
expect(() =>
admitManagedProjection({ name: "\u0001".repeat(12 * 1024 * 1024) }),
).toThrow(ManagedReaderFailure);
expect(() =>
admitManagedProjection({ name: "€".repeat(23 * 1024 * 1024) }),
).toThrow(ManagedReaderFailure);
});
it("counts escaped JSON bytes exactly at the budget boundary", () => {
// Control escapes, quotes, three-byte text, surrogate pairs and lone
// surrogates each have a distinct JSON size; fill the rest with ASCII.
const mixed = "\u0001".repeat(4096) + '"\\' + "€😀\ud800\udc00\ud800";
const used = Buffer.byteLength(JSON.stringify(mixed));
const filled = (extra: number) =>
mixed + "a".repeat(64 * 1024 * 1024 - used + extra);
expect(() => admitManagedProjection(filled(0))).not.toThrow();
expect(() => admitManagedProjection(filled(1))).toThrow(
ManagedReaderFailure,
);
});
});
describe("managed decoding bounds", () => {
it("bounds new row identities without charging lookup replay or merging tables", () => {
const budget = new ManagedDecodeBudget();
budget.reserve(64 * 1024 * 1024 - 512, null);
budget.reserveRow(2, 1, 100);
budget.reserveRow(12, 1, 200);
expect(() => budget.reserveRow(2, 1, 100)).not.toThrow();
expect(() => budget.reserveRow(2, 2, 300)).toThrow(ManagedReaderFailure);
// A rejected row has no retained reservation; replay cannot bypass capacity.
expect(() => budget.reserveRow(2, 2, 300)).toThrow(ManagedReaderFailure);
});
it("keeps concurrent decoding bounds within one budget until released", () => {
const budget = new ManagedDecodeBudget();
const bound = 40 * 1024 * 1024;
budget.admitTransient(bound, null);
expect(() => budget.admitTransient(bound, null)).toThrow(
ManagedReaderFailure,
);
expect(() => budget.reserve(bound, null)).toThrow(ManagedReaderFailure);
budget.releaseTransient();
expect(() => budget.admitTransient(bound, null)).not.toThrow();
});
});