~bigbes/tarantool

tarantool-protobuf

ref: 569bc3c9cbe68a88b744f3dd789421817fc6eeb0 tarantool-protobuf/test/any_fieldmask_test.lua -rw-r--r-- 6.9 KiB
569bc3c9 — Eugene Blikh fix(wire): cap the Lua-number varint fast path at 2^51 (x86_64 corruption) 2 months ago
                                                                                
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
-- Tests for google.protobuf.Any (with type registry) and FieldMask.
local t  = require('luatest')
local pb = require('pb')
local wkt = pb.wkt

local function hex(s)
    local out = {}
    for i = 1, #s do out[i] = string.format('%02x', s:byte(i)) end
    return table.concat(out)
end

-- ---------------------------------------------------------------------------
-- FieldMask
-- ---------------------------------------------------------------------------
local gf = t.group('fieldmask.wire')

gf.test_empty = function()
    t.assert_equals(wkt.FieldMask_encode({}), '')
    t.assert_equals(#wkt.FieldMask_decode(''), 0)
end

gf.test_paths_round_trip = function()
    local mask = {'user.email', 'user.address.city', 'enabled'}
    local enc = wkt.FieldMask_encode(mask)
    local dec = wkt.FieldMask_decode(enc)
    t.assert_equals(#dec, 3)
    t.assert_equals(dec[1], mask[1])
    t.assert_equals(dec[2], mask[2])
    t.assert_equals(dec[3], mask[3])
end

local gfj = t.group('fieldmask.json')
local hello = require('full.hello.hello_pb')

local function reparse(s) return require('json').decode(s) end

gfj.test_encode_canonical_camelcase = function()
    local enc = pb.json.encode(hello.Event_descriptor, {
        update_mask = {'user_id', 'is_admin', 'created_at'},
    })
    -- snake_case → lowerCamelCase, joined by commas.
    t.assert_equals(reparse(enc).updateMask, 'userId,isAdmin,createdAt')
end

gfj.test_decode_camelcase_to_snakecase = function()
    local back = pb.json.decode(hello.Event_descriptor,
        '{"updateMask": "userId,isAdmin"}')
    t.assert_equals(back.update_mask[1], 'user_id')
    t.assert_equals(back.update_mask[2], 'is_admin')
end

-- ---------------------------------------------------------------------------
-- Any
-- ---------------------------------------------------------------------------
local ga = t.group('any.wire')

ga.test_opaque_round_trip = function()
    local opaque = {
        type_url = 'type.googleapis.com/hello.Address',
        value    = '\x0a\x05hello',
    }
    local enc = wkt.Any_encode(opaque)
    local dec = wkt.Any_decode(enc)
    t.assert_equals(dec.type_url, opaque.type_url)
    t.assert_equals(dec.value, opaque.value)
end

ga.test_pack_unpack_via_registry = function()
    pb.register(hello.Address_descriptor)
    local boxed = pb.any.pack(hello.Address_descriptor,
                              {street = 'Main', city = 'X', zip = 1})
    t.assert_str_contains(boxed.type_url, 'hello.Address')
    -- value is the wire-encoded Address payload.
    local unpacked = pb.any.unpack(boxed)
    t.assert_equals(unpacked.street, 'Main')
    t.assert_equals(unpacked.city,   'X')
    t.assert_equals(unpacked.zip,    1)
end

ga.test_unpack_unregistered_errors = function()
    t.assert_error_msg_contains(
        'no descriptor for',
        function() pb.any.unpack({type_url = 'type.unknown/Foo', value = ''}) end)
end

ga.test_unpack_with_explicit_descriptor_overrides_registry = function()
    -- Even if not registered, an explicit descriptor lets unpack succeed.
    local boxed = pb.any.pack(hello.Address_descriptor, {street = 'S'})
    local unpacked = pb.any.unpack(boxed, hello.Address_descriptor)
    t.assert_equals(unpacked.street, 'S')
end

local gaj = t.group('any.json')

gaj.test_json_round_trip_with_registered_type = function()
    pb.register(hello.Address_descriptor)
    local e = {
        extension = pb.any.pack(hello.Address_descriptor,
                                {street = 'JSON St', zip = 7}),
    }
    local enc = pb.json.encode(hello.Event_descriptor, e)
    local obj = reparse(enc)
    -- Flat form: @type plus the Address fields.
    t.assert_equals(obj.extension['@type'],
                    'type.googleapis.com/hello.Address')
    t.assert_equals(obj.extension.street, 'JSON St')
    t.assert_equals(obj.extension.zip, 7)

    -- Decode reverses.
    local back = pb.json.decode(hello.Event_descriptor, enc)
    t.assert_str_contains(back.extension.type_url, 'hello.Address')
    local inner = pb.any.unpack(back.extension)
    t.assert_equals(inner.street, 'JSON St')
    t.assert_equals(inner.zip, 7)
end

gaj.test_json_opaque_fallback_when_type_unregistered = function()
    -- Untouched: even without registry knowledge the value field survives
    -- through a base64 round-trip.
    local opaque = {type_url = 'type.opaque/Foo', value = '\x01\x02\x03'}
    local enc = pb.json.encode(hello.Event_descriptor, {extension = opaque})
    local obj = reparse(enc)
    t.assert_equals(obj.extension['@type'], 'type.opaque/Foo')
    t.assert(obj.extension.value, 'value field present as base64')
    local back = pb.json.decode(hello.Event_descriptor, enc)
    t.assert_equals(back.extension.type_url, 'type.opaque/Foo')
    t.assert_equals(back.extension.value, '\x01\x02\x03')
end

gaj.test_json_opaque_value_base64_unwrapped = function()
    -- Same canonical-base64 rule as plain bytes fields: the Any opaque
    -- fallback must not emit MIME-style line wraps inside the JSON string.
    local opaque = {type_url = 'type.opaque/Big', value = string.rep('A', 64)}
    local enc = pb.json.encode(hello.Event_descriptor, {extension = opaque})
    t.assert_not_str_contains(enc, '\n')
    t.assert_not_str_contains(enc, '\\n')
    local back = pb.json.decode(hello.Event_descriptor, enc)
    t.assert_equals(back.extension.value, opaque.value)
end

-- ---------------------------------------------------------------------------
-- End-to-end: Event message round-trip with extension + update_mask.
-- ---------------------------------------------------------------------------
for _, mode in ipairs({'full', 'runtime'}) do
    local ge = t.group('any_fieldmask.event.' .. mode)
    local h = require(mode .. '.hello.hello_pb')

    ge.test_event_with_any_and_mask = function()
        pb.register(h.Address_descriptor)
        local e = {
            title       = 'wrapped',
            extension   = pb.any.pack(h.Address_descriptor,
                                      {street = 'A', city = 'B', zip = 5}),
            update_mask = {'title', 'extension'},
        }
        local dec = h.Event_decode(h.Event_encode(e))
        t.assert_equals(dec.title, 'wrapped')
        t.assert_str_contains(dec.extension.type_url, 'hello.Address')
        local inner = pb.any.unpack(dec.extension)
        t.assert_equals(inner.street, 'A')
        t.assert_equals(inner.zip, 5)
        t.assert_equals(#dec.update_mask, 2)
        t.assert_equals(dec.update_mask[1], 'title')
    end
end

local gp = t.group('any_fieldmask.parity')
local hello_full    = require('full.hello.hello_pb')
local hello_runtime = require('runtime.hello.hello_pb')

gp.test_bytes_match_across_modes = function()
    pb.register(hello_full.Address_descriptor)
    local e = {
        extension   = pb.any.pack(hello_full.Address_descriptor,
                                  {street = 'Same', zip = 9}),
        update_mask = {'a', 'b', 'c'},
    }
    t.assert_equals(hex(hello_full.Event_encode(e)),
                    hex(hello_runtime.Event_encode(e)))
end