diff options
| author | BenoitJGirard <BenoitJGirard@users.noreply.github.com> | 2019-02-17 14:38:55 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-02-17 14:38:55 -0500 |
| commit | 6daa041932ae5ab03eed953dacf3ca506078390c (patch) | |
| tree | 0f51f6c2ff84dde51b61bba6799e5c5abccf91b4 /std/testing.zig | |
| parent | f0ec308e26ff957c7fbb50ccc69d3d549c42c4da (diff) | |
| parent | 8d2a902945ef97f28152c3d5a68bb974809c8539 (diff) | |
| download | zig-6daa041932ae5ab03eed953dacf3ca506078390c.tar.gz zig-6daa041932ae5ab03eed953dacf3ca506078390c.zip | |
Merge pull request #2 from ziglang/master
Refreshing fork.
Diffstat (limited to 'std/testing.zig')
| -rw-r--r-- | std/testing.zig | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/std/testing.zig b/std/testing.zig new file mode 100644 index 0000000000..a47c5984a0 --- /dev/null +++ b/std/testing.zig @@ -0,0 +1,147 @@ +const builtin = @import("builtin"); +const TypeId = builtin.TypeId; +const std = @import("index.zig"); + +/// 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 { + // TODO remove the workaround here for https://github.com/ziglang/zig/issues/1936 + 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. +pub fn expectEqual(expected: var, actual: @typeOf(expected)) void { + switch (@typeInfo(@typeOf(actual))) { + TypeId.NoReturn, + TypeId.BoundFn, + TypeId.ArgTuple, + TypeId.Opaque, + => @compileError("value of type " ++ @typeName(@typeOf(actual)) ++ " encountered"), + + TypeId.Undefined, + TypeId.Null, + TypeId.Void, + => return, + + TypeId.Type, + TypeId.Bool, + TypeId.Int, + TypeId.Float, + TypeId.ComptimeFloat, + TypeId.ComptimeInt, + TypeId.Enum, + TypeId.Namespace, + TypeId.Fn, + TypeId.Promise, + TypeId.Vector, + TypeId.ErrorSet, + => { + if (actual != expected) { + std.debug.panic("expected {}, found {}", expected, actual); + } + }, + + TypeId.Pointer => |pointer| { + switch (pointer.size) { + builtin.TypeInfo.Pointer.Size.One, + builtin.TypeInfo.Pointer.Size.Many, + => { + if (actual != expected) { + std.debug.panic("expected {}, found {}", expected, actual); + } + }, + + builtin.TypeInfo.Pointer.Size.Slice => { + 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); + } + }, + } + }, + + TypeId.Array => |array| expectEqualSlices(array.child, &expected, &actual), + + TypeId.Struct => { + @compileError("TODO implement testing.expectEqual for structs"); + }, + + TypeId.Union => |union_info| { + if (union_info.tag_type == null) { + @compileError("Unable to compare untagged union values"); + } + @compileError("TODO implement testing.expectEqual for tagged unions"); + }, + + TypeId.Optional => { + 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); + } + } + }, + + TypeId.ErrorUnion => { + 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"); +} |
