blob: 30722e05bb7170f3fd9012af03a7797d695f638d [file] [log] [blame]
Damien Neil99f24c32019-03-13 17:06:42 -07001package proto_test
2
3import (
4 "bytes"
5 "fmt"
6 "reflect"
7 "testing"
8
9 protoV1 "github.com/golang/protobuf/proto"
Damien Neil99f24c32019-03-13 17:06:42 -070010 "github.com/golang/protobuf/v2/proto"
11 "github.com/google/go-cmp/cmp"
Damien Neil3016b732019-04-07 12:43:10 -070012
13 test3pb "github.com/golang/protobuf/v2/internal/testprotos/test3"
Damien Neil99f24c32019-03-13 17:06:42 -070014)
15
16func TestEncode(t *testing.T) {
17 for _, test := range testProtos {
18 for _, want := range test.decodeTo {
19 t.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(t *testing.T) {
Damien Neil96c229a2019-04-03 12:17:24 -070020 opts := proto.MarshalOptions{
21 AllowPartial: test.partial,
22 }
23 wire, err := opts.Marshal(want)
Damien Neil99f24c32019-03-13 17:06:42 -070024 if err != nil {
Damien Neil61e93c72019-03-27 09:23:20 -070025 t.Fatalf("Marshal error: %v\nMessage:\n%v", err, marshalText(want))
26 }
27
28 size := proto.Size(want)
29 if size != len(wire) {
30 t.Errorf("Size and marshal disagree: Size(m)=%v; len(Marshal(m))=%v\nMessage:\n%v", size, len(wire), marshalText(want))
Damien Neil99f24c32019-03-13 17:06:42 -070031 }
32
33 got := reflect.New(reflect.TypeOf(want).Elem()).Interface().(proto.Message)
Damien Neil96c229a2019-04-03 12:17:24 -070034 uopts := proto.UnmarshalOptions{
35 AllowPartial: test.partial,
36 }
37 if err := uopts.Unmarshal(wire, got); err != nil {
Damien Neil99f24c32019-03-13 17:06:42 -070038 t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, protoV1.MarshalTextString(want.(protoV1.Message)))
39 return
40 }
41
Damien Neil96c229a2019-04-03 12:17:24 -070042 if test.invalidExtensions {
43 // Equal doesn't work on messages containing invalid extension data.
44 return
45 }
Damien Neil99f24c32019-03-13 17:06:42 -070046 if !protoV1.Equal(got.(protoV1.Message), want.(protoV1.Message)) {
47 t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", protoV1.MarshalTextString(got.(protoV1.Message)), protoV1.MarshalTextString(want.(protoV1.Message)))
48 }
49 })
50 }
51 }
52}
53
54func TestEncodeDeterministic(t *testing.T) {
55 for _, test := range testProtos {
56 for _, want := range test.decodeTo {
57 t.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(t *testing.T) {
Damien Neil96c229a2019-04-03 12:17:24 -070058 opts := proto.MarshalOptions{
59 Deterministic: true,
60 AllowPartial: test.partial,
61 }
62 wire, err := opts.Marshal(want)
Damien Neil99f24c32019-03-13 17:06:42 -070063 if err != nil {
Damien Neil61e93c72019-03-27 09:23:20 -070064 t.Fatalf("Marshal error: %v\nMessage:\n%v", err, marshalText(want))
Damien Neil99f24c32019-03-13 17:06:42 -070065 }
Damien Neil96c229a2019-04-03 12:17:24 -070066 wire2, err := opts.Marshal(want)
Damien Neil99f24c32019-03-13 17:06:42 -070067 if err != nil {
Damien Neil61e93c72019-03-27 09:23:20 -070068 t.Fatalf("Marshal error: %v\nMessage:\n%v", err, marshalText(want))
Damien Neil99f24c32019-03-13 17:06:42 -070069 }
Damien Neil99f24c32019-03-13 17:06:42 -070070 if !bytes.Equal(wire, wire2) {
71 t.Fatalf("deterministic marshal returned varying results:\n%v", cmp.Diff(wire, wire2))
72 }
73
74 got := reflect.New(reflect.TypeOf(want).Elem()).Interface().(proto.Message)
Damien Neil96c229a2019-04-03 12:17:24 -070075 uopts := proto.UnmarshalOptions{
76 AllowPartial: test.partial,
77 }
78 if err := uopts.Unmarshal(wire, got); err != nil {
Damien Neil61e93c72019-03-27 09:23:20 -070079 t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, marshalText(want))
Damien Neil99f24c32019-03-13 17:06:42 -070080 return
81 }
82
Damien Neil96c229a2019-04-03 12:17:24 -070083 if test.invalidExtensions {
84 // Equal doesn't work on messages containing invalid extension data.
85 return
86 }
Damien Neil99f24c32019-03-13 17:06:42 -070087 if !protoV1.Equal(got.(protoV1.Message), want.(protoV1.Message)) {
Damien Neil61e93c72019-03-27 09:23:20 -070088 t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", marshalText(got), marshalText(want))
Damien Neil99f24c32019-03-13 17:06:42 -070089 }
90 })
91 }
92 }
93}
Damien Neil96c229a2019-04-03 12:17:24 -070094
95func TestEncodeRequiredFieldChecks(t *testing.T) {
96 for _, test := range testProtos {
97 if !test.partial {
98 continue
99 }
100 for _, m := range test.decodeTo {
101 t.Run(fmt.Sprintf("%s (%T)", test.desc, m), func(t *testing.T) {
102 _, err := proto.Marshal(m)
103 if err == nil {
104 t.Fatalf("Marshal succeeded (want error)\nMessage:\n%v", marshalText(m))
105 }
106 })
107 }
108 }
109}
Damien Neil3016b732019-04-07 12:43:10 -0700110
111func TestMarshalAppend(t *testing.T) {
112 want := []byte("prefix")
113 got := append([]byte(nil), want...)
114 got, err := proto.MarshalOptions{}.MarshalAppend(got, &test3pb.TestAllTypes{
115 OptionalString: "value",
116 })
117 if err != nil {
118 t.Fatal(err)
119 }
120 if !bytes.HasPrefix(got, want) {
121 t.Fatalf("MarshalAppend modified prefix: got %v, want prefix %v", got, want)
122 }
123}