1 package dbus
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "io/ioutil"
7 "math"
8 "reflect"
9 "testing"
10 )
11
12 var protoTests = []struct {
13 vs []interface{}
14 bigEndian []byte
15 littleEndian []byte
16 }{
17 {
18 []interface{}{int32(0)},
19 []byte{0, 0, 0, 0},
20 []byte{0, 0, 0, 0},
21 },
22 {
23 []interface{}{true, false},
24 []byte{0, 0, 0, 1, 0, 0, 0, 0},
25 []byte{1, 0, 0, 0, 0, 0, 0, 0},
26 },
27 {
28 []interface{}{byte(0), uint16(12), int16(32), uint32(43)},
29 []byte{0, 0, 0, 12, 0, 32, 0, 0, 0, 0, 0, 43},
30 []byte{0, 0, 12, 0, 32, 0, 0, 0, 43, 0, 0, 0},
31 },
32 {
33 []interface{}{int64(-1), uint64(1<<64 - 1)},
34 bytes.Repeat([]byte{255}, 16),
35 bytes.Repeat([]byte{255}, 16),
36 },
37 {
38 []interface{}{math.Inf(+1)},
39 []byte{0x7f, 0xf0, 0, 0, 0, 0, 0, 0},
40 []byte{0, 0, 0, 0, 0, 0, 0xf0, 0x7f},
41 },
42 {
43 []interface{}{"foo"},
44 []byte{0, 0, 0, 3, 'f', 'o', 'o', 0},
45 []byte{3, 0, 0, 0, 'f', 'o', 'o', 0},
46 },
47 {
48 []interface{}{Signature{"ai"}},
49 []byte{2, 'a', 'i', 0},
50 []byte{2, 'a', 'i', 0},
51 },
52 {
53 []interface{}{[]int16{42, 256}},
54 []byte{0, 0, 0, 4, 0, 42, 1, 0},
55 []byte{4, 0, 0, 0, 42, 0, 0, 1},
56 },
57 {
58 []interface{}{MakeVariant("foo")},
59 []byte{1, 's', 0, 0, 0, 0, 0, 3, 'f', 'o', 'o', 0},
60 []byte{1, 's', 0, 0, 3, 0, 0, 0, 'f', 'o', 'o', 0},
61 },
62 {
63 []interface{}{MakeVariant(MakeVariant(Signature{"v"}))},
64 []byte{1, 'v', 0, 1, 'g', 0, 1, 'v', 0},
65 []byte{1, 'v', 0, 1, 'g', 0, 1, 'v', 0},
66 },
67 {
68 []interface{}{map[int32]bool{42: true}},
69 []byte{0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 1},
70 []byte{8, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 1, 0, 0, 0},
71 },
72 {
73 []interface{}{map[string]Variant{}, byte(42)},
74 []byte{0, 0, 0, 0, 0, 0, 0, 0, 42},
75 []byte{0, 0, 0, 0, 0, 0, 0, 0, 42},
76 },
77 {
78 []interface{}{[]uint64{}, byte(42)},
79 []byte{0, 0, 0, 0, 0, 0, 0, 0, 42},
80 []byte{0, 0, 0, 0, 0, 0, 0, 0, 42},
81 },
82 }
83
84 func TestProto(t *testing.T) {
85 for i, v := range protoTests {
86 buf := new(bytes.Buffer)
87 fds := make([]int, 0)
88 bigEnc := newEncoder(buf, binary.BigEndian, fds)
89 bigEnc.Encode(v.vs...)
90 marshalled := buf.Bytes()
91 if !bytes.Equal(marshalled, v.bigEndian) {
92 t.Errorf("test %d (marshal be): got '%v', but expected '%v'\n", i+1, marshalled,
93 v.bigEndian)
94 }
95 buf.Reset()
96 fds = make([]int, 0)
97 litEnc := newEncoder(buf, binary.LittleEndian, fds)
98 litEnc.Encode(v.vs...)
99 marshalled = buf.Bytes()
100 if !bytes.Equal(marshalled, v.littleEndian) {
101 t.Errorf("test %d (marshal le): got '%v', but expected '%v'\n", i+1, marshalled,
102 v.littleEndian)
103 }
104 unmarshalled := reflect.MakeSlice(reflect.TypeOf(v.vs),
105 0, 0)
106 for i := range v.vs {
107 unmarshalled = reflect.Append(unmarshalled,
108 reflect.New(reflect.TypeOf(v.vs[i])))
109 }
110 bigDec := newDecoder(bytes.NewReader(v.bigEndian), binary.BigEndian, make([]int, 0))
111 vs, err := bigDec.Decode(SignatureOf(v.vs...))
112 if err != nil {
113 t.Errorf("test %d (unmarshal be): %s\n", i+1, err)
114 continue
115 }
116 if !reflect.DeepEqual(vs, v.vs) {
117 t.Errorf("test %d (unmarshal be): got %#v, but expected %#v\n", i+1, vs, v.vs)
118 }
119 litDec := newDecoder(bytes.NewReader(v.littleEndian), binary.LittleEndian, make([]int, 0))
120 vs, err = litDec.Decode(SignatureOf(v.vs...))
121 if err != nil {
122 t.Errorf("test %d (unmarshal le): %s\n", i+1, err)
123 continue
124 }
125 if !reflect.DeepEqual(vs, v.vs) {
126 t.Errorf("test %d (unmarshal le): got %#v, but expected %#v\n", i+1, vs, v.vs)
127 }
128
129 }
130 }
131
132 func TestProtoMap(t *testing.T) {
133 m := map[string]uint8{
134 "foo": 23,
135 "bar": 2,
136 }
137 var n map[string]uint8
138 buf := new(bytes.Buffer)
139 fds := make([]int, 0)
140 enc := newEncoder(buf, binary.LittleEndian, fds)
141 enc.Encode(m)
142 dec := newDecoder(buf, binary.LittleEndian, enc.fds)
143 vs, err := dec.Decode(Signature{"a{sy}"})
144 if err != nil {
145 t.Fatal(err)
146 }
147 if err = Store(vs, &n); err != nil {
148 t.Fatal(err)
149 }
150 if len(n) != 2 || n["foo"] != 23 || n["bar"] != 2 {
151 t.Error("got", n)
152 }
153 }
154
155 func TestProtoVariantStruct(t *testing.T) {
156 var variant Variant
157 v := MakeVariant(struct {
158 A int32
159 B int16
160 }{1, 2})
161 buf := new(bytes.Buffer)
162 fds := make([]int, 0)
163 enc := newEncoder(buf, binary.LittleEndian, fds)
164 enc.Encode(v)
165 dec := newDecoder(buf, binary.LittleEndian, enc.fds)
166 vs, err := dec.Decode(Signature{"v"})
167 if err != nil {
168 t.Fatal(err)
169 }
170 if err = Store(vs, &variant); err != nil {
171 t.Fatal(err)
172 }
173 sl := variant.Value().([]interface{})
174 v1, v2 := sl[0].(int32), sl[1].(int16)
175 if v1 != int32(1) {
176 t.Error("got", v1, "as first int")
177 }
178 if v2 != int16(2) {
179 t.Error("got", v2, "as second int")
180 }
181 }
182
183 func TestProtoStructTag(t *testing.T) {
184 type Bar struct {
185 A int32
186 B chan interface{} `dbus:"-"`
187 C int32
188 }
189 var bar1, bar2 Bar
190 bar1.A = 234
191 bar2.C = 345
192 buf := new(bytes.Buffer)
193 fds := make([]int, 0)
194 enc := newEncoder(buf, binary.LittleEndian, fds)
195 enc.Encode(bar1)
196 dec := newDecoder(buf, binary.LittleEndian, enc.fds)
197 vs, err := dec.Decode(Signature{"(ii)"})
198 if err != nil {
199 t.Fatal(err)
200 }
201 if err = Store(vs, &bar2); err != nil {
202 t.Fatal(err)
203 }
204 if bar1 != bar2 {
205 t.Error("struct tag test: got", bar2)
206 }
207 }
208
209 func TestProtoStoreStruct(t *testing.T) {
210 var foo struct {
211 A int32
212 B string
213 c chan interface{}
214 D interface{} `dbus:"-"`
215 }
216 src := []interface{}{[]interface{}{int32(42), "foo"}}
217 err := Store(src, &foo)
218 if err != nil {
219 t.Fatal(err)
220 }
221 }
222
223 func TestProtoStoreNestedStruct(t *testing.T) {
224 var foo struct {
225 A int32
226 B struct {
227 C string
228 D float64
229 }
230 }
231 src := []interface{}{
232 []interface{}{
233 int32(42),
234 []interface{}{
235 "foo",
236 3.14,
237 },
238 },
239 }
240 err := Store(src, &foo)
241 if err != nil {
242 t.Fatal(err)
243 }
244 }
245
246 func TestMessage(t *testing.T) {
247 buf := new(bytes.Buffer)
248 message := new(Message)
249 message.Type = TypeMethodCall
250 message.serial = 32
251 message.Headers = map[HeaderField]Variant{
252 FieldPath: MakeVariant(ObjectPath("/org/foo/bar")),
253 FieldMember: MakeVariant("baz"),
254 }
255 message.Body = make([]interface{}, 0)
256 err := message.EncodeTo(buf, binary.LittleEndian)
257 if err != nil {
258 t.Error(err)
259 }
260 _, err = DecodeMessage(buf)
261 if err != nil {
262 t.Error(err)
263 }
264 }
265
266 func TestProtoStructInterfaces(t *testing.T) {
267 b := []byte{42}
268 vs, err := newDecoder(bytes.NewReader(b), binary.LittleEndian, make([]int, 0)).Decode(Signature{"(y)"})
269 if err != nil {
270 t.Fatal(err)
271 }
272 if vs[0].([]interface{})[0].(byte) != 42 {
273 t.Errorf("wrongs results (got %v)", vs)
274 }
275 }
276
277
278 var smallMessage = &Message{
279 Type: TypeMethodCall,
280 serial: 1,
281 Headers: map[HeaderField]Variant{
282 FieldDestination: MakeVariant("org.freedesktop.DBus"),
283 FieldPath: MakeVariant(ObjectPath("/org/freedesktop/DBus")),
284 FieldInterface: MakeVariant("org.freedesktop.DBus"),
285 FieldMember: MakeVariant("Hello"),
286 },
287 }
288
289
290 var bigMessage = &Message{
291 Type: TypeMethodCall,
292 serial: 2,
293 Headers: map[HeaderField]Variant{
294 FieldDestination: MakeVariant("org.freedesktop.Notifications"),
295 FieldPath: MakeVariant(ObjectPath("/org/freedesktop/Notifications")),
296 FieldInterface: MakeVariant("org.freedesktop.Notifications"),
297 FieldMember: MakeVariant("Notify"),
298 FieldSignature: MakeVariant(Signature{"susssasa{sv}i"}),
299 },
300 Body: []interface{}{
301 "app_name",
302 uint32(0),
303 "dialog-information",
304 "Notification",
305 "This is the body of a notification",
306 []string{"ok", "Ok"},
307 map[string]Variant{
308 "sound-name": MakeVariant("dialog-information"),
309 },
310 int32(-1),
311 },
312 }
313
314 func BenchmarkDecodeMessageSmall(b *testing.B) {
315 var err error
316 var rd *bytes.Reader
317
318 b.StopTimer()
319 buf := new(bytes.Buffer)
320 err = smallMessage.EncodeTo(buf, binary.LittleEndian)
321 if err != nil {
322 b.Fatal(err)
323 }
324 decoded := buf.Bytes()
325 b.StartTimer()
326 for i := 0; i < b.N; i++ {
327 rd = bytes.NewReader(decoded)
328 _, err = DecodeMessage(rd)
329 if err != nil {
330 b.Fatal(err)
331 }
332 }
333 }
334
335 func BenchmarkDecodeMessageBig(b *testing.B) {
336 var err error
337 var rd *bytes.Reader
338
339 b.StopTimer()
340 buf := new(bytes.Buffer)
341 err = bigMessage.EncodeTo(buf, binary.LittleEndian)
342 if err != nil {
343 b.Fatal(err)
344 }
345 decoded := buf.Bytes()
346 b.StartTimer()
347 for i := 0; i < b.N; i++ {
348 rd = bytes.NewReader(decoded)
349 _, err = DecodeMessage(rd)
350 if err != nil {
351 b.Fatal(err)
352 }
353 }
354 }
355
356 func BenchmarkEncodeMessageSmall(b *testing.B) {
357 var err error
358 for i := 0; i < b.N; i++ {
359 err = smallMessage.EncodeTo(ioutil.Discard, binary.LittleEndian)
360 if err != nil {
361 b.Fatal(err)
362 }
363 }
364 }
365
366 func BenchmarkEncodeMessageBig(b *testing.B) {
367 var err error
368 for i := 0; i < b.N; i++ {
369 err = bigMessage.EncodeTo(ioutil.Discard, binary.LittleEndian)
370 if err != nil {
371 b.Fatal(err)
372 }
373 }
374 }
375
View as plain text