authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-05 01:55:35-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:26:56-04:00
log48869bec3d39af0394c90cf6f7e67e656d26eb2b
tree04bac4eaabed4e80cc36d215e6814b84a28864ba
parent90303a7b619ee104133089fc3cf74674d03bf42e

MappedFile: add some basic tests


1 files changed, 170 insertions(+), 0 deletions(-)

src/link/MappedFile.zig+170
...@@ -1337,3 +1337,173 @@ fn verifyNode(mf: *MappedFile, parent_ni: Node.Index) void {...@@ -1337,3 +1337,173 @@ fn verifyNode(mf: *MappedFile, parent_ni: Node.Index) void {
1337 ni = node.next;1337 ni = node.next;
1338 }1338 }
1339}1339}
1340
1341const testing = std.testing;
1342fn testVerifyContent(mf: *@This(), ni: Node.Index, value: u8, init_len: usize) !void {
1343 // Not using std.mem.allEqual, so we can get useful output
1344 const slice = ni.slice(mf);
1345 var buf: [256]u8 = undefined;
1346 @memset(buf[0..init_len], value);
1347 @memset(buf[init_len..], 0);
1348 try testing.expectEqualSlices(u8, buf[0..slice.len], slice);
1349}
1350
1351test {
1352 const gpa = testing.allocator;
1353
1354 var tmp_dir = testing.tmpDir(.{});
1355 defer tmp_dir.cleanup();
1356
1357 var file = try tmp_dir.dir.createFile(testing.io, "test.mf", .{ .read = true });
1358 defer file.close(testing.io);
1359
1360 var mf = try init(file, gpa, testing.io);
1361 defer mf.deinit(gpa);
1362
1363 const a = try mf.addFirstChildNode(gpa, .root, .{ .fixed = true, .alignment = .@"4" });
1364 const c = try mf.addLastChildNode(gpa, .root, .{ .fixed = true, .alignment = .@"4" });
1365 const b = try mf.addNodeAfter(gpa, a, .{ .fixed = true, .alignment = .@"4" });
1366 const d = try mf.addNodeAfter(gpa, b, .{ .alignment = .@"4" });
1367
1368 const a_init_size = 8;
1369 const b_init_size = 16;
1370 const c_init_size = 24;
1371 const d_init_size = 28;
1372
1373 // Resize without content
1374 {
1375 // Verify size is aligned forward
1376 try d.resize(&mf, gpa, d_init_size - 1);
1377 try a.resize(&mf, gpa, a_init_size - 2);
1378 try c.resize(&mf, gpa, c_init_size);
1379 try b.resize(&mf, gpa, b_init_size);
1380 mf.verify();
1381
1382 const a_loc, const a_size = a.location(&mf).resolve(&mf);
1383 const b_loc, const b_size = b.location(&mf).resolve(&mf);
1384 const c_loc, const c_size = c.location(&mf).resolve(&mf);
1385 _, const d_size = d.location(&mf).resolve(&mf);
1386 try testing.expect(a_size >= a_init_size);
1387 try testing.expect(b_size >= b_init_size);
1388 try testing.expect(c_size >= c_init_size);
1389 try testing.expect(d_size >= d_init_size);
1390 try testing.expect(b_loc >= a_loc + a_size);
1391 try testing.expect(c_loc >= b_loc + b_size);
1392 }
1393
1394 const a_exp_size = 24;
1395 const b_exp_size = 28;
1396 const c_exp_size = 48;
1397 const d_exp_size = 32;
1398
1399 // Resize with content
1400 {
1401 @memset(a.slice(&mf)[0..a_init_size], 0xaa);
1402 @memset(b.slice(&mf)[0..b_init_size], 0xbb);
1403 @memset(c.slice(&mf)[0..c_init_size], 0xcc);
1404 @memset(d.slice(&mf)[0..d_init_size], 0xdd);
1405
1406 try a.resize(&mf, gpa, a_exp_size);
1407 try b.resize(&mf, gpa, b_exp_size);
1408 try c.resize(&mf, gpa, c_exp_size);
1409 try d.resize(&mf, gpa, d_exp_size);
1410 mf.verify();
1411
1412 const a_loc, const a_size = a.location(&mf).resolve(&mf);
1413 const b_loc, const b_size = b.location(&mf).resolve(&mf);
1414 const c_loc, const c_size = c.location(&mf).resolve(&mf);
1415 _, const d_size = d.location(&mf).resolve(&mf);
1416 try testing.expect(a_size >= a_exp_size);
1417 try testing.expect(b_size >= b_exp_size);
1418 try testing.expect(c_size >= c_exp_size);
1419 try testing.expect(d_size >= d_exp_size);
1420 try testing.expect(b_loc >= a_loc + a_size);
1421 try testing.expect(c_loc >= b_loc + b_size);
1422
1423 try testVerifyContent(&mf, a, 0xaa, a_init_size);
1424 try testVerifyContent(&mf, b, 0xbb, b_init_size);
1425 try testVerifyContent(&mf, c, 0xcc, c_init_size);
1426 try testVerifyContent(&mf, d, 0xdd, d_init_size);
1427 }
1428
1429 // Re-align nodes
1430 {
1431 try b.realign(&mf, gpa, .@"8", true);
1432 try a.realign(&mf, gpa, .@"16", true);
1433 mf.verify();
1434
1435 try testVerifyContent(&mf, a, 0xaa, a_init_size);
1436 try testVerifyContent(&mf, b, 0xbb, b_init_size);
1437 try testVerifyContent(&mf, c, 0xcc, c_init_size);
1438 try testVerifyContent(&mf, d, 0xdd, d_init_size);
1439 }
1440
1441 const child_init: []const struct { std.mem.Alignment, usize } = &.{
1442 .{ .@"8", 16 },
1443 .{ .@"1", 1 },
1444 .{ .@"1", 19 },
1445 .{ .@"1", 3 },
1446 .{ .@"4", 30 },
1447 .{ .@"2", 5 },
1448 .{ .@"16", 60 },
1449 .{ .@"2", 2 },
1450 .{ .@"16", 32 },
1451 };
1452
1453 var children: [child_init.len]Node.Index = undefined;
1454
1455 // Differently-aligned fixed sibling nodes
1456 {
1457 for (children[0 .. children.len - 1], child_init[0 .. children.len - 1], 0..) |*ni, opts, i| {
1458 ni.* = try mf.addLastChildNode(gpa, b, .{
1459 .alignment = opts.@"0",
1460 .size = opts.@"1",
1461 .fixed = true,
1462 });
1463
1464 @memset(ni.slice(&mf)[0..opts.@"1"], @intCast(i + 1));
1465 }
1466 // Shift differenntly-aligned nodes
1467 children[children.len - 1] = try mf.addNodeAfter(gpa, children[3], .{
1468 .alignment = child_init[children.len - 1].@"0",
1469 .size = child_init[children.len - 1].@"1",
1470 .fixed = true,
1471 });
1472 @memset(children[children.len - 1].slice(&mf), @intCast(children.len));
1473
1474 mf.verify();
1475 for (children, child_init, 0..) |ni, opts, i| {
1476 try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1");
1477 }
1478 }
1479
1480 // Shifting child nodes forward due via resize of parent.prev
1481 {
1482 try testing.expect(a.location(&mf).resolve(&mf)[1] < 64);
1483 try a.resize(&mf, gpa, 64);
1484
1485 try testVerifyContent(&mf, a, 0xaa, a_init_size);
1486 try testVerifyContent(&mf, c, 0xcc, c_init_size);
1487 try testVerifyContent(&mf, d, 0xdd, d_init_size);
1488 for (children, child_init, 0..) |ni, opts, i| {
1489 try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1");
1490 }
1491 }
1492
1493 // Shrink and shift start of trailing node into free space
1494 {
1495 try mf.shrinkNode(gpa, a, 16, true);
1496 mf.verify();
1497
1498 const a_loc, const a_size = a.location(&mf).resolve(&mf);
1499 const b_loc, _ = b.location(&mf).resolve(&mf);
1500 try testing.expectEqual(b_loc, a_loc + a_size);
1501
1502 try testVerifyContent(&mf, a, 0xaa, a_init_size);
1503 try testVerifyContent(&mf, c, 0xcc, c_init_size);
1504 try testVerifyContent(&mf, d, 0xdd, d_init_size);
1505 for (children, child_init, 0..) |ni, opts, i| {
1506 try testVerifyContent(&mf, ni, @intCast(i + 1), opts.@"1");
1507 }
1508 }
1509}