aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/scripts/coro
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-12-13 17:22:17 +0100
committerBenoit Germain <benoit.germain@ubisoft.com>2024-12-13 17:22:17 +0100
commitdc7a2bc3a9c8316e17902493b832ca117805d29f (patch)
tree3c1a03edf586869119ef0de03631f6f603650720 /unit_tests/scripts/coro
parent7500a80fc06c5311c46df8f1761f25ae67277fc4 (diff)
downloadlanes-dc7a2bc3a9c8316e17902493b832ca117805d29f.tar.gz
lanes-dc7a2bc3a9c8316e17902493b832ca117805d29f.tar.bz2
lanes-dc7a2bc3a9c8316e17902493b832ca117805d29f.zip
Append all unit tests to depot
Diffstat (limited to 'unit_tests/scripts/coro')
-rw-r--r--unit_tests/scripts/coro/basics.lua94
-rw-r--r--unit_tests/scripts/coro/error_handling.lua64
2 files changed, 158 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
diff --git a/unit_tests/scripts/coro/error_handling.lua b/unit_tests/scripts/coro/error_handling.lua
new file mode 100644
index 0000000..3b50c7f
--- /dev/null
+++ b/unit_tests/scripts/coro/error_handling.lua
@@ -0,0 +1,64 @@
1local lanes = require "lanes".configure{strip_functions = true}
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, "unexpected reply ".._ack)
19 end
20 return "done!"
21end
22
23local force_error_test = function(error_trace_level_)
24 -- the generator, minimal error handling
25 local coro_g = lanes.coro("*", {name = "auto", error_trace_level = error_trace_level_}, yielder)
26
27 -- launch coroutine lane
28 local h = coro_g("hello", "world", "!")
29 -- read the yielded values, sending back the expected index
30 assert(h:resume(1) == "hello")
31 assert(h:resume(2) == "world")
32 -- mistake: we resume with 0 when the lane expects 3 -> assert() in the lane body!
33 assert(h:resume(0) == "!")
34 local a, b, c = h:join()
35 PRINT(error_trace_level_ .. ":", a, b, c)
36 local expected_c_type = error_trace_level_ == "minimal" and "nil" or "table"
37 assert(h.status == "error" and string.find(b, "unexpected reply 0", 1, true) and type(c) == expected_c_type, "error message is " .. b)
38 utils.dump_error_stack(error_trace_level_, c)
39end
40
41if false then
42 force_error_test("minimal")
43end
44
45if false then
46 force_error_test("basic")
47end
48
49if false then
50 force_error_test("extended")
51end
52
53if true then
54 -- start a coroutine lane that ends with a non-string error
55 local non_string_thrower = function()
56 error({"string in table"})
57 end
58 local coro_g = lanes.coro("*", {name = "auto"}, non_string_thrower)
59 local h = coro_g()
60 local a, b, c = h:join()
61 -- we get the expected error back
62 PRINT("non_string_thrower:", a, b, c)
63 assert(a == nil and type(b) == "table" and b[1] == "string in table" and c == nil)
64end