D-Bus  1.6.8
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->eight.first32 = 0;
42  value->eight.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->eight.first32 == rhs->eight.first32 &&
63  lhs->eight.second32 == rhs->eight.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  if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL ||
1928  atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1)
1929  {
1930  fprintf (stderr, "skipping remaining marshal-recursive tests, "
1931  "run with DBUS_TEST_SLOW=1 (or more) to enable\n");
1932  goto out;
1933  }
1934 
1935  start_next_test ("Each container of each container of each value %d iterations\n",
1936  N_CONTAINERS * N_CONTAINERS * N_VALUES);
1937  for (i = 0; i < N_CONTAINERS; i++)
1938  {
1939  const TestTypeNodeClass *outer_container_klass = container_nodes[i];
1940  TestTypeNode *outer_container = node_new (outer_container_klass);
1941 
1942  for (j = 0; j < N_CONTAINERS; j++)
1943  {
1944  TestTypeNode *child;
1945  const TestTypeNodeClass *inner_container_klass = container_nodes[j];
1946  TestTypeNode *inner_container = node_new (inner_container_klass);
1947 
1948  node_append_child (outer_container, inner_container);
1949 
1950  m = 0;
1951  while ((child = value_generator (&m)))
1952  {
1953  node_append_child (inner_container, child);
1954 
1955  run_test_nodes (&outer_container, 1);
1956 
1957  _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
1958  node_destroy (child);
1959  }
1960  _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
1961  node_destroy (inner_container);
1962  }
1963  node_destroy (outer_container);
1964  }
1965 
1966  start_next_test ("Each container of each container of each container of each value %d iterations\n",
1967  N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
1968  for (i = 0; i < N_CONTAINERS; i++)
1969  {
1970  const TestTypeNodeClass *outer_container_klass = container_nodes[i];
1971  TestTypeNode *outer_container = node_new (outer_container_klass);
1972 
1973  for (j = 0; j < N_CONTAINERS; j++)
1974  {
1975  const TestTypeNodeClass *inner_container_klass = container_nodes[j];
1976  TestTypeNode *inner_container = node_new (inner_container_klass);
1977 
1978  node_append_child (outer_container, inner_container);
1979 
1980  for (k = 0; k < N_CONTAINERS; k++)
1981  {
1982  TestTypeNode *child;
1983  const TestTypeNodeClass *center_container_klass = container_nodes[k];
1984  TestTypeNode *center_container = node_new (center_container_klass);
1985 
1986  node_append_child (inner_container, center_container);
1987 
1988  m = 0;
1989  while ((child = value_generator (&m)))
1990  {
1991  node_append_child (center_container, child);
1992 
1993  run_test_nodes (&outer_container, 1);
1994 
1995  _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
1996  node_destroy (child);
1997  }
1998  _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
1999  node_destroy (center_container);
2000  }
2001  _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
2002  node_destroy (inner_container);
2003  }
2004  node_destroy (outer_container);
2005  }
2006 
2007  /* This one takes a really long time (10 minutes on a Core2), so only enable
2008  * it if you're really sure */
2009  if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2)
2010  {
2011  fprintf (stderr, "skipping really slow marshal-recursive test, "
2012  "run with DBUS_TEST_SLOW=2 (or more) to enable\n");
2013  goto out;
2014  }
2015 
2016  start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
2017  N_VALUES * N_VALUES * N_VALUES);
2018  {
2019  TestTypeNode *nodes[3];
2020 
2021  i = 0;
2022  while ((nodes[0] = value_generator (&i)))
2023  {
2024  j = 0;
2025  while ((nodes[1] = value_generator (&j)))
2026  {
2027  k = 0;
2028  while ((nodes[2] = value_generator (&k)))
2029  {
2030  run_test_nodes (nodes, 3);
2031 
2032  node_destroy (nodes[2]);
2033  }
2034  node_destroy (nodes[1]);
2035  }
2036  node_destroy (nodes[0]);
2037  }
2038  }
2039 
2040 out:
2041  fprintf (stderr, "%d total iterations of recursive marshaling tests\n",
2042  n_iterations_completed_total);
2043  fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n",
2044  MAX_INITIAL_OFFSET);
2045  fprintf (stderr, "out of memory handling %s tested\n",
2046  TEST_OOM_HANDLING ? "was" : "was not");
2047 }
2048 
2050 _dbus_marshal_recursive_test (void)
2051 {
2052  make_and_run_test_nodes ();
2053 
2054  return TRUE;
2055 }
2056 
2057 /*
2058  *
2059  *
2060  * Implementations of each type node class
2061  *
2062  *
2063  *
2064  */
2065 #define MAX_MULTI_COUNT 5
2066 
2067 #define SAMPLE_INT16 1234
2068 #define SAMPLE_INT16_ALTERNATE 6785
2069 static dbus_int16_t
2070 int16_from_seed (int seed)
2071 {
2072  /* Generate an integer value that's predictable from seed. We could
2073  * just use seed itself, but that would only ever touch one byte of
2074  * the int so would miss some kinds of bug.
2075  */
2076  dbus_int16_t v;
2077 
2078  v = 42; /* just to quiet compiler afaik */
2079  switch (seed % 5)
2080  {
2081  case 0:
2082  v = SAMPLE_INT16;
2083  break;
2084  case 1:
2085  v = SAMPLE_INT16_ALTERNATE;
2086  break;
2087  case 2:
2088  v = -1;
2089  break;
2090  case 3:
2091  v = _DBUS_INT16_MAX;
2092  break;
2093  case 4:
2094  v = 1;
2095  break;
2096  }
2097 
2098  if (seed > 1)
2099  v *= seed; /* wraps around eventually, which is fine */
2100 
2101  return v;
2102 }
2103 
2104 static dbus_bool_t
2105 int16_write_value (TestTypeNode *node,
2106  DataBlock *block,
2107  DBusTypeWriter *writer,
2108  int seed)
2109 {
2110  /* also used for uint16 */
2111  dbus_int16_t v;
2112 
2113  v = int16_from_seed (seed);
2114 
2115  return _dbus_type_writer_write_basic (writer,
2116  node->klass->typecode,
2117  &v);
2118 }
2119 
2120 static dbus_bool_t
2121 int16_read_value (TestTypeNode *node,
2122  DBusTypeReader *reader,
2123  int seed)
2124 {
2125  /* also used for uint16 */
2126  dbus_int16_t v;
2127 
2128  check_expected_type (reader, node->klass->typecode);
2129 
2131  (dbus_int16_t*) &v);
2132 
2133  _dbus_assert (v == int16_from_seed (seed));
2134 
2135  return TRUE;
2136 }
2137 
2138 static dbus_bool_t
2139 int16_set_value (TestTypeNode *node,
2140  DBusTypeReader *reader,
2141  DBusTypeReader *realign_root,
2142  int seed)
2143 {
2144  /* also used for uint16 */
2145  dbus_int16_t v;
2146 
2147  v = int16_from_seed (seed);
2148 
2149  return _dbus_type_reader_set_basic (reader,
2150  &v,
2151  realign_root);
2152 }
2153 
2154 static dbus_bool_t
2155 int16_write_multi (TestTypeNode *node,
2156  DataBlock *block,
2157  DBusTypeWriter *writer,
2158  int seed,
2159  int count)
2160 {
2161  /* also used for uint16 */
2162  dbus_int16_t values[MAX_MULTI_COUNT];
2163  dbus_int16_t *v_ARRAY_INT16 = values;
2164  int i;
2165 
2166  for (i = 0; i < count; ++i)
2167  values[i] = int16_from_seed (seed + i);
2168 
2169  return _dbus_type_writer_write_fixed_multi (writer,
2170  node->klass->typecode,
2171  &v_ARRAY_INT16, count);
2172 }
2173 
2174 static dbus_bool_t
2175 int16_read_multi (TestTypeNode *node,
2176  DBusTypeReader *reader,
2177  int seed,
2178  int count)
2179 {
2180  /* also used for uint16 */
2181  dbus_int16_t *values;
2182  int n_elements;
2183  int i;
2184 
2185  check_expected_type (reader, node->klass->typecode);
2186 
2188  &values,
2189  &n_elements);
2190 
2191  if (n_elements != count)
2192  _dbus_warn ("got %d elements expected %d\n", n_elements, count);
2193  _dbus_assert (n_elements == count);
2194 
2195  for (i = 0; i < count; i++)
2196  _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
2197  (const unsigned char*)values + (i * 2))) ==
2198  int16_from_seed (seed + i));
2199 
2200  return TRUE;
2201 }
2202 
2203 
2204 #define SAMPLE_INT32 12345678
2205 #define SAMPLE_INT32_ALTERNATE 53781429
2206 static dbus_int32_t
2207 int32_from_seed (int seed)
2208 {
2209  /* Generate an integer value that's predictable from seed. We could
2210  * just use seed itself, but that would only ever touch one byte of
2211  * the int so would miss some kinds of bug.
2212  */
2213  dbus_int32_t v;
2214 
2215  v = 42; /* just to quiet compiler afaik */
2216  switch (seed % 5)
2217  {
2218  case 0:
2219  v = SAMPLE_INT32;
2220  break;
2221  case 1:
2222  v = SAMPLE_INT32_ALTERNATE;
2223  break;
2224  case 2:
2225  v = -1;
2226  break;
2227  case 3:
2228  v = _DBUS_INT_MAX;
2229  break;
2230  case 4:
2231  v = 1;
2232  break;
2233  }
2234 
2235  if (seed > 1)
2236  v *= seed; /* wraps around eventually, which is fine */
2237 
2238  return v;
2239 }
2240 
2241 static dbus_bool_t
2242 int32_write_value (TestTypeNode *node,
2243  DataBlock *block,
2244  DBusTypeWriter *writer,
2245  int seed)
2246 {
2247  /* also used for uint32 */
2248  dbus_int32_t v;
2249 
2250  v = int32_from_seed (seed);
2251 
2252  return _dbus_type_writer_write_basic (writer,
2253  node->klass->typecode,
2254  &v);
2255 }
2256 
2257 static dbus_bool_t
2258 int32_read_value (TestTypeNode *node,
2259  DBusTypeReader *reader,
2260  int seed)
2261 {
2262  /* also used for uint32 */
2263  dbus_int32_t v;
2264 
2265  check_expected_type (reader, node->klass->typecode);
2266 
2268  (dbus_int32_t*) &v);
2269 
2270  _dbus_assert (v == int32_from_seed (seed));
2271 
2272  return TRUE;
2273 }
2274 
2275 static dbus_bool_t
2276 int32_set_value (TestTypeNode *node,
2277  DBusTypeReader *reader,
2278  DBusTypeReader *realign_root,
2279  int seed)
2280 {
2281  /* also used for uint32 */
2282  dbus_int32_t v;
2283 
2284  v = int32_from_seed (seed);
2285 
2286  return _dbus_type_reader_set_basic (reader,
2287  &v,
2288  realign_root);
2289 }
2290 
2291 static dbus_bool_t
2292 int32_write_multi (TestTypeNode *node,
2293  DataBlock *block,
2294  DBusTypeWriter *writer,
2295  int seed,
2296  int count)
2297 {
2298  /* also used for uint32 */
2299  dbus_int32_t values[MAX_MULTI_COUNT];
2300  dbus_int32_t *v_ARRAY_INT32 = values;
2301  int i;
2302 
2303  for (i = 0; i < count; ++i)
2304  values[i] = int32_from_seed (seed + i);
2305 
2306  return _dbus_type_writer_write_fixed_multi (writer,
2307  node->klass->typecode,
2308  &v_ARRAY_INT32, count);
2309 }
2310 
2311 static dbus_bool_t
2312 int32_read_multi (TestTypeNode *node,
2313  DBusTypeReader *reader,
2314  int seed,
2315  int count)
2316 {
2317  /* also used for uint32 */
2318  dbus_int32_t *values;
2319  int n_elements;
2320  int i;
2321 
2322  check_expected_type (reader, node->klass->typecode);
2323 
2325  &values,
2326  &n_elements);
2327 
2328  if (n_elements != count)
2329  _dbus_warn ("got %d elements expected %d\n", n_elements, count);
2330  _dbus_assert (n_elements == count);
2331 
2332  for (i = 0; i < count; i++)
2334  (const unsigned char*)values + (i * 4))) ==
2335  int32_from_seed (seed + i));
2336 
2337  return TRUE;
2338 }
2339 
2340 #ifdef DBUS_HAVE_INT64
2341 static dbus_int64_t
2342 int64_from_seed (int seed)
2343 {
2344  dbus_int32_t v32;
2345  dbus_int64_t v;
2346 
2347  v32 = int32_from_seed (seed);
2348 
2349  v = - (dbus_int32_t) ~ v32;
2350  v |= (((dbus_int64_t)v32) << 32);
2351 
2352  return v;
2353 }
2354 #endif
2355 
2356 static dbus_bool_t
2357 int64_write_value (TestTypeNode *node,
2358  DataBlock *block,
2359  DBusTypeWriter *writer,
2360  int seed)
2361 {
2362 #ifdef DBUS_HAVE_INT64
2363  /* also used for uint64 */
2364  dbus_int64_t v;
2365 
2366  v = int64_from_seed (seed);
2367 
2368  return _dbus_type_writer_write_basic (writer,
2369  node->klass->typecode,
2370  &v);
2371 #else
2372  return TRUE;
2373 #endif
2374 }
2375 
2376 static dbus_bool_t
2377 int64_read_value (TestTypeNode *node,
2378  DBusTypeReader *reader,
2379  int seed)
2380 {
2381 #ifdef DBUS_HAVE_INT64
2382  /* also used for uint64 */
2383  dbus_int64_t v;
2384 
2385  check_expected_type (reader, node->klass->typecode);
2386 
2388  (dbus_int64_t*) &v);
2389 
2390  _dbus_assert (v == int64_from_seed (seed));
2391 
2392  return TRUE;
2393 #else
2394  return TRUE;
2395 #endif
2396 }
2397 
2398 static dbus_bool_t
2399 int64_set_value (TestTypeNode *node,
2400  DBusTypeReader *reader,
2401  DBusTypeReader *realign_root,
2402  int seed)
2403 {
2404 #ifdef DBUS_HAVE_INT64
2405  /* also used for uint64 */
2406  dbus_int64_t v;
2407 
2408  v = int64_from_seed (seed);
2409 
2410  return _dbus_type_reader_set_basic (reader,
2411  &v,
2412  realign_root);
2413 #else
2414  return TRUE;
2415 #endif
2416 }
2417 
2418 #define MAX_SAMPLE_STRING_LEN 10
2419 static void
2420 string_from_seed (char *buf,
2421  int len,
2422  int seed)
2423 {
2424  int i;
2425  unsigned char v;
2426 
2427  _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
2428 
2429  /* vary the length slightly, though we also have multiple string
2430  * value types for this, varying it here tests the set_value code
2431  */
2432  switch (seed % 3)
2433  {
2434  case 1:
2435  len += 2;
2436  break;
2437  case 2:
2438  len -= 2;
2439  break;
2440  }
2441  if (len < 0)
2442  len = 0;
2443 
2444  v = (unsigned char) ('A' + seed);
2445 
2446  i = 0;
2447  while (i < len)
2448  {
2449  if (v < 'A' || v > 'z')
2450  v = 'A';
2451 
2452  buf[i] = v;
2453 
2454  v += 1;
2455  ++i;
2456  }
2457 
2458  buf[i] = '\0';
2459 }
2460 
2461 static dbus_bool_t
2462 string_write_value (TestTypeNode *node,
2463  DataBlock *block,
2464  DBusTypeWriter *writer,
2465  int seed)
2466 {
2467  char buf[MAX_SAMPLE_STRING_LEN + 1]="";
2468  const char *v_string = buf;
2469 
2470 
2471  string_from_seed (buf, node->klass->subclass_detail,
2472  seed);
2473 
2474  return _dbus_type_writer_write_basic (writer,
2475  node->klass->typecode,
2476  &v_string);
2477 }
2478 
2479 static dbus_bool_t
2480 string_read_value (TestTypeNode *node,
2481  DBusTypeReader *reader,
2482  int seed)
2483 {
2484  const char *v;
2485  char buf[MAX_SAMPLE_STRING_LEN + 1];
2486  v = buf;
2487 
2488  check_expected_type (reader, node->klass->typecode);
2489 
2491  (const char **) &v);
2492 
2493  string_from_seed (buf, node->klass->subclass_detail,
2494  seed);
2495 
2496  if (strcmp (buf, v) != 0)
2497  {
2498  _dbus_warn ("read string '%s' expected '%s'\n",
2499  v, buf);
2500  _dbus_assert_not_reached ("test failed");
2501  }
2502 
2503  return TRUE;
2504 }
2505 
2506 static dbus_bool_t
2507 string_set_value (TestTypeNode *node,
2508  DBusTypeReader *reader,
2509  DBusTypeReader *realign_root,
2510  int seed)
2511 {
2512  char buf[MAX_SAMPLE_STRING_LEN + 1];
2513  const char *v_string = buf;
2514 
2515  string_from_seed (buf, node->klass->subclass_detail,
2516  seed);
2517 
2518 #if RECURSIVE_MARSHAL_WRITE_TRACE
2519  {
2520  const char *old;
2521  _dbus_type_reader_read_basic (reader, &old);
2522  _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
2523  v_string, strlen (v_string), old, strlen (old));
2524  }
2525 #endif
2526 
2527  return _dbus_type_reader_set_basic (reader,
2528  &v_string,
2529  realign_root);
2530 }
2531 
2532 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
2533 
2534 static dbus_bool_t
2535 bool_write_value (TestTypeNode *node,
2536  DataBlock *block,
2537  DBusTypeWriter *writer,
2538  int seed)
2539 {
2540  dbus_bool_t v;
2541 
2542  v = BOOL_FROM_SEED (seed);
2543 
2544  return _dbus_type_writer_write_basic (writer,
2545  node->klass->typecode,
2546  &v);
2547 }
2548 
2549 static dbus_bool_t
2550 bool_read_value (TestTypeNode *node,
2551  DBusTypeReader *reader,
2552  int seed)
2553 {
2554  dbus_bool_t v;
2555 
2556  check_expected_type (reader, node->klass->typecode);
2557 
2559  (unsigned char*) &v);
2560 
2561  _dbus_assert (v == BOOL_FROM_SEED (seed));
2562 
2563  return TRUE;
2564 }
2565 
2566 static dbus_bool_t
2567 bool_set_value (TestTypeNode *node,
2568  DBusTypeReader *reader,
2569  DBusTypeReader *realign_root,
2570  int seed)
2571 {
2572  dbus_bool_t v;
2573 
2574  v = BOOL_FROM_SEED (seed);
2575 
2576  return _dbus_type_reader_set_basic (reader,
2577  &v,
2578  realign_root);
2579 }
2580 
2581 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
2582 
2583 static dbus_bool_t
2584 byte_write_value (TestTypeNode *node,
2585  DataBlock *block,
2586  DBusTypeWriter *writer,
2587  int seed)
2588 {
2589  unsigned char v;
2590 
2591  v = BYTE_FROM_SEED (seed);
2592 
2593  return _dbus_type_writer_write_basic (writer,
2594  node->klass->typecode,
2595  &v);
2596 }
2597 
2598 static dbus_bool_t
2599 byte_read_value (TestTypeNode *node,
2600  DBusTypeReader *reader,
2601  int seed)
2602 {
2603  unsigned char v;
2604 
2605  check_expected_type (reader, node->klass->typecode);
2606 
2608  (unsigned char*) &v);
2609 
2610  _dbus_assert (v == BYTE_FROM_SEED (seed));
2611 
2612  return TRUE;
2613 }
2614 
2615 
2616 static dbus_bool_t
2617 byte_set_value (TestTypeNode *node,
2618  DBusTypeReader *reader,
2619  DBusTypeReader *realign_root,
2620  int seed)
2621 {
2622  unsigned char v;
2623 
2624  v = BYTE_FROM_SEED (seed);
2625 
2626  return _dbus_type_reader_set_basic (reader,
2627  &v,
2628  realign_root);
2629 }
2630 
2631 static double
2632 double_from_seed (int seed)
2633 {
2634  return SAMPLE_INT32 * (double) seed + 0.3;
2635 }
2636 
2637 static dbus_bool_t
2638 double_write_value (TestTypeNode *node,
2639  DataBlock *block,
2640  DBusTypeWriter *writer,
2641  int seed)
2642 {
2643  double v;
2644 
2645  v = double_from_seed (seed);
2646 
2647  return _dbus_type_writer_write_basic (writer,
2648  node->klass->typecode,
2649  &v);
2650 }
2651 
2652 static dbus_bool_t
2653 double_read_value (TestTypeNode *node,
2654  DBusTypeReader *reader,
2655  int seed)
2656 {
2657  double v;
2658  double expected;
2659 
2660  check_expected_type (reader, node->klass->typecode);
2661 
2663  (double*) &v);
2664 
2665  expected = double_from_seed (seed);
2666 
2667  if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
2668  {
2669 #ifdef DBUS_INT64_PRINTF_MODIFIER
2670  _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",
2671  expected, v,
2672  *(dbus_uint64_t*)(char*)&expected,
2673  *(dbus_uint64_t*)(char*)&v);
2674 #endif
2675  _dbus_assert_not_reached ("test failed");
2676  }
2677 
2678  return TRUE;
2679 }
2680 
2681 static dbus_bool_t
2682 double_set_value (TestTypeNode *node,
2683  DBusTypeReader *reader,
2684  DBusTypeReader *realign_root,
2685  int seed)
2686 {
2687  double v;
2688 
2689  v = double_from_seed (seed);
2690 
2691  return _dbus_type_reader_set_basic (reader,
2692  &v,
2693  realign_root);
2694 }
2695 
2696 #define MAX_SAMPLE_OBJECT_PATH_LEN 10
2697 static void
2698 object_path_from_seed (char *buf,
2699  int seed)
2700 {
2701  int i;
2702  unsigned char v;
2703  int len;
2704 
2705  len = seed % 9;
2706  _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
2707 
2708  v = (unsigned char) ('A' + seed);
2709 
2710  if (len < 2)
2711  {
2712  buf[0] = '/';
2713  i = 1;
2714  }
2715  else
2716  {
2717  i = 0;
2718  while (i + 1 < len)
2719  {
2720  if (v < 'A' || v > 'z')
2721  v = 'A';
2722 
2723  buf[i] = '/';
2724  ++i;
2725  buf[i] = v;
2726  ++i;
2727 
2728  v += 1;
2729  }
2730  }
2731 
2732  buf[i] = '\0';
2733 }
2734 
2735 static dbus_bool_t
2736 object_path_write_value (TestTypeNode *node,
2737  DataBlock *block,
2738  DBusTypeWriter *writer,
2739  int seed)
2740 {
2741  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2742  const char *v_string = buf;
2743 
2744  object_path_from_seed (buf, seed);
2745 
2746  return _dbus_type_writer_write_basic (writer,
2747  node->klass->typecode,
2748  &v_string);
2749 }
2750 
2751 static dbus_bool_t
2752 object_path_read_value (TestTypeNode *node,
2753  DBusTypeReader *reader,
2754  int seed)
2755 {
2756  const char *v;
2757  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2758 
2759  check_expected_type (reader, node->klass->typecode);
2760 
2762  (const char **) &v);
2763 
2764  object_path_from_seed (buf, seed);
2765 
2766  if (strcmp (buf, v) != 0)
2767  {
2768  _dbus_warn ("read object path '%s' expected '%s'\n",
2769  v, buf);
2770  _dbus_assert_not_reached ("test failed");
2771  }
2772 
2773  return TRUE;
2774 }
2775 
2776 static dbus_bool_t
2777 object_path_set_value (TestTypeNode *node,
2778  DBusTypeReader *reader,
2779  DBusTypeReader *realign_root,
2780  int seed)
2781 {
2782  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2783  const char *v_string = buf;
2784 
2785  object_path_from_seed (buf, seed);
2786 
2787  return _dbus_type_reader_set_basic (reader,
2788  &v_string,
2789  realign_root);
2790 }
2791 
2792 #define MAX_SAMPLE_SIGNATURE_LEN 10
2793 static void
2794 signature_from_seed (char *buf,
2795  int seed)
2796 {
2797  /* try to avoid ascending, descending, or alternating length to help find bugs */
2798  const char *sample_signatures[] = {
2799  "asax"
2800  "",
2801  "asau(xxxx)",
2802  "x",
2803  "ai",
2804  "a(ii)"
2805  };
2806 
2807  strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
2808 }
2809 
2810 static dbus_bool_t
2811 signature_write_value (TestTypeNode *node,
2812  DataBlock *block,
2813  DBusTypeWriter *writer,
2814  int seed)
2815 {
2816  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2817  const char *v_string = buf;
2818 
2819  signature_from_seed (buf, seed);
2820 
2821  return _dbus_type_writer_write_basic (writer,
2822  node->klass->typecode,
2823  &v_string);
2824 }
2825 
2826 static dbus_bool_t
2827 signature_read_value (TestTypeNode *node,
2828  DBusTypeReader *reader,
2829  int seed)
2830 {
2831  const char *v;
2832  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2833 
2834  check_expected_type (reader, node->klass->typecode);
2835 
2837  (const char **) &v);
2838 
2839  signature_from_seed (buf, seed);
2840 
2841  if (strcmp (buf, v) != 0)
2842  {
2843  _dbus_warn ("read signature value '%s' expected '%s'\n",
2844  v, buf);
2845  _dbus_assert_not_reached ("test failed");
2846  }
2847 
2848  return TRUE;
2849 }
2850 
2851 
2852 static dbus_bool_t
2853 signature_set_value (TestTypeNode *node,
2854  DBusTypeReader *reader,
2855  DBusTypeReader *realign_root,
2856  int seed)
2857 {
2858  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2859  const char *v_string = buf;
2860 
2861  signature_from_seed (buf, seed);
2862 
2863  return _dbus_type_reader_set_basic (reader,
2864  &v_string,
2865  realign_root);
2866 }
2867 
2868 static dbus_bool_t
2869 struct_write_value (TestTypeNode *node,
2870  DataBlock *block,
2871  DBusTypeWriter *writer,
2872  int seed)
2873 {
2874  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2875  DataBlockState saved;
2876  DBusTypeWriter sub;
2877  int i;
2878  int n_copies;
2879 
2880  n_copies = node->klass->subclass_detail;
2881 
2882  _dbus_assert (container->children != NULL);
2883 
2884  data_block_save (block, &saved);
2885 
2887  NULL, 0,
2888  &sub))
2889  return FALSE;
2890 
2891  i = 0;
2892  while (i < n_copies)
2893  {
2894  DBusList *link;
2895 
2896  link = _dbus_list_get_first_link (&container->children);
2897  while (link != NULL)
2898  {
2899  TestTypeNode *child = link->data;
2900  DBusList *next = _dbus_list_get_next_link (&container->children, link);
2901 
2902  if (!node_write_value (child, block, &sub, seed + i))
2903  {
2904  data_block_restore (block, &saved);
2905  return FALSE;
2906  }
2907 
2908  link = next;
2909  }
2910 
2911  ++i;
2912  }
2913 
2914  if (!_dbus_type_writer_unrecurse (writer, &sub))
2915  {
2916  data_block_restore (block, &saved);
2917  return FALSE;
2918  }
2919 
2920  return TRUE;
2921 }
2922 
2923 static dbus_bool_t
2924 struct_read_or_set_value (TestTypeNode *node,
2925  DBusTypeReader *reader,
2926  DBusTypeReader *realign_root,
2927  int seed)
2928 {
2929  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2930  DBusTypeReader sub;
2931  int i;
2932  int n_copies;
2933 
2934  n_copies = node->klass->subclass_detail;
2935 
2936  check_expected_type (reader, DBUS_TYPE_STRUCT);
2937 
2938  _dbus_type_reader_recurse (reader, &sub);
2939 
2940  i = 0;
2941  while (i < n_copies)
2942  {
2943  DBusList *link;
2944 
2945  link = _dbus_list_get_first_link (&container->children);
2946  while (link != NULL)
2947  {
2948  TestTypeNode *child = link->data;
2949  DBusList *next = _dbus_list_get_next_link (&container->children, link);
2950 
2951  if (realign_root == NULL)
2952  {
2953  if (!node_read_value (child, &sub, seed + i))
2954  return FALSE;
2955  }
2956  else
2957  {
2958  if (!node_set_value (child, &sub, realign_root, seed + i))
2959  return FALSE;
2960  }
2961 
2962  if (i == (n_copies - 1) && next == NULL)
2963  NEXT_EXPECTING_FALSE (&sub);
2964  else
2965  NEXT_EXPECTING_TRUE (&sub);
2966 
2967  link = next;
2968  }
2969 
2970  ++i;
2971  }
2972 
2973  return TRUE;
2974 }
2975 
2976 static dbus_bool_t
2977 struct_read_value (TestTypeNode *node,
2978  DBusTypeReader *reader,
2979  int seed)
2980 {
2981  return struct_read_or_set_value (node, reader, NULL, seed);
2982 }
2983 
2984 static dbus_bool_t
2985 struct_set_value (TestTypeNode *node,
2986  DBusTypeReader *reader,
2987  DBusTypeReader *realign_root,
2988  int seed)
2989 {
2990  return struct_read_or_set_value (node, reader, realign_root, seed);
2991 }
2992 
2993 static dbus_bool_t
2994 struct_build_signature (TestTypeNode *node,
2995  DBusString *str)
2996 {
2997  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2998  int i;
2999  int orig_len;
3000  int n_copies;
3001 
3002  n_copies = node->klass->subclass_detail;
3003 
3004  orig_len = _dbus_string_get_length (str);
3005 
3007  goto oom;
3008 
3009  i = 0;
3010  while (i < n_copies)
3011  {
3012  DBusList *link;
3013 
3014  link = _dbus_list_get_first_link (&container->children);
3015  while (link != NULL)
3016  {
3017  TestTypeNode *child = link->data;
3018  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3019 
3020  if (!node_build_signature (child, str))
3021  goto oom;
3022 
3023  link = next;
3024  }
3025 
3026  ++i;
3027  }
3028 
3030  goto oom;
3031 
3032  return TRUE;
3033 
3034  oom:
3035  _dbus_string_set_length (str, orig_len);
3036  return FALSE;
3037 }
3038 
3039 static dbus_bool_t
3040 array_write_value (TestTypeNode *node,
3041  DataBlock *block,
3042  DBusTypeWriter *writer,
3043  int seed)
3044 {
3045  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3046  DataBlockState saved;
3047  DBusTypeWriter sub;
3048  DBusString element_signature;
3049  int i;
3050  int n_copies;
3051  int element_type;
3052  TestTypeNode *child;
3053 
3054  n_copies = node->klass->subclass_detail;
3055 
3056  _dbus_assert (container->children != NULL);
3057 
3058  data_block_save (block, &saved);
3059 
3060  if (!_dbus_string_init (&element_signature))
3061  return FALSE;
3062 
3063  child = _dbus_list_get_first (&container->children);
3064 
3065  if (!node_build_signature (child,
3066  &element_signature))
3067  goto oom;
3068 
3069  element_type = _dbus_first_type_in_signature (&element_signature, 0);
3070 
3072  &element_signature, 0,
3073  &sub))
3074  goto oom;
3075 
3076  if (arrays_write_fixed_in_blocks &&
3077  dbus_type_is_fixed (element_type) &&
3078  child->klass->write_multi)
3079  {
3080  if (!node_write_multi (child, block, &sub, seed, n_copies))
3081  goto oom;
3082  }
3083  else
3084  {
3085  i = 0;
3086  while (i < n_copies)
3087  {
3088  DBusList *link;
3089 
3090  link = _dbus_list_get_first_link (&container->children);
3091  while (link != NULL)
3092  {
3093  TestTypeNode *child = link->data;
3094  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3095 
3096  if (!node_write_value (child, block, &sub, seed + i))
3097  goto oom;
3098 
3099  link = next;
3100  }
3101 
3102  ++i;
3103  }
3104  }
3105 
3106  if (!_dbus_type_writer_unrecurse (writer, &sub))
3107  goto oom;
3108 
3109  _dbus_string_free (&element_signature);
3110  return TRUE;
3111 
3112  oom:
3113  data_block_restore (block, &saved);
3114  _dbus_string_free (&element_signature);
3115  return FALSE;
3116 }
3117 
3118 static dbus_bool_t
3119 array_read_or_set_value (TestTypeNode *node,
3120  DBusTypeReader *reader,
3121  DBusTypeReader *realign_root,
3122  int seed)
3123 {
3124  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3125  DBusTypeReader sub;
3126  int i;
3127  int n_copies;
3128  TestTypeNode *child;
3129 
3130  n_copies = node->klass->subclass_detail;
3131 
3132  check_expected_type (reader, DBUS_TYPE_ARRAY);
3133 
3134  child = _dbus_list_get_first (&container->children);
3135 
3136  if (n_copies > 0)
3137  {
3138  _dbus_type_reader_recurse (reader, &sub);
3139 
3140  if (realign_root == NULL && arrays_write_fixed_in_blocks &&
3142  child->klass->read_multi)
3143  {
3144  if (!node_read_multi (child, &sub, seed, n_copies))
3145  return FALSE;
3146  }
3147  else
3148  {
3149  i = 0;
3150  while (i < n_copies)
3151  {
3152  DBusList *link;
3153 
3154  link = _dbus_list_get_first_link (&container->children);
3155  while (link != NULL)
3156  {
3157  TestTypeNode *child = link->data;
3158  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3159 
3160  _dbus_assert (child->klass->typecode ==
3162 
3163  if (realign_root == NULL)
3164  {
3165  if (!node_read_value (child, &sub, seed + i))
3166  return FALSE;
3167  }
3168  else
3169  {
3170  if (!node_set_value (child, &sub, realign_root, seed + i))
3171  return FALSE;
3172  }
3173 
3174  if (i == (n_copies - 1) && next == NULL)
3175  NEXT_EXPECTING_FALSE (&sub);
3176  else
3177  NEXT_EXPECTING_TRUE (&sub);
3178 
3179  link = next;
3180  }
3181 
3182  ++i;
3183  }
3184  }
3185  }
3186 
3187  return TRUE;
3188 }
3189 
3190 static dbus_bool_t
3191 array_read_value (TestTypeNode *node,
3192  DBusTypeReader *reader,
3193  int seed)
3194 {
3195  return array_read_or_set_value (node, reader, NULL, seed);
3196 }
3197 
3198 static dbus_bool_t
3199 array_set_value (TestTypeNode *node,
3200  DBusTypeReader *reader,
3201  DBusTypeReader *realign_root,
3202  int seed)
3203 {
3204  return array_read_or_set_value (node, reader, realign_root, seed);
3205 }
3206 
3207 static dbus_bool_t
3208 array_build_signature (TestTypeNode *node,
3209  DBusString *str)
3210 {
3211  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3212  int orig_len;
3213 
3214  orig_len = _dbus_string_get_length (str);
3215 
3217  goto oom;
3218 
3219  if (!node_build_signature (_dbus_list_get_first (&container->children),
3220  str))
3221  goto oom;
3222 
3223  return TRUE;
3224 
3225  oom:
3226  _dbus_string_set_length (str, orig_len);
3227  return FALSE;
3228 }
3229 
3230  /* 10 is random just to add another seed that we use in the suite */
3231 #define VARIANT_SEED 10
3232 
3233 static dbus_bool_t
3234 variant_write_value (TestTypeNode *node,
3235  DataBlock *block,
3236  DBusTypeWriter *writer,
3237  int seed)
3238 {
3239  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3240  DataBlockState saved;
3241  DBusTypeWriter sub;
3242  DBusString content_signature;
3243  TestTypeNode *child;
3244 
3245  _dbus_assert (container->children != NULL);
3246  _dbus_assert (_dbus_list_length_is_one (&container->children));
3247 
3248  child = _dbus_list_get_first (&container->children);
3249 
3250  data_block_save (block, &saved);
3251 
3252  if (!_dbus_string_init (&content_signature))
3253  return FALSE;
3254 
3255  if (!node_build_signature (child,
3256  &content_signature))
3257  goto oom;
3258 
3260  &content_signature, 0,
3261  &sub))
3262  goto oom;
3263 
3264  if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
3265  goto oom;
3266 
3267  if (!_dbus_type_writer_unrecurse (writer, &sub))
3268  goto oom;
3269 
3270  _dbus_string_free (&content_signature);
3271  return TRUE;
3272 
3273  oom:
3274  data_block_restore (block, &saved);
3275  _dbus_string_free (&content_signature);
3276  return FALSE;
3277 }
3278 
3279 static dbus_bool_t
3280 variant_read_or_set_value (TestTypeNode *node,
3281  DBusTypeReader *reader,
3282  DBusTypeReader *realign_root,
3283  int seed)
3284 {
3285  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3286  DBusTypeReader sub;
3287  TestTypeNode *child;
3288 
3289  _dbus_assert (container->children != NULL);
3290  _dbus_assert (_dbus_list_length_is_one (&container->children));
3291 
3292  child = _dbus_list_get_first (&container->children);
3293 
3294  check_expected_type (reader, DBUS_TYPE_VARIANT);
3295 
3296  _dbus_type_reader_recurse (reader, &sub);
3297 
3298  if (realign_root == NULL)
3299  {
3300  if (!node_read_value (child, &sub, seed + VARIANT_SEED))
3301  return FALSE;
3302  }
3303  else
3304  {
3305  if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
3306  return FALSE;
3307  }
3308 
3309  NEXT_EXPECTING_FALSE (&sub);
3310 
3311  return TRUE;
3312 }
3313 
3314 static dbus_bool_t
3315 variant_read_value (TestTypeNode *node,
3316  DBusTypeReader *reader,
3317  int seed)
3318 {
3319  return variant_read_or_set_value (node, reader, NULL, seed);
3320 }
3321 
3322 static dbus_bool_t
3323 variant_set_value (TestTypeNode *node,
3324  DBusTypeReader *reader,
3325  DBusTypeReader *realign_root,
3326  int seed)
3327 {
3328  return variant_read_or_set_value (node, reader, realign_root, seed);
3329 }
3330 
3331 static dbus_bool_t
3332 dict_write_value (TestTypeNode *node,
3333  DataBlock *block,
3334  DBusTypeWriter *writer,
3335  int seed)
3336 {
3337  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3338  DataBlockState saved;
3339  DBusTypeWriter sub;
3340  DBusString entry_value_signature;
3341  DBusString dict_entry_signature;
3342  int i;
3343  int n_entries;
3344  TestTypeNode *child;
3345 
3346  n_entries = node->klass->subclass_detail;
3347 
3348  _dbus_assert (container->children != NULL);
3349 
3350  data_block_save (block, &saved);
3351 
3352  if (!_dbus_string_init (&entry_value_signature))
3353  return FALSE;
3354 
3355  if (!_dbus_string_init (&dict_entry_signature))
3356  {
3357  _dbus_string_free (&entry_value_signature);
3358  return FALSE;
3359  }
3360 
3361  child = _dbus_list_get_first (&container->children);
3362 
3363  if (!node_build_signature (child,
3364  &entry_value_signature))
3365  goto oom;
3366 
3367  if (!_dbus_string_append (&dict_entry_signature,
3370  goto oom;
3371 
3372  if (!_dbus_string_copy (&entry_value_signature, 0,
3373  &dict_entry_signature,
3374  _dbus_string_get_length (&dict_entry_signature)))
3375  goto oom;
3376 
3377  if (!_dbus_string_append_byte (&dict_entry_signature,
3379  goto oom;
3380 
3382  &dict_entry_signature, 0,
3383  &sub))
3384  goto oom;
3385 
3386  i = 0;
3387  while (i < n_entries)
3388  {
3389  DBusTypeWriter entry_sub;
3390  dbus_int32_t key;
3391 
3393  NULL, 0,
3394  &entry_sub))
3395  goto oom;
3396 
3397  key = int32_from_seed (seed + i);
3398 
3399  if (!_dbus_type_writer_write_basic (&entry_sub,
3401  &key))
3402  goto oom;
3403 
3404  if (!node_write_value (child, block, &entry_sub, seed + i))
3405  goto oom;
3406 
3407  if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
3408  goto oom;
3409 
3410  ++i;
3411  }
3412 
3413  if (!_dbus_type_writer_unrecurse (writer, &sub))
3414  goto oom;
3415 
3416  _dbus_string_free (&entry_value_signature);
3417  _dbus_string_free (&dict_entry_signature);
3418  return TRUE;
3419 
3420  oom:
3421  data_block_restore (block, &saved);
3422  _dbus_string_free (&entry_value_signature);
3423  _dbus_string_free (&dict_entry_signature);
3424  return FALSE;
3425 }
3426 
3427 static dbus_bool_t
3428 dict_read_or_set_value (TestTypeNode *node,
3429  DBusTypeReader *reader,
3430  DBusTypeReader *realign_root,
3431  int seed)
3432 {
3433  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3434  DBusTypeReader sub;
3435  int i;
3436  int n_entries;
3437  TestTypeNode *child;
3438 
3439  n_entries = node->klass->subclass_detail;
3440 
3441  check_expected_type (reader, DBUS_TYPE_ARRAY);
3442 
3443  child = _dbus_list_get_first (&container->children);
3444 
3445  if (n_entries > 0)
3446  {
3447  _dbus_type_reader_recurse (reader, &sub);
3448 
3449  check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3450 
3451  i = 0;
3452  while (i < n_entries)
3453  {
3454  DBusTypeReader entry_sub;
3455 
3456  check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3457 
3458  _dbus_type_reader_recurse (&sub, &entry_sub);
3459 
3460  if (realign_root == NULL)
3461  {
3462  dbus_int32_t v;
3463 
3464  check_expected_type (&entry_sub, DBUS_TYPE_INT32);
3465 
3466  _dbus_type_reader_read_basic (&entry_sub,
3467  (dbus_int32_t*) &v);
3468 
3469  _dbus_assert (v == int32_from_seed (seed + i));
3470 
3471  NEXT_EXPECTING_TRUE (&entry_sub);
3472 
3473  if (!node_read_value (child, &entry_sub, seed + i))
3474  return FALSE;
3475 
3476  NEXT_EXPECTING_FALSE (&entry_sub);
3477  }
3478  else
3479  {
3480  dbus_int32_t v;
3481 
3482  v = int32_from_seed (seed + i);
3483 
3484  if (!_dbus_type_reader_set_basic (&entry_sub,
3485  &v,
3486  realign_root))
3487  return FALSE;
3488 
3489  NEXT_EXPECTING_TRUE (&entry_sub);
3490 
3491  if (!node_set_value (child, &entry_sub, realign_root, seed + i))
3492  return FALSE;
3493 
3494  NEXT_EXPECTING_FALSE (&entry_sub);
3495  }
3496 
3497  if (i == (n_entries - 1))
3498  NEXT_EXPECTING_FALSE (&sub);
3499  else
3500  NEXT_EXPECTING_TRUE (&sub);
3501 
3502  ++i;
3503  }
3504  }
3505 
3506  return TRUE;
3507 }
3508 
3509 static dbus_bool_t
3510 dict_read_value (TestTypeNode *node,
3511  DBusTypeReader *reader,
3512  int seed)
3513 {
3514  return dict_read_or_set_value (node, reader, NULL, seed);
3515 }
3516 
3517 static dbus_bool_t
3518 dict_set_value (TestTypeNode *node,
3519  DBusTypeReader *reader,
3520  DBusTypeReader *realign_root,
3521  int seed)
3522 {
3523  return dict_read_or_set_value (node, reader, realign_root, seed);
3524 }
3525 
3526 static dbus_bool_t
3527 dict_build_signature (TestTypeNode *node,
3528  DBusString *str)
3529 {
3530  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3531  int orig_len;
3532 
3533  orig_len = _dbus_string_get_length (str);
3534 
3536  goto oom;
3537 
3538  if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
3539  goto oom;
3540 
3541  if (!node_build_signature (_dbus_list_get_first (&container->children),
3542  str))
3543  goto oom;
3544 
3546  goto oom;
3547 
3548  return TRUE;
3549 
3550  oom:
3551  _dbus_string_set_length (str, orig_len);
3552  return FALSE;
3553 }
3554 
3555 static void
3556 container_destroy (TestTypeNode *node)
3557 {
3558  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3559  DBusList *link;
3560 
3561  link = _dbus_list_get_first_link (&container->children);
3562  while (link != NULL)
3563  {
3564  TestTypeNode *child = link->data;
3565  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3566 
3567  node_destroy (child);
3568 
3569  _dbus_list_free_link (link);
3570 
3571  link = next;
3572  }
3573 }
3574 
3575 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
3576 
3577 #endif /* DBUS_BUILD_TESTS */