Skip to content

Instantly share code, notes, and snippets.

@krichprollsch
Last active March 11, 2024 08:39
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 krichprollsch/455f9f7e6274c471b31b9bb11fc971e9 to your computer and use it in GitHub Desktop.
Save krichprollsch/455f9f7e6274c471b31b9bb11fc971e9 to your computer and use it in GitHub Desktop.
Zig root type comparison and tests

Something confuses me with the combination usage of @import("root") and builtin.test_functions in zig.

When I declare a root T class in the custom test runner here, the type comparison with the original Foo struct works in the main function, but doesn't work in a function run via builting.test_functions.

I reproduce the issue with Zig current master (0.12.0-dev.3193+4ba4f94c9).

$ zig build test
type comparison in main function        OK
root.test.type comparison in test function      FAIL
error: TestUnexpectedResult
/usr/local/zig/lib/std/testing.zig:540:14: 0x1033adf in expect (test)
    if (!ok) return error.TestUnexpectedResult;
             ^
/home/pierre/prs/learnzig/type-compare/src/root.zig:26:5: 0x1033bf5 in test.type comparison in test function (test)
    try std.testing.expect(Foo == Root_T); // doesn't work.
    ^
/home/pierre/prs/learnzig/type-compare/src/root.zig:19:13: 0x103437e in main (test)
            return err;
            ^
/home/pierre/prs/learnzig/type-compare/src/test_runner.zig:8:5: 0x1034d13 in main (test)
    try root.main();
    ^
test
└─ run test failure
const std = @import("std");
// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
// runner.
pub fn build(b: *std.Build) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const lib_unit_tests = b.addTest(.{
.root_source_file = .{ .path = "root.zig" },
.target = target,
.optimize = optimize,
.test_runner = "test_runner.zig",
});
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
// Similar to creating the run step earlier, this exposes a `test` step to
// the `zig build --help` menu, providing a way for the user to request
// running the unit tests.
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_lib_unit_tests.step);
}
const std = @import("std");
const builtin = @import("builtin");
const testing = std.testing;
pub const Foo = struct {};
pub const Root_T = @import("root").T;
pub fn main() !void {
std.debug.print("type comparison in main function\t", .{});
try std.testing.expect(Foo == Root_T); // works correctly.
std.debug.print("OK\n", .{});
// run tests functions by using builtin.test_functions.
for (builtin.test_functions) |test_fn| {
std.debug.print("{s}\t", .{test_fn.name});
test_fn.func() catch |err| {
std.debug.print("FAIL\n", .{});
return err;
};
std.debug.print("\tOK\n", .{});
}
}
test "type comparison in test function" {
try std.testing.expect(Foo == Root_T); // doesn't work.
}
const std = @import("std");
const root = @import("root.zig");
pub const T = root.Foo;
pub fn main() !void {
try root.main();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment