diff options
Diffstat (limited to '')
-rw-r--r-- | unit_tests/scripts/coro/basics.lua | 94 |
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 @@ | |||
1 | local lanes = require "lanes" | ||
2 | |||
3 | local fixture = require "fixture" | ||
4 | lanes.finally(fixture.throwing_finalizer) | ||
5 | |||
6 | local utils = lanes.require "_utils" | ||
7 | local PRINT = utils.MAKE_PRINT() | ||
8 | |||
9 | if 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") | ||
27 | end | ||
28 | |||
29 | -- a lane coroutine that yields back what got in, one element at a time | ||
30 | local 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!" | ||
41 | end | ||
42 | |||
43 | if 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) | ||
58 | end | ||
59 | |||
60 | -- the generator | ||
61 | local coro_g = lanes.coro("*", {name = "auto"}, yielder) | ||
62 | |||
63 | if 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!") | ||
73 | end | ||
74 | |||
75 | if 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") | ||
94 | end | ||