...

Source file src/google.golang.org/protobuf/encoding/prototext/decode_test.go

Documentation: google.golang.org/protobuf/encoding/prototext

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package prototext_test
     6  
     7  import (
     8  	"math"
     9  	"strings"
    10  	"testing"
    11  
    12  	"google.golang.org/protobuf/encoding/prototext"
    13  	"google.golang.org/protobuf/internal/flags"
    14  	"google.golang.org/protobuf/proto"
    15  	"google.golang.org/protobuf/reflect/protoregistry"
    16  
    17  	testpb "google.golang.org/protobuf/internal/testprotos/test"
    18  	weakpb "google.golang.org/protobuf/internal/testprotos/test/weak1"
    19  	pb2 "google.golang.org/protobuf/internal/testprotos/textpb2"
    20  	pb3 "google.golang.org/protobuf/internal/testprotos/textpb3"
    21  	pbeditions "google.golang.org/protobuf/internal/testprotos/textpbeditions"
    22  	"google.golang.org/protobuf/types/known/anypb"
    23  )
    24  
    25  func TestUnmarshal(t *testing.T) {
    26  	tests := []struct {
    27  		desc         string
    28  		umo          prototext.UnmarshalOptions
    29  		inputMessage proto.Message
    30  		inputText    string
    31  		wantMessage  proto.Message
    32  		wantErr      string // Expected error substring.
    33  		skip         bool
    34  	}{{
    35  		desc:         "proto2 empty message",
    36  		inputMessage: &pb2.Scalars{},
    37  		wantMessage:  &pb2.Scalars{},
    38  	}, {
    39  		desc:         "proto2 optional scalars set to zero values",
    40  		inputMessage: &pb2.Scalars{},
    41  		inputText: `opt_bool: false
    42  opt_int32: 0
    43  opt_int64: 0
    44  opt_uint32: 0
    45  opt_uint64: 0
    46  opt_sint32: 0
    47  opt_sint64: 0
    48  opt_fixed32: 0
    49  opt_fixed64: 0
    50  opt_sfixed32: 0
    51  opt_sfixed64: 0
    52  opt_float: 0
    53  opt_double: 0
    54  opt_bytes: ""
    55  opt_string: ""
    56  `,
    57  		wantMessage: &pb2.Scalars{
    58  			OptBool:     proto.Bool(false),
    59  			OptInt32:    proto.Int32(0),
    60  			OptInt64:    proto.Int64(0),
    61  			OptUint32:   proto.Uint32(0),
    62  			OptUint64:   proto.Uint64(0),
    63  			OptSint32:   proto.Int32(0),
    64  			OptSint64:   proto.Int64(0),
    65  			OptFixed32:  proto.Uint32(0),
    66  			OptFixed64:  proto.Uint64(0),
    67  			OptSfixed32: proto.Int32(0),
    68  			OptSfixed64: proto.Int64(0),
    69  			OptFloat:    proto.Float32(0),
    70  			OptDouble:   proto.Float64(0),
    71  			OptBytes:    []byte{},
    72  			OptString:   proto.String(""),
    73  		},
    74  	}, {
    75  		desc:         "protoeditions explicit scalars set to zero values",
    76  		inputMessage: &pbeditions.Scalars{},
    77  		inputText: `opt_bool: false
    78  opt_int32: 0
    79  opt_int64: 0
    80  opt_uint32: 0
    81  opt_uint64: 0
    82  opt_sint32: 0
    83  opt_sint64: 0
    84  opt_fixed32: 0
    85  opt_fixed64: 0
    86  opt_sfixed32: 0
    87  opt_sfixed64: 0
    88  opt_float: 0
    89  opt_double: 0
    90  opt_bytes: ""
    91  opt_string: ""
    92  `,
    93  		wantMessage: &pbeditions.Scalars{
    94  			OptBool:     proto.Bool(false),
    95  			OptInt32:    proto.Int32(0),
    96  			OptInt64:    proto.Int64(0),
    97  			OptUint32:   proto.Uint32(0),
    98  			OptUint64:   proto.Uint64(0),
    99  			OptSint32:   proto.Int32(0),
   100  			OptSint64:   proto.Int64(0),
   101  			OptFixed32:  proto.Uint32(0),
   102  			OptFixed64:  proto.Uint64(0),
   103  			OptSfixed32: proto.Int32(0),
   104  			OptSfixed64: proto.Int64(0),
   105  			OptFloat:    proto.Float32(0),
   106  			OptDouble:   proto.Float64(0),
   107  			OptBytes:    []byte{},
   108  			OptString:   proto.String(""),
   109  		},
   110  	}, {
   111  		desc:         "protoeditions implicit scalars set to zero values",
   112  		inputMessage: &pbeditions.ImplicitScalars{},
   113  		inputText: `s_bool: false
   114  s_int32: 0
   115  s_int64: 0
   116  s_uint32: 0
   117  s_uint64: 0
   118  s_sint32: 0
   119  s_sint64: 0
   120  s_fixed32: 0
   121  s_fixed64: 0
   122  s_sfixed32: 0
   123  s_sfixed64: 0
   124  s_float: 0
   125  s_double: 0
   126  s_bytes: ""
   127  s_string: ""
   128  `,
   129  		wantMessage: &pbeditions.ImplicitScalars{},
   130  	}, {
   131  		desc:         "proto3 scalars set to zero values",
   132  		inputMessage: &pb3.Scalars{},
   133  		inputText: `s_bool: false
   134  s_int32: 0
   135  s_int64: 0
   136  s_uint32: 0
   137  s_uint64: 0
   138  s_sint32: 0
   139  s_sint64: 0
   140  s_fixed32: 0
   141  s_fixed64: 0
   142  s_sfixed32: 0
   143  s_sfixed64: 0
   144  s_float: 0
   145  s_double: 0
   146  s_bytes: ""
   147  s_string: ""
   148  `,
   149  		wantMessage: &pb3.Scalars{},
   150  	}, {
   151  		desc:         "proto3 optional set to zero values",
   152  		inputMessage: &pb3.Proto3Optional{},
   153  		inputText: `opt_bool: false
   154  opt_int32: 0
   155  opt_int64: 0
   156  opt_uint32: 0
   157  opt_uint64: 0
   158  opt_float: 0
   159  opt_double: 0
   160  opt_string: ""
   161  opt_bytes: ""
   162  opt_enum: ZERO
   163  opt_message: {}
   164  `,
   165  		wantMessage: &pb3.Proto3Optional{
   166  			OptBool:    proto.Bool(false),
   167  			OptInt32:   proto.Int32(0),
   168  			OptInt64:   proto.Int64(0),
   169  			OptUint32:  proto.Uint32(0),
   170  			OptUint64:  proto.Uint64(0),
   171  			OptFloat:   proto.Float32(0),
   172  			OptDouble:  proto.Float64(0),
   173  			OptString:  proto.String(""),
   174  			OptBytes:   []byte{},
   175  			OptEnum:    pb3.Enum_ZERO.Enum(),
   176  			OptMessage: &pb3.Nested{},
   177  		},
   178  	}, {
   179  		desc:         "proto2 optional scalars",
   180  		inputMessage: &pb2.Scalars{},
   181  		inputText: `opt_bool: true
   182  opt_int32: 255
   183  opt_int64: 3735928559
   184  opt_uint32: 0xff
   185  opt_uint64: 0xdeadbeef
   186  opt_sint32: -1001
   187  opt_sint64: -   0xffff
   188  opt_fixed64: 64
   189  opt_sfixed32: -		32
   190  opt_float: 1.234
   191  opt_double: 1.23e+100
   192  opt_bytes: "\xe8\xb0\xb7\xe6\xad\x8c"
   193  opt_string: "谷歌"
   194  `,
   195  		wantMessage: &pb2.Scalars{
   196  			OptBool:     proto.Bool(true),
   197  			OptInt32:    proto.Int32(0xff),
   198  			OptInt64:    proto.Int64(0xdeadbeef),
   199  			OptUint32:   proto.Uint32(0xff),
   200  			OptUint64:   proto.Uint64(0xdeadbeef),
   201  			OptSint32:   proto.Int32(-1001),
   202  			OptSint64:   proto.Int64(-0xffff),
   203  			OptFixed64:  proto.Uint64(64),
   204  			OptSfixed32: proto.Int32(-32),
   205  			OptFloat:    proto.Float32(1.234),
   206  			OptDouble:   proto.Float64(1.23e100),
   207  			OptBytes:    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
   208  			OptString:   proto.String("谷歌"),
   209  		},
   210  	}, {
   211  		desc:         "protoeditions explicit scalars",
   212  		inputMessage: &pbeditions.Scalars{},
   213  		inputText: `opt_bool: true
   214  opt_int32: 255
   215  opt_int64: 3735928559
   216  opt_uint32: 0xff
   217  opt_uint64: 0xdeadbeef
   218  opt_sint32: -1001
   219  opt_sint64: -   0xffff
   220  opt_fixed64: 64
   221  opt_sfixed32: -		32
   222  opt_float: 1.234
   223  opt_double: 1.23e+100
   224  opt_bytes: "\xe8\xb0\xb7\xe6\xad\x8c"
   225  opt_string: "谷歌"
   226  `,
   227  		wantMessage: &pbeditions.Scalars{
   228  			OptBool:     proto.Bool(true),
   229  			OptInt32:    proto.Int32(0xff),
   230  			OptInt64:    proto.Int64(0xdeadbeef),
   231  			OptUint32:   proto.Uint32(0xff),
   232  			OptUint64:   proto.Uint64(0xdeadbeef),
   233  			OptSint32:   proto.Int32(-1001),
   234  			OptSint64:   proto.Int64(-0xffff),
   235  			OptFixed64:  proto.Uint64(64),
   236  			OptSfixed32: proto.Int32(-32),
   237  			OptFloat:    proto.Float32(1.234),
   238  			OptDouble:   proto.Float64(1.23e100),
   239  			OptBytes:    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
   240  			OptString:   proto.String("谷歌"),
   241  		},
   242  	}, {
   243  		desc:         "case sensitive",
   244  		inputMessage: &pb3.Scalars{},
   245  		inputText:    `S_BOOL: true`,
   246  		wantErr:      "unknown field: S_BOOL",
   247  	}, {
   248  		desc:         "proto3 scalars",
   249  		inputMessage: &pb3.Scalars{},
   250  		inputText: `s_bool: true
   251  s_int32: 255
   252  s_int64: 3735928559
   253  s_uint32: 0xff
   254  s_uint64: 0xdeadbeef
   255  s_sint32: -1001
   256  s_sint64: -  #
   257               0xffff
   258  s_fixed64: 64
   259  s_sfixed32: -32
   260  s_float: 1.234
   261  s_double: 1.23e+100
   262  s_bytes: "\xe8\xb0\xb7\xe6\xad\x8c"
   263  s_string: "谷歌"
   264  `,
   265  		wantMessage: &pb3.Scalars{
   266  			SBool:     true,
   267  			SInt32:    0xff,
   268  			SInt64:    0xdeadbeef,
   269  			SUint32:   0xff,
   270  			SUint64:   0xdeadbeef,
   271  			SSint32:   -1001,
   272  			SSint64:   -0xffff,
   273  			SFixed64:  64,
   274  			SSfixed32: -32,
   275  			SFloat:    1.234,
   276  			SDouble:   1.23e100,
   277  			SBytes:    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
   278  			SString:   "谷歌",
   279  		},
   280  	}, {
   281  		desc:         "proto2 string with invalid UTF-8",
   282  		inputMessage: &pb2.Scalars{},
   283  		inputText:    `opt_string: "abc\xff"`,
   284  		wantMessage: &pb2.Scalars{
   285  			OptString: proto.String("abc\xff"),
   286  		},
   287  	}, {
   288  		desc:         "protoeditions unvalidated string with invalid UTF-8",
   289  		inputMessage: &pbeditions.Scalars{},
   290  		inputText:    `opt_string: "abc\xff"`,
   291  		wantMessage: &pbeditions.Scalars{
   292  			OptString: proto.String("abc\xff"),
   293  		},
   294  	}, {
   295  		desc:         "proto3 string with invalid UTF-8",
   296  		inputMessage: &pb3.Scalars{},
   297  		inputText:    `s_string: "abc\xff"`,
   298  		wantErr:      "(line 1:11): contains invalid UTF-8",
   299  	}, {
   300  		desc:         "proto2 message contains unknown field",
   301  		inputMessage: &pb2.Scalars{},
   302  		inputText:    "unknown_field: 123",
   303  		wantErr:      "unknown field",
   304  	}, {
   305  		desc:         "proto3 message contains unknown field",
   306  		inputMessage: &pb3.Scalars{},
   307  		inputText:    "unknown_field: 456",
   308  		wantErr:      "unknown field",
   309  	}, {
   310  		desc:         "proto2 message contains discarded unknown field",
   311  		umo:          prototext.UnmarshalOptions{DiscardUnknown: true},
   312  		inputMessage: &pb2.Scalars{},
   313  		inputText:    `unknown_field:123 1000:"hello"`,
   314  	}, {
   315  		desc:         "protoeditions message contains discarded unknown field",
   316  		umo:          prototext.UnmarshalOptions{DiscardUnknown: true},
   317  		inputMessage: &pbeditions.Scalars{},
   318  		inputText:    `unknown_field:123 1000:"hello"`,
   319  	}, {
   320  		desc:         "proto3 message contains discarded unknown field",
   321  		umo:          prototext.UnmarshalOptions{DiscardUnknown: true},
   322  		inputMessage: &pb3.Scalars{},
   323  		inputText:    `unknown_field:456 1000:"goodbye"`,
   324  	}, {
   325  		desc:         "proto2 message cannot parse field number",
   326  		umo:          prototext.UnmarshalOptions{DiscardUnknown: true},
   327  		inputMessage: &pb2.Scalars{},
   328  		inputText:    `13:"hello"`,
   329  		wantErr:      "cannot specify field by number",
   330  	}, {
   331  		desc:         "unknown list field",
   332  		umo:          prototext.UnmarshalOptions{DiscardUnknown: true},
   333  		inputMessage: &pb2.Scalars{},
   334  		inputText:    `unknown_field: { strings: [ "" ] }`,
   335  	}, {
   336  		desc:         "unknown list of list field",
   337  		umo:          prototext.UnmarshalOptions{DiscardUnknown: true},
   338  		inputMessage: &pb2.Scalars{},
   339  		inputText:    `unknown_field: { strings: [ [ ] ] }`,
   340  		wantErr:      `(line 1:29): invalid scalar value: [`,
   341  	}, {
   342  		desc:         "unknown list of message field",
   343  		umo:          prototext.UnmarshalOptions{DiscardUnknown: true},
   344  		inputMessage: &pb2.Scalars{},
   345  		inputText:    `unknown_field: [ { a: "b" }, { c: "d" } ]`,
   346  	}, {
   347  		desc:         "proto3 message cannot parse field number",
   348  		umo:          prototext.UnmarshalOptions{DiscardUnknown: true},
   349  		inputMessage: &pb3.Scalars{},
   350  		inputText:    `13:"goodbye"`,
   351  		wantErr:      "cannot specify field by number",
   352  	}, {
   353  		desc:         "proto2 numeric key field",
   354  		inputMessage: &pb2.Scalars{},
   355  		inputText:    "1: true",
   356  		wantErr:      "cannot specify field by number",
   357  	}, {
   358  		desc:         "proto3 numeric key field",
   359  		inputMessage: &pb3.Scalars{},
   360  		inputText:    "1: true",
   361  		wantErr:      "cannot specify field by number",
   362  	}, {
   363  		desc:         "invalid bool value",
   364  		inputMessage: &pb3.Scalars{},
   365  		inputText:    "s_bool: 123",
   366  		wantErr:      "invalid value for bool",
   367  	}, {
   368  		desc:         "invalid int32 value",
   369  		inputMessage: &pb3.Scalars{},
   370  		inputText:    "s_int32: not_a_num",
   371  		wantErr:      "invalid value for int32",
   372  	}, {
   373  		desc:         "invalid int64 value",
   374  		inputMessage: &pb3.Scalars{},
   375  		inputText:    "s_int64: 'not a num either'",
   376  		wantErr:      "invalid value for int64",
   377  	}, {
   378  		desc:         "invalid uint32 value",
   379  		inputMessage: &pb3.Scalars{},
   380  		inputText:    "s_fixed32: -42",
   381  		wantErr:      "invalid value for fixed32",
   382  	}, {
   383  		desc:         "invalid uint64 value",
   384  		inputMessage: &pb3.Scalars{},
   385  		inputText:    "s_uint64: -47",
   386  		wantErr:      "invalid value for uint64",
   387  	}, {
   388  		desc:         "invalid sint32 value",
   389  		inputMessage: &pb3.Scalars{},
   390  		inputText:    "s_sint32: '42'",
   391  		wantErr:      "invalid value for sint32",
   392  	}, {
   393  		desc:         "invalid sint64 value",
   394  		inputMessage: &pb3.Scalars{},
   395  		inputText:    "s_sint64: '-47'",
   396  		wantErr:      "invalid value for sint64",
   397  	}, {
   398  		desc:         "invalid fixed32 value",
   399  		inputMessage: &pb3.Scalars{},
   400  		inputText:    "s_fixed32: -42",
   401  		wantErr:      "invalid value for fixed32",
   402  	}, {
   403  		desc:         "invalid fixed64 value",
   404  		inputMessage: &pb3.Scalars{},
   405  		inputText:    "s_fixed64: -42",
   406  		wantErr:      "invalid value for fixed64",
   407  	}, {
   408  		desc:         "invalid sfixed32 value",
   409  		inputMessage: &pb3.Scalars{},
   410  		inputText:    "s_sfixed32: 'not valid'",
   411  		wantErr:      "invalid value for sfixed32",
   412  	}, {
   413  		desc:         "invalid sfixed64 value",
   414  		inputMessage: &pb3.Scalars{},
   415  		inputText:    "s_sfixed64: bad",
   416  		wantErr:      "invalid value for sfixed64",
   417  	}, {
   418  		desc:         "incomplete number value",
   419  		inputMessage: &pb3.Scalars{},
   420  		inputText:    `s_int32: - `,
   421  		wantErr:      "(line 1:10): invalid scalar value: -",
   422  	}, {
   423  		desc:         "conformance: FloatFieldMaxValue",
   424  		inputMessage: &pb2.Scalars{},
   425  		inputText:    `opt_float: 3.4028235e+38`,
   426  		wantMessage: &pb2.Scalars{
   427  			OptFloat: proto.Float32(3.40282347e+38),
   428  		},
   429  	}, {
   430  		desc:         "conformance: FloatFieldLargerThanUint64",
   431  		inputMessage: &pb2.Scalars{},
   432  		inputText:    `opt_float: 18446744073709551616`,
   433  		wantMessage: &pb2.Scalars{
   434  			OptFloat: proto.Float32(1.84467441e+19),
   435  		},
   436  	}, {
   437  		desc:         "conformance: FloatFieldTooLarge",
   438  		inputMessage: &pb2.Scalars{},
   439  		inputText:    `opt_float: 3.4028235e+39`,
   440  		wantMessage: &pb2.Scalars{
   441  			OptFloat: proto.Float32(float32(math.Inf(1))),
   442  		},
   443  	}, {
   444  		desc:         "invalid string value",
   445  		inputMessage: &pb3.Scalars{},
   446  		inputText:    "s_string: invalid_string",
   447  		wantErr:      "invalid value for string type",
   448  	}, {
   449  		desc:         "proto2 bytes set to empty string",
   450  		inputMessage: &pb2.Scalars{},
   451  		inputText:    "opt_bytes: ''",
   452  		wantMessage: &pb2.Scalars{
   453  			OptBytes: []byte(""),
   454  		},
   455  	}, {
   456  		desc:         "proto3 bytes set to empty string",
   457  		inputMessage: &pb3.Scalars{},
   458  		inputText:    "s_bytes: ''",
   459  		wantMessage:  &pb3.Scalars{},
   460  	}, {
   461  		desc:         "proto2 duplicate singular field",
   462  		inputMessage: &pb2.Scalars{},
   463  		inputText: `
   464  opt_bool: true
   465  opt_bool: false
   466  `,
   467  		wantErr: `(line 3:1): non-repeated field "opt_bool" is repeated`,
   468  	}, {
   469  		desc:         "proto2 more duplicate singular field",
   470  		inputMessage: &pb2.Scalars{},
   471  		inputText: `
   472  opt_bool: true
   473  opt_string: "hello"
   474  opt_bool: false
   475  `,
   476  		wantErr: `(line 4:1): non-repeated field "opt_bool" is repeated`,
   477  	}, {
   478  		desc:         "proto2 invalid singular field",
   479  		inputMessage: &pb2.Scalars{},
   480  		inputText: `
   481  opt_bool: [true, false]
   482  `,
   483  		wantErr: "(line 2:11): unexpected token: [",
   484  	}, {
   485  		desc:         "proto3 duplicate singular field",
   486  		inputMessage: &pb3.Scalars{},
   487  		inputText: `
   488  s_bool: false
   489  s_bool: true
   490  `,
   491  		wantErr: `non-repeated field "s_bool" is repeated`,
   492  	}, {
   493  		desc:         "proto3 more duplicate singular field",
   494  		inputMessage: &pb3.Scalars{},
   495  		inputText: `
   496  s_bool: false
   497  s_string: ""
   498  s_bool: true
   499  `,
   500  		wantErr: `non-repeated field "s_bool" is repeated`,
   501  	}, {
   502  		desc:         "proto2 enum",
   503  		inputMessage: &pb2.Enums{},
   504  		inputText: `
   505  opt_enum: ONE
   506  opt_nested_enum: UNO
   507  `,
   508  		wantMessage: &pb2.Enums{
   509  			OptEnum:       pb2.Enum_ONE.Enum(),
   510  			OptNestedEnum: pb2.Enums_UNO.Enum(),
   511  		},
   512  	}, {
   513  		desc:         "protoeditions closed enum",
   514  		inputMessage: &pbeditions.Enums{},
   515  		inputText: `
   516  opt_enum: ONE
   517  opt_nested_enum: UNO
   518  `,
   519  		wantMessage: &pbeditions.Enums{
   520  			OptEnum:       pbeditions.Enum_ONE.Enum(),
   521  			OptNestedEnum: pbeditions.Enums_UNO.Enum(),
   522  		},
   523  	}, {
   524  		desc:         "protoeditions open enum",
   525  		inputMessage: &pbeditions.Enums{},
   526  		inputText: `
   527  implicit_enum: EINS
   528  implicit_nested_enum: ZEHN
   529  `,
   530  		wantMessage: &pbeditions.Enums{
   531  			ImplicitEnum:       pbeditions.OpenEnum_EINS,
   532  			ImplicitNestedEnum: pbeditions.Enums_ZEHN,
   533  		},
   534  	}, {
   535  		desc:         "protoeditions enum numeric value",
   536  		inputMessage: &pbeditions.Enums{},
   537  		inputText: `
   538  implicit_enum: 1
   539  implicit_nested_enum: 10
   540  `,
   541  		wantMessage: &pbeditions.Enums{
   542  			ImplicitEnum:       pbeditions.OpenEnum_EINS,
   543  			ImplicitNestedEnum: pbeditions.Enums_ZEHN,
   544  		},
   545  	}, {
   546  		desc:         "proto2 enum set to numeric values",
   547  		inputMessage: &pb2.Enums{},
   548  		inputText: `
   549  opt_enum: 2
   550  opt_nested_enum: 2
   551  `,
   552  		wantMessage: &pb2.Enums{
   553  			OptEnum:       pb2.Enum_TWO.Enum(),
   554  			OptNestedEnum: pb2.Enums_DOS.Enum(),
   555  		},
   556  	}, {
   557  		desc:         "proto2 enum set to unnamed numeric values",
   558  		inputMessage: &pb2.Enums{},
   559  		inputText: `
   560  opt_enum: 101
   561  opt_nested_enum: -101
   562  `,
   563  		wantMessage: &pb2.Enums{
   564  			OptEnum:       pb2.Enum(101).Enum(),
   565  			OptNestedEnum: pb2.Enums_NestedEnum(-101).Enum(),
   566  		},
   567  	}, {
   568  		desc:         "proto2 enum set to invalid named",
   569  		inputMessage: &pb2.Enums{},
   570  		inputText: `
   571  opt_enum: UNNAMED
   572  opt_nested_enum: UNNAMED_TOO
   573  `,
   574  		wantErr: "invalid value for enum type: UNNAMED",
   575  	}, {
   576  		desc:         "proto3 enum name value",
   577  		inputMessage: &pb3.Enums{},
   578  		inputText: `
   579  s_enum: ONE
   580  s_nested_enum: DIEZ
   581  `,
   582  		wantMessage: &pb3.Enums{
   583  			SEnum:       pb3.Enum_ONE,
   584  			SNestedEnum: pb3.Enums_DIEZ,
   585  		},
   586  	}, {
   587  		desc:         "proto3 enum numeric value",
   588  		inputMessage: &pb3.Enums{},
   589  		inputText: `
   590  s_enum: 2
   591  s_nested_enum: 2
   592  `,
   593  		wantMessage: &pb3.Enums{
   594  			SEnum:       pb3.Enum_TWO,
   595  			SNestedEnum: pb3.Enums_DOS,
   596  		},
   597  	}, {
   598  		desc:         "proto3 enum unnamed numeric value",
   599  		inputMessage: &pb3.Enums{},
   600  		inputText: `
   601  s_enum: 0x7fffffff
   602  s_nested_enum: -0x80000000
   603  `,
   604  		wantMessage: &pb3.Enums{
   605  			SEnum:       0x7fffffff,
   606  			SNestedEnum: -0x80000000,
   607  		},
   608  	}, {
   609  		desc:         "proto2 nested empty messages",
   610  		inputMessage: &pb2.Nests{},
   611  		inputText: `
   612  opt_nested: {}
   613  OptGroup: {}
   614  `,
   615  		wantMessage: &pb2.Nests{
   616  			OptNested: &pb2.Nested{},
   617  			Optgroup:  &pb2.Nests_OptGroup{},
   618  		},
   619  	}, {
   620  		desc:         "protoeditions nested empty messages",
   621  		inputMessage: &pbeditions.Nests{},
   622  		inputText: `
   623  opt_nested: {}
   624  OptGroup: {}
   625  delimited_field: {}
   626  `,
   627  		wantMessage: &pbeditions.Nests{
   628  			OptNested:      &pbeditions.Nested{},
   629  			Optgroup:       &pbeditions.Nests_OptGroup{},
   630  			DelimitedField: &pbeditions.Nests_OptGroup{},
   631  		},
   632  	}, {
   633  		desc:         "message fields with no field separator",
   634  		inputMessage: &pb2.Nests{},
   635  		inputText: `
   636  opt_nested {}
   637  OptGroup {}
   638  `,
   639  		wantMessage: &pb2.Nests{
   640  			OptNested: &pb2.Nested{},
   641  			Optgroup:  &pb2.Nests_OptGroup{},
   642  		},
   643  	}, {
   644  		desc:         "message fields with no field separator",
   645  		inputMessage: &pbeditions.Nests{},
   646  		inputText: `
   647  opt_nested {}
   648  OptGroup {}
   649  delimited_field {}
   650  `,
   651  		wantMessage: &pbeditions.Nests{
   652  			OptNested:      &pbeditions.Nested{},
   653  			Optgroup:       &pbeditions.Nests_OptGroup{},
   654  			DelimitedField: &pbeditions.Nests_OptGroup{},
   655  		},
   656  	}, {
   657  		desc:         "group field name",
   658  		inputMessage: &pb2.Nests{},
   659  		inputText:    `optgroup: {}`,
   660  		wantMessage: &pb2.Nests{
   661  			Optgroup: &pb2.Nests_OptGroup{},
   662  		},
   663  	}, {
   664  		desc:         "delimited encoded group-like message field name",
   665  		inputMessage: &pbeditions.Nests{},
   666  		inputText:    `optgroup {}`,
   667  		wantMessage: &pbeditions.Nests{
   668  			Optgroup: &pbeditions.Nests_OptGroup{},
   669  		},
   670  	}, {
   671  		desc:         "delimited encoded message field name",
   672  		inputMessage: &pbeditions.Nests{},
   673  		inputText:    `Delimited_Field: {}`,
   674  		wantErr:      "unknown field: Delimited_Field",
   675  	}, {
   676  		desc:         "proto2 nested messages",
   677  		inputMessage: &pb2.Nests{},
   678  		inputText: `
   679  opt_nested: {
   680    opt_string: "nested message"
   681    opt_nested: {
   682      opt_string: "another nested message"
   683    }
   684  }
   685  `,
   686  		wantMessage: &pb2.Nests{
   687  			OptNested: &pb2.Nested{
   688  				OptString: proto.String("nested message"),
   689  				OptNested: &pb2.Nested{
   690  					OptString: proto.String("another nested message"),
   691  				},
   692  			},
   693  		},
   694  	}, {
   695  		desc:         "protoeditions delimited encoded nested messages",
   696  		inputMessage: &pbeditions.Nests{},
   697  		inputText: `
   698  opt_nested: {
   699    opt_string: "nested message"
   700    opt_nested: {
   701      opt_string: "another nested message"
   702    }
   703  }
   704  `,
   705  		wantMessage: &pbeditions.Nests{
   706  			OptNested: &pbeditions.Nested{
   707  				OptString: proto.String("nested message"),
   708  				OptNested: &pbeditions.Nested{
   709  					OptString: proto.String("another nested message"),
   710  				},
   711  			},
   712  		},
   713  	}, {
   714  		desc:         "proto3 nested empty message",
   715  		inputMessage: &pb3.Nests{},
   716  		inputText:    "s_nested: {}",
   717  		wantMessage: &pb3.Nests{
   718  			SNested: &pb3.Nested{},
   719  		},
   720  	}, {
   721  		desc:         "proto3 nested message",
   722  		inputMessage: &pb3.Nests{},
   723  		inputText: `
   724  s_nested: {
   725    s_string: "nested message"
   726    s_nested: {
   727      s_string: "another nested message"
   728    }
   729  }
   730  `,
   731  		wantMessage: &pb3.Nests{
   732  			SNested: &pb3.Nested{
   733  				SString: "nested message",
   734  				SNested: &pb3.Nested{
   735  					SString: "another nested message",
   736  				},
   737  			},
   738  		},
   739  	}, {
   740  		desc:         "proto3 nested message contains invalid UTF-8",
   741  		inputMessage: &pb3.Nests{},
   742  		inputText: `s_nested: {
   743    s_string: "abc\xff"
   744  }
   745  `,
   746  		wantErr: "contains invalid UTF-8",
   747  	}, {
   748  		desc:         "oneof set to empty string",
   749  		inputMessage: &pb3.Oneofs{},
   750  		inputText:    "oneof_string: ''",
   751  		wantMessage: &pb3.Oneofs{
   752  			Union: &pb3.Oneofs_OneofString{},
   753  		},
   754  	}, {
   755  		desc:         "oneof set to string",
   756  		inputMessage: &pb3.Oneofs{},
   757  		inputText:    "oneof_string: 'hello'",
   758  		wantMessage: &pb3.Oneofs{
   759  			Union: &pb3.Oneofs_OneofString{
   760  				OneofString: "hello",
   761  			},
   762  		},
   763  	}, {
   764  		desc:         "oneof set to enum",
   765  		inputMessage: &pb3.Oneofs{},
   766  		inputText:    "oneof_enum: TEN",
   767  		wantMessage: &pb3.Oneofs{
   768  			Union: &pb3.Oneofs_OneofEnum{
   769  				OneofEnum: pb3.Enum_TEN,
   770  			},
   771  		},
   772  	}, {
   773  		desc:         "oneof set to empty message",
   774  		inputMessage: &pb3.Oneofs{},
   775  		inputText:    "oneof_nested: {}",
   776  		wantMessage: &pb3.Oneofs{
   777  			Union: &pb3.Oneofs_OneofNested{
   778  				OneofNested: &pb3.Nested{},
   779  			},
   780  		},
   781  	}, {
   782  		desc:         "oneof set to message",
   783  		inputMessage: &pb3.Oneofs{},
   784  		inputText: `
   785  oneof_nested: {
   786    s_string: "nested message"
   787  }
   788  `,
   789  		wantMessage: &pb3.Oneofs{
   790  			Union: &pb3.Oneofs_OneofNested{
   791  				OneofNested: &pb3.Nested{
   792  					SString: "nested message",
   793  				},
   794  			},
   795  		},
   796  	}, {
   797  		desc:         "oneof set to more than one field",
   798  		inputMessage: &pb3.Oneofs{},
   799  		inputText: `
   800  oneof_enum: ZERO
   801  oneof_string: "hello"
   802  `,
   803  		wantErr: `error parsing "oneof_string", oneof pb3.Oneofs.union is already set`,
   804  	}, {
   805  		desc:         "repeated scalar using same field name",
   806  		inputMessage: &pb2.Repeats{},
   807  		inputText: `
   808  rpt_string: "a"
   809  rpt_string: "b"
   810  rpt_int32: 0xff
   811  rpt_float: 1.23
   812  rpt_bytes: "bytes"
   813  `,
   814  		wantMessage: &pb2.Repeats{
   815  			RptString: []string{"a", "b"},
   816  			RptInt32:  []int32{0xff},
   817  			RptFloat:  []float32{1.23},
   818  			RptBytes:  [][]byte{[]byte("bytes")},
   819  		},
   820  	}, {
   821  		desc:         "repeated using mix of [] and repeated field name",
   822  		inputMessage: &pb2.Repeats{},
   823  		inputText: `
   824  rpt_string: "a"
   825  rpt_bool: true
   826  rpt_string: ["x", "y"]
   827  rpt_bool: [ false, true ]
   828  rpt_string: "b"
   829  `,
   830  		wantMessage: &pb2.Repeats{
   831  			RptString: []string{"a", "x", "y", "b"},
   832  			RptBool:   []bool{true, false, true},
   833  		},
   834  	}, {
   835  		desc:         "repeated proto2 contains invalid UTF-8",
   836  		inputMessage: &pb2.Repeats{},
   837  		inputText:    `rpt_string: "abc\xff"`,
   838  		wantMessage: &pb2.Repeats{
   839  			RptString: []string{"abc\xff"},
   840  		},
   841  	}, {
   842  		desc:         "repeated proto3 contains invalid UTF-8",
   843  		inputMessage: &pb3.Repeats{},
   844  		inputText:    `rpt_string: "abc\xff"`,
   845  		wantErr:      "contains invalid UTF-8",
   846  	}, {
   847  		desc:         "repeated enums",
   848  		inputMessage: &pb2.Enums{},
   849  		inputText: `
   850  rpt_enum: TEN
   851  rpt_enum: 1
   852  rpt_nested_enum: [DOS, 2]
   853  rpt_enum: 42
   854  rpt_nested_enum: -47
   855  `,
   856  		wantMessage: &pb2.Enums{
   857  			RptEnum:       []pb2.Enum{pb2.Enum_TEN, pb2.Enum_ONE, 42},
   858  			RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_DOS, pb2.Enums_DOS, -47},
   859  		},
   860  	}, {
   861  		desc:         "repeated nested messages",
   862  		inputMessage: &pb2.Nests{},
   863  		inputText: `
   864  rpt_nested: {
   865    opt_string: "repeat nested one"
   866  }
   867  rpt_nested: {
   868    opt_string: "repeat nested two"
   869    opt_nested: {
   870      opt_string: "inside repeat nested two"
   871    }
   872  }
   873  rpt_nested: {}
   874  `,
   875  		wantMessage: &pb2.Nests{
   876  			RptNested: []*pb2.Nested{
   877  				{
   878  					OptString: proto.String("repeat nested one"),
   879  				},
   880  				{
   881  					OptString: proto.String("repeat nested two"),
   882  					OptNested: &pb2.Nested{
   883  						OptString: proto.String("inside repeat nested two"),
   884  					},
   885  				},
   886  				{},
   887  			},
   888  		},
   889  	}, {
   890  		desc:         "repeated group fields",
   891  		inputMessage: &pb2.Nests{},
   892  		inputText: `
   893  RptGroup: {
   894    rpt_string: "hello"
   895    rpt_string: "world"
   896  }
   897  RptGroup: {}
   898  `,
   899  		wantMessage: &pb2.Nests{
   900  			Rptgroup: []*pb2.Nests_RptGroup{
   901  				{
   902  					RptString: []string{"hello", "world"},
   903  				},
   904  				{},
   905  			},
   906  		},
   907  	}, {
   908  		desc:         "repeated delimited encoded message fields",
   909  		inputMessage: &pbeditions.Nests{},
   910  		inputText: `
   911  RptGroup: {
   912    rpt_string: "hello"
   913    rpt_string: "world"
   914  }
   915  RptGroup: {}
   916  `,
   917  		wantMessage: &pbeditions.Nests{
   918  			Rptgroup: []*pbeditions.Nests_RptGroup{
   919  				{
   920  					RptString: []string{"hello", "world"},
   921  				},
   922  				{},
   923  			},
   924  		},
   925  	}, {
   926  		desc:         "repeated message fields without field separator",
   927  		inputMessage: &pb2.Nests{},
   928  		inputText: `
   929  rpt_nested {
   930    opt_string: "repeat nested one"
   931  }
   932  rpt_nested: [
   933    {
   934      opt_string: "repeat nested two"
   935    },
   936    {}
   937  ]
   938  `,
   939  		wantMessage: &pb2.Nests{
   940  			RptNested: []*pb2.Nested{
   941  				{
   942  					OptString: proto.String("repeat nested one"),
   943  				},
   944  				{
   945  					OptString: proto.String("repeat nested two"),
   946  				},
   947  				{},
   948  			},
   949  		},
   950  	}, {
   951  		desc:         "bools",
   952  		inputMessage: &pb2.Repeats{},
   953  		inputText: `
   954  rpt_bool: [ True, true, t, 1, False, false, f, 0 ]
   955  `,
   956  		wantMessage: &pb2.Repeats{
   957  			RptBool: []bool{true, true, true, true, false, false, false, false},
   958  		},
   959  	}, {
   960  		desc:         "special floats and doubles",
   961  		inputMessage: &pb2.Repeats{},
   962  		inputText: `
   963  rpt_float: [ inf, Inf, infinity, InFiniTy, -inf, -inF, -infinitY, -InfinitY, nan, NaN, Nan ],
   964  rpt_double: [ inf, Inf, infinity, InFiniTy, -inf, -inF, -infinitY, -InfinitY, nan, NaN, Nan ],
   965  `,
   966  		wantMessage: &pb2.Repeats{
   967  			RptFloat: []float32{
   968  				float32(math.Inf(1)),
   969  				float32(math.Inf(1)),
   970  				float32(math.Inf(1)),
   971  				float32(math.Inf(1)),
   972  				float32(math.Inf(-1)),
   973  				float32(math.Inf(-1)),
   974  				float32(math.Inf(-1)),
   975  				float32(math.Inf(-1)),
   976  				float32(math.NaN()),
   977  				float32(math.NaN()),
   978  				float32(math.NaN()),
   979  			},
   980  			RptDouble: []float64{
   981  				math.Inf(1),
   982  				math.Inf(1),
   983  				math.Inf(1),
   984  				math.Inf(1),
   985  				math.Inf(-1),
   986  				math.Inf(-1),
   987  				math.Inf(-1),
   988  				math.Inf(-1),
   989  				math.NaN(),
   990  				math.NaN(),
   991  				math.NaN(),
   992  			},
   993  		},
   994  	}, {
   995  		desc:         "map fields 1",
   996  		inputMessage: &pb3.Maps{},
   997  		inputText: `
   998  int32_to_str: {
   999    key: -101
  1000    value: "-101"
  1001  }
  1002  int32_to_str {
  1003    key: 0
  1004    value: "zero"
  1005  }
  1006  bool_to_uint32: {
  1007    key: false
  1008    value: 101
  1009  }
  1010  int32_to_str: {
  1011    key: 255
  1012    value: "0xff"
  1013  }
  1014  bool_to_uint32 {
  1015    key: true
  1016    value: 42
  1017  }
  1018  `,
  1019  		wantMessage: &pb3.Maps{
  1020  			Int32ToStr: map[int32]string{
  1021  				-101: "-101",
  1022  				0xff: "0xff",
  1023  				0:    "zero",
  1024  			},
  1025  			BoolToUint32: map[bool]uint32{
  1026  				true:  42,
  1027  				false: 101,
  1028  			},
  1029  		},
  1030  	}, {
  1031  		desc:         "map fields 2",
  1032  		inputMessage: &pb3.Maps{},
  1033  		inputText: `
  1034  uint64_to_enum: {
  1035    key: 1
  1036    value: ONE
  1037  }
  1038  uint64_to_enum: {
  1039    key: 2
  1040    value: 2
  1041  }
  1042  uint64_to_enum: {
  1043    key: 10
  1044    value: 101
  1045  }
  1046  `,
  1047  		wantMessage: &pb3.Maps{
  1048  			Uint64ToEnum: map[uint64]pb3.Enum{
  1049  				1:  pb3.Enum_ONE,
  1050  				2:  pb3.Enum_TWO,
  1051  				10: 101,
  1052  			},
  1053  		},
  1054  	}, {
  1055  		desc:         "map fields 3",
  1056  		inputMessage: &pb3.Maps{},
  1057  		inputText: `
  1058  str_to_nested: {
  1059    key: "nested_one"
  1060    value {
  1061      s_string: "nested in a map"
  1062    }
  1063  }
  1064  `,
  1065  		wantMessage: &pb3.Maps{
  1066  			StrToNested: map[string]*pb3.Nested{
  1067  				"nested_one": &pb3.Nested{
  1068  					SString: "nested in a map",
  1069  				},
  1070  			},
  1071  		},
  1072  	}, {
  1073  		desc:         "map fields 4",
  1074  		inputMessage: &pb3.Maps{},
  1075  		inputText: `
  1076  str_to_oneofs: {
  1077    key: "nested"
  1078    value: {
  1079      oneof_nested: {
  1080        s_string: "nested oneof in map field value"
  1081      }
  1082    }
  1083  }
  1084  str_to_oneofs: {
  1085    key: "string"
  1086    value: {
  1087      oneof_string: "hello"
  1088    }
  1089  }
  1090  `,
  1091  		wantMessage: &pb3.Maps{
  1092  			StrToOneofs: map[string]*pb3.Oneofs{
  1093  				"string": &pb3.Oneofs{
  1094  					Union: &pb3.Oneofs_OneofString{
  1095  						OneofString: "hello",
  1096  					},
  1097  				},
  1098  				"nested": &pb3.Oneofs{
  1099  					Union: &pb3.Oneofs_OneofNested{
  1100  						OneofNested: &pb3.Nested{
  1101  							SString: "nested oneof in map field value",
  1102  						},
  1103  					},
  1104  				},
  1105  			},
  1106  		},
  1107  	}, {
  1108  		desc:         "map contains duplicate keys",
  1109  		inputMessage: &pb3.Maps{},
  1110  		inputText: `
  1111  int32_to_str: {
  1112    key: 0
  1113    value: "cero"
  1114  }
  1115  int32_to_str: {
  1116    key: 0
  1117    value: "zero"
  1118  }
  1119  `,
  1120  		wantMessage: &pb3.Maps{
  1121  			Int32ToStr: map[int32]string{
  1122  				0: "zero",
  1123  			},
  1124  		},
  1125  	}, {
  1126  		desc:         "map contains duplicate key fields",
  1127  		inputMessage: &pb3.Maps{},
  1128  		inputText: `
  1129  int32_to_str: {
  1130    key: 0
  1131    key: 1
  1132    value: "cero"
  1133  }
  1134  `,
  1135  		wantErr: `map entry "key" cannot be repeated`,
  1136  	}, {
  1137  		desc:         "map contains duplicate value fields",
  1138  		inputMessage: &pb3.Maps{},
  1139  		inputText: `
  1140  int32_to_str: {
  1141    key: 1
  1142    value: "cero"
  1143    value: "uno"
  1144  }
  1145  `,
  1146  		wantErr: `map entry "value" cannot be repeated`,
  1147  	}, {
  1148  		desc:         "map contains missing key",
  1149  		inputMessage: &pb3.Maps{},
  1150  		inputText: `
  1151  int32_to_str: {
  1152    value: "zero"
  1153  }
  1154  bool_to_uint32: {
  1155    value: 47
  1156  }
  1157  str_to_nested: {
  1158    value: {}
  1159  }
  1160  `,
  1161  		wantMessage: &pb3.Maps{
  1162  			Int32ToStr: map[int32]string{
  1163  				0: "zero",
  1164  			},
  1165  			BoolToUint32: map[bool]uint32{
  1166  				false: 47,
  1167  			},
  1168  			StrToNested: map[string]*pb3.Nested{
  1169  				"": {},
  1170  			},
  1171  		},
  1172  	}, {
  1173  		desc:         "map contains missing value",
  1174  		inputMessage: &pb3.Maps{},
  1175  		inputText: `
  1176  int32_to_str: {
  1177    key: 100
  1178  }
  1179  bool_to_uint32: {
  1180    key: true
  1181  }
  1182  uint64_to_enum: {
  1183    key: 101
  1184  }
  1185  str_to_nested: {
  1186    key: "hello"
  1187  }
  1188  `,
  1189  		wantMessage: &pb3.Maps{
  1190  			Int32ToStr: map[int32]string{
  1191  				100: "",
  1192  			},
  1193  			BoolToUint32: map[bool]uint32{
  1194  				true: 0,
  1195  			},
  1196  			Uint64ToEnum: map[uint64]pb3.Enum{
  1197  				101: pb3.Enum_ZERO,
  1198  			},
  1199  			StrToNested: map[string]*pb3.Nested{
  1200  				"hello": {},
  1201  			},
  1202  		},
  1203  	}, {
  1204  		desc:         "map contains missing key and value",
  1205  		inputMessage: &pb3.Maps{},
  1206  		inputText: `
  1207  int32_to_str: {}
  1208  bool_to_uint32: {}
  1209  uint64_to_enum: {}
  1210  str_to_nested: {}
  1211  `,
  1212  		wantMessage: &pb3.Maps{
  1213  			Int32ToStr: map[int32]string{
  1214  				0: "",
  1215  			},
  1216  			BoolToUint32: map[bool]uint32{
  1217  				false: 0,
  1218  			},
  1219  			Uint64ToEnum: map[uint64]pb3.Enum{
  1220  				0: pb3.Enum_ZERO,
  1221  			},
  1222  			StrToNested: map[string]*pb3.Nested{
  1223  				"": {},
  1224  			},
  1225  		},
  1226  	}, {
  1227  		desc:         "map contains overriding entries",
  1228  		inputMessage: &pb3.Maps{},
  1229  		inputText: `
  1230  int32_to_str: {
  1231    key: 0
  1232  }
  1233  int32_to_str: {
  1234    value: "empty"
  1235  }
  1236  int32_to_str: {}
  1237  `,
  1238  		wantMessage: &pb3.Maps{
  1239  			Int32ToStr: map[int32]string{
  1240  				0: "",
  1241  			},
  1242  		},
  1243  	}, {
  1244  		desc:         "proto2 map field value contains invalid UTF-8",
  1245  		inputMessage: &pb2.Maps{},
  1246  		inputText: `int32_to_str: {
  1247    key: 101
  1248    value: "abc\xff"
  1249  }
  1250  `,
  1251  		wantMessage: &pb2.Maps{
  1252  			Int32ToStr: map[int32]string{101: "abc\xff"},
  1253  		},
  1254  	}, {
  1255  		desc:         "proto2 map field key contains invalid UTF-8",
  1256  		inputMessage: &pb2.Maps{},
  1257  		inputText: `str_to_nested: {
  1258    key: "abc\xff"
  1259    value: {}
  1260  }
  1261  `,
  1262  		wantMessage: &pb2.Maps{
  1263  			StrToNested: map[string]*pb2.Nested{"abc\xff": {}},
  1264  		},
  1265  	}, {
  1266  		desc:         "proto3 map field value contains invalid UTF-8",
  1267  		inputMessage: &pb3.Maps{},
  1268  		inputText: `int32_to_str: {
  1269    key: 101
  1270    value: "abc\xff"
  1271  }
  1272  `,
  1273  		wantErr: "contains invalid UTF-8",
  1274  	}, {
  1275  		desc:         "proto3 map field key contains invalid UTF-8",
  1276  		inputMessage: &pb3.Maps{},
  1277  		inputText: `str_to_nested: {
  1278    key: "abc\xff"
  1279    value: {}
  1280  }
  1281  `,
  1282  		wantErr: "contains invalid UTF-8",
  1283  	}, {
  1284  		desc:         "map contains unknown field",
  1285  		inputMessage: &pb3.Maps{},
  1286  		inputText: `
  1287  int32_to_str: {
  1288    key: 0
  1289    value: "cero"
  1290    unknown: "bad"
  1291  }
  1292  `,
  1293  		wantErr: `(line 5:3): unknown map entry field "unknown"`,
  1294  	}, {
  1295  		desc:         "map contains extension-like key field",
  1296  		inputMessage: &pb3.Maps{},
  1297  		inputText: `
  1298  int32_to_str: {
  1299    [key]: 10
  1300    value: "ten"
  1301  }
  1302  `,
  1303  		wantErr: `unknown map entry field "[key]"`,
  1304  	}, {
  1305  		desc:         "map contains invalid key",
  1306  		inputMessage: &pb3.Maps{},
  1307  		inputText: `
  1308  int32_to_str: {
  1309    key: "invalid"
  1310    value: "cero"
  1311  }
  1312  `,
  1313  		wantErr: "(line 3:8): invalid value for int32 type",
  1314  	}, {
  1315  		desc:         "map contains invalid value",
  1316  		inputMessage: &pb3.Maps{},
  1317  		inputText: `
  1318  int32_to_str: {
  1319    key: 100
  1320    value: 101
  1321  }
  1322  `,
  1323  		wantErr: "(line 4:10): invalid value for string type",
  1324  	}, {
  1325  		desc:         "map contains invalid message value",
  1326  		inputMessage: &pb3.Maps{},
  1327  		inputText: `
  1328  str_to_nested: {
  1329    key: "one"
  1330    value: 1
  1331  }
  1332  `,
  1333  		wantErr: "syntax error (line 4:10): unexpected token: 1",
  1334  	}, {
  1335  		desc:         "map using mix of [] and repeated",
  1336  		inputMessage: &pb3.Maps{},
  1337  		inputText: `
  1338  int32_to_str: {
  1339    key: 1
  1340    value: "one"
  1341  }
  1342  int32_to_str: [
  1343    {
  1344      key: 2
  1345      value: "not this"
  1346    },
  1347    {
  1348    },
  1349    {
  1350      key: 3
  1351      value: "three"
  1352    }
  1353  ]
  1354  int32_to_str: {
  1355    key: 2
  1356    value: "two"
  1357  }
  1358  `,
  1359  		wantMessage: &pb3.Maps{
  1360  			Int32ToStr: map[int32]string{
  1361  				0: "",
  1362  				1: "one",
  1363  				2: "two",
  1364  				3: "three",
  1365  			},
  1366  		},
  1367  	}, {
  1368  		desc:         "required fields not set",
  1369  		inputMessage: &pb2.Requireds{},
  1370  		wantErr:      "required field",
  1371  	}, {
  1372  		desc:         "required field set",
  1373  		inputMessage: &pb2.PartialRequired{},
  1374  		inputText:    "req_string: 'this is required'",
  1375  		wantMessage: &pb2.PartialRequired{
  1376  			ReqString: proto.String("this is required"),
  1377  		},
  1378  	}, {
  1379  		desc:         "required fields partially set",
  1380  		inputMessage: &pb2.Requireds{},
  1381  		inputText: `
  1382  req_bool: false
  1383  req_sfixed64: 3203386110
  1384  req_string: "hello"
  1385  req_enum: ONE
  1386  `,
  1387  		wantMessage: &pb2.Requireds{
  1388  			ReqBool:     proto.Bool(false),
  1389  			ReqSfixed64: proto.Int64(0xbeefcafe),
  1390  			ReqString:   proto.String("hello"),
  1391  			ReqEnum:     pb2.Enum_ONE.Enum(),
  1392  		},
  1393  		wantErr: "required field",
  1394  	}, {
  1395  		desc:         "required fields partially set with AllowPartial",
  1396  		umo:          prototext.UnmarshalOptions{AllowPartial: true},
  1397  		inputMessage: &pb2.Requireds{},
  1398  		inputText: `
  1399  req_bool: false
  1400  req_sfixed64: 3203386110
  1401  req_string: "hello"
  1402  req_enum: ONE
  1403  `,
  1404  		wantMessage: &pb2.Requireds{
  1405  			ReqBool:     proto.Bool(false),
  1406  			ReqSfixed64: proto.Int64(0xbeefcafe),
  1407  			ReqString:   proto.String("hello"),
  1408  			ReqEnum:     pb2.Enum_ONE.Enum(),
  1409  		},
  1410  	}, {
  1411  		desc:         "required fields all set",
  1412  		inputMessage: &pb2.Requireds{},
  1413  		inputText: `
  1414  req_bool: false
  1415  req_sfixed64: 0
  1416  req_double: 0
  1417  req_string: ""
  1418  req_enum: ONE
  1419  req_nested: {}
  1420  `,
  1421  		wantMessage: &pb2.Requireds{
  1422  			ReqBool:     proto.Bool(false),
  1423  			ReqSfixed64: proto.Int64(0),
  1424  			ReqDouble:   proto.Float64(0),
  1425  			ReqString:   proto.String(""),
  1426  			ReqEnum:     pb2.Enum_ONE.Enum(),
  1427  			ReqNested:   &pb2.Nested{},
  1428  		},
  1429  	}, {
  1430  		desc:         "indirect required field",
  1431  		inputMessage: &pb2.IndirectRequired{},
  1432  		inputText:    "opt_nested: {}",
  1433  		wantMessage: &pb2.IndirectRequired{
  1434  			OptNested: &pb2.NestedWithRequired{},
  1435  		},
  1436  		wantErr: "required field",
  1437  	}, {
  1438  		desc:         "indirect required field with AllowPartial",
  1439  		umo:          prototext.UnmarshalOptions{AllowPartial: true},
  1440  		inputMessage: &pb2.IndirectRequired{},
  1441  		inputText:    "opt_nested: {}",
  1442  		wantMessage: &pb2.IndirectRequired{
  1443  			OptNested: &pb2.NestedWithRequired{},
  1444  		},
  1445  	}, {
  1446  		desc:         "indirect required field in repeated",
  1447  		inputMessage: &pb2.IndirectRequired{},
  1448  		inputText: `
  1449  rpt_nested: {
  1450    req_string: "one"
  1451  }
  1452  rpt_nested: {}
  1453  `,
  1454  		wantMessage: &pb2.IndirectRequired{
  1455  			RptNested: []*pb2.NestedWithRequired{
  1456  				{
  1457  					ReqString: proto.String("one"),
  1458  				},
  1459  				{},
  1460  			},
  1461  		},
  1462  		wantErr: "required field",
  1463  	}, {
  1464  		desc:         "indirect required field in repeated with AllowPartial",
  1465  		umo:          prototext.UnmarshalOptions{AllowPartial: true},
  1466  		inputMessage: &pb2.IndirectRequired{},
  1467  		inputText: `
  1468  rpt_nested: {
  1469    req_string: "one"
  1470  }
  1471  rpt_nested: {}
  1472  `,
  1473  		wantMessage: &pb2.IndirectRequired{
  1474  			RptNested: []*pb2.NestedWithRequired{
  1475  				{
  1476  					ReqString: proto.String("one"),
  1477  				},
  1478  				{},
  1479  			},
  1480  		},
  1481  	}, {
  1482  		desc:         "indirect required field in map",
  1483  		inputMessage: &pb2.IndirectRequired{},
  1484  		inputText: `
  1485  str_to_nested: {
  1486    key: "missing"
  1487  }
  1488  str_to_nested: {
  1489    key: "contains"
  1490    value: {
  1491      req_string: "here"
  1492    }
  1493  }
  1494  `,
  1495  		wantMessage: &pb2.IndirectRequired{
  1496  			StrToNested: map[string]*pb2.NestedWithRequired{
  1497  				"missing": &pb2.NestedWithRequired{},
  1498  				"contains": &pb2.NestedWithRequired{
  1499  					ReqString: proto.String("here"),
  1500  				},
  1501  			},
  1502  		},
  1503  		wantErr: "required field",
  1504  	}, {
  1505  		desc:         "indirect required field in map with AllowPartial",
  1506  		umo:          prototext.UnmarshalOptions{AllowPartial: true},
  1507  		inputMessage: &pb2.IndirectRequired{},
  1508  		inputText: `
  1509  str_to_nested: {
  1510    key: "missing"
  1511  }
  1512  str_to_nested: {
  1513    key: "contains"
  1514    value: {
  1515      req_string: "here"
  1516    }
  1517  }
  1518  `,
  1519  		wantMessage: &pb2.IndirectRequired{
  1520  			StrToNested: map[string]*pb2.NestedWithRequired{
  1521  				"missing": &pb2.NestedWithRequired{},
  1522  				"contains": &pb2.NestedWithRequired{
  1523  					ReqString: proto.String("here"),
  1524  				},
  1525  			},
  1526  		},
  1527  	}, {
  1528  		desc:         "indirect required field in oneof",
  1529  		inputMessage: &pb2.IndirectRequired{},
  1530  		inputText: `oneof_nested: {}
  1531  `,
  1532  		wantMessage: &pb2.IndirectRequired{
  1533  			Union: &pb2.IndirectRequired_OneofNested{
  1534  				OneofNested: &pb2.NestedWithRequired{},
  1535  			},
  1536  		},
  1537  		wantErr: "required field",
  1538  	}, {
  1539  		desc:         "indirect required field in oneof with AllowPartial",
  1540  		umo:          prototext.UnmarshalOptions{AllowPartial: true},
  1541  		inputMessage: &pb2.IndirectRequired{},
  1542  		inputText: `oneof_nested: {}
  1543  `,
  1544  		wantMessage: &pb2.IndirectRequired{
  1545  			Union: &pb2.IndirectRequired_OneofNested{
  1546  				OneofNested: &pb2.NestedWithRequired{},
  1547  			},
  1548  		},
  1549  	}, {
  1550  		desc:         "ignore reserved field",
  1551  		inputMessage: &pb2.Nests{},
  1552  		inputText:    "reserved_field: 'ignore this'",
  1553  		wantMessage:  &pb2.Nests{},
  1554  	}, {
  1555  		desc:         "extensions of non-repeated fields",
  1556  		inputMessage: &pb2.Extensions{},
  1557  		inputText: `opt_string: "non-extension field"
  1558  [pb2.opt_ext_bool]: true
  1559  opt_bool: true
  1560  [pb2.opt_ext_nested]: {
  1561    opt_string: "nested in an extension"
  1562    opt_nested: {
  1563      opt_string: "another nested in an extension"
  1564    }
  1565  }
  1566  [pb2.opt_ext_string]: "extension field"
  1567  opt_int32: 42
  1568  [pb2.opt_ext_enum]: TEN
  1569  `,
  1570  		wantMessage: func() proto.Message {
  1571  			m := &pb2.Extensions{
  1572  				OptString: proto.String("non-extension field"),
  1573  				OptBool:   proto.Bool(true),
  1574  				OptInt32:  proto.Int32(42),
  1575  			}
  1576  			proto.SetExtension(m, pb2.E_OptExtBool, true)
  1577  			proto.SetExtension(m, pb2.E_OptExtString, "extension field")
  1578  			proto.SetExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
  1579  			proto.SetExtension(m, pb2.E_OptExtNested, &pb2.Nested{
  1580  				OptString: proto.String("nested in an extension"),
  1581  				OptNested: &pb2.Nested{
  1582  					OptString: proto.String("another nested in an extension"),
  1583  				},
  1584  			})
  1585  			return m
  1586  		}(),
  1587  	}, {
  1588  		desc:         "extension field contains invalid UTF-8",
  1589  		inputMessage: &pb2.Extensions{},
  1590  		inputText:    `[pb2.opt_ext_string]: "abc\xff"`,
  1591  		wantMessage: func() proto.Message {
  1592  			m := &pb2.Extensions{}
  1593  			proto.SetExtension(m, pb2.E_OptExtString, "abc\xff")
  1594  			return m
  1595  		}(),
  1596  	}, {
  1597  		desc:         "extensions of repeated fields",
  1598  		inputMessage: &pb2.Extensions{},
  1599  		inputText: `[pb2.rpt_ext_enum]: TEN
  1600  [pb2.rpt_ext_enum]: 101
  1601  [pb2.rpt_ext_fixed32]: 42
  1602  [pb2.rpt_ext_enum]: ONE
  1603  [pb2.rpt_ext_nested]: {
  1604    opt_string: "one"
  1605  }
  1606  [pb2.rpt_ext_nested]: {
  1607    opt_string: "two"
  1608  }
  1609  [pb2.rpt_ext_fixed32]: 47
  1610  [pb2.rpt_ext_nested]: {
  1611    opt_string: "three"
  1612  }
  1613  `,
  1614  		wantMessage: func() proto.Message {
  1615  			m := &pb2.Extensions{}
  1616  			proto.SetExtension(m, pb2.E_RptExtEnum, []pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  1617  			proto.SetExtension(m, pb2.E_RptExtFixed32, []uint32{42, 47})
  1618  			proto.SetExtension(m, pb2.E_RptExtNested, []*pb2.Nested{
  1619  				&pb2.Nested{OptString: proto.String("one")},
  1620  				&pb2.Nested{OptString: proto.String("two")},
  1621  				&pb2.Nested{OptString: proto.String("three")},
  1622  			})
  1623  			return m
  1624  		}(),
  1625  	}, {
  1626  		desc:         "extensions of non-repeated fields in another message",
  1627  		inputMessage: &pb2.Extensions{},
  1628  		inputText: `[pb2.ExtensionsContainer.opt_ext_bool]: true
  1629  [pb2.ExtensionsContainer.opt_ext_enum]: TEN
  1630  [pb2.ExtensionsContainer.opt_ext_nested]: {
  1631    opt_string: "nested in an extension"
  1632    opt_nested: {
  1633      opt_string: "another nested in an extension"
  1634    }
  1635  }
  1636  [pb2.ExtensionsContainer.opt_ext_string]: "extension field"
  1637  `,
  1638  		wantMessage: func() proto.Message {
  1639  			m := &pb2.Extensions{}
  1640  			proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
  1641  			proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
  1642  			proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
  1643  			proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
  1644  				OptString: proto.String("nested in an extension"),
  1645  				OptNested: &pb2.Nested{
  1646  					OptString: proto.String("another nested in an extension"),
  1647  				},
  1648  			})
  1649  			return m
  1650  		}(),
  1651  	}, {
  1652  		desc:         "extensions of repeated fields in another message",
  1653  		inputMessage: &pb2.Extensions{},
  1654  		inputText: `opt_string: "non-extension field"
  1655  opt_bool: true
  1656  opt_int32: 42
  1657  [pb2.ExtensionsContainer.rpt_ext_nested]: {
  1658    opt_string: "one"
  1659  }
  1660  [pb2.ExtensionsContainer.rpt_ext_enum]: TEN
  1661  [pb2.ExtensionsContainer.rpt_ext_nested]: {
  1662    opt_string: "two"
  1663  }
  1664  [pb2.ExtensionsContainer.rpt_ext_enum]: 101
  1665  [pb2.ExtensionsContainer.rpt_ext_string]: "hello"
  1666  [pb2.ExtensionsContainer.rpt_ext_enum]: ONE
  1667  [pb2.ExtensionsContainer.rpt_ext_nested]: {
  1668    opt_string: "three"
  1669  }
  1670  [pb2.ExtensionsContainer.rpt_ext_string]: "world"
  1671  `,
  1672  		wantMessage: func() proto.Message {
  1673  			m := &pb2.Extensions{
  1674  				OptString: proto.String("non-extension field"),
  1675  				OptBool:   proto.Bool(true),
  1676  				OptInt32:  proto.Int32(42),
  1677  			}
  1678  			proto.SetExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, []pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  1679  			proto.SetExtension(m, pb2.E_ExtensionsContainer_RptExtString, []string{"hello", "world"})
  1680  			proto.SetExtension(m, pb2.E_ExtensionsContainer_RptExtNested, []*pb2.Nested{
  1681  				&pb2.Nested{OptString: proto.String("one")},
  1682  				&pb2.Nested{OptString: proto.String("two")},
  1683  				&pb2.Nested{OptString: proto.String("three")},
  1684  			})
  1685  			return m
  1686  		}(),
  1687  	}, {
  1688  		desc:         "invalid extension field name",
  1689  		inputMessage: &pb2.Extensions{},
  1690  		inputText:    "[pb2.invalid_message_field]: true",
  1691  		wantErr:      "unknown field",
  1692  	}, {
  1693  		desc:         "MessageSet",
  1694  		inputMessage: &pb2.MessageSet{},
  1695  		inputText: `
  1696  [pb2.MessageSetExtension]: {
  1697    opt_string: "a messageset extension"
  1698  }
  1699  [pb2.MessageSetExtension.ext_nested]: {
  1700    opt_string: "just a regular extension"
  1701  }
  1702  [pb2.MessageSetExtension.not_message_set_extension]: {
  1703    opt_string: "not a messageset extension"
  1704  }
  1705  `,
  1706  		wantMessage: func() proto.Message {
  1707  			m := &pb2.MessageSet{}
  1708  			proto.SetExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
  1709  				OptString: proto.String("a messageset extension"),
  1710  			})
  1711  			proto.SetExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
  1712  				OptString: proto.String("not a messageset extension"),
  1713  			})
  1714  			proto.SetExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
  1715  				OptString: proto.String("just a regular extension"),
  1716  			})
  1717  			return m
  1718  		}(),
  1719  		skip: !flags.ProtoLegacy,
  1720  	}, {
  1721  		desc:         "not real MessageSet 1",
  1722  		inputMessage: &pb2.FakeMessageSet{},
  1723  		inputText: `
  1724  [pb2.FakeMessageSetExtension.message_set_extension]: {
  1725    opt_string: "not a messageset extension"
  1726  }
  1727  `,
  1728  		wantMessage: func() proto.Message {
  1729  			m := &pb2.FakeMessageSet{}
  1730  			proto.SetExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
  1731  				OptString: proto.String("not a messageset extension"),
  1732  			})
  1733  			return m
  1734  		}(),
  1735  		skip: !flags.ProtoLegacy,
  1736  	}, {
  1737  		desc:         "not real MessageSet 2",
  1738  		inputMessage: &pb2.FakeMessageSet{},
  1739  		inputText: `
  1740  [pb2.FakeMessageSetExtension]: {
  1741    opt_string: "not a messageset extension"
  1742  }
  1743  `,
  1744  		wantErr: `unable to resolve [[pb2.FakeMessageSetExtension]]: found wrong type`,
  1745  		skip:    !flags.ProtoLegacy,
  1746  	}, {
  1747  		desc:         "not real MessageSet 3",
  1748  		inputMessage: &pb2.MessageSet{},
  1749  		inputText: `
  1750  [pb2.message_set_extension]: {
  1751    opt_string: "another not a messageset extension"
  1752  }`,
  1753  		wantMessage: func() proto.Message {
  1754  			m := &pb2.MessageSet{}
  1755  			proto.SetExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
  1756  				OptString: proto.String("another not a messageset extension"),
  1757  			})
  1758  			return m
  1759  		}(),
  1760  		skip: !flags.ProtoLegacy,
  1761  	}, {
  1762  		desc:         "Any not expanded",
  1763  		inputMessage: &anypb.Any{},
  1764  		inputText: `
  1765  type_url: "pb2.Nested"
  1766  value: "some bytes"
  1767  `,
  1768  		wantMessage: &anypb.Any{
  1769  			TypeUrl: "pb2.Nested",
  1770  			Value:   []byte("some bytes"),
  1771  		},
  1772  	}, {
  1773  		desc:         "Any not expanded missing value",
  1774  		inputMessage: &anypb.Any{},
  1775  		inputText:    `type_url: "pb2.Nested"`,
  1776  		wantMessage: &anypb.Any{
  1777  			TypeUrl: "pb2.Nested",
  1778  		},
  1779  	}, {
  1780  		desc:         "Any not expanded missing type_url",
  1781  		inputMessage: &anypb.Any{},
  1782  		inputText:    `value: "some bytes"`,
  1783  		wantMessage: &anypb.Any{
  1784  			Value: []byte("some bytes"),
  1785  		},
  1786  	}, {
  1787  		desc:         "Any expanded",
  1788  		inputMessage: &anypb.Any{},
  1789  		inputText: `
  1790  [foobar/pb2.Nested]: {
  1791    opt_string: "embedded inside Any"
  1792    opt_nested: {
  1793      opt_string: "inception"
  1794    }
  1795  }
  1796  `,
  1797  		wantMessage: func() proto.Message {
  1798  			m := &pb2.Nested{
  1799  				OptString: proto.String("embedded inside Any"),
  1800  				OptNested: &pb2.Nested{
  1801  					OptString: proto.String("inception"),
  1802  				},
  1803  			}
  1804  			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1805  			if err != nil {
  1806  				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1807  			}
  1808  			return &anypb.Any{
  1809  				TypeUrl: "foobar/pb2.Nested",
  1810  				Value:   b,
  1811  			}
  1812  		}(),
  1813  	}, {
  1814  		desc:         "Any expanded with empty value",
  1815  		inputMessage: &anypb.Any{},
  1816  		inputText:    `[foo.com/pb2.Nested]: {}`,
  1817  		wantMessage: &anypb.Any{
  1818  			TypeUrl: "foo.com/pb2.Nested",
  1819  		},
  1820  	}, {
  1821  		desc:         "Any expanded with missing required",
  1822  		inputMessage: &anypb.Any{},
  1823  		inputText: `
  1824  [pb2.PartialRequired]: {
  1825    opt_string: "embedded inside Any"
  1826  }
  1827  `,
  1828  		wantMessage: func() proto.Message {
  1829  			m := &pb2.PartialRequired{
  1830  				OptString: proto.String("embedded inside Any"),
  1831  			}
  1832  			b, err := proto.MarshalOptions{
  1833  				AllowPartial:  true,
  1834  				Deterministic: true,
  1835  			}.Marshal(m)
  1836  			if err != nil {
  1837  				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1838  			}
  1839  			return &anypb.Any{
  1840  				TypeUrl: "pb2.PartialRequired",
  1841  				Value:   b,
  1842  			}
  1843  		}(),
  1844  	}, {
  1845  		desc:         "Any with invalid UTF-8",
  1846  		inputMessage: &anypb.Any{},
  1847  		inputText: `
  1848  [pb3.Nested]: {
  1849    s_string: "abc\xff"
  1850  }
  1851  `,
  1852  		wantErr: "contains invalid UTF-8",
  1853  	}, {
  1854  		desc:         "Any expanded with unregistered type",
  1855  		umo:          prototext.UnmarshalOptions{Resolver: new(protoregistry.Types)},
  1856  		inputMessage: &anypb.Any{},
  1857  		inputText:    `[SomeMessage]: {}`,
  1858  		wantErr:      "unable to resolve message [SomeMessage]",
  1859  	}, {
  1860  		desc:         "Any expanded with invalid value",
  1861  		inputMessage: &anypb.Any{},
  1862  		inputText:    `[pb2.Nested]: 123`,
  1863  		wantErr:      "unexpected token: 123",
  1864  	}, {
  1865  		desc:         "Any expanded with unknown fields",
  1866  		inputMessage: &anypb.Any{},
  1867  		inputText: `
  1868  [pb2.Nested]: {}
  1869  unknown: ""
  1870  `,
  1871  		wantErr: `invalid field name "unknown" in google.protobuf.Any message`,
  1872  	}, {
  1873  		desc:         "Any contains expanded and unexpanded fields",
  1874  		inputMessage: &anypb.Any{},
  1875  		inputText: `
  1876  [pb2.Nested]: {}
  1877  type_url: "pb2.Nested"
  1878  `,
  1879  		wantErr: "(line 3:1): conflict with [pb2.Nested] field",
  1880  	}, {
  1881  		desc:         "weak fields",
  1882  		inputMessage: &testpb.TestWeak{},
  1883  		inputText:    `weak_message1:{a:1}`,
  1884  		wantMessage: func() *testpb.TestWeak {
  1885  			m := new(testpb.TestWeak)
  1886  			m.SetWeakMessage1(&weakpb.WeakImportMessage1{A: proto.Int32(1)})
  1887  			return m
  1888  		}(),
  1889  		skip: !flags.ProtoLegacy,
  1890  	}, {
  1891  		desc:         "weak fields; unknown field",
  1892  		inputMessage: &testpb.TestWeak{},
  1893  		inputText:    `weak_message1:{a:1} weak_message2:{a:1}`,
  1894  		wantErr:      "unknown field: weak_message2", // weak_message2 is unknown since the package containing it is not imported
  1895  		skip:         !flags.ProtoLegacy,
  1896  	}}
  1897  
  1898  	for _, tt := range tests {
  1899  		tt := tt
  1900  		if tt.skip {
  1901  			continue
  1902  		}
  1903  		t.Run(tt.desc, func(t *testing.T) {
  1904  			err := tt.umo.Unmarshal([]byte(tt.inputText), tt.inputMessage)
  1905  			if err != nil {
  1906  				if tt.wantErr == "" {
  1907  					t.Errorf("Unmarshal() got unexpected error: %v", err)
  1908  				} else if !strings.Contains(err.Error(), tt.wantErr) {
  1909  					t.Errorf("Unmarshal() error got %q, want %q", err, tt.wantErr)
  1910  				}
  1911  				return
  1912  			}
  1913  			if tt.wantErr != "" {
  1914  				t.Errorf("Unmarshal() got nil error, want error %q", tt.wantErr)
  1915  				return
  1916  			}
  1917  			if tt.wantMessage != nil && !proto.Equal(tt.inputMessage, tt.wantMessage) {
  1918  				t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", tt.inputMessage, tt.wantMessage)
  1919  			}
  1920  		})
  1921  	}
  1922  }
  1923  

View as plain text