...

Source file src/google.golang.org/protobuf/proto/methods_test.go

Documentation: google.golang.org/protobuf/proto

     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  
     9  package proto_test
    10  
    11  import (
    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  
    24  type selfMarshaler struct {
    25  	bytes []byte
    26  	err   error
    27  }
    28  
    29  func (m selfMarshaler) Reset()        {}
    30  func (m selfMarshaler) ProtoMessage() {}
    31  
    32  func (m selfMarshaler) String() string {
    33  	return fmt.Sprintf("selfMarshaler{bytes:%v, err:%v}", m.bytes, m.err)
    34  }
    35  
    36  func (m selfMarshaler) Marshal() ([]byte, error) {
    37  	return m.bytes, m.err
    38  }
    39  
    40  func (m *selfMarshaler) Unmarshal(b []byte) error {
    41  	m.bytes = b
    42  	return m.err
    43  }
    44  
    45  func 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  
    75  func 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  
    87  type descPanicSelfMarshaler struct{}
    88  
    89  const descPanicSelfMarshalerBytes = "bytes"
    90  
    91  func (m *descPanicSelfMarshaler) Reset()                      {}
    92  func (m *descPanicSelfMarshaler) ProtoMessage()               {}
    93  func (m *descPanicSelfMarshaler) Descriptor() ([]byte, []int) { panic("Descriptor method panics") }
    94  func (m *descPanicSelfMarshaler) String() string              { return "descPanicSelfMarshaler{}" }
    95  func (m *descPanicSelfMarshaler) Marshal() ([]byte, error) {
    96  	return []byte(descPanicSelfMarshalerBytes), nil
    97  }
    98  
    99  func 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  
   108  type descSelfMarshaler struct {
   109  	someField int // some non-generated field
   110  }
   111  
   112  const descSelfMarshalerBytes = "bytes"
   113  
   114  func (m *descSelfMarshaler) Reset()        {}
   115  func (m *descSelfMarshaler) ProtoMessage() {}
   116  func (m *descSelfMarshaler) Descriptor() ([]byte, []int) {
   117  	return ((*legacypb.Legacy)(nil)).GetF1().Descriptor()
   118  }
   119  func (m *descSelfMarshaler) String() string {
   120  	return "descSelfMarshaler{}"
   121  }
   122  func (m *descSelfMarshaler) Marshal() ([]byte, error) {
   123  	return []byte(descSelfMarshalerBytes), nil
   124  }
   125  
   126  func 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  
   135  func 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  
   161  type selfMerger struct {
   162  	src protoiface.MessageV1
   163  }
   164  
   165  func (*selfMerger) Reset()         {}
   166  func (*selfMerger) ProtoMessage()  {}
   167  func (*selfMerger) String() string { return "selfMerger{}" }
   168  func (m *selfMerger) Merge(src protoiface.MessageV1) {
   169  	m.src = src
   170  }
   171  
   172  func 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  

View as plain text