github.com/bakjos/protoreflect@v1.9.2/dynamic/json_test.go (about)

     1  package dynamic
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/golang/protobuf/jsonpb"
    12  	"github.com/golang/protobuf/proto"
    13  	"github.com/golang/protobuf/protoc-gen-go/descriptor"
    14  	"github.com/golang/protobuf/ptypes"
    15  	"github.com/golang/protobuf/ptypes/any"
    16  	"github.com/golang/protobuf/ptypes/duration"
    17  	structpb "github.com/golang/protobuf/ptypes/struct"
    18  	"github.com/golang/protobuf/ptypes/timestamp"
    19  	"github.com/golang/protobuf/ptypes/wrappers"
    20  
    21  	"github.com/bakjos/protoreflect/desc"
    22  	"github.com/bakjos/protoreflect/internal/testprotos"
    23  	"github.com/bakjos/protoreflect/internal/testutil"
    24  )
    25  
    26  func TestJSONUnaryFields(t *testing.T) {
    27  	jsonTranslationParty(t, unaryFieldsPosMsg, false)
    28  	jsonTranslationParty(t, unaryFieldsNegMsg, false)
    29  	jsonTranslationParty(t, unaryFieldsPosInfMsg, false)
    30  	jsonTranslationParty(t, unaryFieldsNegInfMsg, false)
    31  	jsonTranslationParty(t, unaryFieldsNanMsg, true)
    32  }
    33  
    34  func TestJSONRepeatedFields(t *testing.T) {
    35  	jsonTranslationParty(t, repeatedFieldsMsg, false)
    36  	jsonTranslationParty(t, repeatedFieldsInfNanMsg, true)
    37  }
    38  
    39  func TestJSONMapKeyFields(t *testing.T) {
    40  	jsonTranslationParty(t, mapKeyFieldsMsg, false)
    41  }
    42  
    43  func TestJSONMapValueFields(t *testing.T) {
    44  	jsonTranslationParty(t, mapValueFieldsMsg, false)
    45  	jsonTranslationParty(t, mapValueFieldsInfNanMsg, true)
    46  	jsonTranslationParty(t, mapValueFieldsNilMsg, false)
    47  	jsonTranslationParty(t, mapValueFieldsNilUnknownMsg, false)
    48  }
    49  
    50  func TestJSONExtensionFields(t *testing.T) {
    51  	// TODO
    52  }
    53  
    54  func createTestFileDescriptor(t *testing.T, packageName string) *desc.FileDescriptor {
    55  	// Create a new type that could only be resolved via custom resolver
    56  	// because it does not exist in compiled form
    57  	fdp := descriptor.FileDescriptorProto{
    58  		Name:       proto.String(fmt.Sprintf("%s.proto", packageName)),
    59  		Dependency: []string{"google/protobuf/any.proto"},
    60  		Package:    proto.String(packageName),
    61  		MessageType: []*descriptor.DescriptorProto{
    62  			{
    63  				Name: proto.String("MyMessage"),
    64  				Field: []*descriptor.FieldDescriptorProto{
    65  					{
    66  						Name:   proto.String("abc"),
    67  						Number: proto.Int(1),
    68  						Label:  descriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
    69  						Type:   descriptor.FieldDescriptorProto_TYPE_STRING.Enum(),
    70  					},
    71  					{
    72  						Name:   proto.String("def"),
    73  						Number: proto.Int(2),
    74  						Label:  descriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
    75  						Type:   descriptor.FieldDescriptorProto_TYPE_INT32.Enum(),
    76  					},
    77  					{
    78  						Name:     proto.String("ghi"),
    79  						Number:   proto.Int(3),
    80  						Label:    descriptor.FieldDescriptorProto_LABEL_REPEATED.Enum(),
    81  						Type:     descriptor.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
    82  						TypeName: proto.String(".google.protobuf.Any"),
    83  					},
    84  				},
    85  			},
    86  		},
    87  	}
    88  	anyfd, err := desc.LoadFileDescriptor("google/protobuf/any.proto")
    89  	testutil.Ok(t, err)
    90  	fd, err := desc.CreateFileDescriptor(&fdp, anyfd)
    91  	testutil.Ok(t, err)
    92  	return fd
    93  }
    94  
    95  func TestJSONAnyResolver(t *testing.T) {
    96  	fd1 := createTestFileDescriptor(t, "foobar")
    97  	fd2 := createTestFileDescriptor(t, "snafu")
    98  	md := fd1.FindMessage("foobar.MyMessage")
    99  	dm := NewMessage(md)
   100  	dm.SetFieldByNumber(1, "fubar")
   101  	dm.SetFieldByNumber(2, int32(123))
   102  	a1, err := ptypes.MarshalAny(dm)
   103  	testutil.Ok(t, err)
   104  	md = fd2.FindMessage("snafu.MyMessage")
   105  	dm = NewMessage(md)
   106  	dm.SetFieldByNumber(1, "snafu")
   107  	dm.SetFieldByNumber(2, int32(456))
   108  	a2, err := ptypes.MarshalAny(dm)
   109  	testutil.Ok(t, err)
   110  
   111  	msg := &testprotos.TestWellKnownTypes{Extras: []*any.Any{a1, a2}}
   112  	resolver := AnyResolver(nil, fd1, fd2)
   113  
   114  	jsm := jsonpb.Marshaler{AnyResolver: resolver}
   115  	js, err := jsm.MarshalToString(msg)
   116  	testutil.Ok(t, err)
   117  	expected := `{"extras":[{"@type":"type.googleapis.com/foobar.MyMessage","abc":"fubar","def":123},{"@type":"type.googleapis.com/snafu.MyMessage","abc":"snafu","def":456}]}`
   118  	testutil.Eq(t, expected, js)
   119  
   120  	jsu := jsonpb.Unmarshaler{AnyResolver: resolver}
   121  	msg2 := &testprotos.TestWellKnownTypes{}
   122  	err = jsu.Unmarshal(strings.NewReader(js), msg2)
   123  	testutil.Ok(t, err)
   124  
   125  	testutil.Ceq(t, msg, msg2, eqpm)
   126  }
   127  
   128  func TestJSONAnyResolver_AutomaticForDynamicMessage(t *testing.T) {
   129  	// marshaling and unmarshaling a dynamic message automatically enables
   130  	// resolving Any messages for known types (a known type is one that is
   131  	// in the dynamic message's file descriptor or that file's transitive
   132  	// dependencies)
   133  	fd := createTestFileDescriptor(t, "foobar")
   134  	md := fd.FindMessage("foobar.MyMessage")
   135  	dm := NewMessageFactoryWithDefaults().NewMessage(md).(*Message)
   136  	dm.SetFieldByNumber(1, "fubar")
   137  	dm.SetFieldByNumber(2, int32(123))
   138  	a1, err := ptypes.MarshalAny(dm)
   139  	testutil.Ok(t, err)
   140  	dm.SetFieldByNumber(1, "snafu")
   141  	dm.SetFieldByNumber(2, int32(456))
   142  	a2, err := ptypes.MarshalAny(dm)
   143  	testutil.Ok(t, err)
   144  	dm.SetFieldByNumber(1, "xyz")
   145  	dm.SetFieldByNumber(2, int32(-987))
   146  	dm.SetFieldByNumber(3, []*any.Any{a1, a2})
   147  
   148  	js, err := dm.MarshalJSON()
   149  	testutil.Ok(t, err)
   150  	expected := `{"abc":"xyz","def":-987,"ghi":[{"@type":"type.googleapis.com/foobar.MyMessage","abc":"fubar","def":123},{"@type":"type.googleapis.com/foobar.MyMessage","abc":"snafu","def":456}]}`
   151  	testutil.Eq(t, expected, string(js))
   152  
   153  	dm2 := NewMessageFactoryWithDefaults().NewMessage(md).(*Message)
   154  	err = dm2.UnmarshalJSON(js)
   155  	testutil.Ok(t, err)
   156  
   157  	testutil.Ceq(t, dm, dm2, eqdm)
   158  }
   159  
   160  func TestMarshalJSONEmitDefaults(t *testing.T) {
   161  	md, err := desc.LoadMessageDescriptorForMessage((*testprotos.ReallySimpleMessage)(nil))
   162  	testutil.Ok(t, err)
   163  	dm := NewMessage(md)
   164  	js, err := dm.MarshalJSON()
   165  	testutil.Ok(t, err)
   166  	testutil.Eq(t, `{}`, string(js))
   167  	jsDefaults, err := dm.MarshalJSONPB(&jsonpb.Marshaler{EmitDefaults: true})
   168  	testutil.Ok(t, err)
   169  	testutil.Eq(t, `{"id":"0","name":""}`, string(jsDefaults))
   170  }
   171  
   172  func TestMarshalJSONEmitDefaultsMapKeyFields(t *testing.T) {
   173  	md, err := desc.LoadMessageDescriptorForMessage((*testprotos.MapKeyFields)(nil))
   174  	testutil.Ok(t, err)
   175  	dm := NewMessage(md)
   176  	m := &jsonpb.Marshaler{EmitDefaults: true}
   177  	jsDefaults, err := dm.MarshalJSONPB(m)
   178  	testutil.Ok(t, err)
   179  	testutil.Eq(t, `{"i":{},"j":{},"k":{},"l":{},"m":{},"n":{},"o":{},"p":{},"q":{},"r":{},"s":{},"t":{}}`, string(jsDefaults))
   180  
   181  	jsDefaults2, err := m.MarshalToString(&testprotos.MapKeyFields{})
   182  	testutil.Ok(t, err)
   183  	testutil.Eq(t, string(jsDefaults), string(jsDefaults2))
   184  }
   185  
   186  func TestMarshalJSONEmitDefaultsOneOfFields(t *testing.T) {
   187  	// we don't include default values for fields in a one-of
   188  	// since it would not round-trip correctly
   189  	testCases := []struct {
   190  		msg          *testprotos.OneOfMessage
   191  		expectedJson string
   192  	}{
   193  		{
   194  			msg:          &testprotos.OneOfMessage{},
   195  			expectedJson: `{}`,
   196  		},
   197  		{
   198  			msg:          &testprotos.OneOfMessage{Value: &testprotos.OneOfMessage_IntValue{IntValue: 12345}},
   199  			expectedJson: `{"intValue":12345}`,
   200  		},
   201  		{
   202  			msg:          &testprotos.OneOfMessage{Value: &testprotos.OneOfMessage_StringValue{StringValue: "foobar"}},
   203  			expectedJson: `{"stringValue":"foobar"}`,
   204  		},
   205  		{
   206  			msg:          &testprotos.OneOfMessage{Value: &testprotos.OneOfMessage_MsgValue{MsgValue: &testprotos.OneOfMessage{}}},
   207  			expectedJson: `{"msgValue":{}}`,
   208  		},
   209  		{
   210  			msg:          &testprotos.OneOfMessage{Value: &testprotos.OneOfMessage_MsgValue{MsgValue: nil}},
   211  			expectedJson: `{"msgValue":null}`,
   212  		},
   213  	}
   214  	m := &jsonpb.Marshaler{EmitDefaults: true}
   215  	for _, testCase := range testCases {
   216  		dm, err := AsDynamicMessageWithMessageFactory(testCase.msg, NewMessageFactoryWithDefaults())
   217  		testutil.Ok(t, err)
   218  		asJson, err := dm.MarshalJSONPB(m)
   219  		testutil.Ok(t, err)
   220  		actualJson := string(asJson)
   221  		testutil.Eq(t, testCase.expectedJson, actualJson)
   222  
   223  		// round-trip
   224  		err = jsonpb.UnmarshalString(actualJson, dm)
   225  		testutil.Ok(t, err)
   226  		var roundtripped testprotos.OneOfMessage
   227  		err = dm.ConvertTo(&roundtripped)
   228  		testutil.Ok(t, err)
   229  		testutil.Ceq(t, testCase.msg, &roundtripped, eqpm)
   230  	}
   231  }
   232  
   233  func TestMarshalJSONEnumsAsInts(t *testing.T) {
   234  	md, err := desc.LoadMessageDescriptorForMessage((*testprotos.TestRequest)(nil))
   235  	testutil.Ok(t, err)
   236  	dm := NewMessage(md)
   237  	dm.SetFieldByNumber(1, []int32{1})
   238  	dm.SetFieldByNumber(2, "bedazzle")
   239  	js, err := dm.MarshalJSONPB(&jsonpb.Marshaler{EnumsAsInts: true})
   240  	testutil.Ok(t, err)
   241  	testutil.Eq(t, `{"foo":[1],"bar":"bedazzle"}`, string(js))
   242  }
   243  
   244  func TestMarshalJSONOrigName(t *testing.T) {
   245  	// TODO
   246  }
   247  
   248  func TestMarshalJSONIndent(t *testing.T) {
   249  	md, err := desc.LoadMessageDescriptorForMessage((*testprotos.TestRequest)(nil))
   250  	testutil.Ok(t, err)
   251  	dm := NewMessage(md)
   252  	dm.SetFieldByNumber(1, []int32{1})
   253  	dm.SetFieldByNumber(2, "bedazzle")
   254  	js, err := dm.MarshalJSON()
   255  	testutil.Ok(t, err)
   256  	testutil.Eq(t, `{"foo":["VALUE1"],"bar":"bedazzle"}`, string(js))
   257  	jsIndent, err := dm.MarshalJSONIndent()
   258  	testutil.Ok(t, err)
   259  	testutil.Eq(t, `{
   260    "foo": [
   261      "VALUE1"
   262    ],
   263    "bar": "bedazzle"
   264  }`, string(jsIndent))
   265  	jsIndent, err = dm.MarshalJSONPB(&jsonpb.Marshaler{Indent: "\t"})
   266  	testutil.Ok(t, err)
   267  	testutil.Eq(t, `{
   268  	"foo": [
   269  		"VALUE1"
   270  	],
   271  	"bar": "bedazzle"
   272  }`, string(jsIndent))
   273  }
   274  
   275  func TestMarshalJSONIndentEmbedWellKnownTypes(t *testing.T) {
   276  	// testing the formatting of dynamic message that embeds non-dynamic message,
   277  	// both those w/ special/simple JSON encoding (like timestamp) and those with
   278  	// more structure (Any).
   279  	md, err := desc.LoadMessageDescriptorForMessage((*testprotos.TestWellKnownTypes)(nil))
   280  	testutil.Ok(t, err)
   281  	dm := NewMessage(md)
   282  
   283  	ts, err := ptypes.TimestampProto(time.Date(2010, 3, 4, 5, 6, 7, 809000, time.UTC))
   284  	testutil.Ok(t, err)
   285  	dm.SetFieldByNumber(1, ts)
   286  
   287  	anys := make([]*any.Any, 3)
   288  	anys[0], err = ptypes.MarshalAny(&testprotos.TestRequest{Bar: "foo"})
   289  	testutil.Ok(t, err)
   290  	anys[1], err = ptypes.MarshalAny(&testprotos.TestRequest{Bar: "bar"})
   291  	testutil.Ok(t, err)
   292  	anys[2], err = ptypes.MarshalAny(&testprotos.TestRequest{Bar: "baz"})
   293  	testutil.Ok(t, err)
   294  	dm.SetFieldByNumber(13, anys)
   295  
   296  	js, err := dm.MarshalJSON()
   297  	testutil.Ok(t, err)
   298  	testutil.Eq(t, `{"startTime":"2010-03-04T05:06:07.000809Z","extras":[{"@type":"type.googleapis.com/testprotos.TestRequest","bar":"foo"},{"@type":"type.googleapis.com/testprotos.TestRequest","bar":"bar"},{"@type":"type.googleapis.com/testprotos.TestRequest","bar":"baz"}]}`, string(js))
   299  	jsIndent, err := dm.MarshalJSONIndent()
   300  	testutil.Ok(t, err)
   301  	testutil.Eq(t, `{
   302    "startTime": "2010-03-04T05:06:07.000809Z",
   303    "extras": [
   304      {
   305        "@type": "type.googleapis.com/testprotos.TestRequest",
   306        "bar": "foo"
   307      },
   308      {
   309        "@type": "type.googleapis.com/testprotos.TestRequest",
   310        "bar": "bar"
   311      },
   312      {
   313        "@type": "type.googleapis.com/testprotos.TestRequest",
   314        "bar": "baz"
   315      }
   316    ]
   317  }`, string(jsIndent))
   318  	jsIndent, err = dm.MarshalJSONPB(&jsonpb.Marshaler{Indent: "\t"})
   319  	testutil.Ok(t, err)
   320  	testutil.Eq(t, `{
   321  	"startTime": "2010-03-04T05:06:07.000809Z",
   322  	"extras": [
   323  		{
   324  			"@type": "type.googleapis.com/testprotos.TestRequest",
   325  			"bar": "foo"
   326  		},
   327  		{
   328  			"@type": "type.googleapis.com/testprotos.TestRequest",
   329  			"bar": "bar"
   330  		},
   331  		{
   332  			"@type": "type.googleapis.com/testprotos.TestRequest",
   333  			"bar": "baz"
   334  		}
   335  	]
   336  }`, string(jsIndent))
   337  }
   338  
   339  func TestUnmarshalJSONAllowUnknownFields(t *testing.T) {
   340  	md, err := desc.LoadMessageDescriptorForMessage((*testprotos.TestRequest)(nil))
   341  	testutil.Ok(t, err)
   342  	js := []byte(`{"foo":["VALUE1"],"bar":"bedazzle","xxx": 1}`)
   343  	dm := NewMessage(md)
   344  	err = dm.UnmarshalJSON(js)
   345  	testutil.Nok(t, err)
   346  	unmarshaler := &jsonpb.Unmarshaler{AllowUnknownFields: true}
   347  	err = dm.UnmarshalJSONPB(unmarshaler, js)
   348  	testutil.Ok(t, err)
   349  	foo := dm.GetFieldByNumber(1)
   350  	bar := dm.GetFieldByNumber(2)
   351  	testutil.Eq(t, []int32{1}, foo)
   352  	testutil.Eq(t, "bedazzle", bar)
   353  }
   354  
   355  func TestJSONWellKnownType(t *testing.T) {
   356  	any1, err := ptypes.MarshalAny(&testprotos.TestRequest{
   357  		Foo: []testprotos.Proto3Enum{testprotos.Proto3Enum_VALUE1, testprotos.Proto3Enum_VALUE2},
   358  		Bar: "bar",
   359  		Baz: &testprotos.TestMessage{Ne: []testprotos.TestMessage_NestedEnum{testprotos.TestMessage_VALUE1}},
   360  	})
   361  	testutil.Ok(t, err)
   362  	any2, err := ptypes.MarshalAny(ptypes.TimestampNow())
   363  	testutil.Ok(t, err)
   364  
   365  	wkts := &testprotos.TestWellKnownTypes{
   366  		StartTime: &timestamp.Timestamp{Seconds: 1010101, Nanos: 20202},
   367  		Elapsed:   &duration.Duration{Seconds: 30303, Nanos: 40404},
   368  		Dbl:       &wrappers.DoubleValue{Value: 3.14159},
   369  		Flt:       &wrappers.FloatValue{Value: -1.0101010},
   370  		Bl:        &wrappers.BoolValue{Value: true},
   371  		I32:       &wrappers.Int32Value{Value: -42},
   372  		I64:       &wrappers.Int64Value{Value: -9090909090},
   373  		U32:       &wrappers.UInt32Value{Value: 42},
   374  		U64:       &wrappers.UInt64Value{Value: 9090909090},
   375  		Str:       &wrappers.StringValue{Value: "foobar"},
   376  		Byt:       &wrappers.BytesValue{Value: []byte("snafu")},
   377  		Json: []*structpb.Value{
   378  			{Kind: &structpb.Value_BoolValue{BoolValue: true}},
   379  			{Kind: &structpb.Value_ListValue{ListValue: &structpb.ListValue{Values: []*structpb.Value{
   380  				{Kind: &structpb.Value_NullValue{}},
   381  				{Kind: &structpb.Value_StringValue{StringValue: "fubar"}},
   382  				{Kind: &structpb.Value_NumberValue{NumberValue: 10101.20202}},
   383  			}}}},
   384  			{Kind: &structpb.Value_StructValue{StructValue: &structpb.Struct{Fields: map[string]*structpb.Value{
   385  				"foo": {Kind: &structpb.Value_NullValue{}},
   386  				"bar": {Kind: &structpb.Value_StringValue{StringValue: "snafu"}},
   387  				"baz": {Kind: &structpb.Value_NumberValue{NumberValue: 30303.40404}},
   388  			}}}},
   389  		},
   390  		Extras: []*any.Any{any1, any2},
   391  	}
   392  
   393  	jsm := jsonpb.Marshaler{}
   394  	js, err := jsm.MarshalToString(wkts)
   395  	testutil.Ok(t, err)
   396  
   397  	md, err := desc.LoadMessageDescriptorForMessage(wkts)
   398  	testutil.Ok(t, err)
   399  	dm := NewMessage(md)
   400  	err = dm.UnmarshalJSON([]byte(js))
   401  	testutil.Ok(t, err)
   402  
   403  	// check that the unmarshalled fields were constructed correctly with the
   404  	// right value and type (e.g. generated well-known-type, not dynamic message)
   405  	ts, ok := dm.GetFieldByNumber(1).(*timestamp.Timestamp)
   406  	testutil.Require(t, ok)
   407  	testutil.Ceq(t, wkts.StartTime, ts, eqpm)
   408  
   409  	dur, ok := dm.GetFieldByNumber(2).(*duration.Duration)
   410  	testutil.Require(t, ok)
   411  	testutil.Ceq(t, wkts.Elapsed, dur, eqpm)
   412  
   413  	dbl, ok := dm.GetFieldByNumber(3).(*wrappers.DoubleValue)
   414  	testutil.Require(t, ok)
   415  	testutil.Eq(t, wkts.Dbl.Value, dbl.Value)
   416  
   417  	flt, ok := dm.GetFieldByNumber(4).(*wrappers.FloatValue)
   418  	testutil.Require(t, ok)
   419  	testutil.Eq(t, wkts.Flt.Value, flt.Value)
   420  
   421  	bl, ok := dm.GetFieldByNumber(5).(*wrappers.BoolValue)
   422  	testutil.Require(t, ok)
   423  	testutil.Eq(t, wkts.Bl.Value, bl.Value)
   424  
   425  	i32, ok := dm.GetFieldByNumber(6).(*wrappers.Int32Value)
   426  	testutil.Require(t, ok)
   427  	testutil.Eq(t, wkts.I32.Value, i32.Value)
   428  
   429  	i64, ok := dm.GetFieldByNumber(7).(*wrappers.Int64Value)
   430  	testutil.Require(t, ok)
   431  	testutil.Eq(t, wkts.I64.Value, i64.Value)
   432  
   433  	u32, ok := dm.GetFieldByNumber(8).(*wrappers.UInt32Value)
   434  	testutil.Require(t, ok)
   435  	testutil.Eq(t, wkts.U32.Value, u32.Value)
   436  
   437  	u64, ok := dm.GetFieldByNumber(9).(*wrappers.UInt64Value)
   438  	testutil.Require(t, ok)
   439  	testutil.Eq(t, wkts.U64.Value, u64.Value)
   440  
   441  	str, ok := dm.GetFieldByNumber(10).(*wrappers.StringValue)
   442  	testutil.Require(t, ok)
   443  	testutil.Eq(t, wkts.Str.Value, str.Value)
   444  
   445  	byt, ok := dm.GetFieldByNumber(11).(*wrappers.BytesValue)
   446  	testutil.Require(t, ok)
   447  	testutil.Eq(t, wkts.Byt.Value, byt.Value)
   448  
   449  	vals, ok := dm.GetFieldByNumber(12).([]interface{})
   450  	testutil.Require(t, ok)
   451  	testutil.Eq(t, len(wkts.Json), len(vals))
   452  	for i := range vals {
   453  		v, ok := vals[i].(*structpb.Value)
   454  		testutil.Require(t, ok)
   455  		testutil.Ceq(t, wkts.Json[i], v, eqpm)
   456  	}
   457  
   458  	extras, ok := dm.GetFieldByNumber(13).([]interface{})
   459  	testutil.Require(t, ok)
   460  	testutil.Eq(t, len(wkts.Extras), len(extras))
   461  	for i := range extras {
   462  		v, ok := extras[i].(*any.Any)
   463  		testutil.Require(t, ok)
   464  		testutil.Eq(t, wkts.Extras[i].TypeUrl, v.TypeUrl)
   465  		testutil.Eq(t, wkts.Extras[i].Value, v.Value)
   466  	}
   467  }
   468  
   469  func TestJSONWellKnownTypeFromFileDescriptorSet(t *testing.T) {
   470  	// TODO: generalize this so it tests all well-known types, not just duration
   471  
   472  	data, err := ioutil.ReadFile("../internal/testprotos/duration.protoset")
   473  	testutil.Ok(t, err)
   474  	fds := &descriptor.FileDescriptorSet{}
   475  	err = proto.Unmarshal(data, fds)
   476  	testutil.Ok(t, err)
   477  	fd, err := desc.CreateFileDescriptorFromSet(fds)
   478  	testutil.Ok(t, err)
   479  	md := fd.FindMessage("google.protobuf.Duration")
   480  	testutil.Neq(t, nil, md)
   481  
   482  	dur := &duration.Duration{Seconds: 30303, Nanos: 40404}
   483  
   484  	// marshal duration to JSON
   485  	jsm := jsonpb.Marshaler{}
   486  	js, err := jsm.MarshalToString(dur)
   487  	testutil.Ok(t, err)
   488  
   489  	// make sure we can unmarshal it
   490  	dm := NewMessage(md)
   491  	err = dm.UnmarshalJSON([]byte(js))
   492  	testutil.Ok(t, err)
   493  
   494  	// and then marshal it again with same output as original
   495  	dynJs, err := jsm.MarshalToString(dm)
   496  	testutil.Ok(t, err)
   497  	testutil.Eq(t, js, dynJs)
   498  }
   499  
   500  func jsonTranslationParty(t *testing.T, msg proto.Message, includesNaN bool) {
   501  	doTranslationParty(t, msg,
   502  		func(pm proto.Message) ([]byte, error) {
   503  			m := jsonpb.Marshaler{}
   504  			var b bytes.Buffer
   505  			err := m.Marshal(&b, pm)
   506  			if err != nil {
   507  				return nil, err
   508  			} else {
   509  				return b.Bytes(), nil
   510  			}
   511  		},
   512  		func(b []byte, pm proto.Message) error {
   513  			return jsonpb.Unmarshal(bytes.NewReader(b), pm)
   514  		},
   515  		(*Message).MarshalJSON, (*Message).UnmarshalJSON, includesNaN, true, true)
   516  }