...

Source file src/github.com/gogo/protobuf/jsonpb/jsonpb_test.go

Documentation: github.com/gogo/protobuf/jsonpb

     1  // Go support for Protocol Buffers - Google's data interchange format
     2  //
     3  // Copyright 2015 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 jsonpb
    33  
    34  import (
    35  	"bytes"
    36  	"encoding/json"
    37  	"io"
    38  	"math"
    39  	"reflect"
    40  	"strings"
    41  	"testing"
    42  
    43  	pb "github.com/gogo/protobuf/jsonpb/jsonpb_test_proto"
    44  	"github.com/gogo/protobuf/proto"
    45  	proto3pb "github.com/gogo/protobuf/proto/proto3_proto"
    46  	"github.com/gogo/protobuf/types"
    47  )
    48  
    49  var (
    50  	marshaler = Marshaler{}
    51  
    52  	marshalerAllOptions = Marshaler{
    53  		Indent: "  ",
    54  	}
    55  
    56  	simpleObject = &pb.Simple{
    57  		OInt32:     proto.Int32(-32),
    58  		OInt32Str:  proto.Int32(-32),
    59  		OInt64:     proto.Int64(-6400000000),
    60  		OInt64Str:  proto.Int64(-6400000000),
    61  		OUint32:    proto.Uint32(32),
    62  		OUint32Str: proto.Uint32(32),
    63  		OUint64:    proto.Uint64(6400000000),
    64  		OUint64Str: proto.Uint64(6400000000),
    65  		OSint32:    proto.Int32(-13),
    66  		OSint32Str: proto.Int32(-13),
    67  		OSint64:    proto.Int64(-2600000000),
    68  		OSint64Str: proto.Int64(-2600000000),
    69  		OFloat:     proto.Float32(3.14),
    70  		OFloatStr:  proto.Float32(3.14),
    71  		ODouble:    proto.Float64(6.02214179e23),
    72  		ODoubleStr: proto.Float64(6.02214179e23),
    73  		OBool:      proto.Bool(true),
    74  		OString:    proto.String("hello \"there\""),
    75  		OBytes:     []byte("beep boop"),
    76  		OCastBytes: pb.Bytes("wow"),
    77  	}
    78  
    79  	simpleObjectInputJSON = `{` +
    80  		`"oBool":true,` +
    81  		`"oInt32":-32,` +
    82  		`"oInt32Str":"-32",` +
    83  		`"oInt64":-6400000000,` +
    84  		`"oInt64Str":"-6400000000",` +
    85  		`"oUint32":32,` +
    86  		`"oUint32Str":"32",` +
    87  		`"oUint64":6400000000,` +
    88  		`"oUint64Str":"6400000000",` +
    89  		`"oSint32":-13,` +
    90  		`"oSint32Str":"-13",` +
    91  		`"oSint64":-2600000000,` +
    92  		`"oSint64Str":"-2600000000",` +
    93  		`"oFloat":3.14,` +
    94  		`"oFloatStr":"3.14",` +
    95  		`"oDouble":6.02214179e+23,` +
    96  		`"oDoubleStr":"6.02214179e+23",` +
    97  		`"oString":"hello \"there\"",` +
    98  		`"oBytes":"YmVlcCBib29w",` +
    99  		`"oCastBytes":"d293"` +
   100  		`}`
   101  
   102  	simpleObjectOutputJSON = `{` +
   103  		`"oBool":true,` +
   104  		`"oInt32":-32,` +
   105  		`"oInt32Str":-32,` +
   106  		`"oInt64":"-6400000000",` +
   107  		`"oInt64Str":"-6400000000",` +
   108  		`"oUint32":32,` +
   109  		`"oUint32Str":32,` +
   110  		`"oUint64":"6400000000",` +
   111  		`"oUint64Str":"6400000000",` +
   112  		`"oSint32":-13,` +
   113  		`"oSint32Str":-13,` +
   114  		`"oSint64":"-2600000000",` +
   115  		`"oSint64Str":"-2600000000",` +
   116  		`"oFloat":3.14,` +
   117  		`"oFloatStr":3.14,` +
   118  		`"oDouble":6.02214179e+23,` +
   119  		`"oDoubleStr":6.02214179e+23,` +
   120  		`"oString":"hello \"there\"",` +
   121  		`"oBytes":"YmVlcCBib29w",` +
   122  		`"oCastBytes":"d293"` +
   123  		`}`
   124  
   125  	simpleObjectInputPrettyJSON = `{
   126    "oBool": true,
   127    "oInt32": -32,
   128    "oInt32Str": "-32",
   129    "oInt64": -6400000000,
   130    "oInt64Str": "-6400000000",
   131    "oUint32": 32,
   132    "oUint32Str": "32",
   133    "oUint64": 6400000000,
   134    "oUint64Str": "6400000000",
   135    "oSint32": -13,
   136    "oSint32Str": "-13",
   137    "oSint64": -2600000000,
   138    "oSint64Str": "-2600000000",
   139    "oFloat": 3.14,
   140    "oFloatStr": "3.14",
   141    "oDouble": 6.02214179e+23,
   142    "oDoubleStr": "6.02214179e+23",
   143    "oString": "hello \"there\"",
   144    "oBytes": "YmVlcCBib29w",
   145    "oCastBytes": "d293"
   146  }`
   147  
   148  	simpleObjectOutputPrettyJSON = `{
   149    "oBool": true,
   150    "oInt32": -32,
   151    "oInt32Str": -32,
   152    "oInt64": "-6400000000",
   153    "oInt64Str": "-6400000000",
   154    "oUint32": 32,
   155    "oUint32Str": 32,
   156    "oUint64": "6400000000",
   157    "oUint64Str": "6400000000",
   158    "oSint32": -13,
   159    "oSint32Str": -13,
   160    "oSint64": "-2600000000",
   161    "oSint64Str": "-2600000000",
   162    "oFloat": 3.14,
   163    "oFloatStr": 3.14,
   164    "oDouble": 6.02214179e+23,
   165    "oDoubleStr": 6.02214179e+23,
   166    "oString": "hello \"there\"",
   167    "oBytes": "YmVlcCBib29w",
   168    "oCastBytes": "d293"
   169  }`
   170  
   171  	repeatsObject = &pb.Repeats{
   172  		RBool:   []bool{true, false, true},
   173  		RInt32:  []int32{-3, -4, -5},
   174  		RInt64:  []int64{-123456789, -987654321},
   175  		RUint32: []uint32{1, 2, 3},
   176  		RUint64: []uint64{6789012345, 3456789012},
   177  		RSint32: []int32{-1, -2, -3},
   178  		RSint64: []int64{-6789012345, -3456789012},
   179  		RFloat:  []float32{3.14, 6.28},
   180  		RDouble: []float64{299792458 * 1e20, 6.62606957e-34},
   181  		RString: []string{"happy", "days"},
   182  		RBytes:  [][]byte{[]byte("skittles"), []byte("m&m's")},
   183  	}
   184  
   185  	repeatsObjectJSON = `{` +
   186  		`"rBool":[true,false,true],` +
   187  		`"rInt32":[-3,-4,-5],` +
   188  		`"rInt64":["-123456789","-987654321"],` +
   189  		`"rUint32":[1,2,3],` +
   190  		`"rUint64":["6789012345","3456789012"],` +
   191  		`"rSint32":[-1,-2,-3],` +
   192  		`"rSint64":["-6789012345","-3456789012"],` +
   193  		`"rFloat":[3.14,6.28],` +
   194  		`"rDouble":[2.99792458e+28,6.62606957e-34],` +
   195  		`"rString":["happy","days"],` +
   196  		`"rBytes":["c2tpdHRsZXM=","bSZtJ3M="]` +
   197  		`}`
   198  
   199  	repeatsObjectPrettyJSON = `{
   200    "rBool": [
   201      true,
   202      false,
   203      true
   204    ],
   205    "rInt32": [
   206      -3,
   207      -4,
   208      -5
   209    ],
   210    "rInt64": [
   211      "-123456789",
   212      "-987654321"
   213    ],
   214    "rUint32": [
   215      1,
   216      2,
   217      3
   218    ],
   219    "rUint64": [
   220      "6789012345",
   221      "3456789012"
   222    ],
   223    "rSint32": [
   224      -1,
   225      -2,
   226      -3
   227    ],
   228    "rSint64": [
   229      "-6789012345",
   230      "-3456789012"
   231    ],
   232    "rFloat": [
   233      3.14,
   234      6.28
   235    ],
   236    "rDouble": [
   237      2.99792458e+28,
   238      6.62606957e-34
   239    ],
   240    "rString": [
   241      "happy",
   242      "days"
   243    ],
   244    "rBytes": [
   245      "c2tpdHRsZXM=",
   246      "bSZtJ3M="
   247    ]
   248  }`
   249  
   250  	innerSimple   = &pb.Simple{OInt32: proto.Int32(-32)}
   251  	innerSimple2  = &pb.Simple{OInt64: proto.Int64(25)}
   252  	innerRepeats  = &pb.Repeats{RString: []string{"roses", "red"}}
   253  	innerRepeats2 = &pb.Repeats{RString: []string{"violets", "blue"}}
   254  	complexObject = &pb.Widget{
   255  		Color:    pb.Widget_GREEN.Enum(),
   256  		RColor:   []pb.Widget_Color{pb.Widget_RED, pb.Widget_GREEN, pb.Widget_BLUE},
   257  		Simple:   innerSimple,
   258  		RSimple:  []*pb.Simple{innerSimple, innerSimple2},
   259  		Repeats:  innerRepeats,
   260  		RRepeats: []*pb.Repeats{innerRepeats, innerRepeats2},
   261  	}
   262  
   263  	complexObjectJSON = `{"color":"GREEN",` +
   264  		`"rColor":["RED","GREEN","BLUE"],` +
   265  		`"simple":{"oInt32":-32},` +
   266  		`"rSimple":[{"oInt32":-32},{"oInt64":"25"}],` +
   267  		`"repeats":{"rString":["roses","red"]},` +
   268  		`"rRepeats":[{"rString":["roses","red"]},{"rString":["violets","blue"]}]` +
   269  		`}`
   270  
   271  	complexObjectPrettyJSON = `{
   272    "color": "GREEN",
   273    "rColor": [
   274      "RED",
   275      "GREEN",
   276      "BLUE"
   277    ],
   278    "simple": {
   279      "oInt32": -32
   280    },
   281    "rSimple": [
   282      {
   283        "oInt32": -32
   284      },
   285      {
   286        "oInt64": "25"
   287      }
   288    ],
   289    "repeats": {
   290      "rString": [
   291        "roses",
   292        "red"
   293      ]
   294    },
   295    "rRepeats": [
   296      {
   297        "rString": [
   298          "roses",
   299          "red"
   300        ]
   301      },
   302      {
   303        "rString": [
   304          "violets",
   305          "blue"
   306        ]
   307      }
   308    ]
   309  }`
   310  
   311  	colorPrettyJSON = `{
   312   "color": 2
   313  }`
   314  
   315  	colorListPrettyJSON = `{
   316    "color": 1000,
   317    "rColor": [
   318      "RED"
   319    ]
   320  }`
   321  
   322  	nummyPrettyJSON = `{
   323    "nummy": {
   324      "1": 2,
   325      "3": 4
   326    }
   327  }`
   328  
   329  	objjyPrettyJSON = `{
   330    "objjy": {
   331      "1": {
   332        "dub": 1
   333      }
   334    }
   335  }`
   336  	realNumber     = &pb.Real{Value: proto.Float64(3.14159265359)}
   337  	realNumberName = "Pi"
   338  	complexNumber  = &pb.Complex{Imaginary: proto.Float64(0.5772156649)}
   339  	realNumberJSON = `{` +
   340  		`"value":3.14159265359,` +
   341  		`"[jsonpb.Complex.real_extension]":{"imaginary":0.5772156649},` +
   342  		`"[jsonpb.name]":"Pi"` +
   343  		`}`
   344  
   345  	anySimple = &pb.KnownTypes{
   346  		An: &types.Any{
   347  			TypeUrl: "something.example.com/jsonpb.Simple",
   348  			Value: []byte{
   349  				// &pb.Simple{OBool:true}
   350  				1 << 3, 1,
   351  			},
   352  		},
   353  	}
   354  	anySimpleJSON       = `{"an":{"@type":"something.example.com/jsonpb.Simple","oBool":true}}`
   355  	anySimplePrettyJSON = `{
   356    "an": {
   357      "@type": "something.example.com/jsonpb.Simple",
   358      "oBool": true
   359    }
   360  }`
   361  
   362  	anyWellKnown = &pb.KnownTypes{
   363  		An: &types.Any{
   364  			TypeUrl: "type.googleapis.com/google.protobuf.Duration",
   365  			Value: []byte{
   366  				// &types.Duration{Seconds: 1, Nanos: 212000000 }
   367  				1 << 3, 1, // seconds
   368  				2 << 3, 0x80, 0xba, 0x8b, 0x65, // nanos
   369  			},
   370  		},
   371  	}
   372  	anyWellKnownJSON       = `{"an":{"@type":"type.googleapis.com/google.protobuf.Duration","value":"1.212s"}}`
   373  	anyWellKnownPrettyJSON = `{
   374    "an": {
   375      "@type": "type.googleapis.com/google.protobuf.Duration",
   376      "value": "1.212s"
   377    }
   378  }`
   379  
   380  	nonFinites = &pb.NonFinites{
   381  		FNan:  proto.Float32(float32(math.NaN())),
   382  		FPinf: proto.Float32(float32(math.Inf(1))),
   383  		FNinf: proto.Float32(float32(math.Inf(-1))),
   384  		DNan:  proto.Float64(float64(math.NaN())),
   385  		DPinf: proto.Float64(float64(math.Inf(1))),
   386  		DNinf: proto.Float64(float64(math.Inf(-1))),
   387  	}
   388  	nonFinitesJSON = `{` +
   389  		`"fNan":"NaN",` +
   390  		`"fPinf":"Infinity",` +
   391  		`"fNinf":"-Infinity",` +
   392  		`"dNan":"NaN",` +
   393  		`"dPinf":"Infinity",` +
   394  		`"dNinf":"-Infinity"` +
   395  		`}`
   396  )
   397  
   398  func init() {
   399  	if err := proto.SetExtension(realNumber, pb.E_Name, &realNumberName); err != nil {
   400  		panic(err)
   401  	}
   402  	if err := proto.SetExtension(realNumber, pb.E_Complex_RealExtension, complexNumber); err != nil {
   403  		panic(err)
   404  	}
   405  }
   406  
   407  var marshalingTests = []struct {
   408  	desc      string
   409  	marshaler Marshaler
   410  	pb        proto.Message
   411  	json      string
   412  }{
   413  	{"simple flat object", marshaler, simpleObject, simpleObjectOutputJSON},
   414  	{"simple pretty object", marshalerAllOptions, simpleObject, simpleObjectOutputPrettyJSON},
   415  	{"non-finite floats fields object", marshaler, nonFinites, nonFinitesJSON},
   416  	{"repeated fields flat object", marshaler, repeatsObject, repeatsObjectJSON},
   417  	{"repeated fields pretty object", marshalerAllOptions, repeatsObject, repeatsObjectPrettyJSON},
   418  	{"nested message/enum flat object", marshaler, complexObject, complexObjectJSON},
   419  	{"nested message/enum pretty object", marshalerAllOptions, complexObject, complexObjectPrettyJSON},
   420  	{"enum-string flat object", Marshaler{},
   421  		&pb.Widget{Color: pb.Widget_BLUE.Enum()}, `{"color":"BLUE"}`},
   422  	{"enum-value pretty object", Marshaler{EnumsAsInts: true, Indent: " "},
   423  		&pb.Widget{Color: pb.Widget_BLUE.Enum()}, colorPrettyJSON},
   424  	{"unknown enum value object", marshalerAllOptions,
   425  		&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}, colorListPrettyJSON},
   426  	{"repeated proto3 enum", Marshaler{},
   427  		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
   428  			proto3pb.Message_PUNS,
   429  			proto3pb.Message_SLAPSTICK,
   430  		}},
   431  		`{"rFunny":["PUNS","SLAPSTICK"]}`},
   432  	{"repeated proto3 enum as int", Marshaler{EnumsAsInts: true},
   433  		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
   434  			proto3pb.Message_PUNS,
   435  			proto3pb.Message_SLAPSTICK,
   436  		}},
   437  		`{"rFunny":[1,2]}`},
   438  	{"empty value", marshaler, &pb.Simple3{}, `{}`},
   439  	{"empty value emitted", Marshaler{EmitDefaults: true}, &pb.Simple3{}, `{"dub":0}`},
   440  	{"empty repeated emitted", Marshaler{EmitDefaults: true}, &pb.SimpleSlice3{}, `{"slices":[]}`},
   441  	{"empty map emitted", Marshaler{EmitDefaults: true}, &pb.SimpleMap3{}, `{"stringy":{}}`},
   442  	{"nested struct null", Marshaler{EmitDefaults: true}, &pb.SimpleNull3{}, `{"simple":null}`},
   443  	{"map<int64, int32>", marshaler, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, `{"nummy":{"1":2,"3":4}}`},
   444  	{"map<int64, int32>", marshalerAllOptions, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, nummyPrettyJSON},
   445  	{"map<string, string>", marshaler,
   446  		&pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}},
   447  		`{"strry":{"\"one\"":"two","three":"four"}}`},
   448  	{"map<int32, Object>", marshaler,
   449  		&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, `{"objjy":{"1":{"dub":1}}}`},
   450  	{"map<int32, Object>", marshalerAllOptions,
   451  		&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, objjyPrettyJSON},
   452  	{"map<int64, string>", marshaler, &pb.Mappy{Buggy: map[int64]string{1234: "yup"}},
   453  		`{"buggy":{"1234":"yup"}}`},
   454  	{"map<bool, bool>", marshaler, &pb.Mappy{Booly: map[bool]bool{false: true}}, `{"booly":{"false":true}}`},
   455  	{"map<string, enum>", marshaler, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":"ROMAN"}}`},
   456  	{"map<string, enum as int>", Marshaler{EnumsAsInts: true}, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":2}}`},
   457  	{"map<int32, bool>", marshaler, &pb.Mappy{S32Booly: map[int32]bool{1: true, 3: false, 10: true, 12: false}}, `{"s32booly":{"1":true,"3":false,"10":true,"12":false}}`},
   458  	{"map<int64, bool>", marshaler, &pb.Mappy{S64Booly: map[int64]bool{1: true, 3: false, 10: true, 12: false}}, `{"s64booly":{"1":true,"3":false,"10":true,"12":false}}`},
   459  	{"map<uint32, bool>", marshaler, &pb.Mappy{U32Booly: map[uint32]bool{1: true, 3: false, 10: true, 12: false}}, `{"u32booly":{"1":true,"3":false,"10":true,"12":false}}`},
   460  	{"map<uint64, bool>", marshaler, &pb.Mappy{U64Booly: map[uint64]bool{1: true, 3: false, 10: true, 12: false}}, `{"u64booly":{"1":true,"3":false,"10":true,"12":false}}`},
   461  	{"proto2 map<int64, string>", marshaler, &pb.Maps{MInt64Str: map[int64]string{213: "cat"}},
   462  		`{"mInt64Str":{"213":"cat"}}`},
   463  	{"proto2 map<bool, Object>", marshaler,
   464  		&pb.Maps{MBoolSimple: map[bool]*pb.Simple{true: {OInt32: proto.Int32(1)}}},
   465  		`{"mBoolSimple":{"true":{"oInt32":1}}}`},
   466  	{"oneof, not set", marshaler, &pb.MsgWithOneof{}, `{}`},
   467  	{"oneof, set", marshaler, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Title{Title: "Grand Poobah"}}, `{"title":"Grand Poobah"}`},
   468  	{"force orig_name", Marshaler{OrigName: true}, &pb.Simple{OInt32: proto.Int32(4)},
   469  		`{"o_int32":4}`},
   470  	{"proto2 extension", marshaler, realNumber, realNumberJSON},
   471  	{"Any with message", marshaler, anySimple, anySimpleJSON},
   472  	{"Any with message and indent", marshalerAllOptions, anySimple, anySimplePrettyJSON},
   473  	{"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON},
   474  	{"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON},
   475  	{"Duration empty", marshaler, &types.Duration{}, `"0s"`},
   476  	{"Duration with secs", marshaler, &types.Duration{Seconds: 3}, `"3s"`},
   477  	{"Duration with -secs", marshaler, &types.Duration{Seconds: -3}, `"-3s"`},
   478  	{"Duration with nanos", marshaler, &types.Duration{Nanos: 1e6}, `"0.001s"`},
   479  	{"Duration with -nanos", marshaler, &types.Duration{Nanos: -1e6}, `"-0.001s"`},
   480  	{"Duration with large secs", marshaler, &types.Duration{Seconds: 1e10, Nanos: 1}, `"10000000000.000000001s"`},
   481  	{"Duration with 6-digit nanos", marshaler, &types.Duration{Nanos: 1e4}, `"0.000010s"`},
   482  	{"Duration with 3-digit nanos", marshaler, &types.Duration{Nanos: 1e6}, `"0.001s"`},
   483  	{"Duration with -secs -nanos", marshaler, &types.Duration{Seconds: -123, Nanos: -450}, `"-123.000000450s"`},
   484  	{"Duration max value", marshaler, &types.Duration{Seconds: 315576000000, Nanos: 999999999}, `"315576000000.999999999s"`},
   485  	{"Duration small negative", marshaler, &types.Duration{Nanos: -1}, `"-0.000000001s"`},
   486  	{"Duration min value", marshaler, &types.Duration{Seconds: -315576000000, Nanos: -999999999}, `"-315576000000.999999999s"`},
   487  	{"Struct", marshaler, &pb.KnownTypes{St: &types.Struct{
   488  		Fields: map[string]*types.Value{
   489  			"one": {Kind: &types.Value_StringValue{StringValue: "loneliest number"}},
   490  			"two": {Kind: &types.Value_NullValue{NullValue: types.NullValue_NULL_VALUE}},
   491  		},
   492  	}}, `{"st":{"one":"loneliest number","two":null}}`},
   493  	{"empty ListValue", marshaler, &pb.KnownTypes{Lv: &types.ListValue{}}, `{"lv":[]}`},
   494  	{"basic ListValue", marshaler, &pb.KnownTypes{Lv: &types.ListValue{Values: []*types.Value{
   495  		{Kind: &types.Value_StringValue{StringValue: "x"}},
   496  		{Kind: &types.Value_NullValue{}},
   497  		{Kind: &types.Value_NumberValue{NumberValue: 3}},
   498  		{Kind: &types.Value_BoolValue{BoolValue: true}},
   499  	}}}, `{"lv":["x",null,3,true]}`},
   500  	{"Timestamp", marshaler, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`},
   501  	{"Timestamp", marshaler, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 0}}, `{"ts":"2014-05-13T16:53:20Z"}`},
   502  	{"number Value", marshaler, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_NumberValue{NumberValue: 1}}}, `{"val":1}`},
   503  	{"null Value", marshaler, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_NullValue{NullValue: types.NullValue_NULL_VALUE}}}, `{"val":null}`},
   504  	{"string number value", marshaler, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_StringValue{StringValue: "9223372036854775807"}}}, `{"val":"9223372036854775807"}`},
   505  	{"list of lists Value", marshaler, &pb.KnownTypes{Val: &types.Value{
   506  		Kind: &types.Value_ListValue{ListValue: &types.ListValue{
   507  			Values: []*types.Value{
   508  				{Kind: &types.Value_StringValue{StringValue: "x"}},
   509  				{Kind: &types.Value_ListValue{ListValue: &types.ListValue{
   510  					Values: []*types.Value{
   511  						{Kind: &types.Value_ListValue{ListValue: &types.ListValue{
   512  							Values: []*types.Value{{Kind: &types.Value_StringValue{StringValue: "y"}}},
   513  						}}},
   514  						{Kind: &types.Value_StringValue{StringValue: "z"}},
   515  					},
   516  				}}},
   517  			},
   518  		}},
   519  	}}, `{"val":["x",[["y"],"z"]]}`},
   520  	{"DoubleValue", marshaler, &pb.KnownTypes{Dbl: &types.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`},
   521  	{"FloatValue", marshaler, &pb.KnownTypes{Flt: &types.FloatValue{Value: 1.2}}, `{"flt":1.2}`},
   522  	{"Int64Value", marshaler, &pb.KnownTypes{I64: &types.Int64Value{Value: -3}}, `{"i64":"-3"}`},
   523  	{"UInt64Value", marshaler, &pb.KnownTypes{U64: &types.UInt64Value{Value: 3}}, `{"u64":"3"}`},
   524  	{"Int32Value", marshaler, &pb.KnownTypes{I32: &types.Int32Value{Value: -4}}, `{"i32":-4}`},
   525  	{"UInt32Value", marshaler, &pb.KnownTypes{U32: &types.UInt32Value{Value: 4}}, `{"u32":4}`},
   526  	{"BoolValue", marshaler, &pb.KnownTypes{Bool: &types.BoolValue{Value: true}}, `{"bool":true}`},
   527  	{"StringValue", marshaler, &pb.KnownTypes{Str: &types.StringValue{Value: "plush"}}, `{"str":"plush"}`},
   528  	{"BytesValue", marshaler, &pb.KnownTypes{Bytes: &types.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`},
   529  	{"required", marshaler, &pb.MsgWithRequired{Str: proto.String("hello")}, `{"str":"hello"}`},
   530  	{"required bytes", marshaler, &pb.MsgWithRequiredBytes{Byts: []byte{}}, `{"byts":""}`},
   531  }
   532  
   533  func TestMarshaling(t *testing.T) {
   534  	for _, tt := range marshalingTests {
   535  		json, err := tt.marshaler.MarshalToString(tt.pb)
   536  		if err != nil {
   537  			t.Errorf("%s: marshaling error: %v", tt.desc, err)
   538  		} else if tt.json != json {
   539  			t.Errorf("%s: got [%v] want [%v]", tt.desc, json, tt.json)
   540  		}
   541  	}
   542  }
   543  
   544  func TestMarshalingNil(t *testing.T) {
   545  	var msg *pb.Simple
   546  	m := &Marshaler{}
   547  	if _, err := m.MarshalToString(msg); err == nil {
   548  		t.Errorf("mashaling nil returned no error")
   549  	}
   550  }
   551  
   552  func TestMarshalIllegalTime(t *testing.T) {
   553  	tests := []struct {
   554  		pb   proto.Message
   555  		fail bool
   556  	}{
   557  		{&types.Duration{Seconds: 1, Nanos: 0}, false},
   558  		{&types.Duration{Seconds: -1, Nanos: 0}, false},
   559  		{&types.Duration{Seconds: 1, Nanos: -1}, true},
   560  		{&types.Duration{Seconds: -1, Nanos: 1}, true},
   561  		{&types.Duration{Seconds: 315576000001}, true},
   562  		{&types.Duration{Seconds: -315576000001}, true},
   563  		{&types.Duration{Seconds: 1, Nanos: 1000000000}, true},
   564  		{&types.Duration{Seconds: -1, Nanos: -1000000000}, true},
   565  		{&types.Timestamp{Seconds: 1, Nanos: 1}, false},
   566  		{&types.Timestamp{Seconds: 1, Nanos: -1}, true},
   567  		{&types.Timestamp{Seconds: 1, Nanos: 1000000000}, true},
   568  	}
   569  	for _, tt := range tests {
   570  		_, err := marshaler.MarshalToString(tt.pb)
   571  		if err == nil && tt.fail {
   572  			t.Errorf("marshaler.MarshalToString(%v) = _, <nil>; want _, <non-nil>", tt.pb)
   573  		}
   574  		if err != nil && !tt.fail {
   575  			t.Errorf("marshaler.MarshalToString(%v) = _, %v; want _, <nil>", tt.pb, err)
   576  		}
   577  	}
   578  }
   579  
   580  func TestMarshalJSONPBMarshaler(t *testing.T) {
   581  	rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }`
   582  	msg := dynamicMessage{RawJson: rawJson}
   583  	str, err := new(Marshaler).MarshalToString(&msg)
   584  	if err != nil {
   585  		t.Errorf("an unexpected error occurred when marshalling JSONPBMarshaler: %v", err)
   586  	}
   587  	if str != rawJson {
   588  		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, rawJson)
   589  	}
   590  }
   591  
   592  func TestMarshalAnyJSONPBMarshaler(t *testing.T) {
   593  	msg := dynamicMessage{RawJson: `{ "foo": "bar", "baz": [0, 1, 2, 3] }`}
   594  	a, err := types.MarshalAny(&msg)
   595  	if err != nil {
   596  		t.Errorf("an unexpected error occurred when marshalling to Any: %v", err)
   597  	}
   598  	str, err := new(Marshaler).MarshalToString(a)
   599  	if err != nil {
   600  		t.Errorf("an unexpected error occurred when marshalling Any to JSON: %v", err)
   601  	}
   602  	// after custom marshaling, it's round-tripped through JSON decoding/encoding already,
   603  	// so the keys are sorted, whitespace is compacted, and "@type" key has been added
   604  	expected := `{"@type":"type.googleapis.com/` + dynamicMessageName + `","baz":[0,1,2,3],"foo":"bar"}`
   605  	if str != expected {
   606  		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, expected)
   607  	}
   608  
   609  	// Do it again, but this time with indentation:
   610  
   611  	marshaler := Marshaler{Indent: "  "}
   612  	str, err = marshaler.MarshalToString(a)
   613  	if err != nil {
   614  		t.Errorf("an unexpected error occurred when marshalling Any to JSON: %v", err)
   615  	}
   616  	// same as expected above, but pretty-printed w/ indentation
   617  	expected = `{
   618    "@type": "type.googleapis.com/` + dynamicMessageName + `",
   619    "baz": [
   620      0,
   621      1,
   622      2,
   623      3
   624    ],
   625    "foo": "bar"
   626  }`
   627  	if str != expected {
   628  		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, expected)
   629  	}
   630  }
   631  
   632  func TestMarshalWithCustomValidation(t *testing.T) {
   633  	msg := dynamicMessage{RawJson: `{ "foo": "bar", "baz": [0, 1, 2, 3] }`, Dummy: &dynamicMessage{}}
   634  
   635  	js, err := new(Marshaler).MarshalToString(&msg)
   636  	if err != nil {
   637  		t.Errorf("an unexpected error occurred when marshalling to json: %v", err)
   638  	}
   639  	err = Unmarshal(strings.NewReader(js), &msg)
   640  	if err != nil {
   641  		t.Errorf("an unexpected error occurred when unmarshalling from json: %v", err)
   642  	}
   643  }
   644  
   645  // Test marshaling message containing unset required fields should produce error.
   646  func TestMarshalUnsetRequiredFields(t *testing.T) {
   647  	msgExt := &pb.Real{}
   648  	proto.SetExtension(msgExt, pb.E_Extm, &pb.MsgWithRequired{})
   649  
   650  	tests := []struct {
   651  		desc      string
   652  		marshaler *Marshaler
   653  		pb        proto.Message
   654  	}{
   655  		{
   656  			desc:      "direct required field",
   657  			marshaler: &Marshaler{},
   658  			pb:        &pb.MsgWithRequired{},
   659  		},
   660  		{
   661  			desc:      "direct required field + emit defaults",
   662  			marshaler: &Marshaler{EmitDefaults: true},
   663  			pb:        &pb.MsgWithRequired{},
   664  		},
   665  		{
   666  			desc:      "indirect required field",
   667  			marshaler: &Marshaler{},
   668  			pb:        &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
   669  		},
   670  		{
   671  			desc:      "indirect required field + emit defaults",
   672  			marshaler: &Marshaler{EmitDefaults: true},
   673  			pb:        &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
   674  		},
   675  		{
   676  			desc:      "direct required wkt field",
   677  			marshaler: &Marshaler{},
   678  			pb:        &pb.MsgWithRequiredWKT{},
   679  		},
   680  		{
   681  			desc:      "direct required wkt field + emit defaults",
   682  			marshaler: &Marshaler{EmitDefaults: true},
   683  			pb:        &pb.MsgWithRequiredWKT{},
   684  		},
   685  		{
   686  			desc:      "direct required bytes field",
   687  			marshaler: &Marshaler{},
   688  			pb:        &pb.MsgWithRequiredBytes{},
   689  		},
   690  		{
   691  			desc:      "required in map value",
   692  			marshaler: &Marshaler{},
   693  			pb: &pb.MsgWithIndirectRequired{
   694  				MapField: map[string]*pb.MsgWithRequired{
   695  					"key": {},
   696  				},
   697  			},
   698  		},
   699  		{
   700  			desc:      "required in repeated item",
   701  			marshaler: &Marshaler{},
   702  			pb: &pb.MsgWithIndirectRequired{
   703  				SliceField: []*pb.MsgWithRequired{
   704  					{Str: proto.String("hello")},
   705  					{},
   706  				},
   707  			},
   708  		},
   709  		{
   710  			desc:      "required inside oneof",
   711  			marshaler: &Marshaler{},
   712  			pb: &pb.MsgWithOneof{
   713  				Union: &pb.MsgWithOneof_MsgWithRequired{MsgWithRequired: &pb.MsgWithRequired{}},
   714  			},
   715  		},
   716  		{
   717  			desc:      "required inside extension",
   718  			marshaler: &Marshaler{},
   719  			pb:        msgExt,
   720  		},
   721  	}
   722  
   723  	for _, tc := range tests {
   724  		if _, err := tc.marshaler.MarshalToString(tc.pb); err == nil {
   725  			t.Errorf("%s: expecting error in marshaling with unset required fields %+v", tc.desc, tc.pb)
   726  		}
   727  	}
   728  }
   729  
   730  var unmarshalingTests = []struct {
   731  	desc        string
   732  	unmarshaler Unmarshaler
   733  	json        string
   734  	pb          proto.Message
   735  }{
   736  	{"simple flat object", Unmarshaler{}, simpleObjectInputJSON, simpleObject},
   737  	{"simple pretty object", Unmarshaler{}, simpleObjectInputPrettyJSON, simpleObject},
   738  	{"repeated fields flat object", Unmarshaler{}, repeatsObjectJSON, repeatsObject},
   739  	{"repeated fields pretty object", Unmarshaler{}, repeatsObjectPrettyJSON, repeatsObject},
   740  	{"nested message/enum flat object", Unmarshaler{}, complexObjectJSON, complexObject},
   741  	{"nested message/enum pretty object", Unmarshaler{}, complexObjectPrettyJSON, complexObject},
   742  	{"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
   743  	{"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
   744  	{"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb.Simple)},
   745  	{"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
   746  	{"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
   747  	{"unknown enum value object",
   748  		Unmarshaler{},
   749  		"{\n  \"color\": 1000,\n  \"r_color\": [\n    \"RED\"\n  ]\n}",
   750  		&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}},
   751  	{"repeated proto3 enum", Unmarshaler{}, `{"rFunny":["PUNS","SLAPSTICK"]}`,
   752  		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
   753  			proto3pb.Message_PUNS,
   754  			proto3pb.Message_SLAPSTICK,
   755  		}}},
   756  	{"repeated proto3 enum as int", Unmarshaler{}, `{"rFunny":[1,2]}`,
   757  		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
   758  			proto3pb.Message_PUNS,
   759  			proto3pb.Message_SLAPSTICK,
   760  		}}},
   761  	{"repeated proto3 enum as mix of strings and ints", Unmarshaler{}, `{"rFunny":["PUNS",2]}`,
   762  		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
   763  			proto3pb.Message_PUNS,
   764  			proto3pb.Message_SLAPSTICK,
   765  		}}},
   766  	{"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
   767  	{"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
   768  	{"NaN", Unmarshaler{}, `{"oDouble":"NaN"}`, &pb.Simple{ODouble: proto.Float64(math.NaN())}},
   769  	{"Inf", Unmarshaler{}, `{"oFloat":"Infinity"}`, &pb.Simple{OFloat: proto.Float32(float32(math.Inf(1)))}},
   770  	{"-Inf", Unmarshaler{}, `{"oDouble":"-Infinity"}`, &pb.Simple{ODouble: proto.Float64(math.Inf(-1))}},
   771  	{"map<int64, int32>", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
   772  	{"map<string, string>", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
   773  	{"map<int32, Object>", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}},
   774  	{"proto2 extension", Unmarshaler{}, realNumberJSON, realNumber},
   775  	// TODO does not work with go version 1.7, but works with go version 1.8 {"Any with message", Unmarshaler{}, anySimpleJSON, anySimple},
   776  	// TODO does not work with go version 1.7, but works with go version 1.8 {"Any with message and indent", Unmarshaler{}, anySimplePrettyJSON, anySimple},
   777  	{"Any with WKT", Unmarshaler{}, anyWellKnownJSON, anyWellKnown},
   778  	{"Any with WKT and indent", Unmarshaler{}, anyWellKnownPrettyJSON, anyWellKnown},
   779  	{"map<string, enum>", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
   780  	{"map<string, enum as int>", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
   781  	{"oneof", Unmarshaler{}, `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{Salary: 31000}}},
   782  	{"oneof spec name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{Country: "Australia"}}},
   783  	{"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{Country: "Australia"}}},
   784  	{"oneof spec name2", Unmarshaler{}, `{"homeAddress":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{HomeAddress: "Australia"}}},
   785  	{"oneof orig_name2", Unmarshaler{}, `{"home_address":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{HomeAddress: "Australia"}}},
   786  	{"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
   787  	{"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
   788  	{"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &types.Duration{Seconds: 3}}},
   789  	{"Duration", Unmarshaler{}, `{"dur":"4s"}`, &pb.KnownTypes{Dur: &types.Duration{Seconds: 4}}},
   790  	{"Duration with unicode", Unmarshaler{}, `{"dur": "3\u0073"}`, &pb.KnownTypes{Dur: &types.Duration{Seconds: 3}}},
   791  	{"null Duration", Unmarshaler{}, `{"dur":null}`, &pb.KnownTypes{Dur: nil}},
   792  	{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
   793  	{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 0}}},
   794  	{"Timestamp with unicode", Unmarshaler{}, `{"ts": "2014-05-13T16:53:20\u005a"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 0}}},
   795  	{"PreEpochTimestamp", Unmarshaler{}, `{"ts":"1969-12-31T23:59:58.999999995Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: -2, Nanos: 999999995}}},
   796  	{"ZeroTimeTimestamp", Unmarshaler{}, `{"ts":"0001-01-01T00:00:00Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: -62135596800, Nanos: 0}}},
   797  	{"null Timestamp", Unmarshaler{}, `{"ts":null}`, &pb.KnownTypes{Ts: nil}},
   798  	{"null Struct", Unmarshaler{}, `{"st": null}`, &pb.KnownTypes{St: nil}},
   799  	{"empty Struct", Unmarshaler{}, `{"st": {}}`, &pb.KnownTypes{St: &types.Struct{}}},
   800  	{"basic Struct", Unmarshaler{}, `{"st": {"a": "x", "b": null, "c": 3, "d": true}}`, &pb.KnownTypes{St: &types.Struct{Fields: map[string]*types.Value{
   801  		"a": {Kind: &types.Value_StringValue{StringValue: "x"}},
   802  		"b": {Kind: &types.Value_NullValue{}},
   803  		"c": {Kind: &types.Value_NumberValue{NumberValue: 3}},
   804  		"d": {Kind: &types.Value_BoolValue{BoolValue: true}},
   805  	}}}},
   806  	{"nested Struct", Unmarshaler{}, `{"st": {"a": {"b": 1, "c": [{"d": true}, "f"]}}}`, &pb.KnownTypes{St: &types.Struct{Fields: map[string]*types.Value{
   807  		"a": {Kind: &types.Value_StructValue{StructValue: &types.Struct{Fields: map[string]*types.Value{
   808  			"b": {Kind: &types.Value_NumberValue{NumberValue: 1}},
   809  			"c": {Kind: &types.Value_ListValue{ListValue: &types.ListValue{Values: []*types.Value{
   810  				{Kind: &types.Value_StructValue{StructValue: &types.Struct{Fields: map[string]*types.Value{"d": {Kind: &types.Value_BoolValue{BoolValue: true}}}}}},
   811  				{Kind: &types.Value_StringValue{StringValue: "f"}},
   812  			}}}},
   813  		}}}},
   814  	}}}},
   815  	{"null ListValue", Unmarshaler{}, `{"lv": null}`, &pb.KnownTypes{Lv: nil}},
   816  	{"empty ListValue", Unmarshaler{}, `{"lv": []}`, &pb.KnownTypes{Lv: &types.ListValue{}}},
   817  	{"basic ListValue", Unmarshaler{}, `{"lv": ["x", null, 3, true]}`, &pb.KnownTypes{Lv: &types.ListValue{Values: []*types.Value{
   818  		{Kind: &types.Value_StringValue{StringValue: "x"}},
   819  		{Kind: &types.Value_NullValue{}},
   820  		{Kind: &types.Value_NumberValue{NumberValue: 3}},
   821  		{Kind: &types.Value_BoolValue{BoolValue: true}},
   822  	}}}},
   823  	{"number Value", Unmarshaler{}, `{"val":1}`, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_NumberValue{NumberValue: 1}}}},
   824  	{"null Value", Unmarshaler{}, `{"val":null}`, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_NullValue{NullValue: types.NullValue_NULL_VALUE}}}},
   825  	{"bool Value", Unmarshaler{}, `{"val":true}`, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_BoolValue{BoolValue: true}}}},
   826  	{"string Value", Unmarshaler{}, `{"val":"x"}`, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_StringValue{StringValue: "x"}}}},
   827  	{"string number value", Unmarshaler{}, `{"val":"9223372036854775807"}`, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_StringValue{StringValue: "9223372036854775807"}}}},
   828  	{"list of lists Value", Unmarshaler{}, `{"val":["x", [["y"], "z"]]}`, &pb.KnownTypes{Val: &types.Value{
   829  		Kind: &types.Value_ListValue{ListValue: &types.ListValue{
   830  			Values: []*types.Value{
   831  				{Kind: &types.Value_StringValue{StringValue: "x"}},
   832  				{Kind: &types.Value_ListValue{ListValue: &types.ListValue{
   833  					Values: []*types.Value{
   834  						{Kind: &types.Value_ListValue{ListValue: &types.ListValue{
   835  							Values: []*types.Value{{Kind: &types.Value_StringValue{StringValue: "y"}}},
   836  						}}},
   837  						{Kind: &types.Value_StringValue{StringValue: "z"}},
   838  					},
   839  				}}},
   840  			},
   841  		}}}}},
   842  
   843  	{"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &types.DoubleValue{Value: 1.2}}},
   844  	{"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &types.FloatValue{Value: 1.2}}},
   845  	{"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb.KnownTypes{I64: &types.Int64Value{Value: -3}}},
   846  	{"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb.KnownTypes{U64: &types.UInt64Value{Value: 3}}},
   847  	{"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb.KnownTypes{I32: &types.Int32Value{Value: -4}}},
   848  	{"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb.KnownTypes{U32: &types.UInt32Value{Value: 4}}},
   849  	{"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb.KnownTypes{Bool: &types.BoolValue{Value: true}}},
   850  	{"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb.KnownTypes{Str: &types.StringValue{Value: "plush"}}},
   851  	{"StringValue containing escaped character", Unmarshaler{}, `{"str":"a\/b"}`, &pb.KnownTypes{Str: &types.StringValue{Value: "a/b"}}},
   852  	{"StructValue containing StringValue's", Unmarshaler{}, `{"escaped": "a\/b", "unicode": "\u00004E16\u0000754C"}`,
   853  		&types.Struct{
   854  			Fields: map[string]*types.Value{
   855  				"escaped": {Kind: &types.Value_StringValue{StringValue: "a/b"}},
   856  				"unicode": {Kind: &types.Value_StringValue{StringValue: "\u00004E16\u0000754C"}},
   857  			},
   858  		}},
   859  	{"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &types.BytesValue{Value: []byte("wow")}}},
   860  	// Ensure that `null` as a value ends up with a nil pointer instead of a [type]Value struct.
   861  	{"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb.KnownTypes{Dbl: nil}},
   862  	{"null FloatValue", Unmarshaler{}, `{"flt":null}`, &pb.KnownTypes{Flt: nil}},
   863  	{"null Int64Value", Unmarshaler{}, `{"i64":null}`, &pb.KnownTypes{I64: nil}},
   864  	{"null UInt64Value", Unmarshaler{}, `{"u64":null}`, &pb.KnownTypes{U64: nil}},
   865  	{"null Int32Value", Unmarshaler{}, `{"i32":null}`, &pb.KnownTypes{I32: nil}},
   866  	{"null UInt32Value", Unmarshaler{}, `{"u32":null}`, &pb.KnownTypes{U32: nil}},
   867  	{"null BoolValue", Unmarshaler{}, `{"bool":null}`, &pb.KnownTypes{Bool: nil}},
   868  	{"null StringValue", Unmarshaler{}, `{"str":null}`, &pb.KnownTypes{Str: nil}},
   869  	{"null BytesValue", Unmarshaler{}, `{"bytes":null}`, &pb.KnownTypes{Bytes: nil}},
   870  	{"required", Unmarshaler{}, `{"str":"hello"}`, &pb.MsgWithRequired{Str: proto.String("hello")}},
   871  	{"required bytes", Unmarshaler{}, `{"byts": []}`, &pb.MsgWithRequiredBytes{Byts: []byte{}}},
   872  }
   873  
   874  func TestUnmarshaling(t *testing.T) {
   875  	for _, tt := range unmarshalingTests {
   876  		// Make a new instance of the type of our expected object.
   877  		p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
   878  
   879  		err := tt.unmarshaler.Unmarshal(strings.NewReader(tt.json), p)
   880  		if err != nil {
   881  			t.Errorf("unmarshalling %s: %v", tt.desc, err)
   882  			continue
   883  		}
   884  
   885  		// For easier diffs, compare text strings of the protos.
   886  		exp := proto.MarshalTextString(tt.pb)
   887  		act := proto.MarshalTextString(p)
   888  		if string(exp) != string(act) {
   889  			t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
   890  		}
   891  	}
   892  }
   893  
   894  func TestUnmarshalNullArray(t *testing.T) {
   895  	var repeats pb.Repeats
   896  	if err := UnmarshalString(`{"rBool":null}`, &repeats); err != nil {
   897  		t.Fatal(err)
   898  	}
   899  	if !reflect.DeepEqual(repeats, pb.Repeats{}) {
   900  		t.Errorf("got non-nil fields in [%#v]", repeats)
   901  	}
   902  }
   903  
   904  func TestUnmarshalNullObject(t *testing.T) {
   905  	var maps pb.Maps
   906  	if err := UnmarshalString(`{"mInt64Str":null}`, &maps); err != nil {
   907  		t.Fatal(err)
   908  	}
   909  	if !reflect.DeepEqual(maps, pb.Maps{}) {
   910  		t.Errorf("got non-nil fields in [%#v]", maps)
   911  	}
   912  }
   913  
   914  func TestUnmarshalNext(t *testing.T) {
   915  	// We only need to check against a few, not all of them.
   916  	tests := unmarshalingTests[:5]
   917  
   918  	// Create a buffer with many concatenated JSON objects.
   919  	var b bytes.Buffer
   920  	for _, tt := range tests {
   921  		b.WriteString(tt.json)
   922  	}
   923  
   924  	dec := json.NewDecoder(&b)
   925  	for _, tt := range tests {
   926  		// Make a new instance of the type of our expected object.
   927  		p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
   928  
   929  		err := tt.unmarshaler.UnmarshalNext(dec, p)
   930  		if err != nil {
   931  			t.Errorf("%s: %v", tt.desc, err)
   932  			continue
   933  		}
   934  
   935  		// For easier diffs, compare text strings of the protos.
   936  		exp := proto.MarshalTextString(tt.pb)
   937  		act := proto.MarshalTextString(p)
   938  		if string(exp) != string(act) {
   939  			t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
   940  		}
   941  	}
   942  
   943  	p := &pb.Simple{}
   944  	err := new(Unmarshaler).UnmarshalNext(dec, p)
   945  	if err != io.EOF {
   946  		t.Errorf("eof: got %v, expected io.EOF", err)
   947  	}
   948  }
   949  
   950  var unmarshalingShouldError = []struct {
   951  	desc string
   952  	in   string
   953  	pb   proto.Message
   954  }{
   955  	{"a value", "666", new(pb.Simple)},
   956  	{"gibberish", "{adskja123;l23=-=", new(pb.Simple)},
   957  	{"unknown field", `{"unknown": "foo"}`, new(pb.Simple)},
   958  	{"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)},
   959  	{"Duration containing invalid character", `{"dur": "3\U0073"}`, &pb.KnownTypes{}},
   960  	{"Timestamp containing invalid character", `{"ts": "2014-05-13T16:53:20\U005a"}`, &pb.KnownTypes{}},
   961  	{"StringValue containing invalid character", `{"str": "\U00004E16\U0000754C"}`, &pb.KnownTypes{}},
   962  	{"StructValue containing invalid character", `{"str": "\U00004E16\U0000754C"}`, &types.Struct{}},
   963  	{"repeated proto3 enum with non array input", `{"rFunny":"PUNS"}`, &proto3pb.Message{RFunny: []proto3pb.Message_Humour{}}},
   964  }
   965  
   966  func TestUnmarshalingBadInput(t *testing.T) {
   967  	for _, tt := range unmarshalingShouldError {
   968  		err := UnmarshalString(tt.in, tt.pb)
   969  		if err == nil {
   970  			t.Errorf("an error was expected when parsing %q instead of an object", tt.desc)
   971  		}
   972  	}
   973  }
   974  
   975  type funcResolver func(turl string) (proto.Message, error)
   976  
   977  func (fn funcResolver) Resolve(turl string) (proto.Message, error) {
   978  	return fn(turl)
   979  }
   980  
   981  func TestAnyWithCustomResolver(t *testing.T) {
   982  	var resolvedTypeUrls []string
   983  	resolver := funcResolver(func(turl string) (proto.Message, error) {
   984  		resolvedTypeUrls = append(resolvedTypeUrls, turl)
   985  		return new(pb.Simple), nil
   986  	})
   987  	msg := &pb.Simple{
   988  		OBytes:  []byte{1, 2, 3, 4},
   989  		OBool:   proto.Bool(true),
   990  		OString: proto.String("foobar"),
   991  		OInt64:  proto.Int64(1020304),
   992  	}
   993  	msgBytes, err := proto.Marshal(msg)
   994  	if err != nil {
   995  		t.Errorf("an unexpected error occurred when marshaling message: %v", err)
   996  	}
   997  	// make an Any with a type URL that won't resolve w/out custom resolver
   998  	any := &types.Any{
   999  		TypeUrl: "https://foobar.com/some.random.MessageKind",
  1000  		Value:   msgBytes,
  1001  	}
  1002  
  1003  	m := Marshaler{AnyResolver: resolver}
  1004  	js, err := m.MarshalToString(any)
  1005  	if err != nil {
  1006  		t.Errorf("an unexpected error occurred when marshaling any to JSON: %v", err)
  1007  	}
  1008  	if len(resolvedTypeUrls) != 1 {
  1009  		t.Errorf("custom resolver was not invoked during marshaling")
  1010  	} else if resolvedTypeUrls[0] != "https://foobar.com/some.random.MessageKind" {
  1011  		t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[0], "https://foobar.com/some.random.MessageKind")
  1012  	}
  1013  	wanted := `{"@type":"https://foobar.com/some.random.MessageKind","oBool":true,"oInt64":"1020304","oString":"foobar","oBytes":"AQIDBA=="}`
  1014  	if js != wanted {
  1015  		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", js, wanted)
  1016  	}
  1017  
  1018  	u := Unmarshaler{AnyResolver: resolver}
  1019  	roundTrip := &types.Any{}
  1020  	err = u.Unmarshal(bytes.NewReader([]byte(js)), roundTrip)
  1021  	if err != nil {
  1022  		t.Errorf("an unexpected error occurred when unmarshaling any from JSON: %v", err)
  1023  	}
  1024  	if len(resolvedTypeUrls) != 2 {
  1025  		t.Errorf("custom resolver was not invoked during marshaling")
  1026  	} else if resolvedTypeUrls[1] != "https://foobar.com/some.random.MessageKind" {
  1027  		t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[1], "https://foobar.com/some.random.MessageKind")
  1028  	}
  1029  	if !proto.Equal(any, roundTrip) {
  1030  		t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", roundTrip, any)
  1031  	}
  1032  }
  1033  
  1034  func TestUnmarshalJSONPBUnmarshaler(t *testing.T) {
  1035  	rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }`
  1036  	var msg dynamicMessage
  1037  	if err := Unmarshal(strings.NewReader(rawJson), &msg); err != nil {
  1038  		t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err)
  1039  	}
  1040  	if msg.RawJson != rawJson {
  1041  		t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", msg.RawJson, rawJson)
  1042  	}
  1043  }
  1044  
  1045  func TestUnmarshalNullWithJSONPBUnmarshaler(t *testing.T) {
  1046  	rawJson := `{"stringField":null}`
  1047  	var ptrFieldMsg ptrFieldMessage
  1048  	if err := Unmarshal(strings.NewReader(rawJson), &ptrFieldMsg); err != nil {
  1049  		t.Errorf("unmarshal error: %v", err)
  1050  	}
  1051  
  1052  	want := ptrFieldMessage{StringField: &stringField{IsSet: true, StringValue: "null"}}
  1053  	if !proto.Equal(&ptrFieldMsg, &want) {
  1054  		t.Errorf("unmarshal result StringField: got %v, want %v", ptrFieldMsg, want)
  1055  	}
  1056  }
  1057  
  1058  func TestUnmarshalAnyJSONPBUnmarshaler(t *testing.T) {
  1059  	rawJson := `{ "@type": "blah.com/` + dynamicMessageName + `", "foo": "bar", "baz": [0, 1, 2, 3] }`
  1060  	var got types.Any
  1061  	if err := Unmarshal(strings.NewReader(rawJson), &got); err != nil {
  1062  		t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err)
  1063  	}
  1064  
  1065  	dm := &dynamicMessage{RawJson: `{"baz":[0,1,2,3],"foo":"bar"}`}
  1066  	var want types.Any
  1067  	if b, err := proto.Marshal(dm); err != nil {
  1068  		t.Errorf("an unexpected error occurred when marshaling message: %v", err)
  1069  	} else {
  1070  		want.TypeUrl = "blah.com/" + dynamicMessageName
  1071  		want.Value = b
  1072  	}
  1073  
  1074  	if !proto.Equal(&got, &want) {
  1075  		t.Errorf("message contents not set correctly after unmarshalling JSON: got %v, wanted %v", got, want)
  1076  	}
  1077  }
  1078  
  1079  const (
  1080  	dynamicMessageName = "google.protobuf.jsonpb.testing.dynamicMessage"
  1081  )
  1082  
  1083  func init() {
  1084  	// we register the custom type below so that we can use it in Any types
  1085  	proto.RegisterType((*dynamicMessage)(nil), dynamicMessageName)
  1086  }
  1087  
  1088  type ptrFieldMessage struct {
  1089  	StringField *stringField `protobuf:"bytes,1,opt,name=stringField"`
  1090  }
  1091  
  1092  func (m *ptrFieldMessage) Reset() {
  1093  }
  1094  
  1095  func (m *ptrFieldMessage) String() string {
  1096  	return m.StringField.StringValue
  1097  }
  1098  
  1099  func (m *ptrFieldMessage) ProtoMessage() {
  1100  }
  1101  
  1102  type stringField struct {
  1103  	IsSet       bool   `protobuf:"varint,1,opt,name=isSet"`
  1104  	StringValue string `protobuf:"bytes,2,opt,name=stringValue"`
  1105  }
  1106  
  1107  func (s *stringField) Reset() {
  1108  }
  1109  
  1110  func (s *stringField) String() string {
  1111  	return s.StringValue
  1112  }
  1113  
  1114  func (s *stringField) ProtoMessage() {
  1115  }
  1116  
  1117  func (s *stringField) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
  1118  	s.IsSet = true
  1119  	s.StringValue = string(js)
  1120  	return nil
  1121  }
  1122  
  1123  // dynamicMessage implements protobuf.Message but is not a normal generated message type.
  1124  // It provides implementations of JSONPBMarshaler and JSONPBUnmarshaler for JSON support.
  1125  type dynamicMessage struct {
  1126  	RawJson string `protobuf:"bytes,1,opt,name=rawJson"`
  1127  
  1128  	// an unexported nested message is present just to ensure that it
  1129  	// won't result in a panic (see issue #509)
  1130  	Dummy *dynamicMessage `protobuf:"bytes,2,opt,name=dummy"`
  1131  }
  1132  
  1133  func (m *dynamicMessage) Reset() {
  1134  	m.RawJson = "{}"
  1135  }
  1136  
  1137  func (m *dynamicMessage) String() string {
  1138  	return m.RawJson
  1139  }
  1140  
  1141  func (m *dynamicMessage) ProtoMessage() {
  1142  }
  1143  
  1144  func (m *dynamicMessage) MarshalJSONPB(jm *Marshaler) ([]byte, error) {
  1145  	return []byte(m.RawJson), nil
  1146  }
  1147  
  1148  func (m *dynamicMessage) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
  1149  	m.RawJson = string(js)
  1150  	return nil
  1151  }
  1152  
  1153  // Test unmarshaling message containing unset required fields should produce error.
  1154  func TestUnmarshalUnsetRequiredFields(t *testing.T) {
  1155  	tests := []struct {
  1156  		desc string
  1157  		pb   proto.Message
  1158  		json string
  1159  	}{
  1160  		{
  1161  			desc: "direct required field missing",
  1162  			pb:   &pb.MsgWithRequired{},
  1163  			json: `{}`,
  1164  		},
  1165  		{
  1166  			desc: "direct required field set to null",
  1167  			pb:   &pb.MsgWithRequired{},
  1168  			json: `{"str": null}`,
  1169  		},
  1170  		{
  1171  			desc: "indirect required field missing",
  1172  			pb:   &pb.MsgWithIndirectRequired{},
  1173  			json: `{"subm": {}}`,
  1174  		},
  1175  		{
  1176  			desc: "indirect required field set to null",
  1177  			pb:   &pb.MsgWithIndirectRequired{},
  1178  			json: `{"subm": {"str": null}}`,
  1179  		},
  1180  		{
  1181  			desc: "direct required bytes field missing",
  1182  			pb:   &pb.MsgWithRequiredBytes{},
  1183  			json: `{}`,
  1184  		},
  1185  		{
  1186  			desc: "direct required bytes field set to null",
  1187  			pb:   &pb.MsgWithRequiredBytes{},
  1188  			json: `{"byts": null}`,
  1189  		},
  1190  		{
  1191  			desc: "direct required wkt field missing",
  1192  			pb:   &pb.MsgWithRequiredWKT{},
  1193  			json: `{}`,
  1194  		},
  1195  		{
  1196  			desc: "direct required wkt field set to null",
  1197  			pb:   &pb.MsgWithRequiredWKT{},
  1198  			json: `{"str": null}`,
  1199  		},
  1200  		{
  1201  			desc: "any containing message with required field set to null",
  1202  			pb:   &pb.KnownTypes{},
  1203  			json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired", "str": null}}`,
  1204  		},
  1205  		{
  1206  			desc: "any containing message with missing required field",
  1207  			pb:   &pb.KnownTypes{},
  1208  			json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired"}}`,
  1209  		},
  1210  		{
  1211  			desc: "missing required in map value",
  1212  			pb:   &pb.MsgWithIndirectRequired{},
  1213  			json: `{"map_field": {"a": {}, "b": {"str": "hi"}}}`,
  1214  		},
  1215  		{
  1216  			desc: "required in map value set to null",
  1217  			pb:   &pb.MsgWithIndirectRequired{},
  1218  			json: `{"map_field": {"a": {"str": "hello"}, "b": {"str": null}}}`,
  1219  		},
  1220  		{
  1221  			desc: "missing required in slice item",
  1222  			pb:   &pb.MsgWithIndirectRequired{},
  1223  			json: `{"slice_field": [{}, {"str": "hi"}]}`,
  1224  		},
  1225  		{
  1226  			desc: "required in slice item set to null",
  1227  			pb:   &pb.MsgWithIndirectRequired{},
  1228  			json: `{"slice_field": [{"str": "hello"}, {"str": null}]}`,
  1229  		},
  1230  		{
  1231  			desc: "required inside oneof missing",
  1232  			pb:   &pb.MsgWithOneof{},
  1233  			json: `{"msgWithRequired": {}}`,
  1234  		},
  1235  		{
  1236  			desc: "required inside oneof set to null",
  1237  			pb:   &pb.MsgWithOneof{},
  1238  			json: `{"msgWithRequired": {"str": null}}`,
  1239  		},
  1240  		{
  1241  			desc: "required field in extension missing",
  1242  			pb:   &pb.Real{},
  1243  			json: `{"[jsonpb.extm]":{}}`,
  1244  		},
  1245  		{
  1246  			desc: "required field in extension set to null",
  1247  			pb:   &pb.Real{},
  1248  			json: `{"[jsonpb.extm]":{"str": null}}`,
  1249  		},
  1250  	}
  1251  
  1252  	for _, tc := range tests {
  1253  		if err := UnmarshalString(tc.json, tc.pb); err == nil {
  1254  			t.Errorf("%s: expecting error in unmarshaling with unset required fields %s", tc.desc, tc.json)
  1255  		}
  1256  	}
  1257  }
  1258  

View as plain text