aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--tests/test-suite/coroutine.js (renamed from tests/test-suite/inprogress/coroutine.js)179
2 files changed, 173 insertions, 8 deletions
diff --git a/README.md b/README.md
index b4c281a..0f693d8 100644
--- a/README.md
+++ b/README.md
@@ -57,6 +57,7 @@
- [x] `calls.lua` (32/32)
- [x] `closure.lua` (16/16)
- [x] `constructs.lua` (`_soft`) (10/10)
+ - [x] `coroutine.lua` (70/70)
- [x] `errors.lua` (64/64)
- [x] `events.lua` (26/26)
- [x] `goto.lua` (18/18)
@@ -67,7 +68,6 @@
- [x] `sort.lua` (24/24)
- [x] `strings.lua` (34/34)
- [x] `vararg.lua` (8/8)
- - [ ] `coroutine.lua` (32/40)
- [ ] `pm.lua` (27/38)
- [ ] `tpack.lua` (20/32)
- [ ] `utf8.lua` (14/20)
diff --git a/tests/test-suite/inprogress/coroutine.js b/tests/test-suite/coroutine.js
index 2d25fb5..82f10a3 100644
--- a/tests/test-suite/inprogress/coroutine.js
+++ b/tests/test-suite/coroutine.js
@@ -4,11 +4,11 @@ const test = require('tape');
global.WEB = false;
-const lua = require('../../../src/lua.js');
-const lauxlib = require('../../../src/lauxlib.js');
-const lualib = require('../../../src/lualib.js');
+const lua = require('../../src/lua.js');
+const lauxlib = require('../../src/lauxlib.js');
+const lualib = require('../../src/lualib.js');
-const ltests = require('../ltests.js');
+const ltests = require('./ltests.js');
const prefix = `
mt = {
@@ -1347,7 +1347,7 @@ 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) {
+test("[test-suite] coroutine: tests for coroutine API", function (t) {
let luaCode = `
local function apico (...)
local x = {...}
@@ -1411,7 +1411,7 @@ test("[test-suite] coroutine: tests for coroutine API", { skip: true }, function
});
-test("[test-suite] coroutine: tests for coroutine API", { skip: true }, function (t) {
+test("[test-suite] coroutine: tests for coroutine API", function (t) {
let luaCode = `
f = T.makeCfunc("pushnum 3; pushnum 5; yield 1;")
co = coroutine.wrap(function ()
@@ -1444,7 +1444,7 @@ test("[test-suite] coroutine: tests for coroutine API", { skip: true }, function
});
-test("[test-suite] coroutine: testing coroutines with C bodies", { skip: true }, function (t) {
+test("[test-suite] coroutine: testing coroutines with C bodies", function (t) {
let luaCode = `
local function eqtab (t1, t2)
assert(#t1 == #t2)
@@ -1499,3 +1499,168 @@ test("[test-suite] coroutine: testing coroutines with C bodies", { skip: true },
}, "Lua program ran without error");
});
+
+
+test("[test-suite] coroutine: testing chain of suspendable C calls", function (t) {
+ let luaCode = `
+ local count = 3 -- number of levels
+
+ f = T.makeCfunc([[
+ remove 1; # remove argument
+ pushvalue U3; # get selection function
+ call 0 1; # call it (result is 'f' or 'yield')
+ pushstring hello # single argument for selected function
+ pushupvalueindex 2; # index of continuation program
+ callk 1 -1 .; # call selected function
+ errorerror # should never arrive here
+ ]],
+ [[
+ # continuation program
+ pushnum 34 # return value
+ return * # return all results
+ ]],
+ function () -- selection function
+ count = count - 1
+ if count == 0 then return coroutine.yield
+ else return f
+ end
+ end
+ )
+
+ co = coroutine.wrap(function () return f(nil) end)
+ assert(co() == "hello") -- argument to 'yield'
+ a = {co()}
+ -- three '34's (one from each pending C call)
+ assert(#a == 3 and a[1] == a[2] and a[2] == a[3] and a[3] == 34)
+ `, 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 yields with continuations", function (t) {
+ let luaCode = `
+ co = coroutine.wrap(function (...) return
+ T.testC([[ # initial function
+ yieldk 1 2
+ cannot be here!
+ ]],
+ [[ # 1st continuation
+ yieldk 0 3
+ cannot be here!
+ ]],
+ [[ # 2nd continuation
+ yieldk 0 4
+ cannot be here!
+ ]],
+ [[ # 3th continuation
+ pushvalue 6 # function which is last arg. to 'testC' here
+ pushnum 10; pushnum 20;
+ pcall 2 0 0 # call should throw an error and return to next line
+ pop 1 # remove error message
+ pushvalue 6
+ getglobal status; getglobal ctx
+ pcallk 2 2 5 # call should throw an error and jump to continuation
+ cannot be here!
+ ]],
+ [[ # 4th (and last) continuation
+ return *
+ ]],
+ -- function called by 3th continuation
+ function (a,b) x=a; y=b; error("errmsg") end,
+ ...
+ )
+ end)
+
+ local a = {co(3,4,6)}
+ assert(a[1] == 6 and a[2] == nil)
+ a = {co()}; assert(a[1] == nil and _G.status == "YIELD" and _G.ctx == 2)
+ a = {co()}; assert(a[1] == nil and _G.status == "YIELD" and _G.ctx == 3)
+ a = {co(7,8)};
+ -- original arguments
+ assert(type(a[1]) == 'string' and type(a[2]) == 'string' and
+ type(a[3]) == 'string' and type(a[4]) == 'string' and
+ type(a[5]) == 'string' and type(a[6]) == 'function')
+ -- arguments left from fist resume
+ assert(a[7] == 3 and a[8] == 4)
+ -- arguments to last resume
+ assert(a[9] == 7 and a[10] == 8)
+ -- error message and nothing more
+ assert(a[11]:find("errmsg") and #a == 11)
+ -- check arguments to pcallk
+ assert(x == "YIELD" and y == 4)
+
+ assert(not pcall(co)) -- coroutine should be dead
+ `, 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: bug in nCcalls", function (t) {
+ let luaCode = `
+ local co = coroutine.wrap(function ()
+ local a = {pcall(pcall,pcall,pcall,pcall,pcall,pcall,pcall,error,"hi")}
+ return pcall(assert, table.unpack(a))
+ end)
+
+ local a = {co()}
+ assert(a[10] == "hi")
+ `, 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");
+});