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