From 99a08b82556f29d3b12e80f5990aac6fc76a5fe3 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Thu, 25 May 2017 15:45:37 +0200 Subject: ltests.js: makeCfunc --- tests/test-suite/inprogress/coroutine.js | 151 ++++++++++++++++++++++++++++++- tests/test-suite/ltests.js | 17 +++- 2 files changed, 164 insertions(+), 4 deletions(-) diff --git a/tests/test-suite/inprogress/coroutine.js b/tests/test-suite/inprogress/coroutine.js index 2aece7d..2d25fb5 100644 --- a/tests/test-suite/inprogress/coroutine.js +++ b/tests/test-suite/inprogress/coroutine.js @@ -1348,5 +1348,154 @@ test("[test-suite] coroutine: using a main thread as a coroutine", function (t) test("[test-suite] coroutine: tests for coroutine API", { skip: true }, function (t) { - t.comment("TODO"); + let luaCode = ` + local function apico (...) + local x = {...} + return coroutine.wrap(function () + return T.testC(table.unpack(x)) + end) + end + + local a = {apico( + [[ + pushstring errorcode + pcallk 1 0 2; + invalid command (should not arrive here) + ]], + [[return *]], + "stackmark", + error + )()} + assert(#a == 4 and + a[3] == "stackmark" and + a[4] == "errorcode" and + _G.status == "ERRRUN" and + _G.ctx == 2) -- 'ctx' to pcallk + + local co = apico( + "pushvalue 2; pushnum 10; pcallk 1 2 3; invalid command;", + coroutine.yield, + "getglobal status; getglobal ctx; pushvalue 2; pushstring a; pcallk 1 0 4; invalid command", + "getglobal status; getglobal ctx; return *") + + assert(co() == 10) + assert(co(20, 30) == 'a') + a = {co()} + assert(#a == 10 and + a[2] == coroutine.yield and + a[5] == 20 and a[6] == 30 and + a[7] == "YIELD" and a[8] == 3 and + a[9] == "YIELD" and a[10] == 4) + assert(not pcall(co)) -- coroutine is dead now + `, L; + + t.plan(2); + + t.doesNotThrow(function () { + + L = lauxlib.luaL_newstate(); + + lualib.luaL_openlibs(L); + + ltests.luaopen_tests(L); + + lauxlib.luaL_loadstring(L, lua.to_luastring(luaCode)); + + }, "Lua program loaded without error"); + + t.doesNotThrow(function () { + + lua.lua_call(L, 0, -1); + + }, "Lua program ran without error"); +}); + + +test("[test-suite] coroutine: tests for coroutine API", { skip: true }, function (t) { + let luaCode = ` + f = T.makeCfunc("pushnum 3; pushnum 5; yield 1;") + co = coroutine.wrap(function () + assert(f() == 23); assert(f() == 23); return 10 + end) + assert(co(23,16) == 5) + assert(co(23,16) == 5) + assert(co(23,16) == 10) + `, L; + + t.plan(2); + + t.doesNotThrow(function () { + + L = lauxlib.luaL_newstate(); + + lualib.luaL_openlibs(L); + + ltests.luaopen_tests(L); + + lauxlib.luaL_loadstring(L, lua.to_luastring(luaCode)); + + }, "Lua program loaded without error"); + + t.doesNotThrow(function () { + + lua.lua_call(L, 0, -1); + + }, "Lua program ran without error"); +}); + + +test("[test-suite] coroutine: testing coroutines with C bodies", { skip: true }, function (t) { + let luaCode = ` + local function eqtab (t1, t2) + assert(#t1 == #t2) + for i = 1, #t1 do + local v = t1[i] + assert(t2[i] == v) + end + end + + f = T.makeCfunc([[ + pushnum 102 + yieldk 1 U2 + cannot be here! + ]], + [[ # continuation + pushvalue U3 # accessing upvalues inside a continuation + pushvalue U4 + return * + ]], 23, "huu") + + x = coroutine.wrap(f) + assert(x() == 102) + eqtab({x()}, {23, "huu"}) + + + f = T.makeCfunc[[pushstring 'a'; pushnum 102; yield 2; ]] + + a, b, c, d = T.testC([[newthread; pushvalue 2; xmove 0 3 1; resume 3 0; + pushstatus; xmove 3 0 0; resume 3 0; pushstatus; + return 4; ]], f) + + assert(a == 'YIELD' and b == 'a' and c == 102 and d == 'OK') + `, L; + + t.plan(2); + + t.doesNotThrow(function () { + + L = lauxlib.luaL_newstate(); + + lualib.luaL_openlibs(L); + + ltests.luaopen_tests(L); + + lauxlib.luaL_loadstring(L, lua.to_luastring(luaCode)); + + }, "Lua program loaded without error"); + + t.doesNotThrow(function () { + + lua.lua_call(L, 0, -1); + + }, "Lua program ran without error"); }); diff --git a/tests/test-suite/ltests.js b/tests/test-suite/ltests.js index 225e8f7..b6ffc4f 100644 --- a/tests/test-suite/ltests.js +++ b/tests/test-suite/ltests.js @@ -492,12 +492,22 @@ const sethook = function(L) { return 0; }; +const Cfunc = function(L) { + return runJS(L, L, { script: lua.lua_tostring(L, lua.lua_upvalueindex(1)), offset: 0 }); +}; + const Cfunck = function(L, status, ctx) { pushcode(L, status); - lua.lua_setglobal(L, "status"); + lua.lua_setglobal(L, lua.to_luastring("status", true)); lua.lua_pushinteger(L, ctx); - lua.lua_setglobal(L, "ctx"); - return runJS(L, L, lua.lua_tostring(L, ctx)); + lua.lua_setglobal(L, lua.to_luastring("ctx", true)); + return runJS(L, L, { script: lua.lua_tostring(L, ctx), offset: 0 }); +}; + +const makeCfunc = function(L) { + lauxlib.luaL_checkstring(L, 1); + lua.lua_pushcclosure(L, Cfunc, lua.lua_gettop(L)); + return 1; }; const coresume = function(L) { @@ -520,6 +530,7 @@ const tests_funcs = { "closestate": closestate, "doremote": doremote, "loadlib": loadlib, + "makeCfunc": makeCfunc, "newstate": newstate, "newuserdata": newuserdata, "resume": coresume, -- cgit v1.2.3-70-g09d2