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