aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/scripts/coro/basics.lua
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--unit_tests/scripts/coro/basics.lua94
1 files changed, 94 insertions, 0 deletions
diff --git a/unit_tests/scripts/coro/basics.lua b/unit_tests/scripts/coro/basics.lua
new file mode 100644
index 0000000..4444e87
--- /dev/null
+++ b/unit_tests/scripts/coro/basics.lua
@@ -0,0 +1,94 @@
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
9if true then
10 -- a lane body that just returns some value
11 local lane = function(msg_)
12 local utils = lanes.require "_utils"
13 local PRINT = utils.MAKE_PRINT()
14 PRINT "In lane"
15 assert(msg_ == "hi")
16 return "bye"
17 end
18
19 -- the generator
20 local g1 = lanes.coro("*", {name = "auto"}, lane)
21
22 -- launch lane
23 local h1 = g1("hi")
24
25 local r = h1[1]
26 assert(r == "bye")
27end
28
29-- a lane coroutine that yields back what got in, one element at a time
30local yielder = function(...)
31 local utils = lanes.require "_utils"
32 local PRINT = utils.MAKE_PRINT()
33 PRINT "In lane"
34 for _i = 1, select('#', ...) do
35 local _val = select(_i, ...)
36 PRINT("yielding #", _i, _val)
37 local _ack = coroutine.yield(_val)
38 assert(_ack == _i)
39 end
40 return "done!"
41end
42
43if true then
44 -- if we start a non-coroutine lane with a yielding function, we should get an error, right?
45 local fun_g = lanes.gen("*", {name = "auto"}, yielder)
46 local h = fun_g("hello", "world", "!")
47 local err, status, stack = h:join()
48 PRINT(err, status, stack)
49 -- the actual error message is not the same for Lua 5.1
50 local msgs = {
51 ["Lua 5.1"] = "attempt to yield across metamethod/C-call boundary",
52 ["Lua 5.2"] = "attempt to yield from outside a coroutine",
53 ["Lua 5.3"] = "attempt to yield from outside a coroutine",
54 ["Lua 5.4"] = "attempt to yield from outside a coroutine"
55 }
56 local expected_msg = msgs[_VERSION]
57 assert(err == nil and status == expected_msg and stack == nil, "status = " .. status)
58end
59
60-- the generator
61local coro_g = lanes.coro("*", {name = "auto"}, yielder)
62
63if true then
64 -- launch coroutine lane
65 local h2 = coro_g("hello", "world", "!")
66 -- read the yielded values, sending back the expected index
67 assert(h2:resume(1) == "hello")
68 assert(h2:resume(2) == "world")
69 assert(h2:resume(3) == "!")
70 -- the lane return value is available as usual
71 local r = h2[1]
72 assert(r == "done!")
73end
74
75if true then
76 -- another coroutine lane
77 local h3 = coro_g("hello", "world", "!")
78
79 -- yielded values are available as regular return values
80 assert(h3[1] == "hello" and h3.status == "suspended")
81 -- since we consumed the returned values, they should not be here when we resume
82 assert(h3:resume(1) == nil)
83
84 -- similarly, we can get them with join()
85 assert(h3:join() == "world" and h3.status == "suspended")
86 -- since we consumed the returned values, they should not be here when we resume
87 assert(h3:resume(2) == nil)
88
89 -- the rest should work as usual
90 assert(h3:resume(3) == "!")
91
92 -- the final return value of the lane body remains to be read
93 assert(h3:join() == "done!" and h3.status == "done")
94end