aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/scripts
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2025-09-30 15:06:21 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2025-09-30 15:06:21 +0200
commitae43a00657a6505910010bdf920c9c0f4823a9c0 (patch)
tree198f7e3d816ac99152a94f5fe3a5328117a36a8e /unit_tests/scripts
parentf011dcafb0f583c89ed9971238fd83ddcbdb5438 (diff)
downloadlanes-master.tar.gz
lanes-master.tar.bz2
lanes-master.zip
Lift restriction on functions and userdata as table keysHEADmaster
As demonstrated by the unit tests, there is no problem with using a function or a userdata as a table key, as long as they are transferable
Diffstat (limited to 'unit_tests/scripts')
-rw-r--r--unit_tests/scripts/linda/send_receive_tables.lua166
-rw-r--r--unit_tests/scripts/linda/send_registered_userdata.lua2
2 files changed, 133 insertions, 35 deletions
diff --git a/unit_tests/scripts/linda/send_receive_tables.lua b/unit_tests/scripts/linda/send_receive_tables.lua
index 08b1f16..0e1569a 100644
--- a/unit_tests/scripts/linda/send_receive_tables.lua
+++ b/unit_tests/scripts/linda/send_receive_tables.lua
@@ -1,41 +1,137 @@
1local lanes = require "lanes" 1local lanes = require "lanes"
2local dt = lanes.require "deep_userdata_example"
2 3
3-- a newly created linda doesn't contain anything
4local l = lanes.linda() 4local l = lanes.linda()
5 5
6-- =================================================================================================
6-- send a table with subtables, both as keys and values, making sure the structure is preserved 7-- send a table with subtables, both as keys and values, making sure the structure is preserved
8-- =================================================================================================
7 9
8local t1 = {["name"] = "t1"} 10if true then
9local t2 = {["name"] = "t2"} 11 local t1 = {["name"] = "t1"}
10 12 local t2 = {["name"] = "t2"}
11local t3 = { 13
12 ["name"] = "t3", 14 local t3 = {
13 ["t1"] = t1, 15 ["name"] = "t3",
14 [t1] = t2, -- table t1 as key, table t2 as value 16 ["t1"] = t1,
15 ["t2"] = t2, 17 [t1] = t2, -- table t1 as key, table t2 as value
16 [t2] = t1 -- table t2 as key, table t1 as value 18 ["t2"] = t2,
17} 19 [t2] = t1 -- table t2 as key, table t1 as value
18 20 }
19-- add recursivity for good measure 21
20t3["t3"] = t3 22 -- add recursivity for good measure
21t3[t3] = t3 23 t3["t3"] = t3
22t1["t3"] = t3 24 t3[t3] = t3
23t2["t3"] = t3 25 t1["t3"] = t3
24 26 t2["t3"] = t3
25l:send("data", t3) 27
26local k, t = l:receive("data") 28 l:send("data", t3)
27assert(k == "data" and type(t) == "table" and t.name == "t3") 29 local k, t = l:receive("data")
28-- when keys are strings 30 assert(k == "data" and type(t) == "table" and t.name == "t3")
29assert(t["t3"] == t) 31 -- when keys are strings
30assert(type(t["t1"]) == "table") 32 assert(t["t3"] == t)
31assert(t["t1"].name == "t1") 33 assert(type(t["t1"]) == "table")
32assert(type(t["t2"]) == "table") 34 assert(t["t1"].name == "t1")
33assert(t["t2"].name == "t2") 35 assert(type(t["t2"]) == "table")
34assert(t["t1"].t3 == t) 36 assert(t["t2"].name == "t2")
35assert(t["t2"].t3 == t) 37 assert(t["t1"].t3 == t)
36-- when keys are tables 38 assert(t["t2"].t3 == t)
37assert(t[t.t1] == t.t2) 39 -- when keys are tables
38assert(t[t.t1]["t3"] == t) 40 assert(t[t.t1] == t.t2)
39assert(t[t.t2] == t.t1) 41 assert(t[t.t1]["t3"] == t)
40assert(t[t.t2]["t3"] == t) 42 assert(t[t.t2] == t.t1)
41assert(t[t.t3] == t.t3) 43 assert(t[t.t2]["t3"] == t)
44 assert(t[t.t3] == t.t3)
45end
46
47-- =================================================================================================
48-- send a table with deep userdata keys and values
49-- =================================================================================================
50
51if true then
52 local fixture = assert(require "fixture")
53 local u = assert(fixture.newuserdata())
54 assert(type(u) == "userdata")
55
56 -- send a table where full userdata is used as key
57 -- should fail because the userdata is not deep
58 local s, r = pcall(l.send, l, "data", {["k"] = u})
59 assert(s == false and type(r) == "string", "got " .. r)
60
61 -- trying again with full userdata
62 local d1 = dt.new_deep()
63 assert(type(d1) == "userdata")
64 local d2 = dt.new_deep()
65 assert(type(d2) == "userdata")
66
67 local t4 =
68 {
69 [d1] = d2,
70 [d2] = d1
71 }
72
73 l:send("data", t4)
74 local k, t = l:receive("data")
75 assert(k == "data" and type(t) == "table")
76 -- we should have 2 userdata entries in the table
77 local count = 0
78 for k, v in pairs(t) do
79 assert(type(k) == "userdata")
80 assert(type(v) == "userdata")
81 count = count + 1
82 end
83 assert(count == 2, "got " .. count)
84 -- all userdata identities should be preserved
85 assert(type(t[d1]) == "userdata")
86 assert(type(t[d2]) == "userdata")
87 assert(t[d1] == d2)
88 assert(t[d2] == d1)
89 assert(t[d1] == t4[d1])
90 assert(t[d2] == t4[d2])
91end
92
93-- =================================================================================================
94-- send a table with clonable userdata keys and values
95-- =================================================================================================
96
97if true then
98 local c1 = dt.new_clonable()
99 c1:set(1)
100 assert(type(c1) == "userdata")
101 local c2 = dt.new_clonable()
102 c2:set(2)
103 assert(type(c2) == "userdata")
104
105 l:send("data", c1)
106 local k, c = l:receive("data")
107 assert(k == "data" and type(c) == "userdata" and c:get() == 1, "got " .. tostring(c))
108
109 local t5 =
110 {
111 [c1] = c2,
112 [c2] = c1
113 }
114
115 l:send("data", t5)
116 local k, t = l:receive("data")
117 assert(k == "data" and type(t) == "table")
118 -- all userdata identities should NOT be preserved, because the cloned userdatas in t are not the originals that were stored in t5
119 assert(type(t[c1]) == "nil")
120 assert(type(t[c2]) == "nil")
121 -- but we should still have 2 userdata entries in the table
122 local count = 0
123 for k, v in pairs(t) do
124 assert(type(k) == "userdata")
125 assert(type(v) == "userdata")
126 count = count + 1
127 end
128 assert(count == 2, "got " .. count)
129 -- and c1-as-key should be identical to c1-as-value (same for c2)
130 -- of course I can't be sure that enumerating the table will start with key c1, but that's not important
131 local c1_as_key, c2_as_value = next(t)
132 assert(type(c1_as_key) == "userdata" and type(c2_as_value) == "userdata" and c1_as_key:get() ~= c2_as_value:get())
133 local c2_as_key, c1_as_value = next(t, c1_as_key)
134 assert(type(c2_as_key) == "userdata" and type(c1_as_value) == "userdata" and c2_as_key:get() ~= c1_as_value:get())
135 assert(c1_as_key == c1_as_value)
136 assert(c2_as_key == c2_as_value)
137end
diff --git a/unit_tests/scripts/linda/send_registered_userdata.lua b/unit_tests/scripts/linda/send_registered_userdata.lua
index 90c05c9..f0ec3d4 100644
--- a/unit_tests/scripts/linda/send_registered_userdata.lua
+++ b/unit_tests/scripts/linda/send_registered_userdata.lua
@@ -1,5 +1,7 @@
1local lanes = require 'lanes'.configure{with_timers = false} 1local lanes = require 'lanes'.configure{with_timers = false}
2local l = lanes.linda{name = 'gleh'} 2local l = lanes.linda{name = 'gleh'}
3
4-- io.stdin is a full userdata that was registered by lanes when it was required and scanned the global environment
3l:set('yo', io.stdin) 5l:set('yo', io.stdin)
4local n, stdin_out = l:get('yo') 6local n, stdin_out = l:get('yo')
5assert(n == 1 and stdin_out == io.stdin, tostring(stdin_out) .. " ~= " .. tostring(io.stdin)) 7assert(n == 1 and stdin_out == io.stdin, tostring(stdin_out) .. " ~= " .. tostring(io.stdin))