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;
}
const strings = @import("../string_immutable.zig");
pub fn evaluate_outcome(self: *const @This()) Outcome {
if (strings.eql(self.expected, self.result)) {
return .pass;
} else {
return .fail;
}
}
};
pub const Outcome = enum {
pass,
fail,
};
pub inline fn expect(tester: *Tester, expected: string, result: string, src: std.builtin.SourceLocation) 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) catch std.debug.panic("Test failure", .{});
},
.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) catch std.debug.panic("Test failure", .{});
},
.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) catch std.debug.panic("Test failure in {s}: {s}:{d}:{d}", .{ src.fn_name, src.file, src.line, src.column });
},
}
}
};
ogenerated-tsconfig
Unnamed repository; edit this file 'description' to name the repository. | |