Add tests for BinaryReader and BinaryWriter (#1273)

* Add tests for BinaryReader and BinaryWriter

* Add guards for integer values

* Add small integer edge cases

* Add mixed data test

* Apply review change requests

* Use std.math.divCeil

* Adapt to endian parameter removal

* Apply review change requests

* Change duplicate u8 into u0
This commit is contained in:
Krzysztof Wiśniewski 2025-04-05 11:19:35 +02:00 committed by GitHub
parent 747a2dc957
commit 823faf64b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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);