DoxigAlpha

expectEqualInner

Function parameters

Parameters

#
T:type
expected:T
actual:T

Type definitions in this namespace

Types

#
Reader
A `std.Io.Reader` that writes a predetermined list of buffers during `stream`.
ReaderIndirect
A `std.Io.Reader` that gets its data from another `std.Io.Reader`, and always

This function is intended to be used only in tests.

Functions

#
expectError
This function is intended to be used only in tests.
expectEqual
This function is intended to be used only in tests.
expectFmt
This function is intended to be used only in tests.
expectApproxEqAbs
This function is intended to be used only in tests.
expectApproxEqRel
This function is intended to be used only in tests.
expectEqualSlices
This function is intended to be used only in tests.
expectEqualSentinel
This function is intended to be used only in tests.
expect
This function is intended to be used only in tests.
expectEqualDeep
This function is intended to be used only in tests.
checkAllAllocationFailures
Exhaustively check that allocation failures within `test_fn` are handled without
refAllDecls
Given a type, references all the declarations inside, so that the semantic analyzer sees them.
refAllDeclsRecursive
Given a type, recursively references all the declarations inside, so that the semantic analyzer sees them.
fuzz
Inline to avoid coverage instrumentation.

Provides deterministic randomness in unit tests.

Values

#
random_seed
Provides deterministic randomness in unit tests.
failing_allocator
= failing_allocator_instance.allocator()
allocator
This should only be used in temporary test programs.
log_level
TODO https://github.com/ziglang/zig/issues/5738
backend_can_print
= switch (builtin.zig_backend) { .stage2_aarch64, .stage2_powerpc, .stage2_riscv64, .stage2_spirv, => false, else => true, }

Source

Implementation

#
fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
    switch (@typeInfo(@TypeOf(actual))) {
        .noreturn,
        .@"opaque",
        .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| {
            var i: usize = 0;
            while (i < info.len) : (i += 1) {
                if (!std.meta.eql(expected[i], actual[i])) {
                    print("index {d} incorrect. expected {any}, found {any}\n", .{
                        i, expected[i], actual[i],
                    });
                    return error.TestExpectedEqual;
                }
            }
        },

        .@"struct" => |structType| {
            inline for (structType.fields) |field| {
                try expectEqual(@field(expected, field.name), @field(actual, field.name));
            }
        },

        .@"union" => |union_info| {
            if (union_info.tag_type == null) {
                const first_size = @bitSizeOf(union_info.fields[0].type);
                inline for (union_info.fields) |field| {
                    if (@bitSizeOf(field.type) != first_size) {
                        @compileError("Unable to compare untagged unions with varying field sizes for type " ++ @typeName(@TypeOf(actual)));
                    }
                }

                const BackingInt = std.meta.Int(.unsigned, @bitSizeOf(T));
                return expectEqual(
                    @as(BackingInt, @bitCast(expected)),
                    @as(BackingInt, @bitCast(actual)),
                );
            }

            const Tag = std.meta.Tag(@TypeOf(expected));

            const expectedTag = @as(Tag, expected);
            const actualTag = @as(Tag, actual);

            try expectEqual(expectedTag, actualTag);

            // we only reach this switch if the tags are equal
            switch (expected) {
                inline else => |val, tag| try expectEqual(val, @field(actual, @tagName(tag))),
            }
        },

        .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);
                }
            }
        },
    }
}