encode_test.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // Copyright 2019 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package proto_test
  5. import (
  6. "bytes"
  7. "fmt"
  8. "math"
  9. "reflect"
  10. "testing"
  11. "github.com/google/go-cmp/cmp"
  12. "google.golang.org/protobuf/encoding/prototext"
  13. "google.golang.org/protobuf/encoding/protowire"
  14. "google.golang.org/protobuf/proto"
  15. "google.golang.org/protobuf/reflect/protoreflect"
  16. "google.golang.org/protobuf/internal/errors"
  17. orderpb "google.golang.org/protobuf/internal/testprotos/order"
  18. testpb "google.golang.org/protobuf/internal/testprotos/test"
  19. test3pb "google.golang.org/protobuf/internal/testprotos/test3"
  20. )
  21. func TestEncode(t *testing.T) {
  22. for _, test := range testValidMessages {
  23. for _, want := range test.decodeTo {
  24. t.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(t *testing.T) {
  25. opts := proto.MarshalOptions{
  26. AllowPartial: test.partial,
  27. }
  28. wire, err := opts.Marshal(want)
  29. if err != nil {
  30. t.Fatalf("Marshal error: %v\nMessage:\n%v", err, prototext.Format(want))
  31. }
  32. size := proto.Size(want)
  33. if size != len(wire) {
  34. t.Errorf("Size and marshal disagree: Size(m)=%v; len(Marshal(m))=%v\nMessage:\n%v", size, len(wire), prototext.Format(want))
  35. }
  36. got := want.ProtoReflect().New().Interface()
  37. uopts := proto.UnmarshalOptions{
  38. AllowPartial: test.partial,
  39. }
  40. if err := uopts.Unmarshal(wire, got); err != nil {
  41. t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, prototext.Format(want))
  42. return
  43. }
  44. if !proto.Equal(got, want) && got.ProtoReflect().IsValid() && want.ProtoReflect().IsValid() {
  45. t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", prototext.Format(got), prototext.Format(want))
  46. }
  47. })
  48. }
  49. }
  50. }
  51. func TestEncodeDeterministic(t *testing.T) {
  52. for _, test := range testValidMessages {
  53. for _, want := range test.decodeTo {
  54. t.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(t *testing.T) {
  55. opts := proto.MarshalOptions{
  56. Deterministic: true,
  57. AllowPartial: test.partial,
  58. }
  59. wire, err := opts.Marshal(want)
  60. if err != nil {
  61. t.Fatalf("Marshal error: %v\nMessage:\n%v", err, prototext.Format(want))
  62. }
  63. wire2, err := opts.Marshal(want)
  64. if err != nil {
  65. t.Fatalf("Marshal error: %v\nMessage:\n%v", err, prototext.Format(want))
  66. }
  67. if !bytes.Equal(wire, wire2) {
  68. t.Fatalf("deterministic marshal returned varying results:\n%v", cmp.Diff(wire, wire2))
  69. }
  70. got := want.ProtoReflect().New().Interface()
  71. uopts := proto.UnmarshalOptions{
  72. AllowPartial: test.partial,
  73. }
  74. if err := uopts.Unmarshal(wire, got); err != nil {
  75. t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, prototext.Format(want))
  76. return
  77. }
  78. if !proto.Equal(got, want) && got.ProtoReflect().IsValid() && want.ProtoReflect().IsValid() {
  79. t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", prototext.Format(got), prototext.Format(want))
  80. }
  81. })
  82. }
  83. }
  84. }
  85. func TestEncodeRequiredFieldChecks(t *testing.T) {
  86. for _, test := range testValidMessages {
  87. if !test.partial {
  88. continue
  89. }
  90. for _, m := range test.decodeTo {
  91. t.Run(fmt.Sprintf("%s (%T)", test.desc, m), func(t *testing.T) {
  92. _, err := proto.Marshal(m)
  93. if err == nil {
  94. t.Fatalf("Marshal succeeded (want error)\nMessage:\n%v", prototext.Format(m))
  95. }
  96. })
  97. }
  98. }
  99. }
  100. func TestEncodeAppend(t *testing.T) {
  101. want := []byte("prefix")
  102. got := append([]byte(nil), want...)
  103. got, err := proto.MarshalOptions{}.MarshalAppend(got, &test3pb.TestAllTypes{
  104. SingularString: "value",
  105. })
  106. if err != nil {
  107. t.Fatal(err)
  108. }
  109. if !bytes.HasPrefix(got, want) {
  110. t.Fatalf("MarshalAppend modified prefix: got %v, want prefix %v", got, want)
  111. }
  112. }
  113. func TestEncodeInvalidMessages(t *testing.T) {
  114. for _, test := range testInvalidMessages {
  115. for _, m := range test.decodeTo {
  116. if !m.ProtoReflect().IsValid() {
  117. continue
  118. }
  119. t.Run(fmt.Sprintf("%s (%T)", test.desc, m), func(t *testing.T) {
  120. opts := proto.MarshalOptions{
  121. AllowPartial: test.partial,
  122. }
  123. got, err := opts.Marshal(m)
  124. if err == nil {
  125. t.Fatalf("Marshal unexpectedly succeeded\noutput bytes: [%x]\nMessage:\n%v", got, prototext.Format(m))
  126. }
  127. if !errors.Is(err, proto.Error) {
  128. t.Fatalf("Marshal error is not a proto.Error: %v", err)
  129. }
  130. })
  131. }
  132. }
  133. }
  134. func TestEncodeOneofNilWrapper(t *testing.T) {
  135. m := &testpb.TestAllTypes{OneofField: (*testpb.TestAllTypes_OneofUint32)(nil)}
  136. b, err := proto.Marshal(m)
  137. if err != nil {
  138. t.Fatal(err)
  139. }
  140. if len(b) > 0 {
  141. t.Errorf("Marshal return non-empty, want empty")
  142. }
  143. }
  144. func TestMarshalAppendAllocations(t *testing.T) {
  145. m := &test3pb.TestAllTypes{SingularInt32: 1}
  146. size := proto.Size(m)
  147. const count = 1000
  148. b := make([]byte, size)
  149. // AllocsPerRun returns an integral value.
  150. marshalAllocs := testing.AllocsPerRun(count, func() {
  151. _, err := proto.MarshalOptions{}.MarshalAppend(b[:0], m)
  152. if err != nil {
  153. t.Fatal(err)
  154. }
  155. })
  156. b = nil
  157. marshalAppendAllocs := testing.AllocsPerRun(count, func() {
  158. var err error
  159. b, err = proto.MarshalOptions{}.MarshalAppend(b, m)
  160. if err != nil {
  161. t.Fatal(err)
  162. }
  163. })
  164. if marshalAllocs != marshalAppendAllocs {
  165. t.Errorf("%v allocs/op when writing to a preallocated buffer", marshalAllocs)
  166. t.Errorf("%v allocs/op when repeatedly appending to a slice", marshalAppendAllocs)
  167. t.Errorf("expect amortized allocs/op to be identical")
  168. }
  169. }
  170. func TestEncodeOrder(t *testing.T) {
  171. // We make no guarantees about the stability of wire marshal output.
  172. // The order in which fields are marshaled may change over time.
  173. // If deterministic marshaling is not enabled, it may change over
  174. // successive calls to proto.Marshal in the same binary.
  175. //
  176. // Unfortunately, many users have come to rely on the specific current
  177. // wire marshal output. Perhaps someday we will choose to deliberately
  178. // change the marshal output; until that day comes, this test verifies
  179. // that we don't unintentionally change it.
  180. m := &orderpb.Message{
  181. Field_1: proto.String("one"),
  182. Field_2: proto.String("two"),
  183. Field_20: proto.String("twenty"),
  184. Oneof_1: &orderpb.Message_Field_10{"ten"},
  185. }
  186. proto.SetExtension(m, orderpb.E_Field_30, "thirty")
  187. proto.SetExtension(m, orderpb.E_Field_31, "thirty-one")
  188. proto.SetExtension(m, orderpb.E_Field_32, "thirty-two")
  189. want := []protoreflect.FieldNumber{
  190. 30, 31, 32, // extensions first, in number order
  191. 1, 2, 20, // non-extension, non-oneof in number order
  192. 10, // oneofs last, undefined order
  193. }
  194. // Test with deterministic serialization, since fields are not sorted without
  195. // it when -tags=protoreflect.
  196. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  197. if err != nil {
  198. t.Fatal(err)
  199. }
  200. var got []protoreflect.FieldNumber
  201. for len(b) > 0 {
  202. num, _, n := protowire.ConsumeField(b)
  203. if n < 0 {
  204. t.Fatal(protowire.ParseError(n))
  205. }
  206. b = b[n:]
  207. got = append(got, num)
  208. }
  209. if !reflect.DeepEqual(got, want) {
  210. t.Errorf("unexpected field marshal order:\ngot: %v\nwant: %v\nmessage:\n%v", got, want, m)
  211. }
  212. }
  213. func TestEncodeLarge(t *testing.T) {
  214. // Encode/decode a message large enough to overflow a 32-bit size cache.
  215. t.Skip("too slow and memory-hungry to run all the time")
  216. size := int64(math.MaxUint32 + 1)
  217. m := &testpb.TestAllTypes_NestedMessage{
  218. Corecursive: &testpb.TestAllTypes{
  219. OptionalBytes: make([]byte, size),
  220. },
  221. }
  222. b, err := proto.Marshal(m)
  223. if err != nil {
  224. t.Fatalf("Marshal: %v", err)
  225. }
  226. if got, want := len(b), proto.Size(m); got != want {
  227. t.Fatalf("Size(m) = %v, but len(Marshal(m)) = %v", got, want)
  228. }
  229. if err := proto.Unmarshal(b, m); err != nil {
  230. t.Fatalf("Unmarshal: %v", err)
  231. }
  232. if got, want := int64(len(m.Corecursive.OptionalBytes)), size; got != want {
  233. t.Errorf("after round-trip marshal, got len(m.OptionalBytes) = %v, want %v", got, want)
  234. }
  235. }
  236. // TestEncodeEmpty tests for boundary conditions when producing an empty output.
  237. // These tests are not necessarily a statement of proper behavior,
  238. // but exist to detect accidental changes in behavior.
  239. func TestEncodeEmpty(t *testing.T) {
  240. for _, m := range []proto.Message{nil, (*testpb.TestAllTypes)(nil), &testpb.TestAllTypes{}} {
  241. isValid := m != nil && m.ProtoReflect().IsValid()
  242. b, err := proto.Marshal(m)
  243. if err != nil {
  244. t.Errorf("proto.Marshal() = %v", err)
  245. }
  246. if isNil := b == nil; isNil == isValid {
  247. t.Errorf("proto.Marshal() == nil: %v, want %v", isNil, !isValid)
  248. }
  249. b, err = proto.MarshalOptions{}.Marshal(m)
  250. if err != nil {
  251. t.Errorf("proto.MarshalOptions{}.Marshal() = %v", err)
  252. }
  253. if isNil := b == nil; isNil == isValid {
  254. t.Errorf("proto.MarshalOptions{}.Marshal() = %v, want %v", isNil, !isValid)
  255. }
  256. }
  257. }