1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
#! /usr/bin/env tarantool
local netbox = require('net.box')
local os = require('os')
local tap = require('tap')
box.cfg{
listen = os.getenv('LISTEN')
}
--
-- gh-4398: error objects after transmission through network
-- should not loose their fields and type.
--
-- Create AccessDeniedError. It is going to be used in the tests
-- below.
function forbidden_function()
return nil
end
local user = box.session.user()
box.session.su('admin')
box.schema.func.create('forbidden_function')
box.session.su('guest')
local tmp = box.func.forbidden_function
local access_denied_error
tmp, access_denied_error = pcall(tmp.call, tmp)
box.session.su('admin')
box.schema.func.drop('forbidden_function')
box.session.su(user)
local test = tap.test('Error marshaling')
test:plan(12)
function error_new(...)
return box.error.new(...)
end
function error_throw(...)
box.error(error_new(...))
end
function error_new_stacked(args1, args2)
local e1 = box.error.new(args1)
local e2 = box.error.new(args2)
e1:set_prev(e2)
return e1
end
function error_throw_stacked(...)
box.error(error_new_stacked(...))
end
function error_access_denied()
return access_denied_error
end
function error_throw_access_denied()
box.error(access_denied_error)
end
local function check_error(err, check_list)
assert(type(check_list) == 'table')
if type(err.trace) ~= 'table' or err.trace[1] == nil or
err.trace[1].file == nil or err.trace[1].line == nil then
return false
end
for k, v in pairs(check_list) do
if err[k] ~= v then
return false
end
end
return true
end
box.schema.user.grant('guest', 'super')
local c = netbox.connect(box.cfg.listen)
c:eval('box.session.settings.error_marshaling_enabled = true')
local args = {{code = 1000, reason = 'Reason'}}
local err = c:call('error_new', args)
local checks = {
code = 1000,
message = 'Reason',
base_type = 'ClientError',
type = 'ClientError',
}
test:ok(check_error(err, checks), "ClientError marshaling")
tmp, err = pcall(c.call, c, 'error_throw', args)
test:ok(check_error(err, checks), "ClientError marshaling in iproto fields")
args = {{code = 1001, reason = 'Reason2', type = 'MyError'}}
err = c:call('error_new', args)
checks = {
code = 1001,
message = 'Reason2',
base_type = 'CustomError',
type = 'MyError',
}
test:ok(check_error(err, checks), "CustomError marshaling")
tmp, err = pcall(c.call, c, 'error_throw', args)
test:ok(check_error(err, checks), "CustomError marshaling in iproto fields")
err = c:call('error_access_denied')
checks = {
code = 42,
type = 'AccessDeniedError',
base_type = 'AccessDeniedError',
message = "Execute access to function 'forbidden_function' is denied for user 'guest'",
object_type = 'function',
object_name = 'forbidden_function',
access_type = 'Execute',
}
test:ok(check_error(err, checks), "AccessDeniedError marshaling")
tmp, err = pcall(c.call, c, 'error_throw_access_denied')
test:ok(check_error(err, checks), "AccessDeniedError marshaling in iproto fields")
args = {
{code = 1003, reason = 'Reason3', type = 'MyError2'},
{code = 1004, reason = 'Reason4'}
}
err = c:call('error_new_stacked', args)
local err1 = err
local err2 = err.prev
test:isnt(err2, nil, 'Stack is received')
local checks1 = {
code = 1003,
message = 'Reason3',
base_type = 'CustomError',
type = 'MyError2'
}
test:ok(check_error(err1, checks1), "First error in the stack")
local checks2 = {
code = 1004,
message = 'Reason4',
base_type = 'ClientError',
type = 'ClientError'
}
test:ok(check_error(err2, checks2), "Second error in the stack")
tmp, err = pcall(c.call, c, 'error_throw_stacked', args)
err1 = err
err2 = err.prev
test:isnt(err2, nil, 'Stack is received via iproto fields')
test:ok(check_error(err1, checks1), "First error in the stack in iproto fields")
test:ok(check_error(err2, checks2), "Second error in the stack in iproto fields")
c:close()
box.schema.user.revoke('guest', 'super')
os.exit(test:check() and 0 or 1)
|