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