D-Bus  1.12.2
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  static const dbus_int16_t v_of_seed[5] = {
2074  SAMPLE_INT16,
2075  SAMPLE_INT16_ALTERNATE,
2076  -1,
2078  1
2079  };
2080 
2081  dbus_int16_t v = v_of_seed[seed % _DBUS_N_ELEMENTS(v_of_seed)];
2082 
2083  if (seed > 1)
2084  v *= seed; /* wraps around eventually, which is fine */
2085 
2086  return v;
2087 }
2088 
2089 static dbus_bool_t
2090 int16_write_value (TestTypeNode *node,
2091  DataBlock *block,
2092  DBusTypeWriter *writer,
2093  int seed)
2094 {
2095  /* also used for uint16 */
2096  dbus_int16_t v;
2097 
2098  v = int16_from_seed (seed);
2099 
2100  return _dbus_type_writer_write_basic (writer,
2101  node->klass->typecode,
2102  &v);
2103 }
2104 
2105 static dbus_bool_t
2106 int16_read_value (TestTypeNode *node,
2107  DBusTypeReader *reader,
2108  int seed)
2109 {
2110  /* also used for uint16 */
2111  dbus_int16_t v;
2112 
2113  check_expected_type (reader, node->klass->typecode);
2114 
2116  (dbus_int16_t*) &v);
2117 
2118  _dbus_assert (v == int16_from_seed (seed));
2119 
2120  return TRUE;
2121 }
2122 
2123 static dbus_bool_t
2124 int16_set_value (TestTypeNode *node,
2125  DBusTypeReader *reader,
2126  DBusTypeReader *realign_root,
2127  int seed)
2128 {
2129  /* also used for uint16 */
2130  dbus_int16_t v;
2131 
2132  v = int16_from_seed (seed);
2133 
2134  return _dbus_type_reader_set_basic (reader,
2135  &v,
2136  realign_root);
2137 }
2138 
2139 static dbus_bool_t
2140 int16_write_multi (TestTypeNode *node,
2141  DataBlock *block,
2142  DBusTypeWriter *writer,
2143  int seed,
2144  int count)
2145 {
2146  /* also used for uint16 */
2147  dbus_int16_t values[MAX_MULTI_COUNT];
2148  dbus_int16_t *v_ARRAY_INT16 = values;
2149  int i;
2150 
2151  for (i = 0; i < count; ++i)
2152  values[i] = int16_from_seed (seed + i);
2153 
2154  return _dbus_type_writer_write_fixed_multi (writer,
2155  node->klass->typecode,
2156  &v_ARRAY_INT16, count);
2157 }
2158 
2159 static dbus_bool_t
2160 int16_read_multi (TestTypeNode *node,
2161  DBusTypeReader *reader,
2162  int seed,
2163  int count)
2164 {
2165  /* also used for uint16 */
2166  dbus_int16_t *values;
2167  int n_elements;
2168  int i;
2169 
2170  check_expected_type (reader, node->klass->typecode);
2171 
2173  &values,
2174  &n_elements);
2175 
2176  if (n_elements != count)
2177  _dbus_warn ("got %d elements expected %d", n_elements, count);
2178  _dbus_assert (n_elements == count);
2179 
2180  for (i = 0; i < count; i++)
2182  (const unsigned char*)values + (i * 2))) ==
2183  int16_from_seed (seed + i));
2184 
2185  return TRUE;
2186 }
2187 
2188 
2189 #define SAMPLE_INT32 12345678
2190 #define SAMPLE_INT32_ALTERNATE 53781429
2191 static dbus_int32_t
2192 int32_from_seed (int seed)
2193 {
2194  /* Generate an integer value that's predictable from seed. We could
2195  * just use seed itself, but that would only ever touch one byte of
2196  * the int so would miss some kinds of bug.
2197  */
2198  static const dbus_int32_t v_of_seed[5] = {
2199  SAMPLE_INT32,
2200  SAMPLE_INT32_ALTERNATE,
2201  -1,
2202  _DBUS_INT_MAX,
2203  1
2204  };
2205 
2206  dbus_int32_t v = v_of_seed[seed % _DBUS_N_ELEMENTS(v_of_seed)];
2207 
2208  if (seed > 1)
2209  v *= seed; /* wraps around eventually, which is fine */
2210 
2211  return v;
2212 }
2213 
2214 static dbus_bool_t
2215 int32_write_value (TestTypeNode *node,
2216  DataBlock *block,
2217  DBusTypeWriter *writer,
2218  int seed)
2219 {
2220  /* also used for uint32 */
2221  dbus_int32_t v;
2222 
2223  v = int32_from_seed (seed);
2224 
2225  return _dbus_type_writer_write_basic (writer,
2226  node->klass->typecode,
2227  &v);
2228 }
2229 
2230 static dbus_bool_t
2231 int32_read_value (TestTypeNode *node,
2232  DBusTypeReader *reader,
2233  int seed)
2234 {
2235  /* also used for uint32 */
2236  dbus_int32_t v;
2237 
2238  check_expected_type (reader, node->klass->typecode);
2239 
2241  (dbus_int32_t*) &v);
2242 
2243  _dbus_assert (v == int32_from_seed (seed));
2244 
2245  return TRUE;
2246 }
2247 
2248 static dbus_bool_t
2249 int32_set_value (TestTypeNode *node,
2250  DBusTypeReader *reader,
2251  DBusTypeReader *realign_root,
2252  int seed)
2253 {
2254  /* also used for uint32 */
2255  dbus_int32_t v;
2256 
2257  v = int32_from_seed (seed);
2258 
2259  return _dbus_type_reader_set_basic (reader,
2260  &v,
2261  realign_root);
2262 }
2263 
2264 static dbus_bool_t
2265 int32_write_multi (TestTypeNode *node,
2266  DataBlock *block,
2267  DBusTypeWriter *writer,
2268  int seed,
2269  int count)
2270 {
2271  /* also used for uint32 */
2272  dbus_int32_t values[MAX_MULTI_COUNT];
2273  dbus_int32_t *v_ARRAY_INT32 = values;
2274  int i;
2275 
2276  for (i = 0; i < count; ++i)
2277  values[i] = int32_from_seed (seed + i);
2278 
2279  return _dbus_type_writer_write_fixed_multi (writer,
2280  node->klass->typecode,
2281  &v_ARRAY_INT32, count);
2282 }
2283 
2284 static dbus_bool_t
2285 int32_read_multi (TestTypeNode *node,
2286  DBusTypeReader *reader,
2287  int seed,
2288  int count)
2289 {
2290  /* also used for uint32 */
2291  dbus_int32_t *values;
2292  int n_elements;
2293  int i;
2294 
2295  check_expected_type (reader, node->klass->typecode);
2296 
2298  &values,
2299  &n_elements);
2300 
2301  if (n_elements != count)
2302  _dbus_warn ("got %d elements expected %d", n_elements, count);
2303  _dbus_assert (n_elements == count);
2304 
2305  for (i = 0; i < count; i++)
2307  (const unsigned char*)values + (i * 4))) ==
2308  int32_from_seed (seed + i));
2309 
2310  return TRUE;
2311 }
2312 
2313 static dbus_int64_t
2314 int64_from_seed (int seed)
2315 {
2316  dbus_int32_t v32;
2317  dbus_int64_t v;
2318 
2319  v32 = int32_from_seed (seed);
2320 
2321  v = - (dbus_int32_t) ~ v32;
2322  v |= (((dbus_int64_t)v32) << 32);
2323 
2324  return v;
2325 }
2326 
2327 static dbus_bool_t
2328 int64_write_value (TestTypeNode *node,
2329  DataBlock *block,
2330  DBusTypeWriter *writer,
2331  int seed)
2332 {
2333  /* also used for uint64 */
2334  dbus_int64_t v;
2335 
2336  v = int64_from_seed (seed);
2337 
2338  return _dbus_type_writer_write_basic (writer,
2339  node->klass->typecode,
2340  &v);
2341 }
2342 
2343 static dbus_bool_t
2344 int64_read_value (TestTypeNode *node,
2345  DBusTypeReader *reader,
2346  int seed)
2347 {
2348  /* also used for uint64 */
2349  dbus_int64_t v;
2350 
2351  check_expected_type (reader, node->klass->typecode);
2352 
2354  (dbus_int64_t*) &v);
2355 
2356  _dbus_assert (v == int64_from_seed (seed));
2357 
2358  return TRUE;
2359 }
2360 
2361 static dbus_bool_t
2362 int64_set_value (TestTypeNode *node,
2363  DBusTypeReader *reader,
2364  DBusTypeReader *realign_root,
2365  int seed)
2366 {
2367  /* also used for uint64 */
2368  dbus_int64_t v;
2369 
2370  v = int64_from_seed (seed);
2371 
2372  return _dbus_type_reader_set_basic (reader,
2373  &v,
2374  realign_root);
2375 }
2376 
2377 #define MAX_SAMPLE_STRING_LEN 10
2378 static void
2379 string_from_seed (char *buf,
2380  int len,
2381  int seed)
2382 {
2383  int i;
2384  unsigned char v;
2385 
2386  _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
2387 
2388  /* vary the length slightly, though we also have multiple string
2389  * value types for this, varying it here tests the set_value code
2390  */
2391  switch (seed % 3)
2392  {
2393  default:
2394  /* don't alter it */
2395  break;
2396  case 1:
2397  len += 2;
2398  break;
2399  case 2:
2400  len -= 2;
2401  break;
2402  }
2403  if (len < 0)
2404  len = 0;
2405 
2406  v = (unsigned char) ('A' + seed);
2407 
2408  i = 0;
2409  while (i < len)
2410  {
2411  if (v < 'A' || v > 'z')
2412  v = 'A';
2413 
2414  buf[i] = v;
2415 
2416  v += 1;
2417  ++i;
2418  }
2419 
2420  buf[i] = '\0';
2421 }
2422 
2423 static dbus_bool_t
2424 string_write_value (TestTypeNode *node,
2425  DataBlock *block,
2426  DBusTypeWriter *writer,
2427  int seed)
2428 {
2429  char buf[MAX_SAMPLE_STRING_LEN + 1]="";
2430  const char *v_string = buf;
2431 
2432 
2433  string_from_seed (buf, node->klass->subclass_detail,
2434  seed);
2435 
2436  return _dbus_type_writer_write_basic (writer,
2437  node->klass->typecode,
2438  &v_string);
2439 }
2440 
2441 static dbus_bool_t
2442 string_read_value (TestTypeNode *node,
2443  DBusTypeReader *reader,
2444  int seed)
2445 {
2446  const char *v;
2447  char buf[MAX_SAMPLE_STRING_LEN + 1];
2448  v = buf;
2449 
2450  check_expected_type (reader, node->klass->typecode);
2451 
2453  (const char **) &v);
2454 
2455  string_from_seed (buf, node->klass->subclass_detail,
2456  seed);
2457 
2458  if (strcmp (buf, v) != 0)
2459  {
2460  _dbus_warn ("read string '%s' expected '%s'",
2461  v, buf);
2462  _dbus_assert_not_reached ("test failed");
2463  }
2464 
2465  return TRUE;
2466 }
2467 
2468 static dbus_bool_t
2469 string_set_value (TestTypeNode *node,
2470  DBusTypeReader *reader,
2471  DBusTypeReader *realign_root,
2472  int seed)
2473 {
2474  char buf[MAX_SAMPLE_STRING_LEN + 1];
2475  const char *v_string = buf;
2476 
2477  string_from_seed (buf, node->klass->subclass_detail,
2478  seed);
2479 
2480 #if RECURSIVE_MARSHAL_WRITE_TRACE
2481  {
2482  const char *old;
2483  _dbus_type_reader_read_basic (reader, &old);
2484  _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
2485  v_string, strlen (v_string), old, strlen (old));
2486  }
2487 #endif
2488 
2489  return _dbus_type_reader_set_basic (reader,
2490  &v_string,
2491  realign_root);
2492 }
2493 
2494 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
2495 
2496 static dbus_bool_t
2497 bool_write_value (TestTypeNode *node,
2498  DataBlock *block,
2499  DBusTypeWriter *writer,
2500  int seed)
2501 {
2502  dbus_bool_t v;
2503 
2504  v = BOOL_FROM_SEED (seed);
2505 
2506  return _dbus_type_writer_write_basic (writer,
2507  node->klass->typecode,
2508  &v);
2509 }
2510 
2511 static dbus_bool_t
2512 bool_read_value (TestTypeNode *node,
2513  DBusTypeReader *reader,
2514  int seed)
2515 {
2516  dbus_bool_t v;
2517 
2518  check_expected_type (reader, node->klass->typecode);
2519 
2521  (unsigned char*) &v);
2522 
2523  _dbus_assert (v == BOOL_FROM_SEED (seed));
2524 
2525  return TRUE;
2526 }
2527 
2528 static dbus_bool_t
2529 bool_set_value (TestTypeNode *node,
2530  DBusTypeReader *reader,
2531  DBusTypeReader *realign_root,
2532  int seed)
2533 {
2534  dbus_bool_t v;
2535 
2536  v = BOOL_FROM_SEED (seed);
2537 
2538  return _dbus_type_reader_set_basic (reader,
2539  &v,
2540  realign_root);
2541 }
2542 
2543 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
2544 
2545 static dbus_bool_t
2546 byte_write_value (TestTypeNode *node,
2547  DataBlock *block,
2548  DBusTypeWriter *writer,
2549  int seed)
2550 {
2551  unsigned char v;
2552 
2553  v = BYTE_FROM_SEED (seed);
2554 
2555  return _dbus_type_writer_write_basic (writer,
2556  node->klass->typecode,
2557  &v);
2558 }
2559 
2560 static dbus_bool_t
2561 byte_read_value (TestTypeNode *node,
2562  DBusTypeReader *reader,
2563  int seed)
2564 {
2565  unsigned char v;
2566 
2567  check_expected_type (reader, node->klass->typecode);
2568 
2570  (unsigned char*) &v);
2571 
2572  _dbus_assert (v == BYTE_FROM_SEED (seed));
2573 
2574  return TRUE;
2575 }
2576 
2577 
2578 static dbus_bool_t
2579 byte_set_value (TestTypeNode *node,
2580  DBusTypeReader *reader,
2581  DBusTypeReader *realign_root,
2582  int seed)
2583 {
2584  unsigned char v;
2585 
2586  v = BYTE_FROM_SEED (seed);
2587 
2588  return _dbus_type_reader_set_basic (reader,
2589  &v,
2590  realign_root);
2591 }
2592 
2593 static double
2594 double_from_seed (int seed)
2595 {
2596  return SAMPLE_INT32 * (double) seed + 0.3;
2597 }
2598 
2599 static dbus_bool_t
2600 double_write_value (TestTypeNode *node,
2601  DataBlock *block,
2602  DBusTypeWriter *writer,
2603  int seed)
2604 {
2605  double v;
2606 
2607  v = double_from_seed (seed);
2608 
2609  return _dbus_type_writer_write_basic (writer,
2610  node->klass->typecode,
2611  &v);
2612 }
2613 
2614 static dbus_bool_t
2615 double_read_value (TestTypeNode *node,
2616  DBusTypeReader *reader,
2617  int seed)
2618 {
2619  double v;
2620  double expected;
2621 
2622  check_expected_type (reader, node->klass->typecode);
2623 
2625  (double*) &v);
2626 
2627  expected = double_from_seed (seed);
2628 
2629  if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
2630  {
2631  _dbus_warn ("Expected double %g got %g\n bits = 0x%" PRIx64 " vs.\n bits = 0x%" PRIx64,
2632  expected, v,
2633  *(dbus_uint64_t*)(char*)&expected,
2634  *(dbus_uint64_t*)(char*)&v);
2635  _dbus_assert_not_reached ("test failed");
2636  }
2637 
2638  return TRUE;
2639 }
2640 
2641 static dbus_bool_t
2642 double_set_value (TestTypeNode *node,
2643  DBusTypeReader *reader,
2644  DBusTypeReader *realign_root,
2645  int seed)
2646 {
2647  double v;
2648 
2649  v = double_from_seed (seed);
2650 
2651  return _dbus_type_reader_set_basic (reader,
2652  &v,
2653  realign_root);
2654 }
2655 
2656 #define MAX_SAMPLE_OBJECT_PATH_LEN 10
2657 static void
2658 object_path_from_seed (char *buf,
2659  int seed)
2660 {
2661  int i;
2662  unsigned char v;
2663  int len;
2664 
2665  len = seed % 9;
2666  _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
2667 
2668  v = (unsigned char) ('A' + seed);
2669 
2670  if (len < 2)
2671  {
2672  buf[0] = '/';
2673  i = 1;
2674  }
2675  else
2676  {
2677  i = 0;
2678  while (i + 1 < len)
2679  {
2680  if (v < 'A' || v > 'z')
2681  v = 'A';
2682 
2683  buf[i] = '/';
2684  ++i;
2685  buf[i] = v;
2686  ++i;
2687 
2688  v += 1;
2689  }
2690  }
2691 
2692  buf[i] = '\0';
2693 }
2694 
2695 static dbus_bool_t
2696 object_path_write_value (TestTypeNode *node,
2697  DataBlock *block,
2698  DBusTypeWriter *writer,
2699  int seed)
2700 {
2701  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2702  const char *v_string = buf;
2703 
2704  object_path_from_seed (buf, seed);
2705 
2706  return _dbus_type_writer_write_basic (writer,
2707  node->klass->typecode,
2708  &v_string);
2709 }
2710 
2711 static dbus_bool_t
2712 object_path_read_value (TestTypeNode *node,
2713  DBusTypeReader *reader,
2714  int seed)
2715 {
2716  const char *v;
2717  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2718 
2719  check_expected_type (reader, node->klass->typecode);
2720 
2722  (const char **) &v);
2723 
2724  object_path_from_seed (buf, seed);
2725 
2726  if (strcmp (buf, v) != 0)
2727  {
2728  _dbus_warn ("read object path '%s' expected '%s'",
2729  v, buf);
2730  _dbus_assert_not_reached ("test failed");
2731  }
2732 
2733  return TRUE;
2734 }
2735 
2736 static dbus_bool_t
2737 object_path_set_value (TestTypeNode *node,
2738  DBusTypeReader *reader,
2739  DBusTypeReader *realign_root,
2740  int seed)
2741 {
2742  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2743  const char *v_string = buf;
2744 
2745  object_path_from_seed (buf, seed);
2746 
2747  return _dbus_type_reader_set_basic (reader,
2748  &v_string,
2749  realign_root);
2750 }
2751 
2752 #define MAX_SAMPLE_SIGNATURE_LEN 10
2753 static void
2754 signature_from_seed (char *buf,
2755  int seed)
2756 {
2757  /* try to avoid ascending, descending, or alternating length to help find bugs */
2758  const char *sample_signatures[] = {
2759  "asax",
2760  "",
2761  "asau(xxxx)",
2762  "x",
2763  "ai",
2764  "a(ii)"
2765  };
2766 
2767  strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
2768 }
2769 
2770 static dbus_bool_t
2771 signature_write_value (TestTypeNode *node,
2772  DataBlock *block,
2773  DBusTypeWriter *writer,
2774  int seed)
2775 {
2776  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2777  const char *v_string = buf;
2778 
2779  signature_from_seed (buf, seed);
2780 
2781  return _dbus_type_writer_write_basic (writer,
2782  node->klass->typecode,
2783  &v_string);
2784 }
2785 
2786 static dbus_bool_t
2787 signature_read_value (TestTypeNode *node,
2788  DBusTypeReader *reader,
2789  int seed)
2790 {
2791  const char *v;
2792  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2793 
2794  check_expected_type (reader, node->klass->typecode);
2795 
2797  (const char **) &v);
2798 
2799  signature_from_seed (buf, seed);
2800 
2801  if (strcmp (buf, v) != 0)
2802  {
2803  _dbus_warn ("read signature value '%s' expected '%s'",
2804  v, buf);
2805  _dbus_assert_not_reached ("test failed");
2806  }
2807 
2808  return TRUE;
2809 }
2810 
2811 
2812 static dbus_bool_t
2813 signature_set_value (TestTypeNode *node,
2814  DBusTypeReader *reader,
2815  DBusTypeReader *realign_root,
2816  int seed)
2817 {
2818  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2819  const char *v_string = buf;
2820 
2821  signature_from_seed (buf, seed);
2822 
2823  return _dbus_type_reader_set_basic (reader,
2824  &v_string,
2825  realign_root);
2826 }
2827 
2828 static dbus_bool_t
2829 struct_write_value (TestTypeNode *node,
2830  DataBlock *block,
2831  DBusTypeWriter *writer,
2832  int seed)
2833 {
2834  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2835  DataBlockState saved;
2836  DBusTypeWriter sub;
2837  int i;
2838  int n_copies;
2839 
2840  n_copies = node->klass->subclass_detail;
2841 
2842  _dbus_assert (container->children != NULL);
2843 
2844  data_block_save (block, &saved);
2845 
2847  NULL, 0,
2848  &sub))
2849  return FALSE;
2850 
2851  i = 0;
2852  while (i < n_copies)
2853  {
2854  DBusList *link;
2855 
2856  link = _dbus_list_get_first_link (&container->children);
2857  while (link != NULL)
2858  {
2859  TestTypeNode *child = link->data;
2860  DBusList *next = _dbus_list_get_next_link (&container->children, link);
2861 
2862  if (!node_write_value (child, block, &sub, seed + i))
2863  {
2864  data_block_restore (block, &saved);
2865  return FALSE;
2866  }
2867 
2868  link = next;
2869  }
2870 
2871  ++i;
2872  }
2873 
2874  if (!_dbus_type_writer_unrecurse (writer, &sub))
2875  {
2876  data_block_restore (block, &saved);
2877  return FALSE;
2878  }
2879 
2880  return TRUE;
2881 }
2882 
2883 static dbus_bool_t
2884 struct_read_or_set_value (TestTypeNode *node,
2885  DBusTypeReader *reader,
2886  DBusTypeReader *realign_root,
2887  int seed)
2888 {
2889  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2890  DBusTypeReader sub;
2891  int i;
2892  int n_copies;
2893 
2894  n_copies = node->klass->subclass_detail;
2895 
2896  check_expected_type (reader, DBUS_TYPE_STRUCT);
2897 
2898  _dbus_type_reader_recurse (reader, &sub);
2899 
2900  i = 0;
2901  while (i < n_copies)
2902  {
2903  DBusList *link;
2904 
2905  link = _dbus_list_get_first_link (&container->children);
2906  while (link != NULL)
2907  {
2908  TestTypeNode *child = link->data;
2909  DBusList *next = _dbus_list_get_next_link (&container->children, link);
2910 
2911  if (realign_root == NULL)
2912  {
2913  if (!node_read_value (child, &sub, seed + i))
2914  return FALSE;
2915  }
2916  else
2917  {
2918  if (!node_set_value (child, &sub, realign_root, seed + i))
2919  return FALSE;
2920  }
2921 
2922  if (i == (n_copies - 1) && next == NULL)
2923  NEXT_EXPECTING_FALSE (&sub);
2924  else
2925  NEXT_EXPECTING_TRUE (&sub);
2926 
2927  link = next;
2928  }
2929 
2930  ++i;
2931  }
2932 
2933  return TRUE;
2934 }
2935 
2936 static dbus_bool_t
2937 struct_read_value (TestTypeNode *node,
2938  DBusTypeReader *reader,
2939  int seed)
2940 {
2941  return struct_read_or_set_value (node, reader, NULL, seed);
2942 }
2943 
2944 static dbus_bool_t
2945 struct_set_value (TestTypeNode *node,
2946  DBusTypeReader *reader,
2947  DBusTypeReader *realign_root,
2948  int seed)
2949 {
2950  return struct_read_or_set_value (node, reader, realign_root, seed);
2951 }
2952 
2953 static dbus_bool_t
2954 struct_build_signature (TestTypeNode *node,
2955  DBusString *str)
2956 {
2957  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2958  int i;
2959  int orig_len;
2960  int n_copies;
2961 
2962  n_copies = node->klass->subclass_detail;
2963 
2964  orig_len = _dbus_string_get_length (str);
2965 
2967  goto oom;
2968 
2969  i = 0;
2970  while (i < n_copies)
2971  {
2972  DBusList *link;
2973 
2974  link = _dbus_list_get_first_link (&container->children);
2975  while (link != NULL)
2976  {
2977  TestTypeNode *child = link->data;
2978  DBusList *next = _dbus_list_get_next_link (&container->children, link);
2979 
2980  if (!node_build_signature (child, str))
2981  goto oom;
2982 
2983  link = next;
2984  }
2985 
2986  ++i;
2987  }
2988 
2990  goto oom;
2991 
2992  return TRUE;
2993 
2994  oom:
2995  _dbus_string_set_length (str, orig_len);
2996  return FALSE;
2997 }
2998 
2999 static dbus_bool_t
3000 array_write_value (TestTypeNode *node,
3001  DataBlock *block,
3002  DBusTypeWriter *writer,
3003  int seed)
3004 {
3005  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3006  DataBlockState saved;
3007  DBusTypeWriter sub;
3008  DBusString element_signature;
3009  int i;
3010  int n_copies;
3011  int element_type;
3012  TestTypeNode *child;
3013 
3014  n_copies = node->klass->subclass_detail;
3015 
3016  _dbus_assert (container->children != NULL);
3017 
3018  data_block_save (block, &saved);
3019 
3020  if (!_dbus_string_init (&element_signature))
3021  return FALSE;
3022 
3023  child = _dbus_list_get_first (&container->children);
3024 
3025  if (!node_build_signature (child,
3026  &element_signature))
3027  goto oom;
3028 
3029  element_type = _dbus_first_type_in_signature (&element_signature, 0);
3030 
3032  &element_signature, 0,
3033  &sub))
3034  goto oom;
3035 
3036  if (arrays_write_fixed_in_blocks &&
3037  dbus_type_is_fixed (element_type) &&
3038  child->klass->write_multi)
3039  {
3040  if (!node_write_multi (child, block, &sub, seed, n_copies))
3041  goto oom;
3042  }
3043  else
3044  {
3045  i = 0;
3046  while (i < n_copies)
3047  {
3048  DBusList *link;
3049 
3050  link = _dbus_list_get_first_link (&container->children);
3051  while (link != NULL)
3052  {
3053  TestTypeNode *child2 = link->data;
3054  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3055 
3056  if (!node_write_value (child2, block, &sub, seed + i))
3057  goto oom;
3058 
3059  link = next;
3060  }
3061 
3062  ++i;
3063  }
3064  }
3065 
3066  if (!_dbus_type_writer_unrecurse (writer, &sub))
3067  goto oom;
3068 
3069  _dbus_string_free (&element_signature);
3070  return TRUE;
3071 
3072  oom:
3073  data_block_restore (block, &saved);
3074  _dbus_string_free (&element_signature);
3075  return FALSE;
3076 }
3077 
3078 static dbus_bool_t
3079 array_read_or_set_value (TestTypeNode *node,
3080  DBusTypeReader *reader,
3081  DBusTypeReader *realign_root,
3082  int seed)
3083 {
3084  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3085  DBusTypeReader sub;
3086  int i;
3087  int n_copies;
3088  TestTypeNode *child;
3089 
3090  n_copies = node->klass->subclass_detail;
3091 
3092  check_expected_type (reader, DBUS_TYPE_ARRAY);
3093 
3094  child = _dbus_list_get_first (&container->children);
3095 
3096  if (n_copies > 0)
3097  {
3098  _dbus_type_reader_recurse (reader, &sub);
3099 
3100  if (realign_root == NULL && arrays_write_fixed_in_blocks &&
3102  child->klass->read_multi)
3103  {
3104  if (!node_read_multi (child, &sub, seed, n_copies))
3105  return FALSE;
3106  }
3107  else
3108  {
3109  i = 0;
3110  while (i < n_copies)
3111  {
3112  DBusList *link;
3113 
3114  link = _dbus_list_get_first_link (&container->children);
3115  while (link != NULL)
3116  {
3117  TestTypeNode *child2 = link->data;
3118  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3119 
3120  _dbus_assert (child2->klass->typecode ==
3122 
3123  if (realign_root == NULL)
3124  {
3125  if (!node_read_value (child2, &sub, seed + i))
3126  return FALSE;
3127  }
3128  else
3129  {
3130  if (!node_set_value (child2, &sub, realign_root, seed + i))
3131  return FALSE;
3132  }
3133 
3134  if (i == (n_copies - 1) && next == NULL)
3135  NEXT_EXPECTING_FALSE (&sub);
3136  else
3137  NEXT_EXPECTING_TRUE (&sub);
3138 
3139  link = next;
3140  }
3141 
3142  ++i;
3143  }
3144  }
3145  }
3146 
3147  return TRUE;
3148 }
3149 
3150 static dbus_bool_t
3151 array_read_value (TestTypeNode *node,
3152  DBusTypeReader *reader,
3153  int seed)
3154 {
3155  return array_read_or_set_value (node, reader, NULL, seed);
3156 }
3157 
3158 static dbus_bool_t
3159 array_set_value (TestTypeNode *node,
3160  DBusTypeReader *reader,
3161  DBusTypeReader *realign_root,
3162  int seed)
3163 {
3164  return array_read_or_set_value (node, reader, realign_root, seed);
3165 }
3166 
3167 static dbus_bool_t
3168 array_build_signature (TestTypeNode *node,
3169  DBusString *str)
3170 {
3171  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3172  int orig_len;
3173 
3174  orig_len = _dbus_string_get_length (str);
3175 
3177  goto oom;
3178 
3179  if (!node_build_signature (_dbus_list_get_first (&container->children),
3180  str))
3181  goto oom;
3182 
3183  return TRUE;
3184 
3185  oom:
3186  _dbus_string_set_length (str, orig_len);
3187  return FALSE;
3188 }
3189 
3190  /* 10 is random just to add another seed that we use in the suite */
3191 #define VARIANT_SEED 10
3192 
3193 static dbus_bool_t
3194 variant_write_value (TestTypeNode *node,
3195  DataBlock *block,
3196  DBusTypeWriter *writer,
3197  int seed)
3198 {
3199  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3200  DataBlockState saved;
3201  DBusTypeWriter sub;
3202  DBusString content_signature;
3203  TestTypeNode *child;
3204 
3205  _dbus_assert (container->children != NULL);
3206  _dbus_assert (_dbus_list_length_is_one (&container->children));
3207 
3208  child = _dbus_list_get_first (&container->children);
3209 
3210  data_block_save (block, &saved);
3211 
3212  if (!_dbus_string_init (&content_signature))
3213  return FALSE;
3214 
3215  if (!node_build_signature (child,
3216  &content_signature))
3217  goto oom;
3218 
3220  &content_signature, 0,
3221  &sub))
3222  goto oom;
3223 
3224  if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
3225  goto oom;
3226 
3227  if (!_dbus_type_writer_unrecurse (writer, &sub))
3228  goto oom;
3229 
3230  _dbus_string_free (&content_signature);
3231  return TRUE;
3232 
3233  oom:
3234  data_block_restore (block, &saved);
3235  _dbus_string_free (&content_signature);
3236  return FALSE;
3237 }
3238 
3239 static dbus_bool_t
3240 variant_read_or_set_value (TestTypeNode *node,
3241  DBusTypeReader *reader,
3242  DBusTypeReader *realign_root,
3243  int seed)
3244 {
3245  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3246  DBusTypeReader sub;
3247  TestTypeNode *child;
3248 
3249  _dbus_assert (container->children != NULL);
3250  _dbus_assert (_dbus_list_length_is_one (&container->children));
3251 
3252  child = _dbus_list_get_first (&container->children);
3253 
3254  check_expected_type (reader, DBUS_TYPE_VARIANT);
3255 
3256  _dbus_type_reader_recurse (reader, &sub);
3257 
3258  if (realign_root == NULL)
3259  {
3260  if (!node_read_value (child, &sub, seed + VARIANT_SEED))
3261  return FALSE;
3262  }
3263  else
3264  {
3265  if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
3266  return FALSE;
3267  }
3268 
3269  NEXT_EXPECTING_FALSE (&sub);
3270 
3271  return TRUE;
3272 }
3273 
3274 static dbus_bool_t
3275 variant_read_value (TestTypeNode *node,
3276  DBusTypeReader *reader,
3277  int seed)
3278 {
3279  return variant_read_or_set_value (node, reader, NULL, seed);
3280 }
3281 
3282 static dbus_bool_t
3283 variant_set_value (TestTypeNode *node,
3284  DBusTypeReader *reader,
3285  DBusTypeReader *realign_root,
3286  int seed)
3287 {
3288  return variant_read_or_set_value (node, reader, realign_root, seed);
3289 }
3290 
3291 static dbus_bool_t
3292 dict_write_value (TestTypeNode *node,
3293  DataBlock *block,
3294  DBusTypeWriter *writer,
3295  int seed)
3296 {
3297  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3298  DataBlockState saved;
3299  DBusTypeWriter sub;
3300  DBusString entry_value_signature;
3301  DBusString dict_entry_signature;
3302  int i;
3303  int n_entries;
3304  TestTypeNode *child;
3305 
3306  n_entries = node->klass->subclass_detail;
3307 
3308  _dbus_assert (container->children != NULL);
3309 
3310  data_block_save (block, &saved);
3311 
3312  if (!_dbus_string_init (&entry_value_signature))
3313  return FALSE;
3314 
3315  if (!_dbus_string_init (&dict_entry_signature))
3316  {
3317  _dbus_string_free (&entry_value_signature);
3318  return FALSE;
3319  }
3320 
3321  child = _dbus_list_get_first (&container->children);
3322 
3323  if (!node_build_signature (child,
3324  &entry_value_signature))
3325  goto oom;
3326 
3327  if (!_dbus_string_append (&dict_entry_signature,
3330  goto oom;
3331 
3332  if (!_dbus_string_copy (&entry_value_signature, 0,
3333  &dict_entry_signature,
3334  _dbus_string_get_length (&dict_entry_signature)))
3335  goto oom;
3336 
3337  if (!_dbus_string_append_byte (&dict_entry_signature,
3339  goto oom;
3340 
3342  &dict_entry_signature, 0,
3343  &sub))
3344  goto oom;
3345 
3346  i = 0;
3347  while (i < n_entries)
3348  {
3349  DBusTypeWriter entry_sub;
3350  dbus_int32_t key;
3351 
3353  NULL, 0,
3354  &entry_sub))
3355  goto oom;
3356 
3357  key = int32_from_seed (seed + i);
3358 
3359  if (!_dbus_type_writer_write_basic (&entry_sub,
3361  &key))
3362  goto oom;
3363 
3364  if (!node_write_value (child, block, &entry_sub, seed + i))
3365  goto oom;
3366 
3367  if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
3368  goto oom;
3369 
3370  ++i;
3371  }
3372 
3373  if (!_dbus_type_writer_unrecurse (writer, &sub))
3374  goto oom;
3375 
3376  _dbus_string_free (&entry_value_signature);
3377  _dbus_string_free (&dict_entry_signature);
3378  return TRUE;
3379 
3380  oom:
3381  data_block_restore (block, &saved);
3382  _dbus_string_free (&entry_value_signature);
3383  _dbus_string_free (&dict_entry_signature);
3384  return FALSE;
3385 }
3386 
3387 static dbus_bool_t
3388 dict_read_or_set_value (TestTypeNode *node,
3389  DBusTypeReader *reader,
3390  DBusTypeReader *realign_root,
3391  int seed)
3392 {
3393  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3394  DBusTypeReader sub;
3395  int i;
3396  int n_entries;
3397  TestTypeNode *child;
3398 
3399  n_entries = node->klass->subclass_detail;
3400 
3401  check_expected_type (reader, DBUS_TYPE_ARRAY);
3402 
3403  child = _dbus_list_get_first (&container->children);
3404 
3405  if (n_entries > 0)
3406  {
3407  _dbus_type_reader_recurse (reader, &sub);
3408 
3409  check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3410 
3411  i = 0;
3412  while (i < n_entries)
3413  {
3414  DBusTypeReader entry_sub;
3415 
3416  check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3417 
3418  _dbus_type_reader_recurse (&sub, &entry_sub);
3419 
3420  if (realign_root == NULL)
3421  {
3422  dbus_int32_t v;
3423 
3424  check_expected_type (&entry_sub, DBUS_TYPE_INT32);
3425 
3426  _dbus_type_reader_read_basic (&entry_sub,
3427  (dbus_int32_t*) &v);
3428 
3429  _dbus_assert (v == int32_from_seed (seed + i));
3430 
3431  NEXT_EXPECTING_TRUE (&entry_sub);
3432 
3433  if (!node_read_value (child, &entry_sub, seed + i))
3434  return FALSE;
3435 
3436  NEXT_EXPECTING_FALSE (&entry_sub);
3437  }
3438  else
3439  {
3440  dbus_int32_t v;
3441 
3442  v = int32_from_seed (seed + i);
3443 
3444  if (!_dbus_type_reader_set_basic (&entry_sub,
3445  &v,
3446  realign_root))
3447  return FALSE;
3448 
3449  NEXT_EXPECTING_TRUE (&entry_sub);
3450 
3451  if (!node_set_value (child, &entry_sub, realign_root, seed + i))
3452  return FALSE;
3453 
3454  NEXT_EXPECTING_FALSE (&entry_sub);
3455  }
3456 
3457  if (i == (n_entries - 1))
3458  NEXT_EXPECTING_FALSE (&sub);
3459  else
3460  NEXT_EXPECTING_TRUE (&sub);
3461 
3462  ++i;
3463  }
3464  }
3465 
3466  return TRUE;
3467 }
3468 
3469 static dbus_bool_t
3470 dict_read_value (TestTypeNode *node,
3471  DBusTypeReader *reader,
3472  int seed)
3473 {
3474  return dict_read_or_set_value (node, reader, NULL, seed);
3475 }
3476 
3477 static dbus_bool_t
3478 dict_set_value (TestTypeNode *node,
3479  DBusTypeReader *reader,
3480  DBusTypeReader *realign_root,
3481  int seed)
3482 {
3483  return dict_read_or_set_value (node, reader, realign_root, seed);
3484 }
3485 
3486 static dbus_bool_t
3487 dict_build_signature (TestTypeNode *node,
3488  DBusString *str)
3489 {
3490  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3491  int orig_len;
3492 
3493  orig_len = _dbus_string_get_length (str);
3494 
3496  goto oom;
3497 
3499  goto oom;
3500 
3501  if (!node_build_signature (_dbus_list_get_first (&container->children),
3502  str))
3503  goto oom;
3504 
3506  goto oom;
3507 
3508  return TRUE;
3509 
3510  oom:
3511  _dbus_string_set_length (str, orig_len);
3512  return FALSE;
3513 }
3514 
3515 static void
3516 container_destroy (TestTypeNode *node)
3517 {
3518  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3519  DBusList *link;
3520 
3521  link = _dbus_list_get_first_link (&container->children);
3522  while (link != NULL)
3523  {
3524  TestTypeNode *child = link->data;
3525  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3526 
3527  node_destroy (child);
3528 
3529  _dbus_list_free_link (link);
3530 
3531  link = next;
3532  }
3533 }
3534 
3535 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
3536 
3537 #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:702
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().
_DBUS_GNUC_EXTENSION typedef unsigned long dbus_uint64_t
A 64-bit unsigned integer.
#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".
_DBUS_GNUC_EXTENSION typedef long dbus_int64_t
A 64-bit signed integer.
#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
short dbus_int16_t
A 16-bit signed integer on all platforms.
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
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:532
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.
int dbus_int32_t
A 32-bit signed integer on all platforms.
#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:597
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