feature. See also
. The project being documented here (as the example) is the Zig library itself.
testing.expectEqualDeepInner
fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error
File
Code
fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpectedEqual}!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) {
.c, .many => {
if (actual != expected) {
print("expected {*}, found {*}\n", .{ expected, actual });
return error.TestExpectedEqual;
}
},
.one => {
switch (@typeInfo(pointer.child)) {
.@"fn", .@"opaque" => {
if (actual != expected) {
print("expected {*}, found {*}\n", .{ expected, actual });
return error.TestExpectedEqual;
}
},
else => try expectEqualDeep(expected.*, actual.*),
}
},
.slice => {
if (expected.len != actual.len) {
print("Slice len not the same, expected {d}, found {d}\n", .{ expected.len, actual.len });
return error.TestExpectedEqual;
}
var i: usize = 0;
while (i < expected.len) : (i += 1) {
expectEqualDeep(expected[i], actual[i]) catch |e| {
print("index {d} incorrect. expected {any}, found {any}\n", .{
i, expected[i], actual[i],
});
return e;
};
}
},
}
},
.array => {
if (expected.len != actual.len) {
print("Array len not the same, expected {d}, found {d}\n", .{ expected.len, actual.len });
return error.TestExpectedEqual;
}
var i: usize = 0;
while (i < expected.len) : (i += 1) {
expectEqualDeep(expected[i], actual[i]) catch |e| {
print("index {d} incorrect. expected {any}, found {any}\n", .{
i, expected[i], actual[i],
});
return e;
};
}
},
.vector => |info| {
if (info.len != @typeInfo(@TypeOf(actual)).vector.len) {
print("Vector len not the same, expected {d}, found {d}\n", .{ info.len, @typeInfo(@TypeOf(actual)).vector.len });
return error.TestExpectedEqual;
}
inline for (0..info.len) |i| {
expectEqualDeep(expected[i], actual[i]) catch |e| {
print("index {d} incorrect. expected {any}, found {any}\n", .{
i, expected[i], actual[i],
});
return e;
};
}
},
.@"struct" => |structType| {
inline for (structType.field_names) |field_name| {
expectEqualDeep(@field(expected, field_name), @field(actual, field_name)) catch |e| {
print("Field {s} incorrect. expected {any}, found {any}\n", .{ field_name, @field(expected, field_name), @field(actual, field_name) });
return e;
};
}
},
.@"union" => |union_info| {
if (union_info.tag_type == null) {
@compileError("Unable to compare untagged union values for type " ++ @typeName(@TypeOf(actual)));
}
const Tag = std.meta.Tag(@TypeOf(expected));
const expectedTag = @as(Tag, expected);
const actualTag = @as(Tag, actual);
try expectEqual(expectedTag, actualTag);
switch (expected) {
inline else => |val, tag| {
try expectEqualDeep(val, @field(actual, @tagName(tag)));
},
}
},
.optional => {
if (expected) |expected_payload| {
if (actual) |actual_payload| {
try expectEqualDeep(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 expectEqualDeep(expected_payload, actual_payload);
} else |actual_err| {
print("expected {any}, found {any}\n", .{ expected_payload, actual_err });
return error.TestExpectedEqual;
}
} else |expected_err| {
if (actual) |actual_payload| {
print("expected {any}, found {any}\n", .{ expected_err, actual_payload });
return error.TestExpectedEqual;
} else |actual_err| {
try expectEqualDeep(expected_err, actual_err);
}
}
},
}
}