Skip to content

Instantly share code, notes, and snippets.

@mikdusan
Last active January 17, 2021 13:27
Show Gist options
  • Save mikdusan/a4621852b4a13bf69fb0f28e49c32ec6 to your computer and use it in GitHub Desktop.
Save mikdusan/a4621852b4a13bf69fb0f28e49c32ec6 to your computer and use it in GitHub Desktop.
raw test harness
const std = @import("std");
const tester = @import("tester.zig");
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = &arena.allocator;
var tests = tester.TestList.init(allocator);
try tester.addTestsSource("foo_single.zig", &tests);
try tester.addTestsSource("foo_many.zig", &tests);
std.debug.warn("tests to run: {d}\n", .{tests.items.len});
for (tests.items) |t,i| {
std.debug.warn("\nrunning test {d} of {d}: {s}\n", .{ i, tests.items.len, t.name });
// new environment for each test
var env: tester.TestEnv = .{};
t.function(env) catch |err| {
std.debug.warn("tested failed: {s}\n", .{err});
};
}
}
const std = @import("std");
const tester = @import("tester.zig");
pub fn one(env: tester.TestEnv) !void {
std.debug.warn("from foo_many.zig -- one\n", .{});
}
pub fn two(env: tester.TestEnv) !void {
std.debug.warn("from foo_many.zig -- two\n", .{});
}
pub fn three(env: tester.TestEnv) !void {
std.debug.warn("from foo_many.zig -- three\n", .{});
}
const std = @import("std");
const tester = @import("tester.zig");
pub fn one(env: tester.TestEnv) !void {
std.debug.warn("from foo_single.zig -- one\n", .{});
}
const std = @import("std");
pub const TestEnv = struct {
// TODO
};
// represents each test function
pub const Test = struct {
function: TestFunction,
name: []const u8,
};
pub const TestFunction = fn (env: TestEnv) anyerror!void;
pub const TestFunctionArgs = std.meta.ArgsTuple(TestFunction);
pub const TestList = std.ArrayList(Test);
pub fn addTestsSource(comptime source: []const u8, tests: *TestList) !void {
try addTestsNamespace(@import(source), tests);
}
pub fn addTestsNamespace(comptime namespace: type, tests: *TestList) !void {
inline for (std.meta.declarations(namespace)) |decl| {
if (decl.data == .Fn) {
// filter for exact function signature
// assume test functions are the only functions in universe that will ever
// be found matching TestFunction signature
if (comptime eqlArgsTuple(TestFunctionArgs, std.meta.ArgsTuple(decl.data.Fn.fn_type))) {
try tests.append(.{ .function = @field(namespace, decl.name), .name = @typeName(namespace) ++ "." ++ decl.name });
}
}
}
}
fn eqlArgsTuple(comptime A: anytype, comptime B: anytype) bool {
const a_info = @typeInfo(A);
const a_fields = std.meta.fields(A);
const b_info = @typeInfo(B);
const b_fields = std.meta.fields(B);
if (a_fields.len != b_fields.len) return false;
inline for (a_fields) |f,i| {
if (f.field_type != b_fields[i].field_type) return false;
}
return true;
}
@mikdusan
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment