Skip to content

Commit f31fe34

Browse files
server: refactor exec() sparse output support
Simplify code from PR #351 based on @Totktonada advice. Follows #350
1 parent 0c06b68 commit f31fe34

File tree

3 files changed

+6
-118
lines changed

3 files changed

+6
-118
lines changed

luatest/server.lua

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -686,33 +686,24 @@ function Server:exec(fn, args, options)
686686
:format(utils.get_fn_location(fn)))
687687
end
688688

689-
local utils_dumps = {
690-
unpack_sparse_array = string.dump(utils.unpack_sparse_array),
691-
}
692-
693689
-- The function `fn` can return multiple values and we cannot use the
694690
-- classical approach to work with the `pcall`:
695691
--
696692
-- local status, result = pcall(function() return 1, 2, 3 end)
697693
--
698694
-- `result` variable will contain only `1` value, not `1, 2, 3`.
699695
-- To solve this, we put everything from `pcall` in a table.
696+
-- Table must be unpacked with `unpack(result, i, table.maxn(result))`,
697+
-- otherwise nil return values won't be supported.
700698
return exec_tail(pcall(self.net_box.eval, self.net_box, [[
701-
local fn_dump, args, passthrough_ups, utils_dumps = ...
702-
703-
local fn = loadstring(fn_dump)
699+
local dump, args, passthrough_ups = ...
700+
local fn = loadstring(dump)
704701
for i = 1, debug.getinfo(fn, 'u').nups do
705702
local name, _ = debug.getupvalue(fn, i)
706703
if passthrough_ups[name] then
707704
debug.setupvalue(fn, i, require(passthrough_ups[name]))
708705
end
709706
end
710-
711-
local utils = {}
712-
for k, v in pairs(utils_dumps) do
713-
utils[k] = loadstring(v)
714-
end
715-
716707
local result
717708
if args == nil then
718709
result = {pcall(fn)}
@@ -725,8 +716,8 @@ function Server:exec(fn, args, options)
725716
end
726717
error(result[2], 0)
727718
end
728-
return utils.unpack_sparse_array(result, 2)
729-
]], {string.dump(fn), args, passthrough_ups, utils_dumps}, options))
719+
return unpack(result, 2, table.maxn(result))
720+
]], {string.dump(fn), args, passthrough_ups}, options))
730721
end
731722

732723
function Server:coverage(action)

luatest/utils.lua

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -191,26 +191,4 @@ function utils.is_tarantool_binary(path)
191191
return path:find('^.*/tarantool[^/]*$') ~= nil
192192
end
193193

194-
function utils.unpack_sparse_array(array, index)
195-
-- Embed everything so no upvalues required on server.
196-
index = index or 1
197-
198-
local len = 0
199-
for k, _ in pairs(array) do
200-
if type(k) == 'number' then
201-
len = math.max(len, k)
202-
end
203-
end
204-
205-
local function unpack_sparse_array_tail(array, index, len) -- luacheck: ignore
206-
if index > len then
207-
return
208-
end
209-
210-
return array[index], unpack_sparse_array_tail(array, index + 1, len)
211-
end
212-
213-
return unpack_sparse_array_tail(array, index, len)
214-
end
215-
216194
return utils

test/utils_test.lua

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
local json = require('json')
2-
31
local t = require('luatest')
42
local g = t.group()
53

@@ -24,82 +22,3 @@ g.test_is_tarantool_binary = function()
2422
("Unexpected result for %q"):format(path))
2523
end
2624
end
27-
28-
g.test_unpack_sparse_array_with_values = function()
29-
local non_sparse_input = {
30-
{{1, 2, 3, 4}, nil},
31-
{{1, 2, 3, 4}, 3},
32-
}
33-
34-
-- Test unpack_sparse_array() is unpack() if non-sparse input.
35-
local non_sparse_cases = {}
36-
for _, v in ipairs(non_sparse_input) do
37-
table.insert(non_sparse_cases, {v[1], v[2], {unpack(v[1], v[2])}})
38-
end
39-
40-
local sparse_cases = {
41-
{{1, nil, 3}, nil, {1, nil, 3}},
42-
{{1, nil, 3}, 2, {nil, 3}},
43-
{{nil, 2, nil}, nil, {nil, 2}},
44-
{{nil, 2, nil}, 2, {2}},
45-
{{nil, 2, box.NULL}, nil, {nil, 2, box.NULL}},
46-
{{nil, 2, box.NULL}, 3 ,{box.NULL}},
47-
{{nil, nil, nil, nil, 5}, 4, {nil, 5}},
48-
{{nil, nil, nil, nil, 5}, 5, {5}},
49-
}
50-
51-
local cases = {unpack(non_sparse_cases), unpack(sparse_cases)}
52-
53-
for _, case in ipairs(cases) do
54-
local array, index, result_packed = unpack(case)
55-
56-
local assert_msg
57-
if index ~= nil then
58-
assert_msg = ("Unexpected result for unpack_sparse_array(%q, %d)"):format(
59-
json.encode(array), index)
60-
else
61-
assert_msg = ("Unexpected result for unpack_sparse_array(%q)"):format(
62-
json.encode(array))
63-
end
64-
65-
t.assert_equals(
66-
{utils.unpack_sparse_array(array, index)},
67-
result_packed,
68-
assert_msg
69-
)
70-
end
71-
end
72-
73-
local function assert_return_no_values(func, ...)
74-
-- http://lua-users.org/lists/lua-l/2011-09/msg00312.html
75-
t.assert_error_msg_contains(
76-
"bad argument #1 to 'assert' (value expected)",
77-
function(...)
78-
assert(func(...))
79-
end,
80-
...
81-
)
82-
end
83-
84-
g.test_unpack_sparse_array_no_values = function()
85-
local non_sparse_cases = {
86-
{{1, 2, 3, 4}, 5},
87-
{{}, 1},
88-
}
89-
90-
local sparse_cases = {
91-
{{1, nil, 3}, 6},
92-
}
93-
94-
-- Assert built-in unpack() symmetric behavior.
95-
for _, case in ipairs(sparse_cases) do
96-
local array, index = unpack(case)
97-
assert_return_no_values(unpack, array, index)
98-
end
99-
100-
local cases = {unpack(non_sparse_cases), unpack(sparse_cases)}
101-
for _, case in ipairs(cases) do
102-
local array, index = unpack(case)
103-
assert_return_no_values(utils.unpack_sparse_array, array, index)
104-
end
105-
end

0 commit comments

Comments
 (0)