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