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