...

Source file src/github.com/gogo/protobuf/proto/text_parser_test.go

Documentation: github.com/gogo/protobuf/proto

     1  // Go support for Protocol Buffers - Google's data interchange format
     2  //
     3  // Copyright 2010 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 proto_test
    33  
    34  import (
    35  	"fmt"
    36  	"math"
    37  	"testing"
    38  
    39  	. "github.com/gogo/protobuf/proto"
    40  	proto3pb "github.com/gogo/protobuf/proto/proto3_proto"
    41  	. "github.com/gogo/protobuf/proto/test_proto"
    42  )
    43  
    44  type UnmarshalTextTest struct {
    45  	in  string
    46  	err string // if "", no error expected
    47  	out *MyMessage
    48  }
    49  
    50  func buildExtStructTest(text string) UnmarshalTextTest {
    51  	msg := &MyMessage{
    52  		Count: Int32(42),
    53  	}
    54  	SetExtension(msg, E_Ext_More, &Ext{
    55  		Data: String("Hello, world!"),
    56  	})
    57  	return UnmarshalTextTest{in: text, out: msg}
    58  }
    59  
    60  func buildExtDataTest(text string) UnmarshalTextTest {
    61  	msg := &MyMessage{
    62  		Count: Int32(42),
    63  	}
    64  	SetExtension(msg, E_Ext_Text, String("Hello, world!"))
    65  	SetExtension(msg, E_Ext_Number, Int32(1729))
    66  	return UnmarshalTextTest{in: text, out: msg}
    67  }
    68  
    69  func buildExtRepStringTest(text string) UnmarshalTextTest {
    70  	msg := &MyMessage{
    71  		Count: Int32(42),
    72  	}
    73  	if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil {
    74  		panic(err)
    75  	}
    76  	return UnmarshalTextTest{in: text, out: msg}
    77  }
    78  
    79  var unMarshalTextTests = []UnmarshalTextTest{
    80  	// Basic
    81  	{
    82  		in: " count:42\n  name:\"Dave\" ",
    83  		out: &MyMessage{
    84  			Count: Int32(42),
    85  			Name:  String("Dave"),
    86  		},
    87  	},
    88  
    89  	// Empty quoted string
    90  	{
    91  		in: `count:42 name:""`,
    92  		out: &MyMessage{
    93  			Count: Int32(42),
    94  			Name:  String(""),
    95  		},
    96  	},
    97  
    98  	// Quoted string concatenation with double quotes
    99  	{
   100  		in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`,
   101  		out: &MyMessage{
   102  			Count: Int32(42),
   103  			Name:  String("My name is elsewhere"),
   104  		},
   105  	},
   106  
   107  	// Quoted string concatenation with single quotes
   108  	{
   109  		in: "count:42 name: 'My name is '\n'elsewhere'",
   110  		out: &MyMessage{
   111  			Count: Int32(42),
   112  			Name:  String("My name is elsewhere"),
   113  		},
   114  	},
   115  
   116  	// Quoted string concatenations with mixed quotes
   117  	{
   118  		in: "count:42 name: 'My name is '\n\"elsewhere\"",
   119  		out: &MyMessage{
   120  			Count: Int32(42),
   121  			Name:  String("My name is elsewhere"),
   122  		},
   123  	},
   124  	{
   125  		in: "count:42 name: \"My name is \"\n'elsewhere'",
   126  		out: &MyMessage{
   127  			Count: Int32(42),
   128  			Name:  String("My name is elsewhere"),
   129  		},
   130  	},
   131  
   132  	// Quoted string with escaped apostrophe
   133  	{
   134  		in: `count:42 name: "HOLIDAY - New Year\'s Day"`,
   135  		out: &MyMessage{
   136  			Count: Int32(42),
   137  			Name:  String("HOLIDAY - New Year's Day"),
   138  		},
   139  	},
   140  
   141  	// Quoted string with single quote
   142  	{
   143  		in: `count:42 name: 'Roger "The Ramster" Ramjet'`,
   144  		out: &MyMessage{
   145  			Count: Int32(42),
   146  			Name:  String(`Roger "The Ramster" Ramjet`),
   147  		},
   148  	},
   149  
   150  	// Quoted string with all the accepted special characters from the C++ test
   151  	{
   152  		in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and  multiple   spaces\"",
   153  		out: &MyMessage{
   154  			Count: Int32(42),
   155  			Name:  String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and  multiple   spaces"),
   156  		},
   157  	},
   158  
   159  	// Quoted string with quoted backslash
   160  	{
   161  		in: `count:42 name: "\\'xyz"`,
   162  		out: &MyMessage{
   163  			Count: Int32(42),
   164  			Name:  String(`\'xyz`),
   165  		},
   166  	},
   167  
   168  	// Quoted string with UTF-8 bytes.
   169  	{
   170  		in: "count:42 name: '\303\277\302\201\x00\xAB\xCD\xEF'",
   171  		out: &MyMessage{
   172  			Count: Int32(42),
   173  			Name:  String("\303\277\302\201\x00\xAB\xCD\xEF"),
   174  		},
   175  	},
   176  
   177  	// Quoted string with unicode escapes.
   178  	{
   179  		in: `count: 42 name: "\u0047\U00000047\uffff\U0010ffff"`,
   180  		out: &MyMessage{
   181  			Count: Int32(42),
   182  			Name:  String("GG\uffff\U0010ffff"),
   183  		},
   184  	},
   185  
   186  	// Bad quoted string
   187  	{
   188  		in:  `inner: < host: "\0" >` + "\n",
   189  		err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`,
   190  	},
   191  
   192  	// Bad \u escape
   193  	{
   194  		in:  `count: 42 name: "\u000"`,
   195  		err: `line 1.16: invalid quoted string "\u000": \u requires 4 following digits`,
   196  	},
   197  
   198  	// Bad \U escape
   199  	{
   200  		in:  `count: 42 name: "\U0000000"`,
   201  		err: `line 1.16: invalid quoted string "\U0000000": \U requires 8 following digits`,
   202  	},
   203  
   204  	// Bad \U escape
   205  	{
   206  		in:  `count: 42 name: "\xxx"`,
   207  		err: `line 1.16: invalid quoted string "\xxx": \xxx contains non-hexadecimal digits`,
   208  	},
   209  
   210  	// Number too large for int64
   211  	{
   212  		in:  "count: 1 others { key: 123456789012345678901 }",
   213  		err: "line 1.23: invalid int64: 123456789012345678901",
   214  	},
   215  
   216  	// Number too large for int32
   217  	{
   218  		in:  "count: 1234567890123",
   219  		err: "line 1.7: invalid int32: 1234567890123",
   220  	},
   221  
   222  	// Number in hexadecimal
   223  	{
   224  		in: "count: 0x2beef",
   225  		out: &MyMessage{
   226  			Count: Int32(0x2beef),
   227  		},
   228  	},
   229  
   230  	// Number in octal
   231  	{
   232  		in: "count: 024601",
   233  		out: &MyMessage{
   234  			Count: Int32(024601),
   235  		},
   236  	},
   237  
   238  	// Floating point number with "f" suffix
   239  	{
   240  		in: "count: 4 others:< weight: 17.0f >",
   241  		out: &MyMessage{
   242  			Count: Int32(4),
   243  			Others: []*OtherMessage{
   244  				{
   245  					Weight: Float32(17),
   246  				},
   247  			},
   248  		},
   249  	},
   250  
   251  	// Floating point positive infinity
   252  	{
   253  		in: "count: 4 bigfloat: inf",
   254  		out: &MyMessage{
   255  			Count:    Int32(4),
   256  			Bigfloat: Float64(math.Inf(1)),
   257  		},
   258  	},
   259  
   260  	// Floating point negative infinity
   261  	{
   262  		in: "count: 4 bigfloat: -inf",
   263  		out: &MyMessage{
   264  			Count:    Int32(4),
   265  			Bigfloat: Float64(math.Inf(-1)),
   266  		},
   267  	},
   268  
   269  	// Number too large for float32
   270  	{
   271  		in:  "others:< weight: 12345678901234567890123456789012345678901234567890 >",
   272  		err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890",
   273  	},
   274  
   275  	// Number posing as a quoted string
   276  	{
   277  		in:  `inner: < host: 12 >` + "\n",
   278  		err: `line 1.15: invalid string: 12`,
   279  	},
   280  
   281  	// Quoted string posing as int32
   282  	{
   283  		in:  `count: "12"`,
   284  		err: `line 1.7: invalid int32: "12"`,
   285  	},
   286  
   287  	// Quoted string posing a float32
   288  	{
   289  		in:  `others:< weight: "17.4" >`,
   290  		err: `line 1.17: invalid float32: "17.4"`,
   291  	},
   292  
   293  	// unclosed bracket doesn't cause infinite loop
   294  	{
   295  		in:  `[`,
   296  		err: `line 1.0: unclosed type_url or extension name`,
   297  	},
   298  
   299  	// Enum
   300  	{
   301  		in: `count:42 bikeshed: BLUE`,
   302  		out: &MyMessage{
   303  			Count:    Int32(42),
   304  			Bikeshed: MyMessage_BLUE.Enum(),
   305  		},
   306  	},
   307  
   308  	// Repeated field
   309  	{
   310  		in: `count:42 pet: "horsey" pet:"bunny"`,
   311  		out: &MyMessage{
   312  			Count: Int32(42),
   313  			Pet:   []string{"horsey", "bunny"},
   314  		},
   315  	},
   316  
   317  	// Repeated field with list notation
   318  	{
   319  		in: `count:42 pet: ["horsey", "bunny"]`,
   320  		out: &MyMessage{
   321  			Count: Int32(42),
   322  			Pet:   []string{"horsey", "bunny"},
   323  		},
   324  	},
   325  
   326  	// Repeated message with/without colon and <>/{}
   327  	{
   328  		in: `count:42 others:{} others{} others:<> others:{}`,
   329  		out: &MyMessage{
   330  			Count: Int32(42),
   331  			Others: []*OtherMessage{
   332  				{},
   333  				{},
   334  				{},
   335  				{},
   336  			},
   337  		},
   338  	},
   339  
   340  	// Missing colon for inner message
   341  	{
   342  		in: `count:42 inner < host: "cauchy.syd" >`,
   343  		out: &MyMessage{
   344  			Count: Int32(42),
   345  			Inner: &InnerMessage{
   346  				Host: String("cauchy.syd"),
   347  			},
   348  		},
   349  	},
   350  
   351  	// Missing colon for string field
   352  	{
   353  		in:  `name "Dave"`,
   354  		err: `line 1.5: expected ':', found "\"Dave\""`,
   355  	},
   356  
   357  	// Missing colon for int32 field
   358  	{
   359  		in:  `count 42`,
   360  		err: `line 1.6: expected ':', found "42"`,
   361  	},
   362  
   363  	// Missing required field
   364  	{
   365  		in:  `name: "Pawel"`,
   366  		err: fmt.Sprintf(`proto: required field "%T.count" not set`, MyMessage{}),
   367  		out: &MyMessage{
   368  			Name: String("Pawel"),
   369  		},
   370  	},
   371  
   372  	// Missing required field in a required submessage
   373  	{
   374  		in:  `count: 42 we_must_go_deeper < leo_finally_won_an_oscar <> >`,
   375  		err: fmt.Sprintf(`proto: required field "%T.host" not set`, InnerMessage{}),
   376  		out: &MyMessage{
   377  			Count:          Int32(42),
   378  			WeMustGoDeeper: &RequiredInnerMessage{LeoFinallyWonAnOscar: &InnerMessage{}},
   379  		},
   380  	},
   381  
   382  	// Repeated non-repeated field
   383  	{
   384  		in:  `name: "Rob" name: "Russ"`,
   385  		err: `line 1.12: non-repeated field "name" was repeated`,
   386  	},
   387  
   388  	// Group
   389  	{
   390  		in: `count: 17 SomeGroup { group_field: 12 }`,
   391  		out: &MyMessage{
   392  			Count: Int32(17),
   393  			Somegroup: &MyMessage_SomeGroup{
   394  				GroupField: Int32(12),
   395  			},
   396  		},
   397  	},
   398  
   399  	// Semicolon between fields
   400  	{
   401  		in: `count:3;name:"Calvin"`,
   402  		out: &MyMessage{
   403  			Count: Int32(3),
   404  			Name:  String("Calvin"),
   405  		},
   406  	},
   407  	// Comma between fields
   408  	{
   409  		in: `count:4,name:"Ezekiel"`,
   410  		out: &MyMessage{
   411  			Count: Int32(4),
   412  			Name:  String("Ezekiel"),
   413  		},
   414  	},
   415  
   416  	// Boolean false
   417  	{
   418  		in: `count:42 inner { host: "example.com" connected: false }`,
   419  		out: &MyMessage{
   420  			Count: Int32(42),
   421  			Inner: &InnerMessage{
   422  				Host:      String("example.com"),
   423  				Connected: Bool(false),
   424  			},
   425  		},
   426  	},
   427  	// Boolean true
   428  	{
   429  		in: `count:42 inner { host: "example.com" connected: true }`,
   430  		out: &MyMessage{
   431  			Count: Int32(42),
   432  			Inner: &InnerMessage{
   433  				Host:      String("example.com"),
   434  				Connected: Bool(true),
   435  			},
   436  		},
   437  	},
   438  	// Boolean 0
   439  	{
   440  		in: `count:42 inner { host: "example.com" connected: 0 }`,
   441  		out: &MyMessage{
   442  			Count: Int32(42),
   443  			Inner: &InnerMessage{
   444  				Host:      String("example.com"),
   445  				Connected: Bool(false),
   446  			},
   447  		},
   448  	},
   449  	// Boolean 1
   450  	{
   451  		in: `count:42 inner { host: "example.com" connected: 1 }`,
   452  		out: &MyMessage{
   453  			Count: Int32(42),
   454  			Inner: &InnerMessage{
   455  				Host:      String("example.com"),
   456  				Connected: Bool(true),
   457  			},
   458  		},
   459  	},
   460  	// Boolean f
   461  	{
   462  		in: `count:42 inner { host: "example.com" connected: f }`,
   463  		out: &MyMessage{
   464  			Count: Int32(42),
   465  			Inner: &InnerMessage{
   466  				Host:      String("example.com"),
   467  				Connected: Bool(false),
   468  			},
   469  		},
   470  	},
   471  	// Boolean t
   472  	{
   473  		in: `count:42 inner { host: "example.com" connected: t }`,
   474  		out: &MyMessage{
   475  			Count: Int32(42),
   476  			Inner: &InnerMessage{
   477  				Host:      String("example.com"),
   478  				Connected: Bool(true),
   479  			},
   480  		},
   481  	},
   482  	// Boolean False
   483  	{
   484  		in: `count:42 inner { host: "example.com" connected: False }`,
   485  		out: &MyMessage{
   486  			Count: Int32(42),
   487  			Inner: &InnerMessage{
   488  				Host:      String("example.com"),
   489  				Connected: Bool(false),
   490  			},
   491  		},
   492  	},
   493  	// Boolean True
   494  	{
   495  		in: `count:42 inner { host: "example.com" connected: True }`,
   496  		out: &MyMessage{
   497  			Count: Int32(42),
   498  			Inner: &InnerMessage{
   499  				Host:      String("example.com"),
   500  				Connected: Bool(true),
   501  			},
   502  		},
   503  	},
   504  
   505  	// Extension
   506  	buildExtStructTest(`count: 42 [test_proto.Ext.more]:<data:"Hello, world!" >`),
   507  	buildExtStructTest(`count: 42 [test_proto.Ext.more] {data:"Hello, world!"}`),
   508  	buildExtDataTest(`count: 42 [test_proto.Ext.text]:"Hello, world!" [test_proto.Ext.number]:1729`),
   509  	buildExtRepStringTest(`count: 42 [test_proto.greeting]:"bula" [test_proto.greeting]:"hola"`),
   510  
   511  	// Big all-in-one
   512  	{
   513  		in: "count:42  # Meaning\n" +
   514  			`name:"Dave" ` +
   515  			`quote:"\"I didn't want to go.\"" ` +
   516  			`pet:"bunny" ` +
   517  			`pet:"kitty" ` +
   518  			`pet:"horsey" ` +
   519  			`inner:<` +
   520  			`  host:"footrest.syd" ` +
   521  			`  port:7001 ` +
   522  			`  connected:true ` +
   523  			`> ` +
   524  			`others:<` +
   525  			`  key:3735928559 ` +
   526  			`  value:"\x01A\a\f" ` +
   527  			`> ` +
   528  			`others:<` +
   529  			"  weight:58.9  # Atomic weight of Co\n" +
   530  			`  inner:<` +
   531  			`    host:"lesha.mtv" ` +
   532  			`    port:8002 ` +
   533  			`  >` +
   534  			`>`,
   535  		out: &MyMessage{
   536  			Count: Int32(42),
   537  			Name:  String("Dave"),
   538  			Quote: String(`"I didn't want to go."`),
   539  			Pet:   []string{"bunny", "kitty", "horsey"},
   540  			Inner: &InnerMessage{
   541  				Host:      String("footrest.syd"),
   542  				Port:      Int32(7001),
   543  				Connected: Bool(true),
   544  			},
   545  			Others: []*OtherMessage{
   546  				{
   547  					Key:   Int64(3735928559),
   548  					Value: []byte{0x1, 'A', '\a', '\f'},
   549  				},
   550  				{
   551  					Weight: Float32(58.9),
   552  					Inner: &InnerMessage{
   553  						Host: String("lesha.mtv"),
   554  						Port: Int32(8002),
   555  					},
   556  				},
   557  			},
   558  		},
   559  	},
   560  }
   561  
   562  func TestUnmarshalText(t *testing.T) {
   563  	for i, test := range unMarshalTextTests {
   564  		pb := new(MyMessage)
   565  		err := UnmarshalText(test.in, pb)
   566  		if test.err == "" {
   567  			// We don't expect failure.
   568  			if err != nil {
   569  				t.Errorf("Test %d: Unexpected error: %v", i, err)
   570  			} else if !Equal(pb, test.out) {
   571  				t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v",
   572  					i, pb, test.out)
   573  			}
   574  		} else {
   575  			// We do expect failure.
   576  			if err == nil {
   577  				t.Errorf("Test %d: Didn't get expected error: %v", i, test.err)
   578  			} else if err.Error() != test.err {
   579  				t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v",
   580  					i, err.Error(), test.err)
   581  			} else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !Equal(pb, test.out) {
   582  				t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v",
   583  					i, pb, test.out)
   584  			}
   585  		}
   586  	}
   587  }
   588  
   589  func TestUnmarshalTextCustomMessage(t *testing.T) {
   590  	msg := &textMessage{}
   591  	if err := UnmarshalText("custom", msg); err != nil {
   592  		t.Errorf("Unexpected error from custom unmarshal: %v", err)
   593  	}
   594  	if UnmarshalText("not custom", msg) == nil {
   595  		t.Errorf("Didn't get expected error from custom unmarshal")
   596  	}
   597  }
   598  
   599  // Regression test; this caused a panic.
   600  func TestRepeatedEnum(t *testing.T) {
   601  	pb := new(RepeatedEnum)
   602  	if err := UnmarshalText("color: RED", pb); err != nil {
   603  		t.Fatal(err)
   604  	}
   605  	exp := &RepeatedEnum{
   606  		Color: []RepeatedEnum_Color{RepeatedEnum_RED},
   607  	}
   608  	if !Equal(pb, exp) {
   609  		t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp)
   610  	}
   611  }
   612  
   613  func TestProto3TextParsing(t *testing.T) {
   614  	m := new(proto3pb.Message)
   615  	const in = `name: "Wallace" true_scotsman: true`
   616  	want := &proto3pb.Message{
   617  		Name:         "Wallace",
   618  		TrueScotsman: true,
   619  	}
   620  	if err := UnmarshalText(in, m); err != nil {
   621  		t.Fatal(err)
   622  	}
   623  	if !Equal(m, want) {
   624  		t.Errorf("\n got %v\nwant %v", m, want)
   625  	}
   626  }
   627  
   628  func TestMapParsing(t *testing.T) {
   629  	m := new(MessageWithMap)
   630  	const in = `name_mapping:<key:1234 value:"Feist"> name_mapping:<key:1 value:"Beatles">` +
   631  		`msg_mapping:<key:-4, value:<f: 2.0>,>` + // separating commas are okay
   632  		`msg_mapping<key:-2 value<f: 4.0>>` + // no colon after "value"
   633  		`msg_mapping:<value:<f: 5.0>>` + // omitted key
   634  		`msg_mapping:<key:1>` + // omitted value
   635  		`byte_mapping:<key:true value:"so be it">` +
   636  		`byte_mapping:<>` // omitted key and value
   637  	want := &MessageWithMap{
   638  		NameMapping: map[int32]string{
   639  			1:    "Beatles",
   640  			1234: "Feist",
   641  		},
   642  		MsgMapping: map[int64]*FloatingPoint{
   643  			-4: {F: Float64(2.0)},
   644  			-2: {F: Float64(4.0)},
   645  			0:  {F: Float64(5.0)},
   646  			1:  nil,
   647  		},
   648  		ByteMapping: map[bool][]byte{
   649  			false: nil,
   650  			true:  []byte("so be it"),
   651  		},
   652  	}
   653  	if err := UnmarshalText(in, m); err != nil {
   654  		t.Fatal(err)
   655  	}
   656  	if !Equal(m, want) {
   657  		t.Errorf("\n got %v\nwant %v", m, want)
   658  	}
   659  }
   660  
   661  func TestOneofParsing(t *testing.T) {
   662  	const in = `name:"Shrek"`
   663  	m := new(Communique)
   664  	want := &Communique{Union: &Communique_Name{Name: "Shrek"}}
   665  	if err := UnmarshalText(in, m); err != nil {
   666  		t.Fatal(err)
   667  	}
   668  	if !Equal(m, want) {
   669  		t.Errorf("\n got %v\nwant %v", m, want)
   670  	}
   671  
   672  	const inOverwrite = `name:"Shrek" number:42`
   673  	m = new(Communique)
   674  	testErr := "line 1.13: field 'number' would overwrite already parsed oneof 'Union'"
   675  	if err := UnmarshalText(inOverwrite, m); err == nil {
   676  		t.Errorf("TestOneofParsing: Didn't get expected error: %v", testErr)
   677  	} else if err.Error() != testErr {
   678  		t.Errorf("TestOneofParsing: Incorrect error.\nHave: %v\nWant: %v",
   679  			err.Error(), testErr)
   680  	}
   681  
   682  }
   683  
   684  var benchInput string
   685  
   686  func init() {
   687  	benchInput = "count: 4\n"
   688  	for i := 0; i < 1000; i++ {
   689  		benchInput += "pet: \"fido\"\n"
   690  	}
   691  
   692  	// Check it is valid input.
   693  	pb := new(MyMessage)
   694  	err := UnmarshalText(benchInput, pb)
   695  	if err != nil {
   696  		panic("Bad benchmark input: " + err.Error())
   697  	}
   698  }
   699  
   700  func BenchmarkUnmarshalText(b *testing.B) {
   701  	pb := new(MyMessage)
   702  	for i := 0; i < b.N; i++ {
   703  		UnmarshalText(benchInput, pb)
   704  	}
   705  	b.SetBytes(int64(len(benchInput)))
   706  }
   707  

View as plain text