1
/*
2
 * Copyright 2008-2011 Novell, Inc.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2.1 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
 * Boston, MA 02110-1301, USA.
18
 */
19

            
20
#include <dbind/dbind.h>
21
#include <glib.h>
22
#include <stdio.h>
23
#include <string.h>
24

            
25
void
26
5
marshal (DBusMessage *msg, const char *type, void *ptr)
27
{
28
  DBusMessageIter iter;
29

            
30
5
  dbus_message_iter_init_append (msg, &iter);
31
5
  dbind_any_marshal (&iter, &type, &ptr);
32
5
}
33

            
34
void
35
5
demarshal (DBusMessage *msg, const char *type, void *ptr)
36
{
37
  DBusMessageIter iter;
38

            
39
5
  if (!dbus_message_iter_init (msg, &iter))
40
    {
41
      fprintf (stderr, "no data in msg\n");
42
      g_assert_not_reached ();
43
    }
44
  else
45
5
    dbind_any_demarshal (&iter, &type, &ptr);
46
5
}
47

            
48
#if 0
49
dbus_bool_t  dbus_message_marshal   (DBusMessage  *msg,
50
                                     char        **marshalled_data_p,
51
                                     int          *len_p);
52

            
53
void dump_msg (DBusMessage *msg)
54
{
55
    char *data = NULL;
56
    int   len, i, j;
57

            
58
    dbus_message_marshal (msg, &data, &len);
59
    for (i = 0; i < (len+15)/16; i++) {
60
        fprintf (stderr, "%4.d | ", i * 16);
61
        for (j = 0; j < 16; j++) {
62
            unsigned char c = (i*16+j <= len) ? data[i*16+j] : 0;
63
            fprintf (stderr, "0x%.2x ", c);
64
        }
65
        fprintf (stderr, " | ");
66
        for (j = 0; j < 16; j++) {
67
            char c = (i*16+j <= len) ? data[i*16+j] : '\0';
68
            fprintf (stderr, "%c", g_ascii_isprint (c) ? c : '.');
69
        }
70
    }
71
}
72
#endif
73

            
74
void
75
1
test_simple ()
76
{
77
  dbus_int32_t v1, v2;
78
  DBusMessage *msg;
79

            
80
1
  msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
81
1
  v1 = 42;
82
1
  marshal (msg, "i", &v1);
83
1
  demarshal (msg, "i", &v2);
84
1
  g_assert (v2 == 42);
85
1
  g_assert (v1 == v2);
86

            
87
1
  dbind_any_free ("i", &v2); /* nop */
88
1
  dbus_message_unref (msg);
89

            
90
1
  printf ("simple ok\n");
91
1
}
92

            
93
void
94
1
test_array ()
95
{
96
  GArray *a1, *a2;
97
  DBusMessage *msg;
98

            
99
  /* pod types */
100
1
  a1 = g_array_new (FALSE, FALSE, sizeof (dbus_int32_t));
101
1
  g_array_set_size (a1, 4);
102
1
  g_array_index (a1, dbus_int32_t, 0) = 42;
103
1
  g_array_index (a1, dbus_int32_t, 1) = 17;
104
1
  g_array_index (a1, dbus_int32_t, 2) = 26;
105
1
  g_array_index (a1, dbus_int32_t, 3) = 38;
106

            
107
1
  msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
108
1
  marshal (msg, "ai", &a1);
109
1
  demarshal (msg, "ai", &a2);
110

            
111
1
  g_assert (a2 != NULL);
112
1
  g_assert (a2->len == 4);
113
1
  g_assert (g_array_index (a2, dbus_int32_t, 0) == 42);
114
1
  g_assert (g_array_index (a2, dbus_int32_t, 1) == 17);
115
1
  g_assert (g_array_index (a2, dbus_int32_t, 2) == 26);
116
1
  g_assert (g_array_index (a2, dbus_int32_t, 3) == 38);
117
1
  g_array_free (a1, TRUE);
118

            
119
1
  dbind_any_free ("ai", &a2);
120
1
  dbus_message_unref (msg);
121

            
122
1
  printf ("array ok\n");
123
1
}
124

            
125
/* this taught me that the struct type is a mis-nomer,
126
   it is generated by brackets */
127
void
128
1
test_struct_native ()
129
{
130
  DBusMessage *msg;
131
  DBusMessageIter iter, arr, str;
132

            
133
  /* manually create ar(ss) */
134
1
  msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
135

            
136
1
  dbus_message_iter_init_append (msg, &iter);
137

            
138
1
  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ss)", &arr);
139
  {
140
    char *foo;
141
1
    dbus_message_iter_open_container (&arr, DBUS_TYPE_STRUCT, NULL, &str);
142

            
143
1
    foo = "foo";
144
1
    dbus_message_iter_append_basic (&str, DBUS_TYPE_STRING, &foo);
145
1
    foo = "baa";
146
1
    dbus_message_iter_append_basic (&str, DBUS_TYPE_STRING, &foo);
147

            
148
1
    dbus_message_iter_close_container (&arr, &str);
149
  }
150
1
  dbus_message_iter_close_container (&iter, &arr);
