Running tests with my own wrapper?

Just before running a compiled “zig test” binary (i.e. the one that gets compiled with zig test), I need to “prepare the binary”:

sudo setcap cap_net_admin=+ep /path/to/that/binary

That way it has enough permissions to run it’s tests. Do I have any options with zig build? A command-line option that would allow me invoke the wrapper. Wrapper pseudocode:

#!/bin/sh
sudo setcap cap_net_admin=+ep $1
exec "$@"

Things I have tried:

  • adding a setExecCmd. It almost makes it work: --test-cmd gets appended to the zig test command line. However, that command is not invoked when --listen=- is passed to the test runner (I am unsure why).
  • creating my test_runner: started poking around, but immediately seems like overkill/wrong direction.

Any more ideas?

Appendix

Current workaround:

zig build test --verbose |& awk '/\/test --listen=-/{print $1; exit 1}' | xargs  -I{} sh -c "sudo setcap cap_net_admin=+ep {} && {}"

Hello @motiejus
welcome to ziggit :slight_smile:

zig test command line accepts the following options:

-femit-bin[=path]  Specifies the path and name of the output binary
--test-no-exec     Compiles test binary without running it

You can call:

zig test src/lib.zig -femit-bin=zig-out/bin/tester --test-no-exec
sudo setcap cap_net_admin=+ep zig-out/bin/tester
zig-out/bin/tester

For build.zig you can execute a command that depends on addTest and make addRunArtifact depends on that command execution step.

The initial build.zig:

    const unit_tests = b.addTest(.{
        .root_source_file = b.path("src/lib.zig"),
        .target = target,
        .optimize = optimize,
    });
    const run_unit_tests = b.addRunArtifact(unit_tests);

becomes:

    const unit_tests = b.addTest(.{
        .root_source_file = b.path("src/lib.zig"),
        .target = target,
        .optimize = optimize,
    });

    // command that runs setcap
    const set_cap = b.addSystemCommand(&.{
        "setcap",
        "cap_net_admin=+ep",
    });
    set_cap.addArtifactArg(unit_tests);

    const run_unit_tests = b.addRunArtifact(unit_tests);

    // tester run, depends on set_cap command
    run_unit_tests.step.dependsOn(&set_cap.step);
3 Likes