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