diff --git a/lib/protox/merge_message.ex b/lib/protox/merge_message.ex index a5cfe2b7..07e7ca21 100644 --- a/lib/protox/merge_message.ex +++ b/lib/protox/merge_message.ex @@ -19,12 +19,12 @@ defmodule Protox.MergeMessage do - both are `nil`: `nil` is returned # Example - iex> r1 = %Protobuf2{a: 0, s: :ONE} - iex> r2 = %Protobuf2{a: nil, s: :TWO} + iex> r1 = %Protobuf2Message{a: 0, b: :ONE} + iex> r2 = %Protobuf2Message{a: nil, b: :TWO} iex> Protox.MergeMessage.merge(r1, r2) - %Protobuf2{a: 0, s: :TWO} + %Protobuf2Message{a: 0, b: :TWO} iex> Protox.MergeMessage.merge(r2, r1) - %Protobuf2{a: 0, s: :ONE} + %Protobuf2Message{a: 0, b: :ONE} """ @spec merge(struct() | nil, struct() | nil) :: struct() | nil def merge(nil, from), do: from diff --git a/test/protox/decode_test.exs b/test/protox/decode_test.exs index 47290943..37dd4e3a 100644 --- a/test/protox/decode_test.exs +++ b/test/protox/decode_test.exs @@ -1,7 +1,11 @@ defmodule Protox.DecodeTest do use ExUnit.Case - alias ProtobufTestMessages.Proto3.{NullHypothesisProto3, TestAllTypesProto3} + alias ProtobufTestMessages.Proto3.{ + NullHypothesisProto3, + TestAllTypesProto3, + TestAllTypesProto3.NestedMessage + } varint_of_max_string_size = Protox.String.max_size() @@ -10,173 +14,15 @@ defmodule Protox.DecodeTest do @success_tests [ { - "Sub.a", - <<8, 150, 1>>, - %Sub{a: 150, b: ""} + "Unknown fields", + <<186, 62, 4, 104, 101, 121, 33, 176, 62, 42>>, + %TestAllTypesProto3{__uf__: [{998, 0, <<42>>}, {999, 2, <<104, 101, 121, 33>>}]} }, - { - "Sub.a, repeated scalar, select last", - <<8, 150, 1, 8, 1, 8, 150, 1, 8, 2>>, - %Sub{a: 2, b: ""} - }, - { - "Sub.a, negative 64 bits", - <<8, 234, 254, 255, 255, 255, 255, 255, 255, 255, 1>>, - %Sub{a: -150, b: ""} - }, - { - "Sub.a, negative 32 bits", - <<8, 234, 254, 255, 255, 15>>, - %Sub{a: -150, b: ""} - }, - { - "Sub.b", - <<18, 7, 116, 101, 115, 116, 105, 110, 103>>, - %Sub{a: 0, b: "testing"} - }, - { - "Sub.b, empty", - <<18, 0>>, - %Sub{a: 0, b: ""} - }, - { - "Sub.a; Sub.b", - <<8, 150, 1, 18, 7, 116, 101, 115, 116, 105, 110, 103>>, - %Sub{a: 150, b: "testing"} - }, - { - "Sub.a; Sub.b; Sub.z", - <<8, 150, 1, 18, 7, 116, 101, 115, 116, 105, 110, 103, 136, 241, 4, 157, 156, 1>>, - %Sub{a: 150, b: "testing", z: -9999} - }, - { - "Sub.b; Sub.a", - <<18, 7, 116, 101, 115, 116, 105, 110, 103, 8, 150, 1>>, - %Sub{a: 150, b: "testing"} - }, - { - "Sub, unknown tag (double)", - <<8, 42, 25, 246, 40, 92, 143, 194, 53, 69, 64, 136, 241, 4, 83>>, - %Sub{ - a: 42, - b: "", - z: -42, - __uf__: [{3, 1, <<246, 40, 92, 143, 194, 53, 69, 64>>}] - } - }, - { - "Sub, unknown tag (embedded message)", - <<8, 42, 34, 0, 136, 241, 4, 83>>, - %Sub{a: 42, b: "", z: -42, __uf__: [{4, 2, <<>>}]} - }, - { - "Sub, unknown tag (string)", - <<8, 42, 42, 4, 121, 97, 121, 101, 136, 241, 4, 83>>, - %Sub{ - a: 42, - b: "", - z: -42, - __uf__: [{5, 2, <<121, 97, 121, 101>>}] - } - }, - { - "Sub, unknown tag (bytes)", - <<8, 142, 26, 82, 4, 104, 101, 121, 33, 136, 241, 4, 19>>, - %Sub{ - a: 3342, - b: "", - z: -10, - __uf__: [{10, 2, <<104, 101, 121, 33>>}] - } - }, - { - "Sub, unknown tag (varint)", - <<8, 142, 26, 82, 4, 104, 101, 121, 33, 88, 154, 5, 136, 241, 4, 19>>, - %Sub{ - a: 3342, - b: "", - z: -10, - __uf__: [{11, 0, <<154, 5>>}, {10, 2, <<104, 101, 121, 33>>}] - } - }, - { - "Sub, unknown tag (float)", - <<8, 142, 26, 82, 4, 104, 101, 121, 33, 88, 154, 5, 101, 236, 81, 5, 66, 136, 241, 4, 19>>, - %Sub{ - a: 3342, - b: "", - z: -10, - __uf__: [ - {12, 5, <<236, 81, 5, 66>>}, - {11, 0, <<154, 5>>}, - {10, 2, <<104, 101, 121, 33>>} - ] - } - }, - { - "Sub.c", - <<48, 212, 253, 255, 255, 255, 255, 255, 255, 255, 1>>, - %Sub{a: 0, b: "", c: -300} - }, - { - "Sub.d; Sub.e", - <<56, 133, 7, 64, 177, 3>>, - %Sub{a: 0, b: "", c: 0, d: 901, e: 433} - }, - { - "Sub.d, overflow values > MAX UINT32", - # <<128, 128, 128, 128, 32>> == 8589934592 - <<56, 128, 128, 128, 128, 32>>, - %Sub{d: 0} - }, - { - "Sub.f", - <<72, 213, 20>>, - %Sub{a: 0, b: "", c: 0, d: 0, e: 0, f: -1323} - }, - {"Sub.g", <<106, 16, 1, 0, 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [1, 18_446_744_073_709_551_614], - h: [], - i: [] - }}, { "Sub.g, not contiguous, should be concatenated", <<106, 8, 1, 0, 0, 0, 0, 0, 0, 0, 8, 150, 1, 106, 8, 254, 255, 255, 255, 255, 255, 255, 255>>, - %Sub{ - a: 150, - c: 0, - b: "", - d: 0, - e: 0, - f: 0, - g: [1, 18_446_744_073_709_551_614], - h: [], - i: [] - } - }, - { - "Sub.g; Sub.h; Sub.i", - <<106, 8, 0, 0, 0, 0, 0, 0, 0, 0, 114, 4, 255, 255, 255, 255, 122, 16, 154, 153, 153, 153, - 153, 153, 64, 64, 0, 0, 0, 0, 0, 0, 70, 192>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [0], - h: [-1], - i: [33.2, -44.0] - } + %Sub{a: 150, g: [1, 18_446_744_073_709_551_614]} }, { "Sub.i, infinity", @@ -197,124 +43,22 @@ defmodule Protox.DecodeTest do { "Sub.h", <<114, 8, 255, 255, 255, 255, 254, 255, 255, 255>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [-1, -2], - i: [] - } + %Sub{h: [-1, -2]} }, { "Sub.j, unpacked in definition", <<128, 1, 1, 128, 1, 2, 128, 1, 3>>, %Sub{j: [1, 2, 3]} }, - { - "Sub.n", - <<162, 1, 4, 1, 0, 0, 1>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - n: [true, false, false, true] - } - }, - { - "Sub.n (all false)", - <<162, 1, 4, 0, 0, 0, 0>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - n: [false, false, false, false] - } - }, - { - "Sub.o ", - <<170, 1, 3, 0, 1, 0>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - n: [], - o: [:FOO, :BAR, :FOO] - } - }, { "Sub.o (unknown entry) ", <<170, 1, 4, 0, 1, 0, 2>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - n: [], - o: [:FOO, :BAR, :FOO, 2] - } - }, - { - "Sub.p", - <<176, 1, 1, 176, 1, 0, 176, 1, 1, 176, 1, 0>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - n: [], - o: [], - p: [true, false, true, false] - } + %Sub{o: [:FOO, :BAR, :FOO, 2]} }, { "Sub.p, not contiguous, should be concatenated", <<176, 1, 1, 176, 1, 0, 8, 150, 1, 176, 1, 1, 176, 1, 0>>, - %Sub{ - a: 150, - c: 0, - b: "", - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - n: [], - o: [], - p: [true, false, true, false] - } + %Sub{a: 150, p: [true, false, true, false]} }, { "Sub.p, packed and unpacked, should be concatenated (1)", @@ -331,548 +75,154 @@ defmodule Protox.DecodeTest do { "Sub.q (unpacked in definition)", <<184, 1, 0, 184, 1, 1, 184, 1, 1, 184, 1, 0>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - n: [], - o: [], - p: [], - q: [:FOO, :BAR, :BAR, :FOO] - } + %Sub{q: [:FOO, :BAR, :BAR, :FOO]} }, { "Sub.q (unpacked in definition, with unknown values)", <<184, 1, 0, 184, 1, 1, 184, 1, 2, 184, 1, 0>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - n: [], - o: [], - p: [], - q: [:FOO, :BAR, 2, :FOO] - } + %Sub{q: [:FOO, :BAR, 2, :FOO]} }, { - "Sub.r, negative constant", - <<192, 1, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1>>, - %Sub{r: :NEG} - }, - { - "Sub.u", - <<218, 1, 6, 0, 1, 2, 3, 144, 78>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - u: [0, 1, 2, 3, 10_000] - } + "Repeated uint32", + <<138, 2, 6, 0, 1, 2, 3, 144, 78>>, + %TestAllTypesProto3{repeated_uint32: [0, 1, 2, 3, 10_000]} }, { - "Sub.w", - <<226, 1, 7, 0, 1, 4, 5, 160, 156, 1>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - w: [0, -1, 2, -3, 10_000] - } + "Repeated sint32", + <<154, 2, 7, 0, 1, 4, 5, 160, 156, 1>>, + %TestAllTypesProto3{repeated_sint32: [0, -1, 2, -3, 10_000]} }, { - "Sub.x", - <<234, 1, 24, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 2, 253, 255, 255, 255, 255, + "Repeated int64", + <<130, 2, 24, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 2, 253, 255, 255, 255, 255, 255, 255, 255, 255, 1, 144, 78>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - x: [0, -1, 2, -3, 10_000] - } + %TestAllTypesProto3{repeated_int64: [0, -1, 2, -3, 10_000]} }, { - "Sub.y", - <<242, 1, 6, 0, 1, 2, 3, 144, 78>>, - %Sub{ - a: 0, - b: "", - c: 0, - d: 0, - e: 0, - f: 0, - g: [], - h: [], - i: [], - y: [0, 1, 2, 3, 10_000] - } + "Repeated uint64", + <<146, 2, 6, 0, 1, 2, 3, 144, 78>>, + %TestAllTypesProto3{repeated_uint64: [0, 1, 2, 3, 10_000]} }, { - "Sub.z, overflow values > MAX UINT32", - # <<130, 128, etc. == 4294967298 - <<136, 241, 4, 130, 128, 128, 128, 16>>, - %Sub{z: 1} + "sint32, overflow values > MAX UINT32", + <<40, 130, 128, 128, 128, 16>>, + %TestAllTypesProto3{optional_sint32: 1} }, { - "Sub.zz, overflow values > MAX UINT64", - # <<130, 128, 128, 128, 1>> == 309485009821345068724781056 - <<144, 241, 4, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 32>>, - %Sub{zz: 0} - }, - { - "Sub.map1/map2", - <<202, 131, 6, 13, 9, 255, 255, 255, 255, 255, 255, 255, 255, 18, 2, 1, 2, 202, 131, 6, 13, - 9, 0, 0, 0, 0, 0, 0, 0, 0, 18, 2, 3, 4, 210, 131, 6, 13, 9, 0, 0, 0, 0, 0, 0, 0, 0, 18, 2, - 5, 6, 210, 131, 6, 13, 9, 1, 0, 0, 0, 0, 0, 0, 0, 18, 2, 7, 8>>, - %Sub{ - map1: %{-1 => <<1, 2>>, 0 => <<3, 4>>}, - map2: %{0 => <<5, 6>>, 1 => <<7, 8>>} - } + "sint64, overflow values > MAX UINT64", + <<48, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 32>>, + %TestAllTypesProto3{optional_sint64: 0} }, { - "Msg.msg_a", - <<218, 1, 7, 0, 2, 3, 6, 159, 156, 1>>, - %Msg{msg_a: [0, 1, -2, 3, -10_000]} + "Repeated sint64", + <<162, 2, 7, 0, 2, 3, 6, 159, 156, 1>>, + %TestAllTypesProto3{repeated_sint64: [0, 1, -2, 3, -10_000]} }, { - "Msg.msg_b", - <<226, 1, 20, 0, 0, 0, 0, 1, 0, 0, 0, 254, 255, 255, 255, 3, 0, 0, 0, 240, 216, 255, 255>>, - %Msg{msg_b: [0, 1, 4_294_967_294, 3, 4_294_957_296]} + "Repeated fixed32", + <<170, 2, 20, 0, 0, 0, 0, 1, 0, 0, 0, 254, 255, 255, 255, 3, 0, 0, 0, 240, 216, 255, 255>>, + %TestAllTypesProto3{repeated_fixed32: [0, 1, 4_294_967_294, 3, 4_294_957_296]} }, { - "Msg.msg_c", - <<234, 1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, + "Repeated sfixed64", + <<194, 2, 40, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255, 3, 0, 0, 0, 0, 0, 0, 0, 240, 216, 255, 255, 255, 255, 255, 255>>, - %Msg{msg_c: [0, 1, -2, 3, -10_000]} - }, - { - "Msg.msg_Sub.a", - <<26, 3, 8, 150, 1>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: %Sub{a: 150, b: ""}, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{} - } - }, - { - "Msg.msg_Sub.a; Msg.msg_Sub.b", - <<26, 12, 8, 150, 1, 18, 7, 116, 101, 115, 116, 105, 110, 103>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: %Sub{a: 150, b: "testing"}, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{} - } - }, - { - "Msg.msg_g", - <<34, 6, 3, 142, 2, 158, 167, 5>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [3, 270, 86_942], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{} - } - }, - { - "Msg.msg_g (unpacked)", - <<32, 1, 32, 2, 32, 3>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [1, 2, 3], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{} - } - }, - { - "Msg.msg_Sub.a; Msg.msg_Sub.b; Msg.msg_g", - <<26, 12, 8, 150, 1, 18, 7, 116, 101, 115, 116, 105, 110, 103, 34, 6, 3, 142, 2, 158, 167, - 5>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: %Sub{a: 150, b: "testing"}, - msg_g: [3, 270, 86_942], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{} - } + %TestAllTypesProto3{repeated_sfixed64: [0, 1, -2, 3, -10_000]} }, { - "Msg.msg_e", - <<16, 1>>, - %Msg{ - msg_d: :FOO, - msg_e: true, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{} - } + "Nested message", + <<146, 1, 3, 8, 150, 1>>, + %TestAllTypesProto3{optional_nested_message: %NestedMessage{a: 150}} }, { - "Msg.msg_h", - <<41, 246, 40, 92, 143, 194, 181, 64, 192>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: -33.42, - msg_i: [], - msg_j: [], - msg_k: %{} - } + "Repeated int32", + <<250, 1, 6, 3, 142, 2, 158, 167, 5>>, + %TestAllTypesProto3{repeated_int32: [3, 270, 86_942]} }, { - "Msg.msg_i", - <<50, 8, 0, 0, 128, 63, 0, 0, 0, 64>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [1.0, 2.0], - msg_j: [], - msg_k: %{} - } + "Double", + <<97, 246, 40, 92, 143, 194, 181, 64, 192>>, + %TestAllTypesProto3{optional_double: -33.42} }, { - "Msg.msg_i, infinity, -infinity", - <<50, 8, 0, 0, 0x80, 0x7F, 0, 0, 0x80, 0xFF>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [:infinity, :"-infinity"], - msg_j: [], - msg_k: %{} - } + "Repeated float", + <<202, 2, 8, 0, 0, 128, 63, 0, 0, 0, 64>>, + %TestAllTypesProto3{repeated_float: [1.0, 2.0]} }, { - "Msg.msg_i, nan", - <<50, 12, 0x01, 0, 0x80, 0x7F, 0, 0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [:nan, :nan, :nan], - msg_j: [], - msg_k: %{} - } - }, - {"Msg.msg_d", <<8, 1>>, - %Msg{ - msg_d: :BAR, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{} - }}, - { - "Msg.msg_d, unknown enum entry", - <<8, 2>>, - %Msg{ - msg_d: 2, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{} - } + "Repeated float, +infinity and -infinity", + <<202, 2, 8, 0, 0, 128, 127, 0, 0, 128, 255>>, + %TestAllTypesProto3{repeated_float: [:infinity, :"-infinity"]} }, { - "Msg.msg_j", - <<58, 3, 8, 146, 6, 58, 5, 18, 3, 102, 111, 111>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [%Sub{a: 786}, %Sub{b: "foo"}], - msg_k: %{} - } + "Repeated float, all NaN", + <<202, 2, 12, 0, 1, 129, 255, 0, 1, 129, 255, 0, 1, 129, 255>>, + %TestAllTypesProto3{repeated_float: [:nan, :nan, :nan]} }, { - "Msg.msg_k", - <<66, 7, 8, 2, 18, 3, 98, 97, 114, 66, 7, 8, 1, 18, 3, 102, 111, 111>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{1 => "foo", 2 => "bar"} - } - }, - { - "Msg.msg_k, duplicate key, last one is kept", - # 1: "f" "o" "o" 1: "b" "a" "r" - <<66, 7, 8, 1, 18, 3, 102, 111, 111, 66, 7, 8, 1, 18, 3, 98, 97, 114>>, - %Msg{ - msg_k: %{1 => "bar"} - } + "Map string -> string", + # | first | second + <<170, 4, 8, 10, 1, 97, 18, 3, 97, 97, 97, 170, 4, 8, 10, 1, 98, 18, 3, 98, 98, 98>>, + %TestAllTypesProto3{map_string_string: %{"a" => "aaa", "b" => "bbb"}} }, { - "Msg.msg_k, with unknown data in map entry", - <<66, 7, 8, 2, 18, 3, 98, 97, 114, 66, 10, 8, 1, 18, 3, 102, 111, 111, 26, 1, 102>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{1 => "foo", 2 => "bar"} - } + "Map string -> string, reversed", + # | second | first + <<170, 4, 8, 10, 1, 98, 18, 3, 98, 98, 98, 170, 4, 8, 10, 1, 97, 18, 3, 97, 97, 97>>, + %TestAllTypesProto3{map_string_string: %{"a" => "aaa", "b" => "bbb"}} }, { - "Msg.msg_k (reversed)", - <<66, 7, 8, 1, 18, 3, 102, 111, 111, 66, 7, 8, 2, 18, 3, 98, 97, 114>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{1 => "foo", 2 => "bar"} - } + "Map string -> string, duplicated key, last one is kep", + # "a" => "a" "a" "a" "a" => "b" "b" "b" + <<170, 4, 8, 10, 1, 97, 18, 3, 97, 97, 97, 170, 4, 8, 10, 1, 97, 18, 3, 98, 98, 98>>, + %TestAllTypesProto3{map_string_string: %{"a" => "bbb"}} }, { - "Msg.msg_k (reversed inside map entry)", - <<66, 7, 18, 3, 98, 97, 114, 8, 2, 66, 7, 8, 1, 18, 3, 102, 111, 111>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{1 => "foo", 2 => "bar"} - } + "Map string -> string, unknown data in a map entry", + # "a" => "a" "a" "a" | + # | unknown data + # | (tag=3,wire_type=2, length=1, data='!') + <<170, 4, 11, 10, 1, 97, 18, 3, 97, 97, 97, 26, 1, 33>>, + %TestAllTypesProto3{map_string_string: %{"a" => "aaa"}} }, { - "Msg.msg_k, missing key", - <<66, 5, 18, 3, 102, 111, 111>>, - %Msg{msg_k: %{0 => "foo"}} + "Map string -> string, reversed inside map entry", + # | value | key + <<170, 4, 8, 18, 3, 97, 97, 97, 10, 1, 97>>, + %TestAllTypesProto3{map_string_string: %{"a" => "aaa"}} }, { - "Msg.msg_k, missing value", - <<66, 2, 8, 1>>, - %Msg{msg_k: %{1 => ""}} + "Map int32 -> int32, missing key", + # Would have been <<194, 3, 4, 8, 0, 16, 42>> with the value in the map. + <<194, 3, 2, 16, 42>>, + %TestAllTypesProto3{map_int32_int32: %{0 => 42}} }, { - "Upper.msg_map, missing message value", - <<18, 5, 10, 3, 102, 111, 111>>, - %Upper{msg_map: %{"foo" => %Msg{}}} + "Map int32 -> int32, missing value", + # Would have been <<194, 3, 4, 8, 42, 16, 0>> with the value in the map. + <<194, 3, 2, 8, 42>>, + %TestAllTypesProto3{map_int32_int32: %{42 => 0}} }, { - "Msg.msg_l", - <<74, 14, 10, 3, 98, 97, 114, 17, 0, 0, 0, 0, 0, 0, 240, 63, 74, 14, 10, 3, 102, 111, 111, - 17, 154, 153, 153, 153, 153, 153, 69, 64>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{}, - msg_l: %{"bar" => 1.0, "foo" => 43.2} - } + "Map string -> nested message, missing value", + # Would have been <<186, 4, 7, 10, 3, 102, 111, 111, 18, 0>> with the value in the map. + <<186, 4, 5, 10, 3, 102, 111, 111>>, + %TestAllTypesProto3{map_string_nested_message: %{"foo" => %NestedMessage{}}} }, { - "Msg.msg_m, empty", - "", - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{}, - msg_l: %{}, - msg_m: nil - } - }, - { - "Msg.msg_m, string", - <<82, 3, 98, 97, 114>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{}, - msg_l: %{}, - msg_m: {:msg_n, "bar"} - } - }, - { - "Msg.msg_m, Sub", - <<90, 2, 8, 42>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{}, - msg_l: %{}, - msg_m: {:msg_o, %Sub{a: 42}} - } - }, - { - "Msg.msg_m, several fields on the wire, keep the last one", - <<90, 2, 8, 42, 82, 3, 98, 97, 114, 82, 3, 98, 97, 114>>, - %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{}, - msg_l: %{}, - msg_m: {:msg_n, "bar"} - } - }, - { - "Upper.msg.f", - <<10, 4, 26, 2, 8, 42>>, - %Upper{ - msg: %Msg{ - msg_d: :FOO, - msg_e: false, - msg_f: %Sub{a: 42}, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [] - } - } - }, - { - "Upper.msg_map", - <<18, 9, 10, 3, 102, 111, 111, 18, 2, 8, 1, 18, 9, 10, 3, 98, 97, 122, 18, 2, 16, 1>>, - %Upper{ - msg: nil, - msg_map: %{ - "foo" => %Msg{ - msg_d: :BAR, - msg_e: false, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{}, - msg_l: %{}, - msg_m: nil - }, - "baz" => %Msg{ - msg_d: :FOO, - msg_e: true, - msg_f: nil, - msg_g: [], - msg_h: 0.0, - msg_i: [], - msg_j: [], - msg_k: %{}, - msg_l: %{}, - msg_m: nil - } - } + "Map string -> nested message", + <<186, 4, 9, 10, 3, 98, 97, 114, 18, 2, 8, 43, 186, 4, 7, 10, 3, 102, 111, 111, 18, 0>>, + %TestAllTypesProto3{ + map_string_nested_message: %{"foo" => %NestedMessage{}, "bar" => %NestedMessage{a: 43}} } }, { - "Upper.empty", - <<26, 0>>, - %Upper{empty: %Empty{}} - }, - { - "Empty", + "Message without fields", <<>>, %NullHypothesisProto3{} }, { - "Empty, unknown fields", + "Message without fields and with unknown fields", <<8, 42, 25, 246, 40, 92, 143, 194, 53, 69, 64, 136, 241, 4, 83>>, %NullHypothesisProto3{ __uf__: [ @@ -882,50 +232,20 @@ defmodule Protox.DecodeTest do ] } }, - { - "Required fields (1)", - <<8, 0>>, - %Required{a: 0} - }, - { - "Required fields (2)", - <<8, 1>>, - %Required{a: 1} - }, { "No name clash for __uf__", <<>>, %NoUfNameClash{__uf__: 0} }, { - "Protobuf2, all fields unset", - <<>>, - %Protobuf2{a: nil, s: nil, t: nil} - }, - { - "Protobuf2.s", - <<200, 1, 2>>, - %Protobuf2{s: :TWO} + "Optional nested message", + <<146, 1, 2, 8, 42>>, + %TestAllTypesProto3{optional_nested_message: %NestedMessage{a: 42}} }, { - "Protobuf2.t, optional is nil when not set", + "Optional nested message set to nil", <<>>, - %Protobuf2{t: nil} - }, - { - "Protobuf2.a, repeated scalar, select last", - <<8, 150, 1, 8, 1>>, - %Protobuf2{a: 1} - }, - { - "Optional sub message", - <<10, 2, 8, 42>>, - %OptionalUpperMsg{sub: %OptionalSubMsg{a: 42}} - }, - { - "Optional sub message set to nil", - <<>>, - %OptionalUpperMsg{sub: nil} + %TestAllTypesProto3{optional_nested_message: nil} }, { "Empty string", @@ -1000,8 +320,9 @@ defmodule Protox.DecodeTest do }, { "invalid double", - <<41, 246, 40, 92, 143, 194, 181, 64>>, - Msg, + # Last byte `66` of float is missing. + <<93, 133, 235, 40>>, + TestAllTypesProto3, Protox.DecodingError }, { @@ -1125,15 +446,16 @@ defmodule Protox.DecodeTest do req2 = <<130, 7, 7, 18, 5, 16, 1, 200, 5, 1>> req = req1 <> req2 - m1 = CoRecursive.decode!(req1) - m2 = CoRecursive.decode!(req2) - m = CoRecursive.decode!(req) + m1 = TestAllTypesProto3.decode!(req1) + m2 = TestAllTypesProto3.decode!(req2) + m = TestAllTypesProto3.decode!(req) # https://developers.google.com/protocol-buffers/docs/encoding#optional assert m == Protox.MergeMessage.merge(m1, m2) end test "failure: missing required fields" do - assert {:error, %Protox.RequiredFieldsError{missing_fields: [:a]}} = Required.decode(<<>>) + assert {:error, %Protox.RequiredFieldsError{missing_fields: [:a]}} = + Protobuf2Required.decode(<<>>) end end diff --git a/test/protox/encode_test.exs b/test/protox/encode_test.exs index f61c7f1d..537df289 100644 --- a/test/protox/encode_test.exs +++ b/test/protox/encode_test.exs @@ -1,19 +1,19 @@ defmodule Protox.EncodeTest do use ExUnit.Case - alias ProtobufTestMessages.Proto3.TestAllTypesProto3 + alias ProtobufTestMessages.Proto3.{NullHypothesisProto3, TestAllTypesProto3} - test "Empty" do - assert %Sub{} |> Protox.encode!() |> :binary.list_to_bin() == <<>> + test "default TestAllTypesProto3" do + assert %TestAllTypesProto3{} |> Protox.encode!() |> :binary.list_to_bin() == <<>> end - test "Empty, with non throwing encode/1" do - {status, bytes} = Protox.encode(%Sub{}) + test "default TestAllTypesProto3, with non throwing encode/1" do + {status, bytes} = Protox.encode(%TestAllTypesProto3{}) assert {:ok, []} == {status, List.flatten(bytes)} end test "Empty, unknown fields are encoded back" do - msg = %Empty{ + msg = %NullHypothesisProto3{ __uf__: [ {1, 0, "*"}, {3, 1, <<246, 40, 92, 143, 194, 53, 69, 64>>}, @@ -326,41 +326,24 @@ defmodule Protox.EncodeTest do <<98, 4, 8, 1, 16, 1>> end - test "Msg.msg_q" do - assert %Msg{msg_q: nil} |> Protox.encode!() |> :binary.list_to_bin() == <<>> + test "A message with all fields unset serializes to <<>>" do + assert %TestAllTypesProto3{} |> Protox.encode!() |> :binary.list_to_bin() == <<>> end - test "Msg.msg_oneof_double" do - assert %Msg{msg_oneof_field: {:msg_oneof_double, 0}} - |> Protox.encode!() - |> :binary.list_to_bin() == <<177, 7, 0, 0, 0, 0, 0, 0, 0, 0>> - end - - test "Sub with all fields unset serializes to <<>>" do - assert %Empty{} |> Protox.encode!() |> :binary.list_to_bin() == <<>> - end - - test "Upper.empty" do - assert %Upper{empty: %Empty{}} |> Protox.encode!() |> :binary.list_to_bin() == - <<26, 0>> - end - - test "Protobuf2.a, unset" do - assert %Protobuf2{a: nil} |> Protox.encode!() |> :binary.list_to_bin() == <<>> + test "Protobuf2Message.a, unset" do + assert %Protobuf2Message{a: nil} |> Protox.encode!() |> :binary.list_to_bin() == <<>> end - test "Protobuf2.s, default" do - assert %Protobuf2{s: :TWO} |> Protox.encode!() |> :binary.list_to_bin() == - <<200, 1, 2>> + test "Protobuf2Message.b, default" do + assert %Protobuf2Message{b: :TWO} |> Protox.encode!() |> :binary.list_to_bin() == <<16, 2>> end - test "Protobuf2.s" do - assert %Protobuf2{s: :ONE} |> Protox.encode!() |> :binary.list_to_bin() == - <<200, 1, 1>> + test "Protobuf2Message.b" do + assert %Protobuf2Message{b: :ONE} |> Protox.encode!() |> :binary.list_to_bin() == <<16, 1>> end - test "Protobuf2.t, default is nil" do - assert %Protobuf2{t: nil} |> Protox.encode!() |> :binary.list_to_bin() == <<>> + test "Protobuf2Message.c, default is nil" do + assert %Protobuf2Message{c: nil} |> Protox.encode!() |> :binary.list_to_bin() == <<>> end test "Optional sub message" do @@ -373,9 +356,9 @@ defmodule Protox.EncodeTest do assert %OptionalUpperMsg{sub: nil} |> Protox.encode!() |> :binary.list_to_bin() == <<>> end - test "Required" do - assert %Required{a: 0} |> Protox.encode!() |> :binary.list_to_bin() == <<8, 0>> - assert %Required{a: 1} |> Protox.encode!() |> :binary.list_to_bin() == <<8, 1>> + test "Protobuf2Required" do + assert %Protobuf2Required{a: 0} |> Protox.encode!() |> :binary.list_to_bin() == <<8, 0>> + assert %Protobuf2Required{a: 1} |> Protox.encode!() |> :binary.list_to_bin() == <<8, 1>> end test "Do not output default double/float" do @@ -393,7 +376,7 @@ defmodule Protox.EncodeTest do test "Raise when required field is missing" do exception = assert_raise Protox.RequiredFieldsError, "Some required fields are not set: [:a]", fn -> - Protox.encode!(%Required{}) + Protox.encode!(%Protobuf2Required{}) end assert exception.missing_fields == [:a] @@ -401,14 +384,8 @@ defmodule Protox.EncodeTest do test "UTF-8 strings" do [ - { - "", - <<>> - }, - { - "hello, 漢字, 💻, 🏁, working fine", - <<114, 39, "hello, 漢字, 💻, 🏁, working fine">> - } + {"", <<>>}, + {"hello, 漢字, 💻, 🏁, working fine", <<114, 39, "hello, 漢字, 💻, 🏁, working fine">>} ] |> Enum.each(fn {string, expected_encoded_msg} -> assert %TestAllTypesProto3{optional_string: string} diff --git a/test/protox/merge_message_test.exs b/test/protox/merge_message_test.exs index 8132023d..4a388307 100644 --- a/test/protox/merge_message_test.exs +++ b/test/protox/merge_message_test.exs @@ -4,22 +4,22 @@ defmodule Protox.MergeMessageTest do doctest Protox.MergeMessage test "Protobuf 2, replace only set scalar fields" do - r1 = %Protobuf2{a: 0, s: :ONE} - r2 = %Protobuf2{a: nil, s: :TWO} - r3 = %Protobuf2{a: 1, s: nil} - - assert Protox.MergeMessage.merge(r1, r2) == %Protobuf2{a: 0, s: :TWO} - assert Protox.MergeMessage.merge(r1, r3) == %Protobuf2{a: 1, s: :ONE} - assert Protox.MergeMessage.merge(r2, r1) == %Protobuf2{a: 0, s: :ONE} - assert Protox.MergeMessage.merge(r3, r1) == %Protobuf2{a: 0, s: :ONE} + r1 = %Protobuf2Message{a: 0, b: :ONE} + r2 = %Protobuf2Message{a: nil, b: :TWO} + r3 = %Protobuf2Message{a: 1, b: nil} + + assert Protox.MergeMessage.merge(r1, r2) == %Protobuf2Message{a: 0, b: :TWO} + assert Protox.MergeMessage.merge(r1, r3) == %Protobuf2Message{a: 1, b: :ONE} + assert Protox.MergeMessage.merge(r2, r1) == %Protobuf2Message{a: 0, b: :ONE} + assert Protox.MergeMessage.merge(r3, r1) == %Protobuf2Message{a: 0, b: :ONE} end test "Replace scalar fields" do - r1 = %Required{a: 3, b: 4} - r2 = %Required{a: 5, b: 7} + r1 = %Protobuf2Required{a: 3, b: 4} + r2 = %Protobuf2Required{a: 5, b: 7} - assert Protox.MergeMessage.merge(r1, r2) == %Required{a: 5, b: 7} - assert Protox.MergeMessage.merge(r2, r1) == %Required{a: 3, b: 4} + assert Protox.MergeMessage.merge(r1, r2) == %Protobuf2Required{a: 5, b: 7} + assert Protox.MergeMessage.merge(r2, r1) == %Protobuf2Required{a: 3, b: 4} end test "Concatenate repeated fields" do diff --git a/test/samples/messages.proto b/test/samples/messages.proto index da396fdd..57fb69b5 100644 --- a/test/samples/messages.proto +++ b/test/samples/messages.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -import "protobuf2.proto"; +import "google/test_messages_proto3.proto"; enum E { option allow_alias = true; @@ -59,29 +59,10 @@ message Msg { Sub msg_o = 11; } map msg_p = 12; - Protobuf2 msg_q = 13; - oneof msg_oneof_field { - double msg_oneof_double = 118; - } } message Upper { Msg msg = 1; map msg_map = 2; - Empty empty = 3; - Required req = 4; -} - -message Empty { -} - -message CoRecursive { - oneof oneof_field { - NestedMessage oneof_nested_message = 112; - } -} - -message NestedMessage { - int32 a = 1; - CoRecursive corecursive = 2; + protobuf_test_messages.proto3.NullHypothesisProto3 empty = 3; } diff --git a/test/samples/protobuf2.proto b/test/samples/protobuf2.proto index ad6daab7..12272193 100644 --- a/test/samples/protobuf2.proto +++ b/test/samples/protobuf2.proto @@ -1,17 +1,17 @@ syntax = "proto2"; -enum F { +enum Protobuf2Enum { ONE = 1; TWO = 2; } -message Protobuf2 { +message Protobuf2Message { optional int32 a = 1; - optional F s = 25 [default = TWO]; - optional F t = 26; + optional Protobuf2Enum b = 2 [default = TWO]; + optional Protobuf2Enum c = 3; } -message Required { +message Protobuf2Required { required int32 a = 1; optional int32 b = 2; } diff --git a/test/support/messages.ex b/test/support/messages.ex index 50502364..d53abac3 100644 --- a/test/support/messages.ex +++ b/test/support/messages.ex @@ -10,7 +10,8 @@ defmodule Protox.Messages do "./test/samples/java_foo.proto", "./test/samples/messages.proto", "./test/samples/no_uf_name_clash.proto", - "./test/samples/optional.proto" + "./test/samples/optional.proto", + "./test/samples/protobuf2.proto" ] # To test the :keep_unknown_fields option.