tests(Clip): added explicit interface checking

This commit is contained in:
Grace Yoder 2026-06-24 17:48:16 -06:00
parent 47f2491ae0
commit ecdcf0c0b8
Signed by: grace
SSH key fingerprint: SHA256:oG9v0ZlohsoMAg083HAwBGOcaPLF3nIuOlAW4MtASMo
2 changed files with 42 additions and 0 deletions

View file

@ -14,6 +14,19 @@ pub fn build(b: *std.Build) void {
b.installArtifact(exe);
const tests = b.addTest(.{
.name = "tpb",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});
const test_step = b.step("test", "Run tests");
const run_tests = b.addRunArtifact(tests);
test_step.dependOn(&run_tests.step);
const run_step = b.step("run", "Run the app");
const run_cmd = b.addRunArtifact(exe);

View file

@ -1 +1,30 @@
pub const OSC52 = @import("Clip/OSC52.zig");
// I am not sure if this is super idiomatic Zig or if this is bad practice, but
// by ensuring that all Clip backends implement the same methods, we are able
// to use the `anytype` type and we are able to have an interface that is able
// to dispatch statically
/// Check if a function with the given name and type exists.
/// `@compileError` if not
fn assertFn(comptime T: type, comptime name: []const u8, comptime Sig: type) void {
if (!@import("std").meta.hasFn(T, name))
@compileError(@typeName(T) ++ " missing fn " ++ name);
if (@TypeOf(@field(T, name)) != Sig)
@compileError(@typeName(T) ++ "." ++ name ++ " must be " ++ @typeName(Sig));
}
test {
inline for (@typeInfo(@This()).@"struct".decls) |decl| {
// Only grab types of structs
const T = @field(@This(), decl.name);
if (@TypeOf(T) != type) continue;
if (@typeInfo(T) != .@"struct") continue;
// ==============================
// === Interface Requirements ===
// ==============================
assertFn(T, "writeCopyBuffer", fn (*T, []const u8) anyerror!void);
assertFn(T, "writePasteboard", fn (*T) anyerror!void);
}
}