D-Bus 1.12.20
dbus-marshal-recursive-util.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-marshal-recursive-util.c Would be in dbus-marshal-recursive.c, but only used in bus/tests
3 *
4 * Copyright (C) 2004, 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
24#include <config.h>
25
26#ifdef DBUS_ENABLE_EMBEDDED_TESTS
27
28#include "dbus-marshal-recursive.h"
29#include "dbus-marshal-basic.h"
30#include "dbus-signature.h"
31#include "dbus-internals.h"
32#include <string.h>
33
34#if !defined(PRIx64) && defined(DBUS_WIN)
35#define PRIx64 "I64x"
36#endif
37
39#define RECURSIVE_MARSHAL_WRITE_TRACE 0
40
41static void
42basic_value_zero (DBusBasicValue *value)
43{
44 value->u64 = 0;
45}
46
47static dbus_bool_t
48basic_value_equal (int type,
49 DBusBasicValue *lhs,
50 DBusBasicValue *rhs)
51{
52 if (type == DBUS_TYPE_STRING ||
53 type == DBUS_TYPE_SIGNATURE ||
55 {
56 return strcmp (lhs->str, rhs->str) == 0;
57 }
58 else
59 {
60 return lhs->u64 == rhs->u64;
61 }
62}
63
64static dbus_bool_t
65equal_values_helper (DBusTypeReader *lhs,
66 DBusTypeReader *rhs)
67{
68 int lhs_type;
69 int rhs_type;
70
73
74 if (lhs_type != rhs_type)
75 return FALSE;
76
77 if (lhs_type == DBUS_TYPE_INVALID)
78 return TRUE;
79
80 if (dbus_type_is_basic (lhs_type))
81 {
82 DBusBasicValue lhs_value;
83 DBusBasicValue rhs_value;
84
85 basic_value_zero (&lhs_value);
86 basic_value_zero (&rhs_value);
87
88 _dbus_type_reader_read_basic (lhs, &lhs_value);
89 _dbus_type_reader_read_basic (rhs, &rhs_value);
90
91 return basic_value_equal (lhs_type, &lhs_value, &rhs_value);
92 }
93 else
94 {
95 DBusTypeReader lhs_sub;
96 DBusTypeReader rhs_sub;
97
98 _dbus_type_reader_recurse (lhs, &lhs_sub);
99 _dbus_type_reader_recurse (rhs, &rhs_sub);
100
101 return equal_values_helper (&lhs_sub, &rhs_sub);
102 }
103}
104
113_dbus_type_reader_equal_values (const DBusTypeReader *lhs,
114 const DBusTypeReader *rhs)
115{
116 DBusTypeReader copy_lhs = *lhs;
117 DBusTypeReader copy_rhs = *rhs;
118
119 return equal_values_helper (&copy_lhs, &copy_rhs);
120}
121
122/* TESTS */
123
124#ifndef DOXYGEN_SHOULD_SKIP_THIS
125
126#include "dbus-test.h"
127#include "dbus-list.h"
128#include <stdio.h>
129#include <stdlib.h>
130
131/* Whether to do the OOM stuff (only with other expensive tests) */
132#define TEST_OOM_HANDLING 0
133/* We do start offset 0 through 9, to get various alignment cases. Still this
134 * obviously makes the test suite run 10x as slow.
135 */
136#define MAX_INITIAL_OFFSET 9
137
138/* Largest iteration count to test copying, realignment,
139 * etc. with. i.e. we only test this stuff with some of the smaller
140 * data sets.
141 */
142#define MAX_ITERATIONS_FOR_EXPENSIVE_TESTS 1000
143
144typedef struct
145{
146 int byte_order;
147 int initial_offset;
148 DBusString signature;
149 DBusString body;
150} DataBlock;
151
152typedef struct
153{
154 int saved_sig_len;
155 int saved_body_len;
156} DataBlockState;
157
158#define N_FENCE_BYTES 5
159#define FENCE_BYTES_STR "abcde"
160#define INITIAL_PADDING_BYTE '\0'
161
162static dbus_bool_t
163data_block_init (DataBlock *block,
164 int byte_order,
165 int initial_offset)
166{
167 if (!_dbus_string_init (&block->signature))
168 return FALSE;
169
170 if (!_dbus_string_init (&block->body))
171 {
172 _dbus_string_free (&block->signature);
173 return FALSE;
174 }
175
176 if (!_dbus_string_insert_bytes (&block->signature, 0, initial_offset,
177 INITIAL_PADDING_BYTE) ||
178 !_dbus_string_insert_bytes (&block->body, 0, initial_offset,
179 INITIAL_PADDING_BYTE) ||
180 !_dbus_string_append (&block->signature, FENCE_BYTES_STR) ||
181 !_dbus_string_append (&block->body, FENCE_BYTES_STR))
182 {
183 _dbus_string_free (&block->signature);
184 _dbus_string_free (&block->body);
185 return FALSE;
186 }
187
188 block->byte_order = byte_order;
189 block->initial_offset = initial_offset;
190
191 return TRUE;
192}
193
194static void
195data_block_save (DataBlock *block,
196 DataBlockState *state)
197{
198 state->saved_sig_len = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES;
199 state->saved_body_len = _dbus_string_get_length (&block->body) - N_FENCE_BYTES;
200}
201
202static void
203data_block_restore (DataBlock *block,
204 DataBlockState *state)
205{
206 _dbus_string_delete (&block->signature,
207 state->saved_sig_len,
208 _dbus_string_get_length (&block->signature) - state->saved_sig_len - N_FENCE_BYTES);
209 _dbus_string_delete (&block->body,
210 state->saved_body_len,
211 _dbus_string_get_length (&block->body) - state->saved_body_len - N_FENCE_BYTES);
212}
213
214static void
215data_block_verify (DataBlock *block)
216{
217 if (!_dbus_string_ends_with_c_str (&block->signature,
218 FENCE_BYTES_STR))
219 {
220 int offset;
221
222 offset = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - 8;
223 if (offset < 0)
224 offset = 0;
225
226 _dbus_verbose_bytes_of_string (&block->signature,
227 offset,
228 _dbus_string_get_length (&block->signature) - offset);
229 _dbus_assert_not_reached ("block did not verify: bad bytes at end of signature");
230 }
231 if (!_dbus_string_ends_with_c_str (&block->body,
232 FENCE_BYTES_STR))
233 {
234 int offset;
235
236 offset = _dbus_string_get_length (&block->body) - N_FENCE_BYTES - 8;
237 if (offset < 0)
238 offset = 0;
239
240 _dbus_verbose_bytes_of_string (&block->body,
241 offset,
242 _dbus_string_get_length (&block->body) - offset);
243 _dbus_assert_not_reached ("block did not verify: bad bytes at end of body");
244 }
245
246 _dbus_assert (_dbus_string_validate_nul (&block->signature,
247 0, block->initial_offset));
249 0, block->initial_offset));
250}
251
252static void
253data_block_free (DataBlock *block)
254{
255 data_block_verify (block);
256
257 _dbus_string_free (&block->signature);
258 _dbus_string_free (&block->body);
259}
260
261static void
262data_block_reset (DataBlock *block)
263{
264 data_block_verify (block);
265
266 _dbus_string_delete (&block->signature,
267 block->initial_offset,
268 _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - block->initial_offset);
269 _dbus_string_delete (&block->body,
270 block->initial_offset,
271 _dbus_string_get_length (&block->body) - N_FENCE_BYTES - block->initial_offset);
272
273 data_block_verify (block);
274}
275
276static void
277data_block_init_reader_writer (DataBlock *block,
278 DBusTypeReader *reader,
279 DBusTypeWriter *writer)
280{
281 if (reader)
283 block->byte_order,
284 &block->signature,
285 block->initial_offset,
286 &block->body,
287 block->initial_offset);
288
289 if (writer)
291 block->byte_order,
292 &block->signature,
293 _dbus_string_get_length (&block->signature) - N_FENCE_BYTES,
294 &block->body,
295 _dbus_string_get_length (&block->body) - N_FENCE_BYTES);
296}
297
298static void
299real_check_expected_type (DBusTypeReader *reader,
300 int expected,
301 const char *funcname,
302 int line)
303{
304 int t;
305
307
308 if (t != expected)
309 {
310 _dbus_warn ("Read type %s while expecting %s at %s line %d",
312 _dbus_type_to_string (expected),
313 funcname, line);
314
315 _dbus_assert_not_reached ("read wrong type");
316 }
317}
318
319#define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
320
321#define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
322 { \
323 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d", \
324 _DBUS_FUNCTION_NAME, __LINE__); \
325 _dbus_assert_not_reached ("test failed"); \
326 } \
327} while (0)
328
329#define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
330 { \
331 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d", \
332 _DBUS_FUNCTION_NAME, __LINE__); \
333 _dbus_assert_not_reached ("test failed"); \
334 } \
335 check_expected_type (reader, DBUS_TYPE_INVALID); \
336} while (0)
337
338typedef struct TestTypeNode TestTypeNode;
339typedef struct TestTypeNodeClass TestTypeNodeClass;
340typedef struct TestTypeNodeContainer TestTypeNodeContainer;
341typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass;
342
343struct TestTypeNode
344{
345 const TestTypeNodeClass *klass;
346};
347
348struct TestTypeNodeContainer
349{
350 TestTypeNode base;
351 DBusList *children;
352};
353
354struct TestTypeNodeClass
355{
356 int typecode;
357
358 int instance_size;
359
360 int subclass_detail; /* a bad hack to avoid a bunch of subclass casting */
361
362 dbus_bool_t (* construct) (TestTypeNode *node);
363 void (* destroy) (TestTypeNode *node);
364
365 dbus_bool_t (* write_value) (TestTypeNode *node,
366 DataBlock *block,
367 DBusTypeWriter *writer,
368 int seed);
369 dbus_bool_t (* read_value) (TestTypeNode *node,
370 DBusTypeReader *reader,
371 int seed);
372 dbus_bool_t (* set_value) (TestTypeNode *node,
373 DBusTypeReader *reader,
374 DBusTypeReader *realign_root,
375 int seed);
376 dbus_bool_t (* build_signature) (TestTypeNode *node,
377 DBusString *str);
378 dbus_bool_t (* write_multi) (TestTypeNode *node,
379 DataBlock *block,
380 DBusTypeWriter *writer,
381 int seed,
382 int count);
383 dbus_bool_t (* read_multi) (TestTypeNode *node,
384 DBusTypeReader *reader,
385 int seed,
386 int count);
387};
388
389struct TestTypeNodeContainerClass
390{
391 TestTypeNodeClass base;
392};
393
394/* FIXME this could be chilled out substantially by unifying
395 * the basic types into basic_write_value/basic_read_value
396 * and by merging read_value and set_value into one function
397 * taking a flag argument.
398 */
399static dbus_bool_t int16_write_value (TestTypeNode *node,
400 DataBlock *block,
401 DBusTypeWriter *writer,
402 int seed);
403static dbus_bool_t int16_read_value (TestTypeNode *node,
404 DBusTypeReader *reader,
405 int seed);
406static dbus_bool_t int16_set_value (TestTypeNode *node,
407 DBusTypeReader *reader,
408 DBusTypeReader *realign_root,
409 int seed);
410static dbus_bool_t int16_write_multi (TestTypeNode *node,
411 DataBlock *block,
412 DBusTypeWriter *writer,
413 int seed,
414 int count);
415static dbus_bool_t int16_read_multi (TestTypeNode *node,
416 DBusTypeReader *reader,
417 int seed,
418 int count);
419static dbus_bool_t int32_write_value (TestTypeNode *node,
420 DataBlock *block,
421 DBusTypeWriter *writer,
422 int seed);
423static dbus_bool_t int32_read_value (TestTypeNode *node,
424 DBusTypeReader *reader,
425 int seed);
426static dbus_bool_t int32_set_value (TestTypeNode *node,
427 DBusTypeReader *reader,
428 DBusTypeReader *realign_root,
429 int seed);
430static dbus_bool_t int32_write_multi (TestTypeNode *node,
431 DataBlock *block,
432 DBusTypeWriter *writer,
433 int seed,
434 int count);
435static dbus_bool_t int32_read_multi (TestTypeNode *node,
436 DBusTypeReader *reader,
437 int seed,
438 int count);
439static dbus_bool_t int64_write_value (TestTypeNode *node,
440 DataBlock *block,
441 DBusTypeWriter *writer,
442 int seed);
443static dbus_bool_t int64_read_value (TestTypeNode *node,
444 DBusTypeReader *reader,
445 int seed);
446static dbus_bool_t int64_set_value (TestTypeNode *node,
447 DBusTypeReader *reader,
448 DBusTypeReader *realign_root,
449 int seed);
450static dbus_bool_t string_write_value (TestTypeNode *node,
451 DataBlock *block,
452 DBusTypeWriter *writer,
453 int seed);
454static dbus_bool_t string_read_value (TestTypeNode *node,
455 DBusTypeReader *reader,
456 int seed);
457static dbus_bool_t string_set_value (TestTypeNode *node,
458 DBusTypeReader *reader,
459 DBusTypeReader *realign_root,
460 int seed);
461static dbus_bool_t bool_write_value (TestTypeNode *node,
462 DataBlock *block,
463 DBusTypeWriter *writer,
464 int seed);
465static dbus_bool_t bool_read_value (TestTypeNode *node,
466 DBusTypeReader *reader,
467 int seed);
468static dbus_bool_t bool_set_value (TestTypeNode *node,
469 DBusTypeReader *reader,
470 DBusTypeReader *realign_root,
471 int seed);
472static dbus_bool_t byte_write_value (TestTypeNode *node,
473 DataBlock *block,
474 DBusTypeWriter *writer,
475 int seed);
476static dbus_bool_t byte_read_value (TestTypeNode *node,
477 DBusTypeReader *reader,
478 int seed);
479static dbus_bool_t byte_set_value (TestTypeNode *node,
480 DBusTypeReader *reader,
481 DBusTypeReader *realign_root,
482 int seed);
483static dbus_bool_t double_write_value (TestTypeNode *node,
484 DataBlock *block,
485 DBusTypeWriter *writer,
486 int seed);
487static dbus_bool_t double_read_value (TestTypeNode *node,
488 DBusTypeReader *reader,
489 int seed);
490static dbus_bool_t double_set_value (TestTypeNode *node,
491 DBusTypeReader *reader,
492 DBusTypeReader *realign_root,
493 int seed);
494static dbus_bool_t object_path_write_value (TestTypeNode *node,
495 DataBlock *block,
496 DBusTypeWriter *writer,
497 int seed);
498static dbus_bool_t object_path_read_value (TestTypeNode *node,
499 DBusTypeReader *reader,
500 int seed);
501static dbus_bool_t object_path_set_value (TestTypeNode *node,
502 DBusTypeReader *reader,
503 DBusTypeReader *realign_root,
504 int seed);
505static dbus_bool_t signature_write_value (TestTypeNode *node,
506 DataBlock *block,
507 DBusTypeWriter *writer,
508 int seed);
509static dbus_bool_t signature_read_value (TestTypeNode *node,
510 DBusTypeReader *reader,
511 int seed);
512static dbus_bool_t signature_set_value (TestTypeNode *node,
513 DBusTypeReader *reader,
514 DBusTypeReader *realign_root,
515 int seed);
516static dbus_bool_t struct_write_value (TestTypeNode *node,
517 DataBlock *block,
518 DBusTypeWriter *writer,
519 int seed);
520static dbus_bool_t struct_read_value (TestTypeNode *node,
521 DBusTypeReader *reader,
522 int seed);
523static dbus_bool_t struct_set_value (TestTypeNode *node,
524 DBusTypeReader *reader,
525 DBusTypeReader *realign_root,
526 int seed);
527static dbus_bool_t struct_build_signature (TestTypeNode *node,
528 DBusString *str);
529static dbus_bool_t dict_write_value (TestTypeNode *node,
530 DataBlock *block,
531 DBusTypeWriter *writer,
532 int seed);
533static dbus_bool_t dict_read_value (TestTypeNode *node,
534 DBusTypeReader *reader,
535 int seed);
536static dbus_bool_t dict_set_value (TestTypeNode *node,
537 DBusTypeReader *reader,
538 DBusTypeReader *realign_root,
539 int seed);
540static dbus_bool_t dict_build_signature (TestTypeNode *node,
541 DBusString *str);
542static dbus_bool_t array_write_value (TestTypeNode *node,
543 DataBlock *block,
544 DBusTypeWriter *writer,
545 int seed);
546static dbus_bool_t array_read_value (TestTypeNode *node,
547 DBusTypeReader *reader,
548 int seed);
549static dbus_bool_t array_set_value (TestTypeNode *node,
550 DBusTypeReader *reader,
551 DBusTypeReader *realign_root,
552 int seed);
553static dbus_bool_t array_build_signature (TestTypeNode *node,
554 DBusString *str);
555static dbus_bool_t variant_write_value (TestTypeNode *node,
556 DataBlock *block,
557 DBusTypeWriter *writer,
558 int seed);
559static dbus_bool_t variant_read_value (TestTypeNode *node,
560 DBusTypeReader *reader,
561 int seed);
562static dbus_bool_t variant_set_value (TestTypeNode *node,
563 DBusTypeReader *reader,
564 DBusTypeReader *realign_root,
565 int seed);
566static void container_destroy (TestTypeNode *node);
567
568
569
570static const TestTypeNodeClass int16_class = {
572 sizeof (TestTypeNode),
573 0,
574 NULL,
575 NULL,
576 int16_write_value,
577 int16_read_value,
578 int16_set_value,
579 NULL,
580 int16_write_multi,
581 int16_read_multi
582};
583
584static const TestTypeNodeClass uint16_class = {
586 sizeof (TestTypeNode),
587 0,
588 NULL,
589 NULL,
590 int16_write_value, /* recycle from int16 */
591 int16_read_value, /* recycle from int16 */
592 int16_set_value, /* recycle from int16 */
593 NULL,
594 int16_write_multi, /* recycle from int16 */
595 int16_read_multi /* recycle from int16 */
596};
597
598static const TestTypeNodeClass int32_class = {
600 sizeof (TestTypeNode),
601 0,
602 NULL,
603 NULL,
604 int32_write_value,
605 int32_read_value,
606 int32_set_value,
607 NULL,
608 int32_write_multi,
609 int32_read_multi
610};
611
612static const TestTypeNodeClass uint32_class = {
614 sizeof (TestTypeNode),
615 0,
616 NULL,
617 NULL,
618 int32_write_value, /* recycle from int32 */
619 int32_read_value, /* recycle from int32 */
620 int32_set_value, /* recycle from int32 */
621 NULL,
622 int32_write_multi, /* recycle from int32 */
623 int32_read_multi /* recycle from int32 */
624};
625
626static const TestTypeNodeClass int64_class = {
628 sizeof (TestTypeNode),
629 0,
630 NULL,
631 NULL,
632 int64_write_value,
633 int64_read_value,
634 int64_set_value,
635 NULL,
636 NULL, /* FIXME */
637 NULL /* FIXME */
638};
639
640static const TestTypeNodeClass uint64_class = {
642 sizeof (TestTypeNode),
643 0,
644 NULL,
645 NULL,
646 int64_write_value, /* recycle from int64 */
647 int64_read_value, /* recycle from int64 */
648 int64_set_value, /* recycle from int64 */
649 NULL,
650 NULL, /* FIXME */
651 NULL /* FIXME */
652};
653
654static const TestTypeNodeClass string_0_class = {
656 sizeof (TestTypeNode),
657 0, /* string length */
658 NULL,
659 NULL,
660 string_write_value,
661 string_read_value,
662 string_set_value,
663 NULL,
664 NULL,
665 NULL
666};
667
668static const TestTypeNodeClass string_1_class = {
670 sizeof (TestTypeNode),
671 1, /* string length */
672 NULL,
673 NULL,
674 string_write_value,
675 string_read_value,
676 string_set_value,
677 NULL,
678 NULL,
679 NULL
680};
681
682/* with nul, a len 3 string should fill 4 bytes and thus is "special" */
683static const TestTypeNodeClass string_3_class = {
685 sizeof (TestTypeNode),
686 3, /* string length */
687 NULL,
688 NULL,
689 string_write_value,
690 string_read_value,
691 string_set_value,
692 NULL,
693 NULL,
694 NULL
695};
696
697/* with nul, a len 8 string should fill 9 bytes and thus is "special" (far-fetched I suppose) */
698static const TestTypeNodeClass string_8_class = {
700 sizeof (TestTypeNode),
701 8, /* string length */
702 NULL,
703 NULL,
704 string_write_value,
705 string_read_value,
706 string_set_value,
707 NULL,
708 NULL,
709 NULL
710};
711
712static const TestTypeNodeClass bool_class = {
714 sizeof (TestTypeNode),
715 0,
716 NULL,
717 NULL,
718 bool_write_value,
719 bool_read_value,
720 bool_set_value,
721 NULL,
722 NULL, /* FIXME */
723 NULL /* FIXME */
724};
725
726static const TestTypeNodeClass byte_class = {
728 sizeof (TestTypeNode),
729 0,
730 NULL,
731 NULL,
732 byte_write_value,
733 byte_read_value,
734 byte_set_value,
735 NULL,
736 NULL, /* FIXME */
737 NULL /* FIXME */
738};
739
740static const TestTypeNodeClass double_class = {
742 sizeof (TestTypeNode),
743 0,
744 NULL,
745 NULL,
746 double_write_value,
747 double_read_value,
748 double_set_value,
749 NULL,
750 NULL, /* FIXME */
751 NULL /* FIXME */
752};
753
754static const TestTypeNodeClass object_path_class = {
756 sizeof (TestTypeNode),
757 0,
758 NULL,
759 NULL,
760 object_path_write_value,
761 object_path_read_value,
762 object_path_set_value,
763 NULL,
764 NULL,
765 NULL
766};
767
768static const TestTypeNodeClass signature_class = {
770 sizeof (TestTypeNode),
771 0,
772 NULL,
773 NULL,
774 signature_write_value,
775 signature_read_value,
776 signature_set_value,
777 NULL,
778 NULL,
779 NULL
780};
781
782static const TestTypeNodeClass struct_1_class = {
784 sizeof (TestTypeNodeContainer),
785 1, /* number of times children appear as fields */
786 NULL,
787 container_destroy,
788 struct_write_value,
789 struct_read_value,
790 struct_set_value,
791 struct_build_signature,
792 NULL,
793 NULL
794};
795
796static const TestTypeNodeClass struct_2_class = {
798 sizeof (TestTypeNodeContainer),
799 2, /* number of times children appear as fields */
800 NULL,
801 container_destroy,
802 struct_write_value,
803 struct_read_value,
804 struct_set_value,
805 struct_build_signature,
806 NULL,
807 NULL
808};
809
810static const TestTypeNodeClass dict_1_class = {
811 DBUS_TYPE_ARRAY, /* this is correct, a dict is an array of dict entry */
812 sizeof (TestTypeNodeContainer),
813 1, /* number of entries */
814 NULL,
815 container_destroy,
816 dict_write_value,
817 dict_read_value,
818 dict_set_value,
819 dict_build_signature,
820 NULL,
821 NULL
822};
823
824static dbus_bool_t arrays_write_fixed_in_blocks = FALSE;
825
826static const TestTypeNodeClass array_0_class = {
828 sizeof (TestTypeNodeContainer),
829 0, /* number of array elements */
830 NULL,
831 container_destroy,
832 array_write_value,
833 array_read_value,
834 array_set_value,
835 array_build_signature,
836 NULL,
837 NULL
838};
839
840static const TestTypeNodeClass array_1_class = {
842 sizeof (TestTypeNodeContainer),
843 1, /* number of array elements */
844 NULL,
845 container_destroy,
846 array_write_value,
847 array_read_value,
848 array_set_value,
849 array_build_signature,
850 NULL,
851 NULL
852};
853
854static const TestTypeNodeClass array_2_class = {
856 sizeof (TestTypeNodeContainer),
857 2, /* number of array elements */
858 NULL,
859 container_destroy,
860 array_write_value,
861 array_read_value,
862 array_set_value,
863 array_build_signature,
864 NULL,
865 NULL
866};
867
868static const TestTypeNodeClass array_9_class = {
870 sizeof (TestTypeNodeContainer),
871 9, /* number of array elements */
872 NULL,
873 container_destroy,
874 array_write_value,
875 array_read_value,
876 array_set_value,
877 array_build_signature,
878 NULL,
879 NULL
880};
881
882static const TestTypeNodeClass variant_class = {
884 sizeof (TestTypeNodeContainer),
885 0,
886 NULL,
887 container_destroy,
888 variant_write_value,
889 variant_read_value,
890 variant_set_value,
891 NULL,
892 NULL,
893 NULL
894};
895
896static const TestTypeNodeClass* const
897basic_nodes[] = {
898 &int16_class,
899 &uint16_class,
900 &int32_class,
901 &uint32_class,
902 &int64_class,
903 &uint64_class,
904 &bool_class,
905 &byte_class,
906 &double_class,
907 &string_0_class,
908 &string_1_class,
909 &string_3_class,
910 &string_8_class,
911 &object_path_class,
912 &signature_class
913};
914#define N_BASICS (_DBUS_N_ELEMENTS (basic_nodes))
915
916static const TestTypeNodeClass* const
917container_nodes[] = {
918 &struct_1_class,
919 &array_1_class,
920 &struct_2_class,
921 &array_0_class,
922 &array_2_class,
923 &variant_class,
924 &dict_1_class /* last since we want struct and array before it */
925 /* array_9_class is omitted on purpose, it's too slow;
926 * we only use it in one hardcoded test below
927 */
928};
929#define N_CONTAINERS (_DBUS_N_ELEMENTS (container_nodes))
930
931static TestTypeNode*
932node_new (const TestTypeNodeClass *klass)
933{
934 TestTypeNode *node;
935
936 node = dbus_malloc0 (klass->instance_size);
937 if (node == NULL)
938 return NULL;
939
940 node->klass = klass;
941
942 if (klass->construct)
943 {
944 if (!(* klass->construct) (node))
945 {
946 dbus_free (node);
947 return NULL;
948 }
949 }
950
951 return node;
952}
953
954static void
955node_destroy (TestTypeNode *node)
956{
957 if (node->klass->destroy)
958 (* node->klass->destroy) (node);
959 dbus_free (node);
960}
961
962static dbus_bool_t
963node_write_value (TestTypeNode *node,
964 DataBlock *block,
965 DBusTypeWriter *writer,
966 int seed)
967{
968 dbus_bool_t retval;
969
970 retval = (* node->klass->write_value) (node, block, writer, seed);
971
972#if 0
973 /* Handy to see where things break, but too expensive to do all the time */
974 data_block_verify (block);
975#endif
976
977 return retval;
978}
979
980static dbus_bool_t
981node_read_value (TestTypeNode *node,
982 DBusTypeReader *reader,
983 int seed)
984{
985 /* DBusTypeReader restored; */
986
987 if (!(* node->klass->read_value) (node, reader, seed))
988 return FALSE;
989
990 return TRUE;
991}
992
993/* Warning: if this one fails due to OOM, it has side effects (can
994 * modify only some of the sub-values). OK in a test suite, but we
995 * never do this in real code.
996 */
997static dbus_bool_t
998node_set_value (TestTypeNode *node,
999 DBusTypeReader *reader,
1000 DBusTypeReader *realign_root,
1001 int seed)
1002{
1003 if (!(* node->klass->set_value) (node, reader, realign_root, seed))
1004 return FALSE;
1005
1006 return TRUE;
1007}
1008
1009static dbus_bool_t
1010node_build_signature (TestTypeNode *node,
1011 DBusString *str)
1012{
1013 if (node->klass->build_signature)
1014 return (* node->klass->build_signature) (node, str);
1015 else
1016 return _dbus_string_append_byte (str, node->klass->typecode);
1017}
1018
1019static dbus_bool_t
1020node_append_child (TestTypeNode *node,
1021 TestTypeNode *child)
1022{
1023 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
1024
1025 _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer));
1026
1027 if (!_dbus_list_append (&container->children, child))
1028 _dbus_assert_not_reached ("no memory"); /* we never check the return value on node_append_child anyhow - it's run from outside the malloc-failure test code */
1029
1030 return TRUE;
1031}
1032
1033static dbus_bool_t
1034node_write_multi (TestTypeNode *node,
1035 DataBlock *block,
1036 DBusTypeWriter *writer,
1037 int seed,
1038 int n_copies)
1039{
1040 dbus_bool_t retval;
1041
1042 _dbus_assert (node->klass->write_multi != NULL);
1043 retval = (* node->klass->write_multi) (node, block, writer, seed, n_copies);
1044
1045#if 0
1046 /* Handy to see where things break, but too expensive to do all the time */
1047 data_block_verify (block);
1048#endif
1049
1050 return retval;
1051}
1052
1053static dbus_bool_t
1054node_read_multi (TestTypeNode *node,
1055 DBusTypeReader *reader,
1056 int seed,
1057 int n_copies)
1058{
1059 _dbus_assert (node->klass->read_multi != NULL);
1060
1061 if (!(* node->klass->read_multi) (node, reader, seed, n_copies))
1062 return FALSE;
1063
1064 return TRUE;
1065}
1066
1067static int n_iterations_completed_total = 0;
1068static int n_iterations_completed_this_test = 0;
1069static int n_iterations_expected_this_test = 0;
1070
1071typedef struct
1072{
1073 const DBusString *signature;
1074 DataBlock *block;
1075 int type_offset;
1076 TestTypeNode **nodes;
1077 int n_nodes;
1078} NodeIterationData;
1079
1080static dbus_bool_t
1081run_test_copy (NodeIterationData *nid)
1082{
1083 DataBlock *src;
1084 DataBlock dest;
1085 dbus_bool_t retval;
1086 DBusTypeReader reader;
1087 DBusTypeWriter writer;
1088
1089 _dbus_verbose ("\n");
1090
1091 src = nid->block;
1092
1093 retval = FALSE;
1094
1095 if (!data_block_init (&dest, src->byte_order, src->initial_offset))
1096 return FALSE;
1097
1098 data_block_init_reader_writer (src, &reader, NULL);
1099 data_block_init_reader_writer (&dest, NULL, &writer);
1100
1101 /* DBusTypeWriter assumes it's writing into an existing signature,
1102 * so doesn't add nul on its own. We have to do that.
1103 */
1104 if (!_dbus_string_insert_byte (&dest.signature,
1105 dest.initial_offset, '\0'))
1106 goto out;
1107
1108 if (!_dbus_type_writer_write_reader (&writer, &reader))
1109 goto out;
1110
1111 /* Data blocks should now be identical */
1112 if (!_dbus_string_equal (&src->signature, &dest.signature))
1113 {
1114 _dbus_verbose ("SOURCE\n");
1115 _dbus_verbose_bytes_of_string (&src->signature, 0,
1116 _dbus_string_get_length (&src->signature));
1117 _dbus_verbose ("DEST\n");
1118 _dbus_verbose_bytes_of_string (&dest.signature, 0,
1119 _dbus_string_get_length (&dest.signature));
1120 _dbus_assert_not_reached ("signatures did not match");
1121 }
1122
1123 if (!_dbus_string_equal (&src->body, &dest.body))
1124 {
1125 _dbus_verbose ("SOURCE\n");
1126 _dbus_verbose_bytes_of_string (&src->body, 0,
1127 _dbus_string_get_length (&src->body));
1128 _dbus_verbose ("DEST\n");
1129 _dbus_verbose_bytes_of_string (&dest.body, 0,
1130 _dbus_string_get_length (&dest.body));
1131 _dbus_assert_not_reached ("bodies did not match");
1132 }
1133
1134 retval = TRUE;
1135
1136 out:
1137
1138 data_block_free (&dest);
1139
1140 return retval;
1141}
1142
1143static dbus_bool_t
1144run_test_values_only_write (NodeIterationData *nid)
1145{
1146 DBusTypeReader reader;
1147 DBusTypeWriter writer;
1148 int i;
1149 dbus_bool_t retval;
1150 int sig_len;
1151
1152 _dbus_verbose ("\n");
1153
1154 retval = FALSE;
1155
1156 data_block_reset (nid->block);
1157
1158 sig_len = _dbus_string_get_length (nid->signature);
1159
1161 nid->block->byte_order,
1162 nid->signature, 0,
1163 &nid->block->body,
1164 _dbus_string_get_length (&nid->block->body) - N_FENCE_BYTES);
1165 _dbus_type_reader_init (&reader,
1166 nid->block->byte_order,
1167 nid->signature, 0,
1168 &nid->block->body,
1169 nid->block->initial_offset);
1170
1171 i = 0;
1172 while (i < nid->n_nodes)
1173 {
1174 if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
1175 goto out;
1176
1177 ++i;
1178 }
1179
1180 /* if we wrote any typecodes then this would fail */
1181 _dbus_assert (sig_len == _dbus_string_get_length (nid->signature));
1182
1183 /* But be sure we wrote out the values correctly */
1184 i = 0;
1185 while (i < nid->n_nodes)
1186 {
1187 if (!node_read_value (nid->nodes[i], &reader, i))
1188 goto out;
1189
1190 if (i + 1 == nid->n_nodes)
1191 NEXT_EXPECTING_FALSE (&reader);
1192 else
1193 NEXT_EXPECTING_TRUE (&reader);
1194
1195 ++i;
1196 }
1197
1198 retval = TRUE;
1199
1200 out:
1201 data_block_reset (nid->block);
1202 return retval;
1203}
1204
1205/* offset the seed for setting, so we set different numbers than
1206 * we originally wrote. Don't offset by a huge number since in
1207 * some cases it's value = possibilities[seed % n_possibilities]
1208 * and we don't want to wrap around. bool_from_seed
1209 * is just seed % 2 even.
1210 */
1211#define SET_SEED 1
1212static dbus_bool_t
1213run_test_set_values (NodeIterationData *nid)
1214{
1215 DBusTypeReader reader;
1216 DBusTypeReader realign_root;
1217 dbus_bool_t retval;
1218 int i;
1219
1220 _dbus_verbose ("\n");
1221
1222 retval = FALSE;
1223
1224 data_block_init_reader_writer (nid->block,
1225 &reader, NULL);
1226
1227 realign_root = reader;
1228
1229 i = 0;
1230 while (i < nid->n_nodes)
1231 {
1232 if (!node_set_value (nid->nodes[i],
1233 &reader, &realign_root,
1234 i + SET_SEED))
1235 goto out;
1236
1237 if (i + 1 == nid->n_nodes)
1238 NEXT_EXPECTING_FALSE (&reader);
1239 else
1240 NEXT_EXPECTING_TRUE (&reader);
1241
1242 ++i;
1243 }
1244
1245 /* Check that the new values were set */
1246
1247 reader = realign_root;
1248
1249 i = 0;
1250 while (i < nid->n_nodes)
1251 {
1252 if (!node_read_value (nid->nodes[i], &reader,
1253 i + SET_SEED))
1254 goto out;
1255
1256 if (i + 1 == nid->n_nodes)
1257 NEXT_EXPECTING_FALSE (&reader);
1258 else
1259 NEXT_EXPECTING_TRUE (&reader);
1260
1261 ++i;
1262 }
1263
1264 retval = TRUE;
1265
1266 out:
1267 return retval;
1268}
1269
1270static dbus_bool_t
1271run_test_delete_values (NodeIterationData *nid)
1272{
1273 DBusTypeReader reader;
1274 dbus_bool_t retval;
1275 int t;
1276
1277 _dbus_verbose ("\n");
1278
1279 retval = FALSE;
1280
1281 data_block_init_reader_writer (nid->block,
1282 &reader, NULL);
1283
1284 while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
1285 {
1286 /* Right now, deleting only works on array elements. We delete
1287 * all array elements, and then verify that there aren't any
1288 * left.
1289 */
1290 if (t == DBUS_TYPE_ARRAY)
1291 {
1292 DBusTypeReader array;
1293 int n_elements;
1294 int elem_type;
1295
1296 _dbus_type_reader_recurse (&reader, &array);
1297 n_elements = 0;
1299 {
1300 n_elements += 1;
1301 _dbus_type_reader_next (&array);
1302 }
1303
1304 /* reset to start of array */
1305 _dbus_type_reader_recurse (&reader, &array);
1306 _dbus_verbose ("recursing into deletion loop reader.value_pos = %d array.value_pos = %d array.u.start_pos = %d\n",
1307 reader.value_pos, array.value_pos, array.u.array.start_pos);
1308 while ((elem_type = _dbus_type_reader_get_current_type (&array)) != DBUS_TYPE_INVALID)
1309 {
1310 /* We don't want to always delete from the same part of the array. */
1311 static int cycle = 0;
1312 int elem;
1313
1314 _dbus_assert (n_elements > 0);
1315
1316 elem = cycle;
1317 if (elem == 3 || elem >= n_elements) /* end of array */
1318 elem = n_elements - 1;
1319
1320 _dbus_verbose ("deleting array element %d of %d type %s cycle %d reader pos %d elem pos %d\n",
1321 elem, n_elements, _dbus_type_to_string (elem_type),
1322 cycle, reader.value_pos, array.value_pos);
1323 while (elem > 0)
1324 {
1325 if (!_dbus_type_reader_next (&array))
1326 _dbus_assert_not_reached ("should have had another element");
1327 --elem;
1328 }
1329
1330 if (!_dbus_type_reader_delete (&array, &reader))
1331 goto out;
1332
1333 n_elements -= 1;
1334
1335 /* reset */
1336 _dbus_type_reader_recurse (&reader, &array);
1337
1338 if (cycle > 2)
1339 cycle = 0;
1340 else
1341 cycle += 1;
1342 }
1343 }
1344 _dbus_type_reader_next (&reader);
1345 }
1346
1347 /* Check that there are no array elements left */
1348 data_block_init_reader_writer (nid->block,
1349 &reader, NULL);
1350
1351 while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
1352 {
1353 _dbus_type_reader_next (&reader);
1354 }
1355
1356 retval = TRUE;
1357
1358 out:
1359 return retval;
1360}
1361
1362static dbus_bool_t
1363run_test_nodes_iteration (void *data)
1364{
1365 NodeIterationData *nid = data;
1366 DBusTypeReader reader;
1367 DBusTypeWriter writer;
1368 int i;
1369 dbus_bool_t retval;
1370
1371 /* Stuff to do:
1372 * 1. write the value
1373 * 2. strcmp-compare with the signature we built
1374 * 3. read the value
1375 * 4. type-iterate the signature and the value and see if they are the same type-wise
1376 */
1377 retval = FALSE;
1378
1379 data_block_init_reader_writer (nid->block,
1380 &reader, &writer);
1381
1382 /* DBusTypeWriter assumes it's writing into an existing signature,
1383 * so doesn't add nul on its own. We have to do that.
1384 */
1385 if (!_dbus_string_insert_byte (&nid->block->signature,
1386 nid->type_offset, '\0'))
1387 goto out;
1388
1389 i = 0;
1390 while (i < nid->n_nodes)
1391 {
1392 if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
1393 goto out;
1394
1395 ++i;
1396 }
1397
1398 if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
1399 &nid->block->signature, nid->type_offset))
1400 {
1401 _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d",
1402 _dbus_string_get_const_data (nid->signature),
1403 _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
1404 nid->type_offset);
1405 _dbus_assert_not_reached ("wrong signature");
1406 }
1407
1408 i = 0;
1409 while (i < nid->n_nodes)
1410 {
1411 if (!node_read_value (nid->nodes[i], &reader, i))
1412 goto out;
1413
1414 if (i + 1 == nid->n_nodes)
1415 NEXT_EXPECTING_FALSE (&reader);
1416 else
1417 NEXT_EXPECTING_TRUE (&reader);
1418
1419 ++i;
1420 }
1421
1422 if (n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
1423 {
1424 /* this set values test uses code from copy and
1425 * values_only_write so would ideally be last so you get a
1426 * simpler test case for problems with copying or values_only
1427 * writing; but it also needs an already-written DataBlock so it
1428 * has to go first. Comment it out if it breaks, and see if the
1429 * later tests also break - debug them first if so.
1430 */
1431 if (!run_test_set_values (nid))
1432 goto out;
1433
1434 if (!run_test_delete_values (nid))
1435 goto out;
1436
1437 if (!run_test_copy (nid))
1438 goto out;
1439
1440 if (!run_test_values_only_write (nid))
1441 goto out;
1442 }
1443
1444 /* FIXME type-iterate both signature and value and compare the resulting
1445 * tree to the node tree perhaps
1446 */
1447
1448 retval = TRUE;
1449
1450 out:
1451
1452 data_block_reset (nid->block);
1453
1454 return retval;
1455}
1456
1457static void
1458run_test_nodes_in_one_configuration (TestTypeNode **nodes,
1459 int n_nodes,
1460 const DBusString *signature,
1461 int byte_order,
1462 int initial_offset)
1463{
1464 DataBlock block;
1465 NodeIterationData nid;
1466
1467 if (!data_block_init (&block, byte_order, initial_offset))
1468 _dbus_assert_not_reached ("no memory");
1469
1470 nid.signature = signature;
1471 nid.block = &block;
1472 nid.type_offset = initial_offset;
1473 nid.nodes = nodes;
1474 nid.n_nodes = n_nodes;
1475
1476 if (TEST_OOM_HANDLING &&
1477 n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
1478 {
1479 _dbus_test_oom_handling ("running test node",
1480 run_test_nodes_iteration,
1481 &nid);
1482 }
1483 else
1484 {
1485 if (!run_test_nodes_iteration (&nid))
1486 _dbus_assert_not_reached ("no memory");
1487 }
1488
1489 data_block_free (&block);
1490}
1491
1492static void
1493run_test_nodes (TestTypeNode **nodes,
1494 int n_nodes)
1495{
1496 int i;
1497 DBusString signature;
1498
1499 if (!_dbus_string_init (&signature))
1500 _dbus_assert_not_reached ("no memory");
1501
1502 i = 0;
1503 while (i < n_nodes)
1504 {
1505 if (! node_build_signature (nodes[i], &signature))
1506 _dbus_assert_not_reached ("no memory");
1507
1508 ++i;
1509 }
1510
1511 _dbus_verbose (">>> test nodes with signature '%s'\n",
1512 _dbus_string_get_const_data (&signature));
1513
1514 i = 0;
1515 while (i <= MAX_INITIAL_OFFSET)
1516 {
1517 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
1519 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
1520 DBUS_BIG_ENDIAN, i);
1521
1522 ++i;
1523 }
1524
1525 n_iterations_completed_this_test += 1;
1526 n_iterations_completed_total += 1;
1527
1528 if (n_iterations_completed_this_test == n_iterations_expected_this_test)
1529 {
1530 fprintf (stderr, " 100%% %d this test (%d cumulative)\n",
1531 n_iterations_completed_this_test,
1532 n_iterations_completed_total);
1533 }
1534 /* this happens to turn out well with mod == 1 */
1535 else if ((n_iterations_completed_this_test %
1536 (int)(n_iterations_expected_this_test / 10.0)) == 1)
1537 {
1538 fprintf (stderr, " %d%% ", (int) (n_iterations_completed_this_test / (double) n_iterations_expected_this_test * 100));
1539 }
1540
1541 _dbus_string_free (&signature);
1542}
1543
1544#define N_VALUES (N_BASICS * N_CONTAINERS + N_BASICS)
1545
1546static TestTypeNode*
1547value_generator (int *ip)
1548{
1549 int i = *ip;
1550 const TestTypeNodeClass *child_klass;
1551 const TestTypeNodeClass *container_klass;
1552 TestTypeNode *child;
1553 TestTypeNode *node;
1554
1555 _dbus_assert (i <= N_VALUES);
1556
1557 if (i == N_VALUES)
1558 {
1559 return NULL;
1560 }
1561 else if (i < N_BASICS)
1562 {
1563 node = node_new (basic_nodes[i]);
1564 }
1565 else
1566 {
1567 /* imagine an array:
1568 * container 0 of basic 0
1569 * container 0 of basic 1
1570 * container 0 of basic 2
1571 * container 1 of basic 0
1572 * container 1 of basic 1
1573 * container 1 of basic 2
1574 */
1575 i -= N_BASICS;
1576
1577 container_klass = container_nodes[i / N_BASICS];
1578 child_klass = basic_nodes[i % N_BASICS];
1579
1580 node = node_new (container_klass);
1581 child = node_new (child_klass);
1582
1583 node_append_child (node, child);
1584 }
1585
1586 *ip += 1; /* increment the generator */
1587
1588 return node;
1589}
1590
1591static void
1592build_body (TestTypeNode **nodes,
1593 int n_nodes,
1594 int byte_order,
1595 DBusString *signature,
1596 DBusString *body)
1597{
1598 int i;
1599 DataBlock block;
1600 DBusTypeReader reader;
1601 DBusTypeWriter writer;
1602
1603 i = 0;
1604 while (i < n_nodes)
1605 {
1606 if (! node_build_signature (nodes[i], signature))
1607 _dbus_assert_not_reached ("no memory");
1608
1609 ++i;
1610 }
1611
1612 if (!data_block_init (&block, byte_order, 0))
1613 _dbus_assert_not_reached ("no memory");
1614
1615 data_block_init_reader_writer (&block,
1616 &reader, &writer);
1617
1618 /* DBusTypeWriter assumes it's writing into an existing signature,
1619 * so doesn't add nul on its own. We have to do that.
1620 */
1621 if (!_dbus_string_insert_byte (&block.signature,
1622 0, '\0'))
1623 _dbus_assert_not_reached ("no memory");
1624
1625 i = 0;
1626 while (i < n_nodes)
1627 {
1628 if (!node_write_value (nodes[i], &block, &writer, i))
1629 _dbus_assert_not_reached ("no memory");
1630
1631 ++i;
1632 }
1633
1634 if (!_dbus_string_copy_len (&block.body, 0,
1635 _dbus_string_get_length (&block.body) - N_FENCE_BYTES,
1636 body, 0))
1638
1639 data_block_free (&block);
1640}
1641
1643dbus_internal_do_not_use_generate_bodies (int sequence,
1644 int byte_order,
1645 DBusString *signature,
1646 DBusString *body)
1647{
1648 TestTypeNode *nodes[1];
1649 int i;
1650 int n_nodes;
1651
1652 nodes[0] = value_generator (&sequence);
1653
1654 if (nodes[0] == NULL)
1655 return FALSE;
1656
1657 n_nodes = 1;
1658
1659 build_body (nodes, n_nodes, byte_order, signature, body);
1660
1661
1662 i = 0;
1663 while (i < n_nodes)
1664 {
1665 node_destroy (nodes[i]);
1666 ++i;
1667 }
1668
1669 return TRUE;
1670}
1671
1672static void
1673make_and_run_values_inside_container (const TestTypeNodeClass *container_klass,
1674 int n_nested)
1675{
1676 TestTypeNode *root;
1677 TestTypeNode *container;
1678 TestTypeNode *child;
1679 int i;
1680
1681 root = node_new (container_klass);
1682 container = root;
1683 for (i = 1; i < n_nested; i++)
1684 {
1685 child = node_new (container_klass);
1686 node_append_child (container, child);
1687 container = child;
1688 }
1689
1690 /* container should now be the most-nested container */
1691
1692 i = 0;
1693 while ((child = value_generator (&i)))
1694 {
1695 node_append_child (container, child);
1696
1697 run_test_nodes (&root, 1);
1698
1699 _dbus_list_clear (&((TestTypeNodeContainer*)container)->children);
1700 node_destroy (child);
1701 }
1702
1703 node_destroy (root);
1704}
1705
1706static void
1707start_next_test (const char *description,
1708 int expected)
1709{
1710 n_iterations_completed_this_test = 0;
1711 n_iterations_expected_this_test = expected;
1712
1713 fprintf (stderr, ">>> >>> %s %d iterations\n",
1714 description,
1715 n_iterations_expected_this_test);
1716}
1717
1718static void
1719make_and_run_test_nodes (void)
1720{
1721 int i, j, k, m;
1722
1723 /* We try to do this in order of "complicatedness" so that test
1724 * failures tend to show up in the simplest test case that
1725 * demonstrates the failure. There are also some tests that run
1726 * more than once for this reason, first while going through simple
1727 * cases, second while going through a broader range of complex
1728 * cases.
1729 */
1730 /* Each basic node. The basic nodes should include:
1731 *
1732 * - each fixed-size type (in such a way that it has different values each time,
1733 * so we can tell if we mix two of them up)
1734 * - strings of various lengths
1735 * - object path
1736 * - signature
1737 */
1738 /* Each container node. The container nodes should include:
1739 *
1740 * struct with 1 and 2 copies of the contained item
1741 * array with 0, 1, 2 copies of the contained item
1742 * variant
1743 */
1744 /* Let a "value" be a basic node, or a container containing a single basic node.
1745 * Let n_values be the number of such values i.e. (n_container * n_basic + n_basic)
1746 * When iterating through all values to make combinations, do the basic types
1747 * first and the containers second.
1748 */
1749 /* Each item is shown with its number of iterations to complete so
1750 * we can keep a handle on this unit test
1751 */
1752
1753 /* FIXME test just an empty body, no types at all */
1754
1755 start_next_test ("Each value by itself", N_VALUES);
1756 {
1757 TestTypeNode *node;
1758 i = 0;
1759 while ((node = value_generator (&i)))
1760 {
1761 run_test_nodes (&node, 1);
1762
1763 node_destroy (node);
1764 }
1765 }
1766
1767 start_next_test ("Each value by itself with arrays as blocks", N_VALUES);
1768 arrays_write_fixed_in_blocks = TRUE;
1769 {
1770 TestTypeNode *node;
1771 i = 0;
1772 while ((node = value_generator (&i)))
1773 {
1774 run_test_nodes (&node, 1);
1775
1776 node_destroy (node);
1777 }
1778 }
1779 arrays_write_fixed_in_blocks = FALSE;
1780
1781 start_next_test ("All values in one big toplevel", 1);
1782 {
1783 TestTypeNode *nodes[N_VALUES];
1784 TestTypeNode *node;
1785
1786 i = 0;
1787 while ((node = value_generator (&i)))
1788 {
1789 nodes[i - 1] = node;
1790 }
1791
1792 run_test_nodes (nodes, N_VALUES);
1793
1794 for (i = 0; i < N_VALUES; i++)
1795 node_destroy (nodes[i]);
1796 }
1797
1798 start_next_test ("Each value,value pair combination as toplevel, in both orders",
1799 N_VALUES * N_VALUES);
1800 {
1801 TestTypeNode *nodes[2];
1802
1803 i = 0;
1804 while ((nodes[0] = value_generator (&i)))
1805 {
1806 j = 0;
1807 while ((nodes[1] = value_generator (&j)))
1808 {
1809 run_test_nodes (nodes, 2);
1810
1811 node_destroy (nodes[1]);
1812 }
1813
1814 node_destroy (nodes[0]);
1815 }
1816 }
1817
1818 start_next_test ("Each container containing each value",
1819 N_CONTAINERS * N_VALUES);
1820 for (i = 0; i < N_CONTAINERS; i++)
1821 {
1822 const TestTypeNodeClass *container_klass = container_nodes[i];
1823
1824 make_and_run_values_inside_container (container_klass, 1);
1825 }
1826
1827 start_next_test ("Each container containing each value with arrays as blocks",
1828 N_CONTAINERS * N_VALUES);
1829 arrays_write_fixed_in_blocks = TRUE;
1830 for (i = 0; i < N_CONTAINERS; i++)
1831 {
1832 const TestTypeNodeClass *container_klass = container_nodes[i];
1833
1834 make_and_run_values_inside_container (container_klass, 1);
1835 }
1836 arrays_write_fixed_in_blocks = FALSE;
1837
1838 start_next_test ("Each container of same container of each value",
1839 N_CONTAINERS * N_VALUES);
1840 for (i = 0; i < N_CONTAINERS; i++)
1841 {
1842 const TestTypeNodeClass *container_klass = container_nodes[i];
1843
1844 make_and_run_values_inside_container (container_klass, 2);
1845 }
1846
1847 start_next_test ("Each container of same container of same container of each value",
1848 N_CONTAINERS * N_VALUES);
1849 for (i = 0; i < N_CONTAINERS; i++)
1850 {
1851 const TestTypeNodeClass *container_klass = container_nodes[i];
1852
1853 make_and_run_values_inside_container (container_klass, 3);
1854 }
1855
1856 start_next_test ("Each value,value pair inside a struct",
1857 N_VALUES * N_VALUES);
1858 {
1859 TestTypeNode *val1, *val2;
1860 TestTypeNode *node;
1861
1862 node = node_new (&struct_1_class);
1863
1864 i = 0;
1865 while ((val1 = value_generator (&i)))
1866 {
1867 j = 0;
1868 while ((val2 = value_generator (&j)))
1869 {
1870 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
1871
1872 node_append_child (node, val1);
1873 node_append_child (node, val2);
1874
1875 run_test_nodes (&node, 1);
1876
1877 _dbus_list_clear (&container->children);
1878 node_destroy (val2);
1879 }
1880 node_destroy (val1);
1881 }
1882 node_destroy (node);
1883 }
1884
1885 start_next_test ("All values in one big struct", 1);
1886 {
1887 TestTypeNode *node;
1888 TestTypeNode *child;
1889
1890 node = node_new (&struct_1_class);
1891
1892 i = 0;
1893 while ((child = value_generator (&i)))
1894 node_append_child (node, child);
1895
1896 run_test_nodes (&node, 1);
1897
1898 node_destroy (node);
1899 }
1900
1901 start_next_test ("Each value in a large array", N_VALUES);
1902 {
1903 TestTypeNode *val;
1904 TestTypeNode *node;
1905
1906 node = node_new (&array_9_class);
1907
1908 i = 0;
1909 while ((val = value_generator (&i)))
1910 {
1911 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
1912
1913 node_append_child (node, val);
1914
1915 run_test_nodes (&node, 1);
1916
1917 _dbus_list_clear (&container->children);
1918 node_destroy (val);
1919 }
1920
1921 node_destroy (node);
1922 }
1923
1924 if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL ||
1925 atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1)
1926 {
1927 fprintf (stderr, "skipping remaining marshal-recursive tests, "
1928 "run with DBUS_TEST_SLOW=1 (or more) to enable\n");
1929 goto out;
1930 }
1931
1932 start_next_test ("Each container of each container of each value",
1933 N_CONTAINERS * N_CONTAINERS * N_VALUES);
1934 for (i = 0; i < N_CONTAINERS; i++)
1935 {
1936 const TestTypeNodeClass *outer_container_klass = container_nodes[i];
1937 TestTypeNode *outer_container = node_new (outer_container_klass);
1938
1939 for (j = 0; j < N_CONTAINERS; j++)
1940 {
1941 TestTypeNode *child;
1942 const TestTypeNodeClass *inner_container_klass = container_nodes[j];
1943 TestTypeNode *inner_container = node_new (inner_container_klass);
1944
1945 node_append_child (outer_container, inner_container);
1946
1947 m = 0;
1948 while ((child = value_generator (&m)))
1949 {
1950 node_append_child (inner_container, child);
1951
1952 run_test_nodes (&outer_container, 1);
1953
1954 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
1955 node_destroy (child);
1956 }
1957 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
1958 node_destroy (inner_container);
1959 }
1960 node_destroy (outer_container);
1961 }
1962
1963 start_next_test ("Each container of each container of each container of each value",
1964 N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
1965 for (i = 0; i < N_CONTAINERS; i++)
1966 {
1967 const TestTypeNodeClass *outer_container_klass = container_nodes[i];
1968 TestTypeNode *outer_container = node_new (outer_container_klass);
1969
1970 for (j = 0; j < N_CONTAINERS; j++)
1971 {
1972 const TestTypeNodeClass *inner_container_klass = container_nodes[j];
1973 TestTypeNode *inner_container = node_new (inner_container_klass);
1974
1975 node_append_child (outer_container, inner_container);
1976
1977 for (k = 0; k < N_CONTAINERS; k++)
1978 {
1979 TestTypeNode *child;
1980 const TestTypeNodeClass *center_container_klass = container_nodes[k];
1981 TestTypeNode *center_container = node_new (center_container_klass);
1982
1983 node_append_child (inner_container, center_container);
1984
1985 m = 0;
1986 while ((child = value_generator (&m)))
1987 {
1988 node_append_child (center_container, child);
1989
1990 run_test_nodes (&outer_container, 1);
1991
1992 _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
1993 node_destroy (child);
1994 }
1995 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
1996 node_destroy (center_container);
1997 }
1998 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
1999 node_destroy (inner_container);
2000 }
2001 node_destroy (outer_container);
2002 }
2003
2004 /* This one takes a really long time (10 minutes on a Core2), so only enable
2005 * it if you're really sure */
2006 if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2)
2007 {
2008 fprintf (stderr, "skipping really slow marshal-recursive test, "
2009 "run with DBUS_TEST_SLOW=2 (or more) to enable\n");
2010 goto out;
2011 }
2012
2013 start_next_test ("Each value,value,value triplet combination as toplevel, in all orders",
2014 N_VALUES * N_VALUES * N_VALUES);
2015 {
2016 TestTypeNode *nodes[3];
2017
2018 i = 0;
2019 while ((nodes[0] = value_generator (&i)))
2020 {
2021 j = 0;
2022 while ((nodes[1] = value_generator (&j)))
2023 {
2024 k = 0;
2025 while ((nodes[2] = value_generator (&k)))
2026 {
2027 run_test_nodes (nodes, 3);
2028
2029 node_destroy (nodes[2]);
2030 }
2031 node_destroy (nodes[1]);
2032 }
2033 node_destroy (nodes[0]);
2034 }
2035 }
2036
2037out:
2038 fprintf (stderr, "%d total iterations of recursive marshaling tests\n",
2039 n_iterations_completed_total);
2040 fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n",
2041 MAX_INITIAL_OFFSET);
2042 fprintf (stderr, "out of memory handling %s tested\n",
2043 TEST_OOM_HANDLING ? "was" : "was not");
2044}
2045
2047_dbus_marshal_recursive_test (void)
2048{
2049 make_and_run_test_nodes ();
2050
2051 return TRUE;
2052}
2053
2054/*
2055 *
2056 *
2057 * Implementations of each type node class
2058 *
2059 *
2060 *
2061 */
2062#define MAX_MULTI_COUNT 5
2063
2064#define SAMPLE_INT16 1234
2065#define SAMPLE_INT16_ALTERNATE 6785
2066static dbus_int16_t
2067int16_from_seed (int seed)
2068{
2069 /* Generate an integer value that's predictable from seed. We could
2070 * just use seed itself, but that would only ever touch one byte of
2071 * the int so would miss some kinds of bug.
2072 */
2073 static const dbus_int16_t v_of_seed[5] = {
2074 SAMPLE_INT16,
2075 SAMPLE_INT16_ALTERNATE,
2076 -1,
2078 1
2079 };
2080
2081 dbus_int16_t v = v_of_seed[seed % _DBUS_N_ELEMENTS(v_of_seed)];
2082
2083 if (seed > 1)
2084 v *= seed; /* wraps around eventually, which is fine */
2085
2086 return v;
2087}
2088
2089static dbus_bool_t
2090int16_write_value (TestTypeNode *node,
2091 DataBlock *block,
2092 DBusTypeWriter *writer,
2093 int seed)
2094{
2095 /* also used for uint16 */
2096 dbus_int16_t v;
2097
2098 v = int16_from_seed (seed);
2099
2100 return _dbus_type_writer_write_basic (writer,
2101 node->klass->typecode,
2102 &v);
2103}
2104
2105static dbus_bool_t
2106int16_read_value (TestTypeNode *node,
2107 DBusTypeReader *reader,
2108 int seed)
2109{
2110 /* also used for uint16 */
2111 dbus_int16_t v;
2112
2113 check_expected_type (reader, node->klass->typecode);
2114
2116 (dbus_int16_t*) &v);
2117
2118 _dbus_assert (v == int16_from_seed (seed));
2119
2120 return TRUE;
2121}
2122
2123static dbus_bool_t
2124int16_set_value (TestTypeNode *node,
2125 DBusTypeReader *reader,
2126 DBusTypeReader *realign_root,
2127 int seed)
2128{
2129 /* also used for uint16 */
2130 dbus_int16_t v;
2131
2132 v = int16_from_seed (seed);
2133
2134 return _dbus_type_reader_set_basic (reader,
2135 &v,
2136 realign_root);
2137}
2138
2139static dbus_bool_t
2140int16_write_multi (TestTypeNode *node,
2141 DataBlock *block,
2142 DBusTypeWriter *writer,
2143 int seed,
2144 int count)
2145{
2146 /* also used for uint16 */
2147 dbus_int16_t values[MAX_MULTI_COUNT];
2148 dbus_int16_t *v_ARRAY_INT16 = values;
2149 int i;
2150
2151 for (i = 0; i < count; ++i)
2152 values[i] = int16_from_seed (seed + i);
2153
2155 node->klass->typecode,
2156 &v_ARRAY_INT16, count);
2157}
2158
2159static dbus_bool_t
2160int16_read_multi (TestTypeNode *node,
2161 DBusTypeReader *reader,
2162 int seed,
2163 int count)
2164{
2165 /* also used for uint16 */
2166 dbus_int16_t *values;
2167 int n_elements;
2168 int i;
2169
2170 check_expected_type (reader, node->klass->typecode);
2171
2173 &values,
2174 &n_elements);
2175
2176 if (n_elements != count)
2177 _dbus_warn ("got %d elements expected %d", n_elements, count);
2178 _dbus_assert (n_elements == count);
2179
2180 for (i = 0; i < count; i++)
2181 _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
2182 (const unsigned char*)values + (i * 2))) ==
2183 int16_from_seed (seed + i));
2184
2185 return TRUE;
2186}
2187
2188
2189#define SAMPLE_INT32 12345678
2190#define SAMPLE_INT32_ALTERNATE 53781429
2191static dbus_int32_t
2192int32_from_seed (int seed)
2193{
2194 /* Generate an integer value that's predictable from seed. We could
2195 * just use seed itself, but that would only ever touch one byte of
2196 * the int so would miss some kinds of bug.
2197 */
2198 static const dbus_int32_t v_of_seed[5] = {
2199 SAMPLE_INT32,
2200 SAMPLE_INT32_ALTERNATE,
2201 -1,
2203 1
2204 };
2205
2206 dbus_int32_t v = v_of_seed[seed % _DBUS_N_ELEMENTS(v_of_seed)];
2207
2208 if (seed > 1)
2209 v *= seed; /* wraps around eventually, which is fine */
2210
2211 return v;
2212}
2213
2214static dbus_bool_t
2215int32_write_value (TestTypeNode *node,
2216 DataBlock *block,
2217 DBusTypeWriter *writer,
2218 int seed)
2219{
2220 /* also used for uint32 */
2221 dbus_int32_t v;
2222
2223 v = int32_from_seed (seed);
2224
2225 return _dbus_type_writer_write_basic (writer,
2226 node->klass->typecode,
2227 &v);
2228}
2229
2230static dbus_bool_t
2231int32_read_value (TestTypeNode *node,
2232 DBusTypeReader *reader,
2233 int seed)
2234{
2235 /* also used for uint32 */
2236 dbus_int32_t v;
2237
2238 check_expected_type (reader, node->klass->typecode);
2239
2241 (dbus_int32_t*) &v);
2242
2243 _dbus_assert (v == int32_from_seed (seed));
2244
2245 return TRUE;
2246}
2247
2248static dbus_bool_t
2249int32_set_value (TestTypeNode *node,
2250 DBusTypeReader *reader,
2251 DBusTypeReader *realign_root,
2252 int seed)
2253{
2254 /* also used for uint32 */
2255 dbus_int32_t v;
2256
2257 v = int32_from_seed (seed);
2258
2259 return _dbus_type_reader_set_basic (reader,
2260 &v,
2261 realign_root);
2262}
2263
2264static dbus_bool_t
2265int32_write_multi (TestTypeNode *node,
2266 DataBlock *block,
2267 DBusTypeWriter *writer,
2268 int seed,
2269 int count)
2270{
2271 /* also used for uint32 */
2272 dbus_int32_t values[MAX_MULTI_COUNT];
2273 dbus_int32_t *v_ARRAY_INT32 = values;
2274 int i;
2275
2276 for (i = 0; i < count; ++i)
2277 values[i] = int32_from_seed (seed + i);
2278
2280 node->klass->typecode,
2281 &v_ARRAY_INT32, count);
2282}
2283
2284static dbus_bool_t
2285int32_read_multi (TestTypeNode *node,
2286 DBusTypeReader *reader,
2287 int seed,
2288 int count)
2289{
2290 /* also used for uint32 */
2291 dbus_int32_t *values;
2292 int n_elements;
2293 int i;
2294
2295 check_expected_type (reader, node->klass->typecode);
2296
2298 &values,
2299 &n_elements);
2300
2301 if (n_elements != count)
2302 _dbus_warn ("got %d elements expected %d", n_elements, count);
2303 _dbus_assert (n_elements == count);
2304
2305 for (i = 0; i < count; i++)
2307 (const unsigned char*)values + (i * 4))) ==
2308 int32_from_seed (seed + i));
2309
2310 return TRUE;
2311}
2312
2313static dbus_int64_t
2314int64_from_seed (int seed)
2315{
2316 dbus_int32_t v32;
2317 dbus_int64_t v;
2318
2319 v32 = int32_from_seed (seed);
2320
2321 v = - (dbus_int32_t) ~ v32;
2322 v |= (((dbus_int64_t)v32) << 32);
2323
2324 return v;
2325}
2326
2327static dbus_bool_t
2328int64_write_value (TestTypeNode *node,
2329 DataBlock *block,
2330 DBusTypeWriter *writer,
2331 int seed)
2332{
2333 /* also used for uint64 */
2334 dbus_int64_t v;
2335
2336 v = int64_from_seed (seed);
2337
2338 return _dbus_type_writer_write_basic (writer,
2339 node->klass->typecode,
2340 &v);
2341}
2342
2343static dbus_bool_t
2344int64_read_value (TestTypeNode *node,
2345 DBusTypeReader *reader,
2346 int seed)
2347{
2348 /* also used for uint64 */
2349 dbus_int64_t v;
2350
2351 check_expected_type (reader, node->klass->typecode);
2352
2354 (dbus_int64_t*) &v);
2355
2356 _dbus_assert (v == int64_from_seed (seed));
2357
2358 return TRUE;
2359}
2360
2361static dbus_bool_t
2362int64_set_value (TestTypeNode *node,
2363 DBusTypeReader *reader,
2364 DBusTypeReader *realign_root,
2365 int seed)
2366{
2367 /* also used for uint64 */
2368 dbus_int64_t v;
2369
2370 v = int64_from_seed (seed);
2371
2372 return _dbus_type_reader_set_basic (reader,
2373 &v,
2374 realign_root);
2375}
2376
2377#define MAX_SAMPLE_STRING_LEN 10
2378static void
2379string_from_seed (char *buf,
2380 int len,
2381 int seed)
2382{
2383 int i;
2384 unsigned char v;
2385
2386 _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
2387
2388 /* vary the length slightly, though we also have multiple string
2389 * value types for this, varying it here tests the set_value code
2390 */
2391 switch (seed % 3)
2392 {
2393 default:
2394 /* don't alter it */
2395 break;
2396 case 1:
2397 len += 2;
2398 break;
2399 case 2:
2400 len -= 2;
2401 break;
2402 }
2403 if (len < 0)
2404 len = 0;
2405
2406 v = (unsigned char) ('A' + seed);
2407
2408 i = 0;
2409 while (i < len)
2410 {
2411 if (v < 'A' || v > 'z')
2412 v = 'A';
2413
2414 buf[i] = v;
2415
2416 v += 1;
2417 ++i;
2418 }
2419
2420 buf[i] = '\0';
2421}
2422
2423static dbus_bool_t
2424string_write_value (TestTypeNode *node,
2425 DataBlock *block,
2426 DBusTypeWriter *writer,
2427 int seed)
2428{
2429 char buf[MAX_SAMPLE_STRING_LEN + 1]="";
2430 const char *v_string = buf;
2431
2432
2433 string_from_seed (buf, node->klass->subclass_detail,
2434 seed);
2435
2436 return _dbus_type_writer_write_basic (writer,
2437 node->klass->typecode,
2438 &v_string);
2439}
2440
2441static dbus_bool_t
2442string_read_value (TestTypeNode *node,
2443 DBusTypeReader *reader,
2444 int seed)
2445{
2446 const char *v;
2447 char buf[MAX_SAMPLE_STRING_LEN + 1];
2448 v = buf;
2449
2450 check_expected_type (reader, node->klass->typecode);
2451
2453 (const char **) &v);
2454
2455 string_from_seed (buf, node->klass->subclass_detail,
2456 seed);
2457
2458 if (strcmp (buf, v) != 0)
2459 {
2460 _dbus_warn ("read string '%s' expected '%s'",
2461 v, buf);
2462 _dbus_assert_not_reached ("test failed");
2463 }
2464
2465 return TRUE;
2466}
2467
2468static dbus_bool_t
2469string_set_value (TestTypeNode *node,
2470 DBusTypeReader *reader,
2471 DBusTypeReader *realign_root,
2472 int seed)
2473{
2474 char buf[MAX_SAMPLE_STRING_LEN + 1];
2475 const char *v_string = buf;
2476
2477 string_from_seed (buf, node->klass->subclass_detail,
2478 seed);
2479
2480#if RECURSIVE_MARSHAL_WRITE_TRACE
2481 {
2482 const char *old;
2483 _dbus_type_reader_read_basic (reader, &old);
2484 _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
2485 v_string, strlen (v_string), old, strlen (old));
2486 }
2487#endif
2488
2489 return _dbus_type_reader_set_basic (reader,
2490 &v_string,
2491 realign_root);
2492}
2493
2494#define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
2495
2496static dbus_bool_t
2497bool_write_value (TestTypeNode *node,
2498 DataBlock *block,
2499 DBusTypeWriter *writer,
2500 int seed)
2501{
2502 dbus_bool_t v;
2503
2504 v = BOOL_FROM_SEED (seed);
2505
2506 return _dbus_type_writer_write_basic (writer,
2507 node->klass->typecode,
2508 &v);
2509}
2510
2511static dbus_bool_t
2512bool_read_value (TestTypeNode *node,
2513 DBusTypeReader *reader,
2514 int seed)
2515{
2516 dbus_bool_t v;
2517
2518 check_expected_type (reader, node->klass->typecode);
2519
2521 (unsigned char*) &v);
2522
2523 _dbus_assert (v == BOOL_FROM_SEED (seed));
2524
2525 return TRUE;
2526}
2527
2528static dbus_bool_t
2529bool_set_value (TestTypeNode *node,
2530 DBusTypeReader *reader,
2531 DBusTypeReader *realign_root,
2532 int seed)
2533{
2534 dbus_bool_t v;
2535
2536 v = BOOL_FROM_SEED (seed);
2537
2538 return _dbus_type_reader_set_basic (reader,
2539 &v,
2540 realign_root);
2541}
2542
2543#define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
2544
2545static dbus_bool_t
2546byte_write_value (TestTypeNode *node,
2547 DataBlock *block,
2548 DBusTypeWriter *writer,
2549 int seed)
2550{
2551 unsigned char v;
2552
2553 v = BYTE_FROM_SEED (seed);
2554
2555 return _dbus_type_writer_write_basic (writer,
2556 node->klass->typecode,
2557 &v);
2558}
2559
2560static dbus_bool_t
2561byte_read_value (TestTypeNode *node,
2562 DBusTypeReader *reader,
2563 int seed)
2564{
2565 unsigned char v;
2566
2567 check_expected_type (reader, node->klass->typecode);
2568
2570 (unsigned char*) &v);
2571
2572 _dbus_assert (v == BYTE_FROM_SEED (seed));
2573
2574 return TRUE;
2575}
2576
2577
2578static dbus_bool_t
2579byte_set_value (TestTypeNode *node,
2580 DBusTypeReader *reader,
2581 DBusTypeReader *realign_root,
2582 int seed)
2583{
2584 unsigned char v;
2585
2586 v = BYTE_FROM_SEED (seed);
2587
2588 return _dbus_type_reader_set_basic (reader,
2589 &v,
2590 realign_root);
2591}
2592
2593static double
2594double_from_seed (int seed)
2595{
2596 return SAMPLE_INT32 * (double) seed + 0.3;
2597}
2598
2599static dbus_bool_t
2600double_write_value (TestTypeNode *node,
2601 DataBlock *block,
2602 DBusTypeWriter *writer,
2603 int seed)
2604{
2605 double v;
2606
2607 v = double_from_seed (seed);
2608
2609 return _dbus_type_writer_write_basic (writer,
2610 node->klass->typecode,
2611 &v);
2612}
2613
2614static dbus_bool_t
2615double_read_value (TestTypeNode *node,
2616 DBusTypeReader *reader,
2617 int seed)
2618{
2619 double v;
2620 double expected;
2621
2622 check_expected_type (reader, node->klass->typecode);
2623
2625 (double*) &v);
2626
2627 expected = double_from_seed (seed);
2628
2629 if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
2630 {
2631 _dbus_warn ("Expected double %g got %g\n bits = 0x%" PRIx64 " vs.\n bits = 0x%" PRIx64,
2632 expected, v,
2633 *(dbus_uint64_t*)(char*)&expected,
2634 *(dbus_uint64_t*)(char*)&v);
2635 _dbus_assert_not_reached ("test failed");
2636 }
2637
2638 return TRUE;
2639}
2640
2641static dbus_bool_t
2642double_set_value (TestTypeNode *node,
2643 DBusTypeReader *reader,
2644 DBusTypeReader *realign_root,
2645 int seed)
2646{
2647 double v;
2648
2649 v = double_from_seed (seed);
2650
2651 return _dbus_type_reader_set_basic (reader,
2652 &v,
2653 realign_root);
2654}
2655
2656#define MAX_SAMPLE_OBJECT_PATH_LEN 10
2657static void
2658object_path_from_seed (char *buf,
2659 int seed)
2660{
2661 int i;
2662 unsigned char v;
2663 int len;
2664
2665 len = seed % 9;
2666 _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
2667
2668 v = (unsigned char) ('A' + seed);
2669
2670 if (len < 2)
2671 {
2672 buf[0] = '/';
2673 i = 1;
2674 }
2675 else
2676 {
2677 i = 0;
2678 while (i + 1 < len)
2679 {
2680 if (v < 'A' || v > 'z')
2681 v = 'A';
2682
2683 buf[i] = '/';
2684 ++i;
2685 buf[i] = v;
2686 ++i;
2687
2688 v += 1;
2689 }
2690 }
2691
2692 buf[i] = '\0';
2693}
2694
2695static dbus_bool_t
2696object_path_write_value (TestTypeNode *node,
2697 DataBlock *block,
2698 DBusTypeWriter *writer,
2699 int seed)
2700{
2701 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2702 const char *v_string = buf;
2703
2704 object_path_from_seed (buf, seed);
2705
2706 return _dbus_type_writer_write_basic (writer,
2707 node->klass->typecode,
2708 &v_string);
2709}
2710
2711static dbus_bool_t
2712object_path_read_value (TestTypeNode *node,
2713 DBusTypeReader *reader,
2714 int seed)
2715{
2716 const char *v;
2717 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2718
2719 check_expected_type (reader, node->klass->typecode);
2720
2722 (const char **) &v);
2723
2724 object_path_from_seed (buf, seed);
2725
2726 if (strcmp (buf, v) != 0)
2727 {
2728 _dbus_warn ("read object path '%s' expected '%s'",
2729 v, buf);
2730 _dbus_assert_not_reached ("test failed");
2731 }
2732
2733 return TRUE;
2734}
2735
2736static dbus_bool_t
2737object_path_set_value (TestTypeNode *node,
2738 DBusTypeReader *reader,
2739 DBusTypeReader *realign_root,
2740 int seed)
2741{
2742 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2743 const char *v_string = buf;
2744
2745 object_path_from_seed (buf, seed);
2746
2747 return _dbus_type_reader_set_basic (reader,
2748 &v_string,
2749 realign_root);
2750}
2751
2752#define MAX_SAMPLE_SIGNATURE_LEN 10
2753static void
2754signature_from_seed (char *buf,
2755 int seed)
2756{
2757 /* try to avoid ascending, descending, or alternating length to help find bugs */
2758 const char *sample_signatures[] = {
2759 "asax",
2760 "",
2761 "asau(xxxx)",
2762 "x",
2763 "ai",
2764 "a(ii)"
2765 };
2766
2767 strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
2768}
2769
2770static dbus_bool_t
2771signature_write_value (TestTypeNode *node,
2772 DataBlock *block,
2773 DBusTypeWriter *writer,
2774 int seed)
2775{
2776 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2777 const char *v_string = buf;
2778
2779 signature_from_seed (buf, seed);
2780
2781 return _dbus_type_writer_write_basic (writer,
2782 node->klass->typecode,
2783 &v_string);
2784}
2785
2786static dbus_bool_t
2787signature_read_value (TestTypeNode *node,
2788 DBusTypeReader *reader,
2789 int seed)
2790{
2791 const char *v;
2792 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2793
2794 check_expected_type (reader, node->klass->typecode);
2795
2797 (const char **) &v);
2798
2799 signature_from_seed (buf, seed);
2800
2801 if (strcmp (buf, v) != 0)
2802 {
2803 _dbus_warn ("read signature value '%s' expected '%s'",
2804 v, buf);
2805 _dbus_assert_not_reached ("test failed");
2806 }
2807
2808 return TRUE;
2809}
2810
2811
2812static dbus_bool_t
2813signature_set_value (TestTypeNode *node,
2814 DBusTypeReader *reader,
2815 DBusTypeReader *realign_root,
2816 int seed)
2817{
2818 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2819 const char *v_string = buf;
2820
2821 signature_from_seed (buf, seed);
2822
2823 return _dbus_type_reader_set_basic (reader,
2824 &v_string,
2825 realign_root);
2826}
2827
2828static dbus_bool_t
2829struct_write_value (TestTypeNode *node,
2830 DataBlock *block,
2831 DBusTypeWriter *writer,
2832 int seed)
2833{
2834 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2835 DataBlockState saved;
2836 DBusTypeWriter sub;
2837 int i;
2838 int n_copies;
2839
2840 n_copies = node->klass->subclass_detail;
2841
2842 _dbus_assert (container->children != NULL);
2843
2844 data_block_save (block, &saved);
2845
2847 NULL, 0,
2848 &sub))
2849 return FALSE;
2850
2851 i = 0;
2852 while (i < n_copies)
2853 {
2854 DBusList *link;
2855
2856 link = _dbus_list_get_first_link (&container->children);
2857 while (link != NULL)
2858 {
2859 TestTypeNode *child = link->data;
2860 DBusList *next = _dbus_list_get_next_link (&container->children, link);
2861
2862 if (!node_write_value (child, block, &sub, seed + i))
2863 {
2864 data_block_restore (block, &saved);
2865 return FALSE;
2866 }
2867
2868 link = next;
2869 }
2870
2871 ++i;
2872 }
2873
2874 if (!_dbus_type_writer_unrecurse (writer, &sub))
2875 {
2876 data_block_restore (block, &saved);
2877 return FALSE;
2878 }
2879
2880 return TRUE;
2881}
2882
2883static dbus_bool_t
2884struct_read_or_set_value (TestTypeNode *node,
2885 DBusTypeReader *reader,
2886 DBusTypeReader *realign_root,
2887 int seed)
2888{
2889 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2890 DBusTypeReader sub;
2891 int i;
2892 int n_copies;
2893
2894 n_copies = node->klass->subclass_detail;
2895
2896 check_expected_type (reader, DBUS_TYPE_STRUCT);
2897
2898 _dbus_type_reader_recurse (reader, &sub);
2899
2900 i = 0;
2901 while (i < n_copies)
2902 {
2903 DBusList *link;
2904
2905 link = _dbus_list_get_first_link (&container->children);
2906 while (link != NULL)
2907 {
2908 TestTypeNode *child = link->data;
2909 DBusList *next = _dbus_list_get_next_link (&container->children, link);
2910
2911 if (realign_root == NULL)
2912 {
2913 if (!node_read_value (child, &sub, seed + i))
2914 return FALSE;
2915 }
2916 else
2917 {
2918 if (!node_set_value (child, &sub, realign_root, seed + i))
2919 return FALSE;
2920 }
2921
2922 if (i == (n_copies - 1) && next == NULL)
2923 NEXT_EXPECTING_FALSE (&sub);
2924 else
2925 NEXT_EXPECTING_TRUE (&sub);
2926
2927 link = next;
2928 }
2929
2930 ++i;
2931 }
2932
2933 return TRUE;
2934}
2935
2936static dbus_bool_t
2937struct_read_value (TestTypeNode *node,
2938 DBusTypeReader *reader,
2939 int seed)
2940{
2941 return struct_read_or_set_value (node, reader, NULL, seed);
2942}
2943
2944static dbus_bool_t
2945struct_set_value (TestTypeNode *node,
2946 DBusTypeReader *reader,
2947 DBusTypeReader *realign_root,
2948 int seed)
2949{
2950 return struct_read_or_set_value (node, reader, realign_root, seed);
2951}
2952
2953static dbus_bool_t
2954struct_build_signature (TestTypeNode *node,
2955 DBusString *str)
2956{
2957 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2958 int i;
2959 int orig_len;
2960 int n_copies;
2961
2962 n_copies = node->klass->subclass_detail;
2963
2964 orig_len = _dbus_string_get_length (str);
2965
2967 goto oom;
2968
2969 i = 0;
2970 while (i < n_copies)
2971 {
2972 DBusList *link;
2973
2974 link = _dbus_list_get_first_link (&container->children);
2975 while (link != NULL)
2976 {
2977 TestTypeNode *child = link->data;
2978 DBusList *next = _dbus_list_get_next_link (&container->children, link);
2979
2980 if (!node_build_signature (child, str))
2981 goto oom;
2982
2983 link = next;
2984 }
2985
2986 ++i;
2987 }
2988
2990 goto oom;
2991
2992 return TRUE;
2993
2994 oom:
2995 _dbus_string_set_length (str, orig_len);
2996 return FALSE;
2997}
2998
2999static dbus_bool_t
3000array_write_value (TestTypeNode *node,
3001 DataBlock *block,
3002 DBusTypeWriter *writer,
3003 int seed)
3004{
3005 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3006 DataBlockState saved;
3007 DBusTypeWriter sub;
3008 DBusString element_signature;
3009 int i;
3010 int n_copies;
3011 int element_type;
3012 TestTypeNode *child;
3013
3014 n_copies = node->klass->subclass_detail;
3015
3016 _dbus_assert (container->children != NULL);
3017
3018 data_block_save (block, &saved);
3019
3020 if (!_dbus_string_init (&element_signature))
3021 return FALSE;
3022
3023 child = _dbus_list_get_first (&container->children);
3024
3025 if (!node_build_signature (child,
3026 &element_signature))
3027 goto oom;
3028
3029 element_type = _dbus_first_type_in_signature (&element_signature, 0);
3030
3032 &element_signature, 0,
3033 &sub))
3034 goto oom;
3035
3036 if (arrays_write_fixed_in_blocks &&
3037 dbus_type_is_fixed (element_type) &&
3038 child->klass->write_multi)
3039 {
3040 if (!node_write_multi (child, block, &sub, seed, n_copies))
3041 goto oom;
3042 }
3043 else
3044 {
3045 i = 0;
3046 while (i < n_copies)
3047 {
3048 DBusList *link;
3049
3050 link = _dbus_list_get_first_link (&container->children);
3051 while (link != NULL)
3052 {
3053 TestTypeNode *child2 = link->data;
3054 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3055
3056 if (!node_write_value (child2, block, &sub, seed + i))
3057 goto oom;
3058
3059 link = next;
3060 }
3061
3062 ++i;
3063 }
3064 }
3065
3066 if (!_dbus_type_writer_unrecurse (writer, &sub))
3067 goto oom;
3068
3069 _dbus_string_free (&element_signature);
3070 return TRUE;
3071
3072 oom:
3073 data_block_restore (block, &saved);
3074 _dbus_string_free (&element_signature);
3075 return FALSE;
3076}
3077
3078static dbus_bool_t
3079array_read_or_set_value (TestTypeNode *node,
3080 DBusTypeReader *reader,
3081 DBusTypeReader *realign_root,
3082 int seed)
3083{
3084 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3085 DBusTypeReader sub;
3086 int i;
3087 int n_copies;
3088 TestTypeNode *child;
3089
3090 n_copies = node->klass->subclass_detail;
3091
3092 check_expected_type (reader, DBUS_TYPE_ARRAY);
3093
3094 child = _dbus_list_get_first (&container->children);
3095
3096 if (n_copies > 0)
3097 {
3098 _dbus_type_reader_recurse (reader, &sub);
3099
3100 if (realign_root == NULL && arrays_write_fixed_in_blocks &&
3102 child->klass->read_multi)
3103 {
3104 if (!node_read_multi (child, &sub, seed, n_copies))
3105 return FALSE;
3106 }
3107 else
3108 {
3109 i = 0;
3110 while (i < n_copies)
3111 {
3112 DBusList *link;
3113
3114 link = _dbus_list_get_first_link (&container->children);
3115 while (link != NULL)
3116 {
3117 TestTypeNode *child2 = link->data;
3118 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3119
3120 _dbus_assert (child2->klass->typecode ==
3122
3123 if (realign_root == NULL)
3124 {
3125 if (!node_read_value (child2, &sub, seed + i))
3126 return FALSE;
3127 }
3128 else
3129 {
3130 if (!node_set_value (child2, &sub, realign_root, seed + i))
3131 return FALSE;
3132 }
3133
3134 if (i == (n_copies - 1) && next == NULL)
3135 NEXT_EXPECTING_FALSE (&sub);
3136 else
3137 NEXT_EXPECTING_TRUE (&sub);
3138
3139 link = next;
3140 }
3141
3142 ++i;
3143 }
3144 }
3145 }
3146
3147 return TRUE;
3148}
3149
3150static dbus_bool_t
3151array_read_value (TestTypeNode *node,
3152 DBusTypeReader *reader,
3153 int seed)
3154{
3155 return array_read_or_set_value (node, reader, NULL, seed);
3156}
3157
3158static dbus_bool_t
3159array_set_value (TestTypeNode *node,
3160 DBusTypeReader *reader,
3161 DBusTypeReader *realign_root,
3162 int seed)
3163{
3164 return array_read_or_set_value (node, reader, realign_root, seed);
3165}
3166
3167static dbus_bool_t
3168array_build_signature (TestTypeNode *node,
3169 DBusString *str)
3170{
3171 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3172 int orig_len;
3173
3174 orig_len = _dbus_string_get_length (str);
3175
3177 goto oom;
3178
3179 if (!node_build_signature (_dbus_list_get_first (&container->children),
3180 str))
3181 goto oom;
3182
3183 return TRUE;
3184
3185 oom:
3186 _dbus_string_set_length (str, orig_len);
3187 return FALSE;
3188}
3189
3190 /* 10 is random just to add another seed that we use in the suite */
3191#define VARIANT_SEED 10
3192
3193static dbus_bool_t
3194variant_write_value (TestTypeNode *node,
3195 DataBlock *block,
3196 DBusTypeWriter *writer,
3197 int seed)
3198{
3199 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3200 DataBlockState saved;
3201 DBusTypeWriter sub;
3202 DBusString content_signature;
3203 TestTypeNode *child;
3204
3205 _dbus_assert (container->children != NULL);
3206 _dbus_assert (_dbus_list_length_is_one (&container->children));
3207
3208 child = _dbus_list_get_first (&container->children);
3209
3210 data_block_save (block, &saved);
3211
3212 if (!_dbus_string_init (&content_signature))
3213 return FALSE;
3214
3215 if (!node_build_signature (child,
3216 &content_signature))
3217 goto oom;
3218
3220 &content_signature, 0,
3221 &sub))
3222 goto oom;
3223
3224 if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
3225 goto oom;
3226
3227 if (!_dbus_type_writer_unrecurse (writer, &sub))
3228 goto oom;
3229
3230 _dbus_string_free (&content_signature);
3231 return TRUE;
3232
3233 oom:
3234 data_block_restore (block, &saved);
3235 _dbus_string_free (&content_signature);
3236 return FALSE;
3237}
3238
3239static dbus_bool_t
3240variant_read_or_set_value (TestTypeNode *node,
3241 DBusTypeReader *reader,
3242 DBusTypeReader *realign_root,
3243 int seed)
3244{
3245 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3246 DBusTypeReader sub;
3247 TestTypeNode *child;
3248
3249 _dbus_assert (container->children != NULL);
3250 _dbus_assert (_dbus_list_length_is_one (&container->children));
3251
3252 child = _dbus_list_get_first (&container->children);
3253
3254 check_expected_type (reader, DBUS_TYPE_VARIANT);
3255
3256 _dbus_type_reader_recurse (reader, &sub);
3257
3258 if (realign_root == NULL)
3259 {
3260 if (!node_read_value (child, &sub, seed + VARIANT_SEED))
3261 return FALSE;
3262 }
3263 else
3264 {
3265 if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
3266 return FALSE;
3267 }
3268
3269 NEXT_EXPECTING_FALSE (&sub);
3270
3271 return TRUE;
3272}
3273
3274static dbus_bool_t
3275variant_read_value (TestTypeNode *node,
3276 DBusTypeReader *reader,
3277 int seed)
3278{
3279 return variant_read_or_set_value (node, reader, NULL, seed);
3280}
3281
3282static dbus_bool_t
3283variant_set_value (TestTypeNode *node,
3284 DBusTypeReader *reader,
3285 DBusTypeReader *realign_root,
3286 int seed)
3287{
3288 return variant_read_or_set_value (node, reader, realign_root, seed);
3289}
3290
3291static dbus_bool_t
3292dict_write_value (TestTypeNode *node,
3293 DataBlock *block,
3294 DBusTypeWriter *writer,
3295 int seed)
3296{
3297 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3298 DataBlockState saved;
3299 DBusTypeWriter sub;
3300 DBusString entry_value_signature;
3301 DBusString dict_entry_signature;
3302 int i;
3303 int n_entries;
3304 TestTypeNode *child;
3305
3306 n_entries = node->klass->subclass_detail;
3307
3308 _dbus_assert (container->children != NULL);
3309
3310 data_block_save (block, &saved);
3311
3312 if (!_dbus_string_init (&entry_value_signature))
3313 return FALSE;
3314
3315 if (!_dbus_string_init (&dict_entry_signature))
3316 {
3317 _dbus_string_free (&entry_value_signature);
3318 return FALSE;
3319 }
3320
3321 child = _dbus_list_get_first (&container->children);
3322
3323 if (!node_build_signature (child,
3324 &entry_value_signature))
3325 goto oom;
3326
3327 if (!_dbus_string_append (&dict_entry_signature,
3330 goto oom;
3331
3332 if (!_dbus_string_copy (&entry_value_signature, 0,
3333 &dict_entry_signature,
3334 _dbus_string_get_length (&dict_entry_signature)))
3335 goto oom;
3336
3337 if (!_dbus_string_append_byte (&dict_entry_signature,
3339 goto oom;
3340
3342 &dict_entry_signature, 0,
3343 &sub))
3344 goto oom;
3345
3346 i = 0;
3347 while (i < n_entries)
3348 {
3349 DBusTypeWriter entry_sub;
3350 dbus_int32_t key;
3351
3353 NULL, 0,
3354 &entry_sub))
3355 goto oom;
3356
3357 key = int32_from_seed (seed + i);
3358
3359 if (!_dbus_type_writer_write_basic (&entry_sub,
3361 &key))
3362 goto oom;
3363
3364 if (!node_write_value (child, block, &entry_sub, seed + i))
3365 goto oom;
3366
3367 if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
3368 goto oom;
3369
3370 ++i;
3371 }
3372
3373 if (!_dbus_type_writer_unrecurse (writer, &sub))
3374 goto oom;
3375
3376 _dbus_string_free (&entry_value_signature);
3377 _dbus_string_free (&dict_entry_signature);
3378 return TRUE;
3379
3380 oom:
3381 data_block_restore (block, &saved);
3382 _dbus_string_free (&entry_value_signature);
3383 _dbus_string_free (&dict_entry_signature);
3384 return FALSE;
3385}
3386
3387static dbus_bool_t
3388dict_read_or_set_value (TestTypeNode *node,
3389 DBusTypeReader *reader,
3390 DBusTypeReader *realign_root,
3391 int seed)
3392{
3393 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3394 DBusTypeReader sub;
3395 int i;
3396 int n_entries;
3397 TestTypeNode *child;
3398
3399 n_entries = node->klass->subclass_detail;
3400
3401 check_expected_type (reader, DBUS_TYPE_ARRAY);
3402
3403 child = _dbus_list_get_first (&container->children);
3404
3405 if (n_entries > 0)
3406 {
3407 _dbus_type_reader_recurse (reader, &sub);
3408
3409 check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3410
3411 i = 0;
3412 while (i < n_entries)
3413 {
3414 DBusTypeReader entry_sub;
3415
3416 check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3417
3418 _dbus_type_reader_recurse (&sub, &entry_sub);
3419
3420 if (realign_root == NULL)
3421 {
3422 dbus_int32_t v;
3423
3424 check_expected_type (&entry_sub, DBUS_TYPE_INT32);
3425
3426 _dbus_type_reader_read_basic (&entry_sub,
3427 (dbus_int32_t*) &v);
3428
3429 _dbus_assert (v == int32_from_seed (seed + i));
3430
3431 NEXT_EXPECTING_TRUE (&entry_sub);
3432
3433 if (!node_read_value (child, &entry_sub, seed + i))
3434 return FALSE;
3435
3436 NEXT_EXPECTING_FALSE (&entry_sub);
3437 }
3438 else
3439 {
3440 dbus_int32_t v;
3441
3442 v = int32_from_seed (seed + i);
3443
3444 if (!_dbus_type_reader_set_basic (&entry_sub,
3445 &v,
3446 realign_root))
3447 return FALSE;
3448
3449 NEXT_EXPECTING_TRUE (&entry_sub);
3450
3451 if (!node_set_value (child, &entry_sub, realign_root, seed + i))
3452 return FALSE;
3453
3454 NEXT_EXPECTING_FALSE (&entry_sub);
3455 }
3456
3457 if (i == (n_entries - 1))
3458 NEXT_EXPECTING_FALSE (&sub);
3459 else
3460 NEXT_EXPECTING_TRUE (&sub);
3461
3462 ++i;
3463 }
3464 }
3465
3466 return TRUE;
3467}
3468
3469static dbus_bool_t
3470dict_read_value (TestTypeNode *node,
3471 DBusTypeReader *reader,
3472 int seed)
3473{
3474 return dict_read_or_set_value (node, reader, NULL, seed);
3475}
3476
3477static dbus_bool_t
3478dict_set_value (TestTypeNode *node,
3479 DBusTypeReader *reader,
3480 DBusTypeReader *realign_root,
3481 int seed)
3482{
3483 return dict_read_or_set_value (node, reader, realign_root, seed);
3484}
3485
3486static dbus_bool_t
3487dict_build_signature (TestTypeNode *node,
3488 DBusString *str)
3489{
3490 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3491 int orig_len;
3492
3493 orig_len = _dbus_string_get_length (str);
3494
3496 goto oom;
3497
3499 goto oom;
3500
3501 if (!node_build_signature (_dbus_list_get_first (&container->children),
3502 str))
3503 goto oom;
3504
3506 goto oom;
3507
3508 return TRUE;
3509
3510 oom:
3511 _dbus_string_set_length (str, orig_len);
3512 return FALSE;
3513}
3514
3515static void
3516container_destroy (TestTypeNode *node)
3517{
3518 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3519 DBusList *link;
3520
3521 link = _dbus_list_get_first_link (&container->children);
3522 while (link != NULL)
3523 {
3524 TestTypeNode *child = link->data;
3525 DBusList *next = _dbus_list_get_next_link (&container->children, link);
3526
3527 node_destroy (child);
3528
3529 _dbus_list_free_link (link);
3530
3531 link = next;
3532 }
3533}
3534
3535#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
3536
3537#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_INT16_MAX
Maximum value of type "int16".
#define _DBUS_INT_MAX
Maximum value of type "int".
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
DBusList * _dbus_list_get_first_link(DBusList **list)
Gets the first link in the list.
Definition: dbus-list.c:567
dbus_bool_t _dbus_list_length_is_one(DBusList **list)
Check whether length is exactly one.
Definition: dbus-list.c:783
void * _dbus_list_get_first(DBusList **list)
Gets the first data in the list.
Definition: dbus-list.c:612
void _dbus_list_free_link(DBusList *link)
Frees a linked list node allocated with _dbus_list_alloc_link.
Definition: dbus-list.c:254
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:542
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:270
#define _dbus_list_get_next_link(list, link)
Gets the next link in the list, or NULL if there are no more links.
Definition: dbus-list.h:116
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
dbus_bool_t _dbus_type_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
dbus_uint16_t _dbus_unpack_uint16(int byte_order, const unsigned char *data)
Unpacks a 16 bit unsigned integer from a data pointer.
void _dbus_type_writer_init_values_only(DBusTypeWriter *writer, int byte_order, const DBusString *type_str, int type_pos, DBusString *value_str, int value_pos)
Like _dbus_type_writer_init(), except the type string passed in should correspond to an existing sign...
void _dbus_type_reader_init(DBusTypeReader *reader, int byte_order, const DBusString *type_str, int type_pos, const DBusString *value_str, int value_pos)
Initializes a type reader.
DBUS_PRIVATE_EXPORT void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
dbus_bool_t _dbus_type_writer_write_reader(DBusTypeWriter *writer, DBusTypeReader *reader)
Iterate through all values in the given reader, writing a copy of each value to the writer.
dbus_bool_t _dbus_type_writer_recurse(DBusTypeWriter *writer, int container_type, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Opens a new container and writes out the initial information for that container.
dbus_uint32_t _dbus_unpack_uint32(int byte_order, const unsigned char *data)
Unpacks a 32 bit unsigned integer from a data pointer.
int _dbus_first_type_in_signature(const DBusString *str, int pos)
Get the first type in the signature.
int _dbus_type_reader_get_element_type(const DBusTypeReader *reader)
Gets the type of an element of the array the reader is currently pointing to.
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
dbus_bool_t _dbus_type_reader_delete(DBusTypeReader *reader, const DBusTypeReader *realign_root)
Recursively deletes any value pointed to by the reader, leaving the reader valid to continue reading.
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
dbus_bool_t _dbus_type_reader_set_basic(DBusTypeReader *reader, const void *value, const DBusTypeReader *realign_root)
Sets a new value for the basic type value pointed to by the reader, leaving the reader valid to conti...
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
dbus_bool_t _dbus_type_writer_unrecurse(DBusTypeWriter *writer, DBusTypeWriter *sub)
Closes a container created by _dbus_type_writer_recurse() and writes any additional information to th...
dbus_bool_t _dbus_type_writer_write_fixed_multi(DBusTypeWriter *writer, int element_type, const void *value, int n_elements)
Writes a block of fixed-length basic values, i.e.
void _dbus_type_writer_init(DBusTypeWriter *writer, int byte_order, DBusString *type_str, int type_pos, DBusString *value_str, int value_pos)
Initialize a write iterator, which is used to write out values in serialized D-Bus format.
void _dbus_type_reader_read_fixed_multi(const DBusTypeReader *reader, void *value, int *n_elements)
Reads a block of fixed-length basic values, from the current point in an array to the end of the arra...
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:702
void * dbus_malloc0(size_t bytes)
Allocates the given number of bytes, as with standard malloc(), but all bytes are initialized to zero...
Definition: dbus-memory.c:532
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
#define DBUS_DICT_ENTRY_END_CHAR
Code marking the end of a dict entry type in a type signature.
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
Definition: dbus-protocol.h:66
#define DBUS_TYPE_INT16
Type code marking a 16-bit signed integer.
Definition: dbus-protocol.h:74
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
DBUS_DICT_ENTRY_BEGIN_CHAR as a string literal instead of a int literal
#define DBUS_TYPE_INT32
Type code marking a 32-bit signed integer.
Definition: dbus-protocol.h:82
#define DBUS_TYPE_INT32_AS_STRING
DBUS_TYPE_INT32 as a string literal instead of a int literal
Definition: dbus-protocol.h:84
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition: dbus-protocol.h:70
#define DBUS_STRUCT_BEGIN_CHAR
Code marking the start of a struct type in a type signature.
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:53
#define DBUS_TYPE_INT64
Type code marking a 64-bit signed integer.
Definition: dbus-protocol.h:90
#define DBUS_TYPE_DOUBLE
Type code marking an 8-byte double in IEEE 754 format.
Definition: dbus-protocol.h:98
#define DBUS_TYPE_UINT64
Type code marking a 64-bit unsigned integer.
Definition: dbus-protocol.h:94
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures,...
#define DBUS_TYPE_UINT16
Type code marking a 16-bit unsigned integer.
Definition: dbus-protocol.h:78
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
#define DBUS_STRUCT_END_CHAR
Code marking the end of a struct type in a type signature.
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:54
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
dbus_bool_t dbus_type_is_basic(int typecode)
A "basic type" is a somewhat arbitrary concept, but the intent is to include those types that are ful...
dbus_bool_t dbus_type_is_fixed(int typecode)
Tells you whether values of this type can change length if you set them to some other value.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:802
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:935
dbus_bool_t _dbus_string_validate_nul(const DBusString *str, int start, int len)
Checks that the given range of the string is all nul bytes.
Definition: dbus-string.c:2653
dbus_bool_t _dbus_string_equal_substring(const DBusString *a, int a_start, int a_len, const DBusString *b, int b_start)
Tests two sub-parts of two DBusString for equality.
Definition: dbus-string.c:2104
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1283
dbus_bool_t _dbus_string_ends_with_c_str(const DBusString *a, const char *c_str)
Returns whether a string ends with the given suffix.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition: dbus-string.c:1193
dbus_bool_t _dbus_string_insert_bytes(DBusString *str, int i, int n_bytes, unsigned char byte)
Inserts a number of bytes of a given value at the given position.
Definition: dbus-string.c:584
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1157
dbus_bool_t _dbus_string_insert_byte(DBusString *str, int i, unsigned char byte)
Inserts a single byte at the given position.
Definition: dbus-string.c:614
dbus_bool_t _dbus_string_equal(const DBusString *a, const DBusString *b)
Tests two DBusString for equality.
Definition: dbus-string.c:2013
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c:1375
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:187
#define _DBUS_DOUBLES_BITWISE_EQUAL(a, b)
On x86 there is an 80-bit FPU, and if you do "a == b" it may have a or b in an 80-bit register,...
Definition: dbus-sysdeps.h:623
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
A node in a linked list.
Definition: dbus-list.h:35
void * data
Data stored at this element.
Definition: dbus-list.h:38
The type reader is an iterator for reading values from a block of values.
union DBusTypeReader::@1 u
class-specific data
int start_pos
for array readers, the start of the array values
int value_pos
current position in values
dbus_uint32_t byte_order
byte order of the block
The type writer is an iterator for writing to a block of values.
A simple value union that lets you access bytes as if they were various types; useful when dealing wi...
Definition: dbus-types.h:138
dbus_uint64_t u64
as int64
Definition: dbus-types.h:146
char * str
as char* (string, object path or signature)
Definition: dbus-types.h:150