Skip to content

Commit 7e50803

Browse files
committed
tests: finish main library tests!
The main Lua API library is tested! The tests are very surface level, but do provide a measure of security against changes now.
1 parent 07580a1 commit 7e50803

File tree

3 files changed

+106
-14
lines changed

3 files changed

+106
-14
lines changed

build.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const LibExeObjStep = std.build.LibExeObjStep;
66
pub fn build(b: *Builder) void {
77
const mode = b.standardReleaseOptions();
88

9-
const tests = b.addTest("src/ziglua.zig");
9+
const tests = b.addTest("src/tests.zig");
1010
link(b, tests, .{ .use_apicheck = true });
1111
tests.setBuildMode(mode);
1212

src/tests.zig

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -886,18 +886,100 @@ test "registry" {
886886
try expectEqualStrings("hello there", lua.toString(-1).?);
887887
}
888888

889+
test "closing vars" {
890+
var lua = try Lua.init(testing.allocator);
891+
defer lua.deinit();
892+
893+
lua.open(.{ .base = true });
894+
895+
// do setup in Lua for ease
896+
try lua.doString(
897+
\\closed_vars = 0
898+
\\mt = { __close = function() closed_vars = closed_vars + 1 end }
899+
);
900+
901+
lua.newTable();
902+
_ = lua.getGlobal("mt");
903+
lua.setMetatable(-2);
904+
lua.toClose(-1);
905+
lua.closeSlot(-1);
906+
lua.pop(1);
907+
908+
lua.newTable();
909+
_ = lua.getGlobal("mt");
910+
lua.setMetatable(-2);
911+
lua.toClose(-1);
912+
lua.closeSlot(-1);
913+
lua.pop(1);
914+
915+
// this should have incremented "closed_vars" to 2
916+
_ = lua.getGlobal("closed_vars");
917+
try expectEqual(@as(Number, 2), lua.toNumber(-1));
918+
}
919+
920+
test "raise error" {
921+
var lua = try Lua.init(testing.allocator);
922+
defer lua.deinit();
923+
924+
const makeError = struct {
925+
fn inner(l: *Lua) i32 {
926+
_ = l.pushString("makeError made an error");
927+
l.raiseError();
928+
return 0;
929+
}
930+
}.inner;
931+
932+
lua.pushCFunction(ziglua.wrap(makeError));
933+
try expectError(Error.Runtime, lua.protectedCall(0, 0, 0));
934+
try expectEqualStrings("makeError made an error", lua.toString(-1).?);
935+
}
936+
937+
fn continuation(l: *Lua, status: Lua.StatusType, ctx: isize) i32 {
938+
_ = status;
939+
940+
if (ctx == 5) {
941+
_ = l.pushString("done");
942+
return 1;
943+
} else {
944+
// yield the current context value
945+
l.pushInteger(ctx);
946+
return l.yieldCont(1, ctx + 1, ziglua.wrap(continuation));
947+
}
948+
}
949+
950+
test "yielding" {
951+
var lua = try Lua.init(testing.allocator);
952+
defer lua.deinit();
953+
954+
// here we create some zig functions that will run 5 times, continutally
955+
// yielding a count until it finally returns the string "done"
956+
const willYield = struct {
957+
fn inner(l: *Lua) i32 {
958+
return continuation(l, .ok, 0);
959+
}
960+
}.inner;
961+
962+
var thread = lua.newThread();
963+
thread.pushCFunction(ziglua.wrap(willYield));
964+
965+
try expect(!lua.isYieldable());
966+
try expect(thread.isYieldable());
967+
968+
var results: i32 = undefined;
969+
var i: i32 = 0;
970+
while (i < 5) : (i += 1) {
971+
try expectEqual(Lua.ResumeStatus.yield, try thread.resumeThread(lua, 0, &results));
972+
try expectEqual(@as(Integer, i), thread.toInteger(-1));
973+
thread.pop(results);
974+
}
975+
try expectEqual(Lua.ResumeStatus.ok, try thread.resumeThread(lua, 0, &results));
976+
try expectEqualStrings("done", thread.toString(-1).?);
977+
}
978+
889979
test "refs" {
890980
// temporary test that includes a reference to all functions so
891981
// they will be type-checked
892982

893-
// stdlib
894-
_ = Lua.closeSlot;
895-
_ = Lua.raiseError;
896-
_ = Lua.isYieldable;
897-
_ = Lua.toClose;
898-
_ = Lua.yield;
899-
_ = Lua.yieldCont;
900-
901983
// debug
902984
_ = Lua.getHook;
903985
_ = Lua.getHookCount;

src/ziglua.zig

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -818,11 +818,21 @@ pub const Lua = struct {
818818
if (c.lua_resetthread(lua.state) != Status.ok) return Error.Fail;
819819
}
820820

821+
pub const ResumeStatus = enum(u1) {
822+
ok = Status.ok,
823+
yield = Status.yield,
824+
};
825+
821826
/// Starts and resumes a coroutine in the given thread
822-
/// TODO: look into possible errors returned
823-
pub fn resumeThread(lua: *Lua, from: ?Lua, num_args: i32, num_results: *i32) i32 {
827+
pub fn resumeThread(lua: *Lua, from: ?Lua, num_args: i32, num_results: *i32) !ResumeStatus {
824828
const from_state = if (from) |from_val| from_val.state else null;
825-
return c.lua_resume(lua.state, from_state, num_args, num_results);
829+
const thread_status = c.lua_resume(lua.state, from_state, num_args, num_results);
830+
switch (thread_status) {
831+
Status.err_runtime => return Error.Runtime,
832+
Status.err_memory => return Error.Memory,
833+
Status.err_error => return Error.MsgHandler,
834+
else => return @intToEnum(ResumeStatus, thread_status),
835+
}
826836
}
827837

828838
/// Rotates the stack elements between the valid `index` and the top of the stack
@@ -1664,7 +1674,7 @@ pub inline fn opaqueCast(comptime T: type, ptr: *anyopaque) *T {
16641674

16651675
pub const ZigFn = fn (lua: *Lua) i32;
16661676
pub const ZigHookFn = fn (lua: *Lua, ar: *DebugInfo) void;
1667-
pub const ZigContFn = fn (lua: *Lua, status: bool, ctx: KContext) c_int;
1677+
pub const ZigContFn = fn (lua: *Lua, status: Lua.StatusType, ctx: KContext) i32;
16681678
pub const ZigReaderFn = fn (lua: *Lua, data: *anyopaque) ?[]const u8;
16691679
pub const ZigWarnFn = fn (data: ?*anyopaque, msg: []const u8, to_cont: bool) void;
16701680
pub const ZigWriterFn = fn (lua: *Lua, buf: []const u8, data: *anyopaque) bool;
@@ -1729,7 +1739,7 @@ fn wrapZigContFn(comptime f: ZigContFn) CContFn {
17291739
fn inner(state: ?*LuaState, status: c_int, ctx: KContext) callconv(.C) c_int {
17301740
// this is called by Lua, state should never be null
17311741
var lua: Lua = .{ .state = state.? };
1732-
return @call(.{ .modifier = .always_inline }, f, .{ &lua, status != 0, ctx });
1742+
return @call(.{ .modifier = .always_inline }, f, .{ &lua, @intToEnum(Lua.StatusType, status), ctx });
17331743
}
17341744
}.inner;
17351745
}

0 commit comments

Comments
 (0)