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