diff options
author | 2021-05-05 19:02:30 -0700 | |
---|---|---|
committer | 2021-05-05 19:02:30 -0700 | |
commit | d975ab19db14b75b1099470cdf984329537a20aa (patch) | |
tree | dfb0845f0e3db99f72ba2217ef0d6b3804592690 /src/test/tester.zig | |
parent | 41c9896e11948b91dea278636c226516f7c01f3d (diff) | |
download | bun-d975ab19db14b75b1099470cdf984329537a20aa.tar.gz bun-d975ab19db14b75b1099470cdf984329537a20aa.tar.zst bun-d975ab19db14b75b1099470cdf984329537a20aa.zip |
cool
Former-commit-id: 3708dd44843274f397ae28b2cead39de8f55e6a6
Diffstat (limited to 'src/test/tester.zig')
-rw-r--r-- | src/test/tester.zig | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/test/tester.zig b/src/test/tester.zig new file mode 100644 index 000000000..6b3174eac --- /dev/null +++ b/src/test/tester.zig @@ -0,0 +1,159 @@ +const std = @import("std"); + +const string = []const u8; + +const RED = "\x1b[31;1m"; +const GREEN = "\x1b[32;1m"; +const CYAN = "\x1b[36;1m"; +const WHITE = "\x1b[37;1m"; +const DIM = "\x1b[2m"; +const RESET = "\x1b[0m"; + +pub const Tester = struct { + pass: std.ArrayList(Expectation), + fail: std.ArrayList(Expectation), + allocator: *std.mem.Allocator, + + pub fn t(allocator: *std.mem.Allocator) Tester { + return Tester{ + .allocator = allocator, + .pass = std.ArrayList(Expectation).init(allocator), + .fail = std.ArrayList(Expectation).init(allocator), + }; + } + + pub const Expectation = struct { + expected: string, + result: string, + source: std.builtin.SourceLocation, + + pub fn init(expected: string, result: string, src: std.builtin.SourceLocation) Expectation { + return Expectation{ + .expected = expected, + .result = result, + .source = src, + }; + } + const PADDING = 0; + pub fn print(self: *const @This()) void { + var pad = &([_]u8{' '} ** PADDING); + var stderr = std.io.getStdErr(); + + stderr.writeAll(RESET) catch unreachable; + stderr.writeAll(pad) catch unreachable; + stderr.writeAll(DIM) catch unreachable; + std.fmt.format(stderr.writer(), "{s}:{d}:{d}", .{ self.source.file, self.source.line, self.source.column }) catch unreachable; + stderr.writeAll(RESET) catch unreachable; + stderr.writeAll("\n") catch unreachable; + + stderr.writeAll(pad) catch unreachable; + stderr.writeAll("Expected: ") catch unreachable; + stderr.writeAll(RESET) catch unreachable; + stderr.writeAll(GREEN) catch unreachable; + std.fmt.format(stderr.writer(), "\"{s}\"", .{self.expected}) catch unreachable; + stderr.writeAll(GREEN) catch unreachable; + stderr.writeAll(RESET) catch unreachable; + + stderr.writeAll("\n") catch unreachable; + stderr.writeAll(pad) catch unreachable; + stderr.writeAll("Received: ") catch unreachable; + stderr.writeAll(RESET) catch unreachable; + stderr.writeAll(RED) catch unreachable; + std.fmt.format(stderr.writer(), "\"{s}\"", .{self.result}) catch unreachable; + stderr.writeAll(RED) catch unreachable; + stderr.writeAll(RESET) catch unreachable; + stderr.writeAll("\n") catch unreachable; + } + + pub fn evaluate_outcome(self: *const @This()) Outcome { + for (self.expected) |char, i| { + if (char != self.result[i]) { + return Outcome.fail; + } + } + + return Outcome.pass; + } + }; + + pub const Outcome = enum { + pass, + fail, + }; + + pub fn expect(tester: *Tester, expected: string, result: string, src: std.builtin.SourceLocation) callconv(.Inline) bool { + var expectation = Expectation.init(expected, result, src); + switch (expectation.evaluate_outcome()) { + .pass => { + tester.pass.append(expectation) catch unreachable; + return true; + }, + .fail => { + tester.fail.append(expectation) catch unreachable; + return false; + }, + } + } + + const ReportType = enum { + none, + pass, + fail, + some_fail, + + pub fn init(tester: *Tester) ReportType { + if (tester.fail.items.len == 0 and tester.pass.items.len == 0) { + return .none; + } else if (tester.fail.items.len == 0) { + return .pass; + } else if (tester.pass.items.len == 0) { + return .fail; + } else { + return .some_fail; + } + } + }; + + pub fn report(tester: *Tester, src: std.builtin.SourceLocation) void { + var stderr = std.io.getStdErr(); + + if (tester.fail.items.len > 0) { + std.fmt.format(stderr.writer(), "\n\n", .{}) catch unreachable; + } + + for (tester.fail.items) |item| { + item.print(); + std.fmt.format(stderr.writer(), "\n", .{}) catch unreachable; + } + + switch (ReportType.init(tester)) { + .none => { + std.log.info("No expectations.\n\n", .{}); + }, + .pass => { + std.fmt.format(stderr.writer(), "{s}All {d} expectations passed.{s}\n", .{ GREEN, tester.pass.items.len, GREEN }) catch unreachable; + std.fmt.format(stderr.writer(), RESET, .{}) catch unreachable; + std.testing.expect(true); + }, + .fail => { + std.fmt.format(stderr.writer(), "{s}All {d} expectations failed.{s}\n\n", .{ RED, tester.fail.items.len, RED }) catch unreachable; + std.fmt.format(stderr.writer(), RESET, .{}) catch unreachable; + std.testing.expect(false); + }, + .some_fail => { + std.fmt.format(stderr.writer(), "{s}{d} failed{s} and {s}{d} passed{s} of {d} expectations{s}\n\n", .{ + RED, + tester.fail.items.len, + RED ++ RESET, + GREEN, + tester.pass.items.len, + GREEN ++ RESET, + tester.fail.items.len + tester.pass.items.len, + RESET, + }) catch unreachable; + std.fmt.format(stderr.writer(), RESET, .{}) catch unreachable; + std.testing.expect(false); + }, + } + } +}; |