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