xref: /aosp_15_r20/external/golang-protobuf/proto/methods_test.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
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
5// The protoreflect tag disables fast-path methods, including legacy ones.
6//go:build !protoreflect
7// +build !protoreflect
8
9package proto_test
10
11import (
12	"bytes"
13	"errors"
14	"fmt"
15	"testing"
16
17	"google.golang.org/protobuf/internal/impl"
18	"google.golang.org/protobuf/proto"
19	"google.golang.org/protobuf/runtime/protoiface"
20
21	legacypb "google.golang.org/protobuf/internal/testprotos/legacy"
22)
23
24type selfMarshaler struct {
25	bytes []byte
26	err   error
27}
28
29func (m selfMarshaler) Reset()        {}
30func (m selfMarshaler) ProtoMessage() {}
31
32func (m selfMarshaler) String() string {
33	return fmt.Sprintf("selfMarshaler{bytes:%v, err:%v}", m.bytes, m.err)
34}
35
36func (m selfMarshaler) Marshal() ([]byte, error) {
37	return m.bytes, m.err
38}
39
40func (m *selfMarshaler) Unmarshal(b []byte) error {
41	m.bytes = b
42	return m.err
43}
44
45func TestLegacyMarshalMethod(t *testing.T) {
46	for _, test := range []selfMarshaler{
47		{bytes: []byte("marshal")},
48		{bytes: []byte("marshal"), err: errors.New("some error")},
49	} {
50		m := impl.Export{}.MessageOf(test).Interface()
51		b, err := proto.Marshal(m)
52		if err != test.err || !bytes.Equal(b, test.bytes) {
53			t.Errorf("proto.Marshal(%v) = %v, %v; want %v, %v", test, b, err, test.bytes, test.err)
54		}
55		if gotSize, wantSize := proto.Size(m), len(test.bytes); gotSize != wantSize {
56			t.Fatalf("proto.Size(%v) = %v, want %v", test, gotSize, wantSize)
57		}
58
59		prefix := []byte("prefix")
60		want := append(prefix, test.bytes...)
61		b, err = proto.MarshalOptions{}.MarshalAppend(prefix, m)
62		if err != test.err || !bytes.Equal(b, want) {
63			t.Errorf("MarshalAppend(%v, %v) = %v, %v; want %v, %v", prefix, test, b, err, test.bytes, test.err)
64		}
65
66		b, err = proto.MarshalOptions{
67			Deterministic: true,
68		}.MarshalAppend(nil, m)
69		if err != test.err || !bytes.Equal(b, test.bytes) {
70			t.Errorf("MarshalOptions{Deterministic:true}.MarshalAppend(nil, %v) = %v, %v; want %v, %v", test, b, err, test.bytes, test.err)
71		}
72	}
73}
74
75func TestLegacyUnmarshalMethod(t *testing.T) {
76	sm := &selfMarshaler{}
77	m := impl.Export{}.MessageOf(sm).Interface()
78	want := []byte("unmarshal")
79	if err := proto.Unmarshal(want, m); err != nil {
80		t.Fatalf("proto.Unmarshal(selfMarshaler{}) = %v, want nil", err)
81	}
82	if !bytes.Equal(sm.bytes, want) {
83		t.Fatalf("proto.Unmarshal(selfMarshaler{}): Marshal method not called")
84	}
85}
86
87type descPanicSelfMarshaler struct{}
88
89const descPanicSelfMarshalerBytes = "bytes"
90
91func (m *descPanicSelfMarshaler) Reset()                      {}
92func (m *descPanicSelfMarshaler) ProtoMessage()               {}
93func (m *descPanicSelfMarshaler) Descriptor() ([]byte, []int) { panic("Descriptor method panics") }
94func (m *descPanicSelfMarshaler) String() string              { return "descPanicSelfMarshaler{}" }
95func (m *descPanicSelfMarshaler) Marshal() ([]byte, error) {
96	return []byte(descPanicSelfMarshalerBytes), nil
97}
98
99func TestSelfMarshalerDescriptorPanics(t *testing.T) {
100	m := &descPanicSelfMarshaler{}
101	got, err := proto.Marshal(impl.Export{}.MessageOf(m).Interface())
102	want := []byte(descPanicSelfMarshalerBytes)
103	if err != nil || !bytes.Equal(got, want) {
104		t.Fatalf("proto.Marshal(%v) = %v, %v; want %v, nil", m, got, err, want)
105	}
106}
107
108type descSelfMarshaler struct {
109	someField int // some non-generated field
110}
111
112const descSelfMarshalerBytes = "bytes"
113
114func (m *descSelfMarshaler) Reset()        {}
115func (m *descSelfMarshaler) ProtoMessage() {}
116func (m *descSelfMarshaler) Descriptor() ([]byte, []int) {
117	return ((*legacypb.Legacy)(nil)).GetF1().Descriptor()
118}
119func (m *descSelfMarshaler) String() string {
120	return "descSelfMarshaler{}"
121}
122func (m *descSelfMarshaler) Marshal() ([]byte, error) {
123	return []byte(descSelfMarshalerBytes), nil
124}
125
126func TestSelfMarshalerWithDescriptor(t *testing.T) {
127	m := &descSelfMarshaler{}
128	got, err := proto.Marshal(impl.Export{}.MessageOf(m).Interface())
129	want := []byte(descSelfMarshalerBytes)
130	if err != nil || !bytes.Equal(got, want) {
131		t.Fatalf("proto.Marshal(%v) = %v, %v; want %v, nil", m, got, err, want)
132	}
133}
134
135func TestDecodeFastCheckInitialized(t *testing.T) {
136	for _, test := range testValidMessages {
137		if !test.checkFastInit {
138			continue
139		}
140		for _, message := range test.decodeTo {
141			t.Run(fmt.Sprintf("%s (%T)", test.desc, message), func(t *testing.T) {
142				m := message.ProtoReflect().New()
143				opts := proto.UnmarshalOptions{
144					AllowPartial: true,
145				}
146				out, err := opts.UnmarshalState(protoiface.UnmarshalInput{
147					Buf:     test.wire,
148					Message: m,
149				})
150				if err != nil {
151					t.Fatalf("Unmarshal error: %v", err)
152				}
153				if got, want := (out.Flags&protoiface.UnmarshalInitialized != 0), !test.partial; got != want {
154					t.Errorf("out.Initialized = %v, want %v", got, want)
155				}
156			})
157		}
158	}
159}
160
161type selfMerger struct {
162	src protoiface.MessageV1
163}
164
165func (*selfMerger) Reset()         {}
166func (*selfMerger) ProtoMessage()  {}
167func (*selfMerger) String() string { return "selfMerger{}" }
168func (m *selfMerger) Merge(src protoiface.MessageV1) {
169	m.src = src
170}
171
172func TestLegacyMergeMethod(t *testing.T) {
173	src := &selfMerger{}
174	dst := &selfMerger{}
175	proto.Merge(
176		impl.Export{}.MessageOf(dst).Interface(),
177		impl.Export{}.MessageOf(src).Interface(),
178	)
179	if got, want := dst.src, src; got != want {
180		t.Errorf("Merge(dst, src): want dst.src = src, got %v", got)
181	}
182	if got := src.src; got != nil {
183		t.Errorf("Merge(dst, src): want src.src = nil, got %v", got)
184	}
185}
186