~bigbes/tarantool

tarantool-protobuf

ref: 2df86386f587e8b84867c9f144bd76a801c3a9d6 tarantool-protobuf/test/c_runtime_wkt_test.lua -rw-r--r-- 6.1 KiB
2df86386 — Eugene Blikh beads: close drm (encode/decode B/op floor investigation) 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
-- Tests for bd-rmf / ra6 3k: WKT override-hook passthrough.
--
-- A plan whose descriptor carries desc.encode / desc.decode dispatches
-- straight to those overrides instead of walking fields. The Event
-- message exercises every WKT shape we ship — Timestamp, Duration,
-- Empty, the <T>Value wrappers, Struct, Value, ListValue, Any,
-- FieldMask — so byte-equality with mode=full proves the override is
-- live at both the top level and when nested as a sub-message field.
--
-- Acceptance per bd-rmf: hello.Event with WKT sub-messages round-trips
-- byte-equal to mode=full pure-Lua, runtime/pb/wkt.lua is unmodified.

local t = require('luatest')
local datetime = require('datetime')

local pb = require('pb')
local c_runtime = pb.c_runtime

local function skip_if_no_c()
    if c_runtime == nil then
        t.skip('PB_ENABLE_C not set or pb.c_runtime not available')
    end
end

local full_hello

for _, mode in ipairs({'full', 'runtime'}) do
    local g = t.group('c_runtime_wkt.' .. mode)
    local hello

    g.before_all(function()
        skip_if_no_c()
        hello = require(mode .. '.hello.hello_pb')
        full_hello = require('full.hello.hello_pb')
    end)

    g.before_each(skip_if_no_c)

    -- ---------- Top-level override dispatch ----------

    function g.test_timestamp_top_level_encode_decode()
        local plan = c_runtime.compile_plan(pb.wkt.Timestamp_descriptor)
        local dt = datetime.new({timestamp = 1700000000, nsec = 123})
        local c_bytes = c_runtime.encode(plan, dt)
        t.assert_equals(c_bytes, pb.wkt.Timestamp_encode(dt))
        local out = c_runtime.decode(plan, c_bytes)
        t.assert(datetime.is_datetime(out))
        t.assert_equals(out.epoch, 1700000000)
        t.assert_equals(out.nsec, 123)
    end

    function g.test_duration_top_level_round_trip()
        local plan = c_runtime.compile_plan(pb.wkt.Duration_descriptor)
        local v = {seconds = 7200, nanos = 500}
        local c_bytes = c_runtime.encode(plan, v)
        t.assert_equals(c_bytes, pb.wkt.Duration_encode(v))
        t.assert_equals(c_runtime.decode(plan, c_bytes),
                        pb.wkt.Duration_decode(c_bytes))
    end

    function g.test_empty_top_level_encode_is_zero_bytes()
        local plan = c_runtime.compile_plan(pb.wkt.Empty_descriptor)
        t.assert_equals(c_runtime.encode(plan, {}), '')
    end

    function g.test_int32value_wrapper_top_level()
        local plan = c_runtime.compile_plan(pb.wkt.Int32Value_descriptor)
        -- The wrapper accepts the bare scalar; presence is meaningful.
        t.assert_equals(c_runtime.encode(plan, 42),
                        pb.wkt.Int32Value_encode(42))
    end

    -- ---------- Nested override dispatch (sub-message field) ----------

    function g.test_event_with_timestamp_byte_equal()
        local plan = c_runtime.compile_plan(hello.Event_descriptor)
        local msg = {
            title = 'hi',
            created_at = datetime.new(
                {timestamp = 1700000000, nsec = 123456789}),
        }
        t.assert_equals(c_runtime.encode(plan, msg),
                        full_hello.Event_encode(msg))
    end

    function g.test_event_with_duration_and_empty_byte_equal()
        local plan = c_runtime.compile_plan(hello.Event_descriptor)
        local msg = {
            title = 'hi',
            duration = {seconds = 60, nanos = 0},
            ack = {},
        }
        t.assert_equals(c_runtime.encode(plan, msg),
                        full_hello.Event_encode(msg))
    end

    function g.test_event_with_wrappers_byte_equal()
        local plan = c_runtime.compile_plan(hello.Event_descriptor)
        local msg = {
            retry_count = 5,
            note = 'remember',
            is_admin = true,
        }
        t.assert_equals(c_runtime.encode(plan, msg),
                        full_hello.Event_encode(msg))
    end

    function g.test_event_with_wrapper_zero_preserved()
        local plan = c_runtime.compile_plan(hello.Event_descriptor)
        -- Wrappers preserve presence at zero — the override must still
        -- emit tag + len(0). A naive "skip default" path would lose it.
        local msg = {retry_count = 0}
        t.assert_equals(c_runtime.encode(plan, msg),
                        full_hello.Event_encode(msg))
    end

    function g.test_event_with_fieldmask_byte_equal()
        local plan = c_runtime.compile_plan(hello.Event_descriptor)
        local msg = {update_mask = {paths = {'foo', 'bar.baz'}}}
        t.assert_equals(c_runtime.encode(plan, msg),
                        full_hello.Event_encode(msg))
    end

    -- ---------- Round-trip parity through the C path ----------
    --
    -- Encode in C, decode in C, compare against mode=full's decode of
    -- the same wire bytes. Asserts the override decode wrapper hands
    -- back the same Lua representation the pure-Lua codec does.

    function g.test_event_round_trip_through_c()
        local plan = c_runtime.compile_plan(hello.Event_descriptor)
        local dt = datetime.new({timestamp = 42, nsec = 500})
        local msg = {
            title = 'x',
            created_at = dt,
            duration = {seconds = 1, nanos = 2},
            ack = {},
            retry_count = 7,
            note = 'hello',
            update_mask = {paths = {'a', 'b'}},
        }
        local bytes = c_runtime.encode(plan, msg)
        local c_dec = c_runtime.decode(plan, bytes)
        local lua_dec = full_hello.Event_decode(bytes)

        t.assert_equals(c_dec.title, lua_dec.title)
        t.assert(datetime.is_datetime(c_dec.created_at))
        t.assert_equals(c_dec.created_at.epoch, lua_dec.created_at.epoch)
        t.assert_equals(c_dec.created_at.nsec,  lua_dec.created_at.nsec)
        t.assert_equals(tonumber(c_dec.duration.seconds),
                        tonumber(lua_dec.duration.seconds))
        t.assert_equals(c_dec.duration.nanos, lua_dec.duration.nanos)
        t.assert_equals(type(c_dec.ack), 'table')
        t.assert_equals(c_dec.retry_count, lua_dec.retry_count)
        t.assert_equals(c_dec.note, lua_dec.note)
        t.assert_equals(c_dec.update_mask.paths, lua_dec.update_mask.paths)
    end
end