blob: 4e3f4e98d89f949d1c7f8745a0617f7f48a866c8 [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 (
35 . "goprotobuf.googlecode.com/hg/proto"
36 . "./testdata/_obj/test_proto"
37 "reflect"
38 "testing"
39)
40
41type UnmarshalTextTest struct {
42 in string
43 error string // if "", no error expected
44 out *MyMessage
45}
46
47var unMarshalTextTests = []UnmarshalTextTest{
48 // Basic
David Symonds9f402812011-04-28 18:08:44 +100049 {
Rob Pikeaaa3a622010-03-20 22:32:34 -070050 in: " count:42\n name:\"Dave\" ",
51 out: &MyMessage{
52 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -070053 Name: String("Dave"),
Rob Pikeaaa3a622010-03-20 22:32:34 -070054 },
55 },
56
57 // Empty quoted string
David Symonds9f402812011-04-28 18:08:44 +100058 {
Rob Pikeaaa3a622010-03-20 22:32:34 -070059 in: `count:42 name:""`,
60 out: &MyMessage{
61 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -070062 Name: String(""),
Rob Pikeaaa3a622010-03-20 22:32:34 -070063 },
64 },
65
66 // Quoted string concatenation
David Symonds9f402812011-04-28 18:08:44 +100067 {
Rob Pikeaaa3a622010-03-20 22:32:34 -070068 in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`,
69 out: &MyMessage{
70 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -070071 Name: String("My name is elsewhere"),
Rob Pikeaaa3a622010-03-20 22:32:34 -070072 },
73 },
74
75 // Bad quoted string
David Symonds9f402812011-04-28 18:08:44 +100076 {
Rob Pike9caa5b92010-05-11 16:04:57 -070077 in: `inner: < host: "\0" >` + "\n",
Rob Pikeaaa3a622010-03-20 22:32:34 -070078 error: `line 1.15: invalid quoted string "\0"`,
79 },
80
81 // Number too large for int64
David Symonds9f402812011-04-28 18:08:44 +100082 {
Rob Pike9caa5b92010-05-11 16:04:57 -070083 in: "count: 123456789012345678901",
Rob Pikeaaa3a622010-03-20 22:32:34 -070084 error: "line 1.7: invalid int32: 123456789012345678901",
85 },
86
87 // Number too large for int32
David Symonds9f402812011-04-28 18:08:44 +100088 {
Rob Pike9caa5b92010-05-11 16:04:57 -070089 in: "count: 1234567890123",
Rob Pikeaaa3a622010-03-20 22:32:34 -070090 error: "line 1.7: invalid int32: 1234567890123",
91 },
92
93 // Number too large for float32
David Symonds9f402812011-04-28 18:08:44 +100094 {
Rob Pike9caa5b92010-05-11 16:04:57 -070095 in: "others:< weight: 12345678901234567890123456789012345678901234567890 >",
Rob Pikeaaa3a622010-03-20 22:32:34 -070096 error: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890",
97 },
98
99 // Number posing as a quoted string
David Symonds9f402812011-04-28 18:08:44 +1000100 {
Rob Pike9caa5b92010-05-11 16:04:57 -0700101 in: `inner: < host: 12 >` + "\n",
Rob Pikeaaa3a622010-03-20 22:32:34 -0700102 error: `line 1.15: invalid string: 12`,
103 },
104
105 // Quoted string posing as int32
David Symonds9f402812011-04-28 18:08:44 +1000106 {
Rob Pike9caa5b92010-05-11 16:04:57 -0700107 in: `count: "12"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700108 error: `line 1.7: invalid int32: "12"`,
109 },
110
111 // Quoted string posing a float32
David Symonds9f402812011-04-28 18:08:44 +1000112 {
Rob Pike9caa5b92010-05-11 16:04:57 -0700113 in: `others:< weight: "17.4" >`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700114 error: `line 1.17: invalid float32: "17.4"`,
115 },
116
117 // Enum
David Symonds9f402812011-04-28 18:08:44 +1000118 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700119 in: `count:42 bikeshed: BLUE`,
120 out: &MyMessage{
Rob Pike9caa5b92010-05-11 16:04:57 -0700121 Count: Int32(42),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700122 Bikeshed: NewMyMessage_Color(MyMessage_BLUE),
123 },
124 },
125
126 // Repeated field
David Symonds9f402812011-04-28 18:08:44 +1000127 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700128 in: `count:42 pet: "horsey" pet:"bunny"`,
129 out: &MyMessage{
130 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -0700131 Pet: []string{"horsey", "bunny"},
Rob Pikeaaa3a622010-03-20 22:32:34 -0700132 },
133 },
134
Rob Pikeaaf695a2010-06-22 15:51:21 -0700135 // Repeated message with/without colon and <>/{}
David Symonds9f402812011-04-28 18:08:44 +1000136 {
Rob Pikeaaf695a2010-06-22 15:51:21 -0700137 in: `count:42 others:{} others{} others:<> others:{}`,
138 out: &MyMessage{
139 Count: Int32(42),
140 Others: []*OtherMessage{
141 &OtherMessage{},
142 &OtherMessage{},
143 &OtherMessage{},
144 &OtherMessage{},
145 },
146 },
147 },
148
Rob Pikeaaa3a622010-03-20 22:32:34 -0700149 // Missing colon for inner message
David Symonds9f402812011-04-28 18:08:44 +1000150 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700151 in: `count:42 inner < host: "cauchy.syd" >`,
152 out: &MyMessage{
153 Count: Int32(42),
154 Inner: &InnerMessage{
155 Host: String("cauchy.syd"),
156 },
157 },
158 },
159
160 // Missing colon for string field
David Symonds9f402812011-04-28 18:08:44 +1000161 {
Rob Pike9caa5b92010-05-11 16:04:57 -0700162 in: `name "Dave"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700163 error: `line 1.5: expected ':', found "\"Dave\""`,
164 },
165
166 // Missing colon for int32 field
David Symonds9f402812011-04-28 18:08:44 +1000167 {
Rob Pike9caa5b92010-05-11 16:04:57 -0700168 in: `count 42`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700169 error: `line 1.6: expected ':', found "42"`,
170 },
171
172 // Missing required field
David Symonds9f402812011-04-28 18:08:44 +1000173 {
Rob Pike9caa5b92010-05-11 16:04:57 -0700174 in: ``,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700175 error: `line 1.0: message test_proto.MyMessage missing required field "count"`,
176 },
177
178 // Repeated non-repeated field
David Symonds9f402812011-04-28 18:08:44 +1000179 {
Rob Pike9caa5b92010-05-11 16:04:57 -0700180 in: `name: "Rob" name: "Russ"`,
Rob Pikeaaa3a622010-03-20 22:32:34 -0700181 error: `line 1.12: non-repeated field "name" was repeated`,
182 },
183
David Symonds9f402812011-04-28 18:08:44 +1000184 // Group
185 {
186 in: `count: 17 SomeGroup { group_field: 12 }`,
187 out: &MyMessage{
188 Count: Int32(17),
189 Somegroup: &MyMessage_SomeGroup{
190 GroupField: Int32(12),
191 },
192 },
193 },
194
Rob Pikeaaa3a622010-03-20 22:32:34 -0700195 // Big all-in-one
David Symonds9f402812011-04-28 18:08:44 +1000196 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700197 in: "count:42 # Meaning\n" +
198 `name:"Dave" ` +
199 `quote:"\"I didn't want to go.\"" ` +
200 `pet:"bunny" ` +
201 `pet:"kitty" ` +
202 `pet:"horsey" ` +
203 `inner:<` +
204 ` host:"footrest.syd" ` +
205 ` port:7001 ` +
206 ` connected:true ` +
207 `> ` +
208 `others:<` +
209 ` key:3735928559 ` +
210 ` value:"\x01A\a\f" ` +
211 `> ` +
212 `others:<` +
213 " weight:58.9 # Atomic weight of Co\n" +
214 ` inner:<` +
215 ` host:"lesha.mtv" ` +
216 ` port:8002 ` +
217 ` >` +
218 `>`,
219 out: &MyMessage{
220 Count: Int32(42),
Rob Pike9caa5b92010-05-11 16:04:57 -0700221 Name: String("Dave"),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700222 Quote: String(`"I didn't want to go."`),
Rob Pike9caa5b92010-05-11 16:04:57 -0700223 Pet: []string{"bunny", "kitty", "horsey"},
Rob Pikeaaa3a622010-03-20 22:32:34 -0700224 Inner: &InnerMessage{
Rob Pike9caa5b92010-05-11 16:04:57 -0700225 Host: String("footrest.syd"),
226 Port: Int32(7001),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700227 Connected: Bool(true),
228 },
229 Others: []*OtherMessage{
230 &OtherMessage{
Rob Pike9caa5b92010-05-11 16:04:57 -0700231 Key: Int64(3735928559),
Rob Pikeaaa3a622010-03-20 22:32:34 -0700232 Value: []byte{0x1, 'A', '\a', '\f'},
233 },
234 &OtherMessage{
235 Weight: Float32(58.9),
236 Inner: &InnerMessage{
237 Host: String("lesha.mtv"),
238 Port: Int32(8002),
239 },
240 },
241 },
242 },
243 },
244}
245
246func TestUnmarshalText(t *testing.T) {
247 for i, test := range unMarshalTextTests {
248 pb := new(MyMessage)
249 err := UnmarshalText(test.in, pb)
250 if test.error == "" {
251 // We don't expect failure.
252 if err != nil {
253 t.Errorf("Test %d: Unexpected error: %v", i, err)
254 } else if !reflect.DeepEqual(pb, test.out) {
255 t.Errorf("Test %d: Incorrect populated \n"+
256 "Have: %v\nWant: %v",
257 i, CompactTextString(pb), CompactTextString(test.out))
258 }
259 } else {
260 // We do expect failure.
261 if err == nil {
262 t.Errorf("Test %d: Didn't get expected error: %v", i, test.error)
263 } else if err.String() != test.error {
264 t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v",
265 i, err.String(), test.error)
266 }
267 }
268 }
269}
David Symonds79eae332010-10-16 11:33:20 +1100270
271var benchInput string
272
273func init() {
274 benchInput = "count: 4\n"
275 for i := 0; i < 1000; i++ {
276 benchInput += "pet: \"fido\"\n"
277 }
278
279 // Check it is valid input.
280 pb := new(MyMessage)
281 err := UnmarshalText(benchInput, pb)
282 if err != nil {
283 panic("Bad benchmark input: " + err.String())
284 }
285}
286
287func BenchmarkUnmarshalText(b *testing.B) {
288 pb := new(MyMessage)
289 for i := 0; i < b.N; i++ {
290 UnmarshalText(benchInput, pb)
291 }
292 b.SetBytes(int64(len(benchInput)))
293}