Merge branch 'dbus-1.10'
[platform/upstream/dbus.git] / dbus / dbus-message-util.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-message-util.c Would be in dbus-message.c, but only used by bus/tests
3  *
4  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
5  * Copyright (C) 2002, 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #include <config.h>
26 #include "dbus-internals.h"
27 #include "dbus-test.h"
28 #include "dbus-message-private.h"
29 #include "dbus-marshal-recursive.h"
30 #include "dbus-string.h"
31 #ifdef HAVE_UNIX_FD_PASSING
32 #include "dbus-sysdeps-unix.h"
33 #endif
34
35 #ifdef __linux__
36 /* Necessary for the Linux-specific fd leak checking code only */
37 #include <sys/types.h>
38 #include <dirent.h>
39 #include <stdlib.h>
40 #include <errno.h>
41 #endif
42
43 /**
44  * @addtogroup DBusMessage
45  * @{
46  */
47
48 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
49 /**
50  * Reads arguments from a message iterator given a variable argument
51  * list. Only arguments of basic type and arrays of fixed-length
52  * basic type may be read with this function. See
53  * dbus_message_get_args() for more details.
54  *
55  * @param iter the message iterator
56  * @param error error to be filled in on failure
57  * @param first_arg_type the first argument type
58  * @param ... location for first argument value, then list of type-location pairs
59  * @returns #FALSE if the error was set
60  */
61 static dbus_bool_t
62 dbus_message_iter_get_args (DBusMessageIter *iter,
63                             DBusError       *error,
64                             int              first_arg_type,
65                             ...)
66 {
67   dbus_bool_t retval;
68   va_list var_args;
69
70   _dbus_return_val_if_fail (iter != NULL, FALSE);
71   _dbus_return_val_if_error_is_set (error, FALSE);
72
73   va_start (var_args, first_arg_type);
74   retval = _dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
75   va_end (var_args);
76
77   return retval;
78 }
79 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
80
81 /** @} */
82
83 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
84 #include "dbus-test.h"
85 #include "dbus-message-factory.h"
86 #include <stdio.h>
87 #include <stdlib.h>
88
89 static int validities_seen[DBUS_VALIDITY_LAST + _DBUS_NEGATIVE_VALIDITY_COUNT];
90
91 static void
92 reset_validities_seen (void)
93 {
94   int i;
95   i = 0;
96   while (i < _DBUS_N_ELEMENTS (validities_seen))
97     {
98       validities_seen[i] = 0;
99       ++i;
100     }
101 }
102
103 static void
104 record_validity_seen (DBusValidity validity)
105 {
106   validities_seen[validity + _DBUS_NEGATIVE_VALIDITY_COUNT] += 1;
107 }
108
109 static void
110 print_validities_seen (dbus_bool_t not_seen)
111 {
112   int i;
113   i = 0;
114   while (i < _DBUS_N_ELEMENTS (validities_seen))
115     {
116       if ((i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_VALIDITY_UNKNOWN ||
117           (i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_INVALID_FOR_UNKNOWN_REASON)
118         ;
119       else if ((not_seen && validities_seen[i] == 0) ||
120                (!not_seen && validities_seen[i] > 0))
121         printf ("validity %3d seen %d times\n",
122                 i - _DBUS_NEGATIVE_VALIDITY_COUNT,
123                 validities_seen[i]);
124       ++i;
125     }
126 }
127
128 static void
129 check_memleaks (void)
130 {
131   dbus_shutdown ();
132
133   if (_dbus_get_malloc_blocks_outstanding () != 0)
134     {
135       _dbus_warn ("%d dbus_malloc blocks were not freed in %s",
136                   _dbus_get_malloc_blocks_outstanding (), __FILE__);
137       _dbus_assert_not_reached ("memleaks");
138     }
139 }
140
141 #ifdef __linux__
142 struct DBusInitialFDs {
143     fd_set set;
144 };
145 #endif
146
147 DBusInitialFDs *
148 _dbus_check_fdleaks_enter (void)
149 {
150 #ifdef __linux__
151   DIR *d;
152   DBusInitialFDs *fds;
153
154   /* this is plain malloc so it won't interfere with leak checking */
155   fds = malloc (sizeof (DBusInitialFDs));
156   _dbus_assert (fds != NULL);
157
158   /* This works on Linux only */
159
160   if ((d = opendir ("/proc/self/fd")))
161     {
162       struct dirent *de;
163
164       while ((de = readdir(d)))
165         {
166           long l;
167           char *e = NULL;
168           int fd;
169
170           if (de->d_name[0] == '.')
171             continue;
172
173           errno = 0;
174           l = strtol (de->d_name, &e, 10);
175           _dbus_assert (errno == 0 && e && !*e);
176
177           fd = (int) l;
178
179           if (fd < 3)
180             continue;
181
182           if (fd == dirfd (d))
183             continue;
184
185           if (fd >= FD_SETSIZE)
186             {
187               _dbus_verbose ("FD %d unexpectedly large; cannot track whether "
188                              "it is leaked\n", fd);
189               continue;
190             }
191
192           FD_SET (fd, &fds->set);
193         }
194
195       closedir (d);
196     }
197
198   return fds;
199 #else
200   return NULL;
201 #endif
202 }
203
204 void
205 _dbus_check_fdleaks_leave (DBusInitialFDs *fds)
206 {
207 #ifdef __linux__
208   DIR *d;
209
210   /* This works on Linux only */
211
212   if ((d = opendir ("/proc/self/fd")))
213     {
214       struct dirent *de;
215
216       while ((de = readdir(d)))
217         {
218           long l;
219           char *e = NULL;
220           int fd;
221
222           if (de->d_name[0] == '.')
223             continue;
224
225           errno = 0;
226           l = strtol (de->d_name, &e, 10);
227           _dbus_assert (errno == 0 && e && !*e);
228
229           fd = (int) l;
230
231           if (fd < 3)
232             continue;
233
234           if (fd == dirfd (d))
235             continue;
236
237           if (fd >= FD_SETSIZE)
238             {
239               _dbus_verbose ("FD %d unexpectedly large; cannot track whether "
240                              "it is leaked\n", fd);
241               continue;
242             }
243
244           if (FD_ISSET (fd, &fds->set))
245             continue;
246
247           _dbus_warn ("file descriptor %i leaked in %s.", fd, __FILE__);
248           _dbus_assert_not_reached ("fdleaks");
249         }
250
251       closedir (d);
252     }
253
254   free (fds);
255 #else
256   _dbus_assert (fds == NULL);
257 #endif
258 }
259
260 static dbus_bool_t
261 check_have_valid_message (DBusMessageLoader *loader)
262 {
263   DBusMessage *message;
264   dbus_bool_t retval;
265
266   message = NULL;
267   retval = FALSE;
268
269   if (_dbus_message_loader_get_is_corrupted (loader))
270     {
271       _dbus_warn ("loader corrupted on message that was expected to be valid; invalid reason %d",
272                   loader->corruption_reason);
273       goto failed;
274     }
275
276   message = _dbus_message_loader_pop_message (loader);
277   if (message == NULL)
278     {
279       _dbus_warn ("didn't load message that was expected to be valid (message not popped)");
280       goto failed;
281     }
282
283   if (_dbus_string_get_length (&loader->data) > 0)
284     {
285       _dbus_warn ("had leftover bytes from expected-to-be-valid single message");
286       goto failed;
287     }
288
289 #if 0
290   /* FIXME */
291   /* Verify that we're able to properly deal with the message.
292    * For example, this would detect improper handling of messages
293    * in nonstandard byte order.
294    */
295   if (!check_message_handling (message))
296     goto failed;
297 #endif
298
299   record_validity_seen (DBUS_VALID);
300   
301   retval = TRUE;
302
303  failed:
304   if (message)
305     dbus_message_unref (message);
306
307   return retval;
308 }
309
310 static dbus_bool_t
311 check_invalid_message (DBusMessageLoader *loader,
312                        DBusValidity       expected_validity)
313 {
314   dbus_bool_t retval;
315
316   retval = FALSE;
317
318   if (!_dbus_message_loader_get_is_corrupted (loader))
319     {
320       _dbus_warn ("loader not corrupted on message that was expected to be invalid");
321       goto failed;
322     }
323
324   record_validity_seen (loader->corruption_reason);
325   
326   if (expected_validity != DBUS_INVALID_FOR_UNKNOWN_REASON &&
327       loader->corruption_reason != expected_validity)
328     {
329       _dbus_warn ("expected message to be corrupted for reason %d and was corrupted for %d instead",
330                   expected_validity, loader->corruption_reason);
331       goto failed;
332     }
333
334   retval = TRUE;
335
336  failed:
337   return retval;
338 }
339
340 static dbus_bool_t
341 check_incomplete_message (DBusMessageLoader *loader)
342 {
343   DBusMessage *message;
344   dbus_bool_t retval;
345
346   message = NULL;
347   retval = FALSE;
348
349   if (_dbus_message_loader_get_is_corrupted (loader))
350     {
351       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete), corruption reason %d",
352                   loader->corruption_reason);
353       goto failed;
354     }
355
356   message = _dbus_message_loader_pop_message (loader);
357   if (message != NULL)
358     {
359       _dbus_warn ("loaded message that was expected to be incomplete");
360       goto failed;
361     }
362
363   record_validity_seen (DBUS_VALID_BUT_INCOMPLETE);
364   retval = TRUE;
365
366  failed:
367   if (message)
368     dbus_message_unref (message);
369   return retval;
370 }
371
372 static dbus_bool_t
373 check_loader_results (DBusMessageLoader      *loader,
374                       DBusValidity            expected_validity)
375 {
376   if (!_dbus_message_loader_queue_messages (loader))
377     _dbus_assert_not_reached ("no memory to queue messages");
378
379   if (expected_validity == DBUS_VALID)
380     return check_have_valid_message (loader);
381   else if (expected_validity == DBUS_VALID_BUT_INCOMPLETE)
382     return check_incomplete_message (loader);
383   else if (expected_validity == DBUS_VALIDITY_UNKNOWN)
384     {
385       /* here we just know we didn't segfault and that was the
386        * only test. Also, we record that we got coverage
387        * for the validity reason.
388        */
389       if (_dbus_message_loader_get_is_corrupted (loader))
390         record_validity_seen (loader->corruption_reason);
391       
392       return TRUE;
393     }
394   else
395     return check_invalid_message (loader, expected_validity);
396 }
397
398 /**
399  * Loads the message in the given message file.
400  *
401  * @param filename filename to load
402  * @param data string to load message into
403  * @returns #TRUE if the message was loaded
404  */
405 dbus_bool_t
406 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
407                                             DBusString          *data)
408 {
409   dbus_bool_t retval;
410   DBusError error = DBUS_ERROR_INIT;
411
412   retval = FALSE;
413
414   _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
415   if (!_dbus_file_get_contents (data, filename, &error))
416     {
417       _dbus_warn ("Could not load message file %s: %s",
418                   _dbus_string_get_const_data (filename),
419                   error.message);
420       dbus_error_free (&error);
421       goto failed;
422     }
423
424   retval = TRUE;
425
426  failed:
427
428   return retval;
429 }
430
431 /**
432  * Tries loading the message in the given message file
433  * and verifies that DBusMessageLoader can handle it.
434  *
435  * @param filename filename to load
436  * @param expected_validity what the message has to be like to return #TRUE
437  * @returns #TRUE if the message has the expected validity
438  */
439 dbus_bool_t
440 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
441                                            DBusValidity         expected_validity)
442 {
443   DBusString data;
444   dbus_bool_t retval;
445
446   retval = FALSE;
447
448   if (!_dbus_string_init (&data))
449     _dbus_assert_not_reached ("could not allocate string");
450
451   if (!dbus_internal_do_not_use_load_message_file (filename, &data))
452     goto failed;
453
454   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
455
456  failed:
457
458   if (!retval)
459     {
460       if (_dbus_string_get_length (&data) > 0)
461         _dbus_verbose_bytes_of_string (&data, 0,
462                                        _dbus_string_get_length (&data));
463
464       _dbus_warn ("Failed message loader test on %s",
465                   _dbus_string_get_const_data (filename));
466     }
467
468   _dbus_string_free (&data);
469
470   return retval;
471 }
472
473 /**
474  * Tries loading the given message data.
475  *
476  *
477  * @param data the message data
478  * @param expected_validity what the message has to be like to return #TRUE
479  * @returns #TRUE if the message has the expected validity
480  */
481 dbus_bool_t
482 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
483                                            DBusValidity         expected_validity)
484 {
485   DBusMessageLoader *loader;
486   dbus_bool_t retval;
487   int len;
488   int i;
489
490   loader = NULL;
491   retval = FALSE;
492
493   /* Write the data one byte at a time */
494
495   loader = _dbus_message_loader_new ();
496   if (loader == NULL)
497     goto failed;
498
499   /* check some trivial loader functions */
500   _dbus_message_loader_ref (loader);
501   _dbus_message_loader_unref (loader);
502
503   len = _dbus_string_get_length (data);
504   for (i = 0; i < len; i++)
505     {
506       DBusString *buffer;
507
508       _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
509       if (!_dbus_string_append_byte (buffer,
510                                      _dbus_string_get_byte (data, i)))
511         goto failed;
512       _dbus_message_loader_return_buffer (loader, buffer);
513     }
514
515   if (!check_loader_results (loader, expected_validity))
516     goto failed;
517
518   _dbus_message_loader_unref (loader);
519   loader = NULL;
520
521   /* Write the data all at once */
522
523   loader = _dbus_message_loader_new ();
524   if (loader == NULL)
525     goto failed;
526
527   {
528     DBusString *buffer;
529
530     _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
531     if (!_dbus_string_copy (data, 0, buffer,
532                             _dbus_string_get_length (buffer)))
533         goto failed;
534     _dbus_message_loader_return_buffer (loader, buffer);
535   }
536
537   if (!check_loader_results (loader, expected_validity))
538     goto failed;
539
540   _dbus_message_loader_unref (loader);
541   loader = NULL;
542
543   /* Write the data 2 bytes at a time */
544
545   loader = _dbus_message_loader_new ();
546   if (loader == NULL)
547     goto failed;
548
549   len = _dbus_string_get_length (data);
550   for (i = 0; i < len; i += 2)
551     {
552       DBusString *buffer;
553
554       _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
555       if (!_dbus_string_append_byte (buffer,
556                                      _dbus_string_get_byte (data, i)))
557         goto failed;
558
559       if ((i+1) < len)
560         {
561           if (!_dbus_string_append_byte (buffer,
562                                          _dbus_string_get_byte (data, i+1)))
563             goto failed;
564         }
565
566       _dbus_message_loader_return_buffer (loader, buffer);
567     }
568
569   if (!check_loader_results (loader, expected_validity))
570     goto failed;
571
572   _dbus_message_loader_unref (loader);
573   loader = NULL;
574
575   retval = TRUE;
576
577  failed:
578
579   if (loader)
580     _dbus_message_loader_unref (loader);
581
582   return retval;
583 }
584
585 static dbus_bool_t
586 process_test_subdir (const DBusString          *test_base_dir,
587                      const char                *subdir,
588                      DBusValidity               expected_validity,
589                      DBusForeachMessageFileFunc function,
590                      void                      *user_data)
591 {
592   DBusString test_directory;
593   DBusString filename;
594   DBusDirIter *dir;
595   dbus_bool_t retval;
596   DBusError error = DBUS_ERROR_INIT;
597
598   retval = FALSE;
599   dir = NULL;
600
601   if (!_dbus_string_init (&test_directory))
602     _dbus_assert_not_reached ("didn't allocate test_directory");
603
604   _dbus_string_init_const (&filename, subdir);
605
606   if (!_dbus_string_copy (test_base_dir, 0,
607                           &test_directory, 0))
608     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
609
610   if (!_dbus_concat_dir_and_file (&test_directory, &filename))
611     _dbus_assert_not_reached ("couldn't allocate full path");
612
613   _dbus_string_free (&filename);
614   if (!_dbus_string_init (&filename))
615     _dbus_assert_not_reached ("didn't allocate filename string");
616
617   dir = _dbus_directory_open (&test_directory, &error);
618   if (dir == NULL)
619     {
620       _dbus_warn ("Could not open %s: %s",
621                   _dbus_string_get_const_data (&test_directory),
622                   error.message);
623       dbus_error_free (&error);
624       goto failed;
625     }
626
627   printf ("Testing %s:\n", subdir);
628
629  next:
630   while (_dbus_directory_get_next_file (dir, &filename, &error))
631     {
632       DBusString full_path;
633
634       if (!_dbus_string_init (&full_path))
635         _dbus_assert_not_reached ("couldn't init string");
636
637       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
638         _dbus_assert_not_reached ("couldn't copy dir to full_path");
639
640       if (!_dbus_concat_dir_and_file (&full_path, &filename))
641         _dbus_assert_not_reached ("couldn't concat file to dir");
642
643       if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
644         ;
645       else
646         {
647           if (_dbus_string_ends_with_c_str (&filename, ".message"))
648             {
649               printf ("SKIP: Could not load %s, message builder language no longer supported\n",
650                       _dbus_string_get_const_data (&filename));
651             }
652           
653           _dbus_verbose ("Skipping non-.message file %s\n",
654                          _dbus_string_get_const_data (&filename));
655           _dbus_string_free (&full_path);
656           goto next;
657         }
658
659       printf ("    %s\n",
660               _dbus_string_get_const_data (&filename));
661
662       if (! (*function) (&full_path,
663                          expected_validity, user_data))
664         {
665           _dbus_string_free (&full_path);
666           goto failed;
667         }
668       else
669         _dbus_string_free (&full_path);
670     }
671
672   if (dbus_error_is_set (&error))
673     {
674       _dbus_warn ("Could not get next file in %s: %s",
675                   _dbus_string_get_const_data (&test_directory),
676                   error.message);
677       dbus_error_free (&error);
678       goto failed;
679     }
680
681   retval = TRUE;
682
683  failed:
684
685   if (dir)
686     _dbus_directory_close (dir);
687   _dbus_string_free (&test_directory);
688   _dbus_string_free (&filename);
689
690   return retval;
691 }
692
693 /**
694  * Runs the given function on every message file in the test suite.
695  * The function should return #FALSE on test failure or fatal error.
696  *
697  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
698  * @param func the function to run
699  * @param user_data data for function
700  * @returns #FALSE if there's a failure
701  */
702 dbus_bool_t
703 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
704                                                DBusForeachMessageFileFunc func,
705                                                void                      *user_data)
706 {
707   DBusString test_directory;
708   dbus_bool_t retval;
709
710   retval = FALSE;
711
712   _dbus_string_init_const (&test_directory, test_data_dir);
713   
714   if (!process_test_subdir (&test_directory, "valid-messages",
715                             DBUS_VALID, func, user_data))
716     goto failed;
717
718   check_memleaks ();
719   
720   if (!process_test_subdir (&test_directory, "invalid-messages",
721                             DBUS_INVALID_FOR_UNKNOWN_REASON, func, user_data))
722     goto failed;
723
724   check_memleaks ();
725   
726   if (!process_test_subdir (&test_directory, "incomplete-messages",
727                             DBUS_VALID_BUT_INCOMPLETE, func, user_data))
728     goto failed;
729
730   check_memleaks ();
731   
732   retval = TRUE;
733   
734  failed:
735
736   _dbus_string_free (&test_directory);
737
738   return retval;
739 }
740
741 #if 0
742 #define GET_AND_CHECK(iter, typename, literal)                                  \
743   do {                                                                          \
744     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
745       _dbus_assert_not_reached ("got wrong argument type from message iter");   \
746     dbus_message_iter_get_basic (&iter, &v_##typename);                         \
747     if (v_##typename != literal)                                                \
748       _dbus_assert_not_reached ("got wrong value from message iter");           \
749   } while (0)
750
751 #define GET_AND_CHECK_STRCMP(iter, typename, literal)                           \
752   do {                                                                          \
753     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
754       _dbus_assert_not_reached ("got wrong argument type from message iter");   \
755     dbus_message_iter_get_basic (&iter, &v_##typename);                         \
756     if (strcmp (v_##typename, literal) != 0)                                    \
757       _dbus_assert_not_reached ("got wrong value from message iter");           \
758   } while (0)
759
760 #define GET_AND_CHECK_AND_NEXT(iter, typename, literal)         \
761   do {                                                          \
762     GET_AND_CHECK(iter, typename, literal);                     \
763     if (!dbus_message_iter_next (&iter))                        \
764       _dbus_assert_not_reached ("failed to move iter to next"); \
765   } while (0)
766
767 #define GET_AND_CHECK_STRCMP_AND_NEXT(iter, typename, literal)  \
768   do {                                                          \
769     GET_AND_CHECK_STRCMP(iter, typename, literal);              \
770     if (!dbus_message_iter_next (&iter))                        \
771       _dbus_assert_not_reached ("failed to move iter to next"); \
772   } while (0)
773
774 static void
775 message_iter_test (DBusMessage *message)
776 {
777   DBusMessageIter iter, array, array2;
778   const char *v_STRING;
779   double v_DOUBLE;
780   dbus_int16_t v_INT16;
781   dbus_uint16_t v_UINT16;
782   dbus_int32_t v_INT32;
783   dbus_uint32_t v_UINT32;
784   dbus_int64_t v_INT64;
785   dbus_uint64_t v_UINT64;
786   unsigned char v_BYTE;
787   dbus_bool_t v_BOOLEAN;
788
789   const dbus_int32_t *our_int_array;
790   int len;
791
792   dbus_message_iter_init (message, &iter);
793
794   GET_AND_CHECK_STRCMP_AND_NEXT (iter, STRING, "Test string");
795   GET_AND_CHECK_AND_NEXT (iter, INT32, -0x12345678);
796   GET_AND_CHECK_AND_NEXT (iter, UINT32, 0xedd1e);
797   GET_AND_CHECK_AND_NEXT (iter, DOUBLE, 3.14159);
798
799   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
800     _dbus_assert_not_reached ("Argument type not an array");
801
802   if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_DOUBLE)
803     _dbus_assert_not_reached ("Array type not double");
804
805   dbus_message_iter_recurse (&iter, &array);
806
807   GET_AND_CHECK_AND_NEXT (array, DOUBLE, 1.5);
808   GET_AND_CHECK (array, DOUBLE, 2.5);
809
810   if (dbus_message_iter_next (&array))
811     _dbus_assert_not_reached ("Didn't reach end of array");
812
813   if (!dbus_message_iter_next (&iter))
814     _dbus_assert_not_reached ("Reached end of arguments");
815
816   GET_AND_CHECK_AND_NEXT (iter, BYTE, 0xF0);
817
818   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
819     _dbus_assert_not_reached ("no array");
820
821   if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_INT32)
822     _dbus_assert_not_reached ("Array type not int32");
823
824   /* Empty array */
825   dbus_message_iter_recurse (&iter, &array);
826
827   if (dbus_message_iter_next (&array))
828     _dbus_assert_not_reached ("Didn't reach end of array");
829
830   if (!dbus_message_iter_next (&iter))
831     _dbus_assert_not_reached ("Reached end of arguments");
832
833   GET_AND_CHECK (iter, BYTE, 0xF0);
834
835   if (dbus_message_iter_next (&iter))
836     _dbus_assert_not_reached ("Didn't reach end of arguments");
837 }
838 #endif
839
840 static void
841 verify_test_message (DBusMessage *message)
842 {
843   DBusMessageIter iter;
844   DBusError error = DBUS_ERROR_INIT;
845   dbus_int16_t our_int16;
846   dbus_uint16_t our_uint16;
847   dbus_int32_t our_int;
848   dbus_uint32_t our_uint;
849   const char *our_str;
850   double our_double;
851   double v_DOUBLE;
852   dbus_bool_t our_bool;
853   unsigned char our_byte_1, our_byte_2;
854   const dbus_uint32_t *our_uint32_array = (void*)0xdeadbeef;
855   int our_uint32_array_len;
856   dbus_int32_t *our_int32_array = (void*)0xdeadbeef;
857   int our_int32_array_len;
858   dbus_int64_t our_int64;
859   dbus_uint64_t our_uint64;
860   dbus_int64_t *our_uint64_array = (void*)0xdeadbeef;
861   int our_uint64_array_len;
862   const dbus_int64_t *our_int64_array = (void*)0xdeadbeef;
863   int our_int64_array_len;
864   const double *our_double_array = (void*)0xdeadbeef;
865   int our_double_array_len;
866   const unsigned char *our_byte_array = (void*)0xdeadbeef;
867   int our_byte_array_len;
868   const dbus_bool_t *our_boolean_array = (void*)0xdeadbeef;
869   int our_boolean_array_len;
870   char **our_string_array;
871   int our_string_array_len;
872
873   dbus_message_iter_init (message, &iter);
874
875   if (!dbus_message_iter_get_args (&iter, &error,
876                                    DBUS_TYPE_INT16, &our_int16,
877                                    DBUS_TYPE_UINT16, &our_uint16,
878                                    DBUS_TYPE_INT32, &our_int,
879                                    DBUS_TYPE_UINT32, &our_uint,
880                                    DBUS_TYPE_INT64, &our_int64,
881                                    DBUS_TYPE_UINT64, &our_uint64,
882                                    DBUS_TYPE_STRING, &our_str,
883                                    DBUS_TYPE_DOUBLE, &our_double,
884                                    DBUS_TYPE_BOOLEAN, &our_bool,
885                                    DBUS_TYPE_BYTE, &our_byte_1,
886                                    DBUS_TYPE_BYTE, &our_byte_2,
887                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
888                                    &our_uint32_array, &our_uint32_array_len,
889                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
890                                    &our_int32_array, &our_int32_array_len,
891                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
892                                    &our_uint64_array, &our_uint64_array_len,
893                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
894                                    &our_int64_array, &our_int64_array_len,
895                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
896                                    &our_double_array, &our_double_array_len,
897                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
898                                    &our_byte_array, &our_byte_array_len,
899                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
900                                    &our_boolean_array, &our_boolean_array_len,
901                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
902                                    &our_string_array, &our_string_array_len,
903                                    0))
904     {
905       _dbus_warn ("error: %s - %s", error.name,
906                   (error.message != NULL) ? error.message : "no message");
907       _dbus_assert_not_reached ("Could not get arguments");
908     }
909
910   if (our_int16 != -0x123)
911     _dbus_assert_not_reached ("16-bit integers differ!");
912
913   if (our_uint16 != 0x123)
914     _dbus_assert_not_reached ("16-bit uints differ!");
915   
916   if (our_int != -0x12345678)
917     _dbus_assert_not_reached ("integers differ!");
918
919   if (our_uint != 0x12300042)
920     _dbus_assert_not_reached ("uints differ!");
921
922   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
923     _dbus_assert_not_reached ("64-bit integers differ!");
924   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
925     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
926
927   v_DOUBLE = 3.14159;
928   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double, v_DOUBLE))
929     _dbus_assert_not_reached ("doubles differ!");
930
931   if (strcmp (our_str, "Test string") != 0)
932     _dbus_assert_not_reached ("strings differ!");
933
934   if (!our_bool)
935     _dbus_assert_not_reached ("booleans differ");
936
937   if (our_byte_1 != 42)
938     _dbus_assert_not_reached ("bytes differ!");
939
940   if (our_byte_2 != 24)
941     _dbus_assert_not_reached ("bytes differ!");
942
943   if (our_uint32_array_len != 4 ||
944       our_uint32_array[0] != 0x12345678 ||
945       our_uint32_array[1] != 0x23456781 ||
946       our_uint32_array[2] != 0x34567812 ||
947       our_uint32_array[3] != 0x45678123)
948     _dbus_assert_not_reached ("uint array differs");
949
950   if (our_int32_array_len != 4 ||
951       our_int32_array[0] != 0x12345678 ||
952       our_int32_array[1] != -0x23456781 ||
953       our_int32_array[2] != 0x34567812 ||
954       our_int32_array[3] != -0x45678123)
955     _dbus_assert_not_reached ("int array differs");
956
957   if (our_uint64_array_len != 4 ||
958       our_uint64_array[0] != 0x12345678 ||
959       our_uint64_array[1] != 0x23456781 ||
960       our_uint64_array[2] != 0x34567812 ||
961       our_uint64_array[3] != 0x45678123)
962     _dbus_assert_not_reached ("uint64 array differs");
963
964   if (our_int64_array_len != 4 ||
965       our_int64_array[0] != 0x12345678 ||
966       our_int64_array[1] != -0x23456781 ||
967       our_int64_array[2] != 0x34567812 ||
968       our_int64_array[3] != -0x45678123)
969     _dbus_assert_not_reached ("int64 array differs");
970
971   if (our_double_array_len != 3)
972     _dbus_assert_not_reached ("double array had wrong length");
973
974   /* On all IEEE machines (i.e. everything sane) exact equality
975    * should be preserved over the wire
976    */
977   v_DOUBLE = 0.1234;
978   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[0], v_DOUBLE))
979     _dbus_assert_not_reached ("double array had wrong values");
980   v_DOUBLE = 9876.54321;
981   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[1], v_DOUBLE))
982     _dbus_assert_not_reached ("double array had wrong values");
983   v_DOUBLE = -300.0;
984   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[2], v_DOUBLE))
985     _dbus_assert_not_reached ("double array had wrong values");
986
987   if (our_byte_array_len != 4)
988     _dbus_assert_not_reached ("byte array had wrong length");
989
990   if (our_byte_array[0] != 'a' ||
991       our_byte_array[1] != 'b' ||
992       our_byte_array[2] != 'c' ||
993       our_byte_array[3] != 234)
994     _dbus_assert_not_reached ("byte array had wrong values");
995
996   if (our_boolean_array_len != 5)
997     _dbus_assert_not_reached ("bool array had wrong length");
998
999   if (our_boolean_array[0] != TRUE ||
1000       our_boolean_array[1] != FALSE ||
1001       our_boolean_array[2] != TRUE ||
1002       our_boolean_array[3] != TRUE ||
1003       our_boolean_array[4] != FALSE)
1004     _dbus_assert_not_reached ("bool array had wrong values");
1005
1006   if (our_string_array_len != 4)
1007     _dbus_assert_not_reached ("string array was wrong length");
1008
1009   if (strcmp (our_string_array[0], "Foo") != 0 ||
1010       strcmp (our_string_array[1], "bar") != 0 ||
1011       strcmp (our_string_array[2], "") != 0 ||
1012       strcmp (our_string_array[3], "woo woo woo woo") != 0)
1013     _dbus_assert_not_reached ("string array had wrong values");
1014
1015   dbus_free_string_array (our_string_array);
1016   
1017   if (dbus_message_iter_next (&iter))
1018     _dbus_assert_not_reached ("Didn't reach end of arguments");
1019 }
1020
1021 static void
1022 verify_test_message_args_ignored (DBusMessage *message)
1023 {
1024   DBusMessageIter iter;
1025   DBusError error = DBUS_ERROR_INIT;
1026   dbus_uint32_t our_uint;
1027   DBusInitialFDs *initial_fds;
1028
1029   initial_fds = _dbus_check_fdleaks_enter ();
1030
1031   /* parse with empty signature: "" */
1032   dbus_message_iter_init (message, &iter);
1033   if (!dbus_message_iter_get_args (&iter, &error,
1034                                    DBUS_TYPE_INVALID))
1035     {
1036       _dbus_warn ("error: %s - %s", error.name,
1037                      (error.message != NULL) ? error.message : "no message");
1038     }
1039   else
1040     {
1041       _dbus_assert (!dbus_error_is_set (&error));
1042       _dbus_verbose ("arguments ignored.\n");
1043     }
1044
1045   /* parse with shorter signature: "u" */
1046   dbus_message_iter_init (message, &iter);
1047   if (!dbus_message_iter_get_args (&iter, &error,
1048                                    DBUS_TYPE_UINT32, &our_uint,
1049                                    DBUS_TYPE_INVALID))
1050     {
1051       _dbus_warn ("error: %s - %s", error.name,
1052                      (error.message != NULL) ? error.message : "no message");
1053     }
1054   else
1055     {
1056       _dbus_assert (!dbus_error_is_set (&error));
1057       _dbus_verbose ("arguments ignored.\n");
1058     }
1059
1060   _dbus_check_fdleaks_leave (initial_fds);
1061 }
1062
1063 static void
1064 verify_test_message_memleak (DBusMessage *message)
1065 {
1066   DBusMessageIter iter;
1067   DBusError error = DBUS_ERROR_INIT;
1068   dbus_uint32_t our_uint1;
1069   dbus_uint32_t our_uint2;
1070   dbus_uint32_t our_uint3;
1071   char **our_string_array1;
1072   int our_string_array_len1;
1073   char **our_string_array2;
1074   int our_string_array_len2;
1075 #ifdef HAVE_UNIX_FD_PASSING
1076   int our_unix_fd1;
1077   int our_unix_fd2;
1078 #endif
1079   DBusInitialFDs *initial_fds;
1080
1081   initial_fds = _dbus_check_fdleaks_enter ();
1082
1083   /* parse with wrong signature: "uashuu" */
1084   dbus_error_free (&error);
1085   dbus_message_iter_init (message, &iter);
1086   if (!dbus_message_iter_get_args (&iter, &error,
1087                                    DBUS_TYPE_UINT32, &our_uint1,
1088                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
1089                                    &our_string_array1, &our_string_array_len1,
1090 #ifdef HAVE_UNIX_FD_PASSING
1091                                    DBUS_TYPE_UNIX_FD, &our_unix_fd1,
1092 #endif
1093                                    DBUS_TYPE_UINT32, &our_uint2,
1094                                    DBUS_TYPE_UINT32, &our_uint3,
1095                                    DBUS_TYPE_INVALID))
1096     {
1097       _dbus_verbose ("expected error: %s - %s\n", error.name,
1098                      (error.message != NULL) ? error.message : "no message");
1099       /* ensure array of string and unix fd not leaked */
1100       _dbus_assert (our_string_array1 == NULL);
1101 #ifdef HAVE_UNIX_FD_PASSING
1102       _dbus_assert (our_unix_fd1 == -1);
1103 #endif
1104     }
1105   else
1106     {
1107       _dbus_warn ("error: parse with wrong signature: 'uashuu'.");
1108     }
1109
1110   /* parse with wrong signature: "uashuashu" */
1111   dbus_message_iter_init (message, &iter);
1112   dbus_error_free (&error);
1113   if (!dbus_message_iter_get_args (&iter, &error,
1114                                    DBUS_TYPE_UINT32, &our_uint1,
1115                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
1116                                    &our_string_array1, &our_string_array_len1,
1117 #ifdef HAVE_UNIX_FD_PASSING
1118                                    DBUS_TYPE_UNIX_FD, &our_unix_fd1,
1119 #endif
1120                                    DBUS_TYPE_UINT32, &our_uint2,
1121                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
1122                                    &our_string_array2, &our_string_array_len2,
1123 #ifdef HAVE_UNIX_FD_PASSING
1124                                    DBUS_TYPE_UNIX_FD, &our_unix_fd2,
1125 #endif
1126                                    DBUS_TYPE_UINT32, &our_uint3,
1127                                    DBUS_TYPE_INVALID))
1128     {
1129       _dbus_verbose ("expected error: %s - %s\n", error.name,
1130                      (error.message != NULL) ? error.message : "no message");
1131       /* ensure array of string and unix fd not leaked */
1132       _dbus_assert (our_string_array1 == NULL);
1133       _dbus_assert (our_string_array2 == NULL);
1134 #ifdef HAVE_UNIX_FD_PASSING
1135       _dbus_assert (our_unix_fd1 == -1);
1136       _dbus_assert (our_unix_fd2 == -1);
1137 #endif
1138     }
1139   else
1140     {
1141       _dbus_warn ("error: parse with wrong signature: 'uashuashu'.");
1142     }
1143
1144   /* parse with correct signature: "uashuash" */
1145   dbus_message_iter_init (message, &iter);
1146   dbus_error_free (&error);
1147   if (!dbus_message_iter_get_args (&iter, &error,
1148                                    DBUS_TYPE_UINT32, &our_uint1,
1149                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
1150                                    &our_string_array1, &our_string_array_len1,
1151 #ifdef HAVE_UNIX_FD_PASSING
1152                                    DBUS_TYPE_UNIX_FD, &our_unix_fd1,
1153 #endif
1154                                    DBUS_TYPE_UINT32, &our_uint2,
1155                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
1156                                    &our_string_array2, &our_string_array_len2,
1157 #ifdef HAVE_UNIX_FD_PASSING
1158                                    DBUS_TYPE_UNIX_FD, &our_unix_fd2,
1159 #endif
1160                                    DBUS_TYPE_INVALID))
1161     {
1162       _dbus_warn ("error: %s - %s", error.name,
1163                   (error.message != NULL) ? error.message : "no message");
1164       _dbus_assert_not_reached ("Could not get arguments");
1165     }
1166   else
1167     {
1168       dbus_free_string_array (our_string_array1);
1169       dbus_free_string_array (our_string_array2);
1170 #ifdef HAVE_UNIX_FD_PASSING
1171       _dbus_close (our_unix_fd1, &error);
1172       _dbus_close (our_unix_fd2, &error);
1173 #endif
1174     }
1175   _dbus_check_fdleaks_leave (initial_fds);
1176 }
1177
1178 /**
1179  * @ingroup DBusMessageInternals
1180  * Unit test for DBusMessage.
1181  *
1182  * @returns #TRUE on success.
1183  */
1184 dbus_bool_t
1185 _dbus_message_test (const char *test_data_dir)
1186 {
1187   DBusMessage *message, *message_without_unix_fds;
1188   DBusMessageLoader *loader;
1189   int i;
1190   const char *data;
1191   DBusMessage *copy;
1192   const char *name1;
1193   const char *name2;
1194   const dbus_uint32_t our_uint32_array[] =
1195     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
1196   const dbus_int32_t our_int32_array[] =
1197     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
1198   const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array;
1199   const dbus_int32_t *v_ARRAY_INT32 = our_int32_array;
1200   const dbus_uint64_t our_uint64_array[] =
1201     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
1202   const dbus_int64_t our_int64_array[] =
1203     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
1204   const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array;
1205   const dbus_int64_t *v_ARRAY_INT64 = our_int64_array;
1206   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
1207   const char *our_string_array1[] = { "foo", "Bar", "", "Woo woo Woo woo" };
1208   const char **v_ARRAY_STRING = our_string_array;
1209   const char **v1_ARRAY_STRING = our_string_array1;
1210   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
1211   const double *v_ARRAY_DOUBLE = our_double_array;
1212   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
1213   const unsigned char *v_ARRAY_BYTE = our_byte_array;
1214   const dbus_bool_t our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
1215   const dbus_bool_t *v_ARRAY_BOOLEAN = our_boolean_array;
1216   char sig[64];
1217   const char *s;
1218   const char *v_STRING;
1219   double v_DOUBLE;
1220   dbus_int16_t v_INT16;
1221   dbus_uint16_t v_UINT16;
1222   dbus_int32_t v_INT32;
1223   dbus_uint32_t v_UINT32;
1224   dbus_uint32_t v1_UINT32;
1225   dbus_int64_t v_INT64;
1226   dbus_uint64_t v_UINT64;
1227   unsigned char v_BYTE;
1228   unsigned char v2_BYTE;
1229   dbus_bool_t v_BOOLEAN;
1230   DBusMessageIter iter, array_iter, struct_iter;
1231 #ifdef HAVE_UNIX_FD_PASSING
1232   int v_UNIX_FD;
1233   int v1_UNIX_FD;
1234 #endif
1235   char **decomposed;
1236   DBusInitialFDs *initial_fds;
1237   dbus_bool_t ok;
1238   char basic_types[] = DBUS_TYPE_BYTE_AS_STRING \
1239                        DBUS_TYPE_BOOLEAN_AS_STRING \
1240                        DBUS_TYPE_INT16_AS_STRING \
1241                        DBUS_TYPE_INT32_AS_STRING \
1242                        DBUS_TYPE_INT64_AS_STRING \
1243                        DBUS_TYPE_UINT16_AS_STRING \
1244                        DBUS_TYPE_UINT32_AS_STRING \
1245                        DBUS_TYPE_UINT64_AS_STRING \
1246                        DBUS_TYPE_DOUBLE_AS_STRING \
1247                        DBUS_TYPE_STRING_AS_STRING;
1248
1249   initial_fds = _dbus_check_fdleaks_enter ();
1250
1251   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
1252                                           "/org/freedesktop/TestPath",
1253                                           "Foo.TestInterface",
1254                                           "TestMethod");
1255   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
1256   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
1257                                              "TestMethod"));
1258   _dbus_assert (strcmp (dbus_message_get_path (message),
1259                         "/org/freedesktop/TestPath") == 0);
1260   dbus_message_set_serial (message, 1234);
1261
1262   /* string length including nul byte not a multiple of 4 */
1263   if (!dbus_message_set_sender (message, "org.foo.bar1"))
1264     _dbus_assert_not_reached ("out of memory");
1265
1266   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
1267   dbus_message_set_reply_serial (message, 5678);
1268
1269   _dbus_verbose_bytes_of_string (&message->header.data, 0,
1270                                  _dbus_string_get_length (&message->header.data));
1271   _dbus_verbose_bytes_of_string (&message->body, 0,
1272                                  _dbus_string_get_length (&message->body));
1273
1274   if (!dbus_message_set_sender (message, NULL))
1275     _dbus_assert_not_reached ("out of memory");
1276
1277
1278   _dbus_verbose_bytes_of_string (&message->header.data, 0,
1279                                  _dbus_string_get_length (&message->header.data));
1280   _dbus_verbose_bytes_of_string (&message->body, 0,
1281                                  _dbus_string_get_length (&message->body));
1282
1283
1284   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
1285   _dbus_assert (dbus_message_get_serial (message) == 1234);
1286   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
1287   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
1288
1289   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
1290   dbus_message_set_no_reply (message, TRUE);
1291   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
1292   dbus_message_set_no_reply (message, FALSE);
1293   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
1294
1295   /* Set/get some header fields */
1296
1297   if (!dbus_message_set_path (message, "/foo"))
1298     _dbus_assert_not_reached ("out of memory");
1299   _dbus_assert (strcmp (dbus_message_get_path (message),
1300                         "/foo") == 0);
1301
1302   if (!dbus_message_set_interface (message, "org.Foo"))
1303     _dbus_assert_not_reached ("out of memory");
1304   _dbus_assert (strcmp (dbus_message_get_interface (message),
1305                         "org.Foo") == 0);
1306
1307   if (!dbus_message_set_member (message, "Bar"))
1308     _dbus_assert_not_reached ("out of memory");
1309   _dbus_assert (strcmp (dbus_message_get_member (message),
1310                         "Bar") == 0);
1311
1312   /* Set/get them with longer values */
1313   if (!dbus_message_set_path (message, "/foo/bar"))
1314     _dbus_assert_not_reached ("out of memory");
1315   _dbus_assert (strcmp (dbus_message_get_path (message),
1316                         "/foo/bar") == 0);
1317
1318   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
1319     _dbus_assert_not_reached ("out of memory");
1320   _dbus_assert (strcmp (dbus_message_get_interface (message),
1321                         "org.Foo.Bar") == 0);
1322
1323   if (!dbus_message_set_member (message, "BarFoo"))
1324     _dbus_assert_not_reached ("out of memory");
1325   _dbus_assert (strcmp (dbus_message_get_member (message),
1326                         "BarFoo") == 0);
1327
1328   /* Realloc shorter again */
1329
1330   if (!dbus_message_set_path (message, "/foo"))
1331     _dbus_assert_not_reached ("out of memory");
1332   _dbus_assert (strcmp (dbus_message_get_path (message),
1333                         "/foo") == 0);
1334
1335   if (!dbus_message_set_interface (message, "org.Foo"))
1336     _dbus_assert_not_reached ("out of memory");
1337   _dbus_assert (strcmp (dbus_message_get_interface (message),
1338                         "org.Foo") == 0);
1339
1340   if (!dbus_message_set_member (message, "Bar"))
1341     _dbus_assert_not_reached ("out of memory");
1342   _dbus_assert (strcmp (dbus_message_get_member (message),
1343                         "Bar") == 0);
1344
1345   /* Path decomposing */
1346   dbus_message_set_path (message, NULL);
1347   dbus_message_get_path_decomposed (message, &decomposed);
1348   _dbus_assert (decomposed == NULL);
1349   dbus_free_string_array (decomposed);
1350
1351   dbus_message_set_path (message, "/");
1352   dbus_message_get_path_decomposed (message, &decomposed);
1353   _dbus_assert (decomposed != NULL);
1354   _dbus_assert (decomposed[0] == NULL);
1355   dbus_free_string_array (decomposed);
1356
1357   dbus_message_set_path (message, "/a/b");
1358   dbus_message_get_path_decomposed (message, &decomposed);
1359   _dbus_assert (decomposed != NULL);
1360   _dbus_assert (strcmp (decomposed[0], "a") == 0);
1361   _dbus_assert (strcmp (decomposed[1], "b") == 0);
1362   _dbus_assert (decomposed[2] == NULL);
1363   dbus_free_string_array (decomposed);
1364
1365   dbus_message_set_path (message, "/spam/eggs");
1366   dbus_message_get_path_decomposed (message, &decomposed);
1367   _dbus_assert (decomposed != NULL);
1368   _dbus_assert (strcmp (decomposed[0], "spam") == 0);
1369   _dbus_assert (strcmp (decomposed[1], "eggs") == 0);
1370   _dbus_assert (decomposed[2] == NULL);
1371   dbus_free_string_array (decomposed);
1372
1373   dbus_message_unref (message);
1374
1375   /* Test the vararg functions */
1376   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
1377                                           "/org/freedesktop/TestPath",
1378                                           "Foo.TestInterface",
1379                                           "TestMethod");
1380   dbus_message_set_serial (message, 1);
1381   dbus_message_set_reply_serial (message, 5678);
1382
1383   v_INT16 = -0x123;
1384   v_UINT16 = 0x123;
1385   v_INT32 = -0x12345678;
1386   v_UINT32 = 0x12300042;
1387   v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd);
1388   v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd);
1389   v_STRING = "Test string";
1390   v_DOUBLE = 3.14159;
1391   v_BOOLEAN = TRUE;
1392   v_BYTE = 42;
1393   v2_BYTE = 24;
1394 #ifdef HAVE_UNIX_FD_PASSING
1395   v_UNIX_FD = 1;
1396   v1_UNIX_FD = 2;
1397 #endif
1398
1399   dbus_message_append_args (message,
1400                             DBUS_TYPE_INT16, &v_INT16,
1401                             DBUS_TYPE_UINT16, &v_UINT16,
1402                             DBUS_TYPE_INT32, &v_INT32,
1403                             DBUS_TYPE_UINT32, &v_UINT32,
1404                             DBUS_TYPE_INT64, &v_INT64,
1405                             DBUS_TYPE_UINT64, &v_UINT64,
1406                             DBUS_TYPE_STRING, &v_STRING,
1407                             DBUS_TYPE_DOUBLE, &v_DOUBLE,
1408                             DBUS_TYPE_BOOLEAN, &v_BOOLEAN,
1409                             DBUS_TYPE_BYTE, &v_BYTE,
1410                             DBUS_TYPE_BYTE, &v2_BYTE,
1411                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32,
1412                             _DBUS_N_ELEMENTS (our_uint32_array),
1413                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32,
1414                             _DBUS_N_ELEMENTS (our_int32_array),
1415                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64,
1416                             _DBUS_N_ELEMENTS (our_uint64_array),
1417                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64,
1418                             _DBUS_N_ELEMENTS (our_int64_array),
1419                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE,
1420                             _DBUS_N_ELEMENTS (our_double_array),
1421                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE,
1422                             _DBUS_N_ELEMENTS (our_byte_array),
1423                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN,
1424                             _DBUS_N_ELEMENTS (our_boolean_array),
1425                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING,
1426                             _DBUS_N_ELEMENTS (our_string_array),
1427
1428                             DBUS_TYPE_INVALID);
1429
1430   i = 0;
1431   sig[i++] = DBUS_TYPE_INT16;
1432   sig[i++] = DBUS_TYPE_UINT16;
1433   sig[i++] = DBUS_TYPE_INT32;
1434   sig[i++] = DBUS_TYPE_UINT32;
1435   sig[i++] = DBUS_TYPE_INT64;
1436   sig[i++] = DBUS_TYPE_UINT64;
1437   sig[i++] = DBUS_TYPE_STRING;
1438   sig[i++] = DBUS_TYPE_DOUBLE;
1439   sig[i++] = DBUS_TYPE_BOOLEAN;
1440   sig[i++] = DBUS_TYPE_BYTE;
1441   sig[i++] = DBUS_TYPE_BYTE;
1442   sig[i++] = DBUS_TYPE_ARRAY;
1443   sig[i++] = DBUS_TYPE_UINT32;
1444   sig[i++] = DBUS_TYPE_ARRAY;
1445   sig[i++] = DBUS_TYPE_INT32;
1446   sig[i++] = DBUS_TYPE_ARRAY;
1447   sig[i++] = DBUS_TYPE_UINT64;
1448   sig[i++] = DBUS_TYPE_ARRAY;
1449   sig[i++] = DBUS_TYPE_INT64;
1450   sig[i++] = DBUS_TYPE_ARRAY;
1451   sig[i++] = DBUS_TYPE_DOUBLE;
1452   sig[i++] = DBUS_TYPE_ARRAY;
1453   sig[i++] = DBUS_TYPE_BYTE;
1454   sig[i++] = DBUS_TYPE_ARRAY;
1455   sig[i++] = DBUS_TYPE_BOOLEAN;
1456   sig[i++] = DBUS_TYPE_ARRAY;
1457   sig[i++] = DBUS_TYPE_STRING;
1458
1459   message_without_unix_fds = dbus_message_copy(message);
1460   _dbus_assert(message_without_unix_fds);
1461 #ifdef HAVE_UNIX_FD_PASSING
1462   dbus_message_append_args (message,
1463                             DBUS_TYPE_UNIX_FD, &v_UNIX_FD,
1464                             DBUS_TYPE_INVALID);
1465   sig[i++] = DBUS_TYPE_UNIX_FD;
1466 #endif
1467   sig[i++] = DBUS_TYPE_INVALID;
1468
1469   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
1470
1471   _dbus_verbose ("HEADER\n");
1472   _dbus_verbose_bytes_of_string (&message->header.data, 0,
1473                                  _dbus_string_get_length (&message->header.data));
1474   _dbus_verbose ("BODY\n");
1475   _dbus_verbose_bytes_of_string (&message->body, 0,
1476                                  _dbus_string_get_length (&message->body));
1477
1478   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
1479                  sig, dbus_message_get_signature (message));
1480
1481   s = dbus_message_get_signature (message);
1482
1483   _dbus_assert (dbus_message_has_signature (message, sig));
1484   _dbus_assert (strcmp (s, sig) == 0);
1485
1486   verify_test_message (message);
1487
1488   copy = dbus_message_copy (message);
1489
1490   _dbus_assert (dbus_message_get_reply_serial (message) ==
1491                 dbus_message_get_reply_serial (copy));
1492   _dbus_assert (message->header.padding == copy->header.padding);
1493
1494   _dbus_assert (_dbus_string_get_length (&message->header.data) ==
1495                 _dbus_string_get_length (&copy->header.data));
1496
1497   _dbus_assert (_dbus_string_get_length (&message->body) ==
1498                 _dbus_string_get_length (&copy->body));
1499
1500   verify_test_message (copy);
1501
1502   name1 = dbus_message_get_interface (message);
1503   name2 = dbus_message_get_interface (copy);
1504
1505   _dbus_assert (strcmp (name1, name2) == 0);
1506
1507   name1 = dbus_message_get_member (message);
1508   name2 = dbus_message_get_member (copy);
1509
1510   _dbus_assert (strcmp (name1, name2) == 0);
1511
1512   dbus_message_unref (copy);
1513
1514   /* Message loader test */
1515   dbus_message_lock (message);
1516   loader = _dbus_message_loader_new ();
1517   
1518   /* check ref/unref */
1519   _dbus_message_loader_ref (loader);
1520   _dbus_message_loader_unref (loader);
1521
1522   /* Write the header data one byte at a time */
1523   data = _dbus_string_get_const_data (&message->header.data);
1524   for (i = 0; i < _dbus_string_get_length (&message->header.data); i++)
1525     {
1526       DBusString *buffer;
1527
1528       _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
1529       _dbus_string_append_byte (buffer, data[i]);
1530       _dbus_message_loader_return_buffer (loader, buffer);
1531     }
1532
1533   /* Write the body data one byte at a time */
1534   data = _dbus_string_get_const_data (&message->body);
1535   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
1536     {
1537       DBusString *buffer;
1538
1539       _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
1540       _dbus_string_append_byte (buffer, data[i]);
1541       _dbus_message_loader_return_buffer (loader, buffer);
1542     }
1543
1544 #ifdef HAVE_UNIX_FD_PASSING
1545   {
1546     int *unix_fds;
1547     unsigned n_unix_fds;
1548     /* Write unix fd */
1549     _dbus_message_loader_get_unix_fds(loader, &unix_fds, &n_unix_fds);
1550     _dbus_assert(n_unix_fds > 0);
1551     _dbus_assert(message->n_unix_fds == 1);
1552     unix_fds[0] = _dbus_dup(message->unix_fds[0], NULL);
1553     _dbus_assert(unix_fds[0] >= 0);
1554     _dbus_message_loader_return_unix_fds(loader, unix_fds, 1);
1555   }
1556 #endif
1557
1558   dbus_message_unref (message);
1559
1560   /* Now pop back the message */
1561   if (!_dbus_message_loader_queue_messages (loader))
1562     _dbus_assert_not_reached ("no memory to queue messages");
1563
1564   if (_dbus_message_loader_get_is_corrupted (loader))
1565     _dbus_assert_not_reached ("message loader corrupted");
1566
1567   message = _dbus_message_loader_pop_message (loader);
1568   if (!message)
1569     _dbus_assert_not_reached ("received a NULL message");
1570
1571   if (dbus_message_get_reply_serial (message) != 5678)
1572     _dbus_assert_not_reached ("reply serial fields differ");
1573
1574   dbus_message_unref (message);
1575
1576   /* ovveride the serial, since it was reset by dbus_message_copy() */
1577   dbus_message_set_serial(message_without_unix_fds, 8901);
1578
1579   dbus_message_lock (message_without_unix_fds);
1580
1581   verify_test_message (message_without_unix_fds);
1582
1583     {
1584       /* Marshal and demarshal the message. */
1585
1586       DBusMessage *message2;
1587       DBusError error = DBUS_ERROR_INIT;
1588       char *marshalled = NULL;
1589       int len = 0;
1590       char garbage_header[DBUS_MINIMUM_HEADER_SIZE] = "xxx";
1591
1592       if (!dbus_message_marshal (message_without_unix_fds, &marshalled, &len))
1593         _dbus_assert_not_reached ("failed to marshal message");
1594
1595       _dbus_assert (len != 0);
1596       _dbus_assert (marshalled != NULL);
1597
1598       _dbus_assert (dbus_message_demarshal_bytes_needed (marshalled, len) == len);
1599       message2 = dbus_message_demarshal (marshalled, len, &error);
1600
1601       _dbus_assert (message2 != NULL);
1602       _dbus_assert (!dbus_error_is_set (&error));
1603       verify_test_message (message2);
1604
1605       dbus_message_unref (message2);
1606       dbus_free (marshalled);
1607
1608       /* Demarshal invalid message. */
1609
1610       message2 = dbus_message_demarshal ("invalid", 7, &error);
1611       _dbus_assert (message2 == NULL);
1612       _dbus_assert (dbus_error_is_set (&error));
1613       dbus_error_free (&error);
1614
1615       /* Demarshal invalid (empty) message. */
1616
1617       message2 = dbus_message_demarshal ("", 0, &error);
1618       _dbus_assert (message2 == NULL);
1619       _dbus_assert (dbus_error_is_set (&error));
1620       dbus_error_free (&error);
1621
1622       /* Bytes needed to demarshal empty message: 0 (more) */
1623
1624       _dbus_assert (dbus_message_demarshal_bytes_needed ("", 0) == 0);
1625       
1626       /* Bytes needed to demarshal invalid message: -1 (error). */
1627
1628       _dbus_assert (dbus_message_demarshal_bytes_needed (garbage_header, DBUS_MINIMUM_HEADER_SIZE) == -1);
1629     }
1630
1631   dbus_message_unref (message_without_unix_fds);
1632   _dbus_message_loader_unref (loader);
1633
1634   check_memleaks ();
1635   _dbus_check_fdleaks_leave (initial_fds);
1636   initial_fds = _dbus_check_fdleaks_enter ();
1637
1638   /* Test enumeration of array elements */
1639   for (i = strlen (basic_types) - 1; i > 0; i--)
1640     {
1641       DBusBasicValue val;
1642       int some;
1643       char* signature = _dbus_strdup ("?");
1644
1645       signature[0] = basic_types[i];
1646       s = "SomeThingToSay";
1647       memset (&val, '\0', sizeof (val));
1648
1649       message = dbus_message_new_method_call ("de.ende.test",
1650         "/de/ende/test", "de.ende.Test", "ArtistName");
1651       _dbus_assert (message != NULL);
1652       dbus_message_iter_init_append (message, &iter);
1653       dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1654                                         signature, &array_iter);
1655       for (some = 0; some < 3; some++)
1656         {
1657           if (basic_types[i] == DBUS_TYPE_STRING)
1658             dbus_message_iter_append_basic (&array_iter, DBUS_TYPE_STRING, &s);
1659           else
1660             dbus_message_iter_append_basic (&array_iter, basic_types[i], &val);
1661         }
1662       dbus_message_iter_close_container (&iter, &array_iter);
1663       dbus_message_iter_init (message, &iter);
1664       _dbus_assert (dbus_message_iter_get_element_count (&iter) == some);
1665       dbus_message_unref (message);
1666       dbus_free (signature);
1667     }
1668   /* Array of structs */
1669   message = dbus_message_new_method_call ("de.ende.test",
1670       "/de/ende/test", "de.ende.Test", "ArtistName");
1671   _dbus_assert (message != NULL);
1672   dbus_message_iter_init_append (message, &iter);
1673   dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1674                                     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1675                                     DBUS_TYPE_STRING_AS_STRING
1676                                     DBUS_STRUCT_END_CHAR_AS_STRING, &array_iter);
1677   dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT,
1678                                     NULL, &struct_iter);
1679   s = "SpamAndEggs";
1680   dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &s);
1681   dbus_message_iter_close_container (&array_iter, &struct_iter);
1682   dbus_message_iter_close_container (&iter, &array_iter);
1683   dbus_message_iter_init (message, &iter);
1684   _dbus_assert (dbus_message_iter_get_element_count (&iter) == 1);
1685   dbus_message_unref (message);
1686   check_memleaks ();
1687
1688   /* Check that we can abandon a container */
1689   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
1690                                           "/org/freedesktop/TestPath",
1691                                           "Foo.TestInterface",
1692                                           "Method");
1693
1694   dbus_message_iter_init_append (message, &iter);
1695
1696   ok = dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1697                                                   (DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1698                                                    DBUS_TYPE_STRING_AS_STRING
1699                                                    DBUS_TYPE_STRING_AS_STRING
1700                                                    DBUS_STRUCT_END_CHAR_AS_STRING),
1701                           &array_iter);
1702   _dbus_assert (ok);
1703   ok = dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT,
1704                           NULL, &struct_iter);
1705   _dbus_assert (ok);
1706   s = "peaches";
1707   ok = dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &s);
1708   _dbus_assert (ok);
1709
1710   /* uh-oh, error, try and unwind */
1711
1712   dbus_message_iter_abandon_container (&array_iter, &struct_iter);
1713   dbus_message_iter_abandon_container (&array_iter, &iter);
1714
1715   dbus_message_unref (message);
1716
1717   /* Check we should not leak array of string or unix fd, fd.o#21259 */
1718   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
1719                                           "/org/freedesktop/TestPath",
1720                                           "Foo.TestInterface",
1721                                           "Method");
1722
1723   /* signature "uashuash" */
1724   dbus_message_append_args (message,
1725                             DBUS_TYPE_UINT32, &v_UINT32,
1726                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING,
1727                             _DBUS_N_ELEMENTS (our_string_array),
1728 #ifdef HAVE_UNIX_FD_PASSING
1729                             DBUS_TYPE_UNIX_FD, &v_UNIX_FD,
1730 #endif
1731                             DBUS_TYPE_UINT32, &v1_UINT32,
1732                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v1_ARRAY_STRING,
1733                             _DBUS_N_ELEMENTS (our_string_array1),
1734 #ifdef HAVE_UNIX_FD_PASSING
1735                             DBUS_TYPE_UNIX_FD, &v1_UNIX_FD,
1736 #endif
1737
1738                             DBUS_TYPE_INVALID);
1739
1740   i = 0;
1741   sig[i++] = DBUS_TYPE_UINT32;
1742   sig[i++] = DBUS_TYPE_ARRAY;
1743   sig[i++] = DBUS_TYPE_STRING;
1744 #ifdef HAVE_UNIX_FD_PASSING
1745   sig[i++] = DBUS_TYPE_UNIX_FD;
1746 #endif
1747   sig[i++] = DBUS_TYPE_UINT32;
1748   sig[i++] = DBUS_TYPE_ARRAY;
1749   sig[i++] = DBUS_TYPE_STRING;
1750 #ifdef HAVE_UNIX_FD_PASSING
1751   sig[i++] = DBUS_TYPE_UNIX_FD;
1752 #endif
1753   sig[i++] = DBUS_TYPE_INVALID;
1754
1755   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
1756
1757   verify_test_message_args_ignored (message);
1758   verify_test_message_memleak (message);
1759
1760   dbus_message_unref (message);
1761
1762   /* Load all the sample messages from the message factory */
1763   {
1764     DBusMessageDataIter diter;
1765     DBusMessageData mdata;
1766     int count;
1767
1768     reset_validities_seen ();
1769     
1770     count = 0;
1771     _dbus_message_data_iter_init (&diter);
1772     
1773     while (_dbus_message_data_iter_get_and_next (&diter,
1774                                                  &mdata))
1775       {
1776         if (!dbus_internal_do_not_use_try_message_data (&mdata.data,
1777                                                         mdata.expected_validity))
1778           {
1779             _dbus_warn ("expected validity %d and did not get it",
1780                         mdata.expected_validity);
1781             _dbus_assert_not_reached ("message data failed");
1782           }
1783
1784         _dbus_message_data_free (&mdata);
1785
1786         count += 1;
1787       }
1788
1789     printf ("%d sample messages tested\n", count);
1790
1791     print_validities_seen (FALSE);
1792     print_validities_seen (TRUE);
1793   }
1794
1795   check_memleaks ();
1796   _dbus_check_fdleaks_leave (initial_fds);
1797
1798   /* Now load every message in test_data_dir if we have one */
1799   if (test_data_dir == NULL)
1800     return TRUE;
1801
1802   initial_fds = _dbus_check_fdleaks_enter ();
1803
1804   if (!dbus_internal_do_not_use_foreach_message_file (test_data_dir,
1805                                                         (DBusForeachMessageFileFunc)
1806                                                         dbus_internal_do_not_use_try_message_file,
1807                                                         NULL))
1808     _dbus_assert_not_reached ("foreach_message_file test failed");
1809
1810   _dbus_check_fdleaks_leave (initial_fds);
1811
1812   return TRUE;
1813 }
1814
1815 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */