initialise
[debian/goprotobuf.git] / proto / text_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         "bytes"
36         "strings"
37         "testing"
38
39         "goprotobuf.googlecode.com/hg/proto"
40
41         pb "./testdata/_obj/test_proto"
42 )
43
44 func newTestMessage() *pb.MyMessage {
45         msg := &pb.MyMessage{
46                 Count: proto.Int32(42),
47                 Name:  proto.String("Dave"),
48                 Quote: proto.String(`"I didn't want to go."`),
49                 Pet:   []string{"bunny", "kitty", "horsey"},
50                 Inner: &pb.InnerMessage{
51                         Host:      proto.String("footrest.syd"),
52                         Port:      proto.Int32(7001),
53                         Connected: proto.Bool(true),
54                 },
55                 Others: []*pb.OtherMessage{
56                         &pb.OtherMessage{
57                                 Key:   proto.Int64(0xdeadbeef),
58                                 Value: []byte{1, 65, 7, 12},
59                         },
60                         &pb.OtherMessage{
61                                 Weight: proto.Float32(6.022),
62                                 Inner: &pb.InnerMessage{
63                                         Host: proto.String("lesha.mtv"),
64                                         Port: proto.Int32(8002),
65                                 },
66                         },
67                 },
68                 Bikeshed: pb.NewMyMessage_Color(pb.MyMessage_BLUE),
69                 Somegroup: &pb.MyMessage_SomeGroup{
70                         GroupField: proto.Int32(8),
71                 },
72                 // One normally wouldn't do this.
73                 // This is an undeclared tag 13, as a varint (wire type 0) with value 4.
74                 XXX_unrecognized: []byte{13<<3 | 0, 4},
75         }
76         ext := &pb.Ext{
77                 Data: proto.String("Big gobs for big rats"),
78         }
79         if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil {
80                 panic(err)
81         }
82
83         // Add an unknown extension. We marshal a pb.Ext, and fake the ID.
84         b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")})
85         if err != nil {
86                 panic(err)
87         }
88         b = append(proto.EncodeVarint(104<<3|proto.WireBytes), b...)
89         proto.SetRawExtension(msg, 104, b)
90
91         // Extensions can be plain fields, too, so let's test that.
92         b = append(proto.EncodeVarint(105<<3|proto.WireVarint), 19)
93         proto.SetRawExtension(msg, 105, b)
94
95         return msg
96 }
97
98 const text = `count: 42
99 name: "Dave"
100 quote: "\"I didn't want to go.\""
101 pet: "bunny"
102 pet: "kitty"
103 pet: "horsey"
104 inner: <
105   host: "footrest.syd"
106   port: 7001
107   connected: true
108 >
109 others: <
110   key: 3735928559
111   value: "\001A\007\014"
112 >
113 others: <
114   weight: 6.022
115   inner: <
116     host: "lesha.mtv"
117     port: 8002
118   >
119 >
120 bikeshed: BLUE
121 SomeGroup {
122   group_field: 8
123 }
124 /* 2 unknown bytes */
125 tag13: 4
126 [test_proto.Ext.more]: <
127   data: "Big gobs for big rats"
128 >
129 /* 13 unknown bytes */
130 tag104: "\t3G skiing"
131 /* 3 unknown bytes */
132 tag105: 19
133 `
134
135 func TestMarshalTextFull(t *testing.T) {
136         buf := new(bytes.Buffer)
137         proto.MarshalText(buf, newTestMessage())
138         s := buf.String()
139         if s != text {
140                 t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text)
141         }
142 }
143
144 func compact(src string) string {
145         // s/[ \n]+/ /g; s/ $//;
146         dst := make([]byte, len(src))
147         space, comment := false, false
148         j := 0
149         for i := 0; i < len(src); i++ {
150                 if strings.HasPrefix(src[i:], "/*") {
151                         comment = true
152                         i++
153                         continue
154                 }
155                 if comment && strings.HasPrefix(src[i:], "*/") {
156                         comment = false
157                         i++
158                         continue
159                 }
160                 if comment {
161                         continue
162                 }
163                 c := src[i]
164                 if c == ' ' || c == '\n' {
165                         space = true
166                         continue
167                 }
168                 if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') {
169                         space = false
170                 }
171                 if c == '{' {
172                         space = false
173                 }
174                 if space {
175                         dst[j] = ' '
176                         j++
177                         space = false
178                 }
179                 dst[j] = c
180                 j++
181         }
182         if space {
183                 dst[j] = ' '
184                 j++
185         }
186         return string(dst[0:j])
187 }
188
189 var compactText = compact(text)
190
191 func TestCompactText(t *testing.T) {
192         s := proto.CompactTextString(newTestMessage())
193         if s != compactText {
194                 t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText)
195         }
196 }
197
198 func TestStringEscaping(t *testing.T) {
199         testCases := []struct {
200                 in  *pb.Strings
201                 out string
202         }{
203                 {
204                         // Test data from C++ test (TextFormatTest.StringEscape).
205                         // Single divergence: we don't escape apostrophes.
206                         &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and  multiple   spaces")},
207                         "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and  multiple   spaces\"\n",
208                 },
209                 {
210                         // Test data from the same C++ test.
211                         &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")},
212                         "string_field: \"\\350\\260\\267\\346\\255\\214\"\n",
213                 },
214         }
215
216         for i, tc := range testCases {
217                 var buf bytes.Buffer
218                 proto.MarshalText(&buf, tc.in)
219                 if s := buf.String(); s != tc.out {
220                         t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out)
221                 }
222         }
223 }
224
225