1// Go support for Protocol Buffers - Google's data interchange format 2// 3// Copyright 2014 The Go Authors. All rights reserved. 4// https://github.com/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 32package proto_test 33 34import ( 35 "bytes" 36 "testing" 37 38 "github.com/golang/protobuf/proto" 39 pb "github.com/golang/protobuf/proto/proto3_proto" 40 tpb "github.com/golang/protobuf/proto/test_proto" 41) 42 43func TestProto3ZeroValues(t *testing.T) { 44 tests := []struct { 45 desc string 46 m proto.Message 47 }{ 48 {"zero message", &pb.Message{}}, 49 {"empty bytes field", &pb.Message{Data: []byte{}}}, 50 } 51 for _, test := range tests { 52 b, err := proto.Marshal(test.m) 53 if err != nil { 54 t.Errorf("%s: proto.Marshal: %v", test.desc, err) 55 continue 56 } 57 if len(b) > 0 { 58 t.Errorf("%s: Encoding is non-empty: %q", test.desc, b) 59 } 60 } 61} 62 63func TestRoundTripProto3(t *testing.T) { 64 m := &pb.Message{ 65 Name: "David", // (2 | 1<<3): 0x0a 0x05 "David" 66 Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01 67 HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01 68 Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto" 69 ResultCount: 47, // (0 | 7<<3): 0x38 0x2f 70 TrueScotsman: true, // (0 | 8<<3): 0x40 0x01 71 Score: 8.1, // (5 | 9<<3): 0x4d <8.1> 72 73 Key: []uint64{1, 0xdeadbeef}, 74 Nested: &pb.Nested{ 75 Bunny: "Monty", 76 }, 77 } 78 t.Logf(" m: %v", m) 79 80 b, err := proto.Marshal(m) 81 if err != nil { 82 t.Fatalf("proto.Marshal: %v", err) 83 } 84 t.Logf(" b: %q", b) 85 86 m2 := new(pb.Message) 87 if err := proto.Unmarshal(b, m2); err != nil { 88 t.Fatalf("proto.Unmarshal: %v", err) 89 } 90 t.Logf("m2: %v", m2) 91 92 if !proto.Equal(m, m2) { 93 t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2) 94 } 95} 96 97func TestGettersForBasicTypesExist(t *testing.T) { 98 var m pb.Message 99 if got := m.GetNested().GetBunny(); got != "" { 100 t.Errorf("m.GetNested().GetBunny() = %q, want empty string", got) 101 } 102 if got := m.GetNested().GetCute(); got { 103 t.Errorf("m.GetNested().GetCute() = %t, want false", got) 104 } 105} 106 107func TestProto3SetDefaults(t *testing.T) { 108 in := &pb.Message{ 109 Terrain: map[string]*pb.Nested{ 110 "meadow": new(pb.Nested), 111 }, 112 Proto2Field: new(tpb.SubDefaults), 113 Proto2Value: map[string]*tpb.SubDefaults{ 114 "badlands": new(tpb.SubDefaults), 115 }, 116 } 117 118 got := proto.Clone(in).(*pb.Message) 119 proto.SetDefaults(got) 120 121 // There are no defaults in proto3. Everything should be the zero value, but 122 // we need to remember to set defaults for nested proto2 messages. 123 want := &pb.Message{ 124 Terrain: map[string]*pb.Nested{ 125 "meadow": new(pb.Nested), 126 }, 127 Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)}, 128 Proto2Value: map[string]*tpb.SubDefaults{ 129 "badlands": &tpb.SubDefaults{N: proto.Int64(7)}, 130 }, 131 } 132 133 if !proto.Equal(got, want) { 134 t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want) 135 } 136} 137 138func TestUnknownFieldPreservation(t *testing.T) { 139 b1 := "\x0a\x05David" // Known tag 1 140 b2 := "\xc2\x0c\x06Google" // Unknown tag 200 141 b := []byte(b1 + b2) 142 143 m := new(pb.Message) 144 if err := proto.Unmarshal(b, m); err != nil { 145 t.Fatalf("proto.Unmarshal: %v", err) 146 } 147 148 if !bytes.Equal(m.XXX_unrecognized, []byte(b2)) { 149 t.Fatalf("mismatching unknown fields:\ngot %q\nwant %q", m.XXX_unrecognized, b2) 150 } 151} 152