Merge branch 'dbus-1.2'
[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_BUILD_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_BUILD_TESTS */
80
81 /** @} */
82
83 #ifdef DBUS_BUILD_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\n",
136                   _dbus_get_malloc_blocks_outstanding (), __FILE__);
137       _dbus_assert_not_reached ("memleaks");
138     }
139 }
140
141 void
142 _dbus_check_fdleaks(void)
143 {
144
145 #ifdef __linux__
146
147   DIR *d;
148
149   /* This works on Linux only */
150
151   if ((d = opendir("/proc/self/fd")))
152     {
153       struct dirent *de;
154
155       while ((de = readdir(d)))
156         {
157           long l;
158           char *e = NULL;
159           int fd;
160
161           if (de->d_name[0] == '.')
162             continue;
163
164           errno = 0;
165           l = strtol(de->d_name, &e, 10);
166           _dbus_assert(errno == 0 && e && !*e);
167
168           fd = (int) l;
169
170           if (fd < 3)
171             continue;
172
173           if (fd == dirfd(d))
174             continue;
175
176           _dbus_warn("file descriptor %i leaked in %s.\n", fd, __FILE__);
177           _dbus_assert_not_reached("fdleaks");
178         }
179
180       closedir(d);
181     }
182 #endif
183 }
184
185 static dbus_bool_t
186 check_have_valid_message (DBusMessageLoader *loader)
187 {
188   DBusMessage *message;
189   dbus_bool_t retval;
190
191   message = NULL;
192   retval = FALSE;
193
194   if (_dbus_message_loader_get_is_corrupted (loader))
195     {
196       _dbus_warn ("loader corrupted on message that was expected to be valid; invalid reason %d\n",
197                   loader->corruption_reason);
198       goto failed;
199     }
200
201   message = _dbus_message_loader_pop_message (loader);
202   if (message == NULL)
203     {
204       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
205       goto failed;
206     }
207
208   if (_dbus_string_get_length (&loader->data) > 0)
209     {
210       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
211       goto failed;
212     }
213
214 #if 0
215   /* FIXME */
216   /* Verify that we're able to properly deal with the message.
217    * For example, this would detect improper handling of messages
218    * in nonstandard byte order.
219    */
220   if (!check_message_handling (message))
221     goto failed;
222 #endif
223
224   record_validity_seen (DBUS_VALID);
225   
226   retval = TRUE;
227
228  failed:
229   if (message)
230     dbus_message_unref (message);
231
232   return retval;
233 }
234
235 static dbus_bool_t
236 check_invalid_message (DBusMessageLoader *loader,
237                        DBusValidity       expected_validity)
238 {
239   dbus_bool_t retval;
240
241   retval = FALSE;
242
243   if (!_dbus_message_loader_get_is_corrupted (loader))
244     {
245       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
246       goto failed;
247     }
248
249   record_validity_seen (loader->corruption_reason);
250   
251   if (expected_validity != DBUS_INVALID_FOR_UNKNOWN_REASON &&
252       loader->corruption_reason != expected_validity)
253     {
254       _dbus_warn ("expected message to be corrupted for reason %d and was corrupted for %d instead\n",
255                   expected_validity, loader->corruption_reason);
256       goto failed;
257     }
258
259   retval = TRUE;
260
261  failed:
262   return retval;
263 }
264
265 static dbus_bool_t
266 check_incomplete_message (DBusMessageLoader *loader)
267 {
268   DBusMessage *message;
269   dbus_bool_t retval;
270
271   message = NULL;
272   retval = FALSE;
273
274   if (_dbus_message_loader_get_is_corrupted (loader))
275     {
276       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete), corruption reason %d\n",
277                   loader->corruption_reason);
278       goto failed;
279     }
280
281   message = _dbus_message_loader_pop_message (loader);
282   if (message != NULL)
283     {
284       _dbus_warn ("loaded message that was expected to be incomplete\n");
285       goto failed;
286     }
287
288   record_validity_seen (DBUS_VALID_BUT_INCOMPLETE);
289   retval = TRUE;
290
291  failed:
292   if (message)
293     dbus_message_unref (message);
294   return retval;
295 }
296
297 static dbus_bool_t
298 check_loader_results (DBusMessageLoader      *loader,
299                       DBusValidity            expected_validity)
300 {
301   if (!_dbus_message_loader_queue_messages (loader))
302     _dbus_assert_not_reached ("no memory to queue messages");
303
304   if (expected_validity == DBUS_VALID)
305     return check_have_valid_message (loader);
306   else if (expected_validity == DBUS_VALID_BUT_INCOMPLETE)
307     return check_incomplete_message (loader);
308   else if (expected_validity == DBUS_VALIDITY_UNKNOWN)
309     {
310       /* here we just know we didn't segfault and that was the
311        * only test. Also, we record that we got coverage
312        * for the validity reason.
313        */
314       if (_dbus_message_loader_get_is_corrupted (loader))
315         record_validity_seen (loader->corruption_reason);
316       
317       return TRUE;
318     }
319   else
320     return check_invalid_message (loader, expected_validity);
321 }
322
323 /**
324  * Loads the message in the given message file.
325  *
326  * @param filename filename to load
327  * @param data string to load message into
328  * @returns #TRUE if the message was loaded
329  */
330 dbus_bool_t
331 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
332                                             DBusString          *data)
333 {
334   dbus_bool_t retval;
335   DBusError error = DBUS_ERROR_INIT;
336
337   retval = FALSE;
338
339   _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
340   if (!_dbus_file_get_contents (data, filename, &error))
341     {
342       _dbus_warn ("Could not load message file %s: %s\n",
343                   _dbus_string_get_const_data (filename),
344                   error.message);
345       dbus_error_free (&error);
346       goto failed;
347     }
348
349   retval = TRUE;
350
351  failed:
352
353   return retval;
354 }
355
356 /**
357  * Tries loading the message in the given message file
358  * and verifies that DBusMessageLoader can handle it.
359  *
360  * @param filename filename to load
361  * @param expected_validity what the message has to be like to return #TRUE
362  * @returns #TRUE if the message has the expected validity
363  */
364 dbus_bool_t
365 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
366                                            DBusValidity         expected_validity)
367 {
368   DBusString data;
369   dbus_bool_t retval;
370
371   retval = FALSE;
372
373   if (!_dbus_string_init (&data))
374     _dbus_assert_not_reached ("could not allocate string\n");
375
376   if (!dbus_internal_do_not_use_load_message_file (filename, &data))
377     goto failed;
378
379   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
380
381  failed:
382
383   if (!retval)
384     {
385       if (_dbus_string_get_length (&data) > 0)
386         _dbus_verbose_bytes_of_string (&data, 0,
387                                        _dbus_string_get_length (&data));
388
389       _dbus_warn ("Failed message loader test on %s\n",
390                   _dbus_string_get_const_data (filename));
391     }
392
393   _dbus_string_free (&data);
394
395   return retval;
396 }
397
398 /**
399  * Tries loading the given message data.
400  *
401  *
402  * @param data the message data
403  * @param expected_validity what the message has to be like to return #TRUE
404  * @returns #TRUE if the message has the expected validity
405  */
406 dbus_bool_t
407 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
408                                            DBusValidity         expected_validity)
409 {
410   DBusMessageLoader *loader;
411   dbus_bool_t retval;
412   int len;
413   int i;
414
415   loader = NULL;
416   retval = FALSE;
417
418   /* Write the data one byte at a time */
419
420   loader = _dbus_message_loader_new ();
421
422   /* check some trivial loader functions */
423   _dbus_message_loader_ref (loader);
424   _dbus_message_loader_unref (loader);
425   _dbus_message_loader_get_max_message_size (loader);
426
427   len = _dbus_string_get_length (data);
428   for (i = 0; i < len; i++)
429     {
430       DBusString *buffer;
431
432       _dbus_message_loader_get_buffer (loader, &buffer);
433       _dbus_string_append_byte (buffer,
434                                 _dbus_string_get_byte (data, i));
435       _dbus_message_loader_return_buffer (loader, buffer, 1);
436     }
437
438   if (!check_loader_results (loader, expected_validity))
439     goto failed;
440
441   _dbus_message_loader_unref (loader);
442   loader = NULL;
443
444   /* Write the data all at once */
445
446   loader = _dbus_message_loader_new ();
447
448   {
449     DBusString *buffer;
450
451     _dbus_message_loader_get_buffer (loader, &buffer);
452     _dbus_string_copy (data, 0, buffer,
453                        _dbus_string_get_length (buffer));
454     _dbus_message_loader_return_buffer (loader, buffer, 1);
455   }
456
457   if (!check_loader_results (loader, expected_validity))
458     goto failed;
459
460   _dbus_message_loader_unref (loader);
461   loader = NULL;
462
463   /* Write the data 2 bytes at a time */
464
465   loader = _dbus_message_loader_new ();
466
467   len = _dbus_string_get_length (data);
468   for (i = 0; i < len; i += 2)
469     {
470       DBusString *buffer;
471
472       _dbus_message_loader_get_buffer (loader, &buffer);
473       _dbus_string_append_byte (buffer,
474                                 _dbus_string_get_byte (data, i));
475       if ((i+1) < len)
476         _dbus_string_append_byte (buffer,
477                                   _dbus_string_get_byte (data, i+1));
478       _dbus_message_loader_return_buffer (loader, buffer, 1);
479     }
480
481   if (!check_loader_results (loader, expected_validity))
482     goto failed;
483
484   _dbus_message_loader_unref (loader);
485   loader = NULL;
486
487   retval = TRUE;
488
489  failed:
490
491   if (loader)
492     _dbus_message_loader_unref (loader);
493
494   return retval;
495 }
496
497 static dbus_bool_t
498 process_test_subdir (const DBusString          *test_base_dir,
499                      const char                *subdir,
500                      DBusValidity               expected_validity,
501                      DBusForeachMessageFileFunc function,
502                      void                      *user_data)
503 {
504   DBusString test_directory;
505   DBusString filename;
506   DBusDirIter *dir;
507   dbus_bool_t retval;
508   DBusError error = DBUS_ERROR_INIT;
509
510   retval = FALSE;
511   dir = NULL;
512
513   if (!_dbus_string_init (&test_directory))
514     _dbus_assert_not_reached ("didn't allocate test_directory\n");
515
516   _dbus_string_init_const (&filename, subdir);
517
518   if (!_dbus_string_copy (test_base_dir, 0,
519                           &test_directory, 0))
520     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
521
522   if (!_dbus_concat_dir_and_file (&test_directory, &filename))
523     _dbus_assert_not_reached ("couldn't allocate full path");
524
525   _dbus_string_free (&filename);
526   if (!_dbus_string_init (&filename))
527     _dbus_assert_not_reached ("didn't allocate filename string\n");
528
529   dir = _dbus_directory_open (&test_directory, &error);
530   if (dir == NULL)
531     {
532       _dbus_warn ("Could not open %s: %s\n",
533                   _dbus_string_get_const_data (&test_directory),
534                   error.message);
535       dbus_error_free (&error);
536       goto failed;
537     }
538
539   printf ("Testing %s:\n", subdir);
540
541  next:
542   while (_dbus_directory_get_next_file (dir, &filename, &error))
543     {
544       DBusString full_path;
545
546       if (!_dbus_string_init (&full_path))
547         _dbus_assert_not_reached ("couldn't init string");
548
549       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
550         _dbus_assert_not_reached ("couldn't copy dir to full_path");
551
552       if (!_dbus_concat_dir_and_file (&full_path, &filename))
553         _dbus_assert_not_reached ("couldn't concat file to dir");
554
555       if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
556         ;
557       else
558         {
559           if (_dbus_string_ends_with_c_str (&filename, ".message"))
560             {
561               _dbus_warn ("Could not load %s, message builder language no longer supported\n",
562                           _dbus_string_get_const_data (&filename));
563             }
564           
565           _dbus_verbose ("Skipping non-.message file %s\n",
566                          _dbus_string_get_const_data (&filename));
567           _dbus_string_free (&full_path);
568           goto next;
569         }
570
571       printf ("    %s\n",
572               _dbus_string_get_const_data (&filename));
573
574       if (! (*function) (&full_path,
575                          expected_validity, user_data))
576         {
577           _dbus_string_free (&full_path);
578           goto failed;
579         }
580       else
581         _dbus_string_free (&full_path);
582     }
583
584   if (dbus_error_is_set (&error))
585     {
586       _dbus_warn ("Could not get next file in %s: %s\n",
587                   _dbus_string_get_const_data (&test_directory),
588                   error.message);
589       dbus_error_free (&error);
590       goto failed;
591     }
592
593   retval = TRUE;
594
595  failed:
596
597   if (dir)
598     _dbus_directory_close (dir);
599   _dbus_string_free (&test_directory);
600   _dbus_string_free (&filename);
601
602   return retval;
603 }
604
605 /**
606  * Runs the given function on every message file in the test suite.
607  * The function should return #FALSE on test failure or fatal error.
608  *
609  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
610  * @param func the function to run
611  * @param user_data data for function
612  * @returns #FALSE if there's a failure
613  */
614 dbus_bool_t
615 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
616                                                DBusForeachMessageFileFunc func,
617                                                void                      *user_data)
618 {
619   DBusString test_directory;
620   dbus_bool_t retval;
621
622   retval = FALSE;
623
624   _dbus_string_init_const (&test_directory, test_data_dir);
625   
626   if (!process_test_subdir (&test_directory, "valid-messages",
627                             DBUS_VALID, func, user_data))
628     goto failed;
629
630   check_memleaks ();
631   
632   if (!process_test_subdir (&test_directory, "invalid-messages",
633                             DBUS_INVALID_FOR_UNKNOWN_REASON, func, user_data))
634     goto failed;
635
636   check_memleaks ();
637   
638   if (!process_test_subdir (&test_directory, "incomplete-messages",
639                             DBUS_VALID_BUT_INCOMPLETE, func, user_data))
640     goto failed;
641
642   check_memleaks ();
643   
644   retval = TRUE;
645   
646  failed:
647
648   _dbus_string_free (&test_directory);
649
650   return retval;
651 }
652
653 #if 0
654 #define GET_AND_CHECK(iter, typename, literal)                                  \
655   do {                                                                          \
656     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
657       _dbus_assert_not_reached ("got wrong argument type from message iter");   \
658     dbus_message_iter_get_basic (&iter, &v_##typename);                         \
659     if (v_##typename != literal)                                                \
660       _dbus_assert_not_reached ("got wrong value from message iter");           \
661   } while (0)
662
663 #define GET_AND_CHECK_STRCMP(iter, typename, literal)                           \
664   do {                                                                          \
665     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
666       _dbus_assert_not_reached ("got wrong argument type from message iter");   \
667     dbus_message_iter_get_basic (&iter, &v_##typename);                         \
668     if (strcmp (v_##typename, literal) != 0)                                    \
669       _dbus_assert_not_reached ("got wrong value from message iter");           \
670   } while (0)
671
672 #define GET_AND_CHECK_AND_NEXT(iter, typename, literal)         \
673   do {                                                          \
674     GET_AND_CHECK(iter, typename, literal);                     \
675     if (!dbus_message_iter_next (&iter))                        \
676       _dbus_assert_not_reached ("failed to move iter to next"); \
677   } while (0)
678
679 #define GET_AND_CHECK_STRCMP_AND_NEXT(iter, typename, literal)  \
680   do {                                                          \
681     GET_AND_CHECK_STRCMP(iter, typename, literal);              \
682     if (!dbus_message_iter_next (&iter))                        \
683       _dbus_assert_not_reached ("failed to move iter to next"); \
684   } while (0)
685
686 static void
687 message_iter_test (DBusMessage *message)
688 {
689   DBusMessageIter iter, array, array2;
690   const char *v_STRING;
691   double v_DOUBLE;
692   dbus_int16_t v_INT16;
693   dbus_uint16_t v_UINT16;
694   dbus_int32_t v_INT32;
695   dbus_uint32_t v_UINT32;
696 #ifdef DBUS_HAVE_INT64
697   dbus_int64_t v_INT64;
698   dbus_uint64_t v_UINT64;
699 #endif
700   unsigned char v_BYTE;
701   dbus_bool_t v_BOOLEAN;
702
703   const dbus_int32_t *our_int_array;
704   int len;
705
706   dbus_message_iter_init (message, &iter);
707
708   GET_AND_CHECK_STRCMP_AND_NEXT (iter, STRING, "Test string");
709   GET_AND_CHECK_AND_NEXT (iter, INT32, -0x12345678);
710   GET_AND_CHECK_AND_NEXT (iter, UINT32, 0xedd1e);
711   GET_AND_CHECK_AND_NEXT (iter, DOUBLE, 3.14159);
712
713   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
714     _dbus_assert_not_reached ("Argument type not an array");
715
716   if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_DOUBLE)
717     _dbus_assert_not_reached ("Array type not double");
718
719   dbus_message_iter_recurse (&iter, &array);
720
721   GET_AND_CHECK_AND_NEXT (array, DOUBLE, 1.5);
722   GET_AND_CHECK (array, DOUBLE, 2.5);
723
724   if (dbus_message_iter_next (&array))
725     _dbus_assert_not_reached ("Didn't reach end of array");
726
727   if (!dbus_message_iter_next (&iter))
728     _dbus_assert_not_reached ("Reached end of arguments");
729
730   GET_AND_CHECK_AND_NEXT (iter, BYTE, 0xF0);
731
732   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
733     _dbus_assert_not_reached ("no array");
734
735   if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_INT32)
736     _dbus_assert_not_reached ("Array type not int32");
737
738   /* Empty array */
739   dbus_message_iter_recurse (&iter, &array);
740
741   if (dbus_message_iter_next (&array))
742     _dbus_assert_not_reached ("Didn't reach end of array");
743
744   if (!dbus_message_iter_next (&iter))
745     _dbus_assert_not_reached ("Reached end of arguments");
746
747   GET_AND_CHECK (iter, BYTE, 0xF0);
748
749   if (dbus_message_iter_next (&iter))
750     _dbus_assert_not_reached ("Didn't reach end of arguments");
751 }
752 #endif
753
754 static void
755 verify_test_message (DBusMessage *message)
756 {
757   DBusMessageIter iter;
758   DBusError error = DBUS_ERROR_INIT;
759   dbus_int16_t our_int16;
760   dbus_uint16_t our_uint16;
761   dbus_int32_t our_int;
762   dbus_uint32_t our_uint;
763   const char *our_str;
764   double our_double;
765   double v_DOUBLE;
766   dbus_bool_t our_bool;
767   unsigned char our_byte_1, our_byte_2;
768   const dbus_uint32_t *our_uint32_array = (void*)0xdeadbeef;
769   int our_uint32_array_len;
770   dbus_int32_t *our_int32_array = (void*)0xdeadbeef;
771   int our_int32_array_len;
772 #ifdef DBUS_HAVE_INT64
773   dbus_int64_t our_int64;
774   dbus_uint64_t our_uint64;
775   dbus_int64_t *our_uint64_array = (void*)0xdeadbeef;
776   int our_uint64_array_len;
777   const dbus_int64_t *our_int64_array = (void*)0xdeadbeef;
778   int our_int64_array_len;
779 #endif
780   const double *our_double_array = (void*)0xdeadbeef;
781   int our_double_array_len;
782   const unsigned char *our_byte_array = (void*)0xdeadbeef;
783   int our_byte_array_len;
784   const dbus_bool_t *our_boolean_array = (void*)0xdeadbeef;
785   int our_boolean_array_len;
786   char **our_string_array;
787   int our_string_array_len;
788
789   dbus_message_iter_init (message, &iter);
790
791   if (!dbus_message_iter_get_args (&iter, &error,
792                                    DBUS_TYPE_INT16, &our_int16,
793                                    DBUS_TYPE_UINT16, &our_uint16,
794                                    DBUS_TYPE_INT32, &our_int,
795                                    DBUS_TYPE_UINT32, &our_uint,
796 #ifdef DBUS_HAVE_INT64
797                                    DBUS_TYPE_INT64, &our_int64,
798                                    DBUS_TYPE_UINT64, &our_uint64,
799 #endif
800                                    DBUS_TYPE_STRING, &our_str,
801                                    DBUS_TYPE_DOUBLE, &our_double,
802                                    DBUS_TYPE_BOOLEAN, &our_bool,
803                                    DBUS_TYPE_BYTE, &our_byte_1,
804                                    DBUS_TYPE_BYTE, &our_byte_2,
805                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
806                                    &our_uint32_array, &our_uint32_array_len,
807                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
808                                    &our_int32_array, &our_int32_array_len,
809 #ifdef DBUS_HAVE_INT64
810                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
811                                    &our_uint64_array, &our_uint64_array_len,
812                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
813                                    &our_int64_array, &our_int64_array_len,
814 #endif
815                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
816                                    &our_double_array, &our_double_array_len,
817                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
818                                    &our_byte_array, &our_byte_array_len,
819                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
820                                    &our_boolean_array, &our_boolean_array_len,
821                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
822                                    &our_string_array, &our_string_array_len,
823                                    0))
824     {
825       _dbus_warn ("error: %s - %s\n", error.name,
826                   (error.message != NULL) ? error.message : "no message");
827       _dbus_assert_not_reached ("Could not get arguments");
828     }
829
830   if (our_int16 != -0x123)
831     _dbus_assert_not_reached ("16-bit integers differ!");
832
833   if (our_uint16 != 0x123)
834     _dbus_assert_not_reached ("16-bit uints differ!");
835   
836   if (our_int != -0x12345678)
837     _dbus_assert_not_reached ("integers differ!");
838
839   if (our_uint != 0x12300042)
840     _dbus_assert_not_reached ("uints differ!");
841
842 #ifdef DBUS_HAVE_INT64
843   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
844     _dbus_assert_not_reached ("64-bit integers differ!");
845   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
846     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
847 #endif
848
849   v_DOUBLE = 3.14159;
850   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double, v_DOUBLE))
851     _dbus_assert_not_reached ("doubles differ!");
852
853   if (strcmp (our_str, "Test string") != 0)
854     _dbus_assert_not_reached ("strings differ!");
855
856   if (!our_bool)
857     _dbus_assert_not_reached ("booleans differ");
858
859   if (our_byte_1 != 42)
860     _dbus_assert_not_reached ("bytes differ!");
861
862   if (our_byte_2 != 24)
863     _dbus_assert_not_reached ("bytes differ!");
864
865   if (our_uint32_array_len != 4 ||
866       our_uint32_array[0] != 0x12345678 ||
867       our_uint32_array[1] != 0x23456781 ||
868       our_uint32_array[2] != 0x34567812 ||
869       our_uint32_array[3] != 0x45678123)
870     _dbus_assert_not_reached ("uint array differs");
871
872   if (our_int32_array_len != 4 ||
873       our_int32_array[0] != 0x12345678 ||
874       our_int32_array[1] != -0x23456781 ||
875       our_int32_array[2] != 0x34567812 ||
876       our_int32_array[3] != -0x45678123)
877     _dbus_assert_not_reached ("int array differs");
878
879 #ifdef DBUS_HAVE_INT64
880   if (our_uint64_array_len != 4 ||
881       our_uint64_array[0] != 0x12345678 ||
882       our_uint64_array[1] != 0x23456781 ||
883       our_uint64_array[2] != 0x34567812 ||
884       our_uint64_array[3] != 0x45678123)
885     _dbus_assert_not_reached ("uint64 array differs");
886
887   if (our_int64_array_len != 4 ||
888       our_int64_array[0] != 0x12345678 ||
889       our_int64_array[1] != -0x23456781 ||
890       our_int64_array[2] != 0x34567812 ||
891       our_int64_array[3] != -0x45678123)
892     _dbus_assert_not_reached ("int64 array differs");
893 #endif /* DBUS_HAVE_INT64 */
894
895   if (our_double_array_len != 3)
896     _dbus_assert_not_reached ("double array had wrong length");
897
898   /* On all IEEE machines (i.e. everything sane) exact equality
899    * should be preserved over the wire
900    */
901   v_DOUBLE = 0.1234;
902   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[0], v_DOUBLE))
903     _dbus_assert_not_reached ("double array had wrong values");
904   v_DOUBLE = 9876.54321;
905   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[1], v_DOUBLE))
906     _dbus_assert_not_reached ("double array had wrong values");
907   v_DOUBLE = -300.0;
908   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[2], v_DOUBLE))
909     _dbus_assert_not_reached ("double array had wrong values");
910
911   if (our_byte_array_len != 4)
912     _dbus_assert_not_reached ("byte array had wrong length");
913
914   if (our_byte_array[0] != 'a' ||
915       our_byte_array[1] != 'b' ||
916       our_byte_array[2] != 'c' ||
917       our_byte_array[3] != 234)
918     _dbus_assert_not_reached ("byte array had wrong values");
919
920   if (our_boolean_array_len != 5)
921     _dbus_assert_not_reached ("bool array had wrong length");
922
923   if (our_boolean_array[0] != TRUE ||
924       our_boolean_array[1] != FALSE ||
925       our_boolean_array[2] != TRUE ||
926       our_boolean_array[3] != TRUE ||
927       our_boolean_array[4] != FALSE)
928     _dbus_assert_not_reached ("bool array had wrong values");
929
930   if (our_string_array_len != 4)
931     _dbus_assert_not_reached ("string array was wrong length");
932
933   if (strcmp (our_string_array[0], "Foo") != 0 ||
934       strcmp (our_string_array[1], "bar") != 0 ||
935       strcmp (our_string_array[2], "") != 0 ||
936       strcmp (our_string_array[3], "woo woo woo woo") != 0)
937     _dbus_assert_not_reached ("string array had wrong values");
938
939   dbus_free_string_array (our_string_array);
940   
941   if (dbus_message_iter_next (&iter))
942     _dbus_assert_not_reached ("Didn't reach end of arguments");
943 }
944
945 /**
946  * @ingroup DBusMessageInternals
947  * Unit test for DBusMessage.
948  *
949  * @returns #TRUE on success.
950  */
951 dbus_bool_t
952 _dbus_message_test (const char *test_data_dir)
953 {
954   DBusMessage *message, *message_without_unix_fds;
955   DBusMessageLoader *loader;
956   int i;
957   const char *data;
958   DBusMessage *copy;
959   const char *name1;
960   const char *name2;
961   const dbus_uint32_t our_uint32_array[] =
962     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
963   const dbus_int32_t our_int32_array[] =
964     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
965   const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array;
966   const dbus_int32_t *v_ARRAY_INT32 = our_int32_array;
967 #ifdef DBUS_HAVE_INT64
968   const dbus_uint64_t our_uint64_array[] =
969     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
970   const dbus_int64_t our_int64_array[] =
971     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
972   const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array;
973   const dbus_int64_t *v_ARRAY_INT64 = our_int64_array;
974 #endif
975   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
976   const char **v_ARRAY_STRING = our_string_array;
977   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
978   const double *v_ARRAY_DOUBLE = our_double_array;
979   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
980   const unsigned char *v_ARRAY_BYTE = our_byte_array;
981   const dbus_bool_t our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
982   const dbus_bool_t *v_ARRAY_BOOLEAN = our_boolean_array;
983   char sig[64];
984   const char *s;
985   const char *v_STRING;
986   double v_DOUBLE;
987   dbus_int16_t v_INT16;
988   dbus_uint16_t v_UINT16;
989   dbus_int32_t v_INT32;
990   dbus_uint32_t v_UINT32;
991 #ifdef DBUS_HAVE_INT64
992   dbus_int64_t v_INT64;
993   dbus_uint64_t v_UINT64;
994 #endif
995   unsigned char v_BYTE;
996   unsigned char v2_BYTE;
997   dbus_bool_t v_BOOLEAN;
998   DBusMessageIter iter, array_iter, struct_iter;
999 #ifdef HAVE_UNIX_FD_PASSING
1000   int v_UNIX_FD;
1001 #endif
1002   char **decomposed;
1003
1004   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
1005                                           "/org/freedesktop/TestPath",
1006                                           "Foo.TestInterface",
1007                                           "TestMethod");
1008   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
1009   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
1010                                              "TestMethod"));
1011   _dbus_assert (strcmp (dbus_message_get_path (message),
1012                         "/org/freedesktop/TestPath") == 0);
1013   dbus_message_set_serial (message, 1234);
1014
1015   /* string length including nul byte not a multiple of 4 */
1016   if (!dbus_message_set_sender (message, "org.foo.bar1"))
1017     _dbus_assert_not_reached ("out of memory");
1018
1019   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
1020   dbus_message_set_reply_serial (message, 5678);
1021
1022   _dbus_verbose_bytes_of_string (&message->header.data, 0,
1023                                  _dbus_string_get_length (&message->header.data));
1024   _dbus_verbose_bytes_of_string (&message->body, 0,
1025                                  _dbus_string_get_length (&message->body));
1026
1027   if (!dbus_message_set_sender (message, NULL))
1028     _dbus_assert_not_reached ("out of memory");
1029
1030
1031   _dbus_verbose_bytes_of_string (&message->header.data, 0,
1032                                  _dbus_string_get_length (&message->header.data));
1033   _dbus_verbose_bytes_of_string (&message->body, 0,
1034                                  _dbus_string_get_length (&message->body));
1035
1036
1037   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
1038   _dbus_assert (dbus_message_get_serial (message) == 1234);
1039   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
1040   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
1041
1042   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
1043   dbus_message_set_no_reply (message, TRUE);
1044   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
1045   dbus_message_set_no_reply (message, FALSE);
1046   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
1047
1048   /* Set/get some header fields */
1049
1050   if (!dbus_message_set_path (message, "/foo"))
1051     _dbus_assert_not_reached ("out of memory");
1052   _dbus_assert (strcmp (dbus_message_get_path (message),
1053                         "/foo") == 0);
1054
1055   if (!dbus_message_set_interface (message, "org.Foo"))
1056     _dbus_assert_not_reached ("out of memory");
1057   _dbus_assert (strcmp (dbus_message_get_interface (message),
1058                         "org.Foo") == 0);
1059
1060   if (!dbus_message_set_member (message, "Bar"))
1061     _dbus_assert_not_reached ("out of memory");
1062   _dbus_assert (strcmp (dbus_message_get_member (message),
1063                         "Bar") == 0);
1064
1065   /* Set/get them with longer values */
1066   if (!dbus_message_set_path (message, "/foo/bar"))
1067     _dbus_assert_not_reached ("out of memory");
1068   _dbus_assert (strcmp (dbus_message_get_path (message),
1069                         "/foo/bar") == 0);
1070
1071   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
1072     _dbus_assert_not_reached ("out of memory");
1073   _dbus_assert (strcmp (dbus_message_get_interface (message),
1074                         "org.Foo.Bar") == 0);
1075
1076   if (!dbus_message_set_member (message, "BarFoo"))
1077     _dbus_assert_not_reached ("out of memory");
1078   _dbus_assert (strcmp (dbus_message_get_member (message),
1079                         "BarFoo") == 0);
1080
1081   /* Realloc shorter again */
1082
1083   if (!dbus_message_set_path (message, "/foo"))
1084     _dbus_assert_not_reached ("out of memory");
1085   _dbus_assert (strcmp (dbus_message_get_path (message),
1086                         "/foo") == 0);
1087
1088   if (!dbus_message_set_interface (message, "org.Foo"))
1089     _dbus_assert_not_reached ("out of memory");
1090   _dbus_assert (strcmp (dbus_message_get_interface (message),
1091                         "org.Foo") == 0);
1092
1093   if (!dbus_message_set_member (message, "Bar"))
1094     _dbus_assert_not_reached ("out of memory");
1095   _dbus_assert (strcmp (dbus_message_get_member (message),
1096                         "Bar") == 0);
1097
1098   /* Path decomposing */
1099   dbus_message_set_path (message, NULL);
1100   dbus_message_get_path_decomposed (message, &decomposed);
1101   _dbus_assert (decomposed == NULL);
1102   dbus_free_string_array (decomposed);
1103
1104   dbus_message_set_path (message, "/");
1105   dbus_message_get_path_decomposed (message, &decomposed);
1106   _dbus_assert (decomposed != NULL);
1107   _dbus_assert (decomposed[0] == NULL);
1108   dbus_free_string_array (decomposed);
1109
1110   dbus_message_set_path (message, "/a/b");
1111   dbus_message_get_path_decomposed (message, &decomposed);
1112   _dbus_assert (decomposed != NULL);
1113   _dbus_assert (strcmp (decomposed[0], "a") == 0);
1114   _dbus_assert (strcmp (decomposed[1], "b") == 0);
1115   _dbus_assert (decomposed[2] == NULL);
1116   dbus_free_string_array (decomposed);
1117
1118   dbus_message_set_path (message, "/spam/eggs");
1119   dbus_message_get_path_decomposed (message, &decomposed);
1120   _dbus_assert (decomposed != NULL);
1121   _dbus_assert (strcmp (decomposed[0], "spam") == 0);
1122   _dbus_assert (strcmp (decomposed[1], "eggs") == 0);
1123   _dbus_assert (decomposed[2] == NULL);
1124   dbus_free_string_array (decomposed);
1125
1126   dbus_message_unref (message);
1127
1128   /* Test the vararg functions */
1129   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
1130                                           "/org/freedesktop/TestPath",
1131                                           "Foo.TestInterface",
1132                                           "TestMethod");
1133   dbus_message_set_serial (message, 1);
1134   dbus_message_set_reply_serial (message, 5678);
1135
1136   v_INT16 = -0x123;
1137   v_UINT16 = 0x123;
1138   v_INT32 = -0x12345678;
1139   v_UINT32 = 0x12300042;
1140 #ifdef DBUS_HAVE_INT64
1141   v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd);
1142   v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd);
1143 #endif
1144   v_STRING = "Test string";
1145   v_DOUBLE = 3.14159;
1146   v_BOOLEAN = TRUE;
1147   v_BYTE = 42;
1148   v2_BYTE = 24;
1149 #ifdef HAVE_UNIX_FD_PASSING
1150   v_UNIX_FD = 1;
1151 #endif
1152
1153   dbus_message_append_args (message,
1154                             DBUS_TYPE_INT16, &v_INT16,
1155                             DBUS_TYPE_UINT16, &v_UINT16,
1156                             DBUS_TYPE_INT32, &v_INT32,
1157                             DBUS_TYPE_UINT32, &v_UINT32,
1158 #ifdef DBUS_HAVE_INT64
1159                             DBUS_TYPE_INT64, &v_INT64,
1160                             DBUS_TYPE_UINT64, &v_UINT64,
1161 #endif
1162                             DBUS_TYPE_STRING, &v_STRING,
1163                             DBUS_TYPE_DOUBLE, &v_DOUBLE,
1164                             DBUS_TYPE_BOOLEAN, &v_BOOLEAN,
1165                             DBUS_TYPE_BYTE, &v_BYTE,
1166                             DBUS_TYPE_BYTE, &v2_BYTE,
1167                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32,
1168                             _DBUS_N_ELEMENTS (our_uint32_array),
1169                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32,
1170                             _DBUS_N_ELEMENTS (our_int32_array),
1171 #ifdef DBUS_HAVE_INT64
1172                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64,
1173                             _DBUS_N_ELEMENTS (our_uint64_array),
1174                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64,
1175                             _DBUS_N_ELEMENTS (our_int64_array),
1176 #endif
1177                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE,
1178                             _DBUS_N_ELEMENTS (our_double_array),
1179                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE,
1180                             _DBUS_N_ELEMENTS (our_byte_array),
1181                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN,
1182                             _DBUS_N_ELEMENTS (our_boolean_array),
1183                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING,
1184                             _DBUS_N_ELEMENTS (our_string_array),
1185
1186                             DBUS_TYPE_INVALID);
1187
1188   i = 0;
1189   sig[i++] = DBUS_TYPE_INT16;
1190   sig[i++] = DBUS_TYPE_UINT16;
1191   sig[i++] = DBUS_TYPE_INT32;
1192   sig[i++] = DBUS_TYPE_UINT32;
1193 #ifdef DBUS_HAVE_INT64
1194   sig[i++] = DBUS_TYPE_INT64;
1195   sig[i++] = DBUS_TYPE_UINT64;
1196 #endif
1197   sig[i++] = DBUS_TYPE_STRING;
1198   sig[i++] = DBUS_TYPE_DOUBLE;
1199   sig[i++] = DBUS_TYPE_BOOLEAN;
1200   sig[i++] = DBUS_TYPE_BYTE;
1201   sig[i++] = DBUS_TYPE_BYTE;
1202   sig[i++] = DBUS_TYPE_ARRAY;
1203   sig[i++] = DBUS_TYPE_UINT32;
1204   sig[i++] = DBUS_TYPE_ARRAY;
1205   sig[i++] = DBUS_TYPE_INT32;
1206 #ifdef DBUS_HAVE_INT64
1207   sig[i++] = DBUS_TYPE_ARRAY;
1208   sig[i++] = DBUS_TYPE_UINT64;
1209   sig[i++] = DBUS_TYPE_ARRAY;
1210   sig[i++] = DBUS_TYPE_INT64;
1211 #endif
1212   sig[i++] = DBUS_TYPE_ARRAY;
1213   sig[i++] = DBUS_TYPE_DOUBLE;
1214   sig[i++] = DBUS_TYPE_ARRAY;
1215   sig[i++] = DBUS_TYPE_BYTE;
1216   sig[i++] = DBUS_TYPE_ARRAY;
1217   sig[i++] = DBUS_TYPE_BOOLEAN;
1218   sig[i++] = DBUS_TYPE_ARRAY;
1219   sig[i++] = DBUS_TYPE_STRING;
1220
1221   message_without_unix_fds = dbus_message_copy(message);
1222   _dbus_assert(message_without_unix_fds);
1223 #ifdef HAVE_UNIX_FD_PASSING
1224   dbus_message_append_args (message,
1225                             DBUS_TYPE_UNIX_FD, &v_UNIX_FD,
1226                             DBUS_TYPE_INVALID);
1227   sig[i++] = DBUS_TYPE_UNIX_FD;
1228 #endif
1229   sig[i++] = DBUS_TYPE_INVALID;
1230
1231   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
1232
1233   _dbus_verbose ("HEADER\n");
1234   _dbus_verbose_bytes_of_string (&message->header.data, 0,
1235                                  _dbus_string_get_length (&message->header.data));
1236   _dbus_verbose ("BODY\n");
1237   _dbus_verbose_bytes_of_string (&message->body, 0,
1238                                  _dbus_string_get_length (&message->body));
1239
1240   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
1241                  sig, dbus_message_get_signature (message));
1242
1243   s = dbus_message_get_signature (message);
1244
1245   _dbus_assert (dbus_message_has_signature (message, sig));
1246   _dbus_assert (strcmp (s, sig) == 0);
1247
1248   verify_test_message (message);
1249
1250   copy = dbus_message_copy (message);
1251
1252   _dbus_assert (dbus_message_get_reply_serial (message) ==
1253                 dbus_message_get_reply_serial (copy));
1254   _dbus_assert (message->header.padding == copy->header.padding);
1255
1256   _dbus_assert (_dbus_string_get_length (&message->header.data) ==
1257                 _dbus_string_get_length (&copy->header.data));
1258
1259   _dbus_assert (_dbus_string_get_length (&message->body) ==
1260                 _dbus_string_get_length (&copy->body));
1261
1262   verify_test_message (copy);
1263
1264   name1 = dbus_message_get_interface (message);
1265   name2 = dbus_message_get_interface (copy);
1266
1267   _dbus_assert (strcmp (name1, name2) == 0);
1268
1269   name1 = dbus_message_get_member (message);
1270   name2 = dbus_message_get_member (copy);
1271
1272   _dbus_assert (strcmp (name1, name2) == 0);
1273
1274   dbus_message_unref (copy);
1275
1276   /* Message loader test */
1277   dbus_message_lock (message);
1278   loader = _dbus_message_loader_new ();
1279   
1280   /* check ref/unref */
1281   _dbus_message_loader_ref (loader);
1282   _dbus_message_loader_unref (loader);
1283
1284   /* Write the header data one byte at a time */
1285   data = _dbus_string_get_const_data (&message->header.data);
1286   for (i = 0; i < _dbus_string_get_length (&message->header.data); i++)
1287     {
1288       DBusString *buffer;
1289
1290       _dbus_message_loader_get_buffer (loader, &buffer);
1291       _dbus_string_append_byte (buffer, data[i]);
1292       _dbus_message_loader_return_buffer (loader, buffer, 1);
1293     }
1294
1295   /* Write the body data one byte at a time */
1296   data = _dbus_string_get_const_data (&message->body);
1297   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
1298     {
1299       DBusString *buffer;
1300
1301       _dbus_message_loader_get_buffer (loader, &buffer);
1302       _dbus_string_append_byte (buffer, data[i]);
1303       _dbus_message_loader_return_buffer (loader, buffer, 1);
1304     }
1305
1306 #ifdef HAVE_UNIX_FD_PASSING
1307   {
1308     int *unix_fds;
1309     unsigned n_unix_fds;
1310     /* Write unix fd */
1311     _dbus_message_loader_get_unix_fds(loader, &unix_fds, &n_unix_fds);
1312     _dbus_assert(n_unix_fds > 0);
1313     _dbus_assert(message->n_unix_fds == 1);
1314     unix_fds[0] = _dbus_dup(message->unix_fds[0], NULL);
1315     _dbus_assert(unix_fds[0] >= 0);
1316     _dbus_message_loader_return_unix_fds(loader, unix_fds, 1);
1317   }
1318 #endif
1319
1320   dbus_message_unref (message);
1321
1322   /* Now pop back the message */
1323   if (!_dbus_message_loader_queue_messages (loader))
1324     _dbus_assert_not_reached ("no memory to queue messages");
1325
1326   if (_dbus_message_loader_get_is_corrupted (loader))
1327     _dbus_assert_not_reached ("message loader corrupted");
1328
1329   message = _dbus_message_loader_pop_message (loader);
1330   if (!message)
1331     _dbus_assert_not_reached ("received a NULL message");
1332
1333   if (dbus_message_get_reply_serial (message) != 5678)
1334     _dbus_assert_not_reached ("reply serial fields differ");
1335
1336   dbus_message_unref (message);
1337
1338   /* ovveride the serial, since it was reset by dbus_message_copy() */
1339   dbus_message_set_serial(message_without_unix_fds, 8901);
1340
1341   dbus_message_lock (message_without_unix_fds);
1342
1343   verify_test_message (message_without_unix_fds);
1344
1345     {
1346       /* Marshal and demarshal the message. */
1347
1348       DBusMessage *message2;
1349       DBusError error = DBUS_ERROR_INIT;
1350       char *marshalled = NULL;
1351       int len = 0;
1352       char garbage_header[DBUS_MINIMUM_HEADER_SIZE] = "xxx";
1353
1354       if (!dbus_message_marshal (message_without_unix_fds, &marshalled, &len))
1355         _dbus_assert_not_reached ("failed to marshal message");
1356
1357       _dbus_assert (len != 0);
1358       _dbus_assert (marshalled != NULL);
1359
1360       _dbus_assert (dbus_message_demarshal_bytes_needed (marshalled, len) == len);
1361       message2 = dbus_message_demarshal (marshalled, len, &error);
1362
1363       _dbus_assert (message2 != NULL);
1364       _dbus_assert (!dbus_error_is_set (&error));
1365       verify_test_message (message2);
1366
1367       dbus_message_unref (message2);
1368       dbus_free (marshalled);
1369
1370       /* Demarshal invalid message. */
1371
1372       message2 = dbus_message_demarshal ("invalid", 7, &error);
1373       _dbus_assert (message2 == NULL);
1374       _dbus_assert (dbus_error_is_set (&error));
1375       dbus_error_free (&error);
1376
1377       /* Demarshal invalid (empty) message. */
1378
1379       message2 = dbus_message_demarshal ("", 0, &error);
1380       _dbus_assert (message2 == NULL);
1381       _dbus_assert (dbus_error_is_set (&error));
1382       dbus_error_free (&error);
1383
1384       /* Bytes needed to demarshal empty message: 0 (more) */
1385
1386       _dbus_assert (dbus_message_demarshal_bytes_needed ("", 0) == 0);
1387       
1388       /* Bytes needed to demarshal invalid message: -1 (error). */
1389
1390       _dbus_assert (dbus_message_demarshal_bytes_needed (garbage_header, DBUS_MINIMUM_HEADER_SIZE) == -1);
1391     }
1392
1393   dbus_message_unref (message_without_unix_fds);
1394   _dbus_message_loader_unref (loader);
1395
1396   check_memleaks ();
1397   _dbus_check_fdleaks();
1398
1399   /* Check that we can abandon a container */
1400   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
1401                                           "/org/freedesktop/TestPath",
1402                                           "Foo.TestInterface",
1403                                           "Method");
1404
1405   dbus_message_iter_init_append (message, &iter);
1406
1407   _dbus_assert (dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1408                                                   (DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1409                                                    DBUS_TYPE_STRING_AS_STRING
1410                                                    DBUS_TYPE_STRING_AS_STRING
1411                                                    DBUS_STRUCT_END_CHAR_AS_STRING),
1412                                                   &array_iter));
1413   _dbus_assert (dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT,
1414                                                   NULL, &struct_iter));
1415
1416   s = "peaches";
1417   _dbus_assert (dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING,
1418                                                 &s));
1419
1420   /* uh-oh, error, try and unwind */
1421
1422   dbus_message_iter_abandon_container (&array_iter, &struct_iter);
1423   dbus_message_iter_abandon_container (&array_iter, &iter);
1424
1425   dbus_message_unref (message);
1426
1427   /* Load all the sample messages from the message factory */
1428   {
1429     DBusMessageDataIter diter;
1430     DBusMessageData mdata;
1431     int count;
1432
1433     reset_validities_seen ();
1434     
1435     count = 0;
1436     _dbus_message_data_iter_init (&diter);
1437     
1438     while (_dbus_message_data_iter_get_and_next (&diter,
1439                                                  &mdata))
1440       {
1441         if (!dbus_internal_do_not_use_try_message_data (&mdata.data,
1442                                                         mdata.expected_validity))
1443           {
1444             _dbus_warn ("expected validity %d and did not get it\n",
1445                         mdata.expected_validity);
1446             _dbus_assert_not_reached ("message data failed");
1447           }
1448
1449         _dbus_message_data_free (&mdata);
1450
1451         count += 1;
1452       }
1453
1454     printf ("%d sample messages tested\n", count);
1455
1456     print_validities_seen (FALSE);
1457     print_validities_seen (TRUE);
1458   }
1459
1460   check_memleaks ();
1461   _dbus_check_fdleaks();
1462
1463   /* Now load every message in test_data_dir if we have one */
1464   if (test_data_dir == NULL)
1465     return TRUE;
1466
1467   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
1468                                                         (DBusForeachMessageFileFunc)
1469                                                         dbus_internal_do_not_use_try_message_file,
1470                                                         NULL);  
1471 }
1472
1473 #endif /* DBUS_BUILD_TESTS */