blob: d757ab393f571d60fa83f55f472028f9d103a59a [file] [log] [blame]
Rob Pikeaaa3a622010-03-20 22:32:34 -07001// Go support for Protocol Buffers - Google's data interchange format
2//
David Symondsee6e9c52012-11-29 08:51:07 +11003// Copyright 2010 The Go Authors. All rights reserved.
David Symonds558f13f2014-11-24 10:28:53 +11004// https://github.com/golang/protobuf
Rob Pikeaaa3a622010-03-20 22:32:34 -07005//
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
32package proto_test
33
34import (
David Symonds31faaca2012-12-06 15:51:11 +110035 "math"
Rob Pikeaaa3a622010-03-20 22:32:34 -070036 "reflect"
37 "testing"
David Symonds20c73662012-01-20 07:32:21 +110038
David Symonds558f13f2014-11-24 10:28:53 +110039 . "github.com/golang/protobuf/proto"
David Symondsa8de2842015-03-20 16:24:29 +110040 proto3pb "github.com/golang/protobuf/proto/proto3_proto"
41 . "github.com/golang/protobuf/proto/testdata"
Rob Pikeaaa3a622010-03-20 22:32:34 -070042)
43
44type UnmarshalTextTest struct {
David Symonds5ed980c2011-11-29 09:52:21 +110045 in string
46 err string // if "", no error expected
47 out *MyMessage
Rob Pikeaaa3a622010-03-20 22:32:34 -070048}
49
David Symonds54531052011-12-08 12:00:31 +110050func 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
60func 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
David Symonds61826da2012-05-05 09:31:28 +100069func 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
Rob Pikeaaa3a622010-03-20 22:32:34 -070079var unMarshalTextTests = []UnmarshalTextTest{
80 // Basic
David Symonds9f402812011-04-28 18:08:44 +100081 {
Rob Pikeaaa3a622010-03-20 22:32:34 -070082 in: " count:42\n name:\"Dave\" ",
83 out: &MyMessage{
84 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -070085 Name: String("Dave"),
Rob Pikeaaa3a622010-03-20 22:32:34 -070086 },
87 },
88
89 // Empty quoted string
David Symonds9f402812011-04-28 18:08:44 +100090 {
Rob Pikeaaa3a622010-03-20 22:32:34 -070091 in: `count:42 name:""`,
92 out: &MyMessage{
93 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -070094 Name: String(""),
Rob Pikeaaa3a622010-03-20 22:32:34 -070095 },
96 },
97
Daniel Kraftb9827042016-02-02 18:33:00 +110098 // Quoted string concatenation with double quotes
David Symonds9f402812011-04-28 18:08:44 +100099 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700100 in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`,
101 out: &MyMessage{
102 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -0700103 Name: String("My name is elsewhere"),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700104 },
105 },
106
Daniel Kraftb9827042016-02-02 18:33:00 +1100107 // 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
David Symonds183124e2012-03-23 13:20:23 +1100132 // 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
David Symonds162d0032012-06-28 09:44:46 -0700141 // 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
David Symondsfa94a1e2012-09-24 13:21:49 +1000150 // 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\xAB'",
171 out: &MyMessage{
172 Count: Int32(42),
173 Name: String("\303\277\302\201\xAB"),
174 },
175 },
176
Rob Pikeaaa3a622010-03-20 22:32:34 -0700177 // Bad quoted string
David Symonds9f402812011-04-28 18:08:44 +1000178 {
David Symonds5ed980c2011-11-29 09:52:21 +1100179 in: `inner: < host: "\0" >` + "\n",
David Symondsbafa7bc2015-07-01 07:59:00 +1000180 err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700181 },
182
183 // Number too large for int64
David Symonds9f402812011-04-28 18:08:44 +1000184 {
David Symonds8bb628d2014-07-22 13:49:35 +1000185 in: "count: 1 others { key: 123456789012345678901 }",
186 err: "line 1.23: invalid int64: 123456789012345678901",
Rob Pikeaaa3a622010-03-20 22:32:34 -0700187 },
188
189 // Number too large for int32
David Symonds9f402812011-04-28 18:08:44 +1000190 {
David Symonds5ed980c2011-11-29 09:52:21 +1100191 in: "count: 1234567890123",
192 err: "line 1.7: invalid int32: 1234567890123",
Rob Pikeaaa3a622010-03-20 22:32:34 -0700193 },
194
David Symonds32612dd2012-06-15 07:59:05 -0700195 // Number in hexadecimal
196 {
197 in: "count: 0x2beef",
198 out: &MyMessage{
199 Count: Int32(0x2beef),
200 },
201 },
202
203 // Number in octal
204 {
205 in: "count: 024601",
206 out: &MyMessage{
207 Count: Int32(024601),
208 },
209 },
210
David Symonds6bd081e2012-06-28 10:46:25 -0700211 // Floating point number with "f" suffix
212 {
213 in: "count: 4 others:< weight: 17.0f >",
214 out: &MyMessage{
215 Count: Int32(4),
216 Others: []*OtherMessage{
217 {
218 Weight: Float32(17),
219 },
220 },
221 },
222 },
223
David Symonds31faaca2012-12-06 15:51:11 +1100224 // Floating point positive infinity
225 {
226 in: "count: 4 bigfloat: inf",
227 out: &MyMessage{
228 Count: Int32(4),
229 Bigfloat: Float64(math.Inf(1)),
230 },
231 },
232
233 // Floating point negative infinity
234 {
235 in: "count: 4 bigfloat: -inf",
236 out: &MyMessage{
237 Count: Int32(4),
238 Bigfloat: Float64(math.Inf(-1)),
239 },
240 },
241
Rob Pikeaaa3a622010-03-20 22:32:34 -0700242 // Number too large for float32
David Symonds9f402812011-04-28 18:08:44 +1000243 {
David Symonds5ed980c2011-11-29 09:52:21 +1100244 in: "others:< weight: 12345678901234567890123456789012345678901234567890 >",
245 err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890",
Rob Pikeaaa3a622010-03-20 22:32:34 -0700246 },
247
248 // Number posing as a quoted string
David Symonds9f402812011-04-28 18:08:44 +1000249 {
David Symonds5ed980c2011-11-29 09:52:21 +1100250 in: `inner: < host: 12 >` + "\n",
251 err: `line 1.15: invalid string: 12`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700252 },
253
254 // Quoted string posing as int32
David Symonds9f402812011-04-28 18:08:44 +1000255 {
David Symonds5ed980c2011-11-29 09:52:21 +1100256 in: `count: "12"`,
257 err: `line 1.7: invalid int32: "12"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700258 },
259
260 // Quoted string posing a float32
David Symonds9f402812011-04-28 18:08:44 +1000261 {
David Symonds5ed980c2011-11-29 09:52:21 +1100262 in: `others:< weight: "17.4" >`,
263 err: `line 1.17: invalid float32: "17.4"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700264 },
265
266 // Enum
David Symonds9f402812011-04-28 18:08:44 +1000267 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700268 in: `count:42 bikeshed: BLUE`,
269 out: &MyMessage{
Rob Pike9caa5b92010-05-11 16:04:57 -0700270 Count: Int32(42),
David Symondsefeca9a2012-05-08 10:36:04 +1000271 Bikeshed: MyMessage_BLUE.Enum(),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700272 },
273 },
274
275 // Repeated field
David Symonds9f402812011-04-28 18:08:44 +1000276 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700277 in: `count:42 pet: "horsey" pet:"bunny"`,
278 out: &MyMessage{
279 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -0700280 Pet: []string{"horsey", "bunny"},
Rob Pikeaaa3a622010-03-20 22:32:34 -0700281 },
282 },
283
Lorenzo Simionatodeb4a5e2015-10-09 07:39:00 +1100284 // Repeated field with list notation
285 {
286 in: `count:42 pet: ["horsey", "bunny"]`,
287 out: &MyMessage{
288 Count: Int32(42),
289 Pet: []string{"horsey", "bunny"},
290 },
291 },
292
Rob Pikeaaf695a2010-06-22 15:51:21 -0700293 // Repeated message with/without colon and <>/{}
David Symonds9f402812011-04-28 18:08:44 +1000294 {
Rob Pikeaaf695a2010-06-22 15:51:21 -0700295 in: `count:42 others:{} others{} others:<> others:{}`,
296 out: &MyMessage{
297 Count: Int32(42),
298 Others: []*OtherMessage{
Albert Strasheim4676f6a2013-04-07 08:59:06 +1000299 {},
300 {},
301 {},
302 {},
Rob Pikeaaf695a2010-06-22 15:51:21 -0700303 },
304 },
305 },
306
Rob Pikeaaa3a622010-03-20 22:32:34 -0700307 // Missing colon for inner message
David Symonds9f402812011-04-28 18:08:44 +1000308 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700309 in: `count:42 inner < host: "cauchy.syd" >`,
310 out: &MyMessage{
311 Count: Int32(42),
312 Inner: &InnerMessage{
313 Host: String("cauchy.syd"),
314 },
315 },
316 },
317
318 // Missing colon for string field
David Symonds9f402812011-04-28 18:08:44 +1000319 {
David Symonds5ed980c2011-11-29 09:52:21 +1100320 in: `name "Dave"`,
321 err: `line 1.5: expected ':', found "\"Dave\""`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700322 },
323
324 // Missing colon for int32 field
David Symonds9f402812011-04-28 18:08:44 +1000325 {
David Symonds5ed980c2011-11-29 09:52:21 +1100326 in: `count 42`,
327 err: `line 1.6: expected ':', found "42"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700328 },
329
330 // Missing required field
David Symonds9f402812011-04-28 18:08:44 +1000331 {
David Symonds2a1c6b92014-10-12 16:42:41 +1100332 in: `name: "Pawel"`,
333 err: `proto: required field "testdata.MyMessage.count" not set`,
334 out: &MyMessage{
335 Name: String("Pawel"),
336 },
Rob Pikeaaa3a622010-03-20 22:32:34 -0700337 },
338
Bryan Mills78550bb2016-04-01 08:55:00 +1100339 // Missing required field in a required submessage
340 {
341 in: `count: 42 we_must_go_deeper < leo_finally_won_an_oscar <> >`,
342 err: `proto: required field "testdata.InnerMessage.host" not set`,
343 out: &MyMessage{
344 Count: Int32(42),
345 WeMustGoDeeper: &RequiredInnerMessage{LeoFinallyWonAnOscar: &InnerMessage{}},
346 },
347 },
348
Rob Pikeaaa3a622010-03-20 22:32:34 -0700349 // Repeated non-repeated field
David Symonds9f402812011-04-28 18:08:44 +1000350 {
David Symonds5ed980c2011-11-29 09:52:21 +1100351 in: `name: "Rob" name: "Russ"`,
352 err: `line 1.12: non-repeated field "name" was repeated`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700353 },
354
David Symonds9f402812011-04-28 18:08:44 +1000355 // Group
356 {
357 in: `count: 17 SomeGroup { group_field: 12 }`,
358 out: &MyMessage{
359 Count: Int32(17),
360 Somegroup: &MyMessage_SomeGroup{
361 GroupField: Int32(12),
362 },
363 },
364 },
365
David Symonds31faaca2012-12-06 15:51:11 +1100366 // Semicolon between fields
367 {
368 in: `count:3;name:"Calvin"`,
369 out: &MyMessage{
370 Count: Int32(3),
371 Name: String("Calvin"),
372 },
373 },
374 // Comma between fields
375 {
376 in: `count:4,name:"Ezekiel"`,
377 out: &MyMessage{
378 Count: Int32(4),
379 Name: String("Ezekiel"),
380 },
381 },
382
light1f49d832016-08-24 20:12:15 +0000383 // Boolean false
384 {
385 in: `count:42 inner { host: "example.com" connected: false }`,
386 out: &MyMessage{
387 Count: Int32(42),
388 Inner: &InnerMessage{
389 Host: String("example.com"),
390 Connected: Bool(false),
391 },
392 },
393 },
394 // Boolean true
395 {
396 in: `count:42 inner { host: "example.com" connected: true }`,
397 out: &MyMessage{
398 Count: Int32(42),
399 Inner: &InnerMessage{
400 Host: String("example.com"),
401 Connected: Bool(true),
402 },
403 },
404 },
405 // Boolean 0
406 {
407 in: `count:42 inner { host: "example.com" connected: 0 }`,
408 out: &MyMessage{
409 Count: Int32(42),
410 Inner: &InnerMessage{
411 Host: String("example.com"),
412 Connected: Bool(false),
413 },
414 },
415 },
416 // Boolean 1
417 {
418 in: `count:42 inner { host: "example.com" connected: 1 }`,
419 out: &MyMessage{
420 Count: Int32(42),
421 Inner: &InnerMessage{
422 Host: String("example.com"),
423 Connected: Bool(true),
424 },
425 },
426 },
427 // Boolean f
428 {
429 in: `count:42 inner { host: "example.com" connected: f }`,
430 out: &MyMessage{
431 Count: Int32(42),
432 Inner: &InnerMessage{
433 Host: String("example.com"),
434 Connected: Bool(false),
435 },
436 },
437 },
438 // Boolean t
439 {
440 in: `count:42 inner { host: "example.com" connected: t }`,
441 out: &MyMessage{
442 Count: Int32(42),
443 Inner: &InnerMessage{
444 Host: String("example.com"),
445 Connected: Bool(true),
446 },
447 },
448 },
449 // Boolean False
450 {
451 in: `count:42 inner { host: "example.com" connected: False }`,
452 out: &MyMessage{
453 Count: Int32(42),
454 Inner: &InnerMessage{
455 Host: String("example.com"),
456 Connected: Bool(false),
457 },
458 },
459 },
460 // Boolean True
461 {
462 in: `count:42 inner { host: "example.com" connected: True }`,
463 out: &MyMessage{
464 Count: Int32(42),
465 Inner: &InnerMessage{
466 Host: String("example.com"),
467 Connected: Bool(true),
468 },
469 },
470 },
471
David Symonds54531052011-12-08 12:00:31 +1100472 // Extension
Rob Pikeb7907bf2012-02-13 14:25:20 +1100473 buildExtStructTest(`count: 42 [testdata.Ext.more]:<data:"Hello, world!" >`),
474 buildExtStructTest(`count: 42 [testdata.Ext.more] {data:"Hello, world!"}`),
475 buildExtDataTest(`count: 42 [testdata.Ext.text]:"Hello, world!" [testdata.Ext.number]:1729`),
David Symonds61826da2012-05-05 09:31:28 +1000476 buildExtRepStringTest(`count: 42 [testdata.greeting]:"bula" [testdata.greeting]:"hola"`),
David Symonds54531052011-12-08 12:00:31 +1100477
Rob Pikeaaa3a622010-03-20 22:32:34 -0700478 // Big all-in-one
David Symonds9f402812011-04-28 18:08:44 +1000479 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700480 in: "count:42 # Meaning\n" +
481 `name:"Dave" ` +
482 `quote:"\"I didn't want to go.\"" ` +
483 `pet:"bunny" ` +
484 `pet:"kitty" ` +
485 `pet:"horsey" ` +
486 `inner:<` +
487 ` host:"footrest.syd" ` +
488 ` port:7001 ` +
489 ` connected:true ` +
490 `> ` +
491 `others:<` +
492 ` key:3735928559 ` +
493 ` value:"\x01A\a\f" ` +
494 `> ` +
495 `others:<` +
496 " weight:58.9 # Atomic weight of Co\n" +
497 ` inner:<` +
498 ` host:"lesha.mtv" ` +
499 ` port:8002 ` +
500 ` >` +
501 `>`,
502 out: &MyMessage{
503 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -0700504 Name: String("Dave"),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700505 Quote: String(`"I didn't want to go."`),
Rob Pike9caa5b92010-05-11 16:04:57 -0700506 Pet: []string{"bunny", "kitty", "horsey"},
Rob Pikeaaa3a622010-03-20 22:32:34 -0700507 Inner: &InnerMessage{
Rob Pike9caa5b92010-05-11 16:04:57 -0700508 Host: String("footrest.syd"),
509 Port: Int32(7001),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700510 Connected: Bool(true),
511 },
512 Others: []*OtherMessage{
Albert Strasheim4676f6a2013-04-07 08:59:06 +1000513 {
Rob Pike9caa5b92010-05-11 16:04:57 -0700514 Key: Int64(3735928559),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700515 Value: []byte{0x1, 'A', '\a', '\f'},
516 },
Albert Strasheim4676f6a2013-04-07 08:59:06 +1000517 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700518 Weight: Float32(58.9),
519 Inner: &InnerMessage{
520 Host: String("lesha.mtv"),
521 Port: Int32(8002),
522 },
523 },
524 },
525 },
526 },
527}
528
529func TestUnmarshalText(t *testing.T) {
530 for i, test := range unMarshalTextTests {
531 pb := new(MyMessage)
532 err := UnmarshalText(test.in, pb)
David Symonds5ed980c2011-11-29 09:52:21 +1100533 if test.err == "" {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700534 // We don't expect failure.
535 if err != nil {
536 t.Errorf("Test %d: Unexpected error: %v", i, err)
537 } else if !reflect.DeepEqual(pb, test.out) {
David Symondsef8f0e82011-10-13 12:57:34 +1100538 t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v",
539 i, pb, test.out)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700540 }
541 } else {
542 // We do expect failure.
543 if err == nil {
David Symonds5ed980c2011-11-29 09:52:21 +1100544 t.Errorf("Test %d: Didn't get expected error: %v", i, test.err)
545 } else if err.Error() != test.err {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700546 t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v",
David Symonds5ed980c2011-11-29 09:52:21 +1100547 i, err.Error(), test.err)
David Symonds2a1c6b92014-10-12 16:42:41 +1100548 } else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !reflect.DeepEqual(pb, test.out) {
549 t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v",
550 i, pb, test.out)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700551 }
552 }
553 }
554}
David Symonds79eae332010-10-16 11:33:20 +1100555
David Symonds267e8052014-02-19 14:50:51 +1100556func TestUnmarshalTextCustomMessage(t *testing.T) {
557 msg := &textMessage{}
558 if err := UnmarshalText("custom", msg); err != nil {
559 t.Errorf("Unexpected error from custom unmarshal: %v", err)
560 }
561 if UnmarshalText("not custom", msg) == nil {
562 t.Errorf("Didn't get expected error from custom unmarshal")
563 }
564}
565
David Symondsef8f0e82011-10-13 12:57:34 +1100566// Regression test; this caused a panic.
567func TestRepeatedEnum(t *testing.T) {
568 pb := new(RepeatedEnum)
569 if err := UnmarshalText("color: RED", pb); err != nil {
570 t.Fatal(err)
571 }
572 exp := &RepeatedEnum{
573 Color: []RepeatedEnum_Color{RepeatedEnum_RED},
574 }
David Symonds007ed9d2012-07-24 10:59:36 +1000575 if !Equal(pb, exp) {
David Symondsef8f0e82011-10-13 12:57:34 +1100576 t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp)
577 }
578}
579
David Symondsabd3b412014-11-28 11:43:44 +1100580func TestProto3TextParsing(t *testing.T) {
581 m := new(proto3pb.Message)
582 const in = `name: "Wallace" true_scotsman: true`
583 want := &proto3pb.Message{
584 Name: "Wallace",
585 TrueScotsman: true,
586 }
587 if err := UnmarshalText(in, m); err != nil {
588 t.Fatal(err)
589 }
590 if !Equal(m, want) {
591 t.Errorf("\n got %v\nwant %v", m, want)
592 }
593}
594
David Symonds3ea3e052014-12-22 16:15:28 +1100595func TestMapParsing(t *testing.T) {
596 m := new(MessageWithMap)
597 const in = `name_mapping:<key:1234 value:"Feist"> name_mapping:<key:1 value:"Beatles">` +
David Symonds056d5ce2015-05-12 19:27:00 +1000598 `msg_mapping:<key:-4, value:<f: 2.0>,>` + // separating commas are okay
David Symondsa11b6342015-01-28 17:07:47 +1100599 `msg_mapping<key:-2 value<f: 4.0>>` + // no colon after "value"
Ross Light11114612016-05-25 19:11:34 -0400600 `msg_mapping:<value:<f: 5.0>>` + // omitted key
601 `msg_mapping:<key:1>` + // omitted value
602 `byte_mapping:<key:true value:"so be it">` +
603 `byte_mapping:<>` // omitted key and value
David Symonds3ea3e052014-12-22 16:15:28 +1100604 want := &MessageWithMap{
605 NameMapping: map[int32]string{
606 1: "Beatles",
607 1234: "Feist",
608 },
609 MsgMapping: map[int64]*FloatingPoint{
610 -4: {F: Float64(2.0)},
David Symondsa11b6342015-01-28 17:07:47 +1100611 -2: {F: Float64(4.0)},
Ross Light11114612016-05-25 19:11:34 -0400612 0: {F: Float64(5.0)},
613 1: nil,
David Symonds3ea3e052014-12-22 16:15:28 +1100614 },
615 ByteMapping: map[bool][]byte{
Ross Light11114612016-05-25 19:11:34 -0400616 false: nil,
617 true: []byte("so be it"),
David Symonds3ea3e052014-12-22 16:15:28 +1100618 },
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
David Symonds59b73b32015-08-24 13:22:02 +1000628func TestOneofParsing(t *testing.T) {
629 const in = `name:"Shrek"`
630 m := new(Communique)
631 want := &Communique{Union: &Communique_Name{"Shrek"}}
632 if err := UnmarshalText(in, m); err != nil {
633 t.Fatal(err)
634 }
635 if !Equal(m, want) {
636 t.Errorf("\n got %v\nwant %v", m, want)
637 }
Googlera66a4fa2016-11-01 19:59:13 +0000638
639 const inOverwrite = `name:"Shrek" number:42`
640 m = new(Communique)
641 testErr := "line 1.13: oneof field 'number' is already set"
642 if err := UnmarshalText(inOverwrite, m); err == nil {
643 t.Errorf("TestOneofParsing: Didn't get expected error: %v", testErr)
644 } else if err.Error() != testErr {
645 t.Errorf("TestOneofParsing: Incorrect error.\nHave: %v\nWant: %v",
646 err.Error(), testErr)
647 }
648
David Symonds59b73b32015-08-24 13:22:02 +1000649}
650
David Symonds79eae332010-10-16 11:33:20 +1100651var benchInput string
652
653func init() {
654 benchInput = "count: 4\n"
655 for i := 0; i < 1000; i++ {
656 benchInput += "pet: \"fido\"\n"
657 }
658
659 // Check it is valid input.
660 pb := new(MyMessage)
661 err := UnmarshalText(benchInput, pb)
662 if err != nil {
Rob Pikea17fdd92011-11-02 12:43:05 -0700663 panic("Bad benchmark input: " + err.Error())
David Symonds79eae332010-10-16 11:33:20 +1100664 }
665}
666
667func BenchmarkUnmarshalText(b *testing.B) {
668 pb := new(MyMessage)
669 for i := 0; i < b.N; i++ {
670 UnmarshalText(benchInput, pb)
671 }
672 b.SetBytes(int64(len(benchInput)))
673}