github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/protobuf/proto/extensions_test.go (about)

     1  // Go support for Protocol Buffers - Google's data interchange format
     2  //
     3  // Copyright 2014 The Go Authors.  All rights reserved.
     4  // https://yougam/libraries/golang/protobuf
     5  //
     6  // Redistribution and use in source and binary forms, with or without
     7  // modification, are permitted provided that the following conditions are
     8  // met:
     9  //
    10  //     * Redistributions of source code must retain the above copyright
    11  // notice, this list of conditions and the following disclaimer.
    12  //     * Redistributions in binary form must reproduce the above
    13  // copyright notice, this list of conditions and the following disclaimer
    14  // in the documentation and/or other materials provided with the
    15  // distribution.
    16  //     * Neither the name of Google Inc. nor the names of its
    17  // contributors may be used to endorse or promote products derived from
    18  // this software without specific prior written permission.
    19  //
    20  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    24  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    25  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    26  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    27  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    28  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    29  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    30  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  
    32  package proto_test
    33  
    34  import (
    35  	"bytes"
    36  	"fmt"
    37  	"reflect"
    38  	"testing"
    39  
    40  	"github.com/insionng/yougam/libraries/golang/protobuf/proto"
    41  	pb "github.com/insionng/yougam/libraries/golang/protobuf/proto/testdata"
    42  )
    43  
    44  func TestGetExtensionsWithMissingExtensions(t *testing.T) {
    45  	msg := &pb.MyMessage{}
    46  	ext1 := &pb.Ext{}
    47  	if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil {
    48  		t.Fatalf("Could not set ext1: %s", ext1)
    49  	}
    50  	exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{
    51  		pb.E_Ext_More,
    52  		pb.E_Ext_Text,
    53  	})
    54  	if err != nil {
    55  		t.Fatalf("GetExtensions() failed: %s", err)
    56  	}
    57  	if exts[0] != ext1 {
    58  		t.Errorf("ext1 not in returned extensions: %T %v", exts[0], exts[0])
    59  	}
    60  	if exts[1] != nil {
    61  		t.Errorf("ext2 in returned extensions: %T %v", exts[1], exts[1])
    62  	}
    63  }
    64  
    65  func TestGetExtensionStability(t *testing.T) {
    66  	check := func(m *pb.MyMessage) bool {
    67  		ext1, err := proto.GetExtension(m, pb.E_Ext_More)
    68  		if err != nil {
    69  			t.Fatalf("GetExtension() failed: %s", err)
    70  		}
    71  		ext2, err := proto.GetExtension(m, pb.E_Ext_More)
    72  		if err != nil {
    73  			t.Fatalf("GetExtension() failed: %s", err)
    74  		}
    75  		return ext1 == ext2
    76  	}
    77  	msg := &pb.MyMessage{Count: proto.Int32(4)}
    78  	ext0 := &pb.Ext{}
    79  	if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil {
    80  		t.Fatalf("Could not set ext1: %s", ext0)
    81  	}
    82  	if !check(msg) {
    83  		t.Errorf("GetExtension() not stable before marshaling")
    84  	}
    85  	bb, err := proto.Marshal(msg)
    86  	if err != nil {
    87  		t.Fatalf("Marshal() failed: %s", err)
    88  	}
    89  	msg1 := &pb.MyMessage{}
    90  	err = proto.Unmarshal(bb, msg1)
    91  	if err != nil {
    92  		t.Fatalf("Unmarshal() failed: %s", err)
    93  	}
    94  	if !check(msg1) {
    95  		t.Errorf("GetExtension() not stable after unmarshaling")
    96  	}
    97  }
    98  
    99  func TestGetExtensionDefaults(t *testing.T) {
   100  	var setFloat64 float64 = 1
   101  	var setFloat32 float32 = 2
   102  	var setInt32 int32 = 3
   103  	var setInt64 int64 = 4
   104  	var setUint32 uint32 = 5
   105  	var setUint64 uint64 = 6
   106  	var setBool = true
   107  	var setBool2 = false
   108  	var setString = "Goodnight string"
   109  	var setBytes = []byte("Goodnight bytes")
   110  	var setEnum = pb.DefaultsMessage_TWO
   111  
   112  	type testcase struct {
   113  		ext  *proto.ExtensionDesc // Extension we are testing.
   114  		want interface{}          // Expected value of extension, or nil (meaning that GetExtension will fail).
   115  		def  interface{}          // Expected value of extension after ClearExtension().
   116  	}
   117  	tests := []testcase{
   118  		{pb.E_NoDefaultDouble, setFloat64, nil},
   119  		{pb.E_NoDefaultFloat, setFloat32, nil},
   120  		{pb.E_NoDefaultInt32, setInt32, nil},
   121  		{pb.E_NoDefaultInt64, setInt64, nil},
   122  		{pb.E_NoDefaultUint32, setUint32, nil},
   123  		{pb.E_NoDefaultUint64, setUint64, nil},
   124  		{pb.E_NoDefaultSint32, setInt32, nil},
   125  		{pb.E_NoDefaultSint64, setInt64, nil},
   126  		{pb.E_NoDefaultFixed32, setUint32, nil},
   127  		{pb.E_NoDefaultFixed64, setUint64, nil},
   128  		{pb.E_NoDefaultSfixed32, setInt32, nil},
   129  		{pb.E_NoDefaultSfixed64, setInt64, nil},
   130  		{pb.E_NoDefaultBool, setBool, nil},
   131  		{pb.E_NoDefaultBool, setBool2, nil},
   132  		{pb.E_NoDefaultString, setString, nil},
   133  		{pb.E_NoDefaultBytes, setBytes, nil},
   134  		{pb.E_NoDefaultEnum, setEnum, nil},
   135  		{pb.E_DefaultDouble, setFloat64, float64(3.1415)},
   136  		{pb.E_DefaultFloat, setFloat32, float32(3.14)},
   137  		{pb.E_DefaultInt32, setInt32, int32(42)},
   138  		{pb.E_DefaultInt64, setInt64, int64(43)},
   139  		{pb.E_DefaultUint32, setUint32, uint32(44)},
   140  		{pb.E_DefaultUint64, setUint64, uint64(45)},
   141  		{pb.E_DefaultSint32, setInt32, int32(46)},
   142  		{pb.E_DefaultSint64, setInt64, int64(47)},
   143  		{pb.E_DefaultFixed32, setUint32, uint32(48)},
   144  		{pb.E_DefaultFixed64, setUint64, uint64(49)},
   145  		{pb.E_DefaultSfixed32, setInt32, int32(50)},
   146  		{pb.E_DefaultSfixed64, setInt64, int64(51)},
   147  		{pb.E_DefaultBool, setBool, true},
   148  		{pb.E_DefaultBool, setBool2, true},
   149  		{pb.E_DefaultString, setString, "Hello, string"},
   150  		{pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")},
   151  		{pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE},
   152  	}
   153  
   154  	checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error {
   155  		val, err := proto.GetExtension(msg, test.ext)
   156  		if err != nil {
   157  			if valWant != nil {
   158  				return fmt.Errorf("GetExtension(): %s", err)
   159  			}
   160  			if want := proto.ErrMissingExtension; err != want {
   161  				return fmt.Errorf("Unexpected error: got %v, want %v", err, want)
   162  			}
   163  			return nil
   164  		}
   165  
   166  		// All proto2 extension values are either a pointer to a value or a slice of values.
   167  		ty := reflect.TypeOf(val)
   168  		tyWant := reflect.TypeOf(test.ext.ExtensionType)
   169  		if got, want := ty, tyWant; got != want {
   170  			return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want)
   171  		}
   172  		tye := ty.Elem()
   173  		tyeWant := tyWant.Elem()
   174  		if got, want := tye, tyeWant; got != want {
   175  			return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want)
   176  		}
   177  
   178  		// Check the name of the type of the value.
   179  		// If it is an enum it will be type int32 with the name of the enum.
   180  		if got, want := tye.Name(), tye.Name(); got != want {
   181  			return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want)
   182  		}
   183  
   184  		// Check that value is what we expect.
   185  		// If we have a pointer in val, get the value it points to.
   186  		valExp := val
   187  		if ty.Kind() == reflect.Ptr {
   188  			valExp = reflect.ValueOf(val).Elem().Interface()
   189  		}
   190  		if got, want := valExp, valWant; !reflect.DeepEqual(got, want) {
   191  			return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want)
   192  		}
   193  
   194  		return nil
   195  	}
   196  
   197  	setTo := func(test testcase) interface{} {
   198  		setTo := reflect.ValueOf(test.want)
   199  		if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr {
   200  			setTo = reflect.New(typ).Elem()
   201  			setTo.Set(reflect.New(setTo.Type().Elem()))
   202  			setTo.Elem().Set(reflect.ValueOf(test.want))
   203  		}
   204  		return setTo.Interface()
   205  	}
   206  
   207  	for _, test := range tests {
   208  		msg := &pb.DefaultsMessage{}
   209  		name := test.ext.Name
   210  
   211  		// Check the initial value.
   212  		if err := checkVal(test, msg, test.def); err != nil {
   213  			t.Errorf("%s: %v", name, err)
   214  		}
   215  
   216  		// Set the per-type value and check value.
   217  		name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want)
   218  		if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil {
   219  			t.Errorf("%s: SetExtension(): %v", name, err)
   220  			continue
   221  		}
   222  		if err := checkVal(test, msg, test.want); err != nil {
   223  			t.Errorf("%s: %v", name, err)
   224  			continue
   225  		}
   226  
   227  		// Set and check the value.
   228  		name += " (cleared)"
   229  		proto.ClearExtension(msg, test.ext)
   230  		if err := checkVal(test, msg, test.def); err != nil {
   231  			t.Errorf("%s: %v", name, err)
   232  		}
   233  	}
   234  }
   235  
   236  func TestExtensionsRoundTrip(t *testing.T) {
   237  	msg := &pb.MyMessage{}
   238  	ext1 := &pb.Ext{
   239  		Data: proto.String("hi"),
   240  	}
   241  	ext2 := &pb.Ext{
   242  		Data: proto.String("there"),
   243  	}
   244  	exists := proto.HasExtension(msg, pb.E_Ext_More)
   245  	if exists {
   246  		t.Error("Extension More present unexpectedly")
   247  	}
   248  	if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil {
   249  		t.Error(err)
   250  	}
   251  	if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil {
   252  		t.Error(err)
   253  	}
   254  	e, err := proto.GetExtension(msg, pb.E_Ext_More)
   255  	if err != nil {
   256  		t.Error(err)
   257  	}
   258  	x, ok := e.(*pb.Ext)
   259  	if !ok {
   260  		t.Errorf("e has type %T, expected testdata.Ext", e)
   261  	} else if *x.Data != "there" {
   262  		t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x)
   263  	}
   264  	proto.ClearExtension(msg, pb.E_Ext_More)
   265  	if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension {
   266  		t.Errorf("got %v, expected ErrMissingExtension", e)
   267  	}
   268  	if _, err := proto.GetExtension(msg, pb.E_X215); err == nil {
   269  		t.Error("expected bad extension error, got nil")
   270  	}
   271  	if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil {
   272  		t.Error("expected extension err")
   273  	}
   274  	if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil {
   275  		t.Error("expected some sort of type mismatch error, got nil")
   276  	}
   277  }
   278  
   279  func TestNilExtension(t *testing.T) {
   280  	msg := &pb.MyMessage{
   281  		Count: proto.Int32(1),
   282  	}
   283  	if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil {
   284  		t.Fatal(err)
   285  	}
   286  	if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil {
   287  		t.Error("expected SetExtension to fail due to a nil extension")
   288  	} else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want {
   289  		t.Errorf("expected error %v, got %v", want, err)
   290  	}
   291  	// Note: if the behavior of Marshal is ever changed to ignore nil extensions, update
   292  	// this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal.
   293  }
   294  
   295  func TestMarshalUnmarshalRepeatedExtension(t *testing.T) {
   296  	// Add a repeated extension to the result.
   297  	tests := []struct {
   298  		name string
   299  		ext  []*pb.ComplexExtension
   300  	}{
   301  		{
   302  			"two fields",
   303  			[]*pb.ComplexExtension{
   304  				{First: proto.Int32(7)},
   305  				{Second: proto.Int32(11)},
   306  			},
   307  		},
   308  		{
   309  			"repeated field",
   310  			[]*pb.ComplexExtension{
   311  				{Third: []int32{1000}},
   312  				{Third: []int32{2000}},
   313  			},
   314  		},
   315  		{
   316  			"two fields and repeated field",
   317  			[]*pb.ComplexExtension{
   318  				{Third: []int32{1000}},
   319  				{First: proto.Int32(9)},
   320  				{Second: proto.Int32(21)},
   321  				{Third: []int32{2000}},
   322  			},
   323  		},
   324  	}
   325  	for _, test := range tests {
   326  		// Marshal message with a repeated extension.
   327  		msg1 := new(pb.OtherMessage)
   328  		err := proto.SetExtension(msg1, pb.E_RComplex, test.ext)
   329  		if err != nil {
   330  			t.Fatalf("[%s] Error setting extension: %v", test.name, err)
   331  		}
   332  		b, err := proto.Marshal(msg1)
   333  		if err != nil {
   334  			t.Fatalf("[%s] Error marshaling message: %v", test.name, err)
   335  		}
   336  
   337  		// Unmarshal and read the merged proto.
   338  		msg2 := new(pb.OtherMessage)
   339  		err = proto.Unmarshal(b, msg2)
   340  		if err != nil {
   341  			t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err)
   342  		}
   343  		e, err := proto.GetExtension(msg2, pb.E_RComplex)
   344  		if err != nil {
   345  			t.Fatalf("[%s] Error getting extension: %v", test.name, err)
   346  		}
   347  		ext := e.([]*pb.ComplexExtension)
   348  		if ext == nil {
   349  			t.Fatalf("[%s] Invalid extension", test.name)
   350  		}
   351  		if !reflect.DeepEqual(ext, test.ext) {
   352  			t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, test.ext)
   353  		}
   354  	}
   355  }
   356  
   357  func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) {
   358  	// We may see multiple instances of the same extension in the wire
   359  	// format. For example, the proto compiler may encode custom options in
   360  	// this way. Here, we verify that we merge the extensions together.
   361  	tests := []struct {
   362  		name string
   363  		ext  []*pb.ComplexExtension
   364  	}{
   365  		{
   366  			"two fields",
   367  			[]*pb.ComplexExtension{
   368  				{First: proto.Int32(7)},
   369  				{Second: proto.Int32(11)},
   370  			},
   371  		},
   372  		{
   373  			"repeated field",
   374  			[]*pb.ComplexExtension{
   375  				{Third: []int32{1000}},
   376  				{Third: []int32{2000}},
   377  			},
   378  		},
   379  		{
   380  			"two fields and repeated field",
   381  			[]*pb.ComplexExtension{
   382  				{Third: []int32{1000}},
   383  				{First: proto.Int32(9)},
   384  				{Second: proto.Int32(21)},
   385  				{Third: []int32{2000}},
   386  			},
   387  		},
   388  	}
   389  	for _, test := range tests {
   390  		var buf bytes.Buffer
   391  		var want pb.ComplexExtension
   392  
   393  		// Generate a serialized representation of a repeated extension
   394  		// by catenating bytes together.
   395  		for i, e := range test.ext {
   396  			// Merge to create the wanted proto.
   397  			proto.Merge(&want, e)
   398  
   399  			// serialize the message
   400  			msg := new(pb.OtherMessage)
   401  			err := proto.SetExtension(msg, pb.E_Complex, e)
   402  			if err != nil {
   403  				t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err)
   404  			}
   405  			b, err := proto.Marshal(msg)
   406  			if err != nil {
   407  				t.Fatalf("[%s] Error marshaling message %d: %v", test.name, i, err)
   408  			}
   409  			buf.Write(b)
   410  		}
   411  
   412  		// Unmarshal and read the merged proto.
   413  		msg2 := new(pb.OtherMessage)
   414  		err := proto.Unmarshal(buf.Bytes(), msg2)
   415  		if err != nil {
   416  			t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err)
   417  		}
   418  		e, err := proto.GetExtension(msg2, pb.E_Complex)
   419  		if err != nil {
   420  			t.Fatalf("[%s] Error getting extension: %v", test.name, err)
   421  		}
   422  		ext := e.(*pb.ComplexExtension)
   423  		if ext == nil {
   424  			t.Fatalf("[%s] Invalid extension", test.name)
   425  		}
   426  		if !reflect.DeepEqual(*ext, want) {
   427  			t.Errorf("[%s] Wrong value for ComplexExtension: got: %s want: %s\n", test.name, ext, want)
   428  		}
   429  	}
   430  }