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