aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lanes.vcxproj1
-rw-r--r--Lanes.vcxproj.filters3
-rw-r--r--src/intercopycontext.cpp7
-rw-r--r--tests/errhangtest.lua20
-rw-r--r--unit_tests/scripts/linda/send_receive_tables.lua166
-rw-r--r--unit_tests/scripts/linda/send_registered_userdata.lua2
6 files changed, 149 insertions, 50 deletions
diff --git a/Lanes.vcxproj b/Lanes.vcxproj
index 3d49d9e..120f473 100644
--- a/Lanes.vcxproj
+++ b/Lanes.vcxproj
@@ -2060,6 +2060,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
2060 <None Include="tests\objects.lua" /> 2060 <None Include="tests\objects.lua" />
2061 <None Include="tests\parallel_os_calls.lua" /> 2061 <None Include="tests\parallel_os_calls.lua" />
2062 <None Include="tests\perftest.lua" /> 2062 <None Include="tests\perftest.lua" />
2063 <None Include="tests\pingpong.lua" />
2063 <None Include="tests\protectproxy.lua" /> 2064 <None Include="tests\protectproxy.lua" />
2064 <None Include="tests\protect_allocator.lua" /> 2065 <None Include="tests\protect_allocator.lua" />
2065 <None Include="tests\recursive.lua" /> 2066 <None Include="tests\recursive.lua" />
diff --git a/Lanes.vcxproj.filters b/Lanes.vcxproj.filters
index 3014132..b8196c8 100644
--- a/Lanes.vcxproj.filters
+++ b/Lanes.vcxproj.filters
@@ -297,6 +297,9 @@
297 <None Include="Lanes.slnenv"> 297 <None Include="Lanes.slnenv">
298 <Filter>Resource Files\Make</Filter> 298 <Filter>Resource Files\Make</Filter>
299 </None> 299 </None>
300 <None Include="tests\pingpong.lua">
301 <Filter>tests</Filter>
302 </None>
300 </ItemGroup> 303 </ItemGroup>
301 <ItemGroup> 304 <ItemGroup>
302 <CustomBuild Include="src\lanes.lua"> 305 <CustomBuild Include="src\lanes.lua">
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp
index 7fb2706..61ce08f 100644
--- a/src/intercopycontext.cpp
+++ b/src/intercopycontext.cpp
@@ -937,10 +937,6 @@ void InterCopyContext::interCopyBoolean() const
937[[nodiscard]] 937[[nodiscard]]
938bool InterCopyContext::interCopyFunction() const 938bool InterCopyContext::interCopyFunction() const
939{ 939{
940 if (vt == VT::KEY) {
941 return false;
942 }
943
944 STACK_CHECK_START_REL(L1, 0); 940 STACK_CHECK_START_REL(L1, 0);
945 STACK_CHECK_START_REL(L2, 0); 941 STACK_CHECK_START_REL(L2, 0);
946 DEBUGSPEW_CODE(DebugSpew(nullptr) << "FUNCTION " << name << std::endl); 942 DEBUGSPEW_CODE(DebugSpew(nullptr) << "FUNCTION " << name << std::endl);
@@ -1169,9 +1165,6 @@ InterCopyOneResult InterCopyContext::interCopyUserdata() const
1169{ 1165{
1170 STACK_CHECK_START_REL(L1, 0); 1166 STACK_CHECK_START_REL(L1, 0);
1171 STACK_CHECK_START_REL(L2, 0); 1167 STACK_CHECK_START_REL(L2, 0);
1172 if (vt == VT::KEY) {
1173 return InterCopyOneResult::NotCopied;
1174 }
1175 1168
1176 // try clonable userdata first 1169 // try clonable userdata first
1177 if (tryCopyClonable()) { 1170 if (tryCopyClonable()) {
diff --git a/tests/errhangtest.lua b/tests/errhangtest.lua
index 5b3f0c0..819bc10 100644
--- a/tests/errhangtest.lua
+++ b/tests/errhangtest.lua
@@ -42,19 +42,23 @@ if true then
42 print "OK" 42 print "OK"
43end 43end
44 44
45-- send a table that contains a function 45-- =================================================================================================
46-- send a table that contains a function, both as key and value
47-- =================================================================================================
48
46if true then 49if true then
47 print "\n#### send table with a function" 50 print "\n#### send table with a function"
48 local fun = function() print "function test ok" end 51 local fun = function() print "function test ok" return 42 end
49 local t_in = { [fun] = fun, fun = fun } 52 local t_in = { [fun] = fun, ["fun"] = fun }
50 print(pcall(linda.send, linda, 'test', t_in)) 53 print(pcall(linda.send, linda, 'test', t_in))
51 local k,t_out = linda:receive('test') -- read the contents successfully sent 54 local k, t_out = linda:receive('test') -- read the contents successfully sent
52 t_out.fun() 55 -- t_out should contain two entries, just like t_in
53 -- t_out should contain a single entry, as [fun] = fun should have been discarded because functions are not acceptable keys
54 local count = 0 56 local count = 0
55 for k,v in pairs(t_out) do count = count + 1 end 57 for k,v in pairs(t_out) do count = count + 1 end
56 assert(count == 1) 58 assert(count == 2)
57 print "OK" 59 assert(t_out["fun"] == t_out[t_out.fun]) -- t_out[t_out.fun] should be identical to t_out["fun"]
60 assert(t_out["fun"] ~= fun) -- even if the function is not the original one but a copy
61 assert(t_out["fun"]() == t_out[t_out.fun]() and t_out["fun"]() == fun()) -- all functions should return the same value, since they are the same
58end 62end
59 63
60-- send a string 64-- send a string
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))