blob: ee8d6f1670c14aa04e671449f302d2cf118fa962 [file] [log] [blame]
Damien Neil37ef6912019-09-25 16:51:15 -07001// 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// +build !protoreflect
7
8package proto_test
9
10import (
11 "bytes"
12 "errors"
13 "fmt"
14 "testing"
15
16 "google.golang.org/protobuf/internal/impl"
17 "google.golang.org/protobuf/proto"
Damien Neilc600d6c2020-01-21 15:00:33 -080018 "google.golang.org/protobuf/runtime/protoiface"
Damien Neil4151cae2019-12-09 14:31:23 -080019
20 legacypb "google.golang.org/protobuf/internal/testprotos/legacy"
Damien Neil37ef6912019-09-25 16:51:15 -070021)
22
23type selfMarshaler struct {
24 bytes []byte
25 err error
26}
27
28func (m selfMarshaler) Reset() {}
29func (m selfMarshaler) ProtoMessage() {}
30
31func (m selfMarshaler) String() string {
32 return fmt.Sprintf("selfMarshaler{bytes:%v, err:%v}", m.bytes, m.err)
33}
34
35func (m selfMarshaler) Marshal() ([]byte, error) {
36 return m.bytes, m.err
37}
38
39func (m *selfMarshaler) Unmarshal(b []byte) error {
40 m.bytes = b
41 return m.err
42}
43
44func TestLegacyMarshalMethod(t *testing.T) {
Damien Neil47d58932019-09-30 15:34:27 -070045 for _, test := range []selfMarshaler{
Damien Neil37ef6912019-09-25 16:51:15 -070046 {bytes: []byte("marshal")},
47 {bytes: []byte("marshal"), err: errors.New("some error")},
48 } {
49 m := impl.Export{}.MessageOf(test).Interface()
50 b, err := proto.Marshal(m)
51 if err != test.err || !bytes.Equal(b, test.bytes) {
52 t.Errorf("proto.Marshal(%v) = %v, %v; want %v, %v", test, b, err, test.bytes, test.err)
53 }
54 if gotSize, wantSize := proto.Size(m), len(test.bytes); gotSize != wantSize {
55 t.Fatalf("proto.Size(%v) = %v, want %v", test, gotSize, wantSize)
56 }
57
58 prefix := []byte("prefix")
59 want := append(prefix, test.bytes...)
60 b, err = proto.MarshalOptions{}.MarshalAppend(prefix, m)
61 if err != test.err || !bytes.Equal(b, want) {
62 t.Errorf("MarshalAppend(%v, %v) = %v, %v; want %v, %v", prefix, test, b, err, test.bytes, test.err)
63 }
Damien Neilc7f2bee2019-11-06 15:29:05 -080064
65 b, err = proto.MarshalOptions{
66 Deterministic: true,
67 }.MarshalAppend(nil, m)
68 if err != test.err || !bytes.Equal(b, test.bytes) {
69 t.Errorf("MarshalOptions{Deterministic:true}.MarshalAppend(nil, %v) = %v, %v; want %v, %v", test, b, err, test.bytes, test.err)
70 }
Damien Neil37ef6912019-09-25 16:51:15 -070071 }
72}
73
74func TestLegacyUnmarshalMethod(t *testing.T) {
75 sm := &selfMarshaler{}
76 m := impl.Export{}.MessageOf(sm).Interface()
77 want := []byte("unmarshal")
78 if err := proto.Unmarshal(want, m); err != nil {
79 t.Fatalf("proto.Unmarshal(selfMarshaler{}) = %v, want nil", err)
80 }
81 if !bytes.Equal(sm.bytes, want) {
82 t.Fatalf("proto.Unmarshal(selfMarshaler{}): Marshal method not called")
83 }
84}
Damien Neil16057752019-11-11 16:30:04 -080085
86type descPanicSelfMarshaler struct{}
87
88const descPanicSelfMarshalerBytes = "bytes"
89
Damien Neil4151cae2019-12-09 14:31:23 -080090func (m *descPanicSelfMarshaler) Reset() {}
91func (m *descPanicSelfMarshaler) ProtoMessage() {}
92func (m *descPanicSelfMarshaler) Descriptor() ([]byte, []int) { panic("Descriptor method panics") }
93func (m *descPanicSelfMarshaler) String() string { return "descPanicSelfMarshaler{}" }
94func (m *descPanicSelfMarshaler) Marshal() ([]byte, error) {
Damien Neil16057752019-11-11 16:30:04 -080095 return []byte(descPanicSelfMarshalerBytes), nil
96}
97
98func TestSelfMarshalerDescriptorPanics(t *testing.T) {
Damien Neil4151cae2019-12-09 14:31:23 -080099 m := &descPanicSelfMarshaler{}
Damien Neil16057752019-11-11 16:30:04 -0800100 got, err := proto.Marshal(impl.Export{}.MessageOf(m).Interface())
101 want := []byte(descPanicSelfMarshalerBytes)
102 if err != nil || !bytes.Equal(got, want) {
103 t.Fatalf("proto.Marshal(%v) = %v, %v; want %v, nil", m, got, err, want)
104 }
105}
Damien Neil4151cae2019-12-09 14:31:23 -0800106
107type descSelfMarshaler struct {
108 someField int // some non-generated field
109}
110
111const descSelfMarshalerBytes = "bytes"
112
113func (m *descSelfMarshaler) Reset() {}
114func (m *descSelfMarshaler) ProtoMessage() {}
115func (m *descSelfMarshaler) Descriptor() ([]byte, []int) {
116 return ((*legacypb.Legacy)(nil)).GetF1().Descriptor()
117}
118func (m *descSelfMarshaler) String() string {
119 return "descSelfMarshaler{}"
120}
121func (m *descSelfMarshaler) Marshal() ([]byte, error) {
122 return []byte(descSelfMarshalerBytes), nil
123}
124
125func TestSelfMarshalerWithDescriptor(t *testing.T) {
126 m := &descSelfMarshaler{}
127 got, err := proto.Marshal(impl.Export{}.MessageOf(m).Interface())
128 want := []byte(descSelfMarshalerBytes)
129 if err != nil || !bytes.Equal(got, want) {
130 t.Fatalf("proto.Marshal(%v) = %v, %v; want %v, nil", m, got, err, want)
131 }
132}
Damien Neilc600d6c2020-01-21 15:00:33 -0800133
134func TestDecodeFastIsInitialized(t *testing.T) {
135 for _, test := range testValidMessages {
136 if !test.checkFastInit {
137 continue
138 }
139 for _, message := range test.decodeTo {
140 t.Run(fmt.Sprintf("%s (%T)", test.desc, message), func(t *testing.T) {
141 m := message.ProtoReflect().New()
142 opts := proto.UnmarshalOptions{
143 AllowPartial: true,
144 }
145 out, err := opts.UnmarshalState(m.Interface(), protoiface.UnmarshalInput{
146 Buf: test.wire,
147 })
148 if err != nil {
149 t.Fatalf("Unmarshal error: %v", err)
150 }
151 if got, want := out.Initialized, !test.partial; got != want {
152 t.Errorf("out.Initialized = %v, want %v", got, want)
153 }
154 })
155 }
156 }
157}