diff --git a/src/utils.zig b/src/utils.zig index 4062d75b..4420b79a 100644 --- a/src/utils.zig +++ b/src/utils.zig @@ -1530,6 +1530,195 @@ pub const BinaryWriter = struct { } }; +const ReadWriteTest = struct { + var testingAllocator = main.heap.ErrorHandlingAllocator.init(std.testing.allocator); + var allocator = testingAllocator.allocator(); + + fn getWriter() BinaryWriter { + return .init(ReadWriteTest.allocator); + } + fn getReader(data: []const u8) BinaryReader { + return .init(data); + } + fn testInt(comptime IntT: type, expected: IntT) !void { + var writer = getWriter(); + defer writer.deinit(); + writer.writeInt(IntT, expected); + + const expectedWidth = std.math.divCeil(comptime_int, @bitSizeOf(IntT), 8); + try std.testing.expectEqual(expectedWidth, writer.data.items.len); + + var reader = getReader(writer.data.items); + const actual = try reader.readInt(IntT); + + try std.testing.expectEqual(expected, actual); + } + fn testFloat(comptime FloatT: type, expected: FloatT) !void { + var writer = getWriter(); + defer writer.deinit(); + writer.writeFloat(FloatT, expected); + + var reader = getReader(writer.data.items); + const actual = try reader.readFloat(FloatT); + + try std.testing.expectEqual(expected, actual); + } + fn testEnum(comptime EnumT: type, expected: EnumT) !void { + var writer = getWriter(); + defer writer.deinit(); + writer.writeEnum(EnumT, expected); + + var reader = getReader(writer.data.items); + const actual = try reader.readEnum(EnumT); + + try std.testing.expectEqual(expected, actual); + } + fn TestEnum(comptime IntT: type) type { + return enum(IntT) { + first = std.math.minInt(IntT), + center = (std.math.maxInt(IntT) + std.math.minInt(IntT))/2, + last = std.math.maxInt(IntT), + }; + } + fn testVec(comptime VecT: type, expected: VecT) !void { + var writer = getWriter(); + defer writer.deinit(); + writer.writeVec(VecT, expected); + + var reader = getReader(writer.data.items); + const actual = try reader.readVec(VecT); + + try std.testing.expectEqual(expected, actual); + } +}; + +test "read/write unsigned int" { + inline for([_]type{u0, u1, u2, u4, u5, u8, u16, u31, u32, u64, u128}) |intT| { + const min = std.math.minInt(intT); + const max = std.math.maxInt(intT); + const mid = (max + min)/2; + + try ReadWriteTest.testInt(intT, min); + try ReadWriteTest.testInt(intT, mid); + try ReadWriteTest.testInt(intT, max); + } +} + +test "read/write signed int" { + inline for([_]type{i1, i2, i4, i5, i8, i16, i31, i32, i64, i128}) |intT| { + const min = std.math.minInt(intT); + const lowerMid = std.math.minInt(intT)/2; + const upperMid = std.math.maxInt(intT)/2; + const max = std.math.maxInt(intT); + + try ReadWriteTest.testInt(intT, min); + try ReadWriteTest.testInt(intT, lowerMid); + try ReadWriteTest.testInt(intT, 0); + try ReadWriteTest.testInt(intT, upperMid); + try ReadWriteTest.testInt(intT, max); + } +} + +test "read/write float" { + inline for([_]type{f16, f32, f64, f80, f128}) |floatT| { + try ReadWriteTest.testFloat(floatT, std.math.floatMax(floatT)); + try ReadWriteTest.testFloat(floatT, 0.0012443); + try ReadWriteTest.testFloat(floatT, 0.0); + try ReadWriteTest.testFloat(floatT, 6457.0); + try ReadWriteTest.testFloat(floatT, std.math.inf(floatT)); + try ReadWriteTest.testFloat(floatT, -std.math.inf(floatT)); + try ReadWriteTest.testFloat(floatT, std.math.floatMin(floatT)); + } +} + +test "read/write enum" { + inline for([_]type{ + ReadWriteTest.TestEnum(u2), + ReadWriteTest.TestEnum(u4), + ReadWriteTest.TestEnum(u5), + ReadWriteTest.TestEnum(u8), + ReadWriteTest.TestEnum(u16), + ReadWriteTest.TestEnum(u32), + ReadWriteTest.TestEnum(i2), + ReadWriteTest.TestEnum(i4), + ReadWriteTest.TestEnum(i5), + ReadWriteTest.TestEnum(i8), + ReadWriteTest.TestEnum(i16), + ReadWriteTest.TestEnum(i32), + }) |enumT| { + try ReadWriteTest.testEnum(enumT, .first); + try ReadWriteTest.testEnum(enumT, .center); + try ReadWriteTest.testEnum(enumT, .last); + } +} + +test "read/write Vec3i" { + try ReadWriteTest.testVec(main.vec.Vec3i, .{0, 0, 0}); + try ReadWriteTest.testVec(main.vec.Vec3i, .{ + std.math.maxInt(@typeInfo(main.vec.Vec3i).vector.child), + std.math.minInt(@typeInfo(main.vec.Vec3i).vector.child), + std.math.minInt(@typeInfo(main.vec.Vec3i).vector.child), + }); + try ReadWriteTest.testVec(main.vec.Vec3i, .{ + std.math.minInt(@typeInfo(main.vec.Vec3i).vector.child), + std.math.maxInt(@typeInfo(main.vec.Vec3i).vector.child), + std.math.maxInt(@typeInfo(main.vec.Vec3i).vector.child), + }); +} + +test "read/write Vec3f/Vec3d" { + inline for([_]type{main.vec.Vec3f, main.vec.Vec3d}) |vecT| { + try ReadWriteTest.testVec(vecT, .{0, 0, 0}); + try ReadWriteTest.testVec(vecT, .{0.0043, 0.01123, 0.05043}); + try ReadWriteTest.testVec(vecT, .{5345.0, 42.0, 7854.0}); + try ReadWriteTest.testVec(vecT, .{ + std.math.floatMax(@typeInfo(vecT).vector.child), + std.math.floatMin(@typeInfo(vecT).vector.child), + std.math.floatMin(@typeInfo(vecT).vector.child), + }); + try ReadWriteTest.testVec(vecT, .{ + std.math.floatMin(@typeInfo(vecT).vector.child), + std.math.floatMax(@typeInfo(vecT).vector.child), + std.math.floatMax(@typeInfo(vecT).vector.child), + }); + } +} + +test "read/write mixed" { + const type0 = u4; + const expected0 = 5; + + const type1 = main.vec.Vec3i; + const expected1 = type1{3, -10, 44}; + + const type2 = enum(u3) {first, second, third}; + const expected2 = .second; + + const type3 = f32; + const expected3 = 0.1234; + + const expected4 = "Hello World!"; + + var writer = ReadWriteTest.getWriter(); + defer writer.deinit(); + + writer.writeInt(type0, expected0); + writer.writeVec(type1, expected1); + writer.writeEnum(type2, expected2); + writer.writeFloat(type3, expected3); + writer.writeSlice(expected4); + + var reader = ReadWriteTest.getReader(writer.data.items); + + try std.testing.expectEqual(expected0, try reader.readInt(type0)); + try std.testing.expectEqual(expected1, try reader.readVec(type1)); + try std.testing.expectEqual(expected2, try reader.readEnum(type2)); + try std.testing.expectEqual(expected3, try reader.readFloat(type3)); + try std.testing.expectEqualStrings(expected4, try reader.readSlice(expected4.len)); + + try std.testing.expect(reader.remaining.len == 0); +} + // MARK: functionPtrCast() fn CastFunctionSelfToAnyopaqueType(Fn: type) type { var typeInfo = @typeInfo(Fn);