D-Bus  1.13.6
dbus-marshal-recursive-util.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-marshal-recursive-util.c Would be in dbus-marshal-recursive.c, but only used in bus/tests
3  *
4  * Copyright (C) 2004, 2005 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23 
24 #include <config.h>
25 
26 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
27 
28 #include "dbus-marshal-recursive.h"
29 #include "dbus-marshal-basic.h"
30 #include "dbus-signature.h"
31 #include "dbus-internals.h"
32 #include <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  int seed);
366  dbus_bool_t (* read_value) (TestTypeNode *node,
367  DBusTypeReader *reader,
368  int seed);
369  dbus_bool_t (* set_value) (TestTypeNode *node,
370  DBusTypeReader *reader,
371  DBusTypeReader *realign_root,
372  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  int seed,
379  int count);
380  dbus_bool_t (* read_multi) (TestTypeNode *node,
381  DBusTypeReader *reader,
382  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 int16_write_value (TestTypeNode *node,
397  DataBlock *block,
398  DBusTypeWriter *writer,
399  int seed);
400 static dbus_bool_t int16_read_value (TestTypeNode *node,
401  DBusTypeReader *reader,
402  int seed);
403 static dbus_bool_t int16_set_value (TestTypeNode *node,
404  DBusTypeReader *reader,
405  DBusTypeReader *realign_root,
406  int seed);
407 static dbus_bool_t int16_write_multi (TestTypeNode *node,
408  DataBlock *block,
409  DBusTypeWriter *writer,
410  int seed,
411  int count);
412 static dbus_bool_t int16_read_multi (TestTypeNode *node,
413  DBusTypeReader *reader,
414  int seed,
415  int count);
416 static dbus_bool_t int32_write_value (TestTypeNode *node,
417  DataBlock *block,
418  DBusTypeWriter *writer,
419  int seed);
420 static dbus_bool_t int32_read_value (TestTypeNode *node,
421  DBusTypeReader *reader,
422  int seed);
423 static dbus_bool_t int32_set_value (TestTypeNode *node,
424  DBusTypeReader *reader,
425  DBusTypeReader *realign_root,
426  int seed);
427 static dbus_bool_t int32_write_multi (TestTypeNode *node,
428  DataBlock *block,
429  DBusTypeWriter *writer,
430  int seed,
431  int count);
432 static dbus_bool_t int32_read_multi (TestTypeNode *node,
433  DBusTypeReader *reader,
434  int seed,
435  int count);
436 static dbus_bool_t int64_write_value (TestTypeNode *node,
437  DataBlock *block,
438  DBusTypeWriter *writer,
439  int seed);
440 static dbus_bool_t int64_read_value (TestTypeNode *node,
441  DBusTypeReader *reader,
442  int seed);
443 static dbus_bool_t int64_set_value (TestTypeNode *node,
444  DBusTypeReader *reader,
445  DBusTypeReader *realign_root,
446  int seed);
447 static dbus_bool_t string_write_value (TestTypeNode *node,
448  DataBlock *block,
449  DBusTypeWriter *writer,
450  int seed);
451 static dbus_bool_t string_read_value (TestTypeNode *node,
452  DBusTypeReader *reader,
453  int seed);
454 static dbus_bool_t string_set_value (TestTypeNode *node,
455  DBusTypeReader *reader,
456  DBusTypeReader *realign_root,
457  int seed);
458 static dbus_bool_t bool_write_value (TestTypeNode *node,
459  DataBlock *block,
460  DBusTypeWriter *writer,
461  int seed);
462 static dbus_bool_t bool_read_value (TestTypeNode *node,
463  DBusTypeReader *reader,
464  int seed);
465 static dbus_bool_t bool_set_value (TestTypeNode *node,
466  DBusTypeReader *reader,
467  DBusTypeReader *realign_root,
468  int seed);
469 static dbus_bool_t byte_write_value (TestTypeNode *node,
470  DataBlock *block,
471  DBusTypeWriter *writer,
472  int seed);
473 static dbus_bool_t byte_read_value (TestTypeNode *node,
474  DBusTypeReader *reader,
475  int seed);
476 static dbus_bool_t byte_set_value (TestTypeNode *node,
477  DBusTypeReader *reader,
478  DBusTypeReader *realign_root,
479  int seed);
480 static dbus_bool_t double_write_value (TestTypeNode *node,
481  DataBlock *block,
482  DBusTypeWriter *writer,
483  int seed);
484 static dbus_bool_t double_read_value (TestTypeNode *node,
485  DBusTypeReader *reader,
486  int seed);
487 static dbus_bool_t double_set_value (TestTypeNode *node,
488  DBusTypeReader *reader,
489  DBusTypeReader *realign_root,
490  int seed);
491 static dbus_bool_t object_path_write_value (TestTypeNode *node,
492  DataBlock *block,
493  DBusTypeWriter *writer,
494  int seed);
495 static dbus_bool_t object_path_read_value (TestTypeNode *node,
496  DBusTypeReader *reader,
497  int seed);
498 static dbus_bool_t object_path_set_value (TestTypeNode *node,
499  DBusTypeReader *reader,
500  DBusTypeReader *realign_root,
501  int seed);
502 static dbus_bool_t signature_write_value (TestTypeNode *node,
503  DataBlock *block,
504  DBusTypeWriter *writer,
505  int seed);
506 static dbus_bool_t signature_read_value (TestTypeNode *node,
507  DBusTypeReader *reader,
508  int seed);
509 static dbus_bool_t signature_set_value (TestTypeNode *node,
510  DBusTypeReader *reader,
511  DBusTypeReader *realign_root,
512  int seed);
513 static dbus_bool_t struct_write_value (TestTypeNode *node,
514  DataBlock *block,
515  DBusTypeWriter *writer,
516  int seed);
517 static dbus_bool_t struct_read_value (TestTypeNode *node,
518  DBusTypeReader *reader,
519  int seed);
520 static dbus_bool_t struct_set_value (TestTypeNode *node,
521  DBusTypeReader *reader,
522  DBusTypeReader *realign_root,
523  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  int seed);
530 static dbus_bool_t dict_read_value (TestTypeNode *node,
531  DBusTypeReader *reader,
532  int seed);
533 static dbus_bool_t dict_set_value (TestTypeNode *node,
534  DBusTypeReader *reader,
535  DBusTypeReader *realign_root,
536  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  int seed);
543 static dbus_bool_t array_read_value (TestTypeNode *node,
544  DBusTypeReader *reader,
545  int seed);
546 static dbus_bool_t array_set_value (TestTypeNode *node,
547  DBusTypeReader *reader,
548  DBusTypeReader *realign_root,
549  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  int seed);
556 static dbus_bool_t variant_read_value (TestTypeNode *node,
557  DBusTypeReader *reader,
558  int seed);
559 static dbus_bool_t variant_set_value (TestTypeNode *node,
560  DBusTypeReader *reader,
561  DBusTypeReader *realign_root,
562  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  int16_write_value,
574  int16_read_value,
575  int16_set_value,
576  NULL,
577  int16_write_multi,
578  int16_read_multi
579 };
580 
581 static const TestTypeNodeClass uint16_class = {
583  sizeof (TestTypeNode),
584  0,
585  NULL,
586  NULL,
587  int16_write_value, /* recycle from int16 */
588  int16_read_value, /* recycle from int16 */
589  int16_set_value, /* recycle from int16 */
590  NULL,
591  int16_write_multi, /* recycle from int16 */
592  int16_read_multi /* recycle from int16 */
593 };
594 
595 static const TestTypeNodeClass int32_class = {
597  sizeof (TestTypeNode),
598  0,
599  NULL,
600  NULL,
601  int32_write_value,
602  int32_read_value,
603  int32_set_value,
604  NULL,
605  int32_write_multi,
606  int32_read_multi
607 };
608 
609 static const TestTypeNodeClass uint32_class = {
611  sizeof (TestTypeNode),
612  0,
613  NULL,
614  NULL,
615  int32_write_value, /* recycle from int32 */
616  int32_read_value, /* recycle from int32 */
617  int32_set_value, /* recycle from int32 */
618  NULL,
619  int32_write_multi, /* recycle from int32 */
620  int32_read_multi /* recycle from int32 */
621 };
622 
623 static const TestTypeNodeClass int64_class = {
625  sizeof (TestTypeNode),
626  0,
627  NULL,
628  NULL,
629  int64_write_value,
630  int64_read_value,
631  int64_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  int64_write_value, /* recycle from int64 */
644  int64_read_value, /* recycle from int64 */
645  int64_set_value, /* recycle from int64 */
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  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  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  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  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  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_int16_t
2064 int16_from_seed (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_int16_t v_of_seed[5] = {
2071  SAMPLE_INT16,
2072  SAMPLE_INT16_ALTERNATE,
2073  -1,
2075  1
2076  };
2077 
2078  dbus_int16_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 int16_write_value (TestTypeNode *node,
2088  DataBlock *block,
2089  DBusTypeWriter *writer,
2090  int seed)
2091 {
2092  /* also used for uint16 */
2093  dbus_int16_t v;
2094 
2095  v = int16_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 int16_read_value (TestTypeNode *node,
2104  DBusTypeReader *reader,
2105  int seed)
2106 {
2107  /* also used for uint16 */
2108  dbus_int16_t v;
2109 
2110  check_expected_type (reader, node->klass->typecode);
2111 
2113  (dbus_int16_t*) &v);
2114 
2115  _dbus_assert (v == int16_from_seed (seed));
2116 
2117  return TRUE;
2118 }
2119 
2120 static dbus_bool_t
2121 int16_set_value (TestTypeNode *node,
2122  DBusTypeReader *reader,
2123  DBusTypeReader *realign_root,
2124  int seed)
2125 {
2126  /* also used for uint16 */
2127  dbus_int16_t v;
2128 
2129  v = int16_from_seed (seed);
2130 
2131  return _dbus_type_reader_set_basic (reader,
2132  &v,
2133  realign_root);
2134 }
2135 
2136 static dbus_bool_t
2137 int16_write_multi (TestTypeNode *node,
2138  DataBlock *block,
2139  DBusTypeWriter *writer,
2140  int seed,
2141  int count)
2142 {
2143  /* also used for uint16 */
2144  dbus_int16_t values[MAX_MULTI_COUNT];
2145  dbus_int16_t *v_ARRAY_INT16 = values;
2146  int i;
2147 
2148  for (i = 0; i < count; ++i)
2149  values[i] = int16_from_seed (seed + i);
2150 
2151  return _dbus_type_writer_write_fixed_multi (writer,
2152  node->klass->typecode,
2153  &v_ARRAY_INT16, count);
2154 }
2155 
2156 static dbus_bool_t
2157 int16_read_multi (TestTypeNode *node,
2158  DBusTypeReader *reader,
2159  int seed,
2160  int count)
2161 {
2162  /* also used for uint16 */
2163  dbus_int16_t *values;
2164  int n_elements;
2165  int i;
2166 
2167  check_expected_type (reader, node->klass->typecode);
2168 
2170  &values,
2171  &n_elements);
2172 
2173  if (n_elements != count)
2174  _dbus_warn ("got %d elements expected %d", n_elements, count);
2175  _dbus_assert (n_elements == count);
2176 
2177  for (i = 0; i < count; i++)
2178  _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
2179  (const unsigned char*)values + (i * 2))) ==
2180  int16_from_seed (seed + i));
2181 
2182  return TRUE;
2183 }
2184 
2185 
2186 #define SAMPLE_INT32 12345678
2187 #define SAMPLE_INT32_ALTERNATE 53781429
2188 static dbus_int32_t
2189 int32_from_seed (int seed)
2190 {
2191  /* Generate an integer value that's predictable from seed. We could
2192  * just use seed itself, but that would only ever touch one byte of
2193  * the int so would miss some kinds of bug.
2194  */
2195  static const dbus_int32_t v_of_seed[5] = {
2196  SAMPLE_INT32,
2197  SAMPLE_INT32_ALTERNATE,
2198  -1,
2199  _DBUS_INT_MAX,
2200  1
2201  };
2202 
2203  dbus_int32_t v = v_of_seed[seed % _DBUS_N_ELEMENTS(v_of_seed)];
2204 
2205  if (seed > 1)
2206  v *= seed; /* wraps around eventually, which is fine */
2207 
2208  return v;
2209 }
2210 
2211 static dbus_bool_t
2212 int32_write_value (TestTypeNode *node,
2213  DataBlock *block,
2214  DBusTypeWriter *writer,
2215  int seed)
2216 {
2217  /* also used for uint32 */
2218  dbus_int32_t v;
2219 
2220  v = int32_from_seed (seed);
2221 
2222  return _dbus_type_writer_write_basic (writer,
2223  node->klass->typecode,
2224  &v);
2225 }
2226 
2227 static dbus_bool_t
2228 int32_read_value (TestTypeNode *node,
2229  DBusTypeReader *reader,
2230  int seed)
2231 {
2232  /* also used for uint32 */
2233  dbus_int32_t v;
2234 
2235  check_expected_type (reader, node->klass->typecode);
2236 
2238  (dbus_int32_t*) &v);
2239 
2240  _dbus_assert (v == int32_from_seed (seed));
2241 
2242  return TRUE;
2243 }
2244 
2245 static dbus_bool_t
2246 int32_set_value (TestTypeNode *node,
2247  DBusTypeReader *reader,
2248  DBusTypeReader *realign_root,
2249  int seed)
2250 {
2251  /* also used for uint32 */
2252  dbus_int32_t v;
2253 
2254  v = int32_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 int32_write_multi (TestTypeNode *node,
2263  DataBlock *block,
2264  DBusTypeWriter *writer,
2265  int seed,
2266  int count)
2267 {
2268  /* also used for uint32 */
2269  dbus_int32_t values[MAX_MULTI_COUNT];
2270  dbus_int32_t *v_ARRAY_INT32 = values;
2271  int i;
2272 
2273  for (i = 0; i < count; ++i)
2274  values[i] = int32_from_seed (seed + i);
2275 
2276  return _dbus_type_writer_write_fixed_multi (writer,
2277  node->klass->typecode,
2278  &v_ARRAY_INT32, count);
2279 }
2280 
2281 static dbus_bool_t
2282 int32_read_multi (TestTypeNode *node,
2283  DBusTypeReader *reader,
2284  int seed,
2285  int count)
2286 {
2287  /* also used for uint32 */
2288  dbus_int32_t *values;
2289  int n_elements;
2290  int i;
2291 
2292  check_expected_type (reader, node->klass->typecode);
2293 
2295  &values,
2296  &n_elements);
2297 
2298  if (n_elements != count)
2299  _dbus_warn ("got %d elements expected %d", n_elements, count);
2300  _dbus_assert (n_elements == count);
2301 
2302  for (i = 0; i < count; i++)
2304  (const unsigned char*)values + (i * 4))) ==
2305  int32_from_seed (seed + i));
2306 
2307  return TRUE;
2308 }
2309 
2310 static dbus_int64_t
2311 int64_from_seed (int seed)
2312 {
2313  dbus_int32_t v32;
2314  dbus_int64_t v;
2315 
2316  v32 = int32_from_seed (seed);
2317 
2318  v = - (dbus_int32_t) ~ v32;
2319  v |= (((dbus_int64_t)v32) << 32);
2320 
2321  return v;
2322 }
2323 
2324 static dbus_bool_t
2325 int64_write_value (TestTypeNode *node,
2326  DataBlock *block,
2327  DBusTypeWriter *writer,
2328  int seed)
2329 {
2330  /* also used for uint64 */
2331  dbus_int64_t v;
2332 
2333  v = int64_from_seed (seed);
2334 
2335  return _dbus_type_writer_write_basic (writer,
2336  node->klass->typecode,
2337  &v);
2338 }
2339 
2340 static dbus_bool_t
2341 int64_read_value (TestTypeNode *node,
2342  DBusTypeReader *reader,
2343  int seed)
2344 {
2345  /* also used for uint64 */
2346  dbus_int64_t v;
2347 
2348  check_expected_type (reader, node->klass->typecode);
2349 
2351  (dbus_int64_t*) &v);
2352 
2353  _dbus_assert (v == int64_from_seed (seed));
2354 
2355  return TRUE;
2356 }
2357 
2358 static dbus_bool_t
2359 int64_set_value (TestTypeNode *node,
2360  DBusTypeReader *reader,
2361  DBusTypeReader *realign_root,
2362  int seed)
2363 {
2364  /* also used for uint64 */
2365  dbus_int64_t v;
2366 
2367  v = int64_from_seed (seed);
2368 
2369  return _dbus_type_reader_set_basic (reader,
2370  &v,
2371  realign_root);
2372 }
2373 
2374 #define MAX_SAMPLE_STRING_LEN 10
2375 static void
2376 string_from_seed (char *buf,
2377  int len,
2378  int seed)
2379 {
2380  int i;
2381  unsigned char v;
2382 
2383  _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
2384 
2385  /* vary the length slightly, though we also have multiple string
2386  * value types for this, varying it here tests the set_value code
2387  */
2388  switch (seed % 3)
2389  {
2390  default:
2391  /* don't alter it */
2392  break;
2393  case 1:
2394  len += 2;
2395  break;
2396  case 2:
2397  len -= 2;
2398  break;
2399  }
2400  if (len < 0)
2401  len = 0;
2402 
2403  v = (unsigned char) ('A' + seed);
2404 
2405  i = 0;
2406  while (i < len)
2407  {
2408  if (v < 'A' || v > 'z')
2409  v = 'A';
2410 
2411  buf[i] = v;
2412 
2413  v += 1;
2414  ++i;
2415  }
2416 
2417  buf[i] = '\0';
2418 }
2419 
2420 static dbus_bool_t
2421 string_write_value (TestTypeNode *node,
2422  DataBlock *block,
2423  DBusTypeWriter *writer,
2424  int seed)
2425 {
2426  char buf[MAX_SAMPLE_STRING_LEN + 1]="";
2427  const char *v_string = buf;
2428 
2429 
2430  string_from_seed (buf, node->klass->subclass_detail,
2431  seed);
2432 
2433  return _dbus_type_writer_write_basic (writer,
2434  node->klass->typecode,
2435  &v_string);
2436 }
2437 
2438 static dbus_bool_t
2439 string_read_value (TestTypeNode *node,
2440  DBusTypeReader *reader,
2441  int seed)
2442 {
2443  const char *v;
2444  char buf[MAX_SAMPLE_STRING_LEN + 1];
2445  v = buf;
2446 
2447  check_expected_type (reader, node->klass->typecode);
2448 
2450  (const char **) &v);
2451 
2452  string_from_seed (buf, node->klass->subclass_detail,
2453  seed);
2454 
2455  if (strcmp (buf, v) != 0)
2456  _dbus_test_fatal ("read string '%s' expected '%s'", v, buf);
2457 
2458  return TRUE;
2459 }
2460 
2461 static dbus_bool_t
2462 string_set_value (TestTypeNode *node,
2463  DBusTypeReader *reader,
2464  DBusTypeReader *realign_root,
2465  int seed)
2466 {
2467  char buf[MAX_SAMPLE_STRING_LEN + 1];
2468  const char *v_string = buf;
2469 
2470  string_from_seed (buf, node->klass->subclass_detail,
2471  seed);
2472 
2473 #if RECURSIVE_MARSHAL_WRITE_TRACE
2474  {
2475  const char *old;
2476  _dbus_type_reader_read_basic (reader, &old);
2477  _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
2478  v_string, strlen (v_string), old, strlen (old));
2479  }
2480 #endif
2481 
2482  return _dbus_type_reader_set_basic (reader,
2483  &v_string,
2484  realign_root);
2485 }
2486 
2487 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
2488 
2489 static dbus_bool_t
2490 bool_write_value (TestTypeNode *node,
2491  DataBlock *block,
2492  DBusTypeWriter *writer,
2493  int seed)
2494 {
2495  dbus_bool_t v;
2496 
2497  v = BOOL_FROM_SEED (seed);
2498 
2499  return _dbus_type_writer_write_basic (writer,
2500  node->klass->typecode,
2501  &v);
2502 }
2503 
2504 static dbus_bool_t
2505 bool_read_value (TestTypeNode *node,
2506  DBusTypeReader *reader,
2507  int seed)
2508 {
2509  dbus_bool_t v;
2510 
2511  check_expected_type (reader, node->klass->typecode);
2512 
2514  (unsigned char*) &v);
2515 
2516  _dbus_assert (v == BOOL_FROM_SEED (seed));
2517 
2518  return TRUE;
2519 }
2520 
2521 static dbus_bool_t
2522 bool_set_value (TestTypeNode *node,
2523  DBusTypeReader *reader,
2524  DBusTypeReader *realign_root,
2525  int seed)
2526 {
2527  dbus_bool_t v;
2528 
2529  v = BOOL_FROM_SEED (seed);
2530 
2531  return _dbus_type_reader_set_basic (reader,
2532  &v,
2533  realign_root);
2534 }
2535 
2536 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
2537 
2538 static dbus_bool_t
2539 byte_write_value (TestTypeNode *node,
2540  DataBlock *block,
2541  DBusTypeWriter *writer,
2542  int seed)
2543 {
2544  unsigned char v;
2545 
2546  v = BYTE_FROM_SEED (seed);
2547 
2548  return _dbus_type_writer_write_basic (writer,
2549  node->klass->typecode,
2550  &v);
2551 }
2552 
2553 static dbus_bool_t
2554 byte_read_value (TestTypeNode *node,
2555  DBusTypeReader *reader,
2556  int seed)
2557 {
2558  unsigned char v;
2559 
2560  check_expected_type (reader, node->klass->typecode);
2561 
2563  (unsigned char*) &v);
2564 
2565  _dbus_assert (v == BYTE_FROM_SEED (seed));
2566 
2567  return TRUE;
2568 }
2569 
2570 
2571 static dbus_bool_t
2572 byte_set_value (TestTypeNode *node,
2573  DBusTypeReader *reader,
2574  DBusTypeReader *realign_root,
2575  int seed)
2576 {
2577  unsigned char v;
2578 
2579  v = BYTE_FROM_SEED (seed);
2580 
2581  return _dbus_type_reader_set_basic (reader,
2582  &v,
2583  realign_root);
2584 }
2585 
2586 static double
2587 double_from_seed (int seed)
2588 {
2589  return SAMPLE_INT32 * (double) seed + 0.3;
2590 }
2591 
2592 static dbus_bool_t
2593 double_write_value (TestTypeNode *node,
2594  DataBlock *block,
2595  DBusTypeWriter *writer,
2596  int seed)
2597 {
2598  double v;
2599 
2600  v = double_from_seed (seed);
2601 
2602  return _dbus_type_writer_write_basic (writer,
2603  node->klass->typecode,
2604  &v);
2605 }
2606 
2607 static dbus_bool_t
2608 double_read_value (TestTypeNode *node,
2609  DBusTypeReader *reader,
2610  int seed)
2611 {
2612  double v;
2613  double expected;
2614 
2615  check_expected_type (reader, node->klass->typecode);
2616 
2618  (double*) &v);
2619 
2620  expected = double_from_seed (seed);
2621 
2622  if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
2623  _dbus_test_fatal ("Expected double %g got %g\n bits = 0x%" PRIx64 " vs.\n bits = 0x%" PRIx64,
2624  expected, v,
2625  *(dbus_uint64_t*)(char*)&expected,
2626  *(dbus_uint64_t*)(char*)&v);
2627 
2628  return TRUE;
2629 }
2630 
2631 static dbus_bool_t
2632 double_set_value (TestTypeNode *node,
2633  DBusTypeReader *reader,
2634  DBusTypeReader *realign_root,
2635  int seed)
2636 {
2637  double v;
2638 
2639  v = double_from_seed (seed);
2640 
2641  return _dbus_type_reader_set_basic (reader,
2642  &v,
2643  realign_root);
2644 }
2645 
2646 #define MAX_SAMPLE_OBJECT_PATH_LEN 10
2647 static void
2648 object_path_from_seed (char *buf,
2649  int seed)
2650 {
2651  int i;
2652  unsigned char v;
2653  int len;
2654 
2655  len = seed % 9;
2656  _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
2657 
2658  v = (unsigned char) ('A' + seed);
2659 
2660  if (len < 2)
2661  {
2662  buf[0] = '/';
2663  i = 1;
2664  }
2665  else
2666  {
2667  i = 0;
2668  while (i + 1 < len)
2669  {
2670  if (v < 'A' || v > 'z')
2671  v = 'A';
2672 
2673  buf[i] = '/';
2674  ++i;
2675  buf[i] = v;
2676  ++i;
2677 
2678  v += 1;
2679  }
2680  }
2681 
2682  buf[i] = '\0';
2683 }
2684 
2685 static dbus_bool_t
2686 object_path_write_value (TestTypeNode *node,
2687  DataBlock *block,
2688  DBusTypeWriter *writer,
2689  int seed)
2690 {
2691  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2692  const char *v_string = buf;
2693 
2694  object_path_from_seed (buf, seed);
2695 
2696  return _dbus_type_writer_write_basic (writer,
2697  node->klass->typecode,
2698  &v_string);
2699 }
2700 
2701 static dbus_bool_t
2702 object_path_read_value (TestTypeNode *node,
2703  DBusTypeReader *reader,
2704  int seed)
2705 {
2706  const char *v;
2707  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2708 
2709  check_expected_type (reader, node->klass->typecode);
2710 
2712  (const char **) &v);
2713 
2714  object_path_from_seed (buf, seed);
2715 
2716  if (strcmp (buf, v) != 0)
2717  _dbus_test_fatal ("read object path '%s' expected '%s'", v, buf);
2718 
2719  return TRUE;
2720 }
2721 
2722 static dbus_bool_t
2723 object_path_set_value (TestTypeNode *node,
2724  DBusTypeReader *reader,
2725  DBusTypeReader *realign_root,
2726  int seed)
2727 {
2728  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2729  const char *v_string = buf;
2730 
2731  object_path_from_seed (buf, seed);
2732 
2733  return _dbus_type_reader_set_basic (reader,
2734  &v_string,
2735  realign_root);
2736 }
2737 
2738 #define MAX_SAMPLE_SIGNATURE_LEN 10
2739 static void
2740 signature_from_seed (char *buf,
2741  int seed)
2742 {
2743  /* try to avoid ascending, descending, or alternating length to help find bugs */
2744  const char *sample_signatures[] = {
2745  "asax",
2746  "",
2747  "asau(xxxx)",
2748  "x",
2749  "ai",
2750  "a(ii)"
2751  };
2752 
2753  strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
2754 }
2755 
2756 static dbus_bool_t
2757 signature_write_value (TestTypeNode *node,
2758  DataBlock *block,
2759  DBusTypeWriter *writer,
2760  int seed)
2761 {
2762  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2763  const char *v_string = buf;
2764 
2765  signature_from_seed (buf, seed);
2766 
2767  return _dbus_type_writer_write_basic (writer,
2768  node->klass->typecode,
2769  &v_string);
2770 }
2771 
2772 static dbus_bool_t
2773 signature_read_value (TestTypeNode *node,
2774  DBusTypeReader *reader,
2775  int seed)
2776 {
2777  const char *v;
2778  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2779 
2780  check_expected_type (reader, node->klass->typecode);
2781 
2783  (const char **) &v);
2784 
2785  signature_from_seed (buf, seed);
2786 
2787  if (strcmp (buf, v) != 0)
2788  _dbus_test_fatal ("read signature value '%s' expected '%s'", v, buf);
2789 
2790  return TRUE;
2791 }
2792 
2793 
2794 static dbus_bool_t
2795 signature_set_value (TestTypeNode *node,
2796  DBusTypeReader *reader,
2797  DBusTypeReader *realign_root,
2798  int seed)
2799 {
2800  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2801  const char *v_string = buf;
2802 
2803  signature_from_seed (buf, seed);
2804 
2805  return _dbus_type_reader_set_basic (reader,
2806  &v_string,
2807  realign_root);
2808 }
2809 
2810 static dbus_bool_t
2811 struct_write_value (TestTypeNode *node,
2812  DataBlock *block,
2813  DBusTypeWriter *writer,
2814  int seed)
2815 {
2816  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2817  DataBlockState saved;
2818  DBusTypeWriter sub;
2819  int i;
2820  int n_copies;
2821 
2822  n_copies = node->klass->subclass_detail;
2823 
2824  _dbus_assert (container->children != NULL);
2825 
2826  data_block_save (block, &saved);
2827 
2829  NULL, 0,
2830  &sub))
2831  return FALSE;
2832 
2833  i = 0;
2834  while (i < n_copies)
2835  {
2836  DBusList *link;
2837 
2838  link = _dbus_list_get_first_link (&container->children);
2839  while (link != NULL)
2840  {
2841  TestTypeNode *child = link->data;
2842  DBusList *next = _dbus_list_get_next_link (&container->children, link);
2843 
2844  if (!node_write_value (child, block, &sub, seed + i))
2845  {
2846  data_block_restore (block, &saved);
2847  return FALSE;
2848  }
2849 
2850  link = next;
2851  }
2852 
2853  ++i;
2854  }
2855 
2856  if (!_dbus_type_writer_unrecurse (writer, &sub))
2857  {
2858  data_block_restore (block, &saved);
2859  return FALSE;
2860  }
2861 
2862  return TRUE;
2863 }
2864 
2865 static dbus_bool_t
2866 struct_read_or_set_value (TestTypeNode *node,
2867  DBusTypeReader *reader,
2868  DBusTypeReader *realign_root,
2869  int seed)
2870 {
2871  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2872  DBusTypeReader sub;
2873  int i;
2874  int n_copies;
2875 
2876  n_copies = node->klass->subclass_detail;
2877 
2878  check_expected_type (reader, DBUS_TYPE_STRUCT);
2879 
2880  _dbus_type_reader_recurse (reader, &sub);
2881 
2882  i = 0;
2883  while (i < n_copies)
2884  {
2885  DBusList *link;
2886 
2887  link = _dbus_list_get_first_link (&container->children);
2888  while (link != NULL)
2889  {
2890  TestTypeNode *child = link->data;
2891  DBusList *next = _dbus_list_get_next_link (&container->children, link);
2892 
2893  if (realign_root == NULL)
2894  {
2895  if (!node_read_value (child, &sub, seed + i))
2896  return FALSE;
2897  }
2898  else
2899  {
2900  if (!node_set_value (child, &sub, realign_root, seed + i))
2901  return FALSE;
2902  }
2903 
2904  if (i == (n_copies - 1) && next == NULL)
2905  NEXT_EXPECTING_FALSE (&sub);
2906  else
2907  NEXT_EXPECTING_TRUE (&sub);
2908 
2909  link = next;
2910  }
2911 
2912  ++i;
2913  }
2914 
2915  return TRUE;
2916 }
2917 
2918 static dbus_bool_t
2919 struct_read_value (TestTypeNode *node,
2920  DBusTypeReader *reader,
2921  int seed)
2922 {
2923  return struct_read_or_set_value (node, reader, NULL, seed);
2924 }
2925 
2926 static dbus_bool_t
2927 struct_set_value (TestTypeNode *node,
2928  DBusTypeReader *reader,
2929  DBusTypeReader *realign_root,
2930  int seed)
2931 {
2932  return struct_read_or_set_value (node, reader, realign_root, seed);
2933 }
2934 
2935 static dbus_bool_t
2936 struct_build_signature (TestTypeNode *node,
2937  DBusString *str)
2938 {
2939  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2940  int i;
2941  int orig_len;
2942  int n_copies;
2943 
2944  n_copies = node->klass->subclass_detail;
2945 
2946  orig_len = _dbus_string_get_length (str);
2947 
2949  goto oom;
2950 
2951  i = 0;
2952  while (i < n_copies)
2953  {
2954  DBusList *link;
2955 
2956  link = _dbus_list_get_first_link (&container->children);
2957  while (link != NULL)
2958  {
2959  TestTypeNode *child = link->data;
2960  DBusList *next = _dbus_list_get_next_link (&container->children, link);
2961 
2962  if (!node_build_signature (child, str))
2963  goto oom;
2964 
2965  link = next;
2966  }
2967 
2968  ++i;
2969  }
2970 
2972  goto oom;
2973 
2974  return TRUE;
2975 
2976  oom:
2977  _dbus_string_set_length (str, orig_len);
2978  return FALSE;
2979 }
2980 
2981 static dbus_bool_t
2982 array_write_value (TestTypeNode *node,
2983  DataBlock *block,
2984  DBusTypeWriter *writer,
2985  int seed)
2986 {
2987  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2988  DataBlockState saved;
2989  DBusTypeWriter sub;
2990  DBusString element_signature;
2991  int i;
2992  int n_copies;
2993  int element_type;
2994  TestTypeNode *child;
2995 
2996  n_copies = node->klass->subclass_detail;
2997 
2998  _dbus_assert (container->children != NULL);
2999 
3000  data_block_save (block, &saved);
3001 
3002  if (!_dbus_string_init (&element_signature))
3003  return FALSE;
3004 
3005  child = _dbus_list_get_first (&container->children);
3006 
3007  if (!node_build_signature (child,
3008  &element_signature))
3009  goto oom;
3010 
3011  element_type = _dbus_first_type_in_signature (&element_signature, 0);
3012 
3014  &element_signature, 0,
3015  &sub))
3016  goto oom;
3017 
3018  if (arrays_write_fixed_in_blocks &&
3019  dbus_type_is_fixed (element_type) &&
3020  child->klass->write_multi)
3021  {
3022  if (!node_write_multi (child, block, &sub, seed, n_copies))
3023  goto oom;
3024  }
3025  else
3026  {
3027  i = 0;
3028  while (i < n_copies)
3029  {
3030  DBusList *link;
3031 
3032  link = _dbus_list_get_first_link (&container->children);
3033  while (link != NULL)
3034  {
3035  TestTypeNode *child2 = link->data;
3036  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3037 
3038  if (!node_write_value (child2, block, &sub, seed + i))
3039  goto oom;
3040 
3041  link = next;
3042  }
3043 
3044  ++i;
3045  }
3046  }
3047 
3048  if (!_dbus_type_writer_unrecurse (writer, &sub))
3049  goto oom;
3050 
3051  _dbus_string_free (&element_signature);
3052  return TRUE;
3053 
3054  oom:
3055  data_block_restore (block, &saved);
3056  _dbus_string_free (&element_signature);
3057  return FALSE;
3058 }
3059 
3060 static dbus_bool_t
3061 array_read_or_set_value (TestTypeNode *node,
3062  DBusTypeReader *reader,
3063  DBusTypeReader *realign_root,
3064  int seed)
3065 {
3066  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3067  DBusTypeReader sub;
3068  int i;
3069  int n_copies;
3070  TestTypeNode *child;
3071 
3072  n_copies = node->klass->subclass_detail;
3073 
3074  check_expected_type (reader, DBUS_TYPE_ARRAY);
3075 
3076  child = _dbus_list_get_first (&container->children);
3077 
3078  if (n_copies > 0)
3079  {
3080  _dbus_type_reader_recurse (reader, &sub);
3081 
3082  if (realign_root == NULL && arrays_write_fixed_in_blocks &&
3084  child->klass->read_multi)
3085  {
3086  if (!node_read_multi (child, &sub, seed, n_copies))
3087  return FALSE;
3088  }
3089  else
3090  {
3091  i = 0;
3092  while (i < n_copies)
3093  {
3094  DBusList *link;
3095 
3096  link = _dbus_list_get_first_link (&container->children);
3097  while (link != NULL)
3098  {
3099  TestTypeNode *child2 = link->data;
3100  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3101 
3102  _dbus_assert (child2->klass->typecode ==
3104 
3105  if (realign_root == NULL)
3106  {
3107  if (!node_read_value (child2, &sub, seed + i))
3108  return FALSE;
3109  }
3110  else
3111  {
3112  if (!node_set_value (child2, &sub, realign_root, seed + i))
3113  return FALSE;
3114  }
3115 
3116  if (i == (n_copies - 1) && next == NULL)
3117  NEXT_EXPECTING_FALSE (&sub);
3118  else
3119  NEXT_EXPECTING_TRUE (&sub);
3120 
3121  link = next;
3122  }
3123 
3124  ++i;
3125  }
3126  }
3127  }
3128 
3129  return TRUE;
3130 }
3131 
3132 static dbus_bool_t
3133 array_read_value (TestTypeNode *node,
3134  DBusTypeReader *reader,
3135  int seed)
3136 {
3137  return array_read_or_set_value (node, reader, NULL, seed);
3138 }
3139 
3140 static dbus_bool_t
3141 array_set_value (TestTypeNode *node,
3142  DBusTypeReader *reader,
3143  DBusTypeReader *realign_root,
3144  int seed)
3145 {
3146  return array_read_or_set_value (node, reader, realign_root, seed);
3147 }
3148 
3149 static dbus_bool_t
3150 array_build_signature (TestTypeNode *node,
3151  DBusString *str)
3152 {
3153  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3154  int orig_len;
3155 
3156  orig_len = _dbus_string_get_length (str);
3157 
3159  goto oom;
3160 
3161  if (!node_build_signature (_dbus_list_get_first (&container->children),
3162  str))
3163  goto oom;
3164 
3165  return TRUE;
3166 
3167  oom:
3168  _dbus_string_set_length (str, orig_len);
3169  return FALSE;
3170 }
3171 
3172  /* 10 is random just to add another seed that we use in the suite */
3173 #define VARIANT_SEED 10
3174 
3175 static dbus_bool_t
3176 variant_write_value (TestTypeNode *node,
3177  DataBlock *block,
3178  DBusTypeWriter *writer,
3179  int seed)
3180 {
3181  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3182  DataBlockState saved;
3183  DBusTypeWriter sub;
3184  DBusString content_signature;
3185  TestTypeNode *child;
3186 
3187  _dbus_assert (container->children != NULL);
3188  _dbus_assert (_dbus_list_length_is_one (&container->children));
3189 
3190  child = _dbus_list_get_first (&container->children);
3191 
3192  data_block_save (block, &saved);
3193 
3194  if (!_dbus_string_init (&content_signature))
3195  return FALSE;
3196 
3197  if (!node_build_signature (child,
3198  &content_signature))
3199  goto oom;
3200 
3202  &content_signature, 0,
3203  &sub))
3204  goto oom;
3205 
3206  if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
3207  goto oom;
3208 
3209  if (!_dbus_type_writer_unrecurse (writer, &sub))
3210  goto oom;
3211 
3212  _dbus_string_free (&content_signature);
3213  return TRUE;
3214 
3215  oom:
3216  data_block_restore (block, &saved);
3217  _dbus_string_free (&content_signature);
3218  return FALSE;
3219 }
3220 
3221 static dbus_bool_t
3222 variant_read_or_set_value (TestTypeNode *node,
3223  DBusTypeReader *reader,
3224  DBusTypeReader *realign_root,
3225  int seed)
3226 {
3227  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3228  DBusTypeReader sub;
3229  TestTypeNode *child;
3230 
3231  _dbus_assert (container->children != NULL);
3232  _dbus_assert (_dbus_list_length_is_one (&container->children));
3233 
3234  child = _dbus_list_get_first (&container->children);
3235 
3236  check_expected_type (reader, DBUS_TYPE_VARIANT);
3237 
3238  _dbus_type_reader_recurse (reader, &sub);
3239 
3240  if (realign_root == NULL)
3241  {
3242  if (!node_read_value (child, &sub, seed + VARIANT_SEED))
3243  return FALSE;
3244  }
3245  else
3246  {
3247  if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
3248  return FALSE;
3249  }
3250 
3251  NEXT_EXPECTING_FALSE (&sub);
3252 
3253  return TRUE;
3254 }
3255 
3256 static dbus_bool_t
3257 variant_read_value (TestTypeNode *node,
3258  DBusTypeReader *reader,
3259  int seed)
3260 {
3261  return variant_read_or_set_value (node, reader, NULL, seed);
3262 }
3263 
3264 static dbus_bool_t
3265 variant_set_value (TestTypeNode *node,
3266  DBusTypeReader *reader,
3267  DBusTypeReader *realign_root,
3268  int seed)
3269 {
3270  return variant_read_or_set_value (node, reader, realign_root, seed);
3271 }
3272 
3273 static dbus_bool_t
3274 dict_write_value (TestTypeNode *node,
3275  DataBlock *block,
3276  DBusTypeWriter *writer,
3277  int seed)
3278 {
3279  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3280  DataBlockState saved;
3281  DBusTypeWriter sub;
3282  DBusString entry_value_signature;
3283  DBusString dict_entry_signature;
3284  int i;
3285  int n_entries;
3286  TestTypeNode *child;
3287 
3288  n_entries = node->klass->subclass_detail;
3289 
3290  _dbus_assert (container->children != NULL);
3291 
3292  data_block_save (block, &saved);
3293 
3294  if (!_dbus_string_init (&entry_value_signature))
3295  return FALSE;
3296 
3297  if (!_dbus_string_init (&dict_entry_signature))
3298  {
3299  _dbus_string_free (&entry_value_signature);
3300  return FALSE;
3301  }
3302 
3303  child = _dbus_list_get_first (&container->children);
3304 
3305  if (!node_build_signature (child,
3306  &entry_value_signature))
3307  goto oom;
3308 
3309  if (!_dbus_string_append (&dict_entry_signature,
3312  goto oom;
3313 
3314  if (!_dbus_string_copy (&entry_value_signature, 0,
3315  &dict_entry_signature,
3316  _dbus_string_get_length (&dict_entry_signature)))
3317  goto oom;
3318 
3319  if (!_dbus_string_append_byte (&dict_entry_signature,
3321  goto oom;
3322 
3324  &dict_entry_signature, 0,
3325  &sub))
3326  goto oom;
3327 
3328  i = 0;
3329  while (i < n_entries)
3330  {
3331  DBusTypeWriter entry_sub;
3332  dbus_int32_t key;
3333 
3335  NULL, 0,
3336  &entry_sub))
3337  goto oom;
3338 
3339  key = int32_from_seed (seed + i);
3340 
3341  if (!_dbus_type_writer_write_basic (&entry_sub,
3343  &key))
3344  goto oom;
3345 
3346  if (!node_write_value (child, block, &entry_sub, seed + i))
3347  goto oom;
3348 
3349  if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
3350  goto oom;
3351 
3352  ++i;
3353  }
3354 
3355  if (!_dbus_type_writer_unrecurse (writer, &sub))
3356  goto oom;
3357 
3358  _dbus_string_free (&entry_value_signature);
3359  _dbus_string_free (&dict_entry_signature);
3360  return TRUE;
3361 
3362  oom:
3363  data_block_restore (block, &saved);
3364  _dbus_string_free (&entry_value_signature);
3365  _dbus_string_free (&dict_entry_signature);
3366  return FALSE;
3367 }
3368 
3369 static dbus_bool_t
3370 dict_read_or_set_value (TestTypeNode *node,
3371  DBusTypeReader *reader,
3372  DBusTypeReader *realign_root,
3373  int seed)
3374 {
3375  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3376  DBusTypeReader sub;
3377  int i;
3378  int n_entries;
3379  TestTypeNode *child;
3380 
3381  n_entries = node->klass->subclass_detail;
3382 
3383  check_expected_type (reader, DBUS_TYPE_ARRAY);
3384 
3385  child = _dbus_list_get_first (&container->children);
3386 
3387  if (n_entries > 0)
3388  {
3389  _dbus_type_reader_recurse (reader, &sub);
3390 
3391  check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3392 
3393  i = 0;
3394  while (i < n_entries)
3395  {
3396  DBusTypeReader entry_sub;
3397 
3398  check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3399 
3400  _dbus_type_reader_recurse (&sub, &entry_sub);
3401 
3402  if (realign_root == NULL)
3403  {
3404  dbus_int32_t v;
3405 
3406  check_expected_type (&entry_sub, DBUS_TYPE_INT32);
3407 
3408  _dbus_type_reader_read_basic (&entry_sub,
3409  (dbus_int32_t*) &v);
3410 
3411  _dbus_assert (v == int32_from_seed (seed + i));
3412 
3413  NEXT_EXPECTING_TRUE (&entry_sub);
3414 
3415  if (!node_read_value (child, &entry_sub, seed + i))
3416  return FALSE;
3417 
3418  NEXT_EXPECTING_FALSE (&entry_sub);
3419  }
3420  else
3421  {
3422  dbus_int32_t v;
3423 
3424  v = int32_from_seed (seed + i);
3425 
3426  if (!_dbus_type_reader_set_basic (&entry_sub,
3427  &v,
3428  realign_root))
3429  return FALSE;
3430 
3431  NEXT_EXPECTING_TRUE (&entry_sub);
3432 
3433  if (!node_set_value (child, &entry_sub, realign_root, seed + i))
3434  return FALSE;
3435 
3436  NEXT_EXPECTING_FALSE (&entry_sub);
3437  }
3438 
3439  if (i == (n_entries - 1))
3440  NEXT_EXPECTING_FALSE (&sub);
3441  else
3442  NEXT_EXPECTING_TRUE (&sub);
3443 
3444  ++i;
3445  }
3446  }
3447 
3448  return TRUE;
3449 }
3450 
3451 static dbus_bool_t
3452 dict_read_value (TestTypeNode *node,
3453  DBusTypeReader *reader,
3454  int seed)
3455 {
3456  return dict_read_or_set_value (node, reader, NULL, seed);
3457 }
3458 
3459 static dbus_bool_t
3460 dict_set_value (TestTypeNode *node,
3461  DBusTypeReader *reader,
3462  DBusTypeReader *realign_root,
3463  int seed)
3464 {
3465  return dict_read_or_set_value (node, reader, realign_root, seed);
3466 }
3467 
3468 static dbus_bool_t
3469 dict_build_signature (TestTypeNode *node,
3470  DBusString *str)
3471 {
3472  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3473  int orig_len;
3474 
3475  orig_len = _dbus_string_get_length (str);
3476 
3478  goto oom;
3479 
3480  if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
3481  goto oom;
3482 
3483  if (!node_build_signature (_dbus_list_get_first (&container->children),
3484  str))
3485  goto oom;
3486 
3488  goto oom;
3489 
3490  return TRUE;
3491 
3492  oom:
3493  _dbus_string_set_length (str, orig_len);
3494  return FALSE;
3495 }
3496 
3497 static void
3498 container_destroy (TestTypeNode *node)
3499 {
3500  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3501  DBusList *link;
3502 
3503  link = _dbus_list_get_first_link (&container->children);
3504  while (link != NULL)
3505  {
3506  TestTypeNode *child = link->data;
3507  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3508 
3509  node_destroy (child);
3510 
3511  _dbus_list_free_link (link);
3512 
3513  link = next;
3514  }
3515 }
3516 
3517 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
3518 
3519 #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 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_INT_MAX
Maximum value of type "int".
#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_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
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:616
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