Artifact f50d210223a26e5ecce6237496ee132b107c7568900076576c15efbbfd124157:
- File
src/container_test.zig
— part of check-in
[e5db38a6df]
at
2026-08-05 21:16:30
on branch sub-manifest
— citations: re-key 31 verified line ranges, baseline 512 to 481
Each was located by reading the draft text that supports what the code comment actually claims, then adversarially re-checked against a verbatim quote of those lines. Clamping a range into its section would satisfy the checker while pointing at the wrong paragraph, so the checker alone was never the gate.
Of 33 proposals, 2 were refuted on exactly that ground -- the quote verified byte-for-byte and still did not state the claim -- and 4 came back unresolved because no draft's §4.1 states what those comments assert at all. Those are mis-sectioned, not line-rotted, and need a section decision rather than a re-key.
Also restores container.zig's `decode` doc block, which 7d26a31305 left stranded above `decodePrefix` when that function was inserted between the comment and the function it describes.
test 3495/3495, fmt. Issue #18. (user: dmestas, size: 6950) [annotate] [blame] [check-ins using]
//! Public-surface unit tests for the §4.1 zlib container codec //! (`container.zig`). The oracle is draft-fossil-sync-protocol-00 §4.1; every //! expected value is transcribed from the spec text and its RFC1950 references, //! never captured from a running Fossil. const std = @import("std"); const container = @import("container.zig"); /// A generous decode capacity for the round-trip tests; the codec's `max_output` /// bound is exercised directly by the "over max_output" test below. Sync passes /// its `reply_body_cap` here in production; the codec itself is cap-agnostic. const cap: usize = 1 << 24; test "container §4.1 r18: the container is BE32 length then a zlib stream (worked example)" { const encoded = try container.encode(std.testing.allocator, "abc", .default); defer std.testing.allocator.free(encoded); // BE32 uncompressed length (r18). try std.testing.expectEqualSlices(u8, &[_]u8{ 0, 0, 0, 3 }, encoded[0..4]); // RFC1950 §2.2 MUST: CM (low nibble of CMF) is 8 (deflate). try std.testing.expectEqual(@as(u8, 8), encoded[4] & 0x0f); // RFC1950 §2.2 MUST: (CMF*256 + FLG) % 31 == 0 (FCHECK). const cmf_flg = @as(u16, encoded[4]) * 256 + @as(u16, encoded[5]); try std.testing.expectEqual(@as(u16, 0), cmf_flg % 31); // FDICT must be 0 — no preset dictionary. try std.testing.expectEqual(@as(u8, 0), encoded[5] & 0x20); // RFC1950 §9 Adler-32 of "abc": s1=1+97+98+99=295=0x0127, // s2=0+98+196+295=589=0x024D, stored MSB-first as the trailer. try std.testing.expectEqualSlices(u8, &[_]u8{ 0x02, 0x4D, 0x01, 0x27 }, encoded[encoded.len - 4 ..]); } test "container §4.1 r19: the ordinary single-input path uses the zlib default level" { const encoded = try container.encode(std.testing.allocator, "hello fossil sync", .default); defer std.testing.allocator.free(encoded); const decoded = try container.decode(std.testing.allocator, encoded, cap); defer std.testing.allocator.free(decoded); try std.testing.expectEqualStrings("hello fossil sync", decoded); } test "container §4.1 r20: an inline-login prepend compresses the concatenation at level 9" { const login = "login foo bar baz\n"; const body = "gimme 0123456789012345678901234567890123456789\n"; const combined = login ++ body; const encoded = try container.encode(std.testing.allocator, combined, .best); defer std.testing.allocator.free(encoded); try std.testing.expectEqual(@as(u32, combined.len), std.mem.readInt(u32, encoded[0..4], .big)); const decoded = try container.decode(std.testing.allocator, encoded, cap); defer std.testing.allocator.free(decoded); try std.testing.expectEqualStrings(combined, decoded); } test "container §4.1 r21: decoding does not depend on the compression level" { const input = "the quick brown fox jumps over the lazy dog"; const enc_default = try container.encode(std.testing.allocator, input, .default); defer std.testing.allocator.free(enc_default); const enc_best = try container.encode(std.testing.allocator, input, .best); defer std.testing.allocator.free(enc_best); const dec_default = try container.decode(std.testing.allocator, enc_default, cap); defer std.testing.allocator.free(dec_default); const dec_best = try container.decode(std.testing.allocator, enc_best, cap); defer std.testing.allocator.free(dec_best); try std.testing.expectEqualStrings(input, dec_default); try std.testing.expectEqualStrings(input, dec_best); } test "container §4.1: the empty input round-trips" { const encoded = try container.encode(std.testing.allocator, "", .default); defer std.testing.allocator.free(encoded); try std.testing.expectEqualSlices(u8, &[_]u8{ 0, 0, 0, 0 }, encoded[0..4]); const decoded = try container.decode(std.testing.allocator, encoded, cap); defer std.testing.allocator.free(decoded); try std.testing.expectEqual(@as(usize, 0), decoded.len); } test "container §4.1: a truncated container header is rejected" { try std.testing.expectError(error.TruncatedHeader, container.decode(std.testing.allocator, "\x00\x00", cap)); } test "container §4.1: a decode that fits within declared capacity is accepted" { // §4.1 L905-909, L1210-1211: the length field is an output-capacity // value, not an exact length — a decode that succeeds within capacity is // accepted. Declared 99, decoded 11 <= 99, so the shorter stream is // accepted as-is and the actual bytes are returned. const encoded = try container.encode(std.testing.allocator, "mismatch me", .default); defer std.testing.allocator.free(encoded); var lied: [64]u8 = undefined; @memcpy(lied[0..encoded.len], encoded); std.mem.writeInt(u32, lied[0..4], 99, .big); // declares 99 (capacity), stream carries 11 const decoded = try container.decode(std.testing.allocator, lied[0..encoded.len], cap); defer std.testing.allocator.free(decoded); try std.testing.expectEqualStrings("mismatch me", decoded); } test "container §4.1: output exceeding declared capacity is rejected" { // §4.1 L1209-1210: reject when the decoder cannot fit its output within the // declared capacity — declared 5, actual 11 > 5. const encoded = try container.encode(std.testing.allocator, "mismatch me", .default); defer std.testing.allocator.free(encoded); var lied: [64]u8 = undefined; @memcpy(lied[0..encoded.len], encoded); std.mem.writeInt(u32, lied[0..4], 5, .big); // declares capacity 5, stream carries 11 try std.testing.expectError(error.OutputTooLarge, container.decode(std.testing.allocator, lied[0..encoded.len], cap)); } test "container §4.1: a declared length over max_output is rejected" { const encoded = try container.encode(std.testing.allocator, "capped", .default); defer std.testing.allocator.free(encoded); try std.testing.expectError(error.OutputTooLarge, container.decode(std.testing.allocator, encoded, 2)); } test "container §4.1: garbage after the length prefix is rejected" { const garbage = [_]u8{ 0, 0, 0, 5, 0xff, 0xff, 0xff, 0xff, 0xff }; try std.testing.expectError(error.InvalidStream, container.decode(std.testing.allocator, &garbage, cap)); } fn encodeNoLeak(gpa: std.mem.Allocator) !void { const out = try container.encode(gpa, "allocation failure probe", .default); gpa.free(out); } test "container §4.1: encode survives allocation failure" { try std.testing.checkAllAllocationFailures(std.testing.allocator, encodeNoLeak, .{}); } fn decodeNoLeak(gpa: std.mem.Allocator) !void { const encoded = try container.encode(gpa, "allocation failure probe", .default); defer gpa.free(encoded); const out = try container.decode(gpa, encoded, cap); gpa.free(out); } test "container §4.1: decode survives allocation failure" { try std.testing.checkAllAllocationFailures(std.testing.allocator, decodeNoLeak, .{}); }