aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/scripts/coro/yielding_function.lua
diff options
context:
space:
mode:
Diffstat (limited to 'unit_tests/scripts/coro/yielding_function.lua')
-rw-r--r--unit_tests/scripts/coro/yielding_function.lua107
1 files changed, 107 insertions, 0 deletions
diff --git a/unit_tests/scripts/coro/yielding_function.lua b/unit_tests/scripts/coro/yielding_function.lua
new file mode 100644
index 0000000..e7367ea
--- /dev/null
+++ b/unit_tests/scripts/coro/yielding_function.lua
@@ -0,0 +1,107 @@
1local lanes = require "lanes"
2
3local fixture = require "fixture"
4lanes.finally(fixture.throwing_finalizer)
5
6local utils = lanes.require "_utils"
7local PRINT = utils.MAKE_PRINT()
8
9-- a lane coroutine that yields back what got in, one element at a time
10local yielder = function(...)
11 local utils = lanes.require "_utils"
12 local PRINT = utils.MAKE_PRINT()
13 PRINT "In lane"
14 for _i = 1, select('#', ...) do
15 local _val = select(_i, ...)
16 PRINT("yielding #", _i, _val)
17 local _ack = coroutine.yield(_val)
18 assert(_ack == _i)
19 end
20 return "done!"
21end
22
23--------------------------------------------------------------------------------------------------
24-- TEST: if we start a non-coroutine lane with a yielding function, we should get an error, right?
25--------------------------------------------------------------------------------------------------
26if true then
27 local fun_g = lanes.gen("*", { name = 'auto' }, yielder)
28 local h = fun_g("hello", "world", "!")
29 local err, status, stack = h:join()
30 PRINT(err, status, stack)
31 -- the actual error message is not the same for Lua 5.1
32 -- of course, it also has to be different for LuaJIT as well
33 -- also, LuaJIT prepends a file:line to the actual error message, which Lua5.1 does not.
34 local msgs = {
35 ["Lua 5.1"] = jit and "attempt to yield across C-call boundary" or "attempt to yield across metamethod/C-call boundary",
36 ["Lua 5.2"] = "attempt to yield from outside a coroutine",
37 ["Lua 5.3"] = "attempt to yield from outside a coroutine",
38 ["Lua 5.4"] = "attempt to yield from outside a coroutine"
39 }
40 local expected_msg = msgs[_VERSION]
41 PRINT("expected_msg = " .. expected_msg)
42 assert(err == nil and string.find(status, expected_msg, 1, true) and stack == nil, "status = " .. status)
43end
44
45-- the coroutine generator
46local coro_g = lanes.coro("*", {name = "auto"}, yielder)
47
48-------------------------------------------------------------------------------------------------
49-- TEST: we can resume as many times as the lane yields, then read the returned value on indexing
50-------------------------------------------------------------------------------------------------
51if true then
52 -- launch coroutine lane
53 local h = coro_g("hello", "world", "!")
54 -- read the yielded values, sending back the expected index
55 assert(h:resume(1) == "hello")
56 assert(h:resume(2) == "world")
57 assert(h:resume(3) == "!")
58 -- the lane return value is available as usual
59 local r = h[1]
60 assert(r == "done!")
61end
62
63---------------------------------------------------------------------------------------------
64-- TEST: we can resume as many times as the lane yields, then read the returned value on join
65---------------------------------------------------------------------------------------------
66if true then
67 -- launch coroutine lane
68 local h = coro_g("hello", "world", "!")
69 -- read the yielded values, sending back the expected index
70 assert(h:resume(1) == "hello")
71 assert(h:resume(2) == "world")
72 assert(h:resume(3) == "!")
73 -- the lane return value is available as usual
74 local s, r = h:join()
75 assert(h.status == "done" and s == true and r == "done!")
76end
77
78---------------------------------------------------------------------------------------------------
79-- TEST: if we join a yielded lane, we get a timeout, and we can resume as if we didn't try to join
80---------------------------------------------------------------------------------------------------
81if true then
82 -- launch coroutine lane
83 local h = coro_g("hello", "world", "!")
84 -- read the first yielded value, sending back the expected index
85 assert(h:resume(1) == "hello")
86 -- join the lane. since it will reach a yield point, it remains suspended, and we should get a timeout
87 local b, r = h:join(0.5)
88 local s = h.status
89 assert(s == "suspended" and b == nil and r == "timeout", "got " .. s .. " " .. tostring(b) .. " " .. r)
90 -- trying to resume again should proceed normally, since nothing changed
91 assert(h:resume(2) == "world")
92 assert(h:resume(3) == "!")
93 -- the lane return value is available as usual
94 local s, r = h:join()
95 assert(h.status == "done" and s == true and r == "done!")
96end
97
98---------------------------------------------------------
99-- TEST: if we index yielded lane, we should get an error
100---------------------------------------------------------
101-- TODO: implement this test!
102
103
104-------------------------------------------------------------------------------------
105-- TEST: if we close yielded lane, we can join it and get the last yielded values out
106-------------------------------------------------------------------------------------
107-- TODO: we need to implement lane:close() for that!