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