2019-03-13 17:06:42 -07:00
package proto_test
import (
"bytes"
"fmt"
"reflect"
"testing"
protoV1 "github.com/golang/protobuf/proto"
"github.com/google/go-cmp/cmp"
2019-05-13 23:55:40 -07:00
"google.golang.org/protobuf/proto"
pref "google.golang.org/protobuf/reflect/protoreflect"
2019-04-07 12:43:10 -07:00
2019-05-13 23:55:40 -07:00
test3pb "google.golang.org/protobuf/internal/testprotos/test3"
2019-03-13 17:06:42 -07:00
)
func TestEncode ( t * testing . T ) {
for _ , test := range testProtos {
for _ , want := range test . decodeTo {
t . Run ( fmt . Sprintf ( "%s (%T)" , test . desc , want ) , func ( t * testing . T ) {
2019-04-03 12:17:24 -07:00
opts := proto . MarshalOptions {
AllowPartial : test . partial ,
}
wire , err := opts . Marshal ( want )
2019-03-13 17:06:42 -07:00
if err != nil {
2019-03-27 09:23:20 -07:00
t . Fatalf ( "Marshal error: %v\nMessage:\n%v" , err , marshalText ( want ) )
}
size := proto . Size ( want )
if size != len ( wire ) {
t . Errorf ( "Size and marshal disagree: Size(m)=%v; len(Marshal(m))=%v\nMessage:\n%v" , size , len ( wire ) , marshalText ( want ) )
2019-03-13 17:06:42 -07:00
}
2019-04-23 17:11:02 -07:00
got := newMessage ( want )
2019-04-03 12:17:24 -07:00
uopts := proto . UnmarshalOptions {
AllowPartial : test . partial ,
}
if err := uopts . Unmarshal ( wire , got ) ; err != nil {
2019-03-13 17:06:42 -07:00
t . Errorf ( "Unmarshal error: %v\nMessage:\n%v" , err , protoV1 . MarshalTextString ( want . ( protoV1 . Message ) ) )
return
}
2019-04-03 12:17:24 -07:00
if test . invalidExtensions {
// Equal doesn't work on messages containing invalid extension data.
return
}
2019-04-23 17:11:02 -07:00
if ! proto . Equal ( got , want ) {
2019-03-13 17:06:42 -07:00
t . Errorf ( "Unmarshal returned unexpected result; got:\n%v\nwant:\n%v" , protoV1 . MarshalTextString ( got . ( protoV1 . Message ) ) , protoV1 . MarshalTextString ( want . ( protoV1 . Message ) ) )
}
} )
}
}
}
func TestEncodeDeterministic ( t * testing . T ) {
for _ , test := range testProtos {
for _ , want := range test . decodeTo {
t . Run ( fmt . Sprintf ( "%s (%T)" , test . desc , want ) , func ( t * testing . T ) {
2019-04-03 12:17:24 -07:00
opts := proto . MarshalOptions {
Deterministic : true ,
AllowPartial : test . partial ,
}
wire , err := opts . Marshal ( want )
2019-03-13 17:06:42 -07:00
if err != nil {
2019-03-27 09:23:20 -07:00
t . Fatalf ( "Marshal error: %v\nMessage:\n%v" , err , marshalText ( want ) )
2019-03-13 17:06:42 -07:00
}
2019-04-03 12:17:24 -07:00
wire2 , err := opts . Marshal ( want )
2019-03-13 17:06:42 -07:00
if err != nil {
2019-03-27 09:23:20 -07:00
t . Fatalf ( "Marshal error: %v\nMessage:\n%v" , err , marshalText ( want ) )
2019-03-13 17:06:42 -07:00
}
if ! bytes . Equal ( wire , wire2 ) {
t . Fatalf ( "deterministic marshal returned varying results:\n%v" , cmp . Diff ( wire , wire2 ) )
}
2019-04-23 17:11:02 -07:00
got := newMessage ( want )
2019-04-03 12:17:24 -07:00
uopts := proto . UnmarshalOptions {
AllowPartial : test . partial ,
}
if err := uopts . Unmarshal ( wire , got ) ; err != nil {
2019-03-27 09:23:20 -07:00
t . Errorf ( "Unmarshal error: %v\nMessage:\n%v" , err , marshalText ( want ) )
2019-03-13 17:06:42 -07:00
return
}
2019-04-03 12:17:24 -07:00
if test . invalidExtensions {
// Equal doesn't work on messages containing invalid extension data.
return
}
2019-04-23 17:11:02 -07:00
if ! proto . Equal ( got , want ) {
2019-03-27 09:23:20 -07:00
t . Errorf ( "Unmarshal returned unexpected result; got:\n%v\nwant:\n%v" , marshalText ( got ) , marshalText ( want ) )
2019-03-13 17:06:42 -07:00
}
} )
}
}
}
2019-04-03 12:17:24 -07:00
2019-04-11 11:46:55 -07:00
func TestEncodeInvalidUTF8 ( t * testing . T ) {
for _ , test := range invalidUTF8TestProtos {
for _ , want := range test . decodeTo {
t . Run ( fmt . Sprintf ( "%s (%T)" , test . desc , want ) , func ( t * testing . T ) {
wire , err := proto . Marshal ( want )
if ! isErrInvalidUTF8 ( err ) {
t . Errorf ( "Marshal did not return expected error for invalid UTF8: %v\nMessage:\n%v" , err , marshalText ( want ) )
}
2019-04-23 17:11:02 -07:00
got := newMessage ( want )
2019-04-11 11:46:55 -07:00
if err := proto . Unmarshal ( wire , got ) ; ! isErrInvalidUTF8 ( err ) {
t . Errorf ( "Unmarshal error: %v\nMessage:\n%v" , err , marshalText ( want ) )
return
}
2019-04-23 17:11:02 -07:00
if ! proto . Equal ( got , want ) {
2019-04-11 11:46:55 -07:00
t . Errorf ( "Unmarshal returned unexpected result; got:\n%v\nwant:\n%v" , marshalText ( got ) , marshalText ( want ) )
}
} )
}
}
}
2019-04-03 12:17:24 -07:00
func TestEncodeRequiredFieldChecks ( t * testing . T ) {
for _ , test := range testProtos {
if ! test . partial {
continue
}
for _ , m := range test . decodeTo {
t . Run ( fmt . Sprintf ( "%s (%T)" , test . desc , m ) , func ( t * testing . T ) {
_ , err := proto . Marshal ( m )
if err == nil {
t . Fatalf ( "Marshal succeeded (want error)\nMessage:\n%v" , marshalText ( m ) )
}
} )
}
}
}
2019-04-07 12:43:10 -07:00
func TestMarshalAppend ( t * testing . T ) {
want := [ ] byte ( "prefix" )
got := append ( [ ] byte ( nil ) , want ... )
got , err := proto . MarshalOptions { } . MarshalAppend ( got , & test3pb . TestAllTypes {
OptionalString : "value" ,
} )
if err != nil {
t . Fatal ( err )
}
if ! bytes . HasPrefix ( got , want ) {
t . Fatalf ( "MarshalAppend modified prefix: got %v, want prefix %v" , got , want )
}
}
2019-04-23 17:11:02 -07:00
// newMessage returns a new message with the same type and extension fields as m.
func newMessage ( m proto . Message ) proto . Message {
n := reflect . New ( reflect . TypeOf ( m ) . Elem ( ) ) . Interface ( ) . ( proto . Message )
m . ProtoReflect ( ) . KnownFields ( ) . ExtensionTypes ( ) . Range ( func ( xt pref . ExtensionType ) bool {
n . ProtoReflect ( ) . KnownFields ( ) . ExtensionTypes ( ) . Register ( xt )
return true
} )
return n
}