initialise
[debian/goprotobuf.git] / proto / text_parser_test.go
1 // 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
32 package proto_test
33
34 import (
35         . "goprotobuf.googlecode.com/hg/proto"
36         . "./testdata/_obj/test_proto"
37         "reflect"
38         "testing"
39 )
40
41 type UnmarshalTextTest struct {
42         in    string
43         error string // if "", no error expected
44         out   *MyMessage
45 }
46
47 var unMarshalTextTests = []UnmarshalTextTest{
48         // Basic
49         {
50                 in: " count:42\n  name:\"Dave\" ",
51                 out: &MyMessage{
52                         Count: Int32(42),
53                         Name:  String("Dave"),
54                 },
55         },
56
57         // Empty quoted string
58         {
59                 in: `count:42 name:""`,
60                 out: &MyMessage{
61                         Count: Int32(42),
62                         Name:  String(""),
63                 },
64         },
65
66         // Quoted string concatenation
67         {
68                 in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`,
69                 out: &MyMessage{
70                         Count: Int32(42),
71                         Name:  String("My name is elsewhere"),
72                 },
73         },
74
75         // Bad quoted string
76         {
77                 in:    `inner: < host: "\0" >` + "\n",
78                 error: `line 1.15: invalid quoted string "\0"`,
79         },
80
81         // Number too large for int64
82         {
83                 in:    "count: 123456789012345678901",
84                 error: "line 1.7: invalid int32: 123456789012345678901",
85         },
86
87         // Number too large for int32
88         {
89                 in:    "count: 1234567890123",
90                 error: "line 1.7: invalid int32: 1234567890123",
91         },
92
93         // Number too large for float32
94         {
95                 in:    "others:< weight: 12345678901234567890123456789012345678901234567890 >",
96                 error: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890",
97         },
98
99         // Number posing as a quoted string
100         {
101                 in:    `inner: < host: 12 >` + "\n",
102                 error: `line 1.15: invalid string: 12`,
103         },
104
105         // Quoted string posing as int32
106         {
107                 in:    `count: "12"`,
108                 error: `line 1.7: invalid int32: "12"`,
109         },
110
111         // Quoted string posing a float32
112         {
113                 in:    `others:< weight: "17.4" >`,
114                 error: `line 1.17: invalid float32: "17.4"`,
115         },
116
117         // Enum
118         {
119                 in: `count:42 bikeshed: BLUE`,
120                 out: &MyMessage{
121                         Count:    Int32(42),
122                         Bikeshed: NewMyMessage_Color(MyMessage_BLUE),
123                 },
124         },
125
126         // Repeated field
127         {
128                 in: `count:42 pet: "horsey" pet:"bunny"`,
129                 out: &MyMessage{
130                         Count: Int32(42),
131                         Pet:   []string{"horsey", "bunny"},
132                 },
133         },
134
135         // Repeated message with/without colon and <>/{}
136         {
137                 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
149         // Missing colon for inner message
150         {
151                 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
161         {
162                 in:    `name "Dave"`,
163                 error: `line 1.5: expected ':', found "\"Dave\""`,
164         },
165
166         // Missing colon for int32 field
167         {
168                 in:    `count 42`,
169                 error: `line 1.6: expected ':', found "42"`,
170         },
171
172         // Missing required field
173         {
174                 in:    ``,
175                 error: `line 1.0: message test_proto.MyMessage missing required field "count"`,
176         },
177
178         // Repeated non-repeated field
179         {
180                 in:    `name: "Rob" name: "Russ"`,
181                 error: `line 1.12: non-repeated field "name" was repeated`,
182         },
183
184         // 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
195         // Big all-in-one
196         {
197                 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),
221                         Name:  String("Dave"),
222                         Quote: String(`"I didn't want to go."`),
223                         Pet:   []string{"bunny", "kitty", "horsey"},
224                         Inner: &InnerMessage{
225                                 Host:      String("footrest.syd"),
226                                 Port:      Int32(7001),
227                                 Connected: Bool(true),
228                         },
229                         Others: []*OtherMessage{
230                                 &OtherMessage{
231                                         Key:   Int64(3735928559),
232                                         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
246 func 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 }
270
271 var benchInput string
272
273 func 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
287 func 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 }