protobuf-go/proto/methods_test.go
Damien Neil 47d5893acf internal/impl: support non-struct-pointer legacy message types
Support, to some limited degree, types which implement protoV1.Message
but which are not struct pointers. Our ability to work with these types
is largely limited to calling Marshal or Unmarshal methods, when
present.

Change-Id: Ie1b851d9e753e2b2cb189b17ffeefebe2d8b3a8f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/198237
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
2019-10-04 16:13:03 +00:00

75 lines
2.0 KiB
Go

// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The protoreflect tag disables fast-path methods, including legacy ones.
// +build !protoreflect
package proto_test
import (
"bytes"
"errors"
"fmt"
"testing"
"google.golang.org/protobuf/internal/impl"
"google.golang.org/protobuf/proto"
)
type selfMarshaler struct {
bytes []byte
err error
}
func (m selfMarshaler) Reset() {}
func (m selfMarshaler) ProtoMessage() {}
func (m selfMarshaler) String() string {
return fmt.Sprintf("selfMarshaler{bytes:%v, err:%v}", m.bytes, m.err)
}
func (m selfMarshaler) Marshal() ([]byte, error) {
return m.bytes, m.err
}
func (m *selfMarshaler) Unmarshal(b []byte) error {
m.bytes = b
return m.err
}
func TestLegacyMarshalMethod(t *testing.T) {
for _, test := range []selfMarshaler{
{bytes: []byte("marshal")},
{bytes: []byte("marshal"), err: errors.New("some error")},
} {
m := impl.Export{}.MessageOf(test).Interface()
b, err := proto.Marshal(m)
if err != test.err || !bytes.Equal(b, test.bytes) {
t.Errorf("proto.Marshal(%v) = %v, %v; want %v, %v", test, b, err, test.bytes, test.err)
}
if gotSize, wantSize := proto.Size(m), len(test.bytes); gotSize != wantSize {
t.Fatalf("proto.Size(%v) = %v, want %v", test, gotSize, wantSize)
}
prefix := []byte("prefix")
want := append(prefix, test.bytes...)
b, err = proto.MarshalOptions{}.MarshalAppend(prefix, m)
if err != test.err || !bytes.Equal(b, want) {
t.Errorf("MarshalAppend(%v, %v) = %v, %v; want %v, %v", prefix, test, b, err, test.bytes, test.err)
}
}
}
func TestLegacyUnmarshalMethod(t *testing.T) {
sm := &selfMarshaler{}
m := impl.Export{}.MessageOf(sm).Interface()
want := []byte("unmarshal")
if err := proto.Unmarshal(want, m); err != nil {
t.Fatalf("proto.Unmarshal(selfMarshaler{}) = %v, want nil", err)
}
if !bytes.Equal(sm.bytes, want) {
t.Fatalf("proto.Unmarshal(selfMarshaler{}): Marshal method not called")
}
}