File: msgpackffi.test.lua

package info (click to toggle)
tarantool 2.6.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 85,364 kB
  • sloc: ansic: 513,760; cpp: 69,489; sh: 25,650; python: 19,190; perl: 14,973; makefile: 4,173; yacc: 1,329; sql: 1,074; pascal: 620; ruby: 190; awk: 18; lisp: 7
file content (136 lines) | stat: -rwxr-xr-x 5,169 bytes parent folder | download | duplicates (3)
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
#!/usr/bin/env tarantool

package.path = "lua/?.lua;"..package.path

local tap = require('tap')
local common = require('serializer_test')
local ffi = require('ffi')

local function is_map(s)
    local b = string.byte(string.sub(s, 1, 1))
    return b >= 0x80 and b <= 0x8f or b == 0xde or b == 0xdf
end

local function is_array(s)
    local b = string.byte(string.sub(s, 1, 1))
    return b >= 0x90 and b <= 0x9f or b == 0xdc or b == 0xdd
end

local function test_offsets(test, s)
    test:plan(6)
    local arr1 = {1, 2, 3}
    local arr2 = {4, 5, 6}
    local dump = s.encode(arr1)..s.encode(arr2)
    test:is(dump:len(), 8, "length of part1 + part2")

    local a
    local offset = 1
    a, offset = s.decode(dump, offset)
    test:is_deeply(a, arr1, "decoded part1")
    test:is(offset, 5, "offset of part2")

    a, offset = s.decode(dump, offset)
    test:is_deeply(a, arr2, "decoded part2")
    test:is(offset, 9, "offset of end")

    test:ok(not pcall(s.decode, dump, offset), "invalid offset")
end

local function test_other(test, s)
    test:plan(24)
    local buf = string.char(0x93, 0x6e, 0xcb, 0x42, 0x2b, 0xed, 0x30, 0x47,
        0x6f, 0xff, 0xff, 0xac, 0x77, 0x6b, 0x61, 0x71, 0x66, 0x7a, 0x73,
        0x7a, 0x75, 0x71, 0x71, 0x78)
    local num = s.decode(buf)[2]
    test:ok(num < 59971740600 and num > 59971740599, "gh-633 double decode")

    -- gh-596: msgpack and msgpackffi have different behaviour
    local arr = {1, 2, 3}
    local map = {k1 = 'v1', k2 = 'v2', k3 = 'v3'}
    test:is(getmetatable(s.decode(s.encode(arr))).__serialize, "seq",
        "array save __serialize")
    test:is(getmetatable(s.decode(s.encode(map))).__serialize, "map",
        "map save __serialize")

    -- gh-1095: `-128` is packed as `d1ff80` instead of `d080`
    test:is(#s.encode(0x7f), 1, "len(encode(0x7f))")
    test:is(#s.encode(0x80), 2, "len(encode(0x80))")
    test:is(#s.encode(0xff), 2, "len(encode(0xff))")
    test:is(#s.encode(0x100), 3, "len(encode(0x100))")
    test:is(#s.encode(0xffff), 3, "len(encode(0xffff))")
    test:is(#s.encode(0x10000), 5, "len(encode(0x10000))")
    test:is(#s.encode(0xffffffff), 5, "len(encode(0xffffffff))")
    test:is(#s.encode(0x100000000), 9, "len(encode(0x100000000))")
    test:is(#s.encode(-0x20), 1, "len(encode(-0x20))")
    test:is(#s.encode(-0x21), 2, "len(encode(-0x21))")
    test:is(#s.encode(-0x80), 2, "len(encode(-0x80))")
    test:is(#s.encode(-0x81), 3, "len(encode(-0x81))")
    test:is(#s.encode(-0x8000), 3, "len(encode(-0x8000))")
    test:is(#s.encode(-0x8001), 5, "len(encode(-0x8001))")
    test:is(#s.encode(-0x80000000), 5, "len(encode(-0x80000000))")
    test:is(#s.encode(-0x80000001), 9, "len(encode(-0x80000001))")

    --
    -- gh-4434: msgpackffi does not care about msgpack serializer
    -- configuration, but it should.
    --
    local function check_depth(depth_to_try)
        local t = nil
        for i = 1, depth_to_try do t = {t} end
        t = s.decode_unchecked(s.encode(t))
        local level = 0
        while t ~= nil do level = level + 1 t = t[1] end
        return level
    end
    local msgpack = require('msgpack')
    local deep_as_nil = msgpack.cfg.encode_deep_as_nil
    msgpack.cfg({encode_deep_as_nil = true})
    local max_depth = msgpack.cfg.encode_max_depth
    local result_depth = check_depth(max_depth + 5)
    test:is(result_depth, max_depth,
            "msgpackffi uses msgpack.cfg.encode_max_depth")

    msgpack.cfg({encode_max_depth = max_depth + 5})
    result_depth = check_depth(max_depth + 5)
    test:is(result_depth, max_depth + 5, "and uses it dynamically")

    -- Recursive tables are handled correctly.
    local level = 0
    local t = {}
    t[1] = t
    t = s.decode(s.encode(t))
    while t ~= nil do level = level + 1 t = t[1] end
    test:is(level, max_depth + 5, "recursive array")
    t = {}
    t.key = t
    t = s.decode(s.encode(t))
    level = 0
    while t ~= nil do level = level + 1 t = t.key end
    test:is(level, max_depth + 5, "recursive map")

    msgpack.cfg({encode_deep_as_nil = false})
    local ok = pcall(check_depth, max_depth + 6)
    test:ok(not ok, "exception is thrown when crop is not allowed")

    msgpack.cfg({encode_deep_as_nil = deep_as_nil,
                 encode_max_depth = max_depth})
end

tap.test("msgpackffi", function(test)
    local serializer = require('msgpackffi')
    test:plan(12)
    test:test("unsigned", common.test_unsigned, serializer)
    test:test("signed", common.test_signed, serializer)
    test:test("double", common.test_double, serializer)
    test:test("decimal", common.test_decimal, serializer)
    test:test("uuid", common.test_uuid, serializer)
    test:test("boolean", common.test_boolean, serializer)
    test:test("string", common.test_string, serializer)
    test:test("nil", common.test_nil, serializer)
    test:test("table", common.test_table, serializer, is_array, is_map)
    -- udata/cdata hooks are not implemented
    --test:test("ucdata", common.test_ucdata, serializer)
    test:test("offsets", test_offsets, serializer)
    test:test("other", test_other, serializer)
    test:test("decode_buffer", common.test_decode_buffer, serializer)
end)