~bigbes/tarantool

tarantool-protobuf

b1d9c7581bcc6b4f299155746dc04acc2330e78c — Eugene Blikh 3 months ago 39233ed
test: pin unknown-fields text-format conformance regressions

Adds eight tests under conformance.core mirroring the
Recommended.Proto3.ProtobufInput.*UnknownFields_*.TextFormatOutput tests
in the Google harness. Each sends the byte-exact upstream payload (field
IDs 1001..1011 from UnknownToTestAllTypes) through cmd/conformance/core
and pins current output, with the target assertion + needed runtime fix
documented in each failure message.

Two blockers surface:
  1. wire.skip_field rejects SGROUP/EGROUP (wire 3/4), so the four
     Group/Repeated tests fail at decode.
  2. pb.text.encode doesn't walk _unknown_fields, so the four *_Print
     tests serialize empty.

Lets us iterate on those fixes locally without the Docker round-trip.
1 files changed, 140 insertions(+), 0 deletions(-)

M test/conformance_test.lua
M test/conformance_test.lua => test/conformance_test.lua +140 -0
@@ 1166,6 1166,146 @@ core_g.test_json_double_integer_valued_emitted_without_decimal = function()
    t.assert_str_contains(resp.json_payload, '"optionalDouble":1')
end

-- =========================================================================
-- Unknown-field text-format regressions.
--
-- Mirrors the eight Recommended.Proto3.ProtobufInput.*UnknownFields_*.
-- TextFormatOutput tests in the Google harness so we can iterate on the
-- runtime without the Docker round-trip. Each test sends the *exact*
-- bytes the conformance suite sends, runs through cmd/conformance/core,
-- and asserts what we produce today plus the target our text encoder
-- should produce once unknown-field rendering / group skipping land.
--
-- Field numbers (from src/google/protobuf/test_messages_proto2.proto
-- `UnknownToTestAllTypes`, used to build the input payloads):
--   1001 optional_int32       1004 OptionalGroup (group)
--   1002 optional_string      1006 optional_bool
--   1003 nested_message (LEN) 1011 repeated_int32 (unpacked)
-- None of these IDs exist in TestAllTypesProto3 so the receiver sees
-- them as unknown fields.
--
-- The Google harness compares semantically via MessageDifferencer after
-- re-parsing our text output with AllowFieldNumber(true). It accepts any
-- text that round-trips to a message with the same field set, so
-- numeric field IDs (e.g. `1001: 123`) are the canonical rendering for
-- types unknown to the testee.
-- =========================================================================

local function pb_to_text(input)
    return decode_resp(core.handle_request(encode_req({
        protobuf_payload = input,
        requested_output_format = TEXT,
        message_type = PROTO3_NAME,
    })))
end

local function pb_to_text_print_unknowns(input)
    return decode_resp(core.handle_request(encode_req({
        protobuf_payload = input,
        requested_output_format = TEXT,
        message_type = PROTO3_NAME,
        print_unknown_fields = true,
    })))
end

-- Payload helpers — same bytes the upstream conformance suite produces.
local SCALAR_UNKNOWN  = '\xc8\x3e\x7b'                       -- field 1001 varint 123
                     .. '\xd2\x3e\x05hello'                  -- field 1002 LEN "hello"
                     .. '\xf0\x3e\x01'                       -- field 1006 varint 1 (bool)
local MESSAGE_UNKNOWN = '\xda\x3e\x02\x08\x6f'               -- field 1003 LEN {1:111}
local GROUP_UNKNOWN   = '\xe3\x3e\x08\xc1\x02\xe4\x3e'       -- field 1004 SGROUP {a:321} EGROUP
-- Repeated builds on Group then appends three repeated_int32 entries.
local REPEATED_UNKNOWN = GROUP_UNKNOWN
                      .. '\xd8\x3e\x01\xd8\x3e\x02\xd8\x3e\x03'  -- field 1011 varint 1,2,3

core_g.test_scalar_unknown_fields_drop = function()
    -- ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput
    -- print_unknown_fields=false → unknowns dropped → text empty.
    local resp = pb_to_text(SCALAR_UNKNOWN)
    t.assert_not(resp.parse_error, resp.parse_error)
    t.assert_not(resp.serialize_error, resp.serialize_error)
    t.assert_equals(resp.text_payload, '')
end

