2019-02-08 15:18:47 -08:00
|
|
|
const builtin = @import("builtin");
|
|
|
|
const TypeId = builtin.TypeId;
|
2019-03-02 13:46:04 -08:00
|
|
|
const std = @import("std.zig");
|
2019-02-08 15:18:47 -08:00
|
|
|
|
|
|
|
/// This function is intended to be used only in tests. It prints diagnostics to stderr
|
|
|
|
/// and then aborts when actual_error_union is not expected_error.
|
|
|
|
pub fn expectError(expected_error: anyerror, actual_error_union: var) void {
|
|
|
|
if (actual_error_union) |actual_payload| {
|
|
|
|
// TODO remove workaround here for https://github.com/ziglang/zig/issues/557
|
|
|
|
if (@sizeOf(@typeOf(actual_payload)) == 0) {
|
|
|
|
std.debug.panic("expected error.{}, found {} value", @errorName(expected_error), @typeName(@typeOf(actual_payload)));
|
|
|
|
} else {
|
|
|
|
std.debug.panic("expected error.{}, found {}", @errorName(expected_error), actual_payload);
|
|
|
|
}
|
|
|
|
} else |actual_error| {
|
|
|
|
if (expected_error != actual_error) {
|
|
|
|
std.debug.panic("expected error.{}, found error.{}", @errorName(expected_error), @errorName(actual_error));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This function is intended to be used only in tests. When the two values are not
|
|
|
|
/// equal, prints diagnostics to stderr to show exactly how they are not equal,
|
|
|
|
/// then aborts.
|
|
|
|
/// The types must match exactly.
|
2019-02-10 03:43:49 -08:00
|
|
|
pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
|
2019-02-08 15:18:47 -08:00
|
|
|
switch (@typeInfo(@typeOf(actual))) {
|
2019-07-21 16:56:37 -07:00
|
|
|
.NoReturn,
|
|
|
|
.BoundFn,
|
|
|
|
.ArgTuple,
|
|
|
|
.Opaque,
|
|
|
|
.Frame,
|
2019-07-26 16:52:35 -07:00
|
|
|
.AnyFrame,
|
2019-02-08 15:18:47 -08:00
|
|
|
=> @compileError("value of type " ++ @typeName(@typeOf(actual)) ++ " encountered"),
|
|
|
|
|
2019-07-21 16:56:37 -07:00
|
|
|
.Undefined,
|
|
|
|
.Null,
|
|
|
|
.Void,
|
2019-02-08 15:18:47 -08:00
|
|
|
=> return,
|
|
|
|
|
2019-07-21 16:56:37 -07:00
|
|
|
.Type,
|
|
|
|
.Bool,
|
|
|
|
.Int,
|
|
|
|
.Float,
|
|
|
|
.ComptimeFloat,
|
|
|
|
.ComptimeInt,
|
|
|
|
.EnumLiteral,
|
|
|
|
.Enum,
|
|
|
|
.Fn,
|
|
|
|
.Vector,
|
|
|
|
.ErrorSet,
|
2019-02-08 15:18:47 -08:00
|
|
|
=> {
|
|
|
|
if (actual != expected) {
|
|
|
|
std.debug.panic("expected {}, found {}", expected, actual);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-07-21 16:56:37 -07:00
|
|
|
.Pointer => |pointer| {
|
2019-02-08 15:18:47 -08:00
|
|
|
switch (pointer.size) {
|
|
|
|
builtin.TypeInfo.Pointer.Size.One,
|
|
|
|
builtin.TypeInfo.Pointer.Size.Many,
|
2019-02-18 08:22:14 -08:00
|
|
|
builtin.TypeInfo.Pointer.Size.C,
|
2019-02-08 15:18:47 -08:00
|
|
|
=> {
|
|
|
|
if (actual != expected) {
|
2019-11-14 14:29:21 -08:00
|
|
|
std.debug.panic("expected {*}, found {*}", expected, actual);
|
2019-02-08 15:18:47 -08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-02-11 13:07:40 -08:00
|
|
|
builtin.TypeInfo.Pointer.Size.Slice => {
|
2019-02-08 15:18:47 -08:00
|
|
|
if (actual.ptr != expected.ptr) {
|
|
|
|
std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr);
|
|
|
|
}
|
|
|
|
if (actual.len != expected.len) {
|
|
|
|
std.debug.panic("expected slice len {}, found {}", expected.len, actual.len);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-07-21 16:56:37 -07:00
|
|
|
.Array => |array| expectEqualSlices(array.child, &expected, &actual),
|
2019-02-08 15:18:47 -08:00
|
|
|
|
2019-07-21 16:56:37 -07:00
|
|
|
.Struct => |structType| {
|
2019-05-20 07:29:46 -07:00
|
|
|
inline for (structType.fields) |field| {
|
|
|
|
expectEqual(@field(expected, field.name), @field(actual, field.name));
|
|
|
|
}
|
2019-02-08 15:18:47 -08:00
|
|
|
},
|
|
|
|
|
2019-07-21 16:56:37 -07:00
|
|
|
.Union => |union_info| {
|
2019-02-08 15:18:47 -08:00
|
|
|
if (union_info.tag_type == null) {
|
|
|
|
@compileError("Unable to compare untagged union values");
|
|
|
|
}
|
|
|
|
@compileError("TODO implement testing.expectEqual for tagged unions");
|
|
|
|
},
|
|
|
|
|
2019-07-21 16:56:37 -07:00
|
|
|
.Optional => {
|
2019-02-08 15:18:47 -08:00
|
|
|
if (expected) |expected_payload| {
|
|
|
|
if (actual) |actual_payload| {
|
|
|
|
expectEqual(expected_payload, actual_payload);
|
|
|
|
} else {
|
|
|
|
std.debug.panic("expected {}, found null", expected_payload);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (actual) |actual_payload| {
|
|
|
|
std.debug.panic("expected null, found {}", actual_payload);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-07-21 16:56:37 -07:00
|
|
|
.ErrorUnion => {
|
2019-02-08 15:18:47 -08:00
|
|
|
if (expected) |expected_payload| {
|
|
|
|
if (actual) |actual_payload| {
|
|
|
|
expectEqual(expected_payload, actual_payload);
|
|
|
|
} else |actual_err| {
|
|
|
|
std.debug.panic("expected {}, found {}", expected_payload, actual_err);
|
|
|
|
}
|
|
|
|
} else |expected_err| {
|
|
|
|
if (actual) |actual_payload| {
|
|
|
|
std.debug.panic("expected {}, found {}", expected_err, actual_payload);
|
|
|
|
} else |actual_err| {
|
|
|
|
expectEqual(expected_err, actual_err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This function is intended to be used only in tests. When the two slices are not
|
|
|
|
/// equal, prints diagnostics to stderr to show exactly how they are not equal,
|
|
|
|
/// then aborts.
|
|
|
|
pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) void {
|
|
|
|
// TODO better printing of the difference
|
|
|
|
// If the arrays are small enough we could print the whole thing
|
|
|
|
// If the child type is u8 and no weird bytes, we could print it as strings
|
|
|
|
// Even for the length difference, it would be useful to see the values of the slices probably.
|
|
|
|
if (expected.len != actual.len) {
|
|
|
|
std.debug.panic("slice lengths differ. expected {}, found {}", expected.len, actual.len);
|
|
|
|
}
|
|
|
|
var i: usize = 0;
|
|
|
|
while (i < expected.len) : (i += 1) {
|
|
|
|
if (expected[i] != actual[i]) {
|
|
|
|
std.debug.panic("index {} incorrect. expected {}, found {}", i, expected[i], actual[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This function is intended to be used only in tests. When `ok` is false, the test fails.
|
|
|
|
/// A message is printed to stderr and then abort is called.
|
|
|
|
pub fn expect(ok: bool) void {
|
|
|
|
if (!ok) @panic("test failure");
|
|
|
|
}
|