2005-01-17 03:53:40 +00:00
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-marshal-recursive-util.c Would be in dbus-marshal-recursive.c, but only used in bus/tests
*
* Copyright ( C ) 2004 , 2005 Red Hat , Inc .
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
2005-01-27 23:39:26 +00:00
# include <config.h>
# ifdef DBUS_BUILD_TESTS
2005-01-17 03:53:40 +00:00
# include "dbus-marshal-recursive.h"
# include "dbus-marshal-basic.h"
2005-02-24 16:03:56 +00:00
# include "dbus-signature.h"
2005-01-17 03:53:40 +00:00
# include "dbus-internals.h"
2005-01-27 23:39:26 +00:00
# include <string.h>
2005-01-17 03:53:40 +00:00
2005-01-27 23:39:26 +00:00
static void
basic_value_zero ( DBusBasicValue * value )
{
# ifdef DBUS_HAVE_INT64
value - > u64 = 0 ;
# else
value - > u64 . first32 = 0 ;
value - > u64 . second32 = 0 ;
# endif
}
static dbus_bool_t
basic_value_equal ( int type ,
DBusBasicValue * lhs ,
DBusBasicValue * rhs )
{
if ( type = = DBUS_TYPE_STRING | |
type = = DBUS_TYPE_SIGNATURE | |
type = = DBUS_TYPE_OBJECT_PATH )
{
return strcmp ( lhs - > str , rhs - > str ) = = 0 ;
}
else
{
# ifdef DBUS_HAVE_INT64
return lhs - > u64 = = rhs - > u64 ;
# else
return lhs - > u64 . first32 = = rhs - > u64 . first32 & &
lhs - > u64 . second32 = = rhs - > u64 . second32 ;
# endif
}
}
static dbus_bool_t
equal_values_helper ( DBusTypeReader * lhs ,
DBusTypeReader * rhs )
{
int lhs_type ;
int rhs_type ;
lhs_type = _dbus_type_reader_get_current_type ( lhs ) ;
rhs_type = _dbus_type_reader_get_current_type ( rhs ) ;
if ( lhs_type ! = rhs_type )
return FALSE ;
if ( lhs_type = = DBUS_TYPE_INVALID )
return TRUE ;
2005-02-24 16:03:56 +00:00
if ( dbus_type_is_basic ( lhs_type ) )
2005-01-27 23:39:26 +00:00
{
DBusBasicValue lhs_value ;
DBusBasicValue rhs_value ;
basic_value_zero ( & lhs_value ) ;
basic_value_zero ( & rhs_value ) ;
_dbus_type_reader_read_basic ( lhs , & lhs_value ) ;
_dbus_type_reader_read_basic ( rhs , & rhs_value ) ;
return basic_value_equal ( lhs_type , & lhs_value , & rhs_value ) ;
}
else
{
DBusTypeReader lhs_sub ;
DBusTypeReader rhs_sub ;
_dbus_type_reader_recurse ( lhs , & lhs_sub ) ;
_dbus_type_reader_recurse ( rhs , & rhs_sub ) ;
return equal_values_helper ( & lhs_sub , & rhs_sub ) ;
}
}
/**
* See whether the two readers point to identical data blocks .
*
* @ param lhs reader 1
* @ param rhs reader 2
* @ returns # TRUE if the data blocks have the same values
*/
dbus_bool_t
_dbus_type_reader_equal_values ( const DBusTypeReader * lhs ,
const DBusTypeReader * rhs )
{
DBusTypeReader copy_lhs = * lhs ;
DBusTypeReader copy_rhs = * rhs ;
return equal_values_helper ( & copy_lhs , & copy_rhs ) ;
}
/* TESTS */
2005-01-17 03:53:40 +00:00
# include "dbus-test.h"
# include "dbus-list.h"
# include <stdio.h>
# include <stdlib.h>
/* Whether to do the OOM stuff (only with other expensive tests) */
# define TEST_OOM_HANDLING 0
/* We do start offset 0 through 9, to get various alignment cases. Still this
* obviously makes the test suite run 10 x as slow .
*/
# define MAX_INITIAL_OFFSET 9
/* Largest iteration count to test copying, realignment,
* etc . with . i . e . we only test this stuff with some of the smaller
* data sets .
*/
# define MAX_ITERATIONS_FOR_EXPENSIVE_TESTS 1000
typedef struct
{
int byte_order ;
int initial_offset ;
DBusString signature ;
DBusString body ;
} DataBlock ;
typedef struct
{
int saved_sig_len ;
int saved_body_len ;
} DataBlockState ;
# define N_FENCE_BYTES 5
# define FENCE_BYTES_STR "abcde"
# define INITIAL_PADDING_BYTE '\0'
static dbus_bool_t
data_block_init ( DataBlock * block ,
int byte_order ,
int initial_offset )
{
if ( ! _dbus_string_init ( & block - > signature ) )
return FALSE ;
if ( ! _dbus_string_init ( & block - > body ) )
{
_dbus_string_free ( & block - > signature ) ;
return FALSE ;
}
if ( ! _dbus_string_insert_bytes ( & block - > signature , 0 , initial_offset ,
INITIAL_PADDING_BYTE ) | |
! _dbus_string_insert_bytes ( & block - > body , 0 , initial_offset ,
INITIAL_PADDING_BYTE ) | |
! _dbus_string_append ( & block - > signature , FENCE_BYTES_STR ) | |
! _dbus_string_append ( & block - > body , FENCE_BYTES_STR ) )
{
_dbus_string_free ( & block - > signature ) ;
_dbus_string_free ( & block - > body ) ;
return FALSE ;
}
block - > byte_order = byte_order ;
block - > initial_offset = initial_offset ;
return TRUE ;
}
static void
data_block_save ( DataBlock * block ,
DataBlockState * state )
{
state - > saved_sig_len = _dbus_string_get_length ( & block - > signature ) - N_FENCE_BYTES ;
state - > saved_body_len = _dbus_string_get_length ( & block - > body ) - N_FENCE_BYTES ;
}
static void
data_block_restore ( DataBlock * block ,
DataBlockState * state )
{
_dbus_string_delete ( & block - > signature ,
state - > saved_sig_len ,
_dbus_string_get_length ( & block - > signature ) - state - > saved_sig_len - N_FENCE_BYTES ) ;
_dbus_string_delete ( & block - > body ,
state - > saved_body_len ,
_dbus_string_get_length ( & block - > body ) - state - > saved_body_len - N_FENCE_BYTES ) ;
}
static void
data_block_verify ( DataBlock * block )
{
if ( ! _dbus_string_ends_with_c_str ( & block - > signature ,
FENCE_BYTES_STR ) )
{
int offset ;
offset = _dbus_string_get_length ( & block - > signature ) - N_FENCE_BYTES - 8 ;
if ( offset < 0 )
offset = 0 ;
_dbus_verbose_bytes_of_string ( & block - > signature ,
offset ,
_dbus_string_get_length ( & block - > signature ) - offset ) ;
_dbus_assert_not_reached ( " block did not verify: bad bytes at end of signature " ) ;
}
if ( ! _dbus_string_ends_with_c_str ( & block - > body ,
FENCE_BYTES_STR ) )
{
int offset ;
offset = _dbus_string_get_length ( & block - > body ) - N_FENCE_BYTES - 8 ;
if ( offset < 0 )
offset = 0 ;
_dbus_verbose_bytes_of_string ( & block - > body ,
offset ,
_dbus_string_get_length ( & block - > body ) - offset ) ;
_dbus_assert_not_reached ( " block did not verify: bad bytes at end of body " ) ;
}
_dbus_assert ( _dbus_string_validate_nul ( & block - > signature ,
0 , block - > initial_offset ) ) ;
_dbus_assert ( _dbus_string_validate_nul ( & block - > body ,
0 , block - > initial_offset ) ) ;
}
static void
data_block_free ( DataBlock * block )
{
data_block_verify ( block ) ;
_dbus_string_free ( & block - > signature ) ;
_dbus_string_free ( & block - > body ) ;
}
static void
data_block_reset ( DataBlock * block )
{
data_block_verify ( block ) ;
_dbus_string_delete ( & block - > signature ,
block - > initial_offset ,
_dbus_string_get_length ( & block - > signature ) - N_FENCE_BYTES - block - > initial_offset ) ;
_dbus_string_delete ( & block - > body ,
block - > initial_offset ,
_dbus_string_get_length ( & block - > body ) - N_FENCE_BYTES - block - > initial_offset ) ;
data_block_verify ( block ) ;
}
static void
data_block_init_reader_writer ( DataBlock * block ,
DBusTypeReader * reader ,
DBusTypeWriter * writer )
{
if ( reader )
_dbus_type_reader_init ( reader ,
block - > byte_order ,
& block - > signature ,
block - > initial_offset ,
& block - > body ,
block - > initial_offset ) ;
if ( writer )
_dbus_type_writer_init ( writer ,
block - > byte_order ,
& block - > signature ,
_dbus_string_get_length ( & block - > signature ) - N_FENCE_BYTES ,
& block - > body ,
_dbus_string_get_length ( & block - > body ) - N_FENCE_BYTES ) ;
}
static void
real_check_expected_type ( DBusTypeReader * reader ,
int expected ,
const char * funcname ,
int line )
{
int t ;
t = _dbus_type_reader_get_current_type ( reader ) ;
if ( t ! = expected )
{
_dbus_warn ( " Read type %s while expecting %s at %s line %d \n " ,
_dbus_type_to_string ( t ) ,
_dbus_type_to_string ( expected ) ,
funcname , line ) ;
_dbus_assert_not_reached ( " read wrong type " ) ;
}
}
# define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
# define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
{ \
_dbus_warn ( " _dbus_type_reader_next() should have returned TRUE at %s %d \n " , \
_DBUS_FUNCTION_NAME , __LINE__ ) ; \
_dbus_assert_not_reached ( " test failed " ) ; \
} \
} while ( 0 )
# define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
{ \
_dbus_warn ( " _dbus_type_reader_next() should have returned FALSE at %s %d \n " , \
_DBUS_FUNCTION_NAME , __LINE__ ) ; \
_dbus_assert_not_reached ( " test failed " ) ; \
} \
check_expected_type ( reader , DBUS_TYPE_INVALID ) ; \
} while ( 0 )
typedef struct TestTypeNode TestTypeNode ;
typedef struct TestTypeNodeClass TestTypeNodeClass ;
typedef struct TestTypeNodeContainer TestTypeNodeContainer ;
typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass ;
struct TestTypeNode
{
const TestTypeNodeClass * klass ;
} ;
struct TestTypeNodeContainer
{
TestTypeNode base ;
DBusList * children ;
} ;
struct TestTypeNodeClass
{
int typecode ;
int instance_size ;
int subclass_detail ; /* a bad hack to avoid a bunch of subclass casting */
dbus_bool_t ( * construct ) ( TestTypeNode * node ) ;
void ( * destroy ) ( TestTypeNode * node ) ;
dbus_bool_t ( * write_value ) ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
dbus_bool_t ( * read_value ) ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
dbus_bool_t ( * set_value ) ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
dbus_bool_t ( * build_signature ) ( TestTypeNode * node ,
DBusString * str ) ;
dbus_bool_t ( * write_multi ) ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ,
int count ) ;
dbus_bool_t ( * read_multi ) ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ,
int count ) ;
} ;
struct TestTypeNodeContainerClass
{
TestTypeNodeClass base ;
} ;
/* FIXME this could be chilled out substantially by unifying
* the basic types into basic_write_value / basic_read_value
* and by merging read_value and set_value into one function
* taking a flag argument .
*/
2005-01-28 03:06:56 +00:00
static dbus_bool_t int16_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t int16_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t int16_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t int16_write_multi ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ,
int count ) ;
static dbus_bool_t int16_read_multi ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ,
int count ) ;
2005-01-17 03:53:40 +00:00
static dbus_bool_t int32_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t int32_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t int32_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t int32_write_multi ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ,
int count ) ;
static dbus_bool_t int32_read_multi ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ,
int count ) ;
static dbus_bool_t int64_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t int64_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t int64_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t string_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t string_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t string_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t bool_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t bool_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t bool_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t byte_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t byte_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t byte_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t double_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t double_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t double_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t object_path_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t object_path_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t object_path_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t signature_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t signature_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t signature_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t struct_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t struct_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t struct_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t struct_build_signature ( TestTypeNode * node ,
DBusString * str ) ;
2005-01-28 05:30:53 +00:00
static dbus_bool_t dict_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t dict_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t dict_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t dict_build_signature ( TestTypeNode * node ,
DBusString * str ) ;
2005-01-17 03:53:40 +00:00
static dbus_bool_t array_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t array_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t array_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static dbus_bool_t array_build_signature ( TestTypeNode * node ,
DBusString * str ) ;
static dbus_bool_t variant_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ) ;
static dbus_bool_t variant_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ) ;
static dbus_bool_t variant_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed ) ;
static void container_destroy ( TestTypeNode * node ) ;
2005-01-28 05:30:53 +00:00
2005-01-28 03:06:56 +00:00
static const TestTypeNodeClass int16_class = {
DBUS_TYPE_INT16 ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
int16_write_value ,
int16_read_value ,
int16_set_value ,
NULL ,
int16_write_multi ,
int16_read_multi
} ;
static const TestTypeNodeClass uint16_class = {
DBUS_TYPE_UINT16 ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
int16_write_value , /* recycle from int16 */
int16_read_value , /* recycle from int16 */
int16_set_value , /* recycle from int16 */
NULL ,
int16_write_multi , /* recycle from int16 */
int16_read_multi /* recycle from int16 */
} ;
2005-01-17 03:53:40 +00:00
static const TestTypeNodeClass int32_class = {
DBUS_TYPE_INT32 ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
int32_write_value ,
int32_read_value ,
int32_set_value ,
NULL ,
int32_write_multi ,
int32_read_multi
} ;
static const TestTypeNodeClass uint32_class = {
DBUS_TYPE_UINT32 ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
int32_write_value , /* recycle from int32 */
int32_read_value , /* recycle from int32 */
int32_set_value , /* recycle from int32 */
NULL ,
int32_write_multi , /* recycle from int32 */
int32_read_multi /* recycle from int32 */
} ;
static const TestTypeNodeClass int64_class = {
DBUS_TYPE_INT64 ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
int64_write_value ,
int64_read_value ,
int64_set_value ,
NULL ,
NULL , /* FIXME */
NULL /* FIXME */
} ;
static const TestTypeNodeClass uint64_class = {
DBUS_TYPE_UINT64 ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
int64_write_value , /* recycle from int64 */
int64_read_value , /* recycle from int64 */
int64_set_value , /* recycle from int64 */
NULL ,
NULL , /* FIXME */
NULL /* FIXME */
} ;
static const TestTypeNodeClass string_0_class = {
DBUS_TYPE_STRING ,
sizeof ( TestTypeNode ) ,
0 , /* string length */
NULL ,
NULL ,
string_write_value ,
string_read_value ,
string_set_value ,
NULL ,
NULL ,
NULL
} ;
static const TestTypeNodeClass string_1_class = {
DBUS_TYPE_STRING ,
sizeof ( TestTypeNode ) ,
1 , /* string length */
NULL ,
NULL ,
string_write_value ,
string_read_value ,
string_set_value ,
NULL ,
NULL ,
NULL
} ;
/* with nul, a len 3 string should fill 4 bytes and thus is "special" */
static const TestTypeNodeClass string_3_class = {
DBUS_TYPE_STRING ,
sizeof ( TestTypeNode ) ,
3 , /* string length */
NULL ,
NULL ,
string_write_value ,
string_read_value ,
string_set_value ,
NULL ,
NULL ,
NULL
} ;
/* with nul, a len 8 string should fill 9 bytes and thus is "special" (far-fetched I suppose) */
static const TestTypeNodeClass string_8_class = {
DBUS_TYPE_STRING ,
sizeof ( TestTypeNode ) ,
8 , /* string length */
NULL ,
NULL ,
string_write_value ,
string_read_value ,
string_set_value ,
NULL ,
NULL ,
NULL
} ;
static const TestTypeNodeClass bool_class = {
DBUS_TYPE_BOOLEAN ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
bool_write_value ,
bool_read_value ,
bool_set_value ,
NULL ,
NULL , /* FIXME */
NULL /* FIXME */
} ;
static const TestTypeNodeClass byte_class = {
DBUS_TYPE_BYTE ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
byte_write_value ,
byte_read_value ,
byte_set_value ,
NULL ,
NULL , /* FIXME */
NULL /* FIXME */
} ;
static const TestTypeNodeClass double_class = {
DBUS_TYPE_DOUBLE ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
double_write_value ,
double_read_value ,
double_set_value ,
NULL ,
NULL , /* FIXME */
NULL /* FIXME */
} ;
static const TestTypeNodeClass object_path_class = {
DBUS_TYPE_OBJECT_PATH ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
object_path_write_value ,
object_path_read_value ,
object_path_set_value ,
NULL ,
NULL ,
NULL
} ;
static const TestTypeNodeClass signature_class = {
DBUS_TYPE_SIGNATURE ,
sizeof ( TestTypeNode ) ,
0 ,
NULL ,
NULL ,
signature_write_value ,
signature_read_value ,
signature_set_value ,
NULL ,
NULL ,
NULL
} ;
static const TestTypeNodeClass struct_1_class = {
DBUS_TYPE_STRUCT ,
sizeof ( TestTypeNodeContainer ) ,
1 , /* number of times children appear as fields */
NULL ,
container_destroy ,
struct_write_value ,
struct_read_value ,
struct_set_value ,
struct_build_signature ,
NULL ,
NULL
} ;
static const TestTypeNodeClass struct_2_class = {
DBUS_TYPE_STRUCT ,
sizeof ( TestTypeNodeContainer ) ,
2 , /* number of times children appear as fields */
NULL ,
container_destroy ,
struct_write_value ,
struct_read_value ,
struct_set_value ,
struct_build_signature ,
NULL ,
NULL
} ;
2005-01-28 05:30:53 +00:00
static const TestTypeNodeClass dict_1_class = {
DBUS_TYPE_ARRAY , /* this is correct, a dict is an array of dict entry */
sizeof ( TestTypeNodeContainer ) ,
1 , /* number of entries */
NULL ,
container_destroy ,
dict_write_value ,
dict_read_value ,
dict_set_value ,
dict_build_signature ,
NULL ,
NULL
} ;
2005-01-17 03:53:40 +00:00
static dbus_bool_t arrays_write_fixed_in_blocks = FALSE ;
static const TestTypeNodeClass array_0_class = {
DBUS_TYPE_ARRAY ,
sizeof ( TestTypeNodeContainer ) ,
0 , /* number of array elements */
NULL ,
container_destroy ,
array_write_value ,
array_read_value ,
array_set_value ,
array_build_signature ,
NULL ,
NULL
} ;
static const TestTypeNodeClass array_1_class = {
DBUS_TYPE_ARRAY ,
sizeof ( TestTypeNodeContainer ) ,
1 , /* number of array elements */
NULL ,
container_destroy ,
array_write_value ,
array_read_value ,
array_set_value ,
array_build_signature ,
NULL ,
NULL
} ;
static const TestTypeNodeClass array_2_class = {
DBUS_TYPE_ARRAY ,
sizeof ( TestTypeNodeContainer ) ,
2 , /* number of array elements */
NULL ,
container_destroy ,
array_write_value ,
array_read_value ,
array_set_value ,
array_build_signature ,
NULL ,
NULL
} ;
static const TestTypeNodeClass array_9_class = {
DBUS_TYPE_ARRAY ,
sizeof ( TestTypeNodeContainer ) ,
9 , /* number of array elements */
NULL ,
container_destroy ,
array_write_value ,
array_read_value ,
array_set_value ,
array_build_signature ,
NULL ,
NULL
} ;
static const TestTypeNodeClass variant_class = {
DBUS_TYPE_VARIANT ,
sizeof ( TestTypeNodeContainer ) ,
0 ,
NULL ,
container_destroy ,
variant_write_value ,
variant_read_value ,
variant_set_value ,
NULL ,
NULL ,
NULL
} ;
static const TestTypeNodeClass * const
basic_nodes [ ] = {
2005-01-28 03:06:56 +00:00
& int16_class ,
& uint16_class ,
2005-01-17 03:53:40 +00:00
& int32_class ,
& uint32_class ,
& int64_class ,
& uint64_class ,
& bool_class ,
& byte_class ,
& double_class ,
& string_0_class ,
& string_1_class ,
& string_3_class ,
& string_8_class ,
& object_path_class ,
& signature_class
} ;
# define N_BASICS (_DBUS_N_ELEMENTS (basic_nodes))
static const TestTypeNodeClass * const
container_nodes [ ] = {
& struct_1_class ,
& array_1_class ,
& struct_2_class ,
& array_0_class ,
& array_2_class ,
2005-01-28 05:30:53 +00:00
& variant_class ,
& dict_1_class /* last since we want struct and array before it */
2005-01-17 03:53:40 +00:00
/* array_9_class is omitted on purpose, it's too slow;
* we only use it in one hardcoded test below
*/
} ;
# define N_CONTAINERS (_DBUS_N_ELEMENTS (container_nodes))
static TestTypeNode *
node_new ( const TestTypeNodeClass * klass )
{
TestTypeNode * node ;
node = dbus_malloc0 ( klass - > instance_size ) ;
if ( node = = NULL )
return NULL ;
node - > klass = klass ;
if ( klass - > construct )
{
if ( ! ( * klass - > construct ) ( node ) )
{
dbus_free ( node ) ;
return FALSE ;
}
}
return node ;
}
static void
node_destroy ( TestTypeNode * node )
{
if ( node - > klass - > destroy )
( * node - > klass - > destroy ) ( node ) ;
dbus_free ( node ) ;
}
static dbus_bool_t
node_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
dbus_bool_t retval ;
retval = ( * node - > klass - > write_value ) ( node , block , writer , seed ) ;
#if 0
/* Handy to see where things break, but too expensive to do all the time */
data_block_verify ( block ) ;
# endif
return retval ;
}
static dbus_bool_t
node_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
DBusTypeMark mark ;
DBusTypeReader restored ;
_dbus_type_reader_save_mark ( reader , & mark ) ;
if ( ! ( * node - > klass - > read_value ) ( node , reader , seed ) )
return FALSE ;
_dbus_type_reader_init_from_mark ( & restored ,
reader - > byte_order ,
reader - > type_str ,
reader - > value_str ,
& mark ) ;
if ( ! ( * node - > klass - > read_value ) ( node , & restored , seed ) )
return FALSE ;
return TRUE ;
}
/* Warning: if this one fails due to OOM, it has side effects (can
* modify only some of the sub - values ) . OK in a test suite , but we
* never do this in real code .
*/
static dbus_bool_t
node_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
if ( ! ( * node - > klass - > set_value ) ( node , reader , realign_root , seed ) )
return FALSE ;
return TRUE ;
}
static dbus_bool_t
node_build_signature ( TestTypeNode * node ,
DBusString * str )
{
if ( node - > klass - > build_signature )
return ( * node - > klass - > build_signature ) ( node , str ) ;
else
return _dbus_string_append_byte ( str , node - > klass - > typecode ) ;
}
static dbus_bool_t
node_append_child ( TestTypeNode * node ,
TestTypeNode * child )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
_dbus_assert ( node - > klass - > instance_size > = ( int ) sizeof ( TestTypeNodeContainer ) ) ;
if ( ! _dbus_list_append ( & container - > children , child ) )
_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 */
return TRUE ;
}
static dbus_bool_t
node_write_multi ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ,
int n_copies )
{
dbus_bool_t retval ;
_dbus_assert ( node - > klass - > write_multi ! = NULL ) ;
retval = ( * node - > klass - > write_multi ) ( node , block , writer , seed , n_copies ) ;
#if 0
/* Handy to see where things break, but too expensive to do all the time */
data_block_verify ( block ) ;
# endif
return retval ;
}
static dbus_bool_t
node_read_multi ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ,
int n_copies )
{
_dbus_assert ( node - > klass - > read_multi ! = NULL ) ;
if ( ! ( * node - > klass - > read_multi ) ( node , reader , seed , n_copies ) )
return FALSE ;
return TRUE ;
}
static int n_iterations_completed_total = 0 ;
static int n_iterations_completed_this_test = 0 ;
static int n_iterations_expected_this_test = 0 ;
typedef struct
{
const DBusString * signature ;
DataBlock * block ;
int type_offset ;
TestTypeNode * * nodes ;
int n_nodes ;
} NodeIterationData ;
static dbus_bool_t
run_test_copy ( NodeIterationData * nid )
{
DataBlock * src ;
DataBlock dest ;
dbus_bool_t retval ;
DBusTypeReader reader ;
DBusTypeWriter writer ;
_dbus_verbose ( " %s \n " , _DBUS_FUNCTION_NAME ) ;
src = nid - > block ;
retval = FALSE ;
if ( ! data_block_init ( & dest , src - > byte_order , src - > initial_offset ) )
return FALSE ;
data_block_init_reader_writer ( src , & reader , NULL ) ;
data_block_init_reader_writer ( & dest , NULL , & writer ) ;
/* DBusTypeWriter assumes it's writing into an existing signature,
* so doesn ' t add nul on its own . We have to do that .
*/
if ( ! _dbus_string_insert_byte ( & dest . signature ,
dest . initial_offset , ' \0 ' ) )
goto out ;
if ( ! _dbus_type_writer_write_reader ( & writer , & reader ) )
goto out ;
/* Data blocks should now be identical */
if ( ! _dbus_string_equal ( & src - > signature , & dest . signature ) )
{
_dbus_verbose ( " SOURCE \n " ) ;
_dbus_verbose_bytes_of_string ( & src - > signature , 0 ,
_dbus_string_get_length ( & src - > signature ) ) ;
_dbus_verbose ( " DEST \n " ) ;
_dbus_verbose_bytes_of_string ( & dest . signature , 0 ,
_dbus_string_get_length ( & dest . signature ) ) ;
_dbus_assert_not_reached ( " signatures did not match " ) ;
}
if ( ! _dbus_string_equal ( & src - > body , & dest . body ) )
{
_dbus_verbose ( " SOURCE \n " ) ;
_dbus_verbose_bytes_of_string ( & src - > body , 0 ,
_dbus_string_get_length ( & src - > body ) ) ;
_dbus_verbose ( " DEST \n " ) ;
_dbus_verbose_bytes_of_string ( & dest . body , 0 ,
_dbus_string_get_length ( & dest . body ) ) ;
_dbus_assert_not_reached ( " bodies did not match " ) ;
}
retval = TRUE ;
out :
data_block_free ( & dest ) ;
return retval ;
}
static dbus_bool_t
run_test_values_only_write ( NodeIterationData * nid )
{
DBusTypeReader reader ;
DBusTypeWriter writer ;
int i ;
dbus_bool_t retval ;
int sig_len ;
_dbus_verbose ( " %s \n " , _DBUS_FUNCTION_NAME ) ;
retval = FALSE ;
data_block_reset ( nid - > block ) ;
sig_len = _dbus_string_get_length ( nid - > signature ) ;
_dbus_type_writer_init_values_only ( & writer ,
nid - > block - > byte_order ,
nid - > signature , 0 ,
& nid - > block - > body ,
_dbus_string_get_length ( & nid - > block - > body ) - N_FENCE_BYTES ) ;
_dbus_type_reader_init ( & reader ,
nid - > block - > byte_order ,
nid - > signature , 0 ,
& nid - > block - > body ,
nid - > block - > initial_offset ) ;
i = 0 ;
while ( i < nid - > n_nodes )
{
if ( ! node_write_value ( nid - > nodes [ i ] , nid - > block , & writer , i ) )
goto out ;
+ + i ;
}
/* if we wrote any typecodes then this would fail */
_dbus_assert ( sig_len = = _dbus_string_get_length ( nid - > signature ) ) ;
/* But be sure we wrote out the values correctly */
i = 0 ;
while ( i < nid - > n_nodes )
{
if ( ! node_read_value ( nid - > nodes [ i ] , & reader , i ) )
goto out ;
if ( i + 1 = = nid - > n_nodes )
NEXT_EXPECTING_FALSE ( & reader ) ;
else
NEXT_EXPECTING_TRUE ( & reader ) ;
+ + i ;
}
retval = TRUE ;
out :
data_block_reset ( nid - > block ) ;
return retval ;
}
/* offset the seed for setting, so we set different numbers than
* we originally wrote . Don ' t offset by a huge number since in
* some cases it ' s value = possibilities [ seed % n_possibilities ]
* and we don ' t want to wrap around . bool_from_seed
* is just seed % 2 even .
*/
# define SET_SEED 1
static dbus_bool_t
run_test_set_values ( NodeIterationData * nid )
{
DBusTypeReader reader ;
DBusTypeReader realign_root ;
dbus_bool_t retval ;
int i ;
_dbus_verbose ( " %s \n " , _DBUS_FUNCTION_NAME ) ;
retval = FALSE ;
data_block_init_reader_writer ( nid - > block ,
& reader , NULL ) ;
realign_root = reader ;
i = 0 ;
while ( i < nid - > n_nodes )
{
if ( ! node_set_value ( nid - > nodes [ i ] ,
& reader , & realign_root ,
i + SET_SEED ) )
goto out ;
if ( i + 1 = = nid - > n_nodes )
NEXT_EXPECTING_FALSE ( & reader ) ;
else
NEXT_EXPECTING_TRUE ( & reader ) ;
+ + i ;
}
/* Check that the new values were set */
reader = realign_root ;
i = 0 ;
while ( i < nid - > n_nodes )
{
if ( ! node_read_value ( nid - > nodes [ i ] , & reader ,
i + SET_SEED ) )
goto out ;
if ( i + 1 = = nid - > n_nodes )
NEXT_EXPECTING_FALSE ( & reader ) ;
else
NEXT_EXPECTING_TRUE ( & reader ) ;
+ + i ;
}
retval = TRUE ;
out :
return retval ;
}
static dbus_bool_t
run_test_delete_values ( NodeIterationData * nid )
{
DBusTypeReader reader ;
dbus_bool_t retval ;
int t ;
_dbus_verbose ( " %s \n " , _DBUS_FUNCTION_NAME ) ;
retval = FALSE ;
data_block_init_reader_writer ( nid - > block ,
& reader , NULL ) ;
while ( ( t = _dbus_type_reader_get_current_type ( & reader ) ) ! = DBUS_TYPE_INVALID )
{
/* Right now, deleting only works on array elements. We delete
* all array elements , and then verify that there aren ' t any
* left .
*/
if ( t = = DBUS_TYPE_ARRAY )
{
DBusTypeReader array ;
int n_elements ;
int elem_type ;
_dbus_type_reader_recurse ( & reader , & array ) ;
n_elements = 0 ;
while ( _dbus_type_reader_get_current_type ( & array ) ! = DBUS_TYPE_INVALID )
{
n_elements + = 1 ;
_dbus_type_reader_next ( & array ) ;
}
/* reset to start of array */
_dbus_type_reader_recurse ( & reader , & array ) ;
_dbus_verbose ( " recursing into deletion loop reader.value_pos = %d array.value_pos = %d array.u.start_pos = %d \n " ,
reader . value_pos , array . value_pos , array . u . array . start_pos ) ;
while ( ( elem_type = _dbus_type_reader_get_current_type ( & array ) ) ! = DBUS_TYPE_INVALID )
{
/* We don't want to always delete from the same part of the array. */
static int cycle = 0 ;
int elem ;
_dbus_assert ( n_elements > 0 ) ;
elem = cycle ;
if ( elem = = 3 | | elem > = n_elements ) /* end of array */
elem = n_elements - 1 ;
_dbus_verbose ( " deleting array element %d of %d type %s cycle %d reader pos %d elem pos %d \n " ,
elem , n_elements , _dbus_type_to_string ( elem_type ) ,
cycle , reader . value_pos , array . value_pos ) ;
while ( elem > 0 )
{
if ( ! _dbus_type_reader_next ( & array ) )
_dbus_assert_not_reached ( " should have had another element \n " ) ;
- - elem ;
}
if ( ! _dbus_type_reader_delete ( & array , & reader ) )
goto out ;
n_elements - = 1 ;
/* reset */
_dbus_type_reader_recurse ( & reader , & array ) ;
if ( cycle > 2 )
cycle = 0 ;
else
cycle + = 1 ;
}
}
_dbus_type_reader_next ( & reader ) ;
}
/* Check that there are no array elements left */
data_block_init_reader_writer ( nid - > block ,
& reader , NULL ) ;
while ( ( t = _dbus_type_reader_get_current_type ( & reader ) ) ! = DBUS_TYPE_INVALID )
{
_dbus_type_reader_next ( & reader ) ;
}
retval = TRUE ;
out :
return retval ;
}
static dbus_bool_t
run_test_nodes_iteration ( void * data )
{
NodeIterationData * nid = data ;
DBusTypeReader reader ;
DBusTypeWriter writer ;
int i ;
dbus_bool_t retval ;
/* Stuff to do:
* 1. write the value
* 2. strcmp - compare with the signature we built
* 3. read the value
* 4. type - iterate the signature and the value and see if they are the same type - wise
*/
retval = FALSE ;
data_block_init_reader_writer ( nid - > block ,
& reader , & writer ) ;
/* DBusTypeWriter assumes it's writing into an existing signature,
* so doesn ' t add nul on its own . We have to do that .
*/
if ( ! _dbus_string_insert_byte ( & nid - > block - > signature ,
nid - > type_offset , ' \0 ' ) )
goto out ;
i = 0 ;
while ( i < nid - > n_nodes )
{
if ( ! node_write_value ( nid - > nodes [ i ] , nid - > block , & writer , i ) )
goto out ;
+ + i ;
}
if ( ! _dbus_string_equal_substring ( nid - > signature , 0 , _dbus_string_get_length ( nid - > signature ) ,
& nid - > block - > signature , nid - > type_offset ) )
{
_dbus_warn ( " Expected signature '%s' and got '%s' with initial offset %d \n " ,
_dbus_string_get_const_data ( nid - > signature ) ,
_dbus_string_get_const_data_len ( & nid - > block - > signature , nid - > type_offset , 0 ) ,
nid - > type_offset ) ;
_dbus_assert_not_reached ( " wrong signature " ) ;
}
i = 0 ;
while ( i < nid - > n_nodes )
{
if ( ! node_read_value ( nid - > nodes [ i ] , & reader , i ) )
goto out ;
if ( i + 1 = = nid - > n_nodes )
NEXT_EXPECTING_FALSE ( & reader ) ;
else
NEXT_EXPECTING_TRUE ( & reader ) ;
+ + i ;
}
if ( n_iterations_expected_this_test < = MAX_ITERATIONS_FOR_EXPENSIVE_TESTS )
{
/* this set values test uses code from copy and
* values_only_write so would ideally be last so you get a
* simpler test case for problems with copying or values_only
* writing ; but it also needs an already - written DataBlock so it
* has to go first . Comment it out if it breaks , and see if the
* later tests also break - debug them first if so .
*/
if ( ! run_test_set_values ( nid ) )
goto out ;
if ( ! run_test_delete_values ( nid ) )
goto out ;
if ( ! run_test_copy ( nid ) )
goto out ;
if ( ! run_test_values_only_write ( nid ) )
goto out ;
}
/* FIXME type-iterate both signature and value and compare the resulting
* tree to the node tree perhaps
*/
retval = TRUE ;
out :
data_block_reset ( nid - > block ) ;
return retval ;
}
static void
run_test_nodes_in_one_configuration ( TestTypeNode * * nodes ,
int n_nodes ,
const DBusString * signature ,
int byte_order ,
int initial_offset )
{
DataBlock block ;
NodeIterationData nid ;
if ( ! data_block_init ( & block , byte_order , initial_offset ) )
_dbus_assert_not_reached ( " no memory " ) ;
nid . signature = signature ;
nid . block = & block ;
nid . type_offset = initial_offset ;
nid . nodes = nodes ;
nid . n_nodes = n_nodes ;
if ( TEST_OOM_HANDLING & &
n_iterations_expected_this_test < = MAX_ITERATIONS_FOR_EXPENSIVE_TESTS )
{
_dbus_test_oom_handling ( " running test node " ,
run_test_nodes_iteration ,
& nid ) ;
}
else
{
if ( ! run_test_nodes_iteration ( & nid ) )
_dbus_assert_not_reached ( " no memory " ) ;
}
data_block_free ( & block ) ;
}
static void
run_test_nodes ( TestTypeNode * * nodes ,
int n_nodes )
{
int i ;
DBusString signature ;
if ( ! _dbus_string_init ( & signature ) )
_dbus_assert_not_reached ( " no memory " ) ;
i = 0 ;
while ( i < n_nodes )
{
if ( ! node_build_signature ( nodes [ i ] , & signature ) )
_dbus_assert_not_reached ( " no memory " ) ;
+ + i ;
}
_dbus_verbose ( " >>> test nodes with signature '%s' \n " ,
_dbus_string_get_const_data ( & signature ) ) ;
i = 0 ;
while ( i < = MAX_INITIAL_OFFSET )
{
run_test_nodes_in_one_configuration ( nodes , n_nodes , & signature ,
DBUS_LITTLE_ENDIAN , i ) ;
run_test_nodes_in_one_configuration ( nodes , n_nodes , & signature ,
DBUS_BIG_ENDIAN , i ) ;
+ + i ;
}
n_iterations_completed_this_test + = 1 ;
n_iterations_completed_total + = 1 ;
if ( n_iterations_completed_this_test = = n_iterations_expected_this_test )
{
fprintf ( stderr , " 100%% %d this test (%d cumulative) \n " ,
n_iterations_completed_this_test ,
n_iterations_completed_total ) ;
}
/* this happens to turn out well with mod == 1 */
else if ( ( n_iterations_completed_this_test %
( int ) ( n_iterations_expected_this_test / 10.0 ) ) = = 1 )
{
fprintf ( stderr , " %d%% " , ( int ) ( n_iterations_completed_this_test / ( double ) n_iterations_expected_this_test * 100 ) ) ;
}
_dbus_string_free ( & signature ) ;
}
# define N_VALUES (N_BASICS * N_CONTAINERS + N_BASICS)
static TestTypeNode *
value_generator ( int * ip )
{
int i = * ip ;
const TestTypeNodeClass * child_klass ;
const TestTypeNodeClass * container_klass ;
TestTypeNode * child ;
TestTypeNode * node ;
_dbus_assert ( i < = N_VALUES ) ;
if ( i = = N_VALUES )
{
return NULL ;
}
else if ( i < N_BASICS )
{
node = node_new ( basic_nodes [ i ] ) ;
}
else
{
/* imagine an array:
* container 0 of basic 0
* container 0 of basic 1
* container 0 of basic 2
* container 1 of basic 0
* container 1 of basic 1
* container 1 of basic 2
*/
i - = N_BASICS ;
container_klass = container_nodes [ i / N_BASICS ] ;
child_klass = basic_nodes [ i % N_BASICS ] ;
node = node_new ( container_klass ) ;
child = node_new ( child_klass ) ;
node_append_child ( node , child ) ;
}
* ip + = 1 ; /* increment the generator */
return node ;
}
2005-01-24 05:56:25 +00:00
static void
build_body ( TestTypeNode * * nodes ,
int n_nodes ,
int byte_order ,
DBusString * signature ,
DBusString * body )
{
int i ;
DataBlock block ;
DBusTypeReader reader ;
DBusTypeWriter writer ;
i = 0 ;
while ( i < n_nodes )
{
if ( ! node_build_signature ( nodes [ i ] , signature ) )
_dbus_assert_not_reached ( " no memory " ) ;
+ + i ;
}
if ( ! data_block_init ( & block , byte_order , 0 ) )
_dbus_assert_not_reached ( " no memory " ) ;
data_block_init_reader_writer ( & block ,
& reader , & writer ) ;
/* DBusTypeWriter assumes it's writing into an existing signature,
* so doesn ' t add nul on its own . We have to do that .
*/
if ( ! _dbus_string_insert_byte ( & block . signature ,
0 , ' \0 ' ) )
_dbus_assert_not_reached ( " no memory " ) ;
i = 0 ;
while ( i < n_nodes )
{
if ( ! node_write_value ( nodes [ i ] , & block , & writer , i ) )
_dbus_assert_not_reached ( " no memory " ) ;
+ + i ;
}
if ( ! _dbus_string_copy_len ( & block . body , 0 ,
_dbus_string_get_length ( & block . body ) - N_FENCE_BYTES ,
body , 0 ) )
_dbus_assert_not_reached ( " oom " ) ;
data_block_free ( & block ) ;
}
dbus_bool_t
dbus_internal_do_not_use_generate_bodies ( int sequence ,
int byte_order ,
DBusString * signature ,
DBusString * body )
{
TestTypeNode * nodes [ 1 ] ;
int i ;
int n_nodes ;
nodes [ 0 ] = value_generator ( & sequence ) ;
if ( nodes [ 0 ] = = NULL )
return FALSE ;
n_nodes = 1 ;
build_body ( nodes , n_nodes , byte_order , signature , body ) ;
i = 0 ;
while ( i < n_nodes )
{
node_destroy ( nodes [ i ] ) ;
+ + i ;
}
return TRUE ;
}
2005-01-17 03:53:40 +00:00
static void
make_and_run_values_inside_container ( const TestTypeNodeClass * container_klass ,
int n_nested )
{
TestTypeNode * root ;
TestTypeNode * container ;
TestTypeNode * child ;
int i ;
root = node_new ( container_klass ) ;
container = root ;
for ( i = 1 ; i < n_nested ; i + + )
{
child = node_new ( container_klass ) ;
node_append_child ( container , child ) ;
container = child ;
}
/* container should now be the most-nested container */
i = 0 ;
while ( ( child = value_generator ( & i ) ) )
{
node_append_child ( container , child ) ;
run_test_nodes ( & root , 1 ) ;
_dbus_list_clear ( & ( ( TestTypeNodeContainer * ) container ) - > children ) ;
node_destroy ( child ) ;
}
node_destroy ( root ) ;
}
static void
start_next_test ( const char * format ,
int expected )
{
n_iterations_completed_this_test = 0 ;
n_iterations_expected_this_test = expected ;
fprintf ( stderr , " >>> >>> " ) ;
fprintf ( stderr , format ,
n_iterations_expected_this_test ) ;
}
static void
make_and_run_test_nodes ( void )
{
int i , j , k , m ;
/* We try to do this in order of "complicatedness" so that test
* failures tend to show up in the simplest test case that
* demonstrates the failure . There are also some tests that run
* more than once for this reason , first while going through simple
* cases , second while going through a broader range of complex
* cases .
*/
/* Each basic node. The basic nodes should include:
*
* - each fixed - size type ( in such a way that it has different values each time ,
* so we can tell if we mix two of them up )
* - strings of various lengths
* - object path
* - signature
*/
/* Each container node. The container nodes should include:
*
* struct with 1 and 2 copies of the contained item
* array with 0 , 1 , 2 copies of the contained item
* variant
*/
/* Let a "value" be a basic node, or a container containing a single basic node.
* Let n_values be the number of such values i . e . ( n_container * n_basic + n_basic )
* When iterating through all values to make combinations , do the basic types
* first and the containers second .
*/
/* Each item is shown with its number of iterations to complete so
* we can keep a handle on this unit test
*/
/* FIXME test just an empty body, no types at all */
start_next_test ( " Each value by itself %d iterations \n " , N_VALUES ) ;
{
TestTypeNode * node ;
i = 0 ;
while ( ( node = value_generator ( & i ) ) )
{
run_test_nodes ( & node , 1 ) ;
node_destroy ( node ) ;
}
}
start_next_test ( " Each value by itself with arrays as blocks %d iterations \n " , N_VALUES ) ;
arrays_write_fixed_in_blocks = TRUE ;
{
TestTypeNode * node ;
i = 0 ;
while ( ( node = value_generator ( & i ) ) )
{
run_test_nodes ( & node , 1 ) ;
node_destroy ( node ) ;
}
}
arrays_write_fixed_in_blocks = FALSE ;
start_next_test ( " All values in one big toplevel %d iteration \n " , 1 ) ;
{
TestTypeNode * nodes [ N_VALUES ] ;
i = 0 ;
while ( ( nodes [ i ] = value_generator ( & i ) ) )
;
run_test_nodes ( nodes , N_VALUES ) ;
for ( i = 0 ; i < N_VALUES ; i + + )
node_destroy ( nodes [ i ] ) ;
}
start_next_test ( " Each value,value pair combination as toplevel, in both orders %d iterations \n " ,
N_VALUES * N_VALUES ) ;
{
TestTypeNode * nodes [ 2 ] ;
i = 0 ;
while ( ( nodes [ 0 ] = value_generator ( & i ) ) )
{
j = 0 ;
while ( ( nodes [ 1 ] = value_generator ( & j ) ) )
{
run_test_nodes ( nodes , 2 ) ;
node_destroy ( nodes [ 1 ] ) ;
}
node_destroy ( nodes [ 0 ] ) ;
}
}
start_next_test ( " Each container containing each value %d iterations \n " ,
N_CONTAINERS * N_VALUES ) ;
for ( i = 0 ; i < N_CONTAINERS ; i + + )
{
const TestTypeNodeClass * container_klass = container_nodes [ i ] ;
make_and_run_values_inside_container ( container_klass , 1 ) ;
}
start_next_test ( " Each container containing each value with arrays as blocks %d iterations \n " ,
N_CONTAINERS * N_VALUES ) ;
arrays_write_fixed_in_blocks = TRUE ;
for ( i = 0 ; i < N_CONTAINERS ; i + + )
{
const TestTypeNodeClass * container_klass = container_nodes [ i ] ;
make_and_run_values_inside_container ( container_klass , 1 ) ;
}
arrays_write_fixed_in_blocks = FALSE ;
start_next_test ( " Each container of same container of each value %d iterations \n " ,
N_CONTAINERS * N_VALUES ) ;
for ( i = 0 ; i < N_CONTAINERS ; i + + )
{
const TestTypeNodeClass * container_klass = container_nodes [ i ] ;
make_and_run_values_inside_container ( container_klass , 2 ) ;
}
start_next_test ( " Each container of same container of same container of each value %d iterations \n " ,
N_CONTAINERS * N_VALUES ) ;
for ( i = 0 ; i < N_CONTAINERS ; i + + )
{
const TestTypeNodeClass * container_klass = container_nodes [ i ] ;
make_and_run_values_inside_container ( container_klass , 3 ) ;
}
start_next_test ( " Each value,value pair inside a struct %d iterations \n " ,
N_VALUES * N_VALUES ) ;
{
TestTypeNode * val1 , * val2 ;
TestTypeNode * node ;
node = node_new ( & struct_1_class ) ;
i = 0 ;
while ( ( val1 = value_generator ( & i ) ) )
{
j = 0 ;
while ( ( val2 = value_generator ( & j ) ) )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
node_append_child ( node , val1 ) ;
node_append_child ( node , val2 ) ;
run_test_nodes ( & node , 1 ) ;
_dbus_list_clear ( & container - > children ) ;
node_destroy ( val2 ) ;
}
node_destroy ( val1 ) ;
}
node_destroy ( node ) ;
}
start_next_test ( " All values in one big struct %d iteration \n " ,
1 ) ;
{
TestTypeNode * node ;
TestTypeNode * child ;
node = node_new ( & struct_1_class ) ;
i = 0 ;
while ( ( child = value_generator ( & i ) ) )
node_append_child ( node , child ) ;
run_test_nodes ( & node , 1 ) ;
node_destroy ( node ) ;
}
start_next_test ( " Each value in a large array %d iterations \n " ,
N_VALUES ) ;
{
TestTypeNode * val ;
TestTypeNode * node ;
node = node_new ( & array_9_class ) ;
i = 0 ;
while ( ( val = value_generator ( & i ) ) )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
node_append_child ( node , val ) ;
run_test_nodes ( & node , 1 ) ;
_dbus_list_clear ( & container - > children ) ;
node_destroy ( val ) ;
}
node_destroy ( node ) ;
}
start_next_test ( " Each container of each container of each value %d iterations \n " ,
N_CONTAINERS * N_CONTAINERS * N_VALUES ) ;
for ( i = 0 ; i < N_CONTAINERS ; i + + )
{
const TestTypeNodeClass * outer_container_klass = container_nodes [ i ] ;
TestTypeNode * outer_container = node_new ( outer_container_klass ) ;
for ( j = 0 ; j < N_CONTAINERS ; j + + )
{
TestTypeNode * child ;
const TestTypeNodeClass * inner_container_klass = container_nodes [ j ] ;
TestTypeNode * inner_container = node_new ( inner_container_klass ) ;
node_append_child ( outer_container , inner_container ) ;
m = 0 ;
while ( ( child = value_generator ( & m ) ) )
{
node_append_child ( inner_container , child ) ;
run_test_nodes ( & outer_container , 1 ) ;
_dbus_list_clear ( & ( ( TestTypeNodeContainer * ) inner_container ) - > children ) ;
node_destroy ( child ) ;
}
_dbus_list_clear ( & ( ( TestTypeNodeContainer * ) outer_container ) - > children ) ;
node_destroy ( inner_container ) ;
}
node_destroy ( outer_container ) ;
}
start_next_test ( " Each container of each container of each container of each value %d iterations \n " ,
N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES ) ;
for ( i = 0 ; i < N_CONTAINERS ; i + + )
{
const TestTypeNodeClass * outer_container_klass = container_nodes [ i ] ;
TestTypeNode * outer_container = node_new ( outer_container_klass ) ;
for ( j = 0 ; j < N_CONTAINERS ; j + + )
{
const TestTypeNodeClass * inner_container_klass = container_nodes [ j ] ;
TestTypeNode * inner_container = node_new ( inner_container_klass ) ;
node_append_child ( outer_container , inner_container ) ;
for ( k = 0 ; k < N_CONTAINERS ; k + + )
{
TestTypeNode * child ;
const TestTypeNodeClass * center_container_klass = container_nodes [ k ] ;
TestTypeNode * center_container = node_new ( center_container_klass ) ;
node_append_child ( inner_container , center_container ) ;
m = 0 ;
while ( ( child = value_generator ( & m ) ) )
{
node_append_child ( center_container , child ) ;
run_test_nodes ( & outer_container , 1 ) ;
_dbus_list_clear ( & ( ( TestTypeNodeContainer * ) center_container ) - > children ) ;
node_destroy ( child ) ;
}
_dbus_list_clear ( & ( ( TestTypeNodeContainer * ) inner_container ) - > children ) ;
node_destroy ( center_container ) ;
}
_dbus_list_clear ( & ( ( TestTypeNodeContainer * ) outer_container ) - > children ) ;
node_destroy ( inner_container ) ;
}
node_destroy ( outer_container ) ;
}
#if 0
/* This one takes a really long time, so comment it out for now */
start_next_test ( " Each value,value,value triplet combination as toplevel, in all orders %d iterations \n " ,
N_VALUES * N_VALUES * N_VALUES ) ;
{
TestTypeNode * nodes [ 3 ] ;
i = 0 ;
while ( ( nodes [ 0 ] = value_generator ( & i ) ) )
{
j = 0 ;
while ( ( nodes [ 1 ] = value_generator ( & j ) ) )
{
k = 0 ;
while ( ( nodes [ 2 ] = value_generator ( & k ) ) )
{
run_test_nodes ( nodes , 3 ) ;
node_destroy ( nodes [ 2 ] ) ;
}
node_destroy ( nodes [ 1 ] ) ;
}
node_destroy ( nodes [ 0 ] ) ;
}
}
# endif /* #if 0 expensive test */
fprintf ( stderr , " %d total iterations of recursive marshaling tests \n " ,
n_iterations_completed_total ) ;
fprintf ( stderr , " each iteration ran at initial offsets 0 through %d in both big and little endian \n " ,
MAX_INITIAL_OFFSET ) ;
fprintf ( stderr , " out of memory handling %s tested \n " ,
TEST_OOM_HANDLING ? " was " : " was not " ) ;
}
dbus_bool_t
_dbus_marshal_recursive_test ( void )
{
make_and_run_test_nodes ( ) ;
return TRUE ;
}
/*
*
*
* Implementations of each type node class
*
*
*
*/
# define MAX_MULTI_COUNT 5
2005-01-28 03:06:56 +00:00
# define SAMPLE_INT16 1234
# define SAMPLE_INT16_ALTERNATE 6785
static dbus_int16_t
int16_from_seed ( int seed )
{
/* Generate an integer value that's predictable from seed. We could
* just use seed itself , but that would only ever touch one byte of
* the int so would miss some kinds of bug .
*/
dbus_int16_t v ;
v = 42 ; /* just to quiet compiler afaik */
switch ( seed % 5 )
{
case 0 :
v = SAMPLE_INT16 ;
break ;
case 1 :
v = SAMPLE_INT16_ALTERNATE ;
break ;
case 2 :
v = - 1 ;
break ;
case 3 :
v = _DBUS_INT16_MAX ;
break ;
case 4 :
v = 1 ;
break ;
}
if ( seed > 1 )
v * = seed ; /* wraps around eventually, which is fine */
return v ;
}
static dbus_bool_t
int16_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
/* also used for uint16 */
dbus_int16_t v ;
v = int16_from_seed ( seed ) ;
return _dbus_type_writer_write_basic ( writer ,
node - > klass - > typecode ,
& v ) ;
}
static dbus_bool_t
int16_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
/* also used for uint16 */
dbus_int16_t v ;
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_basic ( reader ,
( dbus_int16_t * ) & v ) ;
_dbus_assert ( v = = int16_from_seed ( seed ) ) ;
return TRUE ;
}
static dbus_bool_t
int16_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
/* also used for uint16 */
dbus_int16_t v ;
v = int16_from_seed ( seed ) ;
return _dbus_type_reader_set_basic ( reader ,
& v ,
realign_root ) ;
}
static dbus_bool_t
int16_write_multi ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ,
int count )
{
/* also used for uint16 */
dbus_int16_t values [ MAX_MULTI_COUNT ] ;
dbus_int16_t * v_ARRAY_INT16 = values ;
int i ;
for ( i = 0 ; i < count ; + + i )
values [ i ] = int16_from_seed ( seed + i ) ;
return _dbus_type_writer_write_fixed_multi ( writer ,
node - > klass - > typecode ,
& v_ARRAY_INT16 , count ) ;
}
static dbus_bool_t
int16_read_multi ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ,
int count )
{
/* also used for uint16 */
dbus_int16_t * values ;
int n_elements ;
int i ;
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_fixed_multi ( reader ,
& values ,
& n_elements ) ;
if ( n_elements ! = count )
_dbus_warn ( " got %d elements expected %d \n " , n_elements , count ) ;
_dbus_assert ( n_elements = = count ) ;
for ( i = 0 ; i < count ; i + + )
2005-01-28 05:30:53 +00:00
_dbus_assert ( ( ( dbus_int16_t ) _dbus_unpack_uint16 ( reader - > byte_order ,
( const unsigned char * ) values + ( i * 2 ) ) ) = =
2005-01-28 03:06:56 +00:00
int16_from_seed ( seed + i ) ) ;
return TRUE ;
}
2005-01-17 03:53:40 +00:00
# define SAMPLE_INT32 12345678
# define SAMPLE_INT32_ALTERNATE 53781429
static dbus_int32_t
int32_from_seed ( int seed )
{
/* Generate an integer value that's predictable from seed. We could
* just use seed itself , but that would only ever touch one byte of
* the int so would miss some kinds of bug .
*/
dbus_int32_t v ;
v = 42 ; /* just to quiet compiler afaik */
switch ( seed % 5 )
{
case 0 :
v = SAMPLE_INT32 ;
break ;
case 1 :
v = SAMPLE_INT32_ALTERNATE ;
break ;
case 2 :
v = - 1 ;
break ;
case 3 :
v = _DBUS_INT_MAX ;
break ;
case 4 :
v = 1 ;
break ;
}
if ( seed > 1 )
v * = seed ; /* wraps around eventually, which is fine */
return v ;
}
static dbus_bool_t
int32_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
/* also used for uint32 */
dbus_int32_t v ;
v = int32_from_seed ( seed ) ;
return _dbus_type_writer_write_basic ( writer ,
node - > klass - > typecode ,
& v ) ;
}
static dbus_bool_t
int32_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
/* also used for uint32 */
dbus_int32_t v ;
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_basic ( reader ,
( dbus_int32_t * ) & v ) ;
_dbus_assert ( v = = int32_from_seed ( seed ) ) ;
return TRUE ;
}
static dbus_bool_t
int32_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
/* also used for uint32 */
dbus_int32_t v ;
v = int32_from_seed ( seed ) ;
return _dbus_type_reader_set_basic ( reader ,
& v ,
realign_root ) ;
}
static dbus_bool_t
int32_write_multi ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed ,
int count )
{
/* also used for uint32 */
dbus_int32_t values [ MAX_MULTI_COUNT ] ;
dbus_int32_t * v_ARRAY_INT32 = values ;
int i ;
for ( i = 0 ; i < count ; + + i )
values [ i ] = int32_from_seed ( seed + i ) ;
return _dbus_type_writer_write_fixed_multi ( writer ,
node - > klass - > typecode ,
& v_ARRAY_INT32 , count ) ;
}
static dbus_bool_t
int32_read_multi ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed ,
int count )
{
/* also used for uint32 */
dbus_int32_t * values ;
int n_elements ;
int i ;
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_fixed_multi ( reader ,
& values ,
& n_elements ) ;
if ( n_elements ! = count )
_dbus_warn ( " got %d elements expected %d \n " , n_elements , count ) ;
_dbus_assert ( n_elements = = count ) ;
for ( i = 0 ; i < count ; i + + )
_dbus_assert ( ( ( int ) _dbus_unpack_uint32 ( reader - > byte_order ,
( const unsigned char * ) values + ( i * 4 ) ) ) = =
int32_from_seed ( seed + i ) ) ;
return TRUE ;
}
# ifdef DBUS_HAVE_INT64
static dbus_int64_t
int64_from_seed ( int seed )
{
dbus_int32_t v32 ;
dbus_int64_t v ;
v32 = int32_from_seed ( seed ) ;
v = - ( dbus_int32_t ) ~ v32 ;
v | = ( ( ( dbus_int64_t ) v32 ) < < 32 ) ;
return v ;
}
# endif
static dbus_bool_t
int64_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
# ifdef DBUS_HAVE_INT64
/* also used for uint64 */
dbus_int64_t v ;
v = int64_from_seed ( seed ) ;
return _dbus_type_writer_write_basic ( writer ,
node - > klass - > typecode ,
& v ) ;
# else
return TRUE ;
# endif
}
static dbus_bool_t
int64_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
# ifdef DBUS_HAVE_INT64
/* also used for uint64 */
dbus_int64_t v ;
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_basic ( reader ,
( dbus_int64_t * ) & v ) ;
_dbus_assert ( v = = int64_from_seed ( seed ) ) ;
return TRUE ;
# else
return TRUE ;
# endif
}
static dbus_bool_t
int64_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
# ifdef DBUS_HAVE_INT64
/* also used for uint64 */
dbus_int64_t v ;
v = int64_from_seed ( seed ) ;
return _dbus_type_reader_set_basic ( reader ,
& v ,
realign_root ) ;
# else
return TRUE ;
# endif
}
# define MAX_SAMPLE_STRING_LEN 10
static void
string_from_seed ( char * buf ,
int len ,
int seed )
{
int i ;
unsigned char v ;
_dbus_assert ( len < MAX_SAMPLE_STRING_LEN ) ;
/* vary the length slightly, though we also have multiple string
* value types for this , varying it here tests the set_value code
*/
switch ( seed % 3 )
{
case 1 :
len + = 2 ;
break ;
case 2 :
len - = 2 ;
break ;
}
if ( len < 0 )
len = 0 ;
v = ( unsigned char ) ( ' A ' + seed ) ;
i = 0 ;
while ( i < len )
{
if ( v < ' A ' | | v > ' z ' )
v = ' A ' ;
buf [ i ] = v ;
v + = 1 ;
+ + i ;
}
buf [ i ] = ' \0 ' ;
}
static dbus_bool_t
string_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
2005-04-23 22:34:48 +00:00
char buf [ MAX_SAMPLE_STRING_LEN + 1 ] = " " ;
2005-01-17 03:53:40 +00:00
const char * v_string = buf ;
2005-04-23 22:34:48 +00:00
2005-01-17 03:53:40 +00:00
string_from_seed ( buf , node - > klass - > subclass_detail ,
seed ) ;
return _dbus_type_writer_write_basic ( writer ,
node - > klass - > typecode ,
& v_string ) ;
}
static dbus_bool_t
string_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
const char * v ;
2005-04-23 22:34:48 +00:00
char buf [ MAX_SAMPLE_STRING_LEN + 1 ] ;
v = buf ;
2005-01-17 03:53:40 +00:00
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_basic ( reader ,
( const char * * ) & v ) ;
string_from_seed ( buf , node - > klass - > subclass_detail ,
seed ) ;
if ( strcmp ( buf , v ) ! = 0 )
{
_dbus_warn ( " read string '%s' expected '%s' \n " ,
v , buf ) ;
_dbus_assert_not_reached ( " test failed " ) ;
}
return TRUE ;
}
static dbus_bool_t
string_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
2005-04-23 22:34:48 +00:00
char buf [ MAX_SAMPLE_STRING_LEN + 1 ] ;
2005-01-17 03:53:40 +00:00
const char * v_string = buf ;
string_from_seed ( buf , node - > klass - > subclass_detail ,
seed ) ;
# if RECURSIVE_MARSHAL_WRITE_TRACE
{
const char * old ;
_dbus_type_reader_read_basic ( reader , & old ) ;
_dbus_verbose ( " SETTING new string '%s' len %d in place of '%s' len %d \n " ,
v_string , strlen ( v_string ) , old , strlen ( old ) ) ;
}
# endif
return _dbus_type_reader_set_basic ( reader ,
& v_string ,
realign_root ) ;
}
2005-01-17 19:49:52 +00:00
# define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
2005-01-17 03:53:40 +00:00
static dbus_bool_t
bool_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
2005-01-17 19:49:52 +00:00
dbus_bool_t v ;
2005-01-17 03:53:40 +00:00
v = BOOL_FROM_SEED ( seed ) ;
return _dbus_type_writer_write_basic ( writer ,
node - > klass - > typecode ,
& v ) ;
}
static dbus_bool_t
bool_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
2005-01-17 19:49:52 +00:00
dbus_bool_t v ;
2005-01-17 03:53:40 +00:00
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_basic ( reader ,
( unsigned char * ) & v ) ;
_dbus_assert ( v = = BOOL_FROM_SEED ( seed ) ) ;
return TRUE ;
}
static dbus_bool_t
bool_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
2005-01-17 19:49:52 +00:00
dbus_bool_t v ;
2005-01-17 03:53:40 +00:00
v = BOOL_FROM_SEED ( seed ) ;
return _dbus_type_reader_set_basic ( reader ,
& v ,
realign_root ) ;
}
# define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
static dbus_bool_t
byte_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
unsigned char v ;
v = BYTE_FROM_SEED ( seed ) ;
return _dbus_type_writer_write_basic ( writer ,
node - > klass - > typecode ,
& v ) ;
}
static dbus_bool_t
byte_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
unsigned char v ;
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_basic ( reader ,
( unsigned char * ) & v ) ;
_dbus_assert ( v = = BYTE_FROM_SEED ( seed ) ) ;
return TRUE ;
}
static dbus_bool_t
byte_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
unsigned char v ;
v = BYTE_FROM_SEED ( seed ) ;
return _dbus_type_reader_set_basic ( reader ,
& v ,
realign_root ) ;
}
static double
double_from_seed ( int seed )
{
return SAMPLE_INT32 * ( double ) seed + 0.3 ;
}
static dbus_bool_t
double_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
double v ;
v = double_from_seed ( seed ) ;
return _dbus_type_writer_write_basic ( writer ,
node - > klass - > typecode ,
& v ) ;
}
static dbus_bool_t
double_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
double v ;
double expected ;
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_basic ( reader ,
( double * ) & v ) ;
expected = double_from_seed ( seed ) ;
if ( ! _DBUS_DOUBLES_BITWISE_EQUAL ( v , expected ) )
{
# ifdef DBUS_HAVE_INT64
_dbus_warn ( " Expected double %g got %g \n bits = 0x%llx vs. \n bits = 0x%llx) \n " ,
expected , v ,
* ( dbus_uint64_t * ) ( char * ) & expected ,
* ( dbus_uint64_t * ) ( char * ) & v ) ;
# endif
_dbus_assert_not_reached ( " test failed " ) ;
}
return TRUE ;
}
static dbus_bool_t
double_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
double v ;
v = double_from_seed ( seed ) ;
return _dbus_type_reader_set_basic ( reader ,
& v ,
realign_root ) ;
}
# define MAX_SAMPLE_OBJECT_PATH_LEN 10
static void
object_path_from_seed ( char * buf ,
int seed )
{
int i ;
unsigned char v ;
int len ;
len = seed % 9 ;
_dbus_assert ( len < MAX_SAMPLE_OBJECT_PATH_LEN ) ;
v = ( unsigned char ) ( ' A ' + seed ) ;
2005-01-24 05:56:25 +00:00
if ( len < 2 )
2005-01-17 03:53:40 +00:00
{
2005-01-24 05:56:25 +00:00
buf [ 0 ] = ' / ' ;
i = 1 ;
}
else
{
i = 0 ;
while ( i + 1 < len )
{
if ( v < ' A ' | | v > ' z ' )
v = ' A ' ;
buf [ i ] = ' / ' ;
+ + i ;
buf [ i ] = v ;
+ + i ;
v + = 1 ;
}
2005-01-17 03:53:40 +00:00
}
buf [ i ] = ' \0 ' ;
}
static dbus_bool_t
object_path_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
2005-04-23 22:34:48 +00:00
char buf [ MAX_SAMPLE_OBJECT_PATH_LEN + 1 ] ;
2005-01-17 03:53:40 +00:00
const char * v_string = buf ;
object_path_from_seed ( buf , seed ) ;
return _dbus_type_writer_write_basic ( writer ,
node - > klass - > typecode ,
& v_string ) ;
}
static dbus_bool_t
object_path_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
const char * v ;
2005-04-23 22:34:48 +00:00
char buf [ MAX_SAMPLE_OBJECT_PATH_LEN + 1 ] ;
2005-01-17 03:53:40 +00:00
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_basic ( reader ,
( const char * * ) & v ) ;
object_path_from_seed ( buf , seed ) ;
if ( strcmp ( buf , v ) ! = 0 )
{
_dbus_warn ( " read object path '%s' expected '%s' \n " ,
v , buf ) ;
_dbus_assert_not_reached ( " test failed " ) ;
}
return TRUE ;
}
static dbus_bool_t
object_path_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
2005-04-23 22:34:48 +00:00
char buf [ MAX_SAMPLE_OBJECT_PATH_LEN + 1 ] ;
2005-01-17 03:53:40 +00:00
const char * v_string = buf ;
object_path_from_seed ( buf , seed ) ;
return _dbus_type_reader_set_basic ( reader ,
& v_string ,
realign_root ) ;
}
# define MAX_SAMPLE_SIGNATURE_LEN 10
static void
signature_from_seed ( char * buf ,
int seed )
{
/* try to avoid ascending, descending, or alternating length to help find bugs */
const char * sample_signatures [ ] = {
" asax "
" " ,
" asau(xxxx) " ,
" x " ,
" ai " ,
" a(ii) "
} ;
2005-04-23 22:34:48 +00:00
strcpy ( buf , sample_signatures [ seed % _DBUS_N_ELEMENTS ( sample_signatures ) ] ) ;
2005-01-17 03:53:40 +00:00
}
static dbus_bool_t
signature_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
2005-04-23 22:34:48 +00:00
char buf [ MAX_SAMPLE_SIGNATURE_LEN + 1 ] ;
2005-01-17 03:53:40 +00:00
const char * v_string = buf ;
signature_from_seed ( buf , seed ) ;
return _dbus_type_writer_write_basic ( writer ,
node - > klass - > typecode ,
& v_string ) ;
}
static dbus_bool_t
signature_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
const char * v ;
2005-04-23 22:34:48 +00:00
char buf [ MAX_SAMPLE_SIGNATURE_LEN + 1 ] ;
2005-01-17 03:53:40 +00:00
check_expected_type ( reader , node - > klass - > typecode ) ;
_dbus_type_reader_read_basic ( reader ,
( const char * * ) & v ) ;
signature_from_seed ( buf , seed ) ;
if ( strcmp ( buf , v ) ! = 0 )
{
_dbus_warn ( " read signature value '%s' expected '%s' \n " ,
v , buf ) ;
_dbus_assert_not_reached ( " test failed " ) ;
}
return TRUE ;
}
static dbus_bool_t
signature_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
2005-04-23 22:34:48 +00:00
char buf [ MAX_SAMPLE_SIGNATURE_LEN + 1 ] ;
2005-01-17 03:53:40 +00:00
const char * v_string = buf ;
signature_from_seed ( buf , seed ) ;
return _dbus_type_reader_set_basic ( reader ,
& v_string ,
realign_root ) ;
}
static dbus_bool_t
struct_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
DataBlockState saved ;
DBusTypeWriter sub ;
int i ;
int n_copies ;
n_copies = node - > klass - > subclass_detail ;
_dbus_assert ( container - > children ! = NULL ) ;
data_block_save ( block , & saved ) ;
if ( ! _dbus_type_writer_recurse ( writer , DBUS_TYPE_STRUCT ,
NULL , 0 ,
& sub ) )
return FALSE ;
i = 0 ;
while ( i < n_copies )
{
DBusList * link ;
link = _dbus_list_get_first_link ( & container - > children ) ;
while ( link ! = NULL )
{
TestTypeNode * child = link - > data ;
DBusList * next = _dbus_list_get_next_link ( & container - > children , link ) ;
if ( ! node_write_value ( child , block , & sub , seed + i ) )
{
data_block_restore ( block , & saved ) ;
return FALSE ;
}
link = next ;
}
+ + i ;
}
if ( ! _dbus_type_writer_unrecurse ( writer , & sub ) )
{
data_block_restore ( block , & saved ) ;
return FALSE ;
}
return TRUE ;
}
static dbus_bool_t
struct_read_or_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
DBusTypeReader sub ;
int i ;
int n_copies ;
n_copies = node - > klass - > subclass_detail ;
check_expected_type ( reader , DBUS_TYPE_STRUCT ) ;
_dbus_type_reader_recurse ( reader , & sub ) ;
i = 0 ;
while ( i < n_copies )
{
DBusList * link ;
link = _dbus_list_get_first_link ( & container - > children ) ;
while ( link ! = NULL )
{
TestTypeNode * child = link - > data ;
DBusList * next = _dbus_list_get_next_link ( & container - > children , link ) ;
if ( realign_root = = NULL )
{
if ( ! node_read_value ( child , & sub , seed + i ) )
return FALSE ;
}
else
{
if ( ! node_set_value ( child , & sub , realign_root , seed + i ) )
return FALSE ;
}
if ( i = = ( n_copies - 1 ) & & next = = NULL )
NEXT_EXPECTING_FALSE ( & sub ) ;
else
NEXT_EXPECTING_TRUE ( & sub ) ;
link = next ;
}
+ + i ;
}
return TRUE ;
}
static dbus_bool_t
struct_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
return struct_read_or_set_value ( node , reader , NULL , seed ) ;
}
static dbus_bool_t
struct_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
return struct_read_or_set_value ( node , reader , realign_root , seed ) ;
}
static dbus_bool_t
struct_build_signature ( TestTypeNode * node ,
DBusString * str )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
int i ;
int orig_len ;
int n_copies ;
n_copies = node - > klass - > subclass_detail ;
orig_len = _dbus_string_get_length ( str ) ;
if ( ! _dbus_string_append_byte ( str , DBUS_STRUCT_BEGIN_CHAR ) )
goto oom ;
i = 0 ;
while ( i < n_copies )
{
DBusList * link ;
link = _dbus_list_get_first_link ( & container - > children ) ;
while ( link ! = NULL )
{
TestTypeNode * child = link - > data ;
DBusList * next = _dbus_list_get_next_link ( & container - > children , link ) ;
if ( ! node_build_signature ( child , str ) )
goto oom ;
link = next ;
}
+ + i ;
}
if ( ! _dbus_string_append_byte ( str , DBUS_STRUCT_END_CHAR ) )
goto oom ;
return TRUE ;
oom :
_dbus_string_set_length ( str , orig_len ) ;
return FALSE ;
}
static dbus_bool_t
array_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
DataBlockState saved ;
DBusTypeWriter sub ;
DBusString element_signature ;
int i ;
int n_copies ;
int element_type ;
TestTypeNode * child ;
n_copies = node - > klass - > subclass_detail ;
_dbus_assert ( container - > children ! = NULL ) ;
data_block_save ( block , & saved ) ;
if ( ! _dbus_string_init ( & element_signature ) )
return FALSE ;
child = _dbus_list_get_first ( & container - > children ) ;
if ( ! node_build_signature ( child ,
& element_signature ) )
goto oom ;
2005-01-17 22:03:19 +00:00
element_type = _dbus_first_type_in_signature ( & element_signature , 0 ) ;
2005-01-17 03:53:40 +00:00
if ( ! _dbus_type_writer_recurse ( writer , DBUS_TYPE_ARRAY ,
& element_signature , 0 ,
& sub ) )
goto oom ;
if ( arrays_write_fixed_in_blocks & &
2005-03-09 17:09:11 +00:00
dbus_type_is_fixed ( element_type ) & &
2005-01-17 03:53:40 +00:00
child - > klass - > write_multi )
{
if ( ! node_write_multi ( child , block , & sub , seed , n_copies ) )
goto oom ;
}
else
{
i = 0 ;
while ( i < n_copies )
{
DBusList * link ;
link = _dbus_list_get_first_link ( & container - > children ) ;
while ( link ! = NULL )
{
TestTypeNode * child = link - > data ;
DBusList * next = _dbus_list_get_next_link ( & container - > children , link ) ;
if ( ! node_write_value ( child , block , & sub , seed + i ) )
goto oom ;
link = next ;
}
+ + i ;
}
}
if ( ! _dbus_type_writer_unrecurse ( writer , & sub ) )
goto oom ;
_dbus_string_free ( & element_signature ) ;
return TRUE ;
oom :
data_block_restore ( block , & saved ) ;
_dbus_string_free ( & element_signature ) ;
return FALSE ;
}
static dbus_bool_t
array_read_or_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
DBusTypeReader sub ;
int i ;
int n_copies ;
TestTypeNode * child ;
n_copies = node - > klass - > subclass_detail ;
check_expected_type ( reader , DBUS_TYPE_ARRAY ) ;
child = _dbus_list_get_first ( & container - > children ) ;
if ( n_copies > 0 )
{
_dbus_type_reader_recurse ( reader , & sub ) ;
if ( realign_root = = NULL & & arrays_write_fixed_in_blocks & &
2005-03-09 17:09:11 +00:00
dbus_type_is_fixed ( _dbus_type_reader_get_element_type ( reader ) ) & &
2005-01-17 03:53:40 +00:00
child - > klass - > read_multi )
{
if ( ! node_read_multi ( child , & sub , seed , n_copies ) )
return FALSE ;
}
else
{
i = 0 ;
while ( i < n_copies )
{
DBusList * link ;
link = _dbus_list_get_first_link ( & container - > children ) ;
while ( link ! = NULL )
{
TestTypeNode * child = link - > data ;
DBusList * next = _dbus_list_get_next_link ( & container - > children , link ) ;
_dbus_assert ( child - > klass - > typecode = =
_dbus_type_reader_get_element_type ( reader ) ) ;
if ( realign_root = = NULL )
{
if ( ! node_read_value ( child , & sub , seed + i ) )
return FALSE ;
}
else
{
if ( ! node_set_value ( child , & sub , realign_root , seed + i ) )
return FALSE ;
}
if ( i = = ( n_copies - 1 ) & & next = = NULL )
NEXT_EXPECTING_FALSE ( & sub ) ;
else
NEXT_EXPECTING_TRUE ( & sub ) ;
link = next ;
}
+ + i ;
}
}
}
return TRUE ;
}
static dbus_bool_t
array_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
return array_read_or_set_value ( node , reader , NULL , seed ) ;
}
static dbus_bool_t
array_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
return array_read_or_set_value ( node , reader , realign_root , seed ) ;
}
static dbus_bool_t
array_build_signature ( TestTypeNode * node ,
DBusString * str )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
int orig_len ;
orig_len = _dbus_string_get_length ( str ) ;
if ( ! _dbus_string_append_byte ( str , DBUS_TYPE_ARRAY ) )
goto oom ;
if ( ! node_build_signature ( _dbus_list_get_first ( & container - > children ) ,
str ) )
goto oom ;
return TRUE ;
oom :
_dbus_string_set_length ( str , orig_len ) ;
return FALSE ;
}
/* 10 is random just to add another seed that we use in the suite */
# define VARIANT_SEED 10
static dbus_bool_t
variant_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
DataBlockState saved ;
DBusTypeWriter sub ;
DBusString content_signature ;
TestTypeNode * child ;
_dbus_assert ( container - > children ! = NULL ) ;
_dbus_assert ( _dbus_list_length_is_one ( & container - > children ) ) ;
child = _dbus_list_get_first ( & container - > children ) ;
data_block_save ( block , & saved ) ;
if ( ! _dbus_string_init ( & content_signature ) )
return FALSE ;
if ( ! node_build_signature ( child ,
& content_signature ) )
goto oom ;
if ( ! _dbus_type_writer_recurse ( writer , DBUS_TYPE_VARIANT ,
& content_signature , 0 ,
& sub ) )
goto oom ;
if ( ! node_write_value ( child , block , & sub , seed + VARIANT_SEED ) )
goto oom ;
if ( ! _dbus_type_writer_unrecurse ( writer , & sub ) )
goto oom ;
_dbus_string_free ( & content_signature ) ;
return TRUE ;
oom :
data_block_restore ( block , & saved ) ;
_dbus_string_free ( & content_signature ) ;
return FALSE ;
}
static dbus_bool_t
variant_read_or_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
DBusTypeReader sub ;
TestTypeNode * child ;
_dbus_assert ( container - > children ! = NULL ) ;
_dbus_assert ( _dbus_list_length_is_one ( & container - > children ) ) ;
child = _dbus_list_get_first ( & container - > children ) ;
check_expected_type ( reader , DBUS_TYPE_VARIANT ) ;
_dbus_type_reader_recurse ( reader , & sub ) ;
if ( realign_root = = NULL )
{
if ( ! node_read_value ( child , & sub , seed + VARIANT_SEED ) )
return FALSE ;
}
else
{
if ( ! node_set_value ( child , & sub , realign_root , seed + VARIANT_SEED ) )
return FALSE ;
}
NEXT_EXPECTING_FALSE ( & sub ) ;
return TRUE ;
}
static dbus_bool_t
variant_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
return variant_read_or_set_value ( node , reader , NULL , seed ) ;
}
static dbus_bool_t
variant_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
return variant_read_or_set_value ( node , reader , realign_root , seed ) ;
}
2005-01-28 05:30:53 +00:00
static dbus_bool_t
dict_write_value ( TestTypeNode * node ,
DataBlock * block ,
DBusTypeWriter * writer ,
int seed )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
DataBlockState saved ;
DBusTypeWriter sub ;
DBusString entry_value_signature ;
DBusString dict_entry_signature ;
int i ;
int n_entries ;
int entry_value_type ;
TestTypeNode * child ;
n_entries = node - > klass - > subclass_detail ;
_dbus_assert ( container - > children ! = NULL ) ;
data_block_save ( block , & saved ) ;
if ( ! _dbus_string_init ( & entry_value_signature ) )
return FALSE ;
if ( ! _dbus_string_init ( & dict_entry_signature ) )
{
_dbus_string_free ( & entry_value_signature ) ;
return FALSE ;
}
child = _dbus_list_get_first ( & container - > children ) ;
if ( ! node_build_signature ( child ,
& entry_value_signature ) )
goto oom ;
if ( ! _dbus_string_append ( & dict_entry_signature ,
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
DBUS_TYPE_INT32_AS_STRING ) )
goto oom ;
if ( ! _dbus_string_copy ( & entry_value_signature , 0 ,
& dict_entry_signature ,
_dbus_string_get_length ( & dict_entry_signature ) ) )
goto oom ;
if ( ! _dbus_string_append_byte ( & dict_entry_signature ,
DBUS_DICT_ENTRY_END_CHAR ) )
goto oom ;
entry_value_type = _dbus_first_type_in_signature ( & entry_value_signature , 0 ) ;
if ( ! _dbus_type_writer_recurse ( writer , DBUS_TYPE_ARRAY ,
& dict_entry_signature , 0 ,
& sub ) )
goto oom ;
i = 0 ;
while ( i < n_entries )
{
DBusTypeWriter entry_sub ;
dbus_int32_t key ;
if ( ! _dbus_type_writer_recurse ( & sub , DBUS_TYPE_DICT_ENTRY ,
NULL , 0 ,
& entry_sub ) )
goto oom ;
key = int32_from_seed ( seed + i ) ;
if ( ! _dbus_type_writer_write_basic ( & entry_sub ,
DBUS_TYPE_INT32 ,
& key ) )
goto oom ;
if ( ! node_write_value ( child , block , & entry_sub , seed + i ) )
goto oom ;
if ( ! _dbus_type_writer_unrecurse ( & sub , & entry_sub ) )
goto oom ;
+ + i ;
}
if ( ! _dbus_type_writer_unrecurse ( writer , & sub ) )
goto oom ;
_dbus_string_free ( & entry_value_signature ) ;
_dbus_string_free ( & dict_entry_signature ) ;
return TRUE ;
oom :
data_block_restore ( block , & saved ) ;
_dbus_string_free ( & entry_value_signature ) ;
_dbus_string_free ( & dict_entry_signature ) ;
return FALSE ;
}
static dbus_bool_t
dict_read_or_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
DBusTypeReader sub ;
int i ;
int n_entries ;
TestTypeNode * child ;
n_entries = node - > klass - > subclass_detail ;
check_expected_type ( reader , DBUS_TYPE_ARRAY ) ;
child = _dbus_list_get_first ( & container - > children ) ;
if ( n_entries > 0 )
{
_dbus_type_reader_recurse ( reader , & sub ) ;
check_expected_type ( & sub , DBUS_TYPE_DICT_ENTRY ) ;
i = 0 ;
while ( i < n_entries )
{
DBusTypeReader entry_sub ;
check_expected_type ( & sub , DBUS_TYPE_DICT_ENTRY ) ;
_dbus_type_reader_recurse ( & sub , & entry_sub ) ;
if ( realign_root = = NULL )
{
dbus_int32_t v ;
check_expected_type ( & entry_sub , DBUS_TYPE_INT32 ) ;
_dbus_type_reader_read_basic ( & entry_sub ,
( dbus_int32_t * ) & v ) ;
_dbus_assert ( v = = int32_from_seed ( seed + i ) ) ;
NEXT_EXPECTING_TRUE ( & entry_sub ) ;
if ( ! node_read_value ( child , & entry_sub , seed + i ) )
return FALSE ;
NEXT_EXPECTING_FALSE ( & entry_sub ) ;
}
else
{
dbus_int32_t v ;
v = int32_from_seed ( seed + i ) ;
if ( ! _dbus_type_reader_set_basic ( & entry_sub ,
& v ,
realign_root ) )
return FALSE ;
NEXT_EXPECTING_TRUE ( & entry_sub ) ;
if ( ! node_set_value ( child , & entry_sub , realign_root , seed + i ) )
return FALSE ;
NEXT_EXPECTING_FALSE ( & entry_sub ) ;
}
if ( i = = ( n_entries - 1 ) )
NEXT_EXPECTING_FALSE ( & sub ) ;
else
NEXT_EXPECTING_TRUE ( & sub ) ;
+ + i ;
}
}
return TRUE ;
}
static dbus_bool_t
dict_read_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
int seed )
{
return dict_read_or_set_value ( node , reader , NULL , seed ) ;
}
static dbus_bool_t
dict_set_value ( TestTypeNode * node ,
DBusTypeReader * reader ,
DBusTypeReader * realign_root ,
int seed )
{
return dict_read_or_set_value ( node , reader , realign_root , seed ) ;
}
static dbus_bool_t
dict_build_signature ( TestTypeNode * node ,
DBusString * str )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
int orig_len ;
orig_len = _dbus_string_get_length ( str ) ;
if ( ! _dbus_string_append_byte ( str , DBUS_TYPE_ARRAY ) )
goto oom ;
if ( ! _dbus_string_append ( str , DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING ) )
goto oom ;
if ( ! node_build_signature ( _dbus_list_get_first ( & container - > children ) ,
str ) )
goto oom ;
if ( ! _dbus_string_append_byte ( str , DBUS_DICT_ENTRY_END_CHAR ) )
goto oom ;
return TRUE ;
oom :
_dbus_string_set_length ( str , orig_len ) ;
return FALSE ;
}
2005-01-17 03:53:40 +00:00
static void
container_destroy ( TestTypeNode * node )
{
TestTypeNodeContainer * container = ( TestTypeNodeContainer * ) node ;
DBusList * link ;
link = _dbus_list_get_first_link ( & container - > children ) ;
while ( link ! = NULL )
{
TestTypeNode * child = link - > data ;
DBusList * next = _dbus_list_get_next_link ( & container - > children , link ) ;
node_destroy ( child ) ;
_dbus_list_free_link ( link ) ;
link = next ;
}
}
# endif /* DBUS_BUILD_TESTS */