github.com/gogo/protobuf@v1.3.2/proto/discard_test.go (about) 1 // Go support for Protocol Buffers - Google's data interchange format 2 // 3 // Copyright 2017 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 32 package proto_test 33 34 import ( 35 "testing" 36 37 "github.com/gogo/protobuf/proto" 38 proto3pb "github.com/gogo/protobuf/proto/proto3_proto" 39 pb "github.com/gogo/protobuf/proto/test_proto" 40 ) 41 42 func TestDiscardUnknown(t *testing.T) { 43 tests := []struct { 44 desc string 45 in, want proto.Message 46 }{{ 47 desc: "Nil", 48 in: nil, want: nil, // Should not panic 49 }, { 50 desc: "NilPtr", 51 in: (*proto3pb.Message)(nil), want: (*proto3pb.Message)(nil), // Should not panic 52 }, { 53 desc: "Nested", 54 in: &proto3pb.Message{ 55 Name: "Aaron", 56 Nested: &proto3pb.Nested{Cute: true, XXX_unrecognized: []byte("blah")}, 57 XXX_unrecognized: []byte("blah"), 58 }, 59 want: &proto3pb.Message{ 60 Name: "Aaron", 61 Nested: &proto3pb.Nested{Cute: true}, 62 }, 63 }, { 64 desc: "Slice", 65 in: &proto3pb.Message{ 66 Name: "Aaron", 67 Children: []*proto3pb.Message{ 68 {Name: "Sarah", XXX_unrecognized: []byte("blah")}, 69 {Name: "Abraham", XXX_unrecognized: []byte("blah")}, 70 }, 71 XXX_unrecognized: []byte("blah"), 72 }, 73 want: &proto3pb.Message{ 74 Name: "Aaron", 75 Children: []*proto3pb.Message{ 76 {Name: "Sarah"}, 77 {Name: "Abraham"}, 78 }, 79 }, 80 }, { 81 desc: "OneOf", 82 in: &pb.Communique{ 83 Union: &pb.Communique_Msg{Msg: &pb.Strings{ 84 StringField: proto.String("123"), 85 XXX_unrecognized: []byte("blah"), 86 }}, 87 XXX_unrecognized: []byte("blah"), 88 }, 89 want: &pb.Communique{ 90 Union: &pb.Communique_Msg{Msg: &pb.Strings{StringField: proto.String("123")}}, 91 }, 92 }, { 93 desc: "Map", 94 in: &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{ 95 0x4002: { 96 Exact: proto.Bool(true), 97 XXX_unrecognized: []byte("blah"), 98 }, 99 }}, 100 want: &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{ 101 0x4002: {Exact: proto.Bool(true)}, 102 }}, 103 }, { 104 desc: "Extension", 105 in: func() proto.Message { 106 m := &pb.MyMessage{ 107 Count: proto.Int32(42), 108 Somegroup: &pb.MyMessage_SomeGroup{ 109 GroupField: proto.Int32(6), 110 XXX_unrecognized: []byte("blah"), 111 }, 112 XXX_unrecognized: []byte("blah"), 113 } 114 proto.SetExtension(m, pb.E_Ext_More, &pb.Ext{ 115 Data: proto.String("extension"), 116 XXX_unrecognized: []byte("blah"), 117 }) 118 return m 119 }(), 120 want: func() proto.Message { 121 m := &pb.MyMessage{ 122 Count: proto.Int32(42), 123 Somegroup: &pb.MyMessage_SomeGroup{GroupField: proto.Int32(6)}, 124 } 125 proto.SetExtension(m, pb.E_Ext_More, &pb.Ext{Data: proto.String("extension")}) 126 return m 127 }(), 128 }} 129 130 // Test the legacy code path. 131 for _, tt := range tests { 132 // Clone the input so that we don't alter the original. 133 in := tt.in 134 if in != nil { 135 in = proto.Clone(tt.in) 136 } 137 138 var m LegacyMessage 139 m.Message, _ = in.(*proto3pb.Message) 140 m.Communique, _ = in.(*pb.Communique) 141 m.MessageWithMap, _ = in.(*pb.MessageWithMap) 142 m.MyMessage, _ = in.(*pb.MyMessage) 143 proto.DiscardUnknown(&m) 144 if !proto.Equal(in, tt.want) { 145 t.Errorf("test %s/Legacy, expected unknown fields to be discarded\ngot %v\nwant %v", tt.desc, in, tt.want) 146 } 147 } 148 149 for _, tt := range tests { 150 proto.DiscardUnknown(tt.in) 151 if !proto.Equal(tt.in, tt.want) { 152 t.Errorf("test %s, expected unknown fields to be discarded\ngot %v\nwant %v", tt.desc, tt.in, tt.want) 153 } 154 } 155 } 156 157 // LegacyMessage is a proto.Message that has several nested messages. 158 // This does not have the XXX_DiscardUnknown method and so forces DiscardUnknown 159 // to use the legacy fallback logic. 160 type LegacyMessage struct { 161 Message *proto3pb.Message 162 Communique *pb.Communique 163 MessageWithMap *pb.MessageWithMap 164 MyMessage *pb.MyMessage 165 } 166 167 func (m *LegacyMessage) Reset() { *m = LegacyMessage{} } 168 func (m *LegacyMessage) String() string { return proto.CompactTextString(m) } 169 func (*LegacyMessage) ProtoMessage() {}