Merge remote-tracking branch 'wjt/arg0namespace' into arg0namespace-24317
[platform/upstream/dbus.git] / dbus / dbus-message-factory.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-message-factory.c Generator of valid and invalid message data for test suite
3  *
4  * Copyright (C) 2005 Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 #include <config.h>
24
25 #ifndef DOXYGEN_SHOULD_SKIP_THIS
26
27 #ifdef DBUS_BUILD_TESTS
28 #include "dbus-message-factory.h"
29 #include "dbus-message-private.h"
30 #include "dbus-signature.h"
31 #include "dbus-test.h"
32 #include <stdio.h>
33
34 typedef enum
35   {
36     CHANGE_TYPE_ADJUST,
37     CHANGE_TYPE_ABSOLUTE
38   } ChangeType;
39
40 #define BYTE_ORDER_OFFSET  0
41 #define TYPE_OFFSET        1
42 #define BODY_LENGTH_OFFSET 4
43 #define FIELDS_ARRAY_LENGTH_OFFSET 12
44
45 static void
46 iter_recurse (DBusMessageDataIter *iter)
47 {
48   iter->depth += 1;
49   _dbus_assert (iter->depth < _DBUS_MESSAGE_DATA_MAX_NESTING);
50   _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
51 }
52
53 static int
54 iter_get_sequence (DBusMessageDataIter *iter)
55 {
56   _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
57   return iter->sequence_nos[iter->depth];
58 }
59
60 static void
61 iter_set_sequence (DBusMessageDataIter *iter,
62                    int                  sequence)
63 {
64   _dbus_assert (sequence >= 0);
65   iter->sequence_nos[iter->depth] = sequence;
66 }
67
68 static void
69 iter_unrecurse (DBusMessageDataIter *iter)
70 {
71   iter->depth -= 1;
72   _dbus_assert (iter->depth >= 0);
73 }
74
75 static void
76 iter_next (DBusMessageDataIter *iter)
77 {
78   iter->sequence_nos[iter->depth] += 1;
79 }
80
81 static dbus_bool_t
82 iter_first_in_series (DBusMessageDataIter *iter)
83 {
84   int i;
85
86   i = iter->depth;
87   while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
88     {
89       if (iter->sequence_nos[i] != 0)
90         return FALSE;
91       ++i;
92     }
93   return TRUE;
94 }
95
96 typedef dbus_bool_t (* DBusInnerGeneratorFunc)   (DBusMessageDataIter *iter,
97                                                   DBusMessage        **message_p);
98 typedef dbus_bool_t (* DBusMessageGeneratorFunc) (DBusMessageDataIter *iter,
99                                                   DBusString          *data,
100                                                   DBusValidity        *expected_validity);
101
102 static void
103 set_reply_serial (DBusMessage *message)
104 {
105   if (message == NULL)
106     _dbus_assert_not_reached ("oom");
107   if (!dbus_message_set_reply_serial (message, 100))
108     _dbus_assert_not_reached ("oom");
109 }
110
111 static dbus_bool_t
112 generate_trivial_inner (DBusMessageDataIter *iter,
113                         DBusMessage        **message_p)
114 {
115   DBusMessage *message;
116
117   switch (iter_get_sequence (iter))
118     {
119     case 0:
120       message = dbus_message_new_method_call ("org.freedesktop.TextEditor",
121                                               "/foo/bar",
122                                               "org.freedesktop.DocumentFactory",
123                                               "Create");
124       break;
125     case 1:
126       message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
127       set_reply_serial (message);
128       break;
129     case 2:
130       message = dbus_message_new_signal ("/foo/bar",
131                                          "org.freedesktop.DocumentFactory",
132                                          "Created");
133       break;
134     case 3:
135       message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
136
137       if (!dbus_message_set_error_name (message,
138                                         "org.freedesktop.TestErrorName"))
139         _dbus_assert_not_reached ("oom");
140       
141       {
142         DBusMessageIter iter;
143         const char *v_STRING = "This is an error";
144         
145         dbus_message_iter_init_append (message, &iter);
146         if (!dbus_message_iter_append_basic (&iter,
147                                              DBUS_TYPE_STRING,
148                                              &v_STRING))
149           _dbus_assert_not_reached ("oom");
150       }
151       
152       set_reply_serial (message);
153       break;
154     default:
155       return FALSE;
156     }
157   
158   if (message == NULL)
159     _dbus_assert_not_reached ("oom");
160
161   *message_p = message;
162   
163   return TRUE;
164 }
165
166 static dbus_bool_t
167 generate_many_bodies_inner (DBusMessageDataIter *iter,
168                             DBusMessage        **message_p)
169 {
170   DBusMessage *message;
171   DBusString signature;
172   DBusString body;
173
174   /* Keeping this small makes things go faster */
175   message = dbus_message_new_method_call ("o.z.F",
176                                           "/",
177                                           "o.z.B",
178                                           "Nah");
179   if (message == NULL)
180     _dbus_assert_not_reached ("oom");
181
182   set_reply_serial (message);
183
184   if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
185     _dbus_assert_not_reached ("oom");
186   
187   if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter),
188                                                 message->byte_order,
189                                                 &signature, &body))
190     {
191       const char *v_SIGNATURE;
192
193       v_SIGNATURE = _dbus_string_get_const_data (&signature);
194       if (!_dbus_header_set_field_basic (&message->header,
195                                          DBUS_HEADER_FIELD_SIGNATURE,
196                                          DBUS_TYPE_SIGNATURE,
197                                          &v_SIGNATURE))
198         _dbus_assert_not_reached ("oom");
199
200       if (!_dbus_string_move (&body, 0, &message->body, 0))
201         _dbus_assert_not_reached ("oom");
202
203       _dbus_marshal_set_uint32 (&message->header.data, BODY_LENGTH_OFFSET,
204                                 _dbus_string_get_length (&message->body),
205                                 message->byte_order);
206       
207       *message_p = message;
208     }
209   else
210     {
211       dbus_message_unref (message);
212       *message_p = NULL;
213     }
214   
215   _dbus_string_free (&signature);
216   _dbus_string_free (&body);
217
218   return *message_p != NULL;
219 }
220
221 static void
222 generate_from_message (DBusString            *data,
223                        DBusValidity          *expected_validity,
224                        DBusMessage           *message)
225 {
226   dbus_message_set_serial (message, 1);
227   dbus_message_lock (message);
228
229   *expected_validity = DBUS_VALID;
230   
231   /* move for efficiency, since we'll nuke the message anyway */
232   if (!_dbus_string_move (&message->header.data, 0,
233                           data, 0))
234     _dbus_assert_not_reached ("oom");
235
236   if (!_dbus_string_copy (&message->body, 0,
237                           data, _dbus_string_get_length (data)))
238     _dbus_assert_not_reached ("oom");
239 }
240
241 static dbus_bool_t
242 generate_outer (DBusMessageDataIter   *iter,
243                 DBusString            *data,
244                 DBusValidity          *expected_validity,
245                 DBusInnerGeneratorFunc func)
246 {
247   DBusMessage *message;
248
249   message = NULL;
250   if (!(*func)(iter, &message))
251     return FALSE;
252
253   iter_next (iter);
254   
255   _dbus_assert (message != NULL);
256
257   generate_from_message (data, expected_validity, message);
258
259   dbus_message_unref (message);
260
261   return TRUE;
262 }
263
264 static dbus_bool_t
265 generate_trivial (DBusMessageDataIter   *iter,
266                   DBusString            *data,
267                   DBusValidity          *expected_validity)
268 {
269   return generate_outer (iter, data, expected_validity,
270                          generate_trivial_inner);
271 }
272
273 static dbus_bool_t
274 generate_many_bodies (DBusMessageDataIter   *iter,
275                       DBusString            *data,
276                       DBusValidity          *expected_validity)
277 {
278   return generate_outer (iter, data, expected_validity,
279                          generate_many_bodies_inner);
280 }
281
282 static DBusMessage*
283 simple_method_call (void)
284 {
285   DBusMessage *message;
286   /* Keeping this small makes stuff go faster */
287   message = dbus_message_new_method_call ("o.b.Q",
288                                           "/f/b",
289                                           "o.b.Z",
290                                           "Fro");
291   if (message == NULL)
292     _dbus_assert_not_reached ("oom");
293   return message;
294 }
295
296 static DBusMessage*
297 simple_signal (void)
298 {
299   DBusMessage *message;
300   message = dbus_message_new_signal ("/f/b",
301                                      "o.b.Z",
302                                      "Fro");
303   if (message == NULL)
304     _dbus_assert_not_reached ("oom");
305   return message;
306 }
307
308 static DBusMessage*
309 simple_method_return (void)
310 {
311   DBusMessage *message;
312   message =  dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
313   if (message == NULL)
314     _dbus_assert_not_reached ("oom");
315
316   set_reply_serial (message);
317   
318   return message;
319 }
320
321 static DBusMessage*
322 simple_error (void)
323 {
324   DBusMessage *message;
325   message =  dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
326   if (message == NULL)
327     _dbus_assert_not_reached ("oom");
328
329   if (!dbus_message_set_error_name (message, "foo.bar"))
330     _dbus_assert_not_reached ("oom");
331   
332   set_reply_serial (message);
333   
334   return message;
335 }
336
337 static DBusMessage*
338 message_with_nesting_levels (int levels)
339 {
340   DBusMessage *message;
341   dbus_int32_t v_INT32;
342   DBusMessageIter *parents;
343   DBusMessageIter *children;
344   int i;
345
346   /* If levels is higher it breaks sig_refcount in DBusMessageRealIter
347    * in dbus-message.c, this assert is just to help you know you need
348    * to fix that if you hit it
349    */
350   _dbus_assert (levels < 256);
351
352   parents = dbus_new(DBusMessageIter, levels + 1);
353   children = dbus_new(DBusMessageIter, levels + 1);
354
355   v_INT32 = 42;
356   message = simple_method_call ();
357
358   i = 0;
359   dbus_message_iter_init_append (message, &parents[i]);
360   while (i < levels)
361     {
362       dbus_message_iter_open_container (&parents[i], DBUS_TYPE_VARIANT,
363                                         i == (levels - 1) ?
364                                         DBUS_TYPE_INT32_AS_STRING :
365                                         DBUS_TYPE_VARIANT_AS_STRING,
366                                         &children[i]);
367       ++i;
368       parents[i] = children[i-1];
369     }
370   --i;
371   dbus_message_iter_append_basic (&children[i], DBUS_TYPE_INT32, &v_INT32);
372   while (i >= 0)
373     {
374       dbus_message_iter_close_container (&parents[i], &children[i]);
375       --i;
376     }
377
378   dbus_free(parents);
379   dbus_free(children);
380
381   return message;
382 }
383
384 static dbus_bool_t
385 generate_special (DBusMessageDataIter   *iter,
386                   DBusString            *data,
387                   DBusValidity          *expected_validity)
388 {
389   int item_seq;
390   DBusMessage *message;
391   int pos;
392   dbus_int32_t v_INT32;
393
394   _dbus_assert (_dbus_string_get_length (data) == 0);
395   
396   message = NULL;
397   pos = -1;
398   v_INT32 = 42;
399   item_seq = iter_get_sequence (iter);
400
401   if (item_seq == 0)
402     {
403       message = simple_method_call ();
404       if (!dbus_message_append_args (message,
405                                      DBUS_TYPE_INT32, &v_INT32,
406                                      DBUS_TYPE_INT32, &v_INT32,
407                                      DBUS_TYPE_INT32, &v_INT32,
408                                      DBUS_TYPE_INVALID))
409         _dbus_assert_not_reached ("oom");
410                                      
411       _dbus_header_get_field_raw (&message->header,
412                                   DBUS_HEADER_FIELD_SIGNATURE,
413                                   NULL, &pos);
414       generate_from_message (data, expected_validity, message);
415       
416       /* set an invalid typecode */
417       _dbus_string_set_byte (data, pos + 1, '$');
418
419       *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE;
420     }
421   else if (item_seq == 1)
422     {
423       char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+2];
424       const char *v_STRING;
425       int i;
426       
427       message = simple_method_call ();
428       if (!dbus_message_append_args (message,
429                                      DBUS_TYPE_INT32, &v_INT32,
430                                      DBUS_TYPE_INT32, &v_INT32,
431                                      DBUS_TYPE_INT32, &v_INT32,
432                                      DBUS_TYPE_INVALID))
433         _dbus_assert_not_reached ("oom");
434
435       i = 0;
436       while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
437         {
438           long_sig[i] = DBUS_TYPE_ARRAY;
439           ++i;
440         }
441       long_sig[i] = DBUS_TYPE_INVALID;
442
443       v_STRING = long_sig;
444       if (!_dbus_header_set_field_basic (&message->header,
445                                          DBUS_HEADER_FIELD_SIGNATURE,
446                                          DBUS_TYPE_SIGNATURE,
447                                          &v_STRING))
448         _dbus_assert_not_reached ("oom");
449       
450       _dbus_header_get_field_raw (&message->header,
451                                   DBUS_HEADER_FIELD_SIGNATURE,
452                                   NULL, &pos);
453       generate_from_message (data, expected_validity, message);
454       
455       *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
456     }
457   else if (item_seq == 2)
458     {
459       char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+4];
460       const char *v_STRING;
461       int i;
462       
463       message = simple_method_call ();
464       if (!dbus_message_append_args (message,
465                                      DBUS_TYPE_INT32, &v_INT32,
466                                      DBUS_TYPE_INT32, &v_INT32,
467                                      DBUS_TYPE_INT32, &v_INT32,
468                                      DBUS_TYPE_INVALID))
469         _dbus_assert_not_reached ("oom");
470
471       i = 0;
472       while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
473         {
474           long_sig[i] = DBUS_STRUCT_BEGIN_CHAR;
475           ++i;
476         }
477
478       long_sig[i] = DBUS_TYPE_INT32;
479       ++i;
480
481       while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3))
482         {
483           long_sig[i] = DBUS_STRUCT_END_CHAR;
484           ++i;
485         }
486       long_sig[i] = DBUS_TYPE_INVALID;
487       
488       v_STRING = long_sig;
489       if (!_dbus_header_set_field_basic (&message->header,
490                                          DBUS_HEADER_FIELD_SIGNATURE,
491                                          DBUS_TYPE_SIGNATURE,
492                                          &v_STRING))
493         _dbus_assert_not_reached ("oom");
494       
495       _dbus_header_get_field_raw (&message->header,
496                                   DBUS_HEADER_FIELD_SIGNATURE,
497                                   NULL, &pos);
498       generate_from_message (data, expected_validity, message);
499       
500       *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
501     }
502   else if (item_seq == 3)
503     {
504       message = simple_method_call ();
505       if (!dbus_message_append_args (message,
506                                      DBUS_TYPE_INT32, &v_INT32,
507                                      DBUS_TYPE_INT32, &v_INT32,
508                                      DBUS_TYPE_INT32, &v_INT32,
509                                      DBUS_TYPE_INVALID))
510         _dbus_assert_not_reached ("oom");
511                                      
512       _dbus_header_get_field_raw (&message->header,
513                                   DBUS_HEADER_FIELD_SIGNATURE,
514                                   NULL, &pos);
515       generate_from_message (data, expected_validity, message);
516       
517       _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
518       
519       *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
520     }
521   else if (item_seq == 4)
522     {
523       message = simple_method_call ();
524       if (!dbus_message_append_args (message,
525                                      DBUS_TYPE_INT32, &v_INT32,
526                                      DBUS_TYPE_INT32, &v_INT32,
527                                      DBUS_TYPE_INT32, &v_INT32,
528                                      DBUS_TYPE_INVALID))
529         _dbus_assert_not_reached ("oom");
530                                      
531       _dbus_header_get_field_raw (&message->header,
532                                   DBUS_HEADER_FIELD_SIGNATURE,
533                                   NULL, &pos);
534       generate_from_message (data, expected_validity, message);
535       
536       _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR);
537       
538       *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
539     }
540   else if (item_seq == 5)
541     {
542       message = simple_method_call ();
543       if (!dbus_message_append_args (message,
544                                      DBUS_TYPE_INT32, &v_INT32,
545                                      DBUS_TYPE_INT32, &v_INT32,
546                                      DBUS_TYPE_INT32, &v_INT32,
547                                      DBUS_TYPE_INVALID))
548         _dbus_assert_not_reached ("oom");
549                                      
550       _dbus_header_get_field_raw (&message->header,
551                                   DBUS_HEADER_FIELD_SIGNATURE,
552                                   NULL, &pos);
553       generate_from_message (data, expected_validity, message);
554       
555       _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
556       _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR);
557       
558       *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
559     }
560   else if (item_seq == 6)
561     {
562       message = simple_method_call ();
563       generate_from_message (data, expected_validity, message);
564       
565       _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID);
566       
567       *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
568     }
569   else if (item_seq == 7)
570     {
571       /* Messages of unknown type are considered valid */
572       message = simple_method_call ();
573       generate_from_message (data, expected_validity, message);
574       
575       _dbus_string_set_byte (data, TYPE_OFFSET, 100);
576       
577       *expected_validity = DBUS_VALID;
578     }
579   else if (item_seq == 8)
580     {
581       message = simple_method_call ();
582       generate_from_message (data, expected_validity, message);
583       
584       _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
585                                 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
586                                 message->byte_order);
587       _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET,
588                                 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
589                                 message->byte_order);
590       *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG;
591     }
592   else if (item_seq == 9)
593     {
594       const char *v_STRING = "not a valid bus name";
595       message = simple_method_call ();
596
597       if (!_dbus_header_set_field_basic (&message->header,
598                                          DBUS_HEADER_FIELD_SENDER,
599                                          DBUS_TYPE_STRING, &v_STRING))
600         _dbus_assert_not_reached ("oom");
601       
602       generate_from_message (data, expected_validity, message);
603
604       *expected_validity = DBUS_INVALID_BAD_SENDER;
605     }
606   else if (item_seq == 10)
607     {
608       message = simple_method_call ();
609
610       if (!dbus_message_set_interface (message, DBUS_INTERFACE_LOCAL))
611         _dbus_assert_not_reached ("oom");
612       
613       generate_from_message (data, expected_validity, message);
614
615       *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE;
616     }
617   else if (item_seq == 11)
618     {
619       message = simple_method_call ();
620
621       if (!dbus_message_set_path (message, DBUS_PATH_LOCAL))
622         _dbus_assert_not_reached ("oom");
623       
624       generate_from_message (data, expected_validity, message);
625
626       *expected_validity = DBUS_INVALID_USES_LOCAL_PATH;
627     }
628   else if (item_seq == 12)
629     {
630       /* Method calls don't have to have interface */
631       message = simple_method_call ();
632
633       if (!dbus_message_set_interface (message, NULL))
634         _dbus_assert_not_reached ("oom");
635       
636       generate_from_message (data, expected_validity, message);
637       
638       *expected_validity = DBUS_VALID;
639     }
640   else if (item_seq == 13)
641     {
642       /* Signals require an interface */
643       message = simple_signal ();
644
645       if (!dbus_message_set_interface (message, NULL))
646         _dbus_assert_not_reached ("oom");
647       
648       generate_from_message (data, expected_validity, message);
649       
650       *expected_validity = DBUS_INVALID_MISSING_INTERFACE;
651     }
652   else if (item_seq == 14)
653     {
654       message = simple_method_return ();
655
656       if (!_dbus_header_delete_field (&message->header, DBUS_HEADER_FIELD_REPLY_SERIAL))
657         _dbus_assert_not_reached ("oom");
658       
659       generate_from_message (data, expected_validity, message);
660       
661       *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL;
662     }
663   else if (item_seq == 15)
664     {
665       message = simple_error ();
666
667       if (!dbus_message_set_error_name (message, NULL))
668         _dbus_assert_not_reached ("oom");
669       
670       generate_from_message (data, expected_validity, message);
671       
672       *expected_validity = DBUS_INVALID_MISSING_ERROR_NAME;
673     }
674   else if (item_seq == 16)
675     {
676       char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*4+10];
677       const char *v_STRING;
678       int i;
679       int n_begins;
680       
681       message = simple_method_call ();
682       if (!dbus_message_append_args (message,
683                                      DBUS_TYPE_INT32, &v_INT32,
684                                      DBUS_TYPE_INT32, &v_INT32,
685                                      DBUS_TYPE_INT32, &v_INT32,
686                                      DBUS_TYPE_INVALID))
687         _dbus_assert_not_reached ("oom");
688
689       i = 0;
690       while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*3 + 3))
691         {
692           long_sig[i] = DBUS_TYPE_ARRAY;
693           ++i;
694           long_sig[i] = DBUS_DICT_ENTRY_BEGIN_CHAR;
695           ++i;
696           long_sig[i] = DBUS_TYPE_INT32;
697           ++i;
698         }
699       n_begins = i / 3;
700
701       long_sig[i] = DBUS_TYPE_INT32;
702       ++i;
703       
704       while (n_begins > 0)
705         {
706           long_sig[i] = DBUS_DICT_ENTRY_END_CHAR;
707           ++i;
708           n_begins -= 1;
709         }
710       long_sig[i] = DBUS_TYPE_INVALID;
711       
712       v_STRING = long_sig;
713       if (!_dbus_header_set_field_basic (&message->header,
714                                          DBUS_HEADER_FIELD_SIGNATURE,
715                                          DBUS_TYPE_SIGNATURE,
716                                          &v_STRING))
717         _dbus_assert_not_reached ("oom");
718       
719       _dbus_header_get_field_raw (&message->header,
720                                   DBUS_HEADER_FIELD_SIGNATURE,
721                                   NULL, &pos);
722       generate_from_message (data, expected_validity, message);
723       
724       *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
725     }
726   else if (item_seq == 17)
727     {
728       message = simple_method_call ();
729       if (!dbus_message_append_args (message,
730                                      DBUS_TYPE_INT32, &v_INT32,
731                                      DBUS_TYPE_INT32, &v_INT32,
732                                      DBUS_TYPE_INT32, &v_INT32,
733                                      DBUS_TYPE_INVALID))
734         _dbus_assert_not_reached ("oom");
735                                      
736       _dbus_header_get_field_raw (&message->header,
737                                   DBUS_HEADER_FIELD_SIGNATURE,
738                                   NULL, &pos);
739       generate_from_message (data, expected_validity, message);
740
741       _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
742       _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
743       
744       *expected_validity = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
745     }
746   else if (item_seq == 18)
747     {
748       message = simple_method_call ();
749       if (!dbus_message_append_args (message,
750                                      DBUS_TYPE_INT32, &v_INT32,
751                                      DBUS_TYPE_INT32, &v_INT32,
752                                      DBUS_TYPE_INT32, &v_INT32,
753                                      DBUS_TYPE_INVALID))
754         _dbus_assert_not_reached ("oom");
755                                      
756       _dbus_header_get_field_raw (&message->header,
757                                   DBUS_HEADER_FIELD_SIGNATURE,
758                                   NULL, &pos);
759       generate_from_message (data, expected_validity, message);
760       
761       _dbus_string_set_byte (data, pos + 1, DBUS_DICT_ENTRY_END_CHAR);
762       
763       *expected_validity = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
764     }
765   else if (item_seq == 19)
766     {
767       message = simple_method_call ();
768       if (!dbus_message_append_args (message,
769                                      DBUS_TYPE_INT32, &v_INT32,
770                                      DBUS_TYPE_INT32, &v_INT32,
771                                      DBUS_TYPE_INT32, &v_INT32,
772                                      DBUS_TYPE_INVALID))
773         _dbus_assert_not_reached ("oom");
774                                      
775       _dbus_header_get_field_raw (&message->header,
776                                   DBUS_HEADER_FIELD_SIGNATURE,
777                                   NULL, &pos);
778       generate_from_message (data, expected_validity, message);
779
780       _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
781       _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
782       _dbus_string_set_byte (data, pos + 3, DBUS_DICT_ENTRY_END_CHAR);
783       
784       *expected_validity = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
785     }
786   else if (item_seq == 20)
787     {
788       /* 64 levels of nesting is OK */
789       message = message_with_nesting_levels(64);
790
791       generate_from_message (data, expected_validity, message);
792
793       *expected_validity = DBUS_VALID;
794     }
795   else if (item_seq == 21)
796     {
797       /* 65 levels of nesting is not OK */
798       message = message_with_nesting_levels(65);
799
800       generate_from_message (data, expected_validity, message);
801
802       *expected_validity = DBUS_INVALID_NESTED_TOO_DEEPLY;
803     }
804   else
805     {
806       return FALSE;
807     }
808
809   if (message)
810     dbus_message_unref (message);
811
812   iter_next (iter);
813   return TRUE;
814 }
815
816 static dbus_bool_t
817 generate_wrong_length (DBusMessageDataIter *iter,
818                        DBusString          *data,
819                        DBusValidity        *expected_validity)
820 {
821   int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1,
822                     1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 };
823   int adjust;
824   int len_seq;
825
826  restart:
827   len_seq = iter_get_sequence (iter);
828   if (len_seq == _DBUS_N_ELEMENTS (lengths))
829     return FALSE;
830
831   _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths));
832   
833   iter_recurse (iter);
834   if (!generate_many_bodies (iter, data, expected_validity))
835     {
836       iter_set_sequence (iter, 0); /* reset to first body */
837       iter_unrecurse (iter);
838       iter_next (iter);            /* next length adjustment */
839       goto restart;
840     }
841   iter_unrecurse (iter);
842
843   adjust = lengths[len_seq];
844
845   if (adjust < 0)
846     {
847       if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE)
848         _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE);
849       else
850         _dbus_string_shorten (data, - adjust);
851       *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON;
852     }
853   else
854     {      
855       if (!_dbus_string_lengthen (data, adjust))
856         _dbus_assert_not_reached ("oom");
857       *expected_validity = DBUS_INVALID_TOO_MUCH_DATA;
858     }
859
860   /* Fixup lengths */
861   {
862     int old_body_len;
863     int new_body_len;
864     int byte_order;
865     
866     _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE);
867     
868     byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
869     old_body_len = _dbus_marshal_read_uint32 (data,
870                                               BODY_LENGTH_OFFSET,
871                                               byte_order,
872                                               NULL);
873     _dbus_assert (old_body_len < _dbus_string_get_length (data));
874     new_body_len = old_body_len + adjust;
875     if (new_body_len < 0)
876       {
877         new_body_len = 0;
878         /* we just munged the header, and aren't sure how */
879         *expected_validity = DBUS_VALIDITY_UNKNOWN;
880       }
881
882     _dbus_verbose ("changing body len from %u to %u by adjust %d\n",
883                    old_body_len, new_body_len, adjust);
884     
885     _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
886                               new_body_len,
887                               byte_order);
888   }
889
890   return TRUE;
891 }
892
893 static dbus_bool_t
894 generate_byte_changed (DBusMessageDataIter *iter,
895                        DBusString          *data,
896                        DBusValidity        *expected_validity)
897 {
898   int byte_seq;
899   int v_BYTE;
900
901   /* This is a little convoluted to make the bodies the
902    * outer loop and each byte of each body the inner
903    * loop
904    */
905
906  restart:
907   if (!generate_many_bodies (iter, data, expected_validity))
908     return FALSE;
909
910   iter_recurse (iter);
911   byte_seq = iter_get_sequence (iter);
912   iter_next (iter);
913   iter_unrecurse (iter);
914   
915   if (byte_seq == _dbus_string_get_length (data))
916     {
917       _dbus_string_set_length (data, 0);
918       /* reset byte count */
919       iter_recurse (iter);
920       iter_set_sequence (iter, 0);
921       iter_unrecurse (iter);
922       goto restart;
923     }
924   else
925     {
926       /* Undo the "next" in generate_many_bodies */
927       iter_set_sequence (iter, iter_get_sequence (iter) - 1);
928     }
929
930   _dbus_assert (byte_seq < _dbus_string_get_length (data));
931   v_BYTE = _dbus_string_get_byte (data, byte_seq);
932   v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */
933   _dbus_string_set_byte (data, byte_seq, v_BYTE);
934   *expected_validity = DBUS_VALIDITY_UNKNOWN;
935
936   return TRUE;
937 }
938
939 static dbus_bool_t
940 find_next_typecode (DBusMessageDataIter *iter,
941                     DBusString          *data,
942                     DBusValidity        *expected_validity)
943 {
944   int body_seq;
945   int byte_seq;
946   int base_depth;
947
948   base_depth = iter->depth;
949
950  restart:
951   _dbus_assert (iter->depth == (base_depth + 0));
952   _dbus_string_set_length (data, 0);
953
954   body_seq = iter_get_sequence (iter);
955   
956   if (!generate_many_bodies (iter, data, expected_validity))
957     return FALSE;
958   /* Undo the "next" in generate_many_bodies */
959   iter_set_sequence (iter, body_seq);
960   
961   iter_recurse (iter);
962   while (TRUE)
963     {
964       _dbus_assert (iter->depth == (base_depth + 1));
965       
966       byte_seq = iter_get_sequence (iter);
967
968       _dbus_assert (byte_seq <= _dbus_string_get_length (data));
969       
970       if (byte_seq == _dbus_string_get_length (data))
971         {
972           /* reset byte count */
973           iter_set_sequence (iter, 0);
974           iter_unrecurse (iter);
975           _dbus_assert (iter->depth == (base_depth + 0));
976           iter_next (iter); /* go to the next body */
977           goto restart;
978         }
979
980       _dbus_assert (byte_seq < _dbus_string_get_length (data));
981
982       if (dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
983         break;
984       else
985         iter_next (iter);
986     }
987
988   _dbus_assert (byte_seq == iter_get_sequence (iter));
989   _dbus_assert (byte_seq < _dbus_string_get_length (data));
990
991   iter_unrecurse (iter);
992
993   _dbus_assert (iter->depth == (base_depth + 0));
994   
995   return TRUE;
996 }
997
998 static const int typecodes[] = {
999   DBUS_TYPE_INVALID,
1000   DBUS_TYPE_BYTE,
1001   DBUS_TYPE_BOOLEAN,
1002   DBUS_TYPE_INT16,
1003   DBUS_TYPE_UINT16,
1004   DBUS_TYPE_INT32,
1005   DBUS_TYPE_UINT32,
1006   DBUS_TYPE_INT64,
1007   DBUS_TYPE_UINT64,
1008   DBUS_TYPE_DOUBLE,
1009   DBUS_TYPE_STRING,
1010   DBUS_TYPE_OBJECT_PATH,
1011   DBUS_TYPE_SIGNATURE,
1012   DBUS_TYPE_ARRAY,
1013   DBUS_TYPE_VARIANT,
1014   DBUS_STRUCT_BEGIN_CHAR,
1015   DBUS_STRUCT_END_CHAR,
1016   DBUS_DICT_ENTRY_BEGIN_CHAR,
1017   DBUS_DICT_ENTRY_END_CHAR,
1018   DBUS_TYPE_UNIX_FD,
1019   255 /* random invalid typecode */
1020 };
1021   
1022 static dbus_bool_t
1023 generate_typecode_changed (DBusMessageDataIter *iter,
1024                            DBusString          *data,
1025                            DBusValidity        *expected_validity)
1026 {
1027   int byte_seq;
1028   int typecode_seq;
1029   int base_depth;
1030
1031   base_depth = iter->depth;
1032
1033  restart:
1034   _dbus_assert (iter->depth == (base_depth + 0));
1035   _dbus_string_set_length (data, 0);
1036   
1037   if (!find_next_typecode (iter, data, expected_validity))
1038     return FALSE;
1039
1040   iter_recurse (iter);
1041   byte_seq = iter_get_sequence (iter);
1042
1043   _dbus_assert (byte_seq < _dbus_string_get_length (data));
1044   
1045   iter_recurse (iter);
1046   typecode_seq = iter_get_sequence (iter);
1047   iter_next (iter);
1048
1049   _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes));
1050   
1051   if (typecode_seq == _DBUS_N_ELEMENTS (typecodes))
1052     {
1053       _dbus_assert (iter->depth == (base_depth + 2));
1054       iter_set_sequence (iter, 0); /* reset typecode sequence */
1055       iter_unrecurse (iter);
1056       _dbus_assert (iter->depth == (base_depth + 1));
1057       iter_next (iter); /* go to the next byte_seq */
1058       iter_unrecurse (iter);
1059       _dbus_assert (iter->depth == (base_depth + 0));
1060       goto restart;
1061     }
1062
1063   _dbus_assert (iter->depth == (base_depth + 2));
1064   iter_unrecurse (iter);
1065   _dbus_assert (iter->depth == (base_depth + 1));
1066   iter_unrecurse (iter);
1067   _dbus_assert (iter->depth == (base_depth + 0));
1068
1069 #if 0
1070   printf ("Changing byte %d in message %d to %c\n",
1071           byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]);
1072 #endif
1073   
1074   _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]);
1075   *expected_validity = DBUS_VALIDITY_UNKNOWN;
1076   return TRUE;
1077 }
1078
1079 typedef struct
1080 {
1081   ChangeType type;
1082   dbus_uint32_t value; /* cast to signed for adjusts */
1083 } UIntChange;
1084
1085 static const UIntChange uint32_changes[] = {
1086   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -1 },
1087   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -2 },
1088   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -3 },
1089   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 1 },
1090   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 2 },
1091   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 3 },
1092   { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX },
1093   { CHANGE_TYPE_ABSOLUTE, 0 },
1094   { CHANGE_TYPE_ABSOLUTE, 1 },
1095   { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 1 },
1096   { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 5 }
1097 };
1098
1099 static dbus_bool_t
1100 generate_uint32_changed (DBusMessageDataIter *iter,
1101                          DBusString          *data,
1102                          DBusValidity        *expected_validity)
1103 {
1104   int body_seq;
1105   int byte_seq;
1106   int change_seq;
1107   dbus_uint32_t v_UINT32;
1108   int byte_order;
1109   const UIntChange *change;
1110   int base_depth;
1111
1112   /* Outer loop is each body, next loop is each change,
1113    * inner loop is each change location
1114    */
1115
1116   base_depth = iter->depth;
1117   
1118  next_body:
1119   _dbus_assert (iter->depth == (base_depth + 0));
1120   _dbus_string_set_length (data, 0);
1121   body_seq = iter_get_sequence (iter);
1122   
1123   if (!generate_many_bodies (iter, data, expected_validity))
1124     return FALSE;
1125
1126   _dbus_assert (iter->depth == (base_depth + 0));
1127
1128   iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */
1129   iter_recurse (iter);
1130  next_change:
1131   _dbus_assert (iter->depth == (base_depth + 1));
1132   change_seq = iter_get_sequence (iter);
1133   
1134   if (change_seq == _DBUS_N_ELEMENTS (uint32_changes))
1135     {
1136       /* Reset change count */
1137       iter_set_sequence (iter, 0);
1138       iter_unrecurse (iter);
1139       iter_next (iter);
1140       goto next_body;
1141     }
1142
1143   _dbus_assert (iter->depth == (base_depth + 1));
1144   
1145   iter_recurse (iter);
1146   _dbus_assert (iter->depth == (base_depth + 2));
1147   byte_seq = iter_get_sequence (iter);
1148   /* skip 4 bytes at a time */
1149   iter_next (iter);
1150   iter_next (iter);
1151   iter_next (iter);
1152   iter_next (iter);
1153   iter_unrecurse (iter);
1154
1155   _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq);
1156   if (byte_seq >= (_dbus_string_get_length (data) - 4))
1157     {
1158       /* reset byte count */
1159       _dbus_assert (iter->depth == (base_depth + 1));
1160       iter_recurse (iter);
1161       _dbus_assert (iter->depth == (base_depth + 2));
1162       iter_set_sequence (iter, 0);
1163       iter_unrecurse (iter);
1164       _dbus_assert (iter->depth == (base_depth + 1));
1165       iter_next (iter);
1166       goto next_change;
1167     }
1168   
1169   _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4));
1170
1171   byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
1172   
1173   v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL);
1174
1175   change = &uint32_changes[change_seq];
1176
1177   if (change->type == CHANGE_TYPE_ADJUST)
1178     {
1179       v_UINT32 += (int) change->value;
1180     }
1181   else
1182     {
1183       v_UINT32 = change->value;
1184     }
1185
1186 #if 0
1187   printf ("body %d change %d pos %d ",
1188           body_seq, change_seq, byte_seq);
1189
1190   if (change->type == CHANGE_TYPE_ADJUST)
1191     printf ("adjust by %d", (int) change->value);
1192   else
1193     printf ("set to %u", change->value);
1194   
1195   printf (" \t%u -> %u\n",
1196           _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL),
1197           v_UINT32);
1198 #endif
1199   
1200   _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order);
1201   *expected_validity = DBUS_VALIDITY_UNKNOWN;
1202
1203   _dbus_assert (iter->depth == (base_depth + 1));
1204   iter_unrecurse (iter);
1205   _dbus_assert (iter->depth == (base_depth + 0));
1206           
1207   return TRUE;
1208 }
1209
1210 typedef struct
1211 {
1212   const char *name;
1213   DBusMessageGeneratorFunc func;  
1214 } DBusMessageGenerator;
1215
1216 static const DBusMessageGenerator generators[] = {
1217   { "trivial example of each message type", generate_trivial },
1218   { "assorted arguments", generate_many_bodies },
1219   { "assorted special cases", generate_special },
1220   { "each uint32 modified", generate_uint32_changed },
1221   { "wrong body lengths", generate_wrong_length },
1222   { "each byte modified", generate_byte_changed },
1223 #if 0
1224   /* This is really expensive and doesn't add too much coverage */
1225   { "change each typecode", generate_typecode_changed }
1226 #endif
1227 };
1228
1229 void
1230 _dbus_message_data_free (DBusMessageData *data)
1231 {
1232   _dbus_string_free (&data->data);
1233 }
1234
1235 void
1236 _dbus_message_data_iter_init (DBusMessageDataIter *iter)
1237 {
1238   int i;
1239   
1240   iter->depth = 0;
1241   i = 0;
1242   while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
1243     {
1244       iter->sequence_nos[i] = 0;
1245       ++i;
1246     }
1247   iter->count = 0;
1248 }
1249
1250 dbus_bool_t
1251 _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter,
1252                                       DBusMessageData     *data)
1253 {
1254   DBusMessageGeneratorFunc func;
1255   int generator;
1256
1257  restart:
1258   generator = iter_get_sequence (iter);
1259   
1260   if (generator == _DBUS_N_ELEMENTS (generators))
1261     return FALSE;
1262
1263   iter_recurse (iter);
1264   
1265   if (iter_first_in_series (iter))
1266     {
1267       printf (" testing message loading: %s ", generators[generator].name);
1268       fflush (stdout);
1269     }
1270   
1271   func = generators[generator].func;
1272
1273   if (!_dbus_string_init (&data->data))
1274     _dbus_assert_not_reached ("oom");
1275   
1276   if ((*func)(iter, &data->data, &data->expected_validity))
1277     ;
1278   else
1279     {
1280       iter_set_sequence (iter, 0);
1281       iter_unrecurse (iter);
1282       iter_next (iter); /* next generator */
1283       _dbus_string_free (&data->data);
1284       printf ("%d test loads cumulative\n", iter->count);
1285       goto restart;
1286     }
1287   iter_unrecurse (iter);
1288
1289   iter->count += 1;
1290   return TRUE;
1291 }
1292
1293 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
1294
1295 #endif /* DBUS_BUILD_TESTS */