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

     1  // Go support for Protocol Buffers - Google's data interchange format
     2  //
     3  // Copyright 2011 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  	"testing"
    36  
    37  	"github.com/insionng/yougam/libraries/golang/protobuf/proto"
    38  
    39  	proto3pb "github.com/insionng/yougam/libraries/golang/protobuf/proto/proto3_proto"
    40  	pb "github.com/insionng/yougam/libraries/golang/protobuf/proto/testdata"
    41  )
    42  
    43  var cloneTestMessage = &pb.MyMessage{
    44  	Count: proto.Int32(42),
    45  	Name:  proto.String("Dave"),
    46  	Pet:   []string{"bunny", "kitty", "horsey"},
    47  	Inner: &pb.InnerMessage{
    48  		Host:      proto.String("niles"),
    49  		Port:      proto.Int32(9099),
    50  		Connected: proto.Bool(true),
    51  	},
    52  	Others: []*pb.OtherMessage{
    53  		{
    54  			Value: []byte("some bytes"),
    55  		},
    56  	},
    57  	Somegroup: &pb.MyMessage_SomeGroup{
    58  		GroupField: proto.Int32(6),
    59  	},
    60  	RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
    61  }
    62  
    63  func init() {
    64  	ext := &pb.Ext{
    65  		Data: proto.String("extension"),
    66  	}
    67  	if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil {
    68  		panic("SetExtension: " + err.Error())
    69  	}
    70  }
    71  
    72  func TestClone(t *testing.T) {
    73  	m := proto.Clone(cloneTestMessage).(*pb.MyMessage)
    74  	if !proto.Equal(m, cloneTestMessage) {
    75  		t.Errorf("Clone(%v) = %v", cloneTestMessage, m)
    76  	}
    77  
    78  	// Verify it was a deep copy.
    79  	*m.Inner.Port++
    80  	if proto.Equal(m, cloneTestMessage) {
    81  		t.Error("Mutating clone changed the original")
    82  	}
    83  	// Byte fields and repeated fields should be copied.
    84  	if &m.Pet[0] == &cloneTestMessage.Pet[0] {
    85  		t.Error("Pet: repeated field not copied")
    86  	}
    87  	if &m.Others[0] == &cloneTestMessage.Others[0] {
    88  		t.Error("Others: repeated field not copied")
    89  	}
    90  	if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] {
    91  		t.Error("Others[0].Value: bytes field not copied")
    92  	}
    93  	if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] {
    94  		t.Error("RepBytes: repeated field not copied")
    95  	}
    96  	if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] {
    97  		t.Error("RepBytes[0]: bytes field not copied")
    98  	}
    99  }
   100  
   101  func TestCloneNil(t *testing.T) {
   102  	var m *pb.MyMessage
   103  	if c := proto.Clone(m); !proto.Equal(m, c) {
   104  		t.Errorf("Clone(%v) = %v", m, c)
   105  	}
   106  }
   107  
   108  var mergeTests = []struct {
   109  	src, dst, want proto.Message
   110  }{
   111  	{
   112  		src: &pb.MyMessage{
   113  			Count: proto.Int32(42),
   114  		},
   115  		dst: &pb.MyMessage{
   116  			Name: proto.String("Dave"),
   117  		},
   118  		want: &pb.MyMessage{
   119  			Count: proto.Int32(42),
   120  			Name:  proto.String("Dave"),
   121  		},
   122  	},
   123  	{
   124  		src: &pb.MyMessage{
   125  			Inner: &pb.InnerMessage{
   126  				Host:      proto.String("hey"),
   127  				Connected: proto.Bool(true),
   128  			},
   129  			Pet: []string{"horsey"},
   130  			Others: []*pb.OtherMessage{
   131  				{
   132  					Value: []byte("some bytes"),
   133  				},
   134  			},
   135  		},
   136  		dst: &pb.MyMessage{
   137  			Inner: &pb.InnerMessage{
   138  				Host: proto.String("niles"),
   139  				Port: proto.Int32(9099),
   140  			},
   141  			Pet: []string{"bunny", "kitty"},
   142  			Others: []*pb.OtherMessage{
   143  				{
   144  					Key: proto.Int64(31415926535),
   145  				},
   146  				{
   147  					// Explicitly test a src=nil field
   148  					Inner: nil,
   149  				},
   150  			},
   151  		},
   152  		want: &pb.MyMessage{
   153  			Inner: &pb.InnerMessage{
   154  				Host:      proto.String("hey"),
   155  				Connected: proto.Bool(true),
   156  				Port:      proto.Int32(9099),
   157  			},
   158  			Pet: []string{"bunny", "kitty", "horsey"},
   159  			Others: []*pb.OtherMessage{
   160  				{
   161  					Key: proto.Int64(31415926535),
   162  				},
   163  				{},
   164  				{
   165  					Value: []byte("some bytes"),
   166  				},
   167  			},
   168  		},
   169  	},
   170  	{
   171  		src: &pb.MyMessage{
   172  			RepBytes: [][]byte{[]byte("wow")},
   173  		},
   174  		dst: &pb.MyMessage{
   175  			Somegroup: &pb.MyMessage_SomeGroup{
   176  				GroupField: proto.Int32(6),
   177  			},
   178  			RepBytes: [][]byte{[]byte("sham")},
   179  		},
   180  		want: &pb.MyMessage{
   181  			Somegroup: &pb.MyMessage_SomeGroup{
   182  				GroupField: proto.Int32(6),
   183  			},
   184  			RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
   185  		},
   186  	},
   187  	// Check that a scalar bytes field replaces rather than appends.
   188  	{
   189  		src:  &pb.OtherMessage{Value: []byte("foo")},
   190  		dst:  &pb.OtherMessage{Value: []byte("bar")},
   191  		want: &pb.OtherMessage{Value: []byte("foo")},
   192  	},
   193  	{
   194  		src: &pb.MessageWithMap{
   195  			NameMapping: map[int32]string{6: "Nigel"},
   196  			MsgMapping: map[int64]*pb.FloatingPoint{
   197  				0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
   198  			},
   199  			ByteMapping: map[bool][]byte{true: []byte("wowsa")},
   200  		},
   201  		dst: &pb.MessageWithMap{
   202  			NameMapping: map[int32]string{
   203  				6: "Bruce", // should be overwritten
   204  				7: "Andrew",
   205  			},
   206  		},
   207  		want: &pb.MessageWithMap{
   208  			NameMapping: map[int32]string{
   209  				6: "Nigel",
   210  				7: "Andrew",
   211  			},
   212  			MsgMapping: map[int64]*pb.FloatingPoint{
   213  				0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
   214  			},
   215  			ByteMapping: map[bool][]byte{true: []byte("wowsa")},
   216  		},
   217  	},
   218  	// proto3 shouldn't merge zero values,
   219  	// in the same way that proto2 shouldn't merge nils.
   220  	{
   221  		src: &proto3pb.Message{
   222  			Name: "Aaron",
   223  			Data: []byte(""), // zero value, but not nil
   224  		},
   225  		dst: &proto3pb.Message{
   226  			HeightInCm: 176,
   227  			Data:       []byte("texas!"),
   228  		},
   229  		want: &proto3pb.Message{
   230  			Name:       "Aaron",
   231  			HeightInCm: 176,
   232  			Data:       []byte("texas!"),
   233  		},
   234  	},
   235  	// Oneof fields should merge by assignment.
   236  	{
   237  		src: &pb.Communique{
   238  			Union: &pb.Communique_Number{41},
   239  		},
   240  		dst: &pb.Communique{
   241  			Union: &pb.Communique_Name{"Bobby Tables"},
   242  		},
   243  		want: &pb.Communique{
   244  			Union: &pb.Communique_Number{41},
   245  		},
   246  	},
   247  	// Oneof nil is the same as not set.
   248  	{
   249  		src: &pb.Communique{},
   250  		dst: &pb.Communique{
   251  			Union: &pb.Communique_Name{"Bobby Tables"},
   252  		},
   253  		want: &pb.Communique{
   254  			Union: &pb.Communique_Name{"Bobby Tables"},
   255  		},
   256  	},
   257  }
   258  
   259  func TestMerge(t *testing.T) {
   260  	for _, m := range mergeTests {
   261  		got := proto.Clone(m.dst)
   262  		proto.Merge(got, m.src)
   263  		if !proto.Equal(got, m.want) {
   264  			t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want)
   265  		}
   266  	}
   267  }