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