github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/protobuf/jsonpb/jsonpb_test.go (about) 1 // Go support for Protocol Buffers - Google's data interchange format 2 // 3 // Copyright 2015 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 jsonpb 33 34 import ( 35 "bytes" 36 "encoding/json" 37 "io" 38 "reflect" 39 "testing" 40 41 "github.com/insionng/yougam/libraries/golang/protobuf/proto" 42 43 pb "github.com/insionng/yougam/libraries/golang/protobuf/jsonpb/jsonpb_test_proto" 44 proto3pb "github.com/insionng/yougam/libraries/golang/protobuf/proto/proto3_proto" 45 durpb "github.com/insionng/yougam/libraries/golang/protobuf/ptypes/duration" 46 stpb "github.com/insionng/yougam/libraries/golang/protobuf/ptypes/struct" 47 tspb "github.com/insionng/yougam/libraries/golang/protobuf/ptypes/timestamp" 48 wpb "github.com/insionng/yougam/libraries/golang/protobuf/ptypes/wrappers" 49 ) 50 51 var ( 52 marshaler = Marshaler{} 53 54 marshalerAllOptions = Marshaler{ 55 Indent: " ", 56 } 57 58 simpleObject = &pb.Simple{ 59 OInt32: proto.Int32(-32), 60 OInt64: proto.Int64(-6400000000), 61 OUint32: proto.Uint32(32), 62 OUint64: proto.Uint64(6400000000), 63 OSint32: proto.Int32(-13), 64 OSint64: proto.Int64(-2600000000), 65 OFloat: proto.Float32(3.14), 66 ODouble: proto.Float64(6.02214179e23), 67 OBool: proto.Bool(true), 68 OString: proto.String("hello \"there\""), 69 OBytes: []byte("beep boop"), 70 } 71 72 simpleObjectJSON = `{` + 73 `"oBool":true,` + 74 `"oInt32":-32,` + 75 `"oInt64":"-6400000000",` + 76 `"oUint32":32,` + 77 `"oUint64":"6400000000",` + 78 `"oSint32":-13,` + 79 `"oSint64":"-2600000000",` + 80 `"oFloat":3.14,` + 81 `"oDouble":6.02214179e+23,` + 82 `"oString":"hello \"there\"",` + 83 `"oBytes":"YmVlcCBib29w"` + 84 `}` 85 86 simpleObjectPrettyJSON = `{ 87 "oBool": true, 88 "oInt32": -32, 89 "oInt64": "-6400000000", 90 "oUint32": 32, 91 "oUint64": "6400000000", 92 "oSint32": -13, 93 "oSint64": "-2600000000", 94 "oFloat": 3.14, 95 "oDouble": 6.02214179e+23, 96 "oString": "hello \"there\"", 97 "oBytes": "YmVlcCBib29w" 98 }` 99 100 repeatsObject = &pb.Repeats{ 101 RBool: []bool{true, false, true}, 102 RInt32: []int32{-3, -4, -5}, 103 RInt64: []int64{-123456789, -987654321}, 104 RUint32: []uint32{1, 2, 3}, 105 RUint64: []uint64{6789012345, 3456789012}, 106 RSint32: []int32{-1, -2, -3}, 107 RSint64: []int64{-6789012345, -3456789012}, 108 RFloat: []float32{3.14, 6.28}, 109 RDouble: []float64{299792458, 6.62606957e-34}, 110 RString: []string{"happy", "days"}, 111 RBytes: [][]byte{[]byte("skittles"), []byte("m&m's")}, 112 } 113 114 repeatsObjectJSON = `{` + 115 `"rBool":[true,false,true],` + 116 `"rInt32":[-3,-4,-5],` + 117 `"rInt64":["-123456789","-987654321"],` + 118 `"rUint32":[1,2,3],` + 119 `"rUint64":["6789012345","3456789012"],` + 120 `"rSint32":[-1,-2,-3],` + 121 `"rSint64":["-6789012345","-3456789012"],` + 122 `"rFloat":[3.14,6.28],` + 123 `"rDouble":[2.99792458e+08,6.62606957e-34],` + 124 `"rString":["happy","days"],` + 125 `"rBytes":["c2tpdHRsZXM=","bSZtJ3M="]` + 126 `}` 127 128 repeatsObjectPrettyJSON = `{ 129 "rBool": [ 130 true, 131 false, 132 true 133 ], 134 "rInt32": [ 135 -3, 136 -4, 137 -5 138 ], 139 "rInt64": [ 140 "-123456789", 141 "-987654321" 142 ], 143 "rUint32": [ 144 1, 145 2, 146 3 147 ], 148 "rUint64": [ 149 "6789012345", 150 "3456789012" 151 ], 152 "rSint32": [ 153 -1, 154 -2, 155 -3 156 ], 157 "rSint64": [ 158 "-6789012345", 159 "-3456789012" 160 ], 161 "rFloat": [ 162 3.14, 163 6.28 164 ], 165 "rDouble": [ 166 2.99792458e+08, 167 6.62606957e-34 168 ], 169 "rString": [ 170 "happy", 171 "days" 172 ], 173 "rBytes": [ 174 "c2tpdHRsZXM=", 175 "bSZtJ3M=" 176 ] 177 }` 178 179 innerSimple = &pb.Simple{OInt32: proto.Int32(-32)} 180 innerSimple2 = &pb.Simple{OInt64: proto.Int64(25)} 181 innerRepeats = &pb.Repeats{RString: []string{"roses", "red"}} 182 innerRepeats2 = &pb.Repeats{RString: []string{"violets", "blue"}} 183 complexObject = &pb.Widget{ 184 Color: pb.Widget_GREEN.Enum(), 185 RColor: []pb.Widget_Color{pb.Widget_RED, pb.Widget_GREEN, pb.Widget_BLUE}, 186 Simple: innerSimple, 187 RSimple: []*pb.Simple{innerSimple, innerSimple2}, 188 Repeats: innerRepeats, 189 RRepeats: []*pb.Repeats{innerRepeats, innerRepeats2}, 190 } 191 192 complexObjectJSON = `{"color":"GREEN",` + 193 `"rColor":["RED","GREEN","BLUE"],` + 194 `"simple":{"oInt32":-32},` + 195 `"rSimple":[{"oInt32":-32},{"oInt64":"25"}],` + 196 `"repeats":{"rString":["roses","red"]},` + 197 `"rRepeats":[{"rString":["roses","red"]},{"rString":["violets","blue"]}]` + 198 `}` 199 200 complexObjectPrettyJSON = `{ 201 "color": "GREEN", 202 "rColor": [ 203 "RED", 204 "GREEN", 205 "BLUE" 206 ], 207 "simple": { 208 "oInt32": -32 209 }, 210 "rSimple": [ 211 { 212 "oInt32": -32 213 }, 214 { 215 "oInt64": "25" 216 } 217 ], 218 "repeats": { 219 "rString": [ 220 "roses", 221 "red" 222 ] 223 }, 224 "rRepeats": [ 225 { 226 "rString": [ 227 "roses", 228 "red" 229 ] 230 }, 231 { 232 "rString": [ 233 "violets", 234 "blue" 235 ] 236 } 237 ] 238 }` 239 240 colorPrettyJSON = `{ 241 "color": 2 242 }` 243 244 colorListPrettyJSON = `{ 245 "color": 1000, 246 "rColor": [ 247 "RED" 248 ] 249 }` 250 251 nummyPrettyJSON = `{ 252 "nummy": { 253 "1": 2, 254 "3": 4 255 } 256 }` 257 258 objjyPrettyJSON = `{ 259 "objjy": { 260 "1": { 261 "dub": 1 262 } 263 } 264 }` 265 realNumber = &pb.Real{Value: proto.Float64(3.14159265359)} 266 realNumberName = "Pi" 267 complexNumber = &pb.Complex{Imaginary: proto.Float64(0.5772156649)} 268 realNumberJSON = `{` + 269 `"value":3.14159265359,` + 270 `"[jsonpb.Complex.real_extension]":{"imaginary":0.5772156649},` + 271 `"[jsonpb.name]":"Pi"` + 272 `}` 273 ) 274 275 func init() { 276 if err := proto.SetExtension(realNumber, pb.E_Name, &realNumberName); err != nil { 277 panic(err) 278 } 279 if err := proto.SetExtension(realNumber, pb.E_Complex_RealExtension, complexNumber); err != nil { 280 panic(err) 281 } 282 } 283 284 var marshalingTests = []struct { 285 desc string 286 marshaler Marshaler 287 pb proto.Message 288 json string 289 }{ 290 {"simple flat object", marshaler, simpleObject, simpleObjectJSON}, 291 {"simple pretty object", marshalerAllOptions, simpleObject, simpleObjectPrettyJSON}, 292 {"repeated fields flat object", marshaler, repeatsObject, repeatsObjectJSON}, 293 {"repeated fields pretty object", marshalerAllOptions, repeatsObject, repeatsObjectPrettyJSON}, 294 {"nested message/enum flat object", marshaler, complexObject, complexObjectJSON}, 295 {"nested message/enum pretty object", marshalerAllOptions, complexObject, complexObjectPrettyJSON}, 296 {"enum-string flat object", Marshaler{}, 297 &pb.Widget{Color: pb.Widget_BLUE.Enum()}, `{"color":"BLUE"}`}, 298 {"enum-value pretty object", Marshaler{EnumsAsInts: true, Indent: " "}, 299 &pb.Widget{Color: pb.Widget_BLUE.Enum()}, colorPrettyJSON}, 300 {"unknown enum value object", marshalerAllOptions, 301 &pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}, colorListPrettyJSON}, 302 {"repeated proto3 enum", Marshaler{}, 303 &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ 304 proto3pb.Message_PUNS, 305 proto3pb.Message_SLAPSTICK, 306 }}, 307 `{"rFunny":["PUNS","SLAPSTICK"]}`}, 308 {"repeated proto3 enum as int", Marshaler{EnumsAsInts: true}, 309 &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ 310 proto3pb.Message_PUNS, 311 proto3pb.Message_SLAPSTICK, 312 }}, 313 `{"rFunny":[1,2]}`}, 314 {"empty value", marshaler, &pb.Simple3{}, `{}`}, 315 {"empty value emitted", Marshaler{EmitDefaults: true}, &pb.Simple3{}, `{"dub":0}`}, 316 {"map<int64, int32>", marshaler, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, `{"nummy":{"1":2,"3":4}}`}, 317 {"map<int64, int32>", marshalerAllOptions, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, nummyPrettyJSON}, 318 {"map<string, string>", marshaler, 319 &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}, 320 `{"strry":{"\"one\"":"two","three":"four"}}`}, 321 {"map<int32, Object>", marshaler, 322 &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}, `{"objjy":{"1":{"dub":1}}}`}, 323 {"map<int32, Object>", marshalerAllOptions, 324 &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}, objjyPrettyJSON}, 325 {"map<int64, string>", marshaler, &pb.Mappy{Buggy: map[int64]string{1234: "yup"}}, 326 `{"buggy":{"1234":"yup"}}`}, 327 {"map<bool, bool>", marshaler, &pb.Mappy{Booly: map[bool]bool{false: true}}, `{"booly":{"false":true}}`}, 328 // TODO: This is broken. 329 //{"map<string, enum>", marshaler, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":"ROMAN"}`}, 330 {"map<string, enum as int>", Marshaler{EnumsAsInts: true}, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":2}}`}, 331 {"proto2 map<int64, string>", marshaler, &pb.Maps{MInt64Str: map[int64]string{213: "cat"}}, 332 `{"mInt64Str":{"213":"cat"}}`}, 333 {"proto2 map<bool, Object>", marshaler, 334 &pb.Maps{MBoolSimple: map[bool]*pb.Simple{true: &pb.Simple{OInt32: proto.Int32(1)}}}, 335 `{"mBoolSimple":{"true":{"oInt32":1}}}`}, 336 {"oneof, not set", marshaler, &pb.MsgWithOneof{}, `{}`}, 337 {"oneof, set", marshaler, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Title{"Grand Poobah"}}, `{"title":"Grand Poobah"}`}, 338 {"force orig_name", Marshaler{OrigName: true}, &pb.Simple{OInt32: proto.Int32(4)}, 339 `{"o_int32":4}`}, 340 {"proto2 extension", marshaler, realNumber, realNumberJSON}, 341 342 {"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3.000s"}`}, 343 {"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{ 344 Fields: map[string]*stpb.Value{ 345 "one": &stpb.Value{Kind: &stpb.Value_StringValue{"loneliest number"}}, 346 "two": &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}, 347 }, 348 }}, `{"st":{"one":"loneliest number","two":null}}`}, 349 {"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`}, 350 351 {"DoubleValue", marshaler, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`}, 352 {"FloatValue", marshaler, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}, `{"flt":1.2}`}, 353 {"Int64Value", marshaler, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}, `{"i64":"-3"}`}, 354 {"UInt64Value", marshaler, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}, `{"u64":"3"}`}, 355 {"Int32Value", marshaler, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}, `{"i32":-4}`}, 356 {"UInt32Value", marshaler, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}, `{"u32":4}`}, 357 {"BoolValue", marshaler, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}, `{"bool":true}`}, 358 {"StringValue", marshaler, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}, `{"str":"plush"}`}, 359 {"BytesValue", marshaler, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`}, 360 } 361 362 func TestMarshaling(t *testing.T) { 363 for _, tt := range marshalingTests { 364 json, err := tt.marshaler.MarshalToString(tt.pb) 365 if err != nil { 366 t.Errorf("%s: marshaling error: %v", tt.desc, err) 367 } else if tt.json != json { 368 t.Errorf("%s: got [%v] want [%v]", tt.desc, json, tt.json) 369 } 370 } 371 } 372 373 var unmarshalingTests = []struct { 374 desc string 375 json string 376 pb proto.Message 377 }{ 378 {"simple flat object", simpleObjectJSON, simpleObject}, 379 {"simple pretty object", simpleObjectPrettyJSON, simpleObject}, 380 {"repeated fields flat object", repeatsObjectJSON, repeatsObject}, 381 {"repeated fields pretty object", repeatsObjectPrettyJSON, repeatsObject}, 382 {"nested message/enum flat object", complexObjectJSON, complexObject}, 383 {"nested message/enum pretty object", complexObjectPrettyJSON, complexObject}, 384 {"enum-string object", `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}}, 385 {"enum-value object", "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}}, 386 {"proto3 enum string", `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, 387 {"proto3 enum value", `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, 388 {"unknown enum value object", 389 "{\n \"color\": 1000,\n \"r_color\": [\n \"RED\"\n ]\n}", 390 &pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}}, 391 {"repeated proto3 enum", `{"rFunny":["PUNS","SLAPSTICK"]}`, 392 &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ 393 proto3pb.Message_PUNS, 394 proto3pb.Message_SLAPSTICK, 395 }}}, 396 {"repeated proto3 enum as int", `{"rFunny":[1,2]}`, 397 &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ 398 proto3pb.Message_PUNS, 399 proto3pb.Message_SLAPSTICK, 400 }}}, 401 {"repeated proto3 enum as mix of strings and ints", `{"rFunny":["PUNS",2]}`, 402 &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ 403 proto3pb.Message_PUNS, 404 proto3pb.Message_SLAPSTICK, 405 }}}, 406 {"unquoted int64 object", `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}}, 407 {"unquoted uint64 object", `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}}, 408 {"map<int64, int32>", `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}}, 409 {"map<string, string>", `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}}, 410 {"map<int32, Object>", `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}}, 411 // TODO: This is broken. 412 //{"map<string, enum>", `{"enumy":{"XIV":"ROMAN"}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}}, 413 {"map<string, enum as int>", `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}}, 414 {"oneof", `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}}, 415 {"oneof spec name", `{"country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}}, 416 {"oneof orig_name", `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}}, 417 {"orig_name input", `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}}, 418 {"camelName input", `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}}, 419 420 {"Duration", `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}}, 421 {"Timestamp", `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}}, 422 423 {"DoubleValue", `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}}, 424 {"FloatValue", `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}}, 425 {"Int64Value", `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}}, 426 {"UInt64Value", `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}}, 427 {"Int32Value", `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}}, 428 {"UInt32Value", `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}}, 429 {"BoolValue", `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}}, 430 {"StringValue", `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}}, 431 {"BytesValue", `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}}, 432 // `null` is also a permissible value. Let's just test one. 433 {"null DoubleValue", `{"dbl":null}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{}}}, 434 } 435 436 func TestUnmarshaling(t *testing.T) { 437 for _, tt := range unmarshalingTests { 438 // Make a new instance of the type of our expected object. 439 p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message) 440 441 err := UnmarshalString(tt.json, p) 442 if err != nil { 443 t.Errorf("%s: %v", tt.desc, err) 444 continue 445 } 446 447 // For easier diffs, compare text strings of the protos. 448 exp := proto.MarshalTextString(tt.pb) 449 act := proto.MarshalTextString(p) 450 if string(exp) != string(act) { 451 t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp) 452 } 453 } 454 } 455 456 func TestUnmarshalNext(t *testing.T) { 457 // We only need to check against a few, not all of them. 458 tests := unmarshalingTests[:5] 459 460 // Create a buffer with many concatenated JSON objects. 461 var b bytes.Buffer 462 for _, tt := range tests { 463 b.WriteString(tt.json) 464 } 465 466 dec := json.NewDecoder(&b) 467 for _, tt := range tests { 468 // Make a new instance of the type of our expected object. 469 p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message) 470 471 err := UnmarshalNext(dec, p) 472 if err != nil { 473 t.Errorf("%s: %v", tt.desc, err) 474 continue 475 } 476 477 // For easier diffs, compare text strings of the protos. 478 exp := proto.MarshalTextString(tt.pb) 479 act := proto.MarshalTextString(p) 480 if string(exp) != string(act) { 481 t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp) 482 } 483 } 484 485 p := &pb.Simple{} 486 err := UnmarshalNext(dec, p) 487 if err != io.EOF { 488 t.Errorf("eof: got %v, expected io.EOF", err) 489 } 490 } 491 492 var unmarshalingShouldError = []struct { 493 desc string 494 in string 495 pb proto.Message 496 }{ 497 {"a value", "666", new(pb.Simple)}, 498 {"gibberish", "{adskja123;l23=-=", new(pb.Simple)}, 499 {"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)}, 500 } 501 502 func TestUnmarshalingBadInput(t *testing.T) { 503 for _, tt := range unmarshalingShouldError { 504 err := UnmarshalString(tt.in, tt.pb) 505 if err == nil { 506 t.Errorf("an error was expected when parsing %q instead of an object", tt.desc) 507 } 508 } 509 }