2005-01-26 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-message-util.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dbus-internals.h"
26 #include "dbus-test.h"
27 #include "dbus-message-private.h"
28 #include "dbus-marshal-recursive.h"
29 #include "dbus-string.h"
30
31 /**
32  * @addtogroup DBusMessage
33  * @{
34  */
35
36 #ifdef DBUS_BUILD_TESTS
37 /**
38  * Reads arguments from a message iterator given a variable argument
39  * list. Only arguments of basic type and arrays of fixed-length
40  * basic type may be read with this function. See
41  * dbus_message_get_args() for more details.
42  *
43  * @todo this is static for now because there's no corresponding
44  * iter_append_args() and I'm not sure we need this function to be
45  * public since dbus_message_get_args() is what you usually want
46  *
47  * @param iter the message iterator
48  * @param error error to be filled in on failure
49  * @param first_arg_type the first argument type
50  * @param ... location for first argument value, then list of type-location pairs
51  * @returns #FALSE if the error was set
52  */
53 static dbus_bool_t
54 dbus_message_iter_get_args (DBusMessageIter *iter,
55                             DBusError       *error,
56                             int              first_arg_type,
57                             ...)
58 {
59   dbus_bool_t retval;
60   va_list var_args;
61
62   _dbus_return_val_if_fail (iter != NULL, FALSE);
63   _dbus_return_val_if_error_is_set (error, FALSE);
64
65   va_start (var_args, first_arg_type);
66   retval = _dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
67   va_end (var_args);
68
69   return retval;
70 }
71 #endif /* DBUS_BUILD_TESTS */
72
73 /** @} */
74
75 #ifdef DBUS_BUILD_TESTS
76 #include "dbus-test.h"
77 #include "dbus-message-factory.h"
78 #include <stdio.h>
79 #include <stdlib.h>
80
81 static void
82 check_memleaks (void)
83 {
84   dbus_shutdown ();
85
86   if (_dbus_get_malloc_blocks_outstanding () != 0)
87     {
88       _dbus_warn ("%d dbus_malloc blocks were not freed in %s\n",
89                   _dbus_get_malloc_blocks_outstanding (), __FILE__);
90       _dbus_assert_not_reached ("memleaks");
91     }
92 }
93
94 static dbus_bool_t
95 check_have_valid_message (DBusMessageLoader *loader)
96 {
97   DBusMessage *message;
98   dbus_bool_t retval;
99
100   message = NULL;
101   retval = FALSE;
102
103   if (_dbus_message_loader_get_is_corrupted (loader))
104     {
105       _dbus_warn ("loader corrupted on message that was expected to be valid; invalid reason %d\n",
106                   loader->corruption_reason);
107       goto failed;
108     }
109
110   message = _dbus_message_loader_pop_message (loader);
111   if (message == NULL)
112     {
113       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
114       goto failed;
115     }
116
117   if (_dbus_string_get_length (&loader->data) > 0)
118     {
119       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
120       goto failed;
121     }
122
123 #if 0
124   /* FIXME */
125   /* Verify that we're able to properly deal with the message.
126    * For example, this would detect improper handling of messages
127    * in nonstandard byte order.
128    */
129   if (!check_message_handling (message))
130     goto failed;
131 #endif
132
133   retval = TRUE;
134
135  failed:
136   if (message)
137     dbus_message_unref (message);
138
139   return retval;
140 }
141
142 static dbus_bool_t
143 check_invalid_message (DBusMessageLoader *loader,
144                        DBusValidity       expected_validity)
145 {
146   dbus_bool_t retval;
147
148   retval = FALSE;
149
150   if (!_dbus_message_loader_get_is_corrupted (loader))
151     {
152       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
153       goto failed;
154     }
155
156   if (expected_validity != DBUS_INVALID_FOR_UNKNOWN_REASON &&
157       loader->corruption_reason != expected_validity)
158     {
159       _dbus_warn ("expected message to be corrupted for reason %d and was corrupted for %d instead\n",
160                   expected_validity, loader->corruption_reason);
161       goto failed;
162     }
163
164   retval = TRUE;
165
166  failed:
167   return retval;
168 }
169
170 static dbus_bool_t
171 check_incomplete_message (DBusMessageLoader *loader)
172 {
173   DBusMessage *message;
174   dbus_bool_t retval;
175
176   message = NULL;
177   retval = FALSE;
178
179   if (_dbus_message_loader_get_is_corrupted (loader))
180     {
181       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete), corruption reason %d\n",
182                   loader->corruption_reason);
183       goto failed;
184     }
185
186   message = _dbus_message_loader_pop_message (loader);
187   if (message != NULL)
188     {
189       _dbus_warn ("loaded message that was expected to be incomplete\n");
190       goto failed;
191     }
192
193   retval = TRUE;
194
195  failed:
196   if (message)
197     dbus_message_unref (message);
198   return retval;
199 }
200
201 static dbus_bool_t
202 check_loader_results (DBusMessageLoader      *loader,
203                       DBusValidity            expected_validity)
204 {
205   if (!_dbus_message_loader_queue_messages (loader))
206     _dbus_assert_not_reached ("no memory to queue messages");
207
208   if (expected_validity == DBUS_VALID)
209     return check_have_valid_message (loader);
210   else if (expected_validity == DBUS_VALID_BUT_INCOMPLETE)
211     return check_incomplete_message (loader);
212   else if (expected_validity == DBUS_VALIDITY_UNKNOWN)
213     {
214       /* here we just know we didn't segfault and that was the
215        * only test
216        */
217       return TRUE;
218     }
219   else
220     return check_invalid_message (loader, expected_validity);
221 }
222
223 /**
224  * Loads the message in the given message file.
225  *
226  * @param filename filename to load
227  * @param data string to load message into
228  * @returns #TRUE if the message was loaded
229  */
230 dbus_bool_t
231 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
232                                             DBusString          *data)
233 {
234   dbus_bool_t retval;
235   DBusError error;
236   
237   retval = FALSE;
238
239   _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
240   dbus_error_init (&error);
241   if (!_dbus_file_get_contents (data, filename, &error))
242     {
243       _dbus_warn ("Could not load message file %s: %s\n",
244                   _dbus_string_get_const_data (filename),
245                   error.message);
246       dbus_error_free (&error);
247       goto failed;
248     }
249
250   retval = TRUE;
251
252  failed:
253
254   return retval;
255 }
256
257 /**
258  * Tries loading the message in the given message file
259  * and verifies that DBusMessageLoader can handle it.
260  *
261  * @param filename filename to load
262  * @param expected_validity what the message has to be like to return #TRUE
263  * @returns #TRUE if the message has the expected validity
264  */
265 dbus_bool_t
266 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
267                                            DBusValidity         expected_validity)
268 {
269   DBusString data;
270   dbus_bool_t retval;
271
272   retval = FALSE;
273
274   if (!_dbus_string_init (&data))
275     _dbus_assert_not_reached ("could not allocate string\n");
276
277   if (!dbus_internal_do_not_use_load_message_file (filename, &data))
278     goto failed;
279
280   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
281
282  failed:
283
284   if (!retval)
285     {
286       if (_dbus_string_get_length (&data) > 0)
287         _dbus_verbose_bytes_of_string (&data, 0,
288                                        _dbus_string_get_length (&data));
289
290       _dbus_warn ("Failed message loader test on %s\n",
291                   _dbus_string_get_const_data (filename));
292     }
293
294   _dbus_string_free (&data);
295
296   return retval;
297 }
298
299 /**
300  * Tries loading the given message data.
301  *
302  *
303  * @param data the message data
304  * @param expected_validity what the message has to be like to return #TRUE
305  * @returns #TRUE if the message has the expected validity
306  */
307 dbus_bool_t
308 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
309                                            DBusValidity         expected_validity)
310 {
311   DBusMessageLoader *loader;
312   dbus_bool_t retval;
313   int len;
314   int i;
315
316   loader = NULL;
317   retval = FALSE;
318
319   /* Write the data one byte at a time */
320
321   loader = _dbus_message_loader_new ();
322
323   /* check some trivial loader functions */
324   _dbus_message_loader_ref (loader);
325   _dbus_message_loader_unref (loader);
326   _dbus_message_loader_get_max_message_size (loader);
327
328   len = _dbus_string_get_length (data);
329   for (i = 0; i < len; i++)
330     {
331       DBusString *buffer;
332
333       _dbus_message_loader_get_buffer (loader, &buffer);
334       _dbus_string_append_byte (buffer,
335                                 _dbus_string_get_byte (data, i));
336       _dbus_message_loader_return_buffer (loader, buffer, 1);
337     }
338
339   if (!check_loader_results (loader, expected_validity))
340     goto failed;
341
342   _dbus_message_loader_unref (loader);
343   loader = NULL;
344
345   /* Write the data all at once */
346
347   loader = _dbus_message_loader_new ();
348
349   {
350     DBusString *buffer;
351
352     _dbus_message_loader_get_buffer (loader, &buffer);
353     _dbus_string_copy (data, 0, buffer,
354                        _dbus_string_get_length (buffer));
355     _dbus_message_loader_return_buffer (loader, buffer, 1);
356   }
357
358   if (!check_loader_results (loader, expected_validity))
359     goto failed;
360
361   _dbus_message_loader_unref (loader);
362   loader = NULL;
363
364   /* Write the data 2 bytes at a time */
365
366   loader = _dbus_message_loader_new ();
367
368   len = _dbus_string_get_length (data);
369   for (i = 0; i < len; i += 2)
370     {
371       DBusString *buffer;
372
373       _dbus_message_loader_get_buffer (loader, &buffer);
374       _dbus_string_append_byte (buffer,
375                                 _dbus_string_get_byte (data, i));
376       if ((i+1) < len)
377         _dbus_string_append_byte (buffer,
378                                   _dbus_string_get_byte (data, i+1));
379       _dbus_message_loader_return_buffer (loader, buffer, 1);
380     }
381
382   if (!check_loader_results (loader, expected_validity))
383     goto failed;
384
385   _dbus_message_loader_unref (loader);
386   loader = NULL;
387
388   retval = TRUE;
389
390  failed:
391
392   if (loader)
393     _dbus_message_loader_unref (loader);
394
395   return retval;
396 }
397
398 static dbus_bool_t
399 process_test_subdir (const DBusString          *test_base_dir,
400                      const char                *subdir,
401                      DBusValidity               expected_validity,
402                      DBusForeachMessageFileFunc function,
403                      void                      *user_data)
404 {
405   DBusString test_directory;
406   DBusString filename;
407   DBusDirIter *dir;
408   dbus_bool_t retval;
409   DBusError error;
410
411   retval = FALSE;
412   dir = NULL;
413
414   if (!_dbus_string_init (&test_directory))
415     _dbus_assert_not_reached ("didn't allocate test_directory\n");
416
417   _dbus_string_init_const (&filename, subdir);
418
419   if (!_dbus_string_copy (test_base_dir, 0,
420                           &test_directory, 0))
421     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
422
423   if (!_dbus_concat_dir_and_file (&test_directory, &filename))
424     _dbus_assert_not_reached ("couldn't allocate full path");
425
426   _dbus_string_free (&filename);
427   if (!_dbus_string_init (&filename))
428     _dbus_assert_not_reached ("didn't allocate filename string\n");
429
430   dbus_error_init (&error);
431   dir = _dbus_directory_open (&test_directory, &error);
432   if (dir == NULL)
433     {
434       _dbus_warn ("Could not open %s: %s\n",
435                   _dbus_string_get_const_data (&test_directory),
436                   error.message);
437       dbus_error_free (&error);
438       goto failed;
439     }
440
441   printf ("Testing %s:\n", subdir);
442
443  next:
444   while (_dbus_directory_get_next_file (dir, &filename, &error))
445     {
446       DBusString full_path;
447
448       if (!_dbus_string_init (&full_path))
449         _dbus_assert_not_reached ("couldn't init string");
450
451       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
452         _dbus_assert_not_reached ("couldn't copy dir to full_path");
453
454       if (!_dbus_concat_dir_and_file (&full_path, &filename))
455         _dbus_assert_not_reached ("couldn't concat file to dir");
456
457       if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
458         ;
459       else
460         {
461           if (_dbus_string_ends_with_c_str (&filename, ".message"))
462             {
463               _dbus_warn ("Could not load %s, message builder language no longer supported\n",
464                           _dbus_string_get_const_data (&filename));
465             }
466           
467           _dbus_verbose ("Skipping non-.message file %s\n",
468                          _dbus_string_get_const_data (&filename));
469           _dbus_string_free (&full_path);
470           goto next;
471         }
472
473       printf ("    %s\n",
474               _dbus_string_get_const_data (&filename));
475
476       if (! (*function) (&full_path,
477                          expected_validity, user_data))
478         {
479           _dbus_string_free (&full_path);
480           goto failed;
481         }
482       else
483         _dbus_string_free (&full_path);
484     }
485
486   if (dbus_error_is_set (&error))
487     {
488       _dbus_warn ("Could not get next file in %s: %s\n",
489                   _dbus_string_get_const_data (&test_directory),
490                   error.message);
491       dbus_error_free (&error);
492       goto failed;
493     }
494
495   retval = TRUE;
496
497  failed:
498
499   if (dir)
500     _dbus_directory_close (dir);
501   _dbus_string_free (&test_directory);
502   _dbus_string_free (&filename);
503
504   return retval;
505 }
506
507 /**
508  * Runs the given function on every message file in the test suite.
509  * The function should return #FALSE on test failure or fatal error.
510  *
511  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
512  * @param func the function to run
513  * @param user_data data for function
514  * @returns #FALSE if there's a failure
515  */
516 dbus_bool_t
517 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
518                                                DBusForeachMessageFileFunc func,
519                                                void                      *user_data)
520 {
521   DBusString test_directory;
522   dbus_bool_t retval;
523
524   retval = FALSE;
525
526   _dbus_string_init_const (&test_directory, test_data_dir);
527   
528   if (!process_test_subdir (&test_directory, "valid-messages",
529                             DBUS_VALID, func, user_data))
530     goto failed;
531
532   check_memleaks ();
533   
534   if (!process_test_subdir (&test_directory, "invalid-messages",
535                             DBUS_INVALID_FOR_UNKNOWN_REASON, func, user_data))
536     goto failed;
537
538   check_memleaks ();
539   
540   if (!process_test_subdir (&test_directory, "incomplete-messages",
541                             DBUS_VALID_BUT_INCOMPLETE, func, user_data))
542     goto failed;
543
544   check_memleaks ();
545   
546   retval = TRUE;
547   
548  failed:
549
550   _dbus_string_free (&test_directory);
551
552   return retval;
553 }
554
555 #if 0
556 #define GET_AND_CHECK(iter, typename, literal)                                  \
557   do {                                                                          \
558     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
559       _dbus_assert_not_reached ("got wrong argument type from message iter");   \
560     dbus_message_iter_get_basic (&iter, &v_##typename);                         \
561     if (v_##typename != literal)                                                \
562       _dbus_assert_not_reached ("got wrong value from message iter");           \
563   } while (0)
564
565 #define GET_AND_CHECK_STRCMP(iter, typename, literal)                           \
566   do {                                                                          \
567     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
568       _dbus_assert_not_reached ("got wrong argument type from message iter");   \
569     dbus_message_iter_get_basic (&iter, &v_##typename);                         \
570     if (strcmp (v_##typename, literal) != 0)                                    \
571       _dbus_assert_not_reached ("got wrong value from message iter");           \
572   } while (0)
573
574 #define GET_AND_CHECK_AND_NEXT(iter, typename, literal)         \
575   do {                                                          \
576     GET_AND_CHECK(iter, typename, literal);                     \
577     if (!dbus_message_iter_next (&iter))                        \
578       _dbus_assert_not_reached ("failed to move iter to next"); \
579   } while (0)
580
581 #define GET_AND_CHECK_STRCMP_AND_NEXT(iter, typename, literal)  \
582   do {                                                          \
583     GET_AND_CHECK_STRCMP(iter, typename, literal);              \
584     if (!dbus_message_iter_next (&iter))                        \
585       _dbus_assert_not_reached ("failed to move iter to next"); \
586   } while (0)
587
588 static void
589 message_iter_test (DBusMessage *message)
590 {
591   DBusMessageIter iter, array, array2;
592   const char *v_STRING;
593   double v_DOUBLE;
594   dbus_int32_t v_INT32;
595   dbus_uint32_t v_UINT32;
596 #ifdef DBUS_HAVE_INT64
597   dbus_int64_t v_INT64;
598   dbus_uint64_t v_UINT64;
599 #endif
600   unsigned char v_BYTE;
601   dbus_bool_t v_BOOLEAN;
602
603   const dbus_int32_t *our_int_array;
604   int len;
605
606   dbus_message_iter_init (message, &iter);
607
608   GET_AND_CHECK_STRCMP_AND_NEXT (iter, STRING, "Test string");
609   GET_AND_CHECK_AND_NEXT (iter, INT32, -0x12345678);
610   GET_AND_CHECK_AND_NEXT (iter, UINT32, 0xedd1e);
611   GET_AND_CHECK_AND_NEXT (iter, DOUBLE, 3.14159);
612
613   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
614     _dbus_assert_not_reached ("Argument type not an array");
615
616   if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_DOUBLE)
617     _dbus_assert_not_reached ("Array type not double");
618
619   dbus_message_iter_recurse (&iter, &array);
620
621   GET_AND_CHECK_AND_NEXT (array, DOUBLE, 1.5);
622   GET_AND_CHECK (array, DOUBLE, 2.5);
623
624   if (dbus_message_iter_next (&array))
625     _dbus_assert_not_reached ("Didn't reach end of array");
626
627   if (!dbus_message_iter_next (&iter))
628     _dbus_assert_not_reached ("Reached end of arguments");
629
630   GET_AND_CHECK_AND_NEXT (iter, BYTE, 0xF0);
631
632   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
633     _dbus_assert_not_reached ("no array");
634
635   if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_INT32)
636     _dbus_assert_not_reached ("Array type not int32");
637
638   /* Empty array */
639   dbus_message_iter_recurse (&iter, &array);
640
641   if (dbus_message_iter_next (&array))
642     _dbus_assert_not_reached ("Didn't reach end of array");
643
644   if (!dbus_message_iter_next (&iter))
645     _dbus_assert_not_reached ("Reached end of arguments");
646
647   GET_AND_CHECK (iter, BYTE, 0xF0);
648
649   if (dbus_message_iter_next (&iter))
650     _dbus_assert_not_reached ("Didn't reach end of arguments");
651 }
652 #endif
653
654 static void
655 verify_test_message (DBusMessage *message)
656 {
657   DBusMessageIter iter;
658   DBusError error;
659   dbus_int32_t our_int;
660   dbus_uint32_t our_uint;
661   const char *our_str;
662   double our_double;
663   double v_DOUBLE;
664   dbus_bool_t our_bool;
665   unsigned char our_byte_1, our_byte_2;
666   const dbus_int32_t *our_uint32_array = (void*)0xdeadbeef;
667   int our_uint32_array_len;
668   dbus_int32_t *our_int32_array = (void*)0xdeadbeef;
669   int our_int32_array_len;
670 #ifdef DBUS_HAVE_INT64
671   dbus_int64_t our_int64;
672   dbus_uint64_t our_uint64;
673   dbus_int64_t *our_uint64_array = (void*)0xdeadbeef;
674   int our_uint64_array_len;
675   const dbus_int64_t *our_int64_array = (void*)0xdeadbeef;
676   int our_int64_array_len;
677 #endif
678   const double *our_double_array = (void*)0xdeadbeef;
679   int our_double_array_len;
680   const unsigned char *our_byte_array = (void*)0xdeadbeef;
681   int our_byte_array_len;
682   const dbus_bool_t *our_boolean_array = (void*)0xdeadbeef;
683   int our_boolean_array_len;
684
685   dbus_message_iter_init (message, &iter);
686
687   dbus_error_init (&error);
688   if (!dbus_message_iter_get_args (&iter, &error,
689                                    DBUS_TYPE_INT32, &our_int,
690                                    DBUS_TYPE_UINT32, &our_uint,
691 #ifdef DBUS_HAVE_INT64
692                                    DBUS_TYPE_INT64, &our_int64,
693                                    DBUS_TYPE_UINT64, &our_uint64,
694 #endif
695                                    DBUS_TYPE_STRING, &our_str,
696                                    DBUS_TYPE_DOUBLE, &our_double,
697                                    DBUS_TYPE_BOOLEAN, &our_bool,
698                                    DBUS_TYPE_BYTE, &our_byte_1,
699                                    DBUS_TYPE_BYTE, &our_byte_2,
700                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
701                                    &our_uint32_array, &our_uint32_array_len,
702                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
703                                    &our_int32_array, &our_int32_array_len,
704 #ifdef DBUS_HAVE_INT64
705                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
706                                    &our_uint64_array, &our_uint64_array_len,
707                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
708                                    &our_int64_array, &our_int64_array_len,
709 #endif
710                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
711                                    &our_double_array, &our_double_array_len,
712                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
713                                    &our_byte_array, &our_byte_array_len,
714                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
715                                    &our_boolean_array, &our_boolean_array_len,
716                                    0))
717     {
718       _dbus_warn ("error: %s - %s\n", error.name,
719                   (error.message != NULL) ? error.message : "no message");
720       _dbus_assert_not_reached ("Could not get arguments");
721     }
722
723   if (our_int != -0x12345678)
724     _dbus_assert_not_reached ("integers differ!");
725
726   if (our_uint != 0x12300042)
727     _dbus_assert_not_reached ("uints differ!");
728
729 #ifdef DBUS_HAVE_INT64
730   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
731     _dbus_assert_not_reached ("64-bit integers differ!");
732   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
733     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
734 #endif
735
736   v_DOUBLE = 3.14159;
737   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double, v_DOUBLE))
738     _dbus_assert_not_reached ("doubles differ!");
739
740   if (strcmp (our_str, "Test string") != 0)
741     _dbus_assert_not_reached ("strings differ!");
742
743   if (!our_bool)
744     _dbus_assert_not_reached ("booleans differ");
745
746   if (our_byte_1 != 42)
747     _dbus_assert_not_reached ("bytes differ!");
748
749   if (our_byte_2 != 24)
750     _dbus_assert_not_reached ("bytes differ!");
751
752   if (our_uint32_array_len != 4 ||
753       our_uint32_array[0] != 0x12345678 ||
754       our_uint32_array[1] != 0x23456781 ||
755       our_uint32_array[2] != 0x34567812 ||
756       our_uint32_array[3] != 0x45678123)
757     _dbus_assert_not_reached ("uint array differs");
758
759   if (our_int32_array_len != 4 ||
760       our_int32_array[0] != 0x12345678 ||
761       our_int32_array[1] != -0x23456781 ||
762       our_int32_array[2] != 0x34567812 ||
763       our_int32_array[3] != -0x45678123)
764     _dbus_assert_not_reached ("int array differs");
765
766 #ifdef DBUS_HAVE_INT64
767   if (our_uint64_array_len != 4 ||
768       our_uint64_array[0] != 0x12345678 ||
769       our_uint64_array[1] != 0x23456781 ||
770       our_uint64_array[2] != 0x34567812 ||
771       our_uint64_array[3] != 0x45678123)
772     _dbus_assert_not_reached ("uint64 array differs");
773
774   if (our_int64_array_len != 4 ||
775       our_int64_array[0] != 0x12345678 ||
776       our_int64_array[1] != -0x23456781 ||
777       our_int64_array[2] != 0x34567812 ||
778       our_int64_array[3] != -0x45678123)
779     _dbus_assert_not_reached ("int64 array differs");
780 #endif /* DBUS_HAVE_INT64 */
781
782   if (our_double_array_len != 3)
783     _dbus_assert_not_reached ("double array had wrong length");
784
785   /* On all IEEE machines (i.e. everything sane) exact equality
786    * should be preserved over the wire
787    */
788   v_DOUBLE = 0.1234;
789   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[0], v_DOUBLE))
790     _dbus_assert_not_reached ("double array had wrong values");
791   v_DOUBLE = 9876.54321;
792   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[1], v_DOUBLE))
793     _dbus_assert_not_reached ("double array had wrong values");
794   v_DOUBLE = -300.0;
795   if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[2], v_DOUBLE))
796     _dbus_assert_not_reached ("double array had wrong values");
797
798   if (our_byte_array_len != 4)
799     _dbus_assert_not_reached ("byte array had wrong length");
800
801   if (our_byte_array[0] != 'a' ||
802       our_byte_array[1] != 'b' ||
803       our_byte_array[2] != 'c' ||
804       our_byte_array[3] != 234)
805     _dbus_assert_not_reached ("byte array had wrong values");
806
807   if (our_boolean_array_len != 5)
808     _dbus_assert_not_reached ("bool array had wrong length");
809
810   if (our_boolean_array[0] != TRUE ||
811       our_boolean_array[1] != FALSE ||
812       our_boolean_array[2] != TRUE ||
813       our_boolean_array[3] != TRUE ||
814       our_boolean_array[4] != FALSE)
815     _dbus_assert_not_reached ("bool array had wrong values");
816
817   if (dbus_message_iter_next (&iter))
818     _dbus_assert_not_reached ("Didn't reach end of arguments");
819 }
820
821 /**
822  * @ingroup DBusMessageInternals
823  * Unit test for DBusMessage.
824  *
825  * @returns #TRUE on success.
826  */
827 dbus_bool_t
828 _dbus_message_test (const char *test_data_dir)
829 {
830   DBusMessage *message;
831   DBusMessageLoader *loader;
832   int i;
833   const char *data;
834   DBusMessage *copy;
835   const char *name1;
836   const char *name2;
837   const dbus_uint32_t our_uint32_array[] =
838     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
839   const dbus_uint32_t our_int32_array[] =
840     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
841   const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array;
842   const dbus_int32_t *v_ARRAY_INT32 = our_int32_array;
843 #ifdef DBUS_HAVE_INT64
844   const dbus_uint64_t our_uint64_array[] =
845     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
846   const dbus_uint64_t our_int64_array[] =
847     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
848   const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array;
849   const dbus_int64_t *v_ARRAY_INT64 = our_int64_array;
850 #endif
851   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
852   const char **v_ARRAY_STRING = our_string_array;
853   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
854   const double *v_ARRAY_DOUBLE = our_double_array;
855   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
856   const unsigned char *v_ARRAY_BYTE = our_byte_array;
857   const dbus_bool_t our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
858   const dbus_bool_t *v_ARRAY_BOOLEAN = our_boolean_array;
859   char sig[64];
860   const char *s;
861   const char *v_STRING;
862   double v_DOUBLE;
863   dbus_int32_t v_INT32;
864   dbus_uint32_t v_UINT32;
865 #ifdef DBUS_HAVE_INT64
866   dbus_int64_t v_INT64;
867   dbus_uint64_t v_UINT64;
868 #endif
869   unsigned char v_BYTE;
870   unsigned char v2_BYTE;
871   dbus_bool_t v_BOOLEAN;
872
873   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
874                                           "/org/freedesktop/TestPath",
875                                           "Foo.TestInterface",
876                                           "TestMethod");
877   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
878   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
879                                              "TestMethod"));
880   _dbus_assert (strcmp (dbus_message_get_path (message),
881                         "/org/freedesktop/TestPath") == 0);
882   _dbus_message_set_serial (message, 1234);
883
884   /* string length including nul byte not a multiple of 4 */
885   if (!dbus_message_set_sender (message, "org.foo.bar1"))
886     _dbus_assert_not_reached ("out of memory");
887
888   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
889   dbus_message_set_reply_serial (message, 5678);
890
891   _dbus_verbose_bytes_of_string (&message->header.data, 0,
892                                  _dbus_string_get_length (&message->header.data));
893   _dbus_verbose_bytes_of_string (&message->body, 0,
894                                  _dbus_string_get_length (&message->body));
895
896   if (!dbus_message_set_sender (message, NULL))
897     _dbus_assert_not_reached ("out of memory");
898
899
900   _dbus_verbose_bytes_of_string (&message->header.data, 0,
901                                  _dbus_string_get_length (&message->header.data));
902   _dbus_verbose_bytes_of_string (&message->body, 0,
903                                  _dbus_string_get_length (&message->body));
904
905
906   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
907   _dbus_assert (dbus_message_get_serial (message) == 1234);
908   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
909   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
910
911   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
912   dbus_message_set_no_reply (message, TRUE);
913   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
914   dbus_message_set_no_reply (message, FALSE);
915   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
916
917   /* Set/get some header fields */
918
919   if (!dbus_message_set_path (message, "/foo"))
920     _dbus_assert_not_reached ("out of memory");
921   _dbus_assert (strcmp (dbus_message_get_path (message),
922                         "/foo") == 0);
923
924   if (!dbus_message_set_interface (message, "org.Foo"))
925     _dbus_assert_not_reached ("out of memory");
926   _dbus_assert (strcmp (dbus_message_get_interface (message),
927                         "org.Foo") == 0);
928
929   if (!dbus_message_set_member (message, "Bar"))
930     _dbus_assert_not_reached ("out of memory");
931   _dbus_assert (strcmp (dbus_message_get_member (message),
932                         "Bar") == 0);
933
934   /* Set/get them with longer values */
935   if (!dbus_message_set_path (message, "/foo/bar"))
936     _dbus_assert_not_reached ("out of memory");
937   _dbus_assert (strcmp (dbus_message_get_path (message),
938                         "/foo/bar") == 0);
939
940   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
941     _dbus_assert_not_reached ("out of memory");
942   _dbus_assert (strcmp (dbus_message_get_interface (message),
943                         "org.Foo.Bar") == 0);
944
945   if (!dbus_message_set_member (message, "BarFoo"))
946     _dbus_assert_not_reached ("out of memory");
947   _dbus_assert (strcmp (dbus_message_get_member (message),
948                         "BarFoo") == 0);
949
950   /* Realloc shorter again */
951
952   if (!dbus_message_set_path (message, "/foo"))
953     _dbus_assert_not_reached ("out of memory");
954   _dbus_assert (strcmp (dbus_message_get_path (message),
955                         "/foo") == 0);
956
957   if (!dbus_message_set_interface (message, "org.Foo"))
958     _dbus_assert_not_reached ("out of memory");
959   _dbus_assert (strcmp (dbus_message_get_interface (message),
960                         "org.Foo") == 0);
961
962   if (!dbus_message_set_member (message, "Bar"))
963     _dbus_assert_not_reached ("out of memory");
964   _dbus_assert (strcmp (dbus_message_get_member (message),
965                         "Bar") == 0);
966
967   dbus_message_unref (message);
968
969   /* Test the vararg functions */
970   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
971                                           "/org/freedesktop/TestPath",
972                                           "Foo.TestInterface",
973                                           "TestMethod");
974   _dbus_message_set_serial (message, 1);
975   dbus_message_set_reply_serial (message, 5678);
976
977   v_INT32 = -0x12345678;
978   v_UINT32 = 0x12300042;
979 #ifdef DBUS_HAVE_INT64
980   v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd);
981   v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd);
982 #endif
983   v_STRING = "Test string";
984   v_DOUBLE = 3.14159;
985   v_BOOLEAN = TRUE;
986   v_BYTE = 42;
987   v2_BYTE = 24;
988
989   dbus_message_append_args (message,
990                             DBUS_TYPE_INT32, &v_INT32,
991                             DBUS_TYPE_UINT32, &v_UINT32,
992 #ifdef DBUS_HAVE_INT64
993                             DBUS_TYPE_INT64, &v_INT64,
994                             DBUS_TYPE_UINT64, &v_UINT64,
995 #endif
996                             DBUS_TYPE_STRING, &v_STRING,
997                             DBUS_TYPE_DOUBLE, &v_DOUBLE,
998                             DBUS_TYPE_BOOLEAN, &v_BOOLEAN,
999                             DBUS_TYPE_BYTE, &v_BYTE,
1000                             DBUS_TYPE_BYTE, &v2_BYTE,
1001                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32,
1002                             _DBUS_N_ELEMENTS (our_uint32_array),
1003                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32,
1004                             _DBUS_N_ELEMENTS (our_int32_array),
1005 #ifdef DBUS_HAVE_INT64
1006                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64,
1007                             _DBUS_N_ELEMENTS (our_uint64_array),
1008                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64,
1009                             _DBUS_N_ELEMENTS (our_int64_array),
1010 #endif
1011                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE,
1012                             _DBUS_N_ELEMENTS (our_double_array),
1013                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE,
1014                             _DBUS_N_ELEMENTS (our_byte_array),
1015                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN,
1016                             _DBUS_N_ELEMENTS (our_boolean_array),
1017                             DBUS_TYPE_INVALID);
1018
1019   i = 0;
1020   sig[i++] = DBUS_TYPE_INT32;
1021   sig[i++] = DBUS_TYPE_UINT32;
1022 #ifdef DBUS_HAVE_INT64
1023   sig[i++] = DBUS_TYPE_INT64;
1024   sig[i++] = DBUS_TYPE_UINT64;
1025 #endif
1026   sig[i++] = DBUS_TYPE_STRING;
1027   sig[i++] = DBUS_TYPE_DOUBLE;
1028   sig[i++] = DBUS_TYPE_BOOLEAN;
1029   sig[i++] = DBUS_TYPE_BYTE;
1030   sig[i++] = DBUS_TYPE_BYTE;
1031   sig[i++] = DBUS_TYPE_ARRAY;
1032   sig[i++] = DBUS_TYPE_UINT32;
1033   sig[i++] = DBUS_TYPE_ARRAY;
1034   sig[i++] = DBUS_TYPE_INT32;
1035 #ifdef DBUS_HAVE_INT64
1036   sig[i++] = DBUS_TYPE_ARRAY;
1037   sig[i++] = DBUS_TYPE_UINT64;
1038   sig[i++] = DBUS_TYPE_ARRAY;
1039   sig[i++] = DBUS_TYPE_INT64;
1040 #endif
1041   sig[i++] = DBUS_TYPE_ARRAY;
1042   sig[i++] = DBUS_TYPE_DOUBLE;
1043   sig[i++] = DBUS_TYPE_ARRAY;
1044   sig[i++] = DBUS_TYPE_BYTE;
1045   sig[i++] = DBUS_TYPE_ARRAY;
1046   sig[i++] = DBUS_TYPE_BOOLEAN;
1047   sig[i++] = DBUS_TYPE_INVALID;
1048
1049   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
1050
1051   _dbus_verbose ("HEADER\n");
1052   _dbus_verbose_bytes_of_string (&message->header.data, 0,
1053                                  _dbus_string_get_length (&message->header.data));
1054   _dbus_verbose ("BODY\n");
1055   _dbus_verbose_bytes_of_string (&message->body, 0,
1056                                  _dbus_string_get_length (&message->body));
1057
1058   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
1059                  sig, dbus_message_get_signature (message));
1060
1061   s = dbus_message_get_signature (message);
1062
1063   _dbus_assert (dbus_message_has_signature (message, sig));
1064   _dbus_assert (strcmp (s, sig) == 0);
1065
1066   verify_test_message (message);
1067
1068   copy = dbus_message_copy (message);
1069
1070   _dbus_assert (dbus_message_get_reply_serial (message) ==
1071                 dbus_message_get_reply_serial (copy));
1072   _dbus_assert (message->header.padding == copy->header.padding);
1073
1074   _dbus_assert (_dbus_string_get_length (&message->header.data) ==
1075                 _dbus_string_get_length (&copy->header.data));
1076
1077   _dbus_assert (_dbus_string_get_length (&message->body) ==
1078                 _dbus_string_get_length (&copy->body));
1079
1080   verify_test_message (copy);
1081
1082   name1 = dbus_message_get_interface (message);
1083   name2 = dbus_message_get_interface (copy);
1084
1085   _dbus_assert (strcmp (name1, name2) == 0);
1086
1087   name1 = dbus_message_get_member (message);
1088   name2 = dbus_message_get_member (copy);
1089
1090   _dbus_assert (strcmp (name1, name2) == 0);
1091
1092   dbus_message_unref (copy);
1093
1094   /* Message loader test */
1095   _dbus_message_lock (message);
1096   loader = _dbus_message_loader_new ();
1097   
1098   /* check ref/unref */
1099   _dbus_message_loader_ref (loader);
1100   _dbus_message_loader_unref (loader);
1101
1102   /* Write the header data one byte at a time */
1103   data = _dbus_string_get_const_data (&message->header.data);
1104   for (i = 0; i < _dbus_string_get_length (&message->header.data); i++)
1105     {
1106       DBusString *buffer;
1107
1108       _dbus_message_loader_get_buffer (loader, &buffer);
1109       _dbus_string_append_byte (buffer, data[i]);
1110       _dbus_message_loader_return_buffer (loader, buffer, 1);
1111     }
1112
1113   /* Write the body data one byte at a time */
1114   data = _dbus_string_get_const_data (&message->body);
1115   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
1116     {
1117       DBusString *buffer;
1118
1119       _dbus_message_loader_get_buffer (loader, &buffer);
1120       _dbus_string_append_byte (buffer, data[i]);
1121       _dbus_message_loader_return_buffer (loader, buffer, 1);
1122     }
1123
1124   dbus_message_unref (message);
1125
1126   /* Now pop back the message */
1127   if (!_dbus_message_loader_queue_messages (loader))
1128     _dbus_assert_not_reached ("no memory to queue messages");
1129
1130   if (_dbus_message_loader_get_is_corrupted (loader))
1131     _dbus_assert_not_reached ("message loader corrupted");
1132
1133   message = _dbus_message_loader_pop_message (loader);
1134   if (!message)
1135     _dbus_assert_not_reached ("received a NULL message");
1136
1137   if (dbus_message_get_reply_serial (message) != 5678)
1138     _dbus_assert_not_reached ("reply serial fields differ");
1139
1140   verify_test_message (message);
1141
1142   dbus_message_unref (message);
1143   _dbus_message_loader_unref (loader);
1144
1145   check_memleaks ();
1146
1147   /* Load all the sample messages from the message factory */
1148   {
1149     DBusMessageDataIter diter;
1150     DBusMessageData mdata;
1151     int count;
1152
1153     count = 0;
1154     _dbus_message_data_iter_init (&diter);
1155     
1156     while (_dbus_message_data_iter_get_and_next (&diter,
1157                                                  &mdata))
1158       {
1159         if (!dbus_internal_do_not_use_try_message_data (&mdata.data,
1160                                                         mdata.expected_validity))
1161           {
1162             _dbus_warn ("expected validity %d and did not get it\n",
1163                         mdata.expected_validity);
1164             _dbus_assert_not_reached ("message data failed");
1165           }
1166
1167         _dbus_message_data_free (&mdata);
1168
1169         count += 1;
1170       }
1171
1172     printf ("%d sample messages tested\n", count);
1173   }
1174   
1175   check_memleaks ();
1176   
1177   /* Now load every message in test_data_dir if we have one */
1178   if (test_data_dir == NULL)
1179     return TRUE;
1180
1181   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
1182                                                         (DBusForeachMessageFileFunc)
1183                                                         dbus_internal_do_not_use_try_message_file,
1184                                                         NULL);  
1185 }
1186
1187 #endif /* DBUS_BUILD_TESTS */