feature. See also
. The project being documented here (as the example) is the Zig library itself.
testing.expectEqualInner
fn expectEqualInner(comptime T: type, expected: T, actual: T) !void
File
Code
fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
switch (@typeInfo(@TypeOf(actual))) {
.noreturn,
.@"opaque",
.spirv,
.frame,
.@"anyframe",
=> @compileError("value of type " ++ @typeName(@TypeOf(actual)) ++ " encountered"),
.undefined,
.null,
.void,
=> return,
.type => {
if (actual != expected) {
print("expected type {s}, found type {s}\n", .{ @typeName(expected), @typeName(actual) });
return error.TestExpectedEqual;
}
},
.bool,
.int,
.float,
.comptime_float,
.comptime_int,
.enum_literal,
.@"enum",
.@"fn",
.error_set,
=> {
if (actual != expected) {
print("expected {any}, found {any}\n", .{ expected, actual });
return error.TestExpectedEqual;
}
},
.pointer => |pointer| {
switch (pointer.size) {
.one, .many, .c => {
if (actual != expected) {
print("expected {*}, found {*}\n", .{ expected, actual });
return error.TestExpectedEqual;
}
},
.slice => {
if (actual.ptr != expected.ptr) {
print("expected slice ptr {*}, found {*}\n", .{ expected.ptr, actual.ptr });
return error.TestExpectedEqual;
}
if (actual.len != expected.len) {
print("expected slice len {}, found {}\n", .{ expected.len, actual.len });
return error.TestExpectedEqual;
}
},
}
},
.array => |array| try expectEqualSlices(array.child, &expected, &actual),
.vector => |info| {
const expect_array: [info.len]info.child = expected;
const actual_array: [info.len]info.child = actual;
try expectEqualSlices(info.child, &expect_array, &actual_array);
},
.@"struct" => |@"struct"| {
inline for (@"struct".field_names) |field_name| {
try expectEqual(@field(expected, field_name), @field(actual, field_name));
}
},
.@"union" => |@"union"| if (@"union".backing_integer) |Int| {
try expectEqual(@as(Int, @bitCast(expected)), @as(Int, @bitCast(actual)));
} else switch (@"union".layout) {
.@"packed" => {
const Int = @Int(.unsigned, @bitSizeOf(T));
try expectEqual(@as(Int, @bitCast(expected)), @as(Int, @bitCast(actual)));
},
.@"extern" => {
const first_size = @bitSizeOf(@"union".field_types[0]);
inline for (@"union".field_types) |field_type| {
if (@bitSizeOf(field_type) != first_size) {
@compileError("Unable to compare extern unions with varying field sizes for type " ++ @typeName(T));
}
}
const FieldInt = @Int(.unsigned, first_size);
const expected_field = @field(expected, @"union".field_names[0]);
const actual_field = @field(actual, @"union".field_names[0]);
return expectEqual(
@as(FieldInt, @bitCast(expected_field)),
@as(FieldInt, @bitCast(actual_field)),
);
},
.auto => {
const Tag = @"union".tag_type orelse @compileError("byteSwapAllFields expects packed, extern, or tagged union");
try expectEqual(@as(Tag, expected), @as(Tag, actual));
switch (expected) {
inline else => |expected_payload, tag| {
const actual_payload = @field(actual, @tagName(tag));
try expectEqual(expected_payload, actual_payload);
},
}
},
},
.optional => {
if (expected) |expected_payload| {
if (actual) |actual_payload| {
try expectEqual(expected_payload, actual_payload);
} else {
print("expected {any}, found null\n", .{expected_payload});
return error.TestExpectedEqual;
}
} else {
if (actual) |actual_payload| {
print("expected null, found {any}\n", .{actual_payload});
return error.TestExpectedEqual;
}
}
},
.error_union => {
if (expected) |expected_payload| {
if (actual) |actual_payload| {
try expectEqual(expected_payload, actual_payload);
} else |actual_err| {
print("expected {any}, found {}\n", .{ expected_payload, actual_err });
return error.TestExpectedEqual;
}
} else |expected_err| {
if (actual) |actual_payload| {
print("expected {}, found {any}\n", .{ expected_err, actual_payload });
return error.TestExpectedEqual;
} else |actual_err| {
try expectEqual(expected_err, actual_err);
}
}
},
}
}