zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 48869bec3d39af0394c90cf6f7e67e656d26eb2b (tree)
parent 90303a7b619ee104133089fc3cf74674d03bf42e
Author: kcbanner <kcbanner@gmail.com>
Date:   Fri,  5 Jun 2026 01:55:35 -0400

MappedFile: add some basic tests

Diffstat:
Msrc/link/MappedFile.zig | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 170 insertions(+), 0 deletions(-)

diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig @@ -1337,3 +1337,173 @@ fn verifyNode(mf: *MappedFile, parent_ni: Node.Index) void { ni = node.next; } } + +const testing = std.testing; +fn testVerifyContent(mf: *@This(), ni: Node.Index, value: u8, init_len: usize) !void { + // Not using std.mem.allEqual, so we can get useful output + const slice = ni.slice(mf); + var buf: [256]u8 = undefined; + @memset(buf[0..init_len], value); + @memset(buf[init_len..], 0); + try testing.expectEqualSlices(u8, buf[0..slice.len], slice); +} + +test { + const gpa = testing.allocator; + + var tmp_dir = testing.tmpDir(.{}); + defer tmp_dir.cleanup(); + + var file = try tmp_dir.dir.createFile(testing.io, "test.mf", .{ .read = true }); + defer file.close(testing.io); + + var mf = try init(file, gpa, testing.io); + defer mf.deinit(gpa); + + const a = try mf.addFirstChildNode(gpa, .root, .{ .fixed = true, .alignment = .@"4" }); + const c = try mf.addLastChildNode(gpa, .root, .{ .fixed = true, .alignment = .@"4" }); + const b = try mf.addNodeAfter(gpa, a, .{ .fixed = true, .alignment = .@"4" }); + const d = try mf.addNodeAfter(gpa, b, .{ .alignment = .@"4" }); + + const a_init_size = 8; + const b_init_size = 16; + const c_init_size = 24; + const d_init_size = 28; + + // Resize without content + { + // Verify size is aligned forward + try d.resize(&mf, gpa, d_init_size - 1); + try a.resize(&mf, gpa, a_init_size - 2); + try c.resize(&mf, gpa, c_init_size); + try b.resize(&mf, gpa, b_init_size); + mf.verify(); + + const a_loc, const a_size = a.location(&mf).resolve(&mf); + const b_loc, const b_size = b.location(&mf).resolve(&mf); + const c_loc, const c_size = c.location(&mf).resolve(&mf); + _, const d_size = d.location(&mf).resolve(&mf); + try testing.expect(a_size >= a_init_size); + try testing.expect(b_size >= b_init_size); + try testing.expect(c_size >= c_init_size); + try testing.expect(d_size >= d_init_size); + try testing.expect(b_loc >= a_loc + a_size); + try testing.expect(c_loc >= b_loc + b_size); + } + + const a_exp_size = 24; + const b_exp_size = 28; + const c_exp_size = 48; + const d_exp_size = 32; + + // Resize with content + { + @memset(a.slice(&mf)[0..a_init_size], 0xaa); + @memset(b.slice(&mf)[0..b_init_size], 0xbb); + @memset(c.slice(&mf)[0..c_init_size], 0xcc); + @memset(d.slice(&mf)[0..d_init_size], 0xdd); + + try a.resize(&mf, gpa, a_exp_size); + try b.resize(&mf, gpa, b_exp_size); + try c.resize(&mf, gpa, c_exp_size); + try d.resize(&mf, gpa, d_exp_size); + mf.verify(); + + const a_loc, const a_size = a.location(&mf).resolve(&mf); + const b_loc, const b_size = b.location(&mf).resolve(&mf); + const c_loc, const c_size = c.location(&mf).resolve(&mf); + _, const d_size = d.location(&mf).resolve(&mf); + try testing.expect(a_size >= a_exp_size); + try testing.expect(b_size >= b_exp_size); + try testing.expect(c_size >= c_exp_size); + try testing.expect(d_size >= d_exp_size); + try testing.expect(b_loc >= a_loc + a_size); + try testing.expect(c_loc >= b_loc + b_size); + + try testVerifyContent(&mf, a, 0xaa, a_init_size); + try testVerifyContent(&mf, b, 0xbb, b_init_size); + try testVerifyContent(&mf, c, 0xcc, c_init_size); + try testVerifyContent(&mf, d, 0xdd, d_init_size); + } + + // Re-align nodes + { + try b.realign(&mf, gpa, .@"8", true); + try a.realign(&mf, gpa, .@"16", true); + mf.verify(); + + try testVerifyContent(&mf, a, 0xaa, a_init_size); + try testVerifyContent(&mf, b, 0xbb, b_init_size); + try testVerifyContent(&mf, c, 0xcc, c_init_size); + try testVerifyContent(&mf, d, 0xdd, d_init_size); + } + + const child_init: []const struct { std.mem.Alignment, usize } = &.{ + .{ .@"8", 16 }, + .{ .@"1", 1 }, + .{ .@"1", 19 }, + .{ .@"1", 3 }, + .{ .@"4", 30 }, + .{ .@"2", 5 }, + .{ .@"16", 60 }, + .{ .@"2", 2 }, + .{ .@"16", 32 }, + }; + + var children: [child_init.len]Node.Index = undefined; + + // Differently-aligned fixed sibling nodes + { + for (children[0 .. children.len - 1], child_init[0 .. children.len - 1], 0..) |*ni, opts, i| { + ni.* = try mf.addLastChildNode(gpa, b, .{ + .alignment = opts.@"0", + .size = opts.@"1", + .fixed = true, + }); + + @memset(ni.slice(&mf)[0..opts.@"1"], @intCast(i + 1)); + } + // Shift differenntly-aligned nodes + children[children.len - 1] = try mf.addNodeAfter(gpa, children[3], .{ + .alignment = child_init[children.len - 1].@"0", + .size = child_init[children.len - 1].@"1", + .fixed = true, + }); + @memset(children[children.len - 1].slice(&mf), @intCast(children.len)); + + mf.verify(); + for (children, child_init, 0..) |ni, opts, i| { + try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1"); + } + } + + // Shifting child nodes forward due via resize of parent.prev + { + try testing.expect(a.location(&mf).resolve(&mf)[1] < 64); + try a.resize(&mf, gpa, 64); + + try testVerifyContent(&mf, a, 0xaa, a_init_size); + try testVerifyContent(&mf, c, 0xcc, c_init_size); + try testVerifyContent(&mf, d, 0xdd, d_init_size); + for (children, child_init, 0..) |ni, opts, i| { + try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1"); + } + } + + // Shrink and shift start of trailing node into free space + { + try mf.shrinkNode(gpa, a, 16, true); + mf.verify(); + + const a_loc, const a_size = a.location(&mf).resolve(&mf); + const b_loc, _ = b.location(&mf).resolve(&mf); + try testing.expectEqual(b_loc, a_loc + a_size); + + try testVerifyContent(&mf, a, 0xaa, a_init_size); + try testVerifyContent(&mf, c, 0xcc, c_init_size); + try testVerifyContent(&mf, d, 0xdd, d_init_size); + for (children, child_init, 0..) |ni, opts, i| { + try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1"); + } + } +}