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