From db385a43d322c9d6a9c2b661fb16caac60a120d5 Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Sat, 11 Jun 2022 21:48:11 -0600 Subject: [PATCH] tests: garbage collection (gc) Tests the gc function with all of it's variants --- docs.md | 4 ++++ src/ziglua.zig | 56 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/docs.md b/docs.md index b2b420c..e91d449 100644 --- a/docs.md +++ b/docs.md @@ -76,6 +76,10 @@ All functions and types that deal with continuations have been renamed. For exam In general, just replace the "k" with the word "cont". This is just to make the API more clear and Zig-like. +### `lua_error` and `luaL_error` + +Because `error` is a reserved word in Zig, these functions have been renamed to `raiseError` and `raiseErrorAux` respectively. + ### `lua_tostring` and `lua_tolstring` These functions have been combined into `Lua.toString()`. The function `lua_tostring` is a macro around `lua_tolstring` and does not return the length of the string. diff --git a/src/ziglua.zig b/src/ziglua.zig index 64759fd..1d274b0 100644 --- a/src/ziglua.zig +++ b/src/ziglua.zig @@ -90,8 +90,8 @@ pub const GCAction = enum(u5) { countb = c.LUA_GCCOUNTB, step = c.LUA_GCSTEP, is_running = c.LUA_GCISRUNNING, - inc = c.LUA_GCINC, - gen = c.LUA_GCGEN, + set_incremental = c.LUA_GCINC, + set_generational = c.LUA_GCGEN, }; /// Type for debugging hook functions @@ -393,11 +393,37 @@ pub const Lua = struct { unreachable; } + fn TypeOfGC(comptime action: GCAction) type { + return switch (action) { + .stop, .collect, .restart, .step => void, + .count, .countb => i32, + .is_running, .set_incremental, .set_generational => bool, + }; + } + /// Controls the garbage collector - /// The purpose of the return value is dependent on the given action - /// TODO: perhaps `action` could be comptime known to enforce specific return types - pub fn gc(lua: *Lua, action: GCAction, args: anytype) i32 { - return @call(.{}, c.lua_gc, .{ lua.state, @enumToInt(action) } ++ args); + /// The return value type is dependent on the given action + pub fn gc(lua: *Lua, comptime action: GCAction, args: anytype) TypeOfGC(action) { + const val = @enumToInt(action); + switch (action) { + .stop, .collect, .restart => _ = c.lua_gc(lua.state, val), + .step => _ = c.lua_gc(lua.state, val, @as(i32, args.@"0")), + .count, .countb => return c.lua_gc(lua.state, val), + .is_running => return c.lua_gc(lua.state, val) != 0, + .set_incremental => return c.lua_gc( + lua.state, + val, + @as(i32, args.@"0"), + @as(i32, args.@"1"), + @as(i32, args.@"2"), + ) != @enumToInt(GCAction.set_incremental), + .set_generational => return c.lua_gc( + lua.state, + val, + @as(i32, args.@"0"), + @as(i32, args.@"1"), + ) != @enumToInt(GCAction.set_generational), + } } /// Returns the memory allocation function of a given state @@ -2267,6 +2293,24 @@ test "concat" { try expectEqualStrings("hello 10.0 wow!", lua.toString(-1).?); } +test "garbage collector" { + var lua = try Lua.init(testing.allocator); + defer lua.deinit(); + + // because the garbage collector is an opaque, unmanaged + // thing, it is hard to test, so just run each function + lua.gc(.stop, .{}); + lua.gc(.collect, .{}); + lua.gc(.restart, .{}); + lua.gc(.step, .{10}); + _ = lua.gc(.count, .{}); + _ = lua.gc(.countb, .{}); + _ = lua.gc(.is_running, .{}); + try expect(lua.gc(.set_generational, .{0, 10})); + try expect(lua.gc(.set_incremental, .{0, 0, 0})); + try expect(!lua.gc(.set_incremental, .{0, 0, 0})); +} + test "refs" { // temporary test that includes a reference to all functions so // they will be type-checked