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