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