Skip to content

Commit 87fedf3

Browse files
WIP
1 parent ff83f19 commit 87fedf3

6 files changed

+198
-3
lines changed

box_error.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func msgpackDecodeBoxError(d *decoder, v reflect.Value) (err error) {
139139
}
140140

141141
func encodeBoxError(enc *encoder, boxError BoxError) (err error) {
142-
if err = enc.EncodeArrayLen(1); err != nil {
142+
if err = enc.EncodeMapLen(1); err != nil {
143143
return err
144144
}
145145
if err = encodeUint(enc, KeyErrorStack); err != nil {
@@ -152,6 +152,18 @@ func encodeBoxError(enc *encoder, boxError BoxError) (err error) {
152152
}
153153

154154
for ; stackDepth > 0; stackDepth-- {
155+
isWithFields := (len(boxError.Fields) > 0)
156+
157+
if isWithFields {
158+
if err = enc.EncodeMapLen(7); err != nil {
159+
return err
160+
}
161+
} else {
162+
if err = enc.EncodeMapLen(6); err != nil {
163+
return err
164+
}
165+
}
166+
155167
if err = encodeUint(enc, KeyErrorType); err != nil {
156168
return err
157169
}
@@ -201,7 +213,7 @@ func encodeBoxError(enc *encoder, boxError BoxError) (err error) {
201213
return err
202214
}
203215

204-
if len(boxError.Fields) > 0 {
216+
if isWithFields {
205217
if err = encodeUint(enc, KeyErrorFields); err != nil {
206218
return err
207219
}

config.lua

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ box.once("init", function()
130130
-- grants for sql tests
131131
box.schema.user.grant('test', 'create,read,write,drop,alter', 'space')
132132
box.schema.user.grant('test', 'create', 'sequence')
133+
134+
box.schema.user.create('no_grants')
133135
end)
134136

135137
local function func_name()
@@ -159,6 +161,45 @@ rawset(_G, 'push_func', push_func)
159161

160162
box.space.test:truncate()
161163

164+
local function tarantool_version_at_least(wanted_major, wanted_minor, wanted_patch)
165+
-- Borrowed from `determine_enabled_features()` from
166+
-- crud/common/utils.lua.
167+
local major_minor_patch = _TARANTOOL:split('-', 1)[1]
168+
local major_minor_patch_parts = major_minor_patch:split('.', 2)
169+
170+
local major = tonumber(major_minor_patch_parts[1])
171+
local minor = tonumber(major_minor_patch_parts[2])
172+
local patch = tonumber(major_minor_patch_parts[3])
173+
174+
if major < (wanted_major or 0) then return false end
175+
if major > (wanted_major or 0) then return true end
176+
177+
if minor < (wanted_minor or 0) then return false end
178+
if minor > (wanted_minor or 0) then return true end
179+
180+
if patch < (wanted_patch or 0) then return false end
181+
if patch > (wanted_patch or 0) then return true end
182+
183+
return true
184+
end
185+
186+
if tarantool_version_at_least(2, 10) then
187+
local err = box.error.new(box.error.UNKNOWN)
188+
rawset(_G, 'simple_error', err)
189+
190+
local user = box.session.user()
191+
box.schema.func.create('forbidden_function', {body = 'function() end'})
192+
box.session.su('no_grants')
193+
local _, access_denied_error = pcall(function() box.func.forbidden_function:call() end)
194+
box.session.su(user)
195+
rawset(_G, 'access_denied_error', access_denied_error)
196+
197+
local e1 = box.error.new(box.error.UNKNOWN)
198+
local e2 = box.error.new(box.error.UNKNOWN)
199+
e2:set_prev(e1)
200+
rawset(_G, 'chained_error', e2)
201+
end
202+
162203
--box.schema.user.revoke('guest', 'read,write,execute', 'universe')
163204

164205
-- Set listen only when every other thing is configured.

error_ext_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package tarantool_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
. "github.com/tarantool/go-tarantool"
8+
)
9+
10+
var isErrorExtSupported bool
11+
12+
func skipIfErrorExtUnsupported(t *testing.T) {
13+
t.Helper()
14+
15+
if isErrorExtSupported == false {
16+
t.Skip("Skipping test for Tarantool without error extention type support in msgpack")
17+
}
18+
}
19+
20+
var samples = []struct {
21+
goErr BoxError
22+
mpBuf string
23+
ttErrName string
24+
}{
25+
{
26+
BoxError{
27+
Type: "ClientError",
28+
File: "eval",
29+
Line: 1,
30+
Message: "Unknown error",
31+
Errno: 0,
32+
Errcode: 0,
33+
},
34+
"8100918600ab436c69656e744572726f7201a46576616c020103ad556e6b6e6f776e206572726f72" +
35+
"04000500",
36+
"simple_error",
37+
},
38+
{
39+
BoxError{
40+
Type: "AccessDeniedError",
41+
File: "/__w/sdk/sdk/tarantool-2.10/tarantool/src/box/func.c",
42+
Line: 535,
43+
Message: "Execute access to function 'forbidden_function' is denied for user 'no_grants'",
44+
Errno: 0,
45+
Errcode: 42,
46+
Fields: map[interface{}]interface{}{
47+
"object_type": "function",
48+
"object_name": "forbidden_function",
49+
"access_type": "Execute",
50+
},
51+
},
52+
"8100918700b141636365737344656e6965644572726f7201d9342f5f5f772f73646b2f73646b2f74" +
53+
"6172616e746f6f6c2d322e31302f746172616e746f6f6c2f7372632f626f782f66756e632e63" +
54+
"02cd021703d94e457865637574652061636365737320746f2066756e6374696f6e2027666f72" +
55+
"62696464656e5f66756e6374696f6e272069732064656e69656420666f72207573657220276e" +
56+
"6f5f6772616e7473270400052a0683ab6f626a6563745f74797065a866756e6374696f6eab6f" +
57+
"626a6563745f6e616d65b2666f7262696464656e5f66756e6374696f6eab6163636573735f74" +
58+
"797065a745786563757465",
59+
"access_denied_error",
60+
},
61+
{
62+
BoxError{
63+
Type: "ClientError",
64+
File: "eval",
65+
Line: 1,
66+
Message: "Unknown error",
67+
Errno: 0,
68+
Errcode: 0,
69+
Prev: &BoxError{
70+
Type: "ClientError",
71+
File: "eval",
72+
Line: 2,
73+
Message: "Unknown error",
74+
Errno: 0,
75+
Errcode: 0,
76+
},
77+
},
78+
"8100928600ab436c69656e744572726f7201a46576616c020303ad556e6b6e6f776e206572726f72" +
79+
"040005008600ab436c69656e744572726f7201a46576616c020203ad556e6b6e6f776e206572" +
80+
"726f7204000500",
81+
"chained_error",
82+
},
83+
}
84+
85+
func TestErrorExtMPEncodeDecode(t *testing.T) {
86+
for _, testcase := range samples {
87+
t.Run(testcase.ttErrName, func(t *testing.T) {
88+
var buf []byte
89+
var err error
90+
if buf, err = marshal(testcase.goErr); err != nil {
91+
t.Fatalf("Failed to encode error ext type '%v' to a MessagePack buffer: %s", testcase.goErr, err)
92+
}
93+
var v BoxError
94+
if err = unmarshal(buf, &v); err != nil {
95+
t.Fatalf("Failed to decode MessagePack buffer '%x' to a error ext type: %s", buf, err)
96+
}
97+
require.Equal(t, v, testcase.goErr)
98+
})
99+
}
100+
}

msgpack_helper_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package tarantool_test
55

66
import (
7+
. "github.com/tarantool/go-tarantool"
78
"gopkg.in/vmihailenco/msgpack.v2"
89
)
910

@@ -13,3 +14,16 @@ type decoder = msgpack.Decoder
1314
func encodeUint(e *encoder, v uint64) error {
1415
return e.EncodeUint(uint(v))
1516
}
17+
18+
func toBoxError(i interface{}) (v BoxError, ok bool) {
19+
v, ok = i.(BoxError)
20+
return
21+
}
22+
23+
func marshal(v interface{}) ([]byte, error) {
24+
return msgpack.Marshal(v)
25+
}
26+
27+
func unmarshal(data []byte, v interface{}) error {
28+
return msgpack.Unmarshal(data, v)
29+
}

msgpack_v5_helper_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package tarantool_test
55

66
import (
7+
. "github.com/tarantool/go-tarantool"
78
"github.com/vmihailenco/msgpack/v5"
89
)
910

@@ -13,3 +14,19 @@ type decoder = msgpack.Decoder
1314
func encodeUint(e *encoder, v uint64) error {
1415
return e.EncodeUint(v)
1516
}
17+
18+
func toBoxError(i interface{}) (v BoxError, ok bool) {
19+
var ptr *BoxError
20+
if ptr, ok = i.(*BoxError); ok {
21+
dec = *ptr
22+
}
23+
return
24+
}
25+
26+
func marshal(v interface{}) ([]byte, error) {
27+
return msgpack.Marshal(v)
28+
}
29+
30+
func unmarshal(data []byte, v interface{}) error {
31+
return msgpack.Unmarshal(data, v)
32+
}

tarantool_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2869,7 +2869,11 @@ func TestConnectionProtocolInfoSupported(t *testing.T) {
28692869
clientProtocolInfo,
28702870
ProtocolInfo{
28712871
Version: ProtocolVersion(4),
2872-
Features: []ProtocolFeature{StreamsFeature, TransactionsFeature},
2872+
Features: []ProtocolFeature{
2873+
StreamsFeature,
2874+
TransactionsFeature,
2875+
ErrorExtensionFeature,
2876+
},
28732877
})
28742878

28752879
serverProtocolInfo := conn.ServerProtocolInfo()
@@ -3256,6 +3260,13 @@ func runTestMain(m *testing.M) int {
32563260
log.Fatalf("Could not check the Tarantool version")
32573261
}
32583262

3263+
if isStreamUnsupported {
3264+
log.Println("Skipping error extention type tests...")
3265+
isErrorExtSupported = false
3266+
} else {
3267+
isErrorExtSupported = true
3268+
}
3269+
32593270
startOpts.MemtxUseMvccEngine = !isStreamUnsupported
32603271

32613272
inst, err := test_helpers.StartTarantool(startOpts)

0 commit comments

Comments
 (0)