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  }