blob: 91019fa3693245ae4a1350dedd5d3577b6972f2b [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 Neil4151cae2019-12-09 14:31:23 -080018
19 legacypb "google.golang.org/protobuf/internal/testprotos/legacy"
Damien Neil37ef6912019-09-25 16:51:15 -070020)
21
22type selfMarshaler struct {
23 bytes []byte
24 err error
25}
26
27func (m selfMarshaler) Reset() {}
28func (m selfMarshaler) ProtoMessage() {}
29
30func (m selfMarshaler) String() string {
31 return fmt.Sprintf("selfMarshaler{bytes:%v, err:%v}", m.bytes, m.err)
32}
33
34func (m selfMarshaler) Marshal() ([]byte, error) {
35 return m.bytes, m.err
36}
37
38func (m *selfMarshaler) Unmarshal(b []byte) error {
39 m.bytes = b
40 return m.err
41}
42
43func TestLegacyMarshalMethod(t *testing.T) {
Damien Neil47d58932019-09-30 15:34:27 -070044 for _, test := range []selfMarshaler{
Damien Neil37ef6912019-09-25 16:51:15 -070045 {bytes: []byte("marshal")},
46 {bytes: []byte("marshal"), err: errors.New("some error")},
47 } {
48 m := impl.Export{}.MessageOf(test).Interface()
49 b, err := proto.Marshal(m)
50 if err != test.err || !bytes.Equal(b, test.bytes) {
51 t.Errorf("proto.Marshal(%v) = %v, %v; want %v, %v", test, b, err, test.bytes, test.err)
52 }
53 if gotSize, wantSize := proto.Size(m), len(test.bytes); gotSize != wantSize {
54 t.Fatalf("proto.Size(%v) = %v, want %v", test, gotSize, wantSize)
55 }
56
57 prefix := []byte("prefix")
58 want := append(prefix, test.bytes...)
59 b, err = proto.MarshalOptions{}.MarshalAppend(prefix, m)
60 if err != test.err || !bytes.Equal(b, want) {
61 t.Errorf("MarshalAppend(%v, %v) = %v, %v; want %v, %v", prefix, test, b, err, test.bytes, test.err)
62 }
Damien Neilc7f2bee2019-11-06 15:29:05 -080063
64 b, err = proto.MarshalOptions{
65 Deterministic: true,
66 }.MarshalAppend(nil, m)
67 if err != test.err || !bytes.Equal(b, test.bytes) {
68 t.Errorf("MarshalOptions{Deterministic:true}.MarshalAppend(nil, %v) = %v, %v; want %v, %v", test, b, err, test.bytes, test.err)
69 }
Damien Neil37ef6912019-09-25 16:51:15 -070070 }
71}
72
73func TestLegacyUnmarshalMethod(t *testing.T) {
74 sm := &selfMarshaler{}
75 m := impl.Export{}.MessageOf(sm).Interface()
76 want := []byte("unmarshal")
77 if err := proto.Unmarshal(want, m); err != nil {
78 t.Fatalf("proto.Unmarshal(selfMarshaler{}) = %v, want nil", err)
79 }
80 if !bytes.Equal(sm.bytes, want) {
81 t.Fatalf("proto.Unmarshal(selfMarshaler{}): Marshal method not called")
82 }
83}
Damien Neil16057752019-11-11 16:30:04 -080084
85type descPanicSelfMarshaler struct{}
86
87const descPanicSelfMarshalerBytes = "bytes"
88
Damien Neil4151cae2019-12-09 14:31:23 -080089func (m *descPanicSelfMarshaler) Reset() {}
90func (m *descPanicSelfMarshaler) ProtoMessage() {}
91func (m *descPanicSelfMarshaler) Descriptor() ([]byte, []int) { panic("Descriptor method panics") }
92func (m *descPanicSelfMarshaler) String() string { return "descPanicSelfMarshaler{}" }
93func (m *descPanicSelfMarshaler) Marshal() ([]byte, error) {
Damien Neil16057752019-11-11 16:30:04 -080094 return []byte(descPanicSelfMarshalerBytes), nil
95}
96
97func TestSelfMarshalerDescriptorPanics(t *testing.T) {
Damien Neil4151cae2019-12-09 14:31:23 -080098 m := &descPanicSelfMarshaler{}
Damien Neil16057752019-11-11 16:30:04 -080099 got, err := proto.Marshal(impl.Export{}.MessageOf(m).Interface())
100 want := []byte(descPanicSelfMarshalerBytes)
101 if err != nil || !bytes.Equal(got, want) {
102 t.Fatalf("proto.Marshal(%v) = %v, %v; want %v, nil", m, got, err, want)
103 }
104}
Damien Neil4151cae2019-12-09 14:31:23 -0800105
106type descSelfMarshaler struct {
107 someField int // some non-generated field
108}
109
110const descSelfMarshalerBytes = "bytes"
111
112func (m *descSelfMarshaler) Reset() {}
113func (m *descSelfMarshaler) ProtoMessage() {}
114func (m *descSelfMarshaler) Descriptor() ([]byte, []int) {
115 return ((*legacypb.Legacy)(nil)).GetF1().Descriptor()
116}
117func (m *descSelfMarshaler) String() string {
118 return "descSelfMarshaler{}"
119}
120func (m *descSelfMarshaler) Marshal() ([]byte, error) {
121 return []byte(descSelfMarshalerBytes), nil
122}
123
124func TestSelfMarshalerWithDescriptor(t *testing.T) {
125 m := &descSelfMarshaler{}
126 got, err := proto.Marshal(impl.Export{}.MessageOf(m).Interface())
127 want := []byte(descSelfMarshalerBytes)
128 if err != nil || !bytes.Equal(got, want) {
129 t.Fatalf("proto.Marshal(%v) = %v, %v; want %v, nil", m, got, err, want)
130 }
131}