Bug 19567 - Make marshaling code usable without DBusConnection
[dbus4win.git] / dbus / dbus-message-factory.c
blob8550ee86de0ffb8ea87aa5b89719708dd9a86b02
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
4 * Copyright (C) 2005 Red Hat Inc.
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <config.h>
25 #ifndef DOXYGEN_SHOULD_SKIP_THIS
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>
33 typedef enum
35 CHANGE_TYPE_ADJUST,
36 CHANGE_TYPE_ABSOLUTE
37 } ChangeType;
39 #define BYTE_ORDER_OFFSET 0
40 #define TYPE_OFFSET 1
41 #define BODY_LENGTH_OFFSET 4
42 #define FIELDS_ARRAY_LENGTH_OFFSET 12
44 static void
45 iter_recurse (DBusMessageDataIter *iter)
47 iter->depth += 1;
48 _dbus_assert (iter->depth < _DBUS_MESSAGE_DATA_MAX_NESTING);
49 _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
52 static int
53 iter_get_sequence (DBusMessageDataIter *iter)
55 _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
56 return iter->sequence_nos[iter->depth];
59 static void
60 iter_set_sequence (DBusMessageDataIter *iter,
61 int sequence)
63 _dbus_assert (sequence >= 0);
64 iter->sequence_nos[iter->depth] = sequence;
67 static void
68 iter_unrecurse (DBusMessageDataIter *iter)
70 iter->depth -= 1;
71 _dbus_assert (iter->depth >= 0);
74 static void
75 iter_next (DBusMessageDataIter *iter)
77 iter->sequence_nos[iter->depth] += 1;
80 static dbus_bool_t
81 iter_first_in_series (DBusMessageDataIter *iter)
83 int i;
85 i = iter->depth;
86 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
88 if (iter->sequence_nos[i] != 0)
89 return FALSE;
90 ++i;
92 return TRUE;
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);
101 static void
102 set_reply_serial (DBusMessage *message)
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");
110 static dbus_bool_t
111 generate_trivial_inner (DBusMessageDataIter *iter,
112 DBusMessage **message_p)
114 DBusMessage *message;
116 switch (iter_get_sequence (iter))
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);
136 if (!dbus_message_set_error_name (message,
137 "org.freedesktop.TestErrorName"))
138 _dbus_assert_not_reached ("oom");
141 DBusMessageIter iter;
142 const char *v_STRING = "This is an error";
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");
151 set_reply_serial (message);
152 break;
153 default:
154 return FALSE;
157 if (message == NULL)
158 _dbus_assert_not_reached ("oom");
160 *message_p = message;
162 return TRUE;
165 static dbus_bool_t
166 generate_many_bodies_inner (DBusMessageDataIter *iter,
167 DBusMessage **message_p)
169 DBusMessage *message;
170 DBusString signature;
171 DBusString body;
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");
181 set_reply_serial (message);
183 if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
184 _dbus_assert_not_reached ("oom");
186 if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter),
187 message->byte_order,
188 &signature, &body))
190 const char *v_SIGNATURE;
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");
199 if (!_dbus_string_move (&body, 0, &message->body, 0))
200 _dbus_assert_not_reached ("oom");
202 _dbus_marshal_set_uint32 (&message->header.data, BODY_LENGTH_OFFSET,
203 _dbus_string_get_length (&message->body),
204 message->byte_order);
206 *message_p = message;
208 else
210 dbus_message_unref (message);
211 *message_p = NULL;
214 _dbus_string_free (&signature);
215 _dbus_string_free (&body);
217 return *message_p != NULL;
220 static void
221 generate_from_message (DBusString *data,
222 DBusValidity *expected_validity,
223 DBusMessage *message)
225 dbus_message_set_serial (message, 1);
226 dbus_message_lock (message);
228 *expected_validity = DBUS_VALID;
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");
235 if (!_dbus_string_copy (&message->body, 0,
236 data, _dbus_string_get_length (data)))
237 _dbus_assert_not_reached ("oom");
240 static dbus_bool_t
241 generate_outer (DBusMessageDataIter *iter,
242 DBusString *data,
243 DBusValidity *expected_validity,
244 DBusInnerGeneratorFunc func)
246 DBusMessage *message;
248 message = NULL;
249 if (!(*func)(iter, &message))
250 return FALSE;
252 iter_next (iter);
254 _dbus_assert (message != NULL);
256 generate_from_message (data, expected_validity, message);
258 dbus_message_unref (message);
260 return TRUE;
263 static dbus_bool_t
264 generate_trivial (DBusMessageDataIter *iter,
265 DBusString *data,
266 DBusValidity *expected_validity)
268 return generate_outer (iter, data, expected_validity,
269 generate_trivial_inner);
272 static dbus_bool_t
273 generate_many_bodies (DBusMessageDataIter *iter,
274 DBusString *data,
275 DBusValidity *expected_validity)
277 return generate_outer (iter, data, expected_validity,
278 generate_many_bodies_inner);
281 static DBusMessage*
282 simple_method_call (void)
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;
295 static DBusMessage*
296 simple_signal (void)
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;
307 static DBusMessage*
308 simple_method_return (void)
310 DBusMessage *message;
311 message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
312 if (message == NULL)
313 _dbus_assert_not_reached ("oom");
315 set_reply_serial (message);
317 return message;
320 static DBusMessage*
321 simple_error (void)
323 DBusMessage *message;
324 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
325 if (message == NULL)
326 _dbus_assert_not_reached ("oom");
328 if (!dbus_message_set_error_name (message, "foo.bar"))
329 _dbus_assert_not_reached ("oom");
331 set_reply_serial (message);
333 return message;
336 static dbus_bool_t
337 generate_special (DBusMessageDataIter *iter,
338 DBusString *data,
339 DBusValidity *expected_validity)
341 int item_seq;
342 DBusMessage *message;
343 int pos;
344 dbus_int32_t v_INT32;
346 _dbus_assert (_dbus_string_get_length (data) == 0);
348 message = NULL;
349 pos = -1;
350 v_INT32 = 42;
351 item_seq = iter_get_sequence (iter);
353 if (item_seq == 0)
355 message = simple_method_call ();
356 if (!dbus_message_append_args (message,
357 DBUS_TYPE_INT32, &v_INT32,
358 DBUS_TYPE_INT32, &v_INT32,
359 DBUS_TYPE_INT32, &v_INT32,
360 DBUS_TYPE_INVALID))
361 _dbus_assert_not_reached ("oom");
363 _dbus_header_get_field_raw (&message->header,
364 DBUS_HEADER_FIELD_SIGNATURE,
365 NULL, &pos);
366 generate_from_message (data, expected_validity, message);
368 /* set an invalid typecode */
369 _dbus_string_set_byte (data, pos + 1, '$');
371 *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE;
373 else if (item_seq == 1)
375 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+2];
376 const char *v_STRING;
377 int i;
379 message = simple_method_call ();
380 if (!dbus_message_append_args (message,
381 DBUS_TYPE_INT32, &v_INT32,
382 DBUS_TYPE_INT32, &v_INT32,
383 DBUS_TYPE_INT32, &v_INT32,
384 DBUS_TYPE_INVALID))
385 _dbus_assert_not_reached ("oom");
387 i = 0;
388 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
390 long_sig[i] = DBUS_TYPE_ARRAY;
391 ++i;
393 long_sig[i] = DBUS_TYPE_INVALID;
395 v_STRING = long_sig;
396 if (!_dbus_header_set_field_basic (&message->header,
397 DBUS_HEADER_FIELD_SIGNATURE,
398 DBUS_TYPE_SIGNATURE,
399 &v_STRING))
400 _dbus_assert_not_reached ("oom");
402 _dbus_header_get_field_raw (&message->header,
403 DBUS_HEADER_FIELD_SIGNATURE,
404 NULL, &pos);
405 generate_from_message (data, expected_validity, message);
407 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
409 else if (item_seq == 2)
411 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+4];
412 const char *v_STRING;
413 int i;
415 message = simple_method_call ();
416 if (!dbus_message_append_args (message,
417 DBUS_TYPE_INT32, &v_INT32,
418 DBUS_TYPE_INT32, &v_INT32,
419 DBUS_TYPE_INT32, &v_INT32,
420 DBUS_TYPE_INVALID))
421 _dbus_assert_not_reached ("oom");
423 i = 0;
424 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
426 long_sig[i] = DBUS_STRUCT_BEGIN_CHAR;
427 ++i;
430 long_sig[i] = DBUS_TYPE_INT32;
431 ++i;
433 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3))
435 long_sig[i] = DBUS_STRUCT_END_CHAR;
436 ++i;
438 long_sig[i] = DBUS_TYPE_INVALID;
440 v_STRING = long_sig;
441 if (!_dbus_header_set_field_basic (&message->header,
442 DBUS_HEADER_FIELD_SIGNATURE,
443 DBUS_TYPE_SIGNATURE,
444 &v_STRING))
445 _dbus_assert_not_reached ("oom");
447 _dbus_header_get_field_raw (&message->header,
448 DBUS_HEADER_FIELD_SIGNATURE,
449 NULL, &pos);
450 generate_from_message (data, expected_validity, message);
452 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
454 else if (item_seq == 3)
456 message = simple_method_call ();
457 if (!dbus_message_append_args (message,
458 DBUS_TYPE_INT32, &v_INT32,
459 DBUS_TYPE_INT32, &v_INT32,
460 DBUS_TYPE_INT32, &v_INT32,
461 DBUS_TYPE_INVALID))
462 _dbus_assert_not_reached ("oom");
464 _dbus_header_get_field_raw (&message->header,
465 DBUS_HEADER_FIELD_SIGNATURE,
466 NULL, &pos);
467 generate_from_message (data, expected_validity, message);
469 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
471 *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
473 else if (item_seq == 4)
475 message = simple_method_call ();
476 if (!dbus_message_append_args (message,
477 DBUS_TYPE_INT32, &v_INT32,
478 DBUS_TYPE_INT32, &v_INT32,
479 DBUS_TYPE_INT32, &v_INT32,
480 DBUS_TYPE_INVALID))
481 _dbus_assert_not_reached ("oom");
483 _dbus_header_get_field_raw (&message->header,
484 DBUS_HEADER_FIELD_SIGNATURE,
485 NULL, &pos);
486 generate_from_message (data, expected_validity, message);
488 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR);
490 *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
492 else if (item_seq == 5)
494 message = simple_method_call ();
495 if (!dbus_message_append_args (message,
496 DBUS_TYPE_INT32, &v_INT32,
497 DBUS_TYPE_INT32, &v_INT32,
498 DBUS_TYPE_INT32, &v_INT32,
499 DBUS_TYPE_INVALID))
500 _dbus_assert_not_reached ("oom");
502 _dbus_header_get_field_raw (&message->header,
503 DBUS_HEADER_FIELD_SIGNATURE,
504 NULL, &pos);
505 generate_from_message (data, expected_validity, message);
507 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
508 _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR);
510 *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
512 else if (item_seq == 6)
514 message = simple_method_call ();
515 generate_from_message (data, expected_validity, message);
517 _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID);
519 *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
521 else if (item_seq == 7)
523 /* Messages of unknown type are considered valid */
524 message = simple_method_call ();
525 generate_from_message (data, expected_validity, message);
527 _dbus_string_set_byte (data, TYPE_OFFSET, 100);
529 *expected_validity = DBUS_VALID;
531 else if (item_seq == 8)
533 message = simple_method_call ();
534 generate_from_message (data, expected_validity, message);
536 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
537 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
538 message->byte_order);
539 _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET,
540 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
541 message->byte_order);
542 *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG;
544 else if (item_seq == 9)
546 const char *v_STRING = "not a valid bus name";
547 message = simple_method_call ();
549 if (!_dbus_header_set_field_basic (&message->header,
550 DBUS_HEADER_FIELD_SENDER,
551 DBUS_TYPE_STRING, &v_STRING))
552 _dbus_assert_not_reached ("oom");
554 generate_from_message (data, expected_validity, message);
556 *expected_validity = DBUS_INVALID_BAD_SENDER;
558 else if (item_seq == 10)
560 message = simple_method_call ();
562 if (!dbus_message_set_interface (message, DBUS_INTERFACE_LOCAL))
563 _dbus_assert_not_reached ("oom");
565 generate_from_message (data, expected_validity, message);
567 *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE;
569 else if (item_seq == 11)
571 message = simple_method_call ();
573 if (!dbus_message_set_path (message, DBUS_PATH_LOCAL))
574 _dbus_assert_not_reached ("oom");
576 generate_from_message (data, expected_validity, message);
578 *expected_validity = DBUS_INVALID_USES_LOCAL_PATH;
580 else if (item_seq == 12)
582 /* Method calls don't have to have interface */
583 message = simple_method_call ();
585 if (!dbus_message_set_interface (message, NULL))
586 _dbus_assert_not_reached ("oom");
588 generate_from_message (data, expected_validity, message);
590 *expected_validity = DBUS_VALID;
592 else if (item_seq == 13)
594 /* Signals require an interface */
595 message = simple_signal ();
597 if (!dbus_message_set_interface (message, NULL))
598 _dbus_assert_not_reached ("oom");
600 generate_from_message (data, expected_validity, message);
602 *expected_validity = DBUS_INVALID_MISSING_INTERFACE;
604 else if (item_seq == 14)
606 message = simple_method_return ();
608 if (!_dbus_header_delete_field (&message->header, DBUS_HEADER_FIELD_REPLY_SERIAL))
609 _dbus_assert_not_reached ("oom");
611 generate_from_message (data, expected_validity, message);
613 *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL;
615 else if (item_seq == 15)
617 message = simple_error ();
619 if (!dbus_message_set_error_name (message, NULL))
620 _dbus_assert_not_reached ("oom");
622 generate_from_message (data, expected_validity, message);
624 *expected_validity = DBUS_INVALID_MISSING_ERROR_NAME;
626 else if (item_seq == 16)
628 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*4+10];
629 const char *v_STRING;
630 int i;
631 int n_begins;
633 message = simple_method_call ();
634 if (!dbus_message_append_args (message,
635 DBUS_TYPE_INT32, &v_INT32,
636 DBUS_TYPE_INT32, &v_INT32,
637 DBUS_TYPE_INT32, &v_INT32,
638 DBUS_TYPE_INVALID))
639 _dbus_assert_not_reached ("oom");
641 i = 0;
642 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*3 + 3))
644 long_sig[i] = DBUS_TYPE_ARRAY;
645 ++i;
646 long_sig[i] = DBUS_DICT_ENTRY_BEGIN_CHAR;
647 ++i;
648 long_sig[i] = DBUS_TYPE_INT32;
649 ++i;
651 n_begins = i / 3;
653 long_sig[i] = DBUS_TYPE_INT32;
654 ++i;
656 while (n_begins > 0)
658 long_sig[i] = DBUS_DICT_ENTRY_END_CHAR;
659 ++i;
660 n_begins -= 1;
662 long_sig[i] = DBUS_TYPE_INVALID;
664 v_STRING = long_sig;
665 if (!_dbus_header_set_field_basic (&message->header,
666 DBUS_HEADER_FIELD_SIGNATURE,
667 DBUS_TYPE_SIGNATURE,
668 &v_STRING))
669 _dbus_assert_not_reached ("oom");
671 _dbus_header_get_field_raw (&message->header,
672 DBUS_HEADER_FIELD_SIGNATURE,
673 NULL, &pos);
674 generate_from_message (data, expected_validity, message);
676 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
678 else if (item_seq == 17)
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");
688 _dbus_header_get_field_raw (&message->header,
689 DBUS_HEADER_FIELD_SIGNATURE,
690 NULL, &pos);
691 generate_from_message (data, expected_validity, message);
693 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
694 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
696 *expected_validity = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
698 else if (item_seq == 18)
700 message = simple_method_call ();
701 if (!dbus_message_append_args (message,
702 DBUS_TYPE_INT32, &v_INT32,
703 DBUS_TYPE_INT32, &v_INT32,
704 DBUS_TYPE_INT32, &v_INT32,
705 DBUS_TYPE_INVALID))
706 _dbus_assert_not_reached ("oom");
708 _dbus_header_get_field_raw (&message->header,
709 DBUS_HEADER_FIELD_SIGNATURE,
710 NULL, &pos);
711 generate_from_message (data, expected_validity, message);
713 _dbus_string_set_byte (data, pos + 1, DBUS_DICT_ENTRY_END_CHAR);
715 *expected_validity = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
717 else if (item_seq == 19)
719 message = simple_method_call ();
720 if (!dbus_message_append_args (message,
721 DBUS_TYPE_INT32, &v_INT32,
722 DBUS_TYPE_INT32, &v_INT32,
723 DBUS_TYPE_INT32, &v_INT32,
724 DBUS_TYPE_INVALID))
725 _dbus_assert_not_reached ("oom");
727 _dbus_header_get_field_raw (&message->header,
728 DBUS_HEADER_FIELD_SIGNATURE,
729 NULL, &pos);
730 generate_from_message (data, expected_validity, message);
732 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
733 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
734 _dbus_string_set_byte (data, pos + 3, DBUS_DICT_ENTRY_END_CHAR);
736 *expected_validity = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
738 else
740 return FALSE;
743 if (message)
744 dbus_message_unref (message);
746 iter_next (iter);
747 return TRUE;
750 static dbus_bool_t
751 generate_wrong_length (DBusMessageDataIter *iter,
752 DBusString *data,
753 DBusValidity *expected_validity)
755 int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1,
756 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 };
757 int adjust;
758 int len_seq;
760 restart:
761 len_seq = iter_get_sequence (iter);
762 if (len_seq == _DBUS_N_ELEMENTS (lengths))
763 return FALSE;
765 _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths));
767 iter_recurse (iter);
768 if (!generate_many_bodies (iter, data, expected_validity))
770 iter_set_sequence (iter, 0); /* reset to first body */
771 iter_unrecurse (iter);
772 iter_next (iter); /* next length adjustment */
773 goto restart;
775 iter_unrecurse (iter);
777 adjust = lengths[len_seq];
779 if (adjust < 0)
781 if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE)
782 _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE);
783 else
784 _dbus_string_shorten (data, - adjust);
785 *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON;
787 else
789 if (!_dbus_string_lengthen (data, adjust))
790 _dbus_assert_not_reached ("oom");
791 *expected_validity = DBUS_INVALID_TOO_MUCH_DATA;
794 /* Fixup lengths */
796 int old_body_len;
797 int new_body_len;
798 int byte_order;
800 _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE);
802 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
803 old_body_len = _dbus_marshal_read_uint32 (data,
804 BODY_LENGTH_OFFSET,
805 byte_order,
806 NULL);
807 _dbus_assert (old_body_len < _dbus_string_get_length (data));
808 new_body_len = old_body_len + adjust;
809 if (new_body_len < 0)
811 new_body_len = 0;
812 /* we just munged the header, and aren't sure how */
813 *expected_validity = DBUS_VALIDITY_UNKNOWN;
816 _dbus_verbose ("changing body len from %u to %u by adjust %d\n",
817 old_body_len, new_body_len, adjust);
819 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
820 new_body_len,
821 byte_order);
824 return TRUE;
827 static dbus_bool_t
828 generate_byte_changed (DBusMessageDataIter *iter,
829 DBusString *data,
830 DBusValidity *expected_validity)
832 int byte_seq;
833 int v_BYTE;
835 /* This is a little convoluted to make the bodies the
836 * outer loop and each byte of each body the inner
837 * loop
840 restart:
841 if (!generate_many_bodies (iter, data, expected_validity))
842 return FALSE;
844 iter_recurse (iter);
845 byte_seq = iter_get_sequence (iter);
846 iter_next (iter);
847 iter_unrecurse (iter);
849 if (byte_seq == _dbus_string_get_length (data))
851 _dbus_string_set_length (data, 0);
852 /* reset byte count */
853 iter_recurse (iter);
854 iter_set_sequence (iter, 0);
855 iter_unrecurse (iter);
856 goto restart;
858 else
860 /* Undo the "next" in generate_many_bodies */
861 iter_set_sequence (iter, iter_get_sequence (iter) - 1);
864 _dbus_assert (byte_seq < _dbus_string_get_length (data));
865 v_BYTE = _dbus_string_get_byte (data, byte_seq);
866 v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */
867 _dbus_string_set_byte (data, byte_seq, v_BYTE);
868 *expected_validity = DBUS_VALIDITY_UNKNOWN;
870 return TRUE;
873 static dbus_bool_t
874 find_next_typecode (DBusMessageDataIter *iter,
875 DBusString *data,
876 DBusValidity *expected_validity)
878 int body_seq;
879 int byte_seq;
880 int base_depth;
882 base_depth = iter->depth;
884 restart:
885 _dbus_assert (iter->depth == (base_depth + 0));
886 _dbus_string_set_length (data, 0);
888 body_seq = iter_get_sequence (iter);
890 if (!generate_many_bodies (iter, data, expected_validity))
891 return FALSE;
892 /* Undo the "next" in generate_many_bodies */
893 iter_set_sequence (iter, body_seq);
895 iter_recurse (iter);
896 while (TRUE)
898 _dbus_assert (iter->depth == (base_depth + 1));
900 byte_seq = iter_get_sequence (iter);
902 _dbus_assert (byte_seq <= _dbus_string_get_length (data));
904 if (byte_seq == _dbus_string_get_length (data))
906 /* reset byte count */
907 iter_set_sequence (iter, 0);
908 iter_unrecurse (iter);
909 _dbus_assert (iter->depth == (base_depth + 0));
910 iter_next (iter); /* go to the next body */
911 goto restart;
914 _dbus_assert (byte_seq < _dbus_string_get_length (data));
916 if (_dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
917 break;
918 else
919 iter_next (iter);
922 _dbus_assert (byte_seq == iter_get_sequence (iter));
923 _dbus_assert (byte_seq < _dbus_string_get_length (data));
925 iter_unrecurse (iter);
927 _dbus_assert (iter->depth == (base_depth + 0));
929 return TRUE;
932 static const int typecodes[] = {
933 DBUS_TYPE_INVALID,
934 DBUS_TYPE_BYTE,
935 DBUS_TYPE_BOOLEAN,
936 DBUS_TYPE_INT16,
937 DBUS_TYPE_UINT16,
938 DBUS_TYPE_INT32,
939 DBUS_TYPE_UINT32,
940 DBUS_TYPE_INT64,
941 DBUS_TYPE_UINT64,
942 DBUS_TYPE_DOUBLE,
943 DBUS_TYPE_STRING,
944 DBUS_TYPE_OBJECT_PATH,
945 DBUS_TYPE_SIGNATURE,
946 DBUS_TYPE_ARRAY,
947 DBUS_TYPE_VARIANT,
948 DBUS_STRUCT_BEGIN_CHAR,
949 DBUS_STRUCT_END_CHAR,
950 DBUS_DICT_ENTRY_BEGIN_CHAR,
951 DBUS_DICT_ENTRY_END_CHAR,
952 255 /* random invalid typecode */
955 static dbus_bool_t
956 generate_typecode_changed (DBusMessageDataIter *iter,
957 DBusString *data,
958 DBusValidity *expected_validity)
960 int byte_seq;
961 int typecode_seq;
962 int base_depth;
964 base_depth = iter->depth;
966 restart:
967 _dbus_assert (iter->depth == (base_depth + 0));
968 _dbus_string_set_length (data, 0);
970 if (!find_next_typecode (iter, data, expected_validity))
971 return FALSE;
973 iter_recurse (iter);
974 byte_seq = iter_get_sequence (iter);
976 _dbus_assert (byte_seq < _dbus_string_get_length (data));
978 iter_recurse (iter);
979 typecode_seq = iter_get_sequence (iter);
980 iter_next (iter);
982 _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes));
984 if (typecode_seq == _DBUS_N_ELEMENTS (typecodes))
986 _dbus_assert (iter->depth == (base_depth + 2));
987 iter_set_sequence (iter, 0); /* reset typecode sequence */
988 iter_unrecurse (iter);
989 _dbus_assert (iter->depth == (base_depth + 1));
990 iter_next (iter); /* go to the next byte_seq */
991 iter_unrecurse (iter);
992 _dbus_assert (iter->depth == (base_depth + 0));
993 goto restart;
996 _dbus_assert (iter->depth == (base_depth + 2));
997 iter_unrecurse (iter);
998 _dbus_assert (iter->depth == (base_depth + 1));
999 iter_unrecurse (iter);
1000 _dbus_assert (iter->depth == (base_depth + 0));
1002 #if 0
1003 printf ("Changing byte %d in message %d to %c\n",
1004 byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]);
1005 #endif
1007 _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]);
1008 *expected_validity = DBUS_VALIDITY_UNKNOWN;
1009 return TRUE;
1012 typedef struct
1014 ChangeType type;
1015 dbus_uint32_t value; /* cast to signed for adjusts */
1016 } UIntChange;
1018 static const UIntChange uint32_changes[] = {
1019 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -1 },
1020 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -2 },
1021 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -3 },
1022 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 1 },
1023 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 2 },
1024 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 3 },
1025 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX },
1026 { CHANGE_TYPE_ABSOLUTE, 0 },
1027 { CHANGE_TYPE_ABSOLUTE, 1 },
1028 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 1 },
1029 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 5 }
1032 static dbus_bool_t
1033 generate_uint32_changed (DBusMessageDataIter *iter,
1034 DBusString *data,
1035 DBusValidity *expected_validity)
1037 int body_seq;
1038 int byte_seq;
1039 int change_seq;
1040 dbus_uint32_t v_UINT32;
1041 int byte_order;
1042 const UIntChange *change;
1043 int base_depth;
1045 /* Outer loop is each body, next loop is each change,
1046 * inner loop is each change location
1049 base_depth = iter->depth;
1051 next_body:
1052 _dbus_assert (iter->depth == (base_depth + 0));
1053 _dbus_string_set_length (data, 0);
1054 body_seq = iter_get_sequence (iter);
1056 if (!generate_many_bodies (iter, data, expected_validity))
1057 return FALSE;
1059 _dbus_assert (iter->depth == (base_depth + 0));
1061 iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */
1062 iter_recurse (iter);
1063 next_change:
1064 _dbus_assert (iter->depth == (base_depth + 1));
1065 change_seq = iter_get_sequence (iter);
1067 if (change_seq == _DBUS_N_ELEMENTS (uint32_changes))
1069 /* Reset change count */
1070 iter_set_sequence (iter, 0);
1071 iter_unrecurse (iter);
1072 iter_next (iter);
1073 goto next_body;
1076 _dbus_assert (iter->depth == (base_depth + 1));
1078 iter_recurse (iter);
1079 _dbus_assert (iter->depth == (base_depth + 2));
1080 byte_seq = iter_get_sequence (iter);
1081 /* skip 4 bytes at a time */
1082 iter_next (iter);
1083 iter_next (iter);
1084 iter_next (iter);
1085 iter_next (iter);
1086 iter_unrecurse (iter);
1088 _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq);
1089 if (byte_seq >= (_dbus_string_get_length (data) - 4))
1091 /* reset byte count */
1092 _dbus_assert (iter->depth == (base_depth + 1));
1093 iter_recurse (iter);
1094 _dbus_assert (iter->depth == (base_depth + 2));
1095 iter_set_sequence (iter, 0);
1096 iter_unrecurse (iter);
1097 _dbus_assert (iter->depth == (base_depth + 1));
1098 iter_next (iter);
1099 goto next_change;
1102 _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4));
1104 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
1106 v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL);
1108 change = &uint32_changes[change_seq];
1110 if (change->type == CHANGE_TYPE_ADJUST)
1112 v_UINT32 += (int) change->value;
1114 else
1116 v_UINT32 = change->value;
1119 #if 0
1120 printf ("body %d change %d pos %d ",
1121 body_seq, change_seq, byte_seq);
1123 if (change->type == CHANGE_TYPE_ADJUST)
1124 printf ("adjust by %d", (int) change->value);
1125 else
1126 printf ("set to %u", change->value);
1128 printf (" \t%u -> %u\n",
1129 _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL),
1130 v_UINT32);
1131 #endif
1133 _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order);
1134 *expected_validity = DBUS_VALIDITY_UNKNOWN;
1136 _dbus_assert (iter->depth == (base_depth + 1));
1137 iter_unrecurse (iter);
1138 _dbus_assert (iter->depth == (base_depth + 0));
1140 return TRUE;
1143 typedef struct
1145 const char *name;
1146 DBusMessageGeneratorFunc func;
1147 } DBusMessageGenerator;
1149 static const DBusMessageGenerator generators[] = {
1150 { "trivial example of each message type", generate_trivial },
1151 { "assorted arguments", generate_many_bodies },
1152 { "assorted special cases", generate_special },
1153 { "each uint32 modified", generate_uint32_changed },
1154 { "wrong body lengths", generate_wrong_length },
1155 { "each byte modified", generate_byte_changed },
1156 #if 0
1157 /* This is really expensive and doesn't add too much coverage */
1158 { "change each typecode", generate_typecode_changed }
1159 #endif
1162 void
1163 _dbus_message_data_free (DBusMessageData *data)
1165 _dbus_string_free (&data->data);
1168 void
1169 _dbus_message_data_iter_init (DBusMessageDataIter *iter)
1171 int i;
1173 iter->depth = 0;
1174 i = 0;
1175 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
1177 iter->sequence_nos[i] = 0;
1178 ++i;
1180 iter->count = 0;
1183 dbus_bool_t
1184 _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter,
1185 DBusMessageData *data)
1187 DBusMessageGeneratorFunc func;
1188 int generator;
1190 restart:
1191 generator = iter_get_sequence (iter);
1193 if (generator == _DBUS_N_ELEMENTS (generators))
1194 return FALSE;
1196 iter_recurse (iter);
1198 if (iter_first_in_series (iter))
1200 printf (" testing message loading: %s ", generators[generator].name);
1201 fflush (stdout);
1204 func = generators[generator].func;
1206 if (!_dbus_string_init (&data->data))
1207 _dbus_assert_not_reached ("oom");
1209 if ((*func)(iter, &data->data, &data->expected_validity))
1211 else
1213 iter_set_sequence (iter, 0);
1214 iter_unrecurse (iter);
1215 iter_next (iter); /* next generator */
1216 _dbus_string_free (&data->data);
1217 printf ("%d test loads cumulative\n", iter->count);
1218 goto restart;
1220 iter_unrecurse (iter);
1222 iter->count += 1;
1223 return TRUE;
1226 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
1228 #endif /* DBUS_BUILD_TESTS */