151

            
152
1
  printf ("native struct marshalling ok\n");
153

            
154
1
  dbus_message_unref (msg);
155
1
}
156

            
157
void
158
1
test_struct_simple ()
159
{
160
  typedef struct
161
  {
162
    char *foo;
163
    char *baa;
164
    char *baz;
165
  } FooBaa;
166
1
  GArray *a1 = NULL, *a2 = NULL;
167
  DBusMessage *msg;
168

            
169
1
  a1 = g_array_new (FALSE, FALSE, sizeof (FooBaa));
170
1
  g_array_set_size (a1, 2);
171
1
  g_array_index (a1, FooBaa, 0).foo = "foo";
172
1
  g_array_index (a1, FooBaa, 0).baa = "baa";
173
1
  g_array_index (a1, FooBaa, 0).baz = "baz";
174
1
  g_array_index (a1, FooBaa, 1).foo = "Foo";
175
1
  g_array_index (a1, FooBaa, 1).baa = "baA";
176
1
  g_array_index (a1, FooBaa, 1).baz = "BaZ";
177

            
178
1
  msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
179
1
  marshal (msg, "a(sss)", &a1);
180
1
  demarshal (msg, "a(sss)", &a2);
181

            
182
1
  g_assert (a2 != NULL);
183
1
  g_assert (a2 != a1);
184
1
  g_assert (a2->len == 2);
185
1
  g_assert (!strcmp (g_array_index (a2, FooBaa, 0).foo, "foo"));
186
1
  g_assert (!strcmp (g_array_index (a2, FooBaa, 0).baa, "baa"));
187
1
  g_assert (!strcmp (g_array_index (a2, FooBaa, 0).baz, "baz"));
188
1
  g_assert (!strcmp (g_array_index (a2, FooBaa, 1).foo, "Foo"));
189
1
  g_assert (!strcmp (g_array_index (a2, FooBaa, 1).baa, "baA"));
190
1
  g_assert (!strcmp (g_array_index (a2, FooBaa, 1).baz, "BaZ"));
191

            
192
1
  printf ("simple struct ok\n");
193

            
194
1
  dbind_any_free ("a(sss)", &a2);
195
1
  dbus_message_unref (msg);
196
1
  g_array_free (a1, TRUE);
197
1
}
198

            
199
void
200
1
test_struct_complex ()
201
{
202
  typedef struct
203
  {
204
    dbus_int32_t x, y;
205
  } Point;
206
  typedef struct
207
  {
208
    unsigned char pad1;
209
    double val;
210
    Point tl, br;
211
    char pad2;
212
    char *name;
213
  } Complex;
214
#define TYPEOF_POINT               \
215
  DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
216
  DBUS_TYPE_INT32_AS_STRING        \
217
  DBUS_TYPE_INT32_AS_STRING        \
218
  DBUS_STRUCT_END_CHAR_AS_STRING
219
#define TYPEOF_COMPLEX             \
220
  DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
221
  DBUS_TYPE_BYTE_AS_STRING         \
222
  DBUS_TYPE_DOUBLE_AS_STRING       \
223
  TYPEOF_POINT                     \
224
  TYPEOF_POINT                     \
225
  DBUS_TYPE_BYTE_AS_STRING         \
226
  DBUS_TYPE_STRING_AS_STRING       \
227
  DBUS_STRUCT_END_CHAR_AS_STRING
228

            
229
  DBusMessage *msg;
230
  Complex c1, c2;
231

            
232
1
  memset (&c1, 0, sizeof (c1));
233
1
  memset (&c2, 0, sizeof (c2));
234

            
235
1
  c1.pad1 = 2;
236
1
  c1.val = 0.1327569;
237
1
  c1.tl.x = 1;
238
1
  c1.tl.y = 17;
239
1
  c1.br.x = 2587;
240
1
  c1.br.y = -1;
241
1
  c1.pad2 = 1;
242
1
  c1.name = "stroustrup";
243

            
244
1
  msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
245
1
  marshal (msg, TYPEOF_COMPLEX, &c1);
246
1
  demarshal (msg, TYPEOF_COMPLEX, &c2);
247

            
248
1
  g_assert (c2.pad1 == 2);
249
1
  g_assert (c2.val == c1.val);
250
1
  g_assert (c2.val != 0);
251
1
  g_assert (c2.tl.x == 1);
252
1
  g_assert (c2.tl.y == 17);
253
1
  g_assert (c2.br.x == 2587);
254
1
  g_assert (c2.br.y == -1);
255
1
  g_assert (c2.pad2 == 1);
256
1
  g_assert (!strcmp (c1.name, "stroustrup"));
257

            
258
1
  printf ("complex struct ok\n");
259

            
260
1
  dbind_any_free (TYPEOF_COMPLEX, &c2);
261
1
  dbus_message_unref (msg);
262
1
}
263

            
264
void
265
1
test_struct_with_array ()
266
{
267
  typedef struct
268
  {
269
    GArray *vals;
270
    unsigned char pad1;
271
  } ArrayStruct;
272
#define TYPEOF_ARRAYSTRUCT         \
273
  DBUS_TYPE_ARRAY_AS_STRING        \
274
  DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
275
  DBUS_TYPE_ARRAY_AS_STRING        \
276
  DBUS_TYPE_UINT32_AS_STRING       \
277
  DBUS_TYPE_BYTE_AS_STRING         \
278
  DBUS_STRUCT_END_CHAR_AS_STRING
279

            
280
  DBusMessage *msg;
281
  GArray *a1, *a2;
282
  ArrayStruct *p, *q;
283

            
284
1
  a1 = g_array_new (FALSE, FALSE, sizeof (ArrayStruct));
285
1
  g_array_set_size (a1, 2);
286
1
  p = &g_array_index (a1, ArrayStruct, 0);
287
1
  p[0].vals = g_array_new (FALSE, FALSE, sizeof (dbus_uint32_t));
288
1
  g_array_set_size (p[0].vals, 2);
289
1
  g_array_index (p[0].vals, dbus_uint32_t, 0) = 1;
290
1
  g_array_index (p[0].vals, dbus_uint32_t, 1) = 1000;
291
1
  p[0].pad1 = 2;
292
1
  p[1].vals = g_array_new (FALSE, FALSE, sizeof (dbus_uint32_t));
293
1
  g_array_set_size (p[1].vals, 2);
294
1
  g_array_index (p[1].vals, dbus_uint32_t, 0) = 1000000;
295
1
  g_array_index (p[1].vals, dbus_uint32_t, 1) = 1000000000;
296
1
  p[1].pad1 = 8;
297

            
298
1
  msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
299
1
  marshal (msg, TYPEOF_ARRAYSTRUCT, &a1);
300
1
  demarshal (msg, TYPEOF_ARRAYSTRUCT, &a2);
301

            
302
1
  q = &g_array_index (a2, ArrayStruct, 0);
303
1
  g_assert (q[0].pad1 == 2);
304
1
  g_assert (g_array_index (q[1].vals, dbus_uint32_t, 1) == 1000000000);
305

            
306
1
  printf ("struct with array ok\n");
307

            
308
1
  dbind_any_free (TYPEOF_ARRAYSTRUCT, &a2);
309
1
  dbus_message_unref (msg);
310
1
  g_array_free (p[0].vals, TRUE);
311
1
  g_array_free (p[1].vals, TRUE);
312
1
  g_array_free (a1, TRUE);
313
1
}
314

            
315
void
316
1
test_twovals ()
317
{
318
  typedef struct
319
  {
320
    dbus_int32_t v1;
321
    dbus_int32_t v2;
322
  } TwoVal;
323
#define TYPEOF_TWOVAL       \
324
  DBUS_TYPE_INT32_AS_STRING \
325
  DBUS_TYPE_INT32_AS_STRING
326

            
327
  DBusMessage *msg;
328
  DBusMessageIter iter;
329
  TwoVal i, o;
330
1
  const char *type_twoval = TYPEOF_TWOVAL;
331
  const char *type;
332
  void *ptr;
333

            
334
1
  msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
335
1
  i.v1 = 42;
336
1
  i.v2 = 1764;
337
1
  dbus_message_iter_init_append (msg, &iter);
338
1
  type = type_twoval;
339
1
  ptr = &i;
340
1
  dbind_any_marshal (&iter, &type, &ptr);
341
1
  dbind_any_marshal (&iter, &type, &ptr);
342
1
  dbus_message_iter_init (msg, &iter);
343
1
  type = type_twoval;
344
1
  ptr = &o;
345
1
  dbind_any_demarshal (&iter, &type, &ptr);
346
1
  dbind_any_demarshal (&iter, &type, &ptr);
347
1
  g_assert (o.v1 == 42);
348
1
  g_assert (o.v2 == 1764);
349
1
  g_assert (i.v1 == o.v1);
350
1
  g_assert (i.v2 == o.v2);
351

            
352
1
  dbind_any_free ("ii", &o); /* nop */
353
1
  dbus_message_unref (msg);
354

            
355
1
  printf ("two-val ok\n");
356
1
}
357

            
358
void
359
1
test_marshalling ()
360
{
361
1
  test_simple ();
362
1
  test_array ();
363
1
  test_struct_native ();
364
1
  test_struct_simple ();
365
1
  test_struct_complex ();
366
1
  test_struct_with_array ();
367
1
  test_twovals ();
368

            
369
1
  printf ("Marshalling ok\n");
370
1
}
371

            
372
void
373
1
test_helpers ()
374
{
375
1
  dbind_find_c_alignment ("(sss)");
376
1
  dbind_find_c_alignment ("a(sss)");
377
1
  dbind_find_c_alignment ("(s(s)yd(d)s)");
378
1
  dbind_find_c_alignment ("a{ss}");
379
1
  printf ("helpers passed\n");
380
1
}
381

            
382
int
383
1
main (int argc, char **argv)
384
{
385
1
  DBusConnection *bus = dbus_bus_get (DBUS_BUS_SESSION, NULL);
386
1
  g_assert (bus != NULL);
387

            
388
1
  test_helpers ();
389
1
  test_marshalling ();
390

            
391
1
  return 0;
392
}