Skip to content

Commit a027e21

Browse files
committed
tests: add dump and load test
1 parent 196d7c7 commit a027e21

File tree

1 file changed

+71
-26
lines changed

1 file changed

+71
-26
lines changed

src/ziglua.zig

Lines changed: 71 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,9 @@ pub const Lua = struct {
382382
}
383383

384384
/// Dumps a function as a binary chunk
385-
pub fn dump(lua: *Lua, writer: CWriterFn, data: *anyopaque, strip: bool) i32 {
386-
return c.lua_dump(lua.state, writer, data, @boolToInt(strip));
385+
/// Returns an error if writing was unsuccessful
386+
pub fn dump(lua: *Lua, writer: CWriterFn, data: *anyopaque, strip: bool) !void {
387+
if (c.lua_dump(lua.state, writer, data, @boolToInt(strip)) != 0) return Error.Fail;
387388
}
388389

389390
/// Raises a Lua error using the value at the top of the stack as the error object
@@ -446,6 +447,7 @@ pub const Lua = struct {
446447
}
447448

448449
/// Pushes onto the stack the value of the global `name`. Returns the type of that value
450+
/// NOTE: could return an error if it was successful (not nil)
449451
pub fn getGlobal(lua: *Lua, name: [:0]const u8) LuaType {
450452
return @intToEnum(LuaType, c.lua_getglobal(lua.state, name));
451453
}
@@ -564,23 +566,21 @@ pub const Lua = struct {
564566
}
565567

566568
/// Loads a Lua chunk without running it
567-
pub fn load(lua: *Lua, reader: CReaderFn, data: *anyopaque, chunk_name: [:0]const u8, mode: ?Mode) !void {
568-
const mode_str = blk: {
569-
if (mode == null) break :blk "bt";
570-
571-
break :blk switch (mode.?) {
572-
.binary => "b",
573-
.text => "t",
574-
.binary_text => "bt",
575-
};
569+
pub fn load(lua: *Lua, reader: CReaderFn, data: *anyopaque, chunk_name: [:0]const u8, mode: Mode) !void {
570+
const mode_str = switch (mode) {
571+
.binary => "b",
572+
.text => "t",
573+
.binary_text => "bt",
576574
};
577575
const ret = c.lua_load(lua.state, reader, data, chunk_name, mode_str);
578576
switch (ret) {
579577
Status.ok => return,
580578
Status.err_syntax => return Error.Syntax,
581579
Status.err_memory => return Error.Memory,
582-
// NOTE: the docs mention possible other return types, but I couldn't figure them out
583-
else => panic("load returned an unexpected status: `{d}`", .{ret}),
580+
// can also return any result of a pcall error
581+
Status.err_runtime => return Error.Runtime,
582+
Status.err_error => return Error.MsgHandler,
583+
else => unreachable,
584584
}
585585
}
586586

@@ -810,9 +810,9 @@ pub const Lua = struct {
810810
}
811811

812812
/// Resets a thread, cleaning its call stack and closing all pending to-be-closed variables
813-
/// TODO: look into possible errors
814-
pub fn resetThread(lua: *Lua) i32 {
815-
return c.lua_resetthread(lua.state);
813+
/// Returns an error if an error occured and leaves an error object on top of the stack
814+
pub fn resetThread(lua: *Lua) !void {
815+
if (c.lua_resetthread(lua.state) != Status.ok) return Error.Fail;
816816
}
817817

818818
/// Starts and resumes a coroutine in the given thread
@@ -1728,7 +1728,7 @@ fn wrapZigReaderFn(comptime f: ZigReaderFn) CReaderFn {
17281728
var lua: Lua = .{ .state = state.? };
17291729
if (@call(.{ .modifier = .always_inline }, f, .{ &lua, data.? })) |buffer| {
17301730
size.* = buffer.len;
1731-
return buffer;
1731+
return buffer.ptr;
17321732
} else {
17331733
size.* = 0;
17341734
return null;
@@ -1751,15 +1751,14 @@ fn wrapZigWarnFn(comptime f: ZigWarnFn) CWarnFn {
17511751
/// Wrap a ZigWriterFn in a CWriterFn for passing to the API
17521752
fn wrapZigWriterFn(comptime f: ZigWriterFn) CWriterFn {
17531753
return struct {
1754-
fn inner(state: ?*LuaState, buf: ?*anyopaque, size: usize, data: ?*anyopaque) callconv(.C) c_int {
1754+
fn inner(state: ?*LuaState, buf: ?*const anyopaque, size: usize, data: ?*anyopaque) callconv(.C) c_int {
17551755
// this is called by Lua, state should never be null
17561756
var lua: Lua = .{ .state = state.? };
17571757
const buffer = @ptrCast([*]const u8, buf)[0..size];
1758-
return @boolToInt(@call(
1759-
.{ .modifier = .always_inline },
1760-
f,
1761-
.{ &lua, buffer, data.? },
1762-
));
1758+
const result = @call(.{ .modifier = .always_inline }, f, .{ &lua, buffer, data.? });
1759+
// it makes more sense for the inner writer function to return false for failure,
1760+
// so negate the result here
1761+
return @boolToInt(!result);
17631762
}
17641763
}.inner;
17651764
}
@@ -2414,24 +2413,70 @@ test "conversions" {
24142413
try expectEqual(@as(i32, 1), lua.absIndex(-2));
24152414
}
24162415

2416+
test "dump and load" {
2417+
var lua = try Lua.init(testing.allocator);
2418+
defer lua.deinit();
2419+
2420+
// store a function in a global
2421+
try lua.doString("f = function(x) return function(n) return n + x end end");
2422+
// put the function on the stack
2423+
_ = lua.getGlobal("f");
2424+
2425+
const writer = struct {
2426+
fn inner(l: *Lua, buf: []const u8, data: *anyopaque) bool {
2427+
_ = l;
2428+
var arr = @ptrCast(*std.ArrayList(u8), @alignCast(@alignOf(std.ArrayList(u8)), data));
2429+
arr.appendSlice(buf) catch return false;
2430+
return true;
2431+
}
2432+
}.inner;
2433+
2434+
var buffer = std.ArrayList(u8).init(testing.allocator);
2435+
defer buffer.deinit();
2436+
2437+
// save the function as a binary chunk in the buffer
2438+
try lua.dump(wrap(writer), &buffer, false);
2439+
2440+
// clear the stack
2441+
try lua.resetThread();
2442+
2443+
const reader = struct {
2444+
fn inner(l: *Lua, data: *anyopaque) ?[]const u8 {
2445+
_ = l;
2446+
var arr = @ptrCast(*std.ArrayList(u8), @alignCast(@alignOf(std.ArrayList(u8)), data));
2447+
return arr.items;
2448+
}
2449+
}.inner;
2450+
2451+
// now load the function back onto the stack
2452+
try lua.load(wrap(reader), &buffer, "function", .binary);
2453+
try expectEqual(LuaType.function, lua.typeOf(-1));
2454+
2455+
// run the function (creating a new function)
2456+
lua.pushInteger(5);
2457+
try lua.protectedCall(1, 1, 0);
2458+
2459+
// now call the new function (which should return the value + 5)
2460+
lua.pushInteger(6);
2461+
try lua.protectedCall(1, 1, 0);
2462+
try expectEqual(@as(Integer, 11), lua.toInteger(-1));
2463+
}
2464+
24172465
test "refs" {
24182466
// temporary test that includes a reference to all functions so
24192467
// they will be type-checked
24202468

24212469
// stdlib
24222470
_ = Lua.closeSlot;
2423-
_ = Lua.dump;
24242471
_ = Lua.raiseError;
24252472
_ = Lua.getIUserValue;
24262473
_ = Lua.isYieldable;
2427-
_ = Lua.load;
24282474
_ = Lua.newThread;
24292475
_ = Lua.newUserdataUV;
24302476
_ = Lua.next;
24312477
_ = Lua.rawGetP;
24322478
_ = Lua.rawSet;
24332479
_ = Lua.rawSetP;
2434-
_ = Lua.resetThread;
24352480
_ = Lua.setIUserValue;
24362481
_ = Lua.setMetatable;
24372482
_ = Lua.setTable;

0 commit comments

Comments
 (0)