From 7f85750f4d9f90e1fd1c5fba40437ee0070dd7aa Mon Sep 17 00:00:00 2001 From: v0idpwn Date: Sat, 4 Jan 2025 19:48:15 -0300 Subject: [PATCH] Conformance: accept nulls for repeated and maps in JSON decoder --- lib/protobuf/json/decode.ex | 4 ++ .../protobuf/conformance_regressions_test.exs | 41 +++++++++++++------ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/lib/protobuf/json/decode.ex b/lib/protobuf/json/decode.ex index bea70faf..8b573ca7 100644 --- a/lib/protobuf/json/decode.ex +++ b/lib/protobuf/json/decode.ex @@ -278,6 +278,8 @@ defmodule Protobuf.JSON.Decode do end end + defp decode_map(_prop, nil), do: nil + defp decode_map(prop, bad_map), do: throw({:bad_map, prop.name_atom, bad_map}) defp decode_key(type, key, field) when is_binary(key) do @@ -301,6 +303,8 @@ defmodule Protobuf.JSON.Decode do for val <- value, do: decode_singular(prop, val) end + defp decode_repeated(_prop, nil), do: nil + defp decode_repeated(prop, value) do throw({:bad_repeated, prop.name_atom, value}) end diff --git a/test/protobuf/conformance_regressions_test.exs b/test/protobuf/conformance_regressions_test.exs index dc5e9921..8137822f 100644 --- a/test/protobuf/conformance_regressions_test.exs +++ b/test/protobuf/conformance_regressions_test.exs @@ -57,6 +57,35 @@ defmodule Protobuf.ConformanceRegressionsTest do end end + test "Required.Proto2.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.JsonOutput" do + mod = ProtobufTestMessages.Proto2.TestAllTypesProto2 + problematic_payload = <<194, 3, 0>> + assert %{map_int32_int32: %{0 => 0}} = mod.decode(problematic_payload) + end + + test "Required.Proto3.JsonInput.Int32FieldQuotedExponentialValue.JsonOutput" do + mod = ProtobufTestMessages.Proto3.TestAllTypesProto3 + problematic_payload = ~S({"optionalInt32": "1e5"}) + assert %{optional_int32: 100_000} = Protobuf.JSON.decode!(problematic_payload, mod) + end + + test "Required.Proto2.JsonInput.AllFieldAcceptNull.ProtobufOutput" do + mod = ProtobufTestMessages.Proto3.TestAllTypesProto3 + problematic_payload = ~S({ + "map_bool_bool": null, + "repeated_int32": null, + "fieldname1": null + }) + + assert %{ + map_bool_bool: map_bool_bool, + repeated_int32: [], + fieldname1: 0 + } = Protobuf.JSON.decode!(problematic_payload, mod) + + assert is_map(map_bool_bool) and map_size(map_bool_bool) == 0 + end + describe "proto2" do setup :url_to_message setup :decode_conformance_input @@ -83,18 +112,6 @@ defmodule Protobuf.ConformanceRegressionsTest do @describetag message_type: "protobuf_test_messages.proto3.TestAllTypesProto3" - test "Required.Proto2.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.JsonOutput" do - mod = ProtobufTestMessages.Proto2.TestAllTypesProto2 - problematic_payload = <<194, 3, 0>> - assert %{map_int32_int32: %{0 => 0}} = mod.decode(problematic_payload) - end - - test "Required.Proto3.JsonInput.Int32FieldQuotedExponentialValue.JsonOutput" do - mod = ProtobufTestMessages.Proto3.TestAllTypesProto3 - problematic_payload = ~S({"optionalInt32": "1e5"}) - assert %{optional_int32: 100_000} = Protobuf.JSON.decode!(problematic_payload, mod) - end - test "Recommended.Proto3.JsonInput.NullValueInOtherOneofNewFormat.Validator", %{message_mod: message_mod} do json = "{\"oneofNullValue\": null}"