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