core_g.test_scalar_unknown_fields_print = function()
    -- ProtobufInput.ScalarUnknownFields_Print.TextFormatOutput
    -- TARGET: text_payload must round-trip to a message containing the
    -- three unknown fields. Canonical form is numeric IDs, e.g.
    --   1001: 123\n1002: "hello"\n1006: 1\n
    -- CURRENT: pb.text doesn't walk _unknown_fields, so output is empty.
    -- Pin current behavior; flip this assertion when the renderer lands.
    local resp = pb_to_text_print_unknowns(SCALAR_UNKNOWN)
    t.assert_not(resp.parse_error, resp.parse_error)
    t.assert_not(resp.serialize_error, resp.serialize_error)
    t.assert_equals(resp.text_payload, '',
        'current behavior pins empty output; ' ..
        'replace with assert_str_contains(...,"1001: 123") when ' ..
        'pb.text renders captured _unknown_fields')
end

core_g.test_message_unknown_fields_drop = function()
    -- ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput
    local resp = pb_to_text(MESSAGE_UNKNOWN)
    t.assert_not(resp.parse_error, resp.parse_error)
    t.assert_equals(resp.text_payload, '')
end

core_g.test_message_unknown_fields_print = function()
    -- ProtobufInput.MessageUnknownFields_Print.TextFormatOutput
    -- TARGET text:   1003 {\n  1: 111\n}\n
    -- CURRENT: pb.text drops _unknown_fields, so output is empty.
    local resp = pb_to_text_print_unknowns(MESSAGE_UNKNOWN)
    t.assert_not(resp.parse_error, resp.parse_error)
    t.assert_equals(resp.text_payload, '',
        'replace with target "1003 { 1: 111 }" rendering when ' ..
        'pb.text grows submessage unknown-field support')
end

core_g.test_group_unknown_fields_drop = function()
    -- ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput
    -- Wire types 3/4 (SGROUP/EGROUP) — proto3 must tolerate them as
    -- unknown groups. Our skip_field currently errors on wire 3, so the
    -- decoder reports parse_error before reaching the text encoder.
    -- TARGET: parse_error == nil, text_payload == ''.
    local resp = pb_to_text(GROUP_UNKNOWN)
    t.assert_not_equals(resp.parse_error, nil,
        'current: skip_field rejects SGROUP wire type 3. ' ..
        'Fix in runtime/pb/wire.lua to recursively skip until matching ' ..
        'EGROUP, then flip this to assert_not + text_payload == ""')
end

core_g.test_group_unknown_fields_print = function()
    -- ProtobufInput.GroupUnknownFields_Print.TextFormatOutput
    -- TARGET text:   1004 {\n  1: 321\n}\n  (groups render as submessages)
    -- CURRENT: blocked by same SGROUP-skip issue as the Drop variant.
    local resp = pb_to_text_print_unknowns(GROUP_UNKNOWN)
    t.assert_not_equals(resp.parse_error, nil,
        'blocked on SGROUP support in wire.skip_field; once decoder ' ..
        'accepts groups and pb.text renders unknowns, expect ' ..
        'text_payload containing "1004 {" and "1: 321"')
end

core_g.test_repeated_unknown_fields_drop = function()
    -- ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput
    -- Payload prepends a group, so the same SGROUP issue blocks decode.
    -- TARGET: parse_error == nil, text_payload == ''.
    local resp = pb_to_text(REPEATED_UNKNOWN)
    t.assert_not_equals(resp.parse_error, nil,
        'blocked on SGROUP-skip in wire.lua (group bytes come first)')
end

core_g.test_repeated_unknown_fields_print = function()
    -- ProtobufInput.RepeatedUnknownFields_Print.TextFormatOutput
    -- TARGET text:
    --   1004 {\n  1: 321\n}\n1011: 1\n1011: 2\n1011: 3\n
    -- CURRENT: blocked by SGROUP-skip, then by unknown-field rendering.
    local resp = pb_to_text_print_unknowns(REPEATED_UNKNOWN)
    t.assert_not_equals(resp.parse_error, nil,
        'two-stage fix: (1) accept SGROUP in wire.skip_field, ' ..
        '(2) render captured _unknown_fields from pb.text. ' ..
        'Then assert_str_contains for "1011: 1", "1011: 2", "1011: 3"')
end

-- ---------------------------------------------------------------------------
-- 2. Subprocess: stdin/stdout framing
-- ---------------------------------------------------------------------------