Skip to content

Instantly share code, notes, and snippets.

@Jarred-Sumner
Created May 2, 2021 07:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jarred-Sumner/be47a4a01f473b00745660f26178c81b to your computer and use it in GitHub Desktop.
Save Jarred-Sumner/be47a4a01f473b00745660f26178c81b to your computer and use it in GitHub Desktop.
fn expectPrinted(t: *Tester, contents: string, expected: string, src: anytype) !void {
// ...
_ = t.expect(contents, copied, src);
}
test "test name" {
var t_ = Tester.t(std.heap.page_allocator);
var t = &t_;
try expectPrinted(t, "(-x) ** 2", "(-x) ** 2;\n", @src());
try expectPrinted(t, "(+x) ** 2", "(+x) ** 2;\n", @src());
try expectPrinted(t, "(~x) ** 2", "(~x) ** 2;\n", @src());
try expectPrinted(t, "(!x) ** 2", "(!x) ** 2;\n", @src());
try expectPrinted(t, "(-1) ** 2", "(-1) ** 2;\n", @src());
try expectPrinted(t, "(+1) ** 2", "1 ** 2;\n", @src());
try expectPrinted(t, "(~1) ** 2", "(~1) ** 2;\n", @src());
try expectPrinted(t, "(!1) ** 2", "false ** 2;\n", @src());
try expectPrinted(t, "(void x) ** 2", "(void x) ** 2;\n", @src());
try expectPrinted(t, "(delete x) ** 2", "(delete x) ** 2;\n", @src());
try expectPrinted(t, "(typeof x) ** 2", "(typeof x) ** 2;\n", @src());
try expectPrinted(t, "undefined ** 2", "(void 0) ** 2;\n", @src());
try expectPrinted(t, "class Foo { foo() {} }", "class Foo {\n foo() {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { *foo() {} }", "class Foo {\n *foo() {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { get foo() {} }", "class Foo {\n get foo() {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { set foo(x) {} }", "class Foo {\n set foo(x) {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { static foo() {} }", "class Foo {\n static foo() {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { static *foo() {} }", "class Foo {\n static *foo() {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { static get foo() {} }", "class Foo {\n static get foo() {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { static set foo(x) {} }", "class Foo {\n static set foo(x) {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { async foo() {} }", "class Foo {\n async foo() {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { static async foo() {} }", "class Foo {\n static async foo() {\n }\n}\n", @src());
try expectPrinted(t, "class Foo { static async *foo() {} }", "class Foo {\n static async *foo() {\n }\n}\n", @src());
try expectPrinted(t, "({foo})", "({foo});\n", @src());
try expectPrinted(t, "({foo:0})", "({foo: 0});\n", @src());
try expectPrinted(t, "({1e9:0})", "({1e9: 0});\n", @src());
try expectPrinted(t, "({1_2_3n:0})", "({123n: 0});\n", @src());
try expectPrinted(t, "({0x1_2_3n:0})", "({0x123n: 0});\n", @src());
try expectPrinted(t, "({foo() {}})", "({foo() {\n}});\n", @src());
try expectPrinted(t, "({*foo() {}})", "({*foo() {\n}});\n", @src());
try expectPrinted(t, "({get foo() {}})", "({get foo() {\n}});\n", @src());
try expectPrinted(t, "({set foo(x) {}})", "({set foo(x) {\n}});\n", @src());
try expectPrinted(t, "({if:0})", "({if: 0});\n", @src());
try expectPrinted(t, "({if() {}})", "({if() {\n}});\n", @src());
try expectPrinted(t, "({*if() {}})", "({*if() {\n}});\n", @src());
try expectPrinted(t, "({get if() {}})", "({get if() {\n}});\n", @src());
try expectPrinted(t, "({set if(x) {}})", "({set if(x) {\n}});\n", @src());
try expectPrinted(t, "await x", "await x;\n", @src());
try expectPrinted(t, "await +x", "await +x;\n", @src());
try expectPrinted(t, "await -x", "await -x;\n", @src());
try expectPrinted(t, "await ~x", "await ~x;\n", @src());
try expectPrinted(t, "await !x", "await !x;\n", @src());
try expectPrinted(t, "await --x", "await --x;\n", @src());
try expectPrinted(t, "await ++x", "await ++x;\n", @src());
try expectPrinted(t, "await x--", "await x--;\n", @src());
try expectPrinted(t, "await x++", "await x++;\n", @src());
try expectPrinted(t, "await void x", "await void x;\n", @src());
try expectPrinted(t, "await typeof x", "await typeof x;\n", @src());
try expectPrinted(t, "await (x * y)", "await (x * y);\n", @src());
try expectPrinted(t, "await (x ** y)", "await (x ** y);\n", @src());
t.report(@src());
}
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);
},
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment