blob: cb730255cefb47fd8f72578a07237549256d9224 [file] [log] [blame]
Rob Pikeaaa3a622010-03-20 22:32:34 -07001// Go support for Protocol Buffers - Google's data interchange format
2//
3// Copyright 2010 Google Inc. All rights reserved.
4// http://code.google.com/p/goprotobuf/
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
32package proto_test
33
34import (
Rob Pikeaaa3a622010-03-20 22:32:34 -070035 . "./testdata/_obj/test_proto"
Rob Pike3f6f2d82011-12-18 13:55:35 -080036 . "code.google.com/p/goprotobuf/proto"
Rob Pikeaaa3a622010-03-20 22:32:34 -070037 "reflect"
38 "testing"
39)
40
41type UnmarshalTextTest struct {
David Symonds5ed980c2011-11-29 09:52:21 +110042 in string
43 err string // if "", no error expected
44 out *MyMessage
Rob Pikeaaa3a622010-03-20 22:32:34 -070045}
46
David Symonds54531052011-12-08 12:00:31 +110047func buildExtStructTest(text string) UnmarshalTextTest {
48 msg := &MyMessage{
49 Count: Int32(42),
50 }
51 SetExtension(msg, E_Ext_More, &Ext{
52 Data: String("Hello, world!"),
53 })
54 return UnmarshalTextTest{in: text, out: msg}
55}
56
57func buildExtDataTest(text string) UnmarshalTextTest {
58 msg := &MyMessage{
59 Count: Int32(42),
60 }
61 SetExtension(msg, E_Ext_Text, String("Hello, world!"))
62 SetExtension(msg, E_Ext_Number, Int32(1729))
63 return UnmarshalTextTest{in: text, out: msg}
64}
65
Rob Pikeaaa3a622010-03-20 22:32:34 -070066var unMarshalTextTests = []UnmarshalTextTest{
67 // Basic
David Symonds9f402812011-04-28 18:08:44 +100068 {
Rob Pikeaaa3a622010-03-20 22:32:34 -070069 in: " count:42\n name:\"Dave\" ",
70 out: &MyMessage{
71 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -070072 Name: String("Dave"),
Rob Pikeaaa3a622010-03-20 22:32:34 -070073 },
74 },
75
76 // Empty quoted string
David Symonds9f402812011-04-28 18:08:44 +100077 {
Rob Pikeaaa3a622010-03-20 22:32:34 -070078 in: `count:42 name:""`,
79 out: &MyMessage{
80 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -070081 Name: String(""),
Rob Pikeaaa3a622010-03-20 22:32:34 -070082 },
83 },
84
85 // Quoted string concatenation
David Symonds9f402812011-04-28 18:08:44 +100086 {
Rob Pikeaaa3a622010-03-20 22:32:34 -070087 in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`,
88 out: &MyMessage{
89 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -070090 Name: String("My name is elsewhere"),
Rob Pikeaaa3a622010-03-20 22:32:34 -070091 },
92 },
93
94 // Bad quoted string
David Symonds9f402812011-04-28 18:08:44 +100095 {
David Symonds5ed980c2011-11-29 09:52:21 +110096 in: `inner: < host: "\0" >` + "\n",
97 err: `line 1.15: invalid quoted string "\0"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -070098 },
99
100 // Number too large for int64
David Symonds9f402812011-04-28 18:08:44 +1000101 {
David Symonds5ed980c2011-11-29 09:52:21 +1100102 in: "count: 123456789012345678901",
103 err: "line 1.7: invalid int32: 123456789012345678901",
Rob Pikeaaa3a622010-03-20 22:32:34 -0700104 },
105
106 // Number too large for int32
David Symonds9f402812011-04-28 18:08:44 +1000107 {
David Symonds5ed980c2011-11-29 09:52:21 +1100108 in: "count: 1234567890123",
109 err: "line 1.7: invalid int32: 1234567890123",
Rob Pikeaaa3a622010-03-20 22:32:34 -0700110 },
111
112 // Number too large for float32
David Symonds9f402812011-04-28 18:08:44 +1000113 {
David Symonds5ed980c2011-11-29 09:52:21 +1100114 in: "others:< weight: 12345678901234567890123456789012345678901234567890 >",
115 err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890",
Rob Pikeaaa3a622010-03-20 22:32:34 -0700116 },
117
118 // Number posing as a quoted string
David Symonds9f402812011-04-28 18:08:44 +1000119 {
David Symonds5ed980c2011-11-29 09:52:21 +1100120 in: `inner: < host: 12 >` + "\n",
121 err: `line 1.15: invalid string: 12`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700122 },
123
124 // Quoted string posing as int32
David Symonds9f402812011-04-28 18:08:44 +1000125 {
David Symonds5ed980c2011-11-29 09:52:21 +1100126 in: `count: "12"`,
127 err: `line 1.7: invalid int32: "12"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700128 },
129
130 // Quoted string posing a float32
David Symonds9f402812011-04-28 18:08:44 +1000131 {
David Symonds5ed980c2011-11-29 09:52:21 +1100132 in: `others:< weight: "17.4" >`,
133 err: `line 1.17: invalid float32: "17.4"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700134 },
135
136 // Enum
David Symonds9f402812011-04-28 18:08:44 +1000137 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700138 in: `count:42 bikeshed: BLUE`,
139 out: &MyMessage{
Rob Pike9caa5b92010-05-11 16:04:57 -0700140 Count: Int32(42),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700141 Bikeshed: NewMyMessage_Color(MyMessage_BLUE),
142 },
143 },
144
145 // Repeated field
David Symonds9f402812011-04-28 18:08:44 +1000146 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700147 in: `count:42 pet: "horsey" pet:"bunny"`,
148 out: &MyMessage{
149 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -0700150 Pet: []string{"horsey", "bunny"},
Rob Pikeaaa3a622010-03-20 22:32:34 -0700151 },
152 },
153
Rob Pikeaaf695a2010-06-22 15:51:21 -0700154 // Repeated message with/without colon and <>/{}
David Symonds9f402812011-04-28 18:08:44 +1000155 {
Rob Pikeaaf695a2010-06-22 15:51:21 -0700156 in: `count:42 others:{} others{} others:<> others:{}`,
157 out: &MyMessage{
158 Count: Int32(42),
159 Others: []*OtherMessage{
160 &OtherMessage{},
161 &OtherMessage{},
162 &OtherMessage{},
163 &OtherMessage{},
164 },
165 },
166 },
167
Rob Pikeaaa3a622010-03-20 22:32:34 -0700168 // Missing colon for inner message
David Symonds9f402812011-04-28 18:08:44 +1000169 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700170 in: `count:42 inner < host: "cauchy.syd" >`,
171 out: &MyMessage{
172 Count: Int32(42),
173 Inner: &InnerMessage{
174 Host: String("cauchy.syd"),
175 },
176 },
177 },
178
179 // Missing colon for string field
David Symonds9f402812011-04-28 18:08:44 +1000180 {
David Symonds5ed980c2011-11-29 09:52:21 +1100181 in: `name "Dave"`,
182 err: `line 1.5: expected ':', found "\"Dave\""`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700183 },
184
185 // Missing colon for int32 field
David Symonds9f402812011-04-28 18:08:44 +1000186 {
David Symonds5ed980c2011-11-29 09:52:21 +1100187 in: `count 42`,
188 err: `line 1.6: expected ':', found "42"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700189 },
190
191 // Missing required field
David Symonds9f402812011-04-28 18:08:44 +1000192 {
David Symonds5ed980c2011-11-29 09:52:21 +1100193 in: ``,
194 err: `line 1.0: message test_proto.MyMessage missing required field "count"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700195 },
196
197 // Repeated non-repeated field
David Symonds9f402812011-04-28 18:08:44 +1000198 {
David Symonds5ed980c2011-11-29 09:52:21 +1100199 in: `name: "Rob" name: "Russ"`,
200 err: `line 1.12: non-repeated field "name" was repeated`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700201 },
202
David Symonds9f402812011-04-28 18:08:44 +1000203 // Group
204 {
205 in: `count: 17 SomeGroup { group_field: 12 }`,
206 out: &MyMessage{
207 Count: Int32(17),
208 Somegroup: &MyMessage_SomeGroup{
209 GroupField: Int32(12),
210 },
211 },
212 },
213
David Symonds54531052011-12-08 12:00:31 +1100214 // Extension
215 buildExtStructTest(`count: 42 [test_proto.Ext.more]:<data:"Hello, world!" >`),
216 buildExtStructTest(`count: 42 [test_proto.Ext.more] {data:"Hello, world!"}`),
217 buildExtDataTest(`count: 42 [test_proto.Ext.text]:"Hello, world!" [test_proto.Ext.number]:1729`),
218
Rob Pikeaaa3a622010-03-20 22:32:34 -0700219 // Big all-in-one
David Symonds9f402812011-04-28 18:08:44 +1000220 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700221 in: "count:42 # Meaning\n" +
222 `name:"Dave" ` +
223 `quote:"\"I didn't want to go.\"" ` +
224 `pet:"bunny" ` +
225 `pet:"kitty" ` +
226 `pet:"horsey" ` +
227 `inner:<` +
228 ` host:"footrest.syd" ` +
229 ` port:7001 ` +
230 ` connected:true ` +
231 `> ` +
232 `others:<` +
233 ` key:3735928559 ` +
234 ` value:"\x01A\a\f" ` +
235 `> ` +
236 `others:<` +
237 " weight:58.9 # Atomic weight of Co\n" +
238 ` inner:<` +
239 ` host:"lesha.mtv" ` +
240 ` port:8002 ` +
241 ` >` +
242 `>`,
243 out: &MyMessage{
244 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -0700245 Name: String("Dave"),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700246 Quote: String(`"I didn't want to go."`),
Rob Pike9caa5b92010-05-11 16:04:57 -0700247 Pet: []string{"bunny", "kitty", "horsey"},
Rob Pikeaaa3a622010-03-20 22:32:34 -0700248 Inner: &InnerMessage{
Rob Pike9caa5b92010-05-11 16:04:57 -0700249 Host: String("footrest.syd"),
250 Port: Int32(7001),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700251 Connected: Bool(true),
252 },
253 Others: []*OtherMessage{
254 &OtherMessage{
Rob Pike9caa5b92010-05-11 16:04:57 -0700255 Key: Int64(3735928559),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700256 Value: []byte{0x1, 'A', '\a', '\f'},
257 },
258 &OtherMessage{
259 Weight: Float32(58.9),
260 Inner: &InnerMessage{
261 Host: String("lesha.mtv"),
262 Port: Int32(8002),
263 },
264 },
265 },
266 },
267 },
268}
269
270func TestUnmarshalText(t *testing.T) {
271 for i, test := range unMarshalTextTests {
272 pb := new(MyMessage)
273 err := UnmarshalText(test.in, pb)
David Symonds5ed980c2011-11-29 09:52:21 +1100274 if test.err == "" {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700275 // We don't expect failure.
276 if err != nil {
277 t.Errorf("Test %d: Unexpected error: %v", i, err)
278 } else if !reflect.DeepEqual(pb, test.out) {
David Symondsef8f0e82011-10-13 12:57:34 +1100279 t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v",
280 i, pb, test.out)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700281 }
282 } else {
283 // We do expect failure.
284 if err == nil {
David Symonds5ed980c2011-11-29 09:52:21 +1100285 t.Errorf("Test %d: Didn't get expected error: %v", i, test.err)
286 } else if err.Error() != test.err {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700287 t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v",
David Symonds5ed980c2011-11-29 09:52:21 +1100288 i, err.Error(), test.err)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700289 }
290 }
291 }
292}
David Symonds79eae332010-10-16 11:33:20 +1100293
David Symondsef8f0e82011-10-13 12:57:34 +1100294// Regression test; this caused a panic.
295func TestRepeatedEnum(t *testing.T) {
296 pb := new(RepeatedEnum)
297 if err := UnmarshalText("color: RED", pb); err != nil {
298 t.Fatal(err)
299 }
300 exp := &RepeatedEnum{
301 Color: []RepeatedEnum_Color{RepeatedEnum_RED},
302 }
303 if !reflect.DeepEqual(pb, exp) {
304 t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp)
305 }
306}
307
David Symonds79eae332010-10-16 11:33:20 +1100308var benchInput string
309
310func init() {
311 benchInput = "count: 4\n"
312 for i := 0; i < 1000; i++ {
313 benchInput += "pet: \"fido\"\n"
314 }
315
316 // Check it is valid input.
317 pb := new(MyMessage)
318 err := UnmarshalText(benchInput, pb)
319 if err != nil {
Rob Pikea17fdd92011-11-02 12:43:05 -0700320 panic("Bad benchmark input: " + err.Error())
David Symonds79eae332010-10-16 11:33:20 +1100321 }
322}
323
324func BenchmarkUnmarshalText(b *testing.B) {
325 pb := new(MyMessage)
326 for i := 0; i < b.N; i++ {
327 UnmarshalText(benchInput, pb)
328 }
329 b.SetBytes(int64(len(benchInput)))
330}