Switch manifest serialization to CBOR
Replace JSON-based bundle manifest with a CBOR-encoded format. The manifest is now a canonical CBOR map with order-strict key decoding, raw 32-byte hash payloads (instead of hex-encoded JSON), and compact binary representation.
This commit is contained in:
@@ -7,10 +7,10 @@ import { validateManifest, selectExport } from "../src/manifest.js";
|
||||
import { verifyNodeHashes, parseNodeSection as parseNodes } from "../src/merkle.js";
|
||||
import { buildTreeFromNodeMap } from "../src/cli.js";
|
||||
|
||||
const fixtureDir = "test/fixtures";
|
||||
const fixtureDir = "../../test/fixtures";
|
||||
|
||||
describe("run bundle — id.tri.bundle", () => {
|
||||
const bundle = readFileSync(`${fixtureDir}/id.tri.bundle`);
|
||||
describe("run bundle — id.arborix", () => {
|
||||
const bundle = readFileSync(`${fixtureDir}/id.arborix`);
|
||||
const manifest = parseManifest(bundle);
|
||||
const nodeSectionData = bundleParseNodeSection(bundle);
|
||||
const { nodeMap } = parseNodes(nodeSectionData);
|
||||
@@ -24,25 +24,21 @@ describe("run bundle — id.tri.bundle", () => {
|
||||
ok(verified);
|
||||
});
|
||||
|
||||
it("export 'id' is selectable", () => {
|
||||
const exp = selectExport(manifest, "id");
|
||||
strictEqual(exp.name, "id");
|
||||
it("export 'root' is selectable", () => {
|
||||
const exp = selectExport(manifest, "root");
|
||||
strictEqual(exp.name, "root");
|
||||
});
|
||||
|
||||
it("tree reconstructs as a Fork", () => {
|
||||
const exp = selectExport(manifest, "id");
|
||||
const exp = selectExport(manifest, "root");
|
||||
const tree = buildTreeFromNodeMap(nodeMap, exp.root);
|
||||
ok(Array.isArray(tree));
|
||||
// id = t (t t) = Fork (Stem Leaf) Leaf...
|
||||
// In Haskell: id = S = t (t (t t)) t
|
||||
// This is Fork (Fork (Fork Leaf Leaf) Leaf) Leaf
|
||||
// In array form: [[[], []], [], []]
|
||||
ok(tree.length >= 2, "tree should be a Fork (length >= 2)");
|
||||
});
|
||||
});
|
||||
|
||||
describe("run bundle — true.tri.bundle", () => {
|
||||
const bundle = readFileSync(`${fixtureDir}/true.tri.bundle`);
|
||||
describe("run bundle — true.arborix", () => {
|
||||
const bundle = readFileSync(`${fixtureDir}/true.arborix`);
|
||||
const manifest = parseManifest(bundle);
|
||||
const nodeSectionData = bundleParseNodeSection(bundle);
|
||||
const { nodeMap } = parseNodes(nodeSectionData);
|
||||
@@ -51,20 +47,60 @@ describe("run bundle — true.tri.bundle", () => {
|
||||
validateManifest(manifest);
|
||||
});
|
||||
|
||||
it("export 'const' is selectable", () => {
|
||||
const exp = selectExport(manifest, "const");
|
||||
strictEqual(exp.name, "const");
|
||||
it("export 'root' is selectable", () => {
|
||||
const exp = selectExport(manifest, "root");
|
||||
strictEqual(exp.name, "root");
|
||||
});
|
||||
|
||||
it("tree reconstructs", () => {
|
||||
const exp = selectExport(manifest, "const");
|
||||
it("tree reconstructs as Stem Leaf", () => {
|
||||
const exp = selectExport(manifest, "root");
|
||||
const tree = buildTreeFromNodeMap(nodeMap, exp.root);
|
||||
ok(Array.isArray(tree));
|
||||
strictEqual(tree.length, 1, "true should be a Stem (single child)");
|
||||
strictEqual(tree[0].length, 0, "child should be Leaf");
|
||||
});
|
||||
});
|
||||
|
||||
describe("run bundle — false.arborix", () => {
|
||||
const bundle = readFileSync(`${fixtureDir}/false.arborix`);
|
||||
const manifest = parseManifest(bundle);
|
||||
const nodeSectionData = bundleParseNodeSection(bundle);
|
||||
const { nodeMap } = parseNodes(nodeSectionData);
|
||||
|
||||
it("manifest validates", () => {
|
||||
validateManifest(manifest);
|
||||
});
|
||||
|
||||
it("export 'root' is selectable", () => {
|
||||
const exp = selectExport(manifest, "root");
|
||||
strictEqual(exp.name, "root");
|
||||
});
|
||||
|
||||
it("tree reconstructs as Leaf", () => {
|
||||
const exp = selectExport(manifest, "root");
|
||||
const tree = buildTreeFromNodeMap(nodeMap, exp.root);
|
||||
strictEqual(tree.length, 0, "false should be Leaf (empty array)");
|
||||
});
|
||||
});
|
||||
|
||||
describe("run bundle — notQ.arborix", () => {
|
||||
const bundle = readFileSync(`${fixtureDir}/notQ.arborix`);
|
||||
const manifest = parseManifest(bundle);
|
||||
const nodeSectionData = bundleParseNodeSection(bundle);
|
||||
const { nodeMap } = parseNodes(nodeSectionData);
|
||||
|
||||
it("manifest validates", () => {
|
||||
validateManifest(manifest);
|
||||
});
|
||||
|
||||
it("node hashes verify", () => {
|
||||
const { verified } = verifyNodeHashes(nodeMap);
|
||||
ok(verified);
|
||||
});
|
||||
});
|
||||
|
||||
describe("run bundle — missing export", () => {
|
||||
const bundle = readFileSync(`${fixtureDir}/id.tri.bundle`);
|
||||
const bundle = readFileSync(`${fixtureDir}/id.arborix`);
|
||||
const manifest = parseManifest(bundle);
|
||||
|
||||
it("nonexistent export fails clearly", () => {
|
||||
@@ -73,8 +109,8 @@ describe("run bundle — missing export", () => {
|
||||
});
|
||||
|
||||
describe("run bundle — auto-select", () => {
|
||||
// true.tri.bundle has only one export, should auto-select
|
||||
const bundle = readFileSync(`${fixtureDir}/true.tri.bundle`);
|
||||
// true.arborix has only one export, should auto-select
|
||||
const bundle = readFileSync(`${fixtureDir}/true.arborix`);
|
||||
const manifest = parseManifest(bundle);
|
||||
|
||||
it("single export auto-selects", () => {
|
||||
|
||||
Reference in New Issue
Block a user