// Tests for the comptime `compiler` library's binding registry. const std = @import("std"); const compiler_lib = @import("compiler_lib.zig"); const types = @import("types.zig"); // Lock: `findType("Field")` resolves to the welded `StructInfo.Field` type, and // its baked layout EQUALS the real Zig type's `@sizeOf`/`@alignOf`/`@offsetOf`. // This is the foundation the layout sub-step builds on — the welded record's // offsets come from the implementation, so they can't drift. test "compiler_lib: Field welds to StructInfo.Field's real layout" { const FieldZig = types.TypeInfo.StructInfo.Field; const bt = compiler_lib.findType("Field") orelse return error.MissingBoundType; try std.testing.expectEqualStrings("Field", bt.sx_name); try std.testing.expectEqual(@sizeOf(FieldZig), bt.size); try std.testing.expectEqual(@alignOf(FieldZig), bt.alignment); // Two u32 fields, in declaration order. try std.testing.expectEqual(@as(usize, 2), bt.fields.len); try std.testing.expectEqualStrings("name", bt.fields[0].name); try std.testing.expectEqual(@offsetOf(FieldZig, "name"), bt.fields[0].offset); try std.testing.expectEqual(@as(usize, 4), bt.fields[0].size); try std.testing.expectEqualStrings("ty", bt.fields[1].name); try std.testing.expectEqual(@offsetOf(FieldZig, "ty"), bt.fields[1].offset); try std.testing.expectEqual(@as(usize, 4), bt.fields[1].size); // Sanity: the concrete shape the design calls out — two u32s, 8 bytes. try std.testing.expectEqual(@as(usize, 8), bt.size); try std.testing.expectEqual(@as(usize, 0), bt.fields[0].offset); try std.testing.expectEqual(@as(usize, 4), bt.fields[1].offset); } // Lock: a name NOT on the export list is unreachable — `findType` returns null // (the safety boundary; the welded-decl path falls through to a clean error, // never a silent default). test "compiler_lib: unexported name returns null" { try std.testing.expect(compiler_lib.findType("NotExported") == null); try std.testing.expect(compiler_lib.findType("") == null); } // Lock: a faithful sx header for `Field` validates clean (the natural two-u32 // layout matches the welded type). test "compiler_lib: validateStructLayout accepts a faithful Field header" { const bt = compiler_lib.findType("Field").?; const sx = [_]compiler_lib.SxField{ .{ .name = "name", .size = 4 }, .{ .name = "ty", .size = 4 }, }; try std.testing.expect(compiler_lib.validateStructLayout(bt, &sx, 8) == null); } // Lock: every drift the assertion is meant to catch surfaces as the right // `LayoutMismatch` variant (field count / name / size / total), and the first // mismatch wins. test "compiler_lib: validateStructLayout flags each kind of drift" { const bt = compiler_lib.findType("Field").?; // Wrong field count (one field instead of two). { const sx = [_]compiler_lib.SxField{.{ .name = "name", .size = 4 }}; const m = compiler_lib.validateStructLayout(bt, &sx, 4).?; try std.testing.expect(m == .field_count); try std.testing.expectEqual(@as(usize, 2), m.field_count.expected); try std.testing.expectEqual(@as(usize, 1), m.field_count.got); } // Wrong field name (reorder / rename) at index 1. { const sx = [_]compiler_lib.SxField{ .{ .name = "name", .size = 4 }, .{ .name = "kind", .size = 4 }, }; const m = compiler_lib.validateStructLayout(bt, &sx, 8).?; try std.testing.expect(m == .field_name); try std.testing.expectEqual(@as(usize, 1), m.field_name.index); try std.testing.expectEqualStrings("ty", m.field_name.expected); try std.testing.expectEqualStrings("kind", m.field_name.got); } // Wrong field size (retype to an 8-byte field). { const sx = [_]compiler_lib.SxField{ .{ .name = "name", .size = 4 }, .{ .name = "ty", .size = 8 }, }; const m = compiler_lib.validateStructLayout(bt, &sx, 12).?; try std.testing.expect(m == .field_size); try std.testing.expectEqual(@as(usize, 1), m.field_size.index); try std.testing.expectEqual(@as(usize, 4), m.field_size.expected); try std.testing.expectEqual(@as(usize, 8), m.field_size.got); } // Right fields, wrong total (padding drift). { const sx = [_]compiler_lib.SxField{ .{ .name = "name", .size = 4 }, .{ .name = "ty", .size = 4 }, }; const m = compiler_lib.validateStructLayout(bt, &sx, 16).?; try std.testing.expect(m == .total_size); try std.testing.expectEqual(@as(usize, 8), m.total_size.expected); try std.testing.expectEqual(@as(usize, 16), m.total_size.got); } } // Lock: `StructInfo` is reflected in MEMORY order — Zig reorders it from source // order (name, fields, is_protocol, nominal_id) to (fields@0, name@16, // nominal_id@20, is_protocol@24). The registry must present the fields in that // memory order, since an sx welded header must declare them so to be // byte-identical. test "compiler_lib: StructInfo is reflected in Zig memory order" { const StructInfoZig = types.TypeInfo.StructInfo; const bt = compiler_lib.findType("StructInfo").?; try std.testing.expectEqual(@sizeOf(StructInfoZig), bt.size); try std.testing.expectEqual(@as(usize, 4), bt.fields.len); // Memory order: fields, name, nominal_id, is_protocol. try std.testing.expectEqualStrings("fields", bt.fields[0].name); try std.testing.expectEqual(@offsetOf(StructInfoZig, "fields"), bt.fields[0].offset); try std.testing.expectEqualStrings("name", bt.fields[1].name); try std.testing.expectEqual(@offsetOf(StructInfoZig, "name"), bt.fields[1].offset); try std.testing.expectEqualStrings("nominal_id", bt.fields[2].name); try std.testing.expectEqual(@offsetOf(StructInfoZig, "nominal_id"), bt.fields[2].offset); try std.testing.expectEqualStrings("is_protocol", bt.fields[3].name); try std.testing.expectEqual(@offsetOf(StructInfoZig, "is_protocol"), bt.fields[3].offset); // Offsets are strictly ascending (memory order). try std.testing.expect(bt.fields[0].offset < bt.fields[1].offset); try std.testing.expect(bt.fields[1].offset < bt.fields[2].offset); try std.testing.expect(bt.fields[2].offset < bt.fields[3].offset); } // Lock: the welded-function export list resolves the round-trip readers and // rejects unexported names (the boundary the interp's dispatch consults). test "compiler_lib: findFn resolves exported functions, rejects others" { try std.testing.expect(compiler_lib.findFn("intern") != null); try std.testing.expect(compiler_lib.findFn("text_of") != null); try std.testing.expectEqualStrings("intern", compiler_lib.findFn("intern").?.sx_name); try std.testing.expect(compiler_lib.findFn("not_exported") == null); try std.testing.expect(compiler_lib.findFn("") == null); }