xref: /aosp_15_r20/external/golang-protobuf/proto/decode_test.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage proto_test
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"bytes"
9*1c12ee1eSDan Willemsen	"fmt"
10*1c12ee1eSDan Willemsen	"reflect"
11*1c12ee1eSDan Willemsen	"testing"
12*1c12ee1eSDan Willemsen
13*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/encoding/prototext"
14*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/proto"
15*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
16*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/testing/protopack"
17*1c12ee1eSDan Willemsen
18*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/errors"
19*1c12ee1eSDan Willemsen	testpb "google.golang.org/protobuf/internal/testprotos/test"
20*1c12ee1eSDan Willemsen	test3pb "google.golang.org/protobuf/internal/testprotos/test3"
21*1c12ee1eSDan Willemsen)
22*1c12ee1eSDan Willemsen
23*1c12ee1eSDan Willemsenfunc TestDecode(t *testing.T) {
24*1c12ee1eSDan Willemsen	for _, test := range testValidMessages {
25*1c12ee1eSDan Willemsen		if len(test.decodeTo) == 0 {
26*1c12ee1eSDan Willemsen			t.Errorf("%v: no test message types", test.desc)
27*1c12ee1eSDan Willemsen		}
28*1c12ee1eSDan Willemsen		for _, want := range test.decodeTo {
29*1c12ee1eSDan Willemsen			t.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(t *testing.T) {
30*1c12ee1eSDan Willemsen				opts := test.unmarshalOptions
31*1c12ee1eSDan Willemsen				opts.AllowPartial = test.partial
32*1c12ee1eSDan Willemsen				wire := append(([]byte)(nil), test.wire...)
33*1c12ee1eSDan Willemsen				got := reflect.New(reflect.TypeOf(want).Elem()).Interface().(proto.Message)
34*1c12ee1eSDan Willemsen				if err := opts.Unmarshal(wire, got); err != nil {
35*1c12ee1eSDan Willemsen					t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, prototext.Format(want))
36*1c12ee1eSDan Willemsen					return
37*1c12ee1eSDan Willemsen				}
38*1c12ee1eSDan Willemsen
39*1c12ee1eSDan Willemsen				// Aliasing check: Unmarshal shouldn't modify the original wire
40*1c12ee1eSDan Willemsen				// bytes, and modifying the original wire bytes shouldn't affect
41*1c12ee1eSDan Willemsen				// the unmarshaled message.
42*1c12ee1eSDan Willemsen				if !bytes.Equal(test.wire, wire) {
43*1c12ee1eSDan Willemsen					t.Errorf("Unmarshal unexpectedly modified its input")
44*1c12ee1eSDan Willemsen				}
45*1c12ee1eSDan Willemsen				for i := range wire {
46*1c12ee1eSDan Willemsen					wire[i] = 0
47*1c12ee1eSDan Willemsen				}
48*1c12ee1eSDan Willemsen				if !proto.Equal(got, want) && got.ProtoReflect().IsValid() && want.ProtoReflect().IsValid() {
49*1c12ee1eSDan Willemsen					t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", prototext.Format(got), prototext.Format(want))
50*1c12ee1eSDan Willemsen				}
51*1c12ee1eSDan Willemsen			})
52*1c12ee1eSDan Willemsen		}
53*1c12ee1eSDan Willemsen	}
54*1c12ee1eSDan Willemsen}
55*1c12ee1eSDan Willemsen
56*1c12ee1eSDan Willemsenfunc TestDecodeRequiredFieldChecks(t *testing.T) {
57*1c12ee1eSDan Willemsen	for _, test := range testValidMessages {
58*1c12ee1eSDan Willemsen		if !test.partial {
59*1c12ee1eSDan Willemsen			continue
60*1c12ee1eSDan Willemsen		}
61*1c12ee1eSDan Willemsen		for _, m := range test.decodeTo {
62*1c12ee1eSDan Willemsen			t.Run(fmt.Sprintf("%s (%T)", test.desc, m), func(t *testing.T) {
63*1c12ee1eSDan Willemsen				opts := test.unmarshalOptions
64*1c12ee1eSDan Willemsen				opts.AllowPartial = false
65*1c12ee1eSDan Willemsen				got := reflect.New(reflect.TypeOf(m).Elem()).Interface().(proto.Message)
66*1c12ee1eSDan Willemsen				if err := proto.Unmarshal(test.wire, got); err == nil {
67*1c12ee1eSDan Willemsen					t.Fatalf("Unmarshal succeeded (want error)\nMessage:\n%v", prototext.Format(got))
68*1c12ee1eSDan Willemsen				}
69*1c12ee1eSDan Willemsen			})
70*1c12ee1eSDan Willemsen		}
71*1c12ee1eSDan Willemsen	}
72*1c12ee1eSDan Willemsen}
73*1c12ee1eSDan Willemsen
74*1c12ee1eSDan Willemsenfunc TestDecodeInvalidMessages(t *testing.T) {
75*1c12ee1eSDan Willemsen	for _, test := range testInvalidMessages {
76*1c12ee1eSDan Willemsen		if len(test.decodeTo) == 0 {
77*1c12ee1eSDan Willemsen			t.Errorf("%v: no test message types", test.desc)
78*1c12ee1eSDan Willemsen		}
79*1c12ee1eSDan Willemsen		for _, want := range test.decodeTo {
80*1c12ee1eSDan Willemsen			t.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(t *testing.T) {
81*1c12ee1eSDan Willemsen				opts := test.unmarshalOptions
82*1c12ee1eSDan Willemsen				opts.AllowPartial = test.partial
83*1c12ee1eSDan Willemsen				got := want.ProtoReflect().New().Interface()
84*1c12ee1eSDan Willemsen				if err := opts.Unmarshal(test.wire, got); err == nil {
85*1c12ee1eSDan Willemsen					t.Errorf("Unmarshal unexpectedly succeeded\ninput bytes: [%x]\nMessage:\n%v", test.wire, prototext.Format(got))
86*1c12ee1eSDan Willemsen				} else if !errors.Is(err, proto.Error) {
87*1c12ee1eSDan Willemsen					t.Errorf("Unmarshal error is not a proto.Error: %v", err)
88*1c12ee1eSDan Willemsen				}
89*1c12ee1eSDan Willemsen			})
90*1c12ee1eSDan Willemsen		}
91*1c12ee1eSDan Willemsen	}
92*1c12ee1eSDan Willemsen}
93*1c12ee1eSDan Willemsen
94*1c12ee1eSDan Willemsenfunc TestDecodeZeroLengthBytes(t *testing.T) {
95*1c12ee1eSDan Willemsen	// Verify that proto3 bytes fields don't give the mistaken
96*1c12ee1eSDan Willemsen	// impression that they preserve presence.
97*1c12ee1eSDan Willemsen	wire := protopack.Message{
98*1c12ee1eSDan Willemsen		protopack.Tag{94, protopack.BytesType}, protopack.Bytes(nil),
99*1c12ee1eSDan Willemsen	}.Marshal()
100*1c12ee1eSDan Willemsen	m := &test3pb.TestAllTypes{}
101*1c12ee1eSDan Willemsen	if err := proto.Unmarshal(wire, m); err != nil {
102*1c12ee1eSDan Willemsen		t.Fatal(err)
103*1c12ee1eSDan Willemsen	}
104*1c12ee1eSDan Willemsen	if m.OptionalBytes != nil {
105*1c12ee1eSDan Willemsen		t.Errorf("unmarshal zero-length proto3 bytes field: got %v, want nil", m.OptionalBytes)
106*1c12ee1eSDan Willemsen	}
107*1c12ee1eSDan Willemsen}
108*1c12ee1eSDan Willemsen
109*1c12ee1eSDan Willemsenfunc TestDecodeOneofNilWrapper(t *testing.T) {
110*1c12ee1eSDan Willemsen	wire := protopack.Message{
111*1c12ee1eSDan Willemsen		protopack.Tag{111, protopack.VarintType}, protopack.Varint(1111),
112*1c12ee1eSDan Willemsen	}.Marshal()
113*1c12ee1eSDan Willemsen	m := &testpb.TestAllTypes{OneofField: (*testpb.TestAllTypes_OneofUint32)(nil)}
114*1c12ee1eSDan Willemsen	if err := proto.Unmarshal(wire, m); err != nil {
115*1c12ee1eSDan Willemsen		t.Fatal(err)
116*1c12ee1eSDan Willemsen	}
117*1c12ee1eSDan Willemsen	if got := m.GetOneofUint32(); got != 1111 {
118*1c12ee1eSDan Willemsen		t.Errorf("GetOneofUint32() = %v, want %v", got, 1111)
119*1c12ee1eSDan Willemsen	}
120*1c12ee1eSDan Willemsen}
121*1c12ee1eSDan Willemsen
122*1c12ee1eSDan Willemsenfunc TestDecodeEmptyBytes(t *testing.T) {
123*1c12ee1eSDan Willemsen	// There's really nothing wrong with a nil entry in a [][]byte,
124*1c12ee1eSDan Willemsen	// but we take care to produce non-nil []bytes for zero-length
125*1c12ee1eSDan Willemsen	// byte strings, so test for it.
126*1c12ee1eSDan Willemsen	m := &testpb.TestAllTypes{}
127*1c12ee1eSDan Willemsen	b := protopack.Message{
128*1c12ee1eSDan Willemsen		protopack.Tag{45, protopack.BytesType}, protopack.Bytes(nil),
129*1c12ee1eSDan Willemsen	}.Marshal()
130*1c12ee1eSDan Willemsen	if err := proto.Unmarshal(b, m); err != nil {
131*1c12ee1eSDan Willemsen		t.Fatal(err)
132*1c12ee1eSDan Willemsen	}
133*1c12ee1eSDan Willemsen	if m.RepeatedBytes[0] == nil {
134*1c12ee1eSDan Willemsen		t.Errorf("unmarshaling repeated bytes field containing zero-length value: Got nil bytes, want non-nil")
135*1c12ee1eSDan Willemsen	}
136*1c12ee1eSDan Willemsen}
137*1c12ee1eSDan Willemsen
138*1c12ee1eSDan Willemsenfunc build(m proto.Message, opts ...buildOpt) proto.Message {
139*1c12ee1eSDan Willemsen	for _, opt := range opts {
140*1c12ee1eSDan Willemsen		opt(m)
141*1c12ee1eSDan Willemsen	}
142*1c12ee1eSDan Willemsen	return m
143*1c12ee1eSDan Willemsen}
144*1c12ee1eSDan Willemsen
145*1c12ee1eSDan Willemsentype buildOpt func(proto.Message)
146*1c12ee1eSDan Willemsen
147*1c12ee1eSDan Willemsenfunc unknown(raw protoreflect.RawFields) buildOpt {
148*1c12ee1eSDan Willemsen	return func(m proto.Message) {
149*1c12ee1eSDan Willemsen		m.ProtoReflect().SetUnknown(raw)
150*1c12ee1eSDan Willemsen	}
151*1c12ee1eSDan Willemsen}
152*1c12ee1eSDan Willemsen
153*1c12ee1eSDan Willemsenfunc extend(desc protoreflect.ExtensionType, value interface{}) buildOpt {
154*1c12ee1eSDan Willemsen	return func(m proto.Message) {
155*1c12ee1eSDan Willemsen		proto.SetExtension(m, desc, value)
156*1c12ee1eSDan Willemsen	}
157*1c12ee1eSDan Willemsen}
158