dbus/dbus Makefile.am, 1.62, 1.63 dbus-auth-util.c, NONE,
1.1 dbus-auth.c, 1.39, 1.40 dbus-hash.c, 1.18,
1.19 dbus-internals.c, 1.40, 1.41 dbus-internals.h, 1.49,
1.50 dbus-list.c, 1.19, 1.20 dbus-marshal-basic.c, 1.17,
1.18 dbus-marshal-basic.h, 1.14,
1.15 dbus-marshal-recursive-util.c, NONE,
1.1 dbus-marshal-recursive.c, 1.42,
1.43 dbus-message-builder.c, 1.26,
1.27 dbus-message-internal.h, 1.19,
1.20 dbus-message-private.h, NONE, 1.1 dbus-message-util.c,
NONE, 1.1 dbus-message.c, 1.149, 1.150 dbus-string-private.h,
1.4, 1.5 dbus-string-util.c, NONE, 1.1 dbus-string.c, 1.63,
1.64 dbus-string.h, 1.36, 1.37 dbus-sysdeps-util.c, NONE,
1.1 dbus-sysdeps.c, 1.87, 1.88 dbus-userdb-util.c, 1.1,
1.2 dbus-userdb.c, 1.13, 1.14
Havoc Pennington
hp@freedesktop.org
Sun Jan 16 19:53:42 PST 2005
Update of /cvs/dbus/dbus/dbus
In directory gabe:/tmp/cvs-serv15337/dbus
Modified Files:
Makefile.am dbus-auth.c dbus-hash.c dbus-internals.c
dbus-internals.h dbus-list.c dbus-marshal-basic.c
dbus-marshal-basic.h dbus-marshal-recursive.c
dbus-message-builder.c dbus-message-internal.h dbus-message.c
dbus-string-private.h dbus-string.c dbus-string.h
dbus-sysdeps.c dbus-userdb-util.c dbus-userdb.c
Added Files:
dbus-auth-util.c dbus-marshal-recursive-util.c
dbus-message-private.h dbus-message-util.c dbus-string-util.c
dbus-sysdeps-util.c
Log Message:
2005-01-16 Havoc Pennington <hp@redhat.com>
This is about it on what can be disabled/deleted from libdbus
easily, back below 150K anyhow. Deeper cuts are more work than
just turning the code off as I've done here.
* dbus/dbus-marshal-basic.c (_dbus_pack_int32): we don't need the
signed int convenience funcs
* dbus/dbus-internals.c (_dbus_verbose_real): omit when not in
verbose mode
* dbus/dbus-string-util.c, dbus/dbus-string.c: more breaking
things out of libdbus
* dbus/dbus-sysdeps.c, dbus/dbus-sysdeps-util.c: same
* dbus/dbus-hash.c: purge the TWO_STRINGS crap (well, make it
tests-enabled-only, though it should probably be deleted)
* dbus/dbus-message-util.c: same stuff
* dbus/dbus-auth-util.c: same stuff
Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/dbus/Makefile.am,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -d -r1.62 -r1.63
--- Makefile.am 17 Jan 2005 01:20:02 -0000 1.62
+++ Makefile.am 17 Jan 2005 03:53:40 -0000 1.63
@@ -62,15 +62,16 @@
dbus-marshal-validate.h \
dbus-message.c \
dbus-message-internal.h \
+ dbus-message-private.h \
dbus-object-tree.c \
dbus-object-tree.h \
dbus-pending-call.c \
dbus-resources.c \
dbus-resources.h \
dbus-server.c \
- dbus-server-protected.h \
dbus-server-debug-pipe.c \
dbus-server-debug-pipe.h \
+ dbus-server-protected.h \
dbus-server-unix.c \
dbus-server-unix.h \
dbus-sha.c \
@@ -121,16 +122,18 @@
### should be underscore-prefixed but don't really need
### to be unless they move to DBUS_SHARED_SOURCES later)
DBUS_UTIL_SOURCES= \
+ dbus-auth-util.c \
dbus-mainloop.c \
dbus-mainloop.h \
+ dbus-marshal-recursive-util.c \
+ dbus-message-util.c \
dbus-spawn.c \
dbus-spawn.h \
+ dbus-string-util.c \
dbus-sysdeps-util.c \
- dbus-sysdeps-util.h \
dbus-test.c \
dbus-test.h \
- dbus-userdb-util.c \
- dbus-userdb-util.h
+ dbus-userdb-util.c
libdbus_1_la_SOURCES= \
$(DBUS_LIB_SOURCES) \
--- NEW FILE: dbus-auth-util.c ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-auth-util.c Would be in dbus-auth.c, but only used for tests/bus
*
* Copyright (C) 2002, 2003, 2004 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
*
*/
#include "dbus-internals.h"
#include "dbus-test.h"
#include "dbus-auth.h"
/**
* @addtogroup DBusAuth
* @{
*/
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include "dbus-auth-script.h"
#include <stdio.h>
static dbus_bool_t
process_test_subdir (const DBusString *test_base_dir,
const char *subdir)
{
DBusString test_directory;
DBusString filename;
DBusDirIter *dir;
dbus_bool_t retval;
DBusError error;
retval = FALSE;
dir = NULL;
if (!_dbus_string_init (&test_directory))
_dbus_assert_not_reached ("didn't allocate test_directory\n");
_dbus_string_init_const (&filename, subdir);
if (!_dbus_string_copy (test_base_dir, 0,
&test_directory, 0))
_dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
if (!_dbus_concat_dir_and_file (&test_directory, &filename))
_dbus_assert_not_reached ("couldn't allocate full path");
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename))
_dbus_assert_not_reached ("didn't allocate filename string\n");
dbus_error_init (&error);
dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
_dbus_warn ("Could not open %s: %s\n",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
goto failed;
}
printf ("Testing %s:\n", subdir);
next:
while (_dbus_directory_get_next_file (dir, &filename, &error))
{
DBusString full_path;
if (!_dbus_string_init (&full_path))
_dbus_assert_not_reached ("couldn't init string");
if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
_dbus_assert_not_reached ("couldn't copy dir to full_path");
if (!_dbus_concat_dir_and_file (&full_path, &filename))
_dbus_assert_not_reached ("couldn't concat file to dir");
if (!_dbus_string_ends_with_c_str (&filename, ".auth-script"))
{
_dbus_verbose ("Skipping non-.auth-script file %s\n",
_dbus_string_get_const_data (&filename));
_dbus_string_free (&full_path);
goto next;
}
printf (" %s\n", _dbus_string_get_const_data (&filename));
if (!_dbus_auth_script_run (&full_path))
{
_dbus_string_free (&full_path);
goto failed;
}
else
_dbus_string_free (&full_path);
}
if (dbus_error_is_set (&error))
{
_dbus_warn ("Could not get next file in %s: %s\n",
_dbus_string_get_const_data (&test_directory), error.message);
dbus_error_free (&error);
goto failed;
}
retval = TRUE;
failed:
if (dir)
_dbus_directory_close (dir);
_dbus_string_free (&test_directory);
_dbus_string_free (&filename);
return retval;
}
static dbus_bool_t
process_test_dirs (const char *test_data_dir)
{
DBusString test_directory;
dbus_bool_t retval;
retval = FALSE;
_dbus_string_init_const (&test_directory, test_data_dir);
if (!process_test_subdir (&test_directory, "auth"))
goto failed;
retval = TRUE;
failed:
_dbus_string_free (&test_directory);
return retval;
}
dbus_bool_t
_dbus_auth_test (const char *test_data_dir)
{
if (test_data_dir == NULL)
return TRUE;
if (!process_test_dirs (test_data_dir))
return FALSE;
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */
Index: dbus-auth.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-auth.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- dbus-auth.c 17 Jan 2005 01:20:02 -0000 1.39
+++ dbus-auth.c 17 Jan 2005 03:53:40 -0000 1.40
@@ -2392,139 +2392,4 @@
/** @} */
-#ifdef DBUS_BUILD_TESTS
-#include "dbus-test.h"
-#include "dbus-auth-script.h"
-#include <stdio.h>
-
-static dbus_bool_t
-process_test_subdir (const DBusString *test_base_dir,
- const char *subdir)
-{
- DBusString test_directory;
- DBusString filename;
- DBusDirIter *dir;
- dbus_bool_t retval;
- DBusError error;
-
- retval = FALSE;
- dir = NULL;
-
- if (!_dbus_string_init (&test_directory))
- _dbus_assert_not_reached ("didn't allocate test_directory\n");
-
- _dbus_string_init_const (&filename, subdir);
-
- if (!_dbus_string_copy (test_base_dir, 0,
- &test_directory, 0))
- _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
-
- if (!_dbus_concat_dir_and_file (&test_directory, &filename))
- _dbus_assert_not_reached ("couldn't allocate full path");
-
- _dbus_string_free (&filename);
- if (!_dbus_string_init (&filename))
- _dbus_assert_not_reached ("didn't allocate filename string\n");
-
- dbus_error_init (&error);
- dir = _dbus_directory_open (&test_directory, &error);
- if (dir == NULL)
- {
- _dbus_warn ("Could not open %s: %s\n",
- _dbus_string_get_const_data (&test_directory),
- error.message);
- dbus_error_free (&error);
- goto failed;
- }
-
- printf ("Testing %s:\n", subdir);
-
- next:
- while (_dbus_directory_get_next_file (dir, &filename, &error))
- {
- DBusString full_path;
-
- if (!_dbus_string_init (&full_path))
- _dbus_assert_not_reached ("couldn't init string");
-
- if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
- _dbus_assert_not_reached ("couldn't copy dir to full_path");
-
- if (!_dbus_concat_dir_and_file (&full_path, &filename))
- _dbus_assert_not_reached ("couldn't concat file to dir");
-
- if (!_dbus_string_ends_with_c_str (&filename, ".auth-script"))
- {
- _dbus_verbose ("Skipping non-.auth-script file %s\n",
- _dbus_string_get_const_data (&filename));
- _dbus_string_free (&full_path);
- goto next;
- }
-
- printf (" %s\n", _dbus_string_get_const_data (&filename));
-
- if (!_dbus_auth_script_run (&full_path))
- {
- _dbus_string_free (&full_path);
- goto failed;
- }
- else
- _dbus_string_free (&full_path);
- }
-
- if (dbus_error_is_set (&error))
- {
- _dbus_warn ("Could not get next file in %s: %s\n",
- _dbus_string_get_const_data (&test_directory), error.message);
- dbus_error_free (&error);
- goto failed;
- }
-
- retval = TRUE;
-
- failed:
-
- if (dir)
- _dbus_directory_close (dir);
- _dbus_string_free (&test_directory);
- _dbus_string_free (&filename);
-
- return retval;
-}
-
-static dbus_bool_t
-process_test_dirs (const char *test_data_dir)
-{
- DBusString test_directory;
- dbus_bool_t retval;
-
- retval = FALSE;
-
- _dbus_string_init_const (&test_directory, test_data_dir);
-
- if (!process_test_subdir (&test_directory, "auth"))
- goto failed;
-
- retval = TRUE;
-
- failed:
-
- _dbus_string_free (&test_directory);
-
- return retval;
-}
-
-dbus_bool_t
-_dbus_auth_test (const char *test_data_dir)
-{
-
- if (test_data_dir == NULL)
- return TRUE;
-
- if (!process_test_dirs (test_data_dir))
- return FALSE;
-
- return TRUE;
-}
-
-#endif /* DBUS_BUILD_TESTS */
+/* tests in dbus-auth-util.c */
Index: dbus-hash.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-hash.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- dbus-hash.c 10 Aug 2004 03:06:59 -0000 1.18
+++ dbus-hash.c 17 Jan 2005 03:53:40 -0000 1.19
@@ -231,13 +231,17 @@
dbus_bool_t create_if_not_found,
DBusHashEntry ***bucket,
DBusPreallocatedHash *preallocated);
+#ifdef DBUS_BUILD_TESTS
static DBusHashEntry* find_two_strings_function (DBusHashTable *table,
void *key,
dbus_bool_t create_if_not_found,
DBusHashEntry ***bucket,
DBusPreallocatedHash *preallocated);
+#endif
static unsigned int string_hash (const char *str);
+#ifdef DBUS_BUILD_TESTS
static unsigned int two_strings_hash (const char *str);
+#endif
static void rebuild_table (DBusHashTable *table);
static DBusHashEntry* alloc_entry (DBusHashTable *table);
static void remove_entry (DBusHashTable *table,
@@ -330,7 +334,9 @@
table->find_function = find_string_function;
break;
case DBUS_HASH_TWO_STRINGS:
+#ifdef DBUS_BUILD_TESTS
table->find_function = find_two_strings_function;
+#endif
break;
default:
_dbus_assert_not_reached ("Unknown hash table type");
@@ -696,6 +702,7 @@
return real->entry->key;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Gets the key for the current entry.
* Only works for hash tables of type #DBUS_HASH_TWO_STRINGS
@@ -713,6 +720,7 @@
return real->entry->key;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* A low-level but efficient interface for manipulating the hash
@@ -849,6 +857,7 @@
return h;
}
+#ifdef DBUS_BUILD_TESTS
/* This hashes a memory block with two nul-terminated strings
* in it, used in dbus-object-registry.c at the moment.
*/
@@ -867,6 +876,7 @@
return h;
}
+#endif /* DBUS_BUILD_TESTS */
/** Key comparison function */
typedef int (* KeyCompareFunc) (const void *key_a, const void *key_b);
@@ -928,6 +938,7 @@
preallocated);
}
+#ifdef DBUS_BUILD_TESTS
static int
two_strings_cmp (const char *a,
const char *b)
@@ -945,7 +956,9 @@
return strcmp (a + len_a + 1, b + len_b + 1);
}
+#endif
+#ifdef DBUS_BUILD_TESTS
static DBusHashEntry*
find_two_strings_function (DBusHashTable *table,
void *key,
@@ -961,6 +974,7 @@
(KeyCompareFunc) two_strings_cmp, create_if_not_found, bucket,
preallocated);
}
+#endif /* DBUS_BUILD_TESTS */
static DBusHashEntry*
find_direct_function (DBusHashTable *table,
@@ -1077,7 +1091,12 @@
idx = string_hash (entry->key) & table->mask;
break;
case DBUS_HASH_TWO_STRINGS:
+#ifdef DBUS_BUILD_TESTS
idx = two_strings_hash (entry->key) & table->mask;
+#else
+ idx = 0;
+ _dbus_assert_not_reached ("two-strings is not enabled");
+#endif
break;
case DBUS_HASH_INT:
case DBUS_HASH_ULONG:
@@ -1127,6 +1146,7 @@
return NULL;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Looks up the value for a given string in a hash table
* of type #DBUS_HASH_TWO_STRINGS. Returns %NULL if the value
@@ -1151,6 +1171,7 @@
else
return NULL;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Looks up the value for a given integer in a hash table
@@ -1258,6 +1279,7 @@
return FALSE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Removes the hash entry for the given key. If no hash entry
* for the key exists, does nothing.
@@ -1285,6 +1307,7 @@
else
return FALSE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Removes the hash entry for the given key. If no hash entry
@@ -1407,6 +1430,7 @@
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Creates a hash entry with the given key and value.
* The key and value are not copied; they are stored
@@ -1447,6 +1471,7 @@
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Creates a hash entry with the given key and value.
Index: dbus-internals.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-internals.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- dbus-internals.c 17 Jan 2005 00:16:28 -0000 1.40
+++ dbus-internals.c 17 Jan 2005 03:53:40 -0000 1.41
@@ -174,6 +174,8 @@
va_end (args);
}
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+
static dbus_bool_t verbose_initted = FALSE;
/**
@@ -238,6 +240,8 @@
verbose_initted = FALSE;
}
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+
/**
* Duplicates a string. Result must be freed with
* dbus_free(). Returns #NULL if memory allocation fails.
@@ -354,6 +358,7 @@
return FALSE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Returns a string describing the given name.
*
@@ -387,6 +392,7 @@
return "unknown";
}
}
+#endif /* DBUS_BUILD_TESTS */
#ifndef DBUS_DISABLE_CHECKS
/** String used in _dbus_return_if_fail macro */
Index: dbus-internals.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-internals.h,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- dbus-internals.h 17 Jan 2005 00:16:28 -0000 1.49
+++ dbus-internals.h 17 Jan 2005 03:53:40 -0000 1.50
@@ -39,9 +39,6 @@
void _dbus_warn (const char *format,
...) _DBUS_GNUC_PRINTF (1, 2);
-void _dbus_verbose_real (const char *format,
- ...) _DBUS_GNUC_PRINTF (1, 2);
-void _dbus_verbose_reset_real (void);
#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define _DBUS_FUNCTION_NAME __func__
@@ -79,6 +76,11 @@
#endif
#ifdef DBUS_ENABLE_VERBOSE_MODE
+
+void _dbus_verbose_real (const char *format,
+ ...) _DBUS_GNUC_PRINTF (1, 2);
+void _dbus_verbose_reset_real (void);
+
# define _dbus_verbose _dbus_verbose_real
# define _dbus_verbose_reset _dbus_verbose_reset_real
#else
Index: dbus-list.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-list.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- dbus-list.c 10 Aug 2004 03:06:59 -0000 1.19
+++ dbus-list.c 17 Jan 2005 03:53:40 -0000 1.20
@@ -126,6 +126,7 @@
}
}
+#ifdef DBUS_BUILD_TESTS
static void
link_after (DBusList **list,
DBusList *after_this_link,
@@ -145,6 +146,7 @@
link->next->prev = link;
}
}
+#endif /* DBUS_BUILD_TESTS */
/** @} */
@@ -313,6 +315,7 @@
link_before (list, *list, link);
}
+#ifdef DBUS_BUILD_TESTS
/**
* Inserts data into the list before the given existing link.
*
@@ -341,7 +344,9 @@
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
+#ifdef DBUS_BUILD_TESTS
/**
* Inserts data into the list after the given existing link.
*
@@ -370,6 +375,7 @@
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Inserts a link into the list before the given existing link.
@@ -389,6 +395,7 @@
link_before (list, before_this_link, link);
}
+#ifdef DBUS_BUILD_TESTS
/**
* Inserts a link into the list after the given existing link.
*
@@ -406,6 +413,7 @@
else
link_after (list, after_this_link, link);
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Removes a value from the list. Only removes the
@@ -690,6 +698,7 @@
return data;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Removes the last link in the list and returns it. This is a
* constant-time operation.
@@ -710,6 +719,7 @@
return link;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Copies a list. This is a linear-time operation. If there isn't
Index: dbus-marshal-basic.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-marshal-basic.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- dbus-marshal-basic.c 17 Jan 2005 00:16:28 -0000 1.17
+++ dbus-marshal-basic.c 17 Jan 2005 03:53:40 -0000 1.18
@@ -88,21 +88,6 @@
pack_4_octets (value, byte_order, data);
}
-/**
- * Packs a 32 bit signed integer into a data pointer.
- *
- * @param value the value
- * @param byte_order the byte order to use
- * @param data the data pointer
- */
-void
-_dbus_pack_int32 (dbus_int32_t value,
- int byte_order,
- unsigned char *data)
-{
- pack_4_octets ((dbus_uint32_t) value, byte_order, data);
-}
-
#ifndef DBUS_HAVE_INT64
/* from ORBit */
static void
@@ -183,20 +168,6 @@
}
#endif /* _dbus_unpack_uint32 */
-/**
- * Unpacks a 32 bit signed integer from a data pointer
- *
- * @param byte_order The byte order to use
- * @param data the data pointer
- * @returns the integer
- */
-dbus_int32_t
-_dbus_unpack_int32 (int byte_order,
- const unsigned char *data)
-{
- return (dbus_int32_t) _dbus_unpack_uint32 (byte_order, data);
-}
-
static void
set_4_octets (DBusString *str,
int offset,
Index: dbus-marshal-basic.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-marshal-basic.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- dbus-marshal-basic.h 16 Jan 2005 15:51:55 -0000 1.14
+++ dbus-marshal-basic.h 17 Jan 2005 03:53:40 -0000 1.15
@@ -152,11 +152,6 @@
DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)(data)))
#endif
-void _dbus_pack_int32 (dbus_int32_t value,
- int byte_order,
- unsigned char *data);
-dbus_int32_t _dbus_unpack_int32 (int byte_order,
- const unsigned char *data);
void _dbus_pack_uint32 (dbus_uint32_t value,
int byte_order,
unsigned char *data);
--- NEW FILE: dbus-marshal-recursive-util.c ---
/* -*- 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
*
*/
#include "dbus-marshal-recursive.h"
#include "dbus-marshal-basic.h"
#include "dbus-internals.h"
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include "dbus-list.h"
#include <stdio.h>
#include <stdlib.h>
static int
first_type_in_signature (const DBusString *str,
int pos)
{
unsigned char t;
t = _dbus_string_get_byte (str, pos);
if (t == DBUS_STRUCT_BEGIN_CHAR)
return DBUS_TYPE_STRUCT;
else
return t;
}
/* 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 10x 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.
*/
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);
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);
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
};
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[] = {
&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,
&variant_class
/* 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 = █
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;
}
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
#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)
{
char buf[MAX_SAMPLE_STRING_LEN];
const char *v_string = buf;
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;
char buf[MAX_SAMPLE_STRING_LEN];
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)
{
char buf[MAX_SAMPLE_STRING_LEN];
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);
}
#define BOOL_FROM_SEED(seed) (seed % 2)
static dbus_bool_t
bool_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
int seed)
{
unsigned char v;
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)
{
unsigned char v;
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)
{
unsigned char v;
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);
i = 0;
while (i + 1 < len)
{
if (v < 'A' || v > 'z')
v = 'A';
buf[i] = '/';
++i;
buf[i] = v;
++i;
v += 1;
}
buf[i] = '\0';
}
static dbus_bool_t
object_path_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
int seed)
{
char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
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;
char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
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)
{
char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
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)
{
int i;
const char *s;
/* try to avoid ascending, descending, or alternating length to help find bugs */
const char *sample_signatures[] = {
"asax"
"",
"asau(xxxx)",
"x",
"ai",
"a(ii)"
};
s = sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)];
for (i = 0; s[i]; i++)
{
buf[i] = s[i];
}
buf[i] = '\0';
}
static dbus_bool_t
signature_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
int seed)
{
char buf[MAX_SAMPLE_SIGNATURE_LEN];
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;
char buf[MAX_SAMPLE_SIGNATURE_LEN];
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)
{
char buf[MAX_SAMPLE_SIGNATURE_LEN];
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;
element_type = first_type_in_signature (&element_signature, 0);
if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
&element_signature, 0,
&sub))
goto oom;
if (arrays_write_fixed_in_blocks &&
_dbus_type_is_fixed (element_type) &&
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 &&
_dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
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);
}
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 */
Index: dbus-marshal-recursive.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-marshal-recursive.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- dbus-marshal-recursive.c 17 Jan 2005 00:16:28 -0000 1.42
+++ dbus-marshal-recursive.c 17 Jan 2005 03:53:40 -0000 1.43
@@ -2710,2925 +2710,4 @@
/** @} */ /* end of DBusMarshal group */
-#ifdef DBUS_BUILD_TESTS
-#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 10x 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.
- */
-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);
-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);
-
-
-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
-};
-
-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[] = {
- &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,
- &variant_class
- /* 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 = █
- 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;
-}
-
-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
-
-
-#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 (_dbus_unpack_int32 (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)
-{
- char buf[MAX_SAMPLE_STRING_LEN];
- const char *v_string = buf;
-
- 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;
- char buf[MAX_SAMPLE_STRING_LEN];
-
- 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)
-{
- char buf[MAX_SAMPLE_STRING_LEN];
- 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);
-}
-
-#define BOOL_FROM_SEED(seed) (seed % 2)
-
-static dbus_bool_t
-bool_write_value (TestTypeNode *node,
- DataBlock *block,
- DBusTypeWriter *writer,
- int seed)
-{
- unsigned char v;
-
- 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)
-{
- unsigned char v;
-
- 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)
-{
- unsigned char v;
-
- 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);
-
- i = 0;
- while (i + 1 < len)
- {
- if (v < 'A' || v > 'z')
- v = 'A';
-
- buf[i] = '/';
- ++i;
- buf[i] = v;
- ++i;
-
- v += 1;
- }
-
- buf[i] = '\0';
-}
-
-static dbus_bool_t
-object_path_write_value (TestTypeNode *node,
- DataBlock *block,
- DBusTypeWriter *writer,
- int seed)
-{
- char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
- 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;
- char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
-
- 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)
-{
- char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
- 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)
-{
- int i;
- const char *s;
- /* try to avoid ascending, descending, or alternating length to help find bugs */
- const char *sample_signatures[] = {
- "asax"
- "",
- "asau(xxxx)",
- "x",
- "ai",
- "a(ii)"
- };
-
- s = sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)];
-
- for (i = 0; s[i]; i++)
- {
- buf[i] = s[i];
- }
- buf[i] = '\0';
-}
-
-static dbus_bool_t
-signature_write_value (TestTypeNode *node,
- DataBlock *block,
- DBusTypeWriter *writer,
- int seed)
-{
- char buf[MAX_SAMPLE_SIGNATURE_LEN];
- 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;
- char buf[MAX_SAMPLE_SIGNATURE_LEN];
-
- 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)
-{
- char buf[MAX_SAMPLE_SIGNATURE_LEN];
- 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;
-
- element_type = first_type_in_signature (&element_signature, 0);
-
- if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
- &element_signature, 0,
- &sub))
- goto oom;
-
- if (arrays_write_fixed_in_blocks &&
- _dbus_type_is_fixed (element_type) &&
- 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 &&
- _dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
- 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);
-}
-
-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 */
+/* tests in dbus-marshal-recursive-util.c */
Index: dbus-message-builder.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message-builder.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- dbus-message-builder.c 15 Jan 2005 07:15:38 -0000 1.26
+++ dbus-message-builder.c 17 Jan 2005 03:53:40 -0000 1.27
@@ -335,6 +335,115 @@
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
+/**
+ * Parses a basic type defined by type contained in a DBusString. The
+ * end_return parameter may be #NULL if you aren't interested in it. The
+ * type is parsed and stored in value_return. Return parameters are not
+ * initialized if the function returns #FALSE.
+ *
+ * @param str the string
+ * @param type the type of the basic type
+ * @param start the byte index of the start of the type
+ * @param value_return return location of the value or #NULL
+ * @param end_return return location of the end of the type, or #NULL
+ * @returns #TRUE on success
+ */
+static dbus_bool_t
+_dbus_string_parse_basic_type (const DBusString *str,
+ char type,
+ int start,
+ void *value,
+ int *end_return)
+{
+ int end = start;
+
+ switch (type)
+ {
+ case DBUS_TYPE_BOOLEAN:
+ {
+ int len = _dbus_string_get_length (str) - start;
+ if (len >= 5 && _dbus_string_find_to (str, start, start + 5, "false", NULL))
+ {
+ end += 5;
+ *(unsigned char *) value = TRUE;
+ }
+ else if (len >= 4 && _dbus_string_find_to (str, start, start + 4, "true", NULL))
+ {
+ end += 4;
+ *(unsigned char *) value = FALSE;
+ }
+ else
+ _dbus_warn ("could not parse BOOLEAN\n");
+ break;
+ }
+ case DBUS_TYPE_BYTE:
+ {
+ long val = 0;
+
+ if (_dbus_string_get_byte (str, start) == '\'' &&
+ _dbus_string_get_length (str) >= start + 4 &&
+ _dbus_string_get_byte (str, start + 1) == '\\' &&
+ _dbus_string_get_byte (str, start + 2) == '\'' &&
+ _dbus_string_get_byte (str, start + 3) == '\'')
+ {
+ val = '\'';
+ end += 4;
+ }
+ else if (_dbus_string_get_byte (str, start) == '\'' &&
+ _dbus_string_get_length (str) >= start + 3 &&
+ _dbus_string_get_byte (str, start + 2) == '\'')
+ {
+ val = _dbus_string_get_byte (str, start + 1);
+ end += 3;
+ }
+ else
+ {
+ if (!_dbus_string_parse_int (str, start, &val, &end))
+ _dbus_warn ("Failed to parse integer for BYTE\n");
+ }
+
+ if (val > 255)
+ _dbus_warn ("A byte must be in range 0-255 not %ld\n", val);
+
+ *(unsigned char *) value = val;
+ break;
+ }
+ case DBUS_TYPE_INT32:
+ {
+ long val;
+ if (_dbus_string_parse_int (str, start, &val, &end))
+ *(dbus_int32_t *)value = val;
+ break;
+ }
+ case DBUS_TYPE_UINT32:
+ {
+ unsigned long val;
+ if (_dbus_string_parse_uint (str, start, &val, &end))
+ *(dbus_uint32_t *)value = val;
+ break;
+ }
+#ifdef DBUS_HAVE_INT64
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ /* use stroll oull */
+ _dbus_assert_not_reached ("string -> [u]int64 not supported yet");
+ break;
+#endif /* DBUS_HAVE_INT64 */
+ case DBUS_TYPE_DOUBLE:
+ _dbus_string_parse_double (str, start, value, &end);
+ break;
+ default:
+ _dbus_assert_not_reached ("not a basic type");
+ break;
+ }
+ if (end_return)
+ *end_return = end;
+
+ return end != start;
+}
+#endif /* DBUS_BUILD_TESTS */
+
static dbus_bool_t
parse_basic_type (DBusString *src, char type,
DBusString *dest, dbus_bool_t *unalign,
Index: dbus-message-internal.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message-internal.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- dbus-message-internal.h 15 Jan 2005 07:15:38 -0000 1.19
+++ dbus-message-internal.h 17 Jan 2005 03:53:40 -0000 1.20
@@ -71,4 +71,4 @@
DBUS_END_DECLS
-#endif /* DBUS_MESSAGE_H */
+#endif /* DBUS_MESSAGE_INTERNAL_H */
--- NEW FILE: dbus-message-private.h ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-message-private.h header shared between dbus-message.c and dbus-message-util.c
*
* Copyright (C) 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
*
*/
#ifndef DBUS_MESSAGE_PRIVATE_H
#define DBUS_MESSAGE_PRIVATE_H
#include <dbus/dbus-message.h>
#include <dbus/dbus-message-internal.h>
#include <dbus/dbus-string.h>
#include <dbus/dbus-dataslot.h>
#include <dbus/dbus-marshal-header.h>
DBUS_BEGIN_DECLS
/**
* @addtogroup DBusMessageInternals
* @{
*/
/**
* @typedef DBusMessageLoader
*
* The DBusMessageLoader object encapsulates the process of converting
* a byte stream into a series of DBusMessage. It buffers the incoming
* bytes as efficiently as possible, and generates a queue of
* messages. DBusMessageLoader is typically used as part of a
* DBusTransport implementation. The DBusTransport then hands off
* the loaded messages to a DBusConnection, making the messages
* visible to the application.
*
* @todo write tests for break-loader that a) randomly delete header
* fields and b) set string fields to zero-length and other funky
* values.
*
*/
/**
* Implementation details of DBusMessageLoader.
* All members are private.
*/
struct DBusMessageLoader
{
int refcount; /**< Reference count. */
DBusString data; /**< Buffered data */
DBusList *messages; /**< Complete messages. */
long max_message_size; /**< Maximum size of a message */
unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
};
/** How many bits are in the changed_stamp used to validate iterators */
#define CHANGED_STAMP_BITS 21
/**
* @brief Internals of DBusMessage
*
* Object representing a message received from or to be sent to
* another application. This is an opaque object, all members
* are private.
*/
struct DBusMessage
{
DBusAtomic refcount; /**< Reference count */
DBusHeader header; /**< Header network data and associated cache */
DBusString body; /**< Body network data. */
char byte_order; /**< Message byte order. */
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
DBusList *size_counters; /**< 0-N DBusCounter used to track message size. */
long size_counter_delta; /**< Size we incremented the size counters by. */
dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; /**< Incremented when iterators are invalidated. */
DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */
#ifndef DBUS_DISABLE_CHECKS
int generation; /**< _dbus_current_generation when message was created */
#endif
};
dbus_bool_t _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
DBusError *error,
int first_arg_type,
va_list var_args);
/** @} */
DBUS_END_DECLS
#endif /* DBUS_MESSAGE_H */
--- NEW FILE: dbus-message-util.c ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-message-util.c Would be in dbus-message.c, but only used by bus/tests
*
* Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
* Copyright (C) 2002, 2003 CodeFactory AB
*
* 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
*
*/
#include "dbus-internals.h"
#include "dbus-test.h"
#include "dbus-message-private.h"
#include "dbus-marshal-recursive.h"
#include "dbus-string.h"
/**
* @addtogroup DBusMessage
* @{
*/
#ifdef DBUS_BUILD_TESTS
/**
* Reads arguments from a message iterator given a variable argument
* list. Only arguments of basic type and arrays of fixed-length
* basic type may be read with this function. See
* dbus_message_get_args() for more details.
*
* @todo this is static for now because there's no corresponding
* iter_append_args() and I'm not sure we need this function to be
* public since dbus_message_get_args() is what you usually want
*
* @param iter the message iterator
* @param error error to be filled in on failure
* @param first_arg_type the first argument type
* @param ... location for first argument value, then list of type-location pairs
* @returns #FALSE if the error was set
*/
static dbus_bool_t
dbus_message_iter_get_args (DBusMessageIter *iter,
DBusError *error,
int first_arg_type,
...)
{
dbus_bool_t retval;
va_list var_args;
_dbus_return_val_if_fail (iter != NULL, FALSE);
_dbus_return_val_if_error_is_set (error, FALSE);
va_start (var_args, first_arg_type);
retval = _dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
va_end (var_args);
return retval;
}
#endif /* DBUS_BUILD_TESTS */
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include <stdio.h>
#include <stdlib.h>
static dbus_bool_t
check_have_valid_message (DBusMessageLoader *loader)
{
DBusMessage *message;
dbus_bool_t retval;
message = NULL;
retval = FALSE;
if (!_dbus_message_loader_queue_messages (loader))
_dbus_assert_not_reached ("no memory to queue messages");
if (_dbus_message_loader_get_is_corrupted (loader))
{
_dbus_warn ("loader corrupted on message that was expected to be valid\n");
goto failed;
}
message = _dbus_message_loader_pop_message (loader);
if (message == NULL)
{
_dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
goto failed;
}
if (_dbus_string_get_length (&loader->data) > 0)
{
_dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
goto failed;
}
#if 0
/* FIXME */
/* Verify that we're able to properly deal with the message.
* For example, this would detect improper handling of messages
* in nonstandard byte order.
*/
if (!check_message_handling (message))
goto failed;
#endif
retval = TRUE;
failed:
if (message)
dbus_message_unref (message);
return retval;
}
static dbus_bool_t
check_invalid_message (DBusMessageLoader *loader)
{
dbus_bool_t retval;
retval = FALSE;
if (!_dbus_message_loader_queue_messages (loader))
_dbus_assert_not_reached ("no memory to queue messages");
if (!_dbus_message_loader_get_is_corrupted (loader))
{
_dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
goto failed;
}
retval = TRUE;
failed:
return retval;
}
static dbus_bool_t
check_incomplete_message (DBusMessageLoader *loader)
{
DBusMessage *message;
dbus_bool_t retval;
message = NULL;
retval = FALSE;
if (!_dbus_message_loader_queue_messages (loader))
_dbus_assert_not_reached ("no memory to queue messages");
if (_dbus_message_loader_get_is_corrupted (loader))
{
_dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
goto failed;
}
message = _dbus_message_loader_pop_message (loader);
if (message != NULL)
{
_dbus_warn ("loaded message that was expected to be incomplete\n");
goto failed;
}
retval = TRUE;
failed:
if (message)
dbus_message_unref (message);
return retval;
}
static dbus_bool_t
check_loader_results (DBusMessageLoader *loader,
DBusMessageValidity validity)
{
if (!_dbus_message_loader_queue_messages (loader))
_dbus_assert_not_reached ("no memory to queue messages");
switch (validity)
{
case _DBUS_MESSAGE_VALID:
return check_have_valid_message (loader);
case _DBUS_MESSAGE_INVALID:
return check_invalid_message (loader);
case _DBUS_MESSAGE_INCOMPLETE:
return check_incomplete_message (loader);
case _DBUS_MESSAGE_UNKNOWN:
return TRUE;
}
_dbus_assert_not_reached ("bad DBusMessageValidity");
return FALSE;
}
/**
* Loads the message in the given message file.
*
* @param filename filename to load
* @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
* @param data string to load message into
* @returns #TRUE if the message was loaded
*/
dbus_bool_t
dbus_internal_do_not_use_load_message_file (const DBusString *filename,
dbus_bool_t is_raw,
DBusString *data)
{
dbus_bool_t retval;
retval = FALSE;
if (is_raw)
{
DBusError error;
_dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
dbus_error_init (&error);
if (!_dbus_file_get_contents (data, filename, &error))
{
_dbus_warn ("Could not load message file %s: %s\n",
_dbus_string_get_const_data (filename),
error.message);
dbus_error_free (&error);
goto failed;
}
}
else
{
if (FALSE) /* Message builder disabled, probably permanently,
* I want to do it another way
*/
{
_dbus_warn ("Could not load message file %s\n",
_dbus_string_get_const_data (filename));
goto failed;
}
}
retval = TRUE;
failed:
return retval;
}
/**
* Tries loading the message in the given message file
* and verifies that DBusMessageLoader can handle it.
*
* @param filename filename to load
* @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
* @param expected_validity what the message has to be like to return #TRUE
* @returns #TRUE if the message has the expected validity
*/
dbus_bool_t
dbus_internal_do_not_use_try_message_file (const DBusString *filename,
dbus_bool_t is_raw,
DBusMessageValidity expected_validity)
{
DBusString data;
dbus_bool_t retval;
retval = FALSE;
if (!_dbus_string_init (&data))
_dbus_assert_not_reached ("could not allocate string\n");
if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
&data))
goto failed;
retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
failed:
if (!retval)
{
if (_dbus_string_get_length (&data) > 0)
_dbus_verbose_bytes_of_string (&data, 0,
_dbus_string_get_length (&data));
_dbus_warn ("Failed message loader test on %s\n",
_dbus_string_get_const_data (filename));
}
_dbus_string_free (&data);
return retval;
}
/**
* Tries loading the given message data.
*
*
* @param data the message data
* @param expected_validity what the message has to be like to return #TRUE
* @returns #TRUE if the message has the expected validity
*/
dbus_bool_t
dbus_internal_do_not_use_try_message_data (const DBusString *data,
DBusMessageValidity expected_validity)
{
DBusMessageLoader *loader;
dbus_bool_t retval;
int len;
int i;
loader = NULL;
retval = FALSE;
/* Write the data one byte at a time */
loader = _dbus_message_loader_new ();
/* check some trivial loader functions */
_dbus_message_loader_ref (loader);
_dbus_message_loader_unref (loader);
_dbus_message_loader_get_max_message_size (loader);
len = _dbus_string_get_length (data);
for (i = 0; i < len; i++)
{
DBusString *buffer;
_dbus_message_loader_get_buffer (loader, &buffer);
_dbus_string_append_byte (buffer,
_dbus_string_get_byte (data, i));
_dbus_message_loader_return_buffer (loader, buffer, 1);
}
if (!check_loader_results (loader, expected_validity))
goto failed;
_dbus_message_loader_unref (loader);
loader = NULL;
/* Write the data all at once */
loader = _dbus_message_loader_new ();
{
DBusString *buffer;
_dbus_message_loader_get_buffer (loader, &buffer);
_dbus_string_copy (data, 0, buffer,
_dbus_string_get_length (buffer));
_dbus_message_loader_return_buffer (loader, buffer, 1);
}
if (!check_loader_results (loader, expected_validity))
goto failed;
_dbus_message_loader_unref (loader);
loader = NULL;
/* Write the data 2 bytes at a time */
loader = _dbus_message_loader_new ();
len = _dbus_string_get_length (data);
for (i = 0; i < len; i += 2)
{
DBusString *buffer;
_dbus_message_loader_get_buffer (loader, &buffer);
_dbus_string_append_byte (buffer,
_dbus_string_get_byte (data, i));
if ((i+1) < len)
_dbus_string_append_byte (buffer,
_dbus_string_get_byte (data, i+1));
_dbus_message_loader_return_buffer (loader, buffer, 1);
}
if (!check_loader_results (loader, expected_validity))
goto failed;
_dbus_message_loader_unref (loader);
loader = NULL;
retval = TRUE;
failed:
if (loader)
_dbus_message_loader_unref (loader);
return retval;
}
static dbus_bool_t
process_test_subdir (const DBusString *test_base_dir,
const char *subdir,
DBusMessageValidity validity,
DBusForeachMessageFileFunc function,
void *user_data)
{
DBusString test_directory;
DBusString filename;
DBusDirIter *dir;
dbus_bool_t retval;
DBusError error;
retval = FALSE;
dir = NULL;
if (!_dbus_string_init (&test_directory))
_dbus_assert_not_reached ("didn't allocate test_directory\n");
_dbus_string_init_const (&filename, subdir);
if (!_dbus_string_copy (test_base_dir, 0,
&test_directory, 0))
_dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
if (!_dbus_concat_dir_and_file (&test_directory, &filename))
_dbus_assert_not_reached ("couldn't allocate full path");
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename))
_dbus_assert_not_reached ("didn't allocate filename string\n");
dbus_error_init (&error);
dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
_dbus_warn ("Could not open %s: %s\n",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
goto failed;
}
printf ("Testing %s:\n", subdir);
next:
while (_dbus_directory_get_next_file (dir, &filename, &error))
{
DBusString full_path;
dbus_bool_t is_raw;
if (!_dbus_string_init (&full_path))
_dbus_assert_not_reached ("couldn't init string");
if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
_dbus_assert_not_reached ("couldn't copy dir to full_path");
if (!_dbus_concat_dir_and_file (&full_path, &filename))
_dbus_assert_not_reached ("couldn't concat file to dir");
if (_dbus_string_ends_with_c_str (&filename, ".message"))
is_raw = FALSE;
else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
is_raw = TRUE;
else
{
_dbus_verbose ("Skipping non-.message file %s\n",
_dbus_string_get_const_data (&filename));
_dbus_string_free (&full_path);
goto next;
}
printf (" %s\n",
_dbus_string_get_const_data (&filename));
_dbus_verbose (" expecting %s for %s\n",
validity == _DBUS_MESSAGE_VALID ? "valid" :
(validity == _DBUS_MESSAGE_INVALID ? "invalid" :
(validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
_dbus_string_get_const_data (&filename));
if (! (*function) (&full_path, is_raw, validity, user_data))
{
_dbus_string_free (&full_path);
goto failed;
}
else
_dbus_string_free (&full_path);
}
if (dbus_error_is_set (&error))
{
_dbus_warn ("Could not get next file in %s: %s\n",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
goto failed;
}
retval = TRUE;
failed:
if (dir)
_dbus_directory_close (dir);
_dbus_string_free (&test_directory);
_dbus_string_free (&filename);
return retval;
}
/**
* Runs the given function on every message file in the test suite.
* The function should return #FALSE on test failure or fatal error.
*
* @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
* @param func the function to run
* @param user_data data for function
* @returns #FALSE if there's a failure
*/
dbus_bool_t
dbus_internal_do_not_use_foreach_message_file (const char *test_data_dir,
DBusForeachMessageFileFunc func,
void *user_data)
{
DBusString test_directory;
dbus_bool_t retval;
retval = FALSE;
_dbus_string_init_const (&test_directory, test_data_dir);
if (!process_test_subdir (&test_directory, "valid-messages",
_DBUS_MESSAGE_VALID, func, user_data))
goto failed;
if (!process_test_subdir (&test_directory, "invalid-messages",
_DBUS_MESSAGE_INVALID, func, user_data))
goto failed;
if (!process_test_subdir (&test_directory, "incomplete-messages",
_DBUS_MESSAGE_INCOMPLETE, func, user_data))
goto failed;
retval = TRUE;
failed:
_dbus_string_free (&test_directory);
return retval;
}
#define GET_AND_CHECK(iter, typename, literal) \
do { \
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename) \
_dbus_assert_not_reached ("got wrong argument type from message iter"); \
dbus_message_iter_get_basic (&iter, &v_##typename); \
if (v_##typename != literal) \
_dbus_assert_not_reached ("got wrong value from message iter"); \
} while (0)
#define GET_AND_CHECK_STRCMP(iter, typename, literal) \
do { \
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename) \
_dbus_assert_not_reached ("got wrong argument type from message iter"); \
dbus_message_iter_get_basic (&iter, &v_##typename); \
if (strcmp (v_##typename, literal) != 0) \
_dbus_assert_not_reached ("got wrong value from message iter"); \
} while (0)
#define GET_AND_CHECK_AND_NEXT(iter, typename, literal) \
do { \
GET_AND_CHECK(iter, typename, literal); \
if (!dbus_message_iter_next (&iter)) \
_dbus_assert_not_reached ("failed to move iter to next"); \
} while (0)
#define GET_AND_CHECK_STRCMP_AND_NEXT(iter, typename, literal) \
do { \
GET_AND_CHECK_STRCMP(iter, typename, literal); \
if (!dbus_message_iter_next (&iter)) \
_dbus_assert_not_reached ("failed to move iter to next"); \
} while (0)
static void
message_iter_test (DBusMessage *message)
{
DBusMessageIter iter, array, array2;
const char *v_STRING;
double v_DOUBLE;
dbus_int32_t v_INT32;
dbus_uint32_t v_UINT32;
#ifdef DBUS_HAVE_INT64
dbus_int64_t v_INT64;
dbus_uint64_t v_UINT64;
#endif
unsigned char v_BYTE;
unsigned char v_BOOLEAN;
const dbus_int32_t *our_int_array;
int len;
dbus_message_iter_init (message, &iter);
GET_AND_CHECK_STRCMP_AND_NEXT (iter, STRING, "Test string");
GET_AND_CHECK_AND_NEXT (iter, INT32, -0x12345678);
GET_AND_CHECK_AND_NEXT (iter, UINT32, 0xedd1e);
GET_AND_CHECK_AND_NEXT (iter, DOUBLE, 3.14159);
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
_dbus_assert_not_reached ("Argument type not an array");
if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_DOUBLE)
_dbus_assert_not_reached ("Array type not double");
dbus_message_iter_recurse (&iter, &array);
GET_AND_CHECK_AND_NEXT (array, DOUBLE, 1.5);
GET_AND_CHECK (array, DOUBLE, 2.5);
if (dbus_message_iter_next (&array))
_dbus_assert_not_reached ("Didn't reach end of array");
if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of arguments");
GET_AND_CHECK_AND_NEXT (iter, BYTE, 0xF0);
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
_dbus_assert_not_reached ("no array");
if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_INT32)
_dbus_assert_not_reached ("Array type not int32");
/* Empty array */
dbus_message_iter_recurse (&iter, &array);
if (dbus_message_iter_next (&array))
_dbus_assert_not_reached ("Didn't reach end of array");
if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of arguments");
GET_AND_CHECK (iter, BYTE, 0xF0);
if (dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Didn't reach end of arguments");
}
static void
verify_test_message (DBusMessage *message)
{
DBusMessageIter iter;
DBusError error;
dbus_int32_t our_int;
const char *our_str;
double our_double;
unsigned char our_bool;
unsigned char our_byte_1, our_byte_2;
dbus_uint32_t our_uint32;
const dbus_int32_t *our_uint32_array = (void*)0xdeadbeef;
int our_uint32_array_len;
dbus_int32_t *our_int32_array = (void*)0xdeadbeef;
int our_int32_array_len;
#ifdef DBUS_HAVE_INT64
dbus_int64_t our_int64;
dbus_uint64_t our_uint64;
dbus_int64_t *our_uint64_array = (void*)0xdeadbeef;
int our_uint64_array_len;
const dbus_int64_t *our_int64_array = (void*)0xdeadbeef;
int our_int64_array_len;
#endif
const double *our_double_array = (void*)0xdeadbeef;
int our_double_array_len;
const unsigned char *our_byte_array = (void*)0xdeadbeef;
int our_byte_array_len;
const unsigned char *our_boolean_array = (void*)0xdeadbeef;
int our_boolean_array_len;
dbus_message_iter_init (message, &iter);
dbus_error_init (&error);
if (!dbus_message_iter_get_args (&iter, &error,
DBUS_TYPE_INT32, &our_int,
#ifdef DBUS_HAVE_INT64
DBUS_TYPE_INT64, &our_int64,
DBUS_TYPE_UINT64, &our_uint64,
#endif
DBUS_TYPE_STRING, &our_str,
DBUS_TYPE_DOUBLE, &our_double,
DBUS_TYPE_BOOLEAN, &our_bool,
DBUS_TYPE_BYTE, &our_byte_1,
DBUS_TYPE_BYTE, &our_byte_2,
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
&our_uint32_array, &our_uint32_array_len,
DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
&our_int32_array, &our_int32_array_len,
#ifdef DBUS_HAVE_INT64
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
&our_uint64_array, &our_uint64_array_len,
DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
&our_int64_array, &our_int64_array_len,
#endif
DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
&our_double_array, &our_double_array_len,
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
&our_byte_array, &our_byte_array_len,
DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
&our_boolean_array, &our_boolean_array_len,
0))
{
_dbus_warn ("error: %s - %s\n", error.name,
(error.message != NULL) ? error.message : "no message");
_dbus_assert_not_reached ("Could not get arguments");
}
if (our_int != -0x12345678)
_dbus_assert_not_reached ("integers differ!");
#ifdef DBUS_HAVE_INT64
if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
_dbus_assert_not_reached ("64-bit integers differ!");
if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
_dbus_assert_not_reached ("64-bit unsigned integers differ!");
#endif
if (our_double != 3.14159)
_dbus_assert_not_reached ("doubles differ!");
if (strcmp (our_str, "Test string") != 0)
_dbus_assert_not_reached ("strings differ!");
if (!our_bool)
_dbus_assert_not_reached ("booleans differ");
if (our_byte_1 != 42)
_dbus_assert_not_reached ("bytes differ!");
if (our_byte_2 != 24)
_dbus_assert_not_reached ("bytes differ!");
if (our_uint32_array_len != 4 ||
our_uint32_array[0] != 0x12345678 ||
our_uint32_array[1] != 0x23456781 ||
our_uint32_array[2] != 0x34567812 ||
our_uint32_array[3] != 0x45678123)
_dbus_assert_not_reached ("uint array differs");
if (our_int32_array_len != 4 ||
our_int32_array[0] != 0x12345678 ||
our_int32_array[1] != -0x23456781 ||
our_int32_array[2] != 0x34567812 ||
our_int32_array[3] != -0x45678123)
_dbus_assert_not_reached ("int array differs");
#ifdef DBUS_HAVE_INT64
if (our_uint64_array_len != 4 ||
our_uint64_array[0] != 0x12345678 ||
our_uint64_array[1] != 0x23456781 ||
our_uint64_array[2] != 0x34567812 ||
our_uint64_array[3] != 0x45678123)
_dbus_assert_not_reached ("uint64 array differs");
if (our_int64_array_len != 4 ||
our_int64_array[0] != 0x12345678 ||
our_int64_array[1] != -0x23456781 ||
our_int64_array[2] != 0x34567812 ||
our_int64_array[3] != -0x45678123)
_dbus_assert_not_reached ("int64 array differs");
#endif /* DBUS_HAVE_INT64 */
if (our_double_array_len != 3)
_dbus_assert_not_reached ("double array had wrong length");
/* On all IEEE machines (i.e. everything sane) exact equality
* should be preserved over the wire
*/
if (our_double_array[0] != 0.1234 ||
our_double_array[1] != 9876.54321 ||
our_double_array[2] != -300.0)
_dbus_assert_not_reached ("double array had wrong values");
if (our_byte_array_len != 4)
_dbus_assert_not_reached ("byte array had wrong length");
if (our_byte_array[0] != 'a' ||
our_byte_array[1] != 'b' ||
our_byte_array[2] != 'c' ||
our_byte_array[3] != 234)
_dbus_assert_not_reached ("byte array had wrong values");
if (our_boolean_array_len != 5)
_dbus_assert_not_reached ("bool array had wrong length");
if (our_boolean_array[0] != TRUE ||
our_boolean_array[1] != FALSE ||
our_boolean_array[2] != TRUE ||
our_boolean_array[3] != TRUE ||
our_boolean_array[4] != FALSE)
_dbus_assert_not_reached ("bool array had wrong values");
if (dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Didn't reach end of arguments");
}
/**
* @ingroup DBusMessageInternals
* Unit test for DBusMessage.
*
* @returns #TRUE on success.
*/
dbus_bool_t
_dbus_message_test (const char *test_data_dir)
{
DBusMessage *message;
DBusMessageLoader *loader;
DBusMessageIter iter, child_iter, child_iter2, child_iter3;
int i;
const char *data;
DBusMessage *copy;
const char *name1;
const char *name2;
const dbus_uint32_t our_uint32_array[] =
{ 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
const dbus_uint32_t our_int32_array[] =
{ 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array;
const dbus_int32_t *v_ARRAY_INT32 = our_int32_array;
#ifdef DBUS_HAVE_INT64
const dbus_uint64_t our_uint64_array[] =
{ 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
const dbus_uint64_t our_int64_array[] =
{ 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array;
const dbus_int64_t *v_ARRAY_INT64 = our_int64_array;
#endif
const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
const char **v_ARRAY_STRING = our_string_array;
const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
const double *v_ARRAY_DOUBLE = our_double_array;
const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
const unsigned char *v_ARRAY_BYTE = our_byte_array;
const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
const unsigned char *v_ARRAY_BOOLEAN = our_boolean_array;
char sig[64];
const char *s;
char *t;
DBusError error;
const char *v_STRING;
double v_DOUBLE;
dbus_int32_t v_INT32;
dbus_uint32_t v_UINT32;
#ifdef DBUS_HAVE_INT64
dbus_int64_t v_INT64;
dbus_uint64_t v_UINT64;
#endif
unsigned char v_BYTE;
unsigned char v2_BYTE;
unsigned char v_BOOLEAN;
message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
"/org/freedesktop/TestPath",
"Foo.TestInterface",
"TestMethod");
_dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
_dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
"TestMethod"));
_dbus_assert (strcmp (dbus_message_get_path (message),
"/org/freedesktop/TestPath") == 0);
_dbus_message_set_serial (message, 1234);
/* string length including nul byte not a multiple of 4 */
if (!dbus_message_set_sender (message, "org.foo.bar1"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
dbus_message_set_reply_serial (message, 5678);
_dbus_verbose_bytes_of_string (&message->header.data, 0,
_dbus_string_get_length (&message->header.data));
_dbus_verbose_bytes_of_string (&message->body, 0,
_dbus_string_get_length (&message->body));
if (!dbus_message_set_sender (message, NULL))
_dbus_assert_not_reached ("out of memory");
_dbus_verbose_bytes_of_string (&message->header.data, 0,
_dbus_string_get_length (&message->header.data));
_dbus_verbose_bytes_of_string (&message->body, 0,
_dbus_string_get_length (&message->body));
_dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
_dbus_assert (dbus_message_get_serial (message) == 1234);
_dbus_assert (dbus_message_get_reply_serial (message) == 5678);
_dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
_dbus_assert (dbus_message_get_no_reply (message) == FALSE);
dbus_message_set_no_reply (message, TRUE);
_dbus_assert (dbus_message_get_no_reply (message) == TRUE);
dbus_message_set_no_reply (message, FALSE);
_dbus_assert (dbus_message_get_no_reply (message) == FALSE);
/* Set/get some header fields */
if (!dbus_message_set_path (message, "/foo"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (strcmp (dbus_message_get_path (message),
"/foo") == 0);
if (!dbus_message_set_interface (message, "org.Foo"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (strcmp (dbus_message_get_interface (message),
"org.Foo") == 0);
if (!dbus_message_set_member (message, "Bar"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (strcmp (dbus_message_get_member (message),
"Bar") == 0);
/* Set/get them with longer values */
if (!dbus_message_set_path (message, "/foo/bar"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (strcmp (dbus_message_get_path (message),
"/foo/bar") == 0);
if (!dbus_message_set_interface (message, "org.Foo.Bar"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (strcmp (dbus_message_get_interface (message),
"org.Foo.Bar") == 0);
if (!dbus_message_set_member (message, "BarFoo"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (strcmp (dbus_message_get_member (message),
"BarFoo") == 0);
/* Realloc shorter again */
if (!dbus_message_set_path (message, "/foo"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (strcmp (dbus_message_get_path (message),
"/foo") == 0);
if (!dbus_message_set_interface (message, "org.Foo"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (strcmp (dbus_message_get_interface (message),
"org.Foo") == 0);
if (!dbus_message_set_member (message, "Bar"))
_dbus_assert_not_reached ("out of memory");
_dbus_assert (strcmp (dbus_message_get_member (message),
"Bar") == 0);
dbus_message_unref (message);
/* Test the vararg functions */
message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
"/org/freedesktop/TestPath",
"Foo.TestInterface",
"TestMethod");
_dbus_message_set_serial (message, 1);
v_INT32 = -0x12345678;
#ifdef DBUS_HAVE_INT64
v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd);
v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd);
#endif
v_STRING = "Test string";
v_DOUBLE = 3.14159;
v_BOOLEAN = TRUE;
v_BYTE = 42;
v2_BYTE = 24;
dbus_message_append_args (message,
DBUS_TYPE_INT32, &v_INT32,
#ifdef DBUS_HAVE_INT64
DBUS_TYPE_INT64, &v_INT64,
DBUS_TYPE_UINT64, &v_UINT64,
#endif
DBUS_TYPE_STRING, &v_STRING,
DBUS_TYPE_DOUBLE, &v_DOUBLE,
DBUS_TYPE_BOOLEAN, &v_BOOLEAN,
DBUS_TYPE_BYTE, &v_BYTE,
DBUS_TYPE_BYTE, &v2_BYTE,
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32,
_DBUS_N_ELEMENTS (our_uint32_array),
DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32,
_DBUS_N_ELEMENTS (our_int32_array),
#ifdef DBUS_HAVE_INT64
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64,
_DBUS_N_ELEMENTS (our_uint64_array),
DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64,
_DBUS_N_ELEMENTS (our_int64_array),
#endif
DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE,
_DBUS_N_ELEMENTS (our_double_array),
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE,
_DBUS_N_ELEMENTS (our_byte_array),
DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN,
_DBUS_N_ELEMENTS (our_boolean_array),
DBUS_TYPE_INVALID);
i = 0;
sig[i++] = DBUS_TYPE_INT32;
#ifdef DBUS_HAVE_INT64
sig[i++] = DBUS_TYPE_INT64;
sig[i++] = DBUS_TYPE_UINT64;
#endif
sig[i++] = DBUS_TYPE_STRING;
sig[i++] = DBUS_TYPE_DOUBLE;
sig[i++] = DBUS_TYPE_BOOLEAN;
sig[i++] = DBUS_TYPE_BYTE;
sig[i++] = DBUS_TYPE_BYTE;
sig[i++] = DBUS_TYPE_ARRAY;
sig[i++] = DBUS_TYPE_UINT32;
sig[i++] = DBUS_TYPE_ARRAY;
sig[i++] = DBUS_TYPE_INT32;
#ifdef DBUS_HAVE_INT64
sig[i++] = DBUS_TYPE_ARRAY;
sig[i++] = DBUS_TYPE_UINT64;
sig[i++] = DBUS_TYPE_ARRAY;
sig[i++] = DBUS_TYPE_INT64;
#endif
sig[i++] = DBUS_TYPE_ARRAY;
sig[i++] = DBUS_TYPE_DOUBLE;
sig[i++] = DBUS_TYPE_ARRAY;
sig[i++] = DBUS_TYPE_BYTE;
sig[i++] = DBUS_TYPE_ARRAY;
sig[i++] = DBUS_TYPE_BOOLEAN;
sig[i++] = DBUS_TYPE_INVALID;
_dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
_dbus_verbose ("HEADER\n");
_dbus_verbose_bytes_of_string (&message->header.data, 0,
_dbus_string_get_length (&message->header.data));
_dbus_verbose ("BODY\n");
_dbus_verbose_bytes_of_string (&message->body, 0,
_dbus_string_get_length (&message->body));
_dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
sig, dbus_message_get_signature (message));
s = dbus_message_get_signature (message);
_dbus_assert (dbus_message_has_signature (message, sig));
_dbus_assert (strcmp (s, sig) == 0);
verify_test_message (message);
copy = dbus_message_copy (message);
_dbus_assert (dbus_message_get_reply_serial (message) ==
dbus_message_get_reply_serial (copy));
_dbus_assert (message->header.padding == copy->header.padding);
_dbus_assert (_dbus_string_get_length (&message->header.data) ==
_dbus_string_get_length (©->header.data));
_dbus_assert (_dbus_string_get_length (&message->body) ==
_dbus_string_get_length (©->body));
verify_test_message (copy);
name1 = dbus_message_get_interface (message);
name2 = dbus_message_get_interface (copy);
_dbus_assert (strcmp (name1, name2) == 0);
name1 = dbus_message_get_member (message);
name2 = dbus_message_get_member (copy);
_dbus_assert (strcmp (name1, name2) == 0);
dbus_message_unref (message);
dbus_message_unref (copy);
#if 0
/* FIXME */
message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
"/org/freedesktop/TestPath",
"Foo.TestInterface",
"TestMethod");
_dbus_message_set_serial (message, 1);
dbus_message_set_reply_serial (message, 0x12345678);
dbus_message_iter_init_append (message, &iter);
dbus_message_iter_append_string (&iter, "Test string");
dbus_message_iter_append_int32 (&iter, -0x12345678);
dbus_message_iter_append_uint32 (&iter, 0xedd1e);
dbus_message_iter_append_double (&iter, 3.14159);
dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
dbus_message_iter_append_double (&child_iter, 1.5);
dbus_message_iter_append_double (&child_iter, 2.5);
/* dict */
dbus_message_iter_append_dict (&iter, &child_iter);
dbus_message_iter_append_dict_key (&child_iter, "test");
dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
/* dict (in dict) */
dbus_message_iter_append_dict_key (&child_iter, "testdict");
dbus_message_iter_append_dict (&child_iter, &child_iter2);
dbus_message_iter_append_dict_key (&child_iter2, "dictkey");
dbus_message_iter_append_string (&child_iter2, "dictvalue");
/* array of array of int32 (in dict) */
dbus_message_iter_append_dict_key (&child_iter, "array");
dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
_dbus_warn ("next call expected to fail with wrong array type\n");
_dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
dbus_message_iter_append_byte (&iter, 0xF0);
dbus_message_iter_append_nil (&iter);
dbus_message_iter_append_custom (&iter, "MyTypeName",
"data", 5);
dbus_message_iter_append_byte (&iter, 0xF0);
dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_INT32);
dbus_message_iter_append_byte (&iter, 0xF0);
dbus_message_iter_append_dict (&iter, &child_iter);
dbus_message_iter_append_byte (&iter, 0xF0);
message_iter_test (message);
/* Message loader test */
_dbus_message_lock (message);
loader = _dbus_message_loader_new ();
/* check ref/unref */
_dbus_message_loader_ref (loader);
_dbus_message_loader_unref (loader);
/* Write the header data one byte at a time */
data = _dbus_string_get_const_data (&message->header);
for (i = 0; i < _dbus_string_get_length (&message->header); i++)
{
DBusString *buffer;
_dbus_message_loader_get_buffer (loader, &buffer);
_dbus_string_append_byte (buffer, data[i]);
_dbus_message_loader_return_buffer (loader, buffer, 1);
}
/* Write the body data one byte at a time */
data = _dbus_string_get_const_data (&message->body);
for (i = 0; i < _dbus_string_get_length (&message->body); i++)
{
DBusString *buffer;
_dbus_message_loader_get_buffer (loader, &buffer);
_dbus_string_append_byte (buffer, data[i]);
_dbus_message_loader_return_buffer (loader, buffer, 1);
}
copy = dbus_message_copy (message); /* save for tests below */
dbus_message_unref (message);
/* Now pop back the message */
if (!_dbus_message_loader_queue_messages (loader))
_dbus_assert_not_reached ("no memory to queue messages");
if (_dbus_message_loader_get_is_corrupted (loader))
_dbus_assert_not_reached ("message loader corrupted");
message = _dbus_message_loader_pop_message (loader);
if (!message)
_dbus_assert_not_reached ("received a NULL message");
if (dbus_message_get_reply_serial (message) != 0x12345678)
_dbus_assert_not_reached ("reply serial fields differ");
message_iter_test (message);
dbus_message_unref (message);
_dbus_message_loader_unref (loader);
message = dbus_message_new_method_return (copy);
if (message == NULL)
_dbus_assert_not_reached ("out of memory\n");
dbus_message_unref (copy);
if (!dbus_message_append_args (message,
DBUS_TYPE_STRING, "hello",
DBUS_TYPE_INVALID))
_dbus_assert_not_reached ("no memory");
if (!dbus_message_has_signature (message, "s"))
_dbus_assert_not_reached ("method return has wrong signature");
dbus_error_init (&error);
if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
&t, DBUS_TYPE_INVALID))
{
_dbus_warn ("Failed to get expected string arg: %s\n", error.message);
exit (1);
}
dbus_free (t);
dbus_message_unref (message);
/* This ServiceAcquired message used to trigger a bug in
* setting header fields, adding to regression test.
*/
message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
"ServiceAcquired");
if (message == NULL)
_dbus_assert_not_reached ("out of memory");
_dbus_verbose ("Bytes after creation\n");
_dbus_verbose_bytes_of_string (&message->header, 0,
_dbus_string_get_length (&message->header));
if (!dbus_message_set_destination (message, ":1.0") ||
!dbus_message_append_args (message,
DBUS_TYPE_STRING, ":1.0",
DBUS_TYPE_INVALID))
_dbus_assert_not_reached ("out of memory");
_dbus_verbose ("Bytes after set_destination() and append_args()\n");
_dbus_verbose_bytes_of_string (&message->header, 0,
_dbus_string_get_length (&message->header));
if (!dbus_message_set_sender (message, "org.freedesktop.DBus"))
_dbus_assert_not_reached ("out of memory");
_dbus_verbose ("Bytes after set_sender()\n");
_dbus_verbose_bytes_of_string (&message->header, 0,
_dbus_string_get_length (&message->header));
/* When the bug happened the above set_destination() would
* corrupt the signature
*/
if (!dbus_message_has_signature (message, "s"))
{
_dbus_warn ("Signature should be 's' but is '%s'\n",
dbus_message_get_signature (message));
_dbus_assert_not_reached ("signal has wrong signature");
}
/* have to set destination again to reproduce the bug */
if (!dbus_message_set_destination (message, ":1.0"))
_dbus_assert_not_reached ("out of memory");
_dbus_verbose ("Bytes after set_destination()\n");
_dbus_verbose_bytes_of_string (&message->header, 0,
_dbus_string_get_length (&message->header));
/* When the bug happened the above set_destination() would
* corrupt the signature
*/
if (!dbus_message_has_signature (message, "s"))
{
_dbus_warn ("Signature should be 's' but is '%s'\n",
dbus_message_get_signature (message));
_dbus_assert_not_reached ("signal has wrong signature");
}
dbus_error_init (&error);
if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
&t, DBUS_TYPE_INVALID))
{
_dbus_warn ("Failed to get expected string arg for signal: %s\n", error.message);
exit (1);
}
dbus_free (t);
dbus_message_unref (message);
/* Now load every message in test_data_dir if we have one */
if (test_data_dir == NULL)
return TRUE;
return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
(DBusForeachMessageFileFunc)
dbus_internal_do_not_use_try_message_file,
NULL);
#endif /* Commented out most tests for now */
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */
Index: dbus-message.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message.c,v
retrieving revision 1.149
retrieving revision 1.150
diff -u -d -r1.149 -r1.150
--- dbus-message.c 17 Jan 2005 00:16:28 -0000 1.149
+++ dbus-message.c 17 Jan 2005 03:53:40 -0000 1.150
@@ -26,12 +26,10 @@
#include "dbus-marshal-recursive.h"
#include "dbus-marshal-validate.h"
#include "dbus-marshal-header.h"
-#include "dbus-message.h"
-#include "dbus-message-internal.h"
+#include "dbus-message-private.h"
#include "dbus-object-tree.h"
#include "dbus-memory.h"
#include "dbus-list.h"
-#include "dbus-dataslot.h"
#include <string.h>
/**
@@ -44,54 +42,11 @@
* @{
*/
-static dbus_bool_t dbus_message_iter_get_args (DBusMessageIter *iter,
- DBusError *error,
- int first_arg_type,
- ...);
-static dbus_bool_t dbus_message_iter_get_args_valist (DBusMessageIter *iter,
- DBusError *error,
- int first_arg_type,
- va_list var_args);
-
/* Not thread locked, but strictly const/read-only so should be OK
*/
/** An static string representing an empty signature */
_DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, "");
-/** How many bits are in the changed_stamp used to validate iterators */
-#define CHANGED_STAMP_BITS 21
-
-/**
- * @brief Internals of DBusMessage
- *
- * Object representing a message received from or to be sent to
- * another application. This is an opaque object, all members
- * are private.
- */
-struct DBusMessage
-{
- DBusAtomic refcount; /**< Reference count */
-
- DBusHeader header; /**< Header network data and associated cache */
-
- DBusString body; /**< Body network data. */
-
- char byte_order; /**< Message byte order. */
-
- unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
-
- DBusList *size_counters; /**< 0-N DBusCounter used to track message size. */
- long size_counter_delta; /**< Size we incremented the size counters by. */
-
- dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; /**< Incremented when iterators are invalidated. */
-
- DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */
-
-#ifndef DBUS_DISABLE_CHECKS
- int generation; /**< _dbus_current_generation when message was created */
-#endif
-};
-
/* these have wacky values to help trap uninitialized iterators;
* but has to fit in 3 bits
*/
@@ -1380,42 +1335,7 @@
_dbus_return_val_if_error_is_set (error, FALSE);
dbus_message_iter_init (message, &iter);
- return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
-}
-
-/**
- * Reads arguments from a message iterator given a variable argument
- * list. Only arguments of basic type and arrays of fixed-length
- * basic type may be read with this function. See
- * dbus_message_get_args() for more details.
- *
- * @todo this is static for now because there's no corresponding
- * iter_append_args() and I'm not sure we need this function to be
- * public since dbus_message_get_args() is what you usually want
- *
- * @param iter the message iterator
- * @param error error to be filled in on failure
- * @param first_arg_type the first argument type
- * @param ... location for first argument value, then list of type-location pairs
- * @returns #FALSE if the error was set
- */
-static dbus_bool_t
-dbus_message_iter_get_args (DBusMessageIter *iter,
- DBusError *error,
- int first_arg_type,
- ...)
-{
- dbus_bool_t retval;
- va_list var_args;
-
- _dbus_return_val_if_fail (iter != NULL, FALSE);
- _dbus_return_val_if_error_is_set (error, FALSE);
-
- va_start (var_args, first_arg_type);
- retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
- va_end (var_args);
-
- return retval;
+ return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
}
static void
@@ -1700,9 +1620,6 @@
* dbus_message_get_args() is the place to go for complete
* documentation.
*
- * @todo this is static for now, should be public if
- * dbus_message_iter_get_args_valist() is made public.
- *
* @see dbus_message_get_args
* @param iter the message iter
* @param error error to be filled in
@@ -1710,18 +1627,17 @@
* @param var_args return location for first argument, followed by list of type/location pairs
* @returns #FALSE if error was set
*/
-static dbus_bool_t
-dbus_message_iter_get_args_valist (DBusMessageIter *iter,
- DBusError *error,
- int first_arg_type,
- va_list var_args)
+dbus_bool_t
+_dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int spec_type, msg_type, i;
dbus_bool_t retval;
- _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
- _dbus_return_val_if_error_is_set (error, FALSE);
+ _dbus_assert (_dbus_message_iter_check (real));
retval = FALSE;
@@ -1749,7 +1665,7 @@
ptr = va_arg (var_args, DBusBasicValue*);
- _dbus_return_val_if_fail (ptr != NULL, FALSE);
+ _dbus_assert (ptr != NULL);
_dbus_type_reader_read_basic (&real->u.reader,
ptr);
@@ -1782,8 +1698,8 @@
ptr = va_arg (var_args, const DBusBasicValue**);
n_elements_p = va_arg (var_args, int*);
- _dbus_return_val_if_fail (ptr != NULL, FALSE);
- _dbus_return_val_if_fail (n_elements_p != NULL, FALSE);
+ _dbus_assert (ptr != NULL);
+ _dbus_assert (n_elements_p != NULL);
_dbus_type_reader_recurse (&real->u.reader, &array);
@@ -1801,8 +1717,8 @@
str_array_p = va_arg (var_args, char***);
n_elements_p = va_arg (var_args, int*);
- _dbus_return_val_if_fail (str_array_p != NULL, FALSE);
- _dbus_return_val_if_fail (n_elements_p != NULL, FALSE);
+ _dbus_assert (str_array_p != NULL);
+ _dbus_assert (n_elements_p != NULL);
/* Count elements in the array */
_dbus_type_reader_recurse (&real->u.reader, &array);
@@ -2937,41 +2853,6 @@
*
* @{
*/
-/**
- * @typedef DBusMessageLoader
- *
- * The DBusMessageLoader object encapsulates the process of converting
- * a byte stream into a series of DBusMessage. It buffers the incoming
- * bytes as efficiently as possible, and generates a queue of
- * messages. DBusMessageLoader is typically used as part of a
- * DBusTransport implementation. The DBusTransport then hands off
- * the loaded messages to a DBusConnection, making the messages
- * visible to the application.
- *
- * @todo write tests for break-loader that a) randomly delete header
- * fields and b) set string fields to zero-length and other funky
- * values.
- *
- */
-
-/**
- * Implementation details of DBusMessageLoader.
- * All members are private.
- */
-struct DBusMessageLoader
-{
- int refcount; /**< Reference count. */
-
- DBusString data; /**< Buffered data */
-
- DBusList *messages; /**< Complete messages. */
-
- long max_message_size; /**< Maximum size of a message */
-
- unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
-
- unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
-};
/**
* The initial buffer size of the message loader.
@@ -3579,1240 +3460,5 @@
}
/** @} */
-#ifdef DBUS_BUILD_TESTS
-#include "dbus-test.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-static dbus_bool_t
-check_have_valid_message (DBusMessageLoader *loader)
-{
- DBusMessage *message;
- dbus_bool_t retval;
-
- message = NULL;
- retval = FALSE;
-
- if (!_dbus_message_loader_queue_messages (loader))
- _dbus_assert_not_reached ("no memory to queue messages");
-
- if (_dbus_message_loader_get_is_corrupted (loader))
- {
- _dbus_warn ("loader corrupted on message that was expected to be valid\n");
- goto failed;
- }
-
- message = _dbus_message_loader_pop_message (loader);
- if (message == NULL)
- {
- _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
- goto failed;
- }
-
- if (_dbus_string_get_length (&loader->data) > 0)
- {
- _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
- goto failed;
- }
-
-#if 0
- /* FIXME */
- /* Verify that we're able to properly deal with the message.
- * For example, this would detect improper handling of messages
- * in nonstandard byte order.
- */
- if (!check_message_handling (message))
- goto failed;
-#endif
-
- retval = TRUE;
-
- failed:
- if (message)
- dbus_message_unref (message);
-
- return retval;
-}
-
-static dbus_bool_t
-check_invalid_message (DBusMessageLoader *loader)
-{
- dbus_bool_t retval;
-
- retval = FALSE;
-
- if (!_dbus_message_loader_queue_messages (loader))
- _dbus_assert_not_reached ("no memory to queue messages");
-
- if (!_dbus_message_loader_get_is_corrupted (loader))
- {
- _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
- goto failed;
- }
-
- retval = TRUE;
-
- failed:
- return retval;
-}
-
-static dbus_bool_t
-check_incomplete_message (DBusMessageLoader *loader)
-{
- DBusMessage *message;
- dbus_bool_t retval;
-
- message = NULL;
- retval = FALSE;
-
- if (!_dbus_message_loader_queue_messages (loader))
- _dbus_assert_not_reached ("no memory to queue messages");
-
- if (_dbus_message_loader_get_is_corrupted (loader))
- {
- _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
- goto failed;
- }
-
- message = _dbus_message_loader_pop_message (loader);
- if (message != NULL)
- {
- _dbus_warn ("loaded message that was expected to be incomplete\n");
- goto failed;
- }
-
- retval = TRUE;
-
- failed:
- if (message)
- dbus_message_unref (message);
- return retval;
-}
-
-static dbus_bool_t
-check_loader_results (DBusMessageLoader *loader,
- DBusMessageValidity validity)
-{
- if (!_dbus_message_loader_queue_messages (loader))
- _dbus_assert_not_reached ("no memory to queue messages");
-
- switch (validity)
- {
- case _DBUS_MESSAGE_VALID:
- return check_have_valid_message (loader);
- case _DBUS_MESSAGE_INVALID:
- return check_invalid_message (loader);
- case _DBUS_MESSAGE_INCOMPLETE:
- return check_incomplete_message (loader);
- case _DBUS_MESSAGE_UNKNOWN:
- return TRUE;
- }
-
- _dbus_assert_not_reached ("bad DBusMessageValidity");
- return FALSE;
-}
-
-
-/**
- * Loads the message in the given message file.
- *
- * @param filename filename to load
- * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
- * @param data string to load message into
- * @returns #TRUE if the message was loaded
- */
-dbus_bool_t
-dbus_internal_do_not_use_load_message_file (const DBusString *filename,
- dbus_bool_t is_raw,
- DBusString *data)
-{
- dbus_bool_t retval;
-
- retval = FALSE;
-
- if (is_raw)
- {
- DBusError error;
-
- _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
- dbus_error_init (&error);
- if (!_dbus_file_get_contents (data, filename, &error))
- {
- _dbus_warn ("Could not load message file %s: %s\n",
- _dbus_string_get_const_data (filename),
- error.message);
- dbus_error_free (&error);
- goto failed;
- }
- }
- else
- {
- if (FALSE) /* Message builder disabled, probably permanently,
- * I want to do it another way
- */
- {
- _dbus_warn ("Could not load message file %s\n",
- _dbus_string_get_const_data (filename));
- goto failed;
- }
- }
-
- retval = TRUE;
-
- failed:
-
- return retval;
-}
-
-/**
- * Tries loading the message in the given message file
- * and verifies that DBusMessageLoader can handle it.
- *
- * @param filename filename to load
- * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
- * @param expected_validity what the message has to be like to return #TRUE
- * @returns #TRUE if the message has the expected validity
- */
-dbus_bool_t
-dbus_internal_do_not_use_try_message_file (const DBusString *filename,
- dbus_bool_t is_raw,
- DBusMessageValidity expected_validity)
-{
- DBusString data;
- dbus_bool_t retval;
-
- retval = FALSE;
-
- if (!_dbus_string_init (&data))
- _dbus_assert_not_reached ("could not allocate string\n");
-
- if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
- &data))
- goto failed;
-
- retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
-
- failed:
-
- if (!retval)
- {
- if (_dbus_string_get_length (&data) > 0)
- _dbus_verbose_bytes_of_string (&data, 0,
- _dbus_string_get_length (&data));
-
- _dbus_warn ("Failed message loader test on %s\n",
- _dbus_string_get_const_data (filename));
- }
-
- _dbus_string_free (&data);
-
- return retval;
-}
-
-/**
- * Tries loading the given message data.
- *
- *
- * @param data the message data
- * @param expected_validity what the message has to be like to return #TRUE
- * @returns #TRUE if the message has the expected validity
- */
-dbus_bool_t
-dbus_internal_do_not_use_try_message_data (const DBusString *data,
- DBusMessageValidity expected_validity)
-{
- DBusMessageLoader *loader;
- dbus_bool_t retval;
- int len;
- int i;
-
- loader = NULL;
- retval = FALSE;
-
- /* Write the data one byte at a time */
-
- loader = _dbus_message_loader_new ();
-
- /* check some trivial loader functions */
- _dbus_message_loader_ref (loader);
- _dbus_message_loader_unref (loader);
- _dbus_message_loader_get_max_message_size (loader);
-
- len = _dbus_string_get_length (data);
- for (i = 0; i < len; i++)
- {
- DBusString *buffer;
-
- _dbus_message_loader_get_buffer (loader, &buffer);
- _dbus_string_append_byte (buffer,
- _dbus_string_get_byte (data, i));
- _dbus_message_loader_return_buffer (loader, buffer, 1);
- }
-
- if (!check_loader_results (loader, expected_validity))
- goto failed;
-
- _dbus_message_loader_unref (loader);
- loader = NULL;
-
- /* Write the data all at once */
-
- loader = _dbus_message_loader_new ();
-
- {
- DBusString *buffer;
-
- _dbus_message_loader_get_buffer (loader, &buffer);
- _dbus_string_copy (data, 0, buffer,
- _dbus_string_get_length (buffer));
- _dbus_message_loader_return_buffer (loader, buffer, 1);
- }
-
- if (!check_loader_results (loader, expected_validity))
- goto failed;
-
- _dbus_message_loader_unref (loader);
- loader = NULL;
-
- /* Write the data 2 bytes at a time */
-
- loader = _dbus_message_loader_new ();
-
- len = _dbus_string_get_length (data);
- for (i = 0; i < len; i += 2)
- {
- DBusString *buffer;
-
- _dbus_message_loader_get_buffer (loader, &buffer);
- _dbus_string_append_byte (buffer,
- _dbus_string_get_byte (data, i));
- if ((i+1) < len)
- _dbus_string_append_byte (buffer,
- _dbus_string_get_byte (data, i+1));
- _dbus_message_loader_return_buffer (loader, buffer, 1);
- }
-
- if (!check_loader_results (loader, expected_validity))
- goto failed;
-
- _dbus_message_loader_unref (loader);
- loader = NULL;
-
- retval = TRUE;
-
- failed:
-
- if (loader)
- _dbus_message_loader_unref (loader);
-
- return retval;
-}
-
-static dbus_bool_t
-process_test_subdir (const DBusString *test_base_dir,
- const char *subdir,
- DBusMessageValidity validity,
- DBusForeachMessageFileFunc function,
- void *user_data)
-{
- DBusString test_directory;
- DBusString filename;
- DBusDirIter *dir;
- dbus_bool_t retval;
- DBusError error;
-
- retval = FALSE;
- dir = NULL;
-
- if (!_dbus_string_init (&test_directory))
- _dbus_assert_not_reached ("didn't allocate test_directory\n");
-
- _dbus_string_init_const (&filename, subdir);
-
- if (!_dbus_string_copy (test_base_dir, 0,
- &test_directory, 0))
- _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
-
- if (!_dbus_concat_dir_and_file (&test_directory, &filename))
- _dbus_assert_not_reached ("couldn't allocate full path");
-
- _dbus_string_free (&filename);
- if (!_dbus_string_init (&filename))
- _dbus_assert_not_reached ("didn't allocate filename string\n");
-
- dbus_error_init (&error);
- dir = _dbus_directory_open (&test_directory, &error);
- if (dir == NULL)
- {
- _dbus_warn ("Could not open %s: %s\n",
- _dbus_string_get_const_data (&test_directory),
- error.message);
- dbus_error_free (&error);
- goto failed;
- }
-
- printf ("Testing %s:\n", subdir);
-
- next:
- while (_dbus_directory_get_next_file (dir, &filename, &error))
- {
- DBusString full_path;
- dbus_bool_t is_raw;
-
- if (!_dbus_string_init (&full_path))
- _dbus_assert_not_reached ("couldn't init string");
-
- if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
- _dbus_assert_not_reached ("couldn't copy dir to full_path");
-
- if (!_dbus_concat_dir_and_file (&full_path, &filename))
- _dbus_assert_not_reached ("couldn't concat file to dir");
-
- if (_dbus_string_ends_with_c_str (&filename, ".message"))
- is_raw = FALSE;
- else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
- is_raw = TRUE;
- else
- {
- _dbus_verbose ("Skipping non-.message file %s\n",
- _dbus_string_get_const_data (&filename));
- _dbus_string_free (&full_path);
- goto next;
- }
-
- printf (" %s\n",
- _dbus_string_get_const_data (&filename));
-
- _dbus_verbose (" expecting %s for %s\n",
- validity == _DBUS_MESSAGE_VALID ? "valid" :
- (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
- (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
- _dbus_string_get_const_data (&filename));
-
- if (! (*function) (&full_path, is_raw, validity, user_data))
- {
- _dbus_string_free (&full_path);
- goto failed;
- }
- else
- _dbus_string_free (&full_path);
- }
-
- if (dbus_error_is_set (&error))
- {
- _dbus_warn ("Could not get next file in %s: %s\n",
- _dbus_string_get_const_data (&test_directory),
- error.message);
- dbus_error_free (&error);
- goto failed;
- }
-
- retval = TRUE;
-
- failed:
-
- if (dir)
- _dbus_directory_close (dir);
- _dbus_string_free (&test_directory);
- _dbus_string_free (&filename);
-
- return retval;
-}
-
-/**
- * Runs the given function on every message file in the test suite.
- * The function should return #FALSE on test failure or fatal error.
- *
- * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
- * @param func the function to run
- * @param user_data data for function
- * @returns #FALSE if there's a failure
- */
-dbus_bool_t
-dbus_internal_do_not_use_foreach_message_file (const char *test_data_dir,
- DBusForeachMessageFileFunc func,
- void *user_data)
-{
- DBusString test_directory;
- dbus_bool_t retval;
-
- retval = FALSE;
-
- _dbus_string_init_const (&test_directory, test_data_dir);
-
- if (!process_test_subdir (&test_directory, "valid-messages",
- _DBUS_MESSAGE_VALID, func, user_data))
- goto failed;
-
- if (!process_test_subdir (&test_directory, "invalid-messages",
- _DBUS_MESSAGE_INVALID, func, user_data))
- goto failed;
-
- if (!process_test_subdir (&test_directory, "incomplete-messages",
- _DBUS_MESSAGE_INCOMPLETE, func, user_data))
- goto failed;
-
- retval = TRUE;
-
- failed:
-
- _dbus_string_free (&test_directory);
-
- return retval;
-}
-
-#define GET_AND_CHECK(iter, typename, literal) \
- do { \
- if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename) \
- _dbus_assert_not_reached ("got wrong argument type from message iter"); \
- dbus_message_iter_get_basic (&iter, &v_##typename); \
- if (v_##typename != literal) \
- _dbus_assert_not_reached ("got wrong value from message iter"); \
- } while (0)
-
-#define GET_AND_CHECK_STRCMP(iter, typename, literal) \
- do { \
- if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename) \
- _dbus_assert_not_reached ("got wrong argument type from message iter"); \
- dbus_message_iter_get_basic (&iter, &v_##typename); \
- if (strcmp (v_##typename, literal) != 0) \
- _dbus_assert_not_reached ("got wrong value from message iter"); \
- } while (0)
-
-#define GET_AND_CHECK_AND_NEXT(iter, typename, literal) \
- do { \
- GET_AND_CHECK(iter, typename, literal); \
- if (!dbus_message_iter_next (&iter)) \
- _dbus_assert_not_reached ("failed to move iter to next"); \
- } while (0)
-
-#define GET_AND_CHECK_STRCMP_AND_NEXT(iter, typename, literal) \
- do { \
- GET_AND_CHECK_STRCMP(iter, typename, literal); \
- if (!dbus_message_iter_next (&iter)) \
- _dbus_assert_not_reached ("failed to move iter to next"); \
- } while (0)
-
-static void
-message_iter_test (DBusMessage *message)
-{
- DBusMessageIter iter, array, array2;
- const char *v_STRING;
- double v_DOUBLE;
- dbus_int32_t v_INT32;
- dbus_uint32_t v_UINT32;
-#ifdef DBUS_HAVE_INT64
- dbus_int64_t v_INT64;
- dbus_uint64_t v_UINT64;
-#endif
- unsigned char v_BYTE;
- unsigned char v_BOOLEAN;
-
- const dbus_int32_t *our_int_array;
- int len;
-
- dbus_message_iter_init (message, &iter);
-
- GET_AND_CHECK_STRCMP_AND_NEXT (iter, STRING, "Test string");
- GET_AND_CHECK_AND_NEXT (iter, INT32, -0x12345678);
- GET_AND_CHECK_AND_NEXT (iter, UINT32, 0xedd1e);
- GET_AND_CHECK_AND_NEXT (iter, DOUBLE, 3.14159);
-
- if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
- _dbus_assert_not_reached ("Argument type not an array");
-
- if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_DOUBLE)
- _dbus_assert_not_reached ("Array type not double");
-
- dbus_message_iter_recurse (&iter, &array);
- GET_AND_CHECK_AND_NEXT (array, DOUBLE, 1.5);
- GET_AND_CHECK (array, DOUBLE, 2.5);
-
- if (dbus_message_iter_next (&array))
- _dbus_assert_not_reached ("Didn't reach end of array");
-
- if (!dbus_message_iter_next (&iter))
- _dbus_assert_not_reached ("Reached end of arguments");
-
- GET_AND_CHECK_AND_NEXT (iter, BYTE, 0xF0);
-
- if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
- _dbus_assert_not_reached ("no array");
-
- if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_INT32)
- _dbus_assert_not_reached ("Array type not int32");
-
- /* Empty array */
- dbus_message_iter_recurse (&iter, &array);
-
- if (dbus_message_iter_next (&array))
- _dbus_assert_not_reached ("Didn't reach end of array");
-
- if (!dbus_message_iter_next (&iter))
- _dbus_assert_not_reached ("Reached end of arguments");
-
- GET_AND_CHECK (iter, BYTE, 0xF0);
-
- if (dbus_message_iter_next (&iter))
- _dbus_assert_not_reached ("Didn't reach end of arguments");
-}
-
-static void
-verify_test_message (DBusMessage *message)
-{
- DBusMessageIter iter;
- DBusError error;
- dbus_int32_t our_int;
- const char *our_str;
- double our_double;
- unsigned char our_bool;
- unsigned char our_byte_1, our_byte_2;
- dbus_uint32_t our_uint32;
- const dbus_int32_t *our_uint32_array = (void*)0xdeadbeef;
- int our_uint32_array_len;
- dbus_int32_t *our_int32_array = (void*)0xdeadbeef;
- int our_int32_array_len;
-#ifdef DBUS_HAVE_INT64
- dbus_int64_t our_int64;
- dbus_uint64_t our_uint64;
- dbus_int64_t *our_uint64_array = (void*)0xdeadbeef;
- int our_uint64_array_len;
- const dbus_int64_t *our_int64_array = (void*)0xdeadbeef;
- int our_int64_array_len;
-#endif
- const double *our_double_array = (void*)0xdeadbeef;
- int our_double_array_len;
- const unsigned char *our_byte_array = (void*)0xdeadbeef;
- int our_byte_array_len;
- const unsigned char *our_boolean_array = (void*)0xdeadbeef;
- int our_boolean_array_len;
-
- dbus_message_iter_init (message, &iter);
-
- dbus_error_init (&error);
- if (!dbus_message_iter_get_args (&iter, &error,
- DBUS_TYPE_INT32, &our_int,
-#ifdef DBUS_HAVE_INT64
- DBUS_TYPE_INT64, &our_int64,
- DBUS_TYPE_UINT64, &our_uint64,
-#endif
- DBUS_TYPE_STRING, &our_str,
- DBUS_TYPE_DOUBLE, &our_double,
- DBUS_TYPE_BOOLEAN, &our_bool,
- DBUS_TYPE_BYTE, &our_byte_1,
- DBUS_TYPE_BYTE, &our_byte_2,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
- &our_uint32_array, &our_uint32_array_len,
- DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
- &our_int32_array, &our_int32_array_len,
-#ifdef DBUS_HAVE_INT64
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
- &our_uint64_array, &our_uint64_array_len,
- DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
- &our_int64_array, &our_int64_array_len,
-#endif
- DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
- &our_double_array, &our_double_array_len,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &our_byte_array, &our_byte_array_len,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
- &our_boolean_array, &our_boolean_array_len,
- 0))
- {
- _dbus_warn ("error: %s - %s\n", error.name,
- (error.message != NULL) ? error.message : "no message");
- _dbus_assert_not_reached ("Could not get arguments");
- }
-
- if (our_int != -0x12345678)
- _dbus_assert_not_reached ("integers differ!");
-
-#ifdef DBUS_HAVE_INT64
- if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
- _dbus_assert_not_reached ("64-bit integers differ!");
- if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
- _dbus_assert_not_reached ("64-bit unsigned integers differ!");
-#endif
-
- if (our_double != 3.14159)
- _dbus_assert_not_reached ("doubles differ!");
-
- if (strcmp (our_str, "Test string") != 0)
- _dbus_assert_not_reached ("strings differ!");
-
- if (!our_bool)
- _dbus_assert_not_reached ("booleans differ");
-
- if (our_byte_1 != 42)
- _dbus_assert_not_reached ("bytes differ!");
-
- if (our_byte_2 != 24)
- _dbus_assert_not_reached ("bytes differ!");
-
- if (our_uint32_array_len != 4 ||
- our_uint32_array[0] != 0x12345678 ||
- our_uint32_array[1] != 0x23456781 ||
- our_uint32_array[2] != 0x34567812 ||
- our_uint32_array[3] != 0x45678123)
- _dbus_assert_not_reached ("uint array differs");
-
- if (our_int32_array_len != 4 ||
- our_int32_array[0] != 0x12345678 ||
- our_int32_array[1] != -0x23456781 ||
- our_int32_array[2] != 0x34567812 ||
- our_int32_array[3] != -0x45678123)
- _dbus_assert_not_reached ("int array differs");
-
-#ifdef DBUS_HAVE_INT64
- if (our_uint64_array_len != 4 ||
- our_uint64_array[0] != 0x12345678 ||
- our_uint64_array[1] != 0x23456781 ||
- our_uint64_array[2] != 0x34567812 ||
- our_uint64_array[3] != 0x45678123)
- _dbus_assert_not_reached ("uint64 array differs");
-
- if (our_int64_array_len != 4 ||
- our_int64_array[0] != 0x12345678 ||
- our_int64_array[1] != -0x23456781 ||
- our_int64_array[2] != 0x34567812 ||
- our_int64_array[3] != -0x45678123)
- _dbus_assert_not_reached ("int64 array differs");
-#endif /* DBUS_HAVE_INT64 */
-
- if (our_double_array_len != 3)
- _dbus_assert_not_reached ("double array had wrong length");
-
- /* On all IEEE machines (i.e. everything sane) exact equality
- * should be preserved over the wire
- */
- if (our_double_array[0] != 0.1234 ||
- our_double_array[1] != 9876.54321 ||
- our_double_array[2] != -300.0)
- _dbus_assert_not_reached ("double array had wrong values");
-
- if (our_byte_array_len != 4)
- _dbus_assert_not_reached ("byte array had wrong length");
-
- if (our_byte_array[0] != 'a' ||
- our_byte_array[1] != 'b' ||
- our_byte_array[2] != 'c' ||
- our_byte_array[3] != 234)
- _dbus_assert_not_reached ("byte array had wrong values");
-
- if (our_boolean_array_len != 5)
- _dbus_assert_not_reached ("bool array had wrong length");
-
- if (our_boolean_array[0] != TRUE ||
- our_boolean_array[1] != FALSE ||
- our_boolean_array[2] != TRUE ||
- our_boolean_array[3] != TRUE ||
- our_boolean_array[4] != FALSE)
- _dbus_assert_not_reached ("bool array had wrong values");
-
- if (dbus_message_iter_next (&iter))
- _dbus_assert_not_reached ("Didn't reach end of arguments");
-}
-
-/**
- * @ingroup DBusMessageInternals
- * Unit test for DBusMessage.
- *
- * @returns #TRUE on success.
- */
-dbus_bool_t
-_dbus_message_test (const char *test_data_dir)
-{
- DBusMessage *message;
- DBusMessageLoader *loader;
- DBusMessageIter iter, child_iter, child_iter2, child_iter3;
- int i;
- const char *data;
- DBusMessage *copy;
- const char *name1;
- const char *name2;
- const dbus_uint32_t our_uint32_array[] =
- { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
- const dbus_uint32_t our_int32_array[] =
- { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
- const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array;
- const dbus_int32_t *v_ARRAY_INT32 = our_int32_array;
-#ifdef DBUS_HAVE_INT64
- const dbus_uint64_t our_uint64_array[] =
- { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
- const dbus_uint64_t our_int64_array[] =
- { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
- const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array;
- const dbus_int64_t *v_ARRAY_INT64 = our_int64_array;
-#endif
- const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
- const char **v_ARRAY_STRING = our_string_array;
- const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
- const double *v_ARRAY_DOUBLE = our_double_array;
- const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
- const unsigned char *v_ARRAY_BYTE = our_byte_array;
- const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
- const unsigned char *v_ARRAY_BOOLEAN = our_boolean_array;
- char sig[64];
- const char *s;
- char *t;
- DBusError error;
- const char *v_STRING;
- double v_DOUBLE;
- dbus_int32_t v_INT32;
- dbus_uint32_t v_UINT32;
-#ifdef DBUS_HAVE_INT64
- dbus_int64_t v_INT64;
- dbus_uint64_t v_UINT64;
-#endif
- unsigned char v_BYTE;
- unsigned char v2_BYTE;
- unsigned char v_BOOLEAN;
-
- _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
-
- message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
- "/org/freedesktop/TestPath",
- "Foo.TestInterface",
- "TestMethod");
- _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
- _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
- "TestMethod"));
- _dbus_assert (strcmp (dbus_message_get_path (message),
- "/org/freedesktop/TestPath") == 0);
- _dbus_message_set_serial (message, 1234);
-
- /* string length including nul byte not a multiple of 4 */
- if (!dbus_message_set_sender (message, "org.foo.bar1"))
- _dbus_assert_not_reached ("out of memory");
-
- _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
- dbus_message_set_reply_serial (message, 5678);
-
- _dbus_verbose_bytes_of_string (&message->header.data, 0,
- _dbus_string_get_length (&message->header.data));
- _dbus_verbose_bytes_of_string (&message->body, 0,
- _dbus_string_get_length (&message->body));
-
- if (!dbus_message_set_sender (message, NULL))
- _dbus_assert_not_reached ("out of memory");
-
-
- _dbus_verbose_bytes_of_string (&message->header.data, 0,
- _dbus_string_get_length (&message->header.data));
- _dbus_verbose_bytes_of_string (&message->body, 0,
- _dbus_string_get_length (&message->body));
-
-
- _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
- _dbus_assert (dbus_message_get_serial (message) == 1234);
- _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
- _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
-
- _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
- dbus_message_set_no_reply (message, TRUE);
- _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
- dbus_message_set_no_reply (message, FALSE);
- _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
-
- /* Set/get some header fields */
-
- if (!dbus_message_set_path (message, "/foo"))
- _dbus_assert_not_reached ("out of memory");
- _dbus_assert (strcmp (dbus_message_get_path (message),
- "/foo") == 0);
-
- if (!dbus_message_set_interface (message, "org.Foo"))
- _dbus_assert_not_reached ("out of memory");
- _dbus_assert (strcmp (dbus_message_get_interface (message),
- "org.Foo") == 0);
-
- if (!dbus_message_set_member (message, "Bar"))
- _dbus_assert_not_reached ("out of memory");
- _dbus_assert (strcmp (dbus_message_get_member (message),
- "Bar") == 0);
-
- /* Set/get them with longer values */
- if (!dbus_message_set_path (message, "/foo/bar"))
- _dbus_assert_not_reached ("out of memory");
- _dbus_assert (strcmp (dbus_message_get_path (message),
- "/foo/bar") == 0);
-
- if (!dbus_message_set_interface (message, "org.Foo.Bar"))
- _dbus_assert_not_reached ("out of memory");
- _dbus_assert (strcmp (dbus_message_get_interface (message),
- "org.Foo.Bar") == 0);
-
- if (!dbus_message_set_member (message, "BarFoo"))
- _dbus_assert_not_reached ("out of memory");
- _dbus_assert (strcmp (dbus_message_get_member (message),
- "BarFoo") == 0);
-
- /* Realloc shorter again */
-
- if (!dbus_message_set_path (message, "/foo"))
- _dbus_assert_not_reached ("out of memory");
- _dbus_assert (strcmp (dbus_message_get_path (message),
- "/foo") == 0);
-
- if (!dbus_message_set_interface (message, "org.Foo"))
- _dbus_assert_not_reached ("out of memory");
- _dbus_assert (strcmp (dbus_message_get_interface (message),
- "org.Foo") == 0);
-
- if (!dbus_message_set_member (message, "Bar"))
- _dbus_assert_not_reached ("out of memory");
- _dbus_assert (strcmp (dbus_message_get_member (message),
- "Bar") == 0);
-
- dbus_message_unref (message);
-
- /* Test the vararg functions */
- message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
- "/org/freedesktop/TestPath",
- "Foo.TestInterface",
- "TestMethod");
- _dbus_message_set_serial (message, 1);
-
- v_INT32 = -0x12345678;
-#ifdef DBUS_HAVE_INT64
- v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd);
- v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd);
-#endif
- v_STRING = "Test string";
- v_DOUBLE = 3.14159;
- v_BOOLEAN = TRUE;
- v_BYTE = 42;
- v2_BYTE = 24;
-
- dbus_message_append_args (message,
- DBUS_TYPE_INT32, &v_INT32,
-#ifdef DBUS_HAVE_INT64
- DBUS_TYPE_INT64, &v_INT64,
- DBUS_TYPE_UINT64, &v_UINT64,
-#endif
- DBUS_TYPE_STRING, &v_STRING,
- DBUS_TYPE_DOUBLE, &v_DOUBLE,
- DBUS_TYPE_BOOLEAN, &v_BOOLEAN,
- DBUS_TYPE_BYTE, &v_BYTE,
- DBUS_TYPE_BYTE, &v2_BYTE,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32,
- _DBUS_N_ELEMENTS (our_uint32_array),
- DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32,
- _DBUS_N_ELEMENTS (our_int32_array),
-#ifdef DBUS_HAVE_INT64
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64,
- _DBUS_N_ELEMENTS (our_uint64_array),
- DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64,
- _DBUS_N_ELEMENTS (our_int64_array),
-#endif
- DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE,
- _DBUS_N_ELEMENTS (our_double_array),
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE,
- _DBUS_N_ELEMENTS (our_byte_array),
- DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN,
- _DBUS_N_ELEMENTS (our_boolean_array),
- DBUS_TYPE_INVALID);
-
- i = 0;
- sig[i++] = DBUS_TYPE_INT32;
-#ifdef DBUS_HAVE_INT64
- sig[i++] = DBUS_TYPE_INT64;
- sig[i++] = DBUS_TYPE_UINT64;
-#endif
- sig[i++] = DBUS_TYPE_STRING;
- sig[i++] = DBUS_TYPE_DOUBLE;
- sig[i++] = DBUS_TYPE_BOOLEAN;
- sig[i++] = DBUS_TYPE_BYTE;
- sig[i++] = DBUS_TYPE_BYTE;
- sig[i++] = DBUS_TYPE_ARRAY;
- sig[i++] = DBUS_TYPE_UINT32;
- sig[i++] = DBUS_TYPE_ARRAY;
- sig[i++] = DBUS_TYPE_INT32;
-#ifdef DBUS_HAVE_INT64
- sig[i++] = DBUS_TYPE_ARRAY;
- sig[i++] = DBUS_TYPE_UINT64;
- sig[i++] = DBUS_TYPE_ARRAY;
- sig[i++] = DBUS_TYPE_INT64;
-#endif
- sig[i++] = DBUS_TYPE_ARRAY;
- sig[i++] = DBUS_TYPE_DOUBLE;
- sig[i++] = DBUS_TYPE_ARRAY;
- sig[i++] = DBUS_TYPE_BYTE;
- sig[i++] = DBUS_TYPE_ARRAY;
- sig[i++] = DBUS_TYPE_BOOLEAN;
- sig[i++] = DBUS_TYPE_INVALID;
-
- _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
-
- _dbus_verbose ("HEADER\n");
- _dbus_verbose_bytes_of_string (&message->header.data, 0,
- _dbus_string_get_length (&message->header.data));
- _dbus_verbose ("BODY\n");
- _dbus_verbose_bytes_of_string (&message->body, 0,
- _dbus_string_get_length (&message->body));
-
- _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
- sig, dbus_message_get_signature (message));
-
- s = dbus_message_get_signature (message);
-
- _dbus_assert (dbus_message_has_signature (message, sig));
- _dbus_assert (strcmp (s, sig) == 0);
-
- verify_test_message (message);
-
- copy = dbus_message_copy (message);
-
- _dbus_assert (dbus_message_get_reply_serial (message) ==
- dbus_message_get_reply_serial (copy));
- _dbus_assert (message->header.padding == copy->header.padding);
-
- _dbus_assert (_dbus_string_get_length (&message->header.data) ==
- _dbus_string_get_length (©->header.data));
-
- _dbus_assert (_dbus_string_get_length (&message->body) ==
- _dbus_string_get_length (©->body));
-
- verify_test_message (copy);
-
- name1 = dbus_message_get_interface (message);
- name2 = dbus_message_get_interface (copy);
-
- _dbus_assert (strcmp (name1, name2) == 0);
-
- name1 = dbus_message_get_member (message);
- name2 = dbus_message_get_member (copy);
-
- _dbus_assert (strcmp (name1, name2) == 0);
-
- dbus_message_unref (message);
- dbus_message_unref (copy);
-
-#if 0
- /* FIXME */
- message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
- "/org/freedesktop/TestPath",
- "Foo.TestInterface",
- "TestMethod");
-
- _dbus_message_set_serial (message, 1);
- dbus_message_set_reply_serial (message, 0x12345678);
-
- dbus_message_iter_init_append (message, &iter);
- dbus_message_iter_append_string (&iter, "Test string");
- dbus_message_iter_append_int32 (&iter, -0x12345678);
- dbus_message_iter_append_uint32 (&iter, 0xedd1e);
- dbus_message_iter_append_double (&iter, 3.14159);
-
- dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
- dbus_message_iter_append_double (&child_iter, 1.5);
- dbus_message_iter_append_double (&child_iter, 2.5);
-
- /* dict */
- dbus_message_iter_append_dict (&iter, &child_iter);
- dbus_message_iter_append_dict_key (&child_iter, "test");
- dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
-
- /* dict (in dict) */
- dbus_message_iter_append_dict_key (&child_iter, "testdict");
- dbus_message_iter_append_dict (&child_iter, &child_iter2);
-
- dbus_message_iter_append_dict_key (&child_iter2, "dictkey");
- dbus_message_iter_append_string (&child_iter2, "dictvalue");
-
- /* array of array of int32 (in dict) */
- dbus_message_iter_append_dict_key (&child_iter, "array");
- dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
- dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
- dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
- dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
- _dbus_warn ("next call expected to fail with wrong array type\n");
- _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
- dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
- dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
- dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
- dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
-
- dbus_message_iter_append_byte (&iter, 0xF0);
-
- dbus_message_iter_append_nil (&iter);
-
- dbus_message_iter_append_custom (&iter, "MyTypeName",
- "data", 5);
-
- dbus_message_iter_append_byte (&iter, 0xF0);
-
- dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_INT32);
-
- dbus_message_iter_append_byte (&iter, 0xF0);
-
- dbus_message_iter_append_dict (&iter, &child_iter);
-
- dbus_message_iter_append_byte (&iter, 0xF0);
-
- message_iter_test (message);
-
- /* Message loader test */
- _dbus_message_lock (message);
- loader = _dbus_message_loader_new ();
-
- /* check ref/unref */
- _dbus_message_loader_ref (loader);
- _dbus_message_loader_unref (loader);
-
- /* Write the header data one byte at a time */
- data = _dbus_string_get_const_data (&message->header);
- for (i = 0; i < _dbus_string_get_length (&message->header); i++)
- {
- DBusString *buffer;
-
- _dbus_message_loader_get_buffer (loader, &buffer);
- _dbus_string_append_byte (buffer, data[i]);
- _dbus_message_loader_return_buffer (loader, buffer, 1);
- }
-
- /* Write the body data one byte at a time */
- data = _dbus_string_get_const_data (&message->body);
- for (i = 0; i < _dbus_string_get_length (&message->body); i++)
- {
- DBusString *buffer;
-
- _dbus_message_loader_get_buffer (loader, &buffer);
- _dbus_string_append_byte (buffer, data[i]);
- _dbus_message_loader_return_buffer (loader, buffer, 1);
- }
-
- copy = dbus_message_copy (message); /* save for tests below */
- dbus_message_unref (message);
-
- /* Now pop back the message */
- if (!_dbus_message_loader_queue_messages (loader))
- _dbus_assert_not_reached ("no memory to queue messages");
-
- if (_dbus_message_loader_get_is_corrupted (loader))
- _dbus_assert_not_reached ("message loader corrupted");
-
- message = _dbus_message_loader_pop_message (loader);
- if (!message)
- _dbus_assert_not_reached ("received a NULL message");
-
- if (dbus_message_get_reply_serial (message) != 0x12345678)
- _dbus_assert_not_reached ("reply serial fields differ");
-
- message_iter_test (message);
-
- dbus_message_unref (message);
- _dbus_message_loader_unref (loader);
-
- message = dbus_message_new_method_return (copy);
- if (message == NULL)
- _dbus_assert_not_reached ("out of memory\n");
- dbus_message_unref (copy);
-
- if (!dbus_message_append_args (message,
- DBUS_TYPE_STRING, "hello",
- DBUS_TYPE_INVALID))
- _dbus_assert_not_reached ("no memory");
-
- if (!dbus_message_has_signature (message, "s"))
- _dbus_assert_not_reached ("method return has wrong signature");
-
- dbus_error_init (&error);
- if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
- &t, DBUS_TYPE_INVALID))
-
- {
- _dbus_warn ("Failed to get expected string arg: %s\n", error.message);
- exit (1);
- }
- dbus_free (t);
-
- dbus_message_unref (message);
-
- /* This ServiceAcquired message used to trigger a bug in
- * setting header fields, adding to regression test.
- */
- message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ServiceAcquired");
-
- if (message == NULL)
- _dbus_assert_not_reached ("out of memory");
-
- _dbus_verbose ("Bytes after creation\n");
- _dbus_verbose_bytes_of_string (&message->header, 0,
- _dbus_string_get_length (&message->header));
-
- if (!dbus_message_set_destination (message, ":1.0") ||
- !dbus_message_append_args (message,
- DBUS_TYPE_STRING, ":1.0",
- DBUS_TYPE_INVALID))
- _dbus_assert_not_reached ("out of memory");
-
- _dbus_verbose ("Bytes after set_destination() and append_args()\n");
- _dbus_verbose_bytes_of_string (&message->header, 0,
- _dbus_string_get_length (&message->header));
-
- if (!dbus_message_set_sender (message, "org.freedesktop.DBus"))
- _dbus_assert_not_reached ("out of memory");
-
- _dbus_verbose ("Bytes after set_sender()\n");
- _dbus_verbose_bytes_of_string (&message->header, 0,
- _dbus_string_get_length (&message->header));
-
- /* When the bug happened the above set_destination() would
- * corrupt the signature
- */
- if (!dbus_message_has_signature (message, "s"))
- {
- _dbus_warn ("Signature should be 's' but is '%s'\n",
- dbus_message_get_signature (message));
- _dbus_assert_not_reached ("signal has wrong signature");
- }
-
- /* have to set destination again to reproduce the bug */
- if (!dbus_message_set_destination (message, ":1.0"))
- _dbus_assert_not_reached ("out of memory");
-
- _dbus_verbose ("Bytes after set_destination()\n");
- _dbus_verbose_bytes_of_string (&message->header, 0,
- _dbus_string_get_length (&message->header));
-
- /* When the bug happened the above set_destination() would
- * corrupt the signature
- */
- if (!dbus_message_has_signature (message, "s"))
- {
- _dbus_warn ("Signature should be 's' but is '%s'\n",
- dbus_message_get_signature (message));
- _dbus_assert_not_reached ("signal has wrong signature");
- }
-
- dbus_error_init (&error);
- if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
- &t, DBUS_TYPE_INVALID))
-
- {
- _dbus_warn ("Failed to get expected string arg for signal: %s\n", error.message);
- exit (1);
- }
- dbus_free (t);
-
- dbus_message_unref (message);
-
- /* Now load every message in test_data_dir if we have one */
- if (test_data_dir == NULL)
- return TRUE;
-
- return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
- (DBusForeachMessageFileFunc)
- dbus_internal_do_not_use_try_message_file,
- NULL);
-
-#endif /* Commented out most tests for now */
-
- return TRUE;
-}
-
-#endif /* DBUS_BUILD_TESTS */
+/* tests in dbus-message-util.c */
Index: dbus-string-private.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string-private.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- dbus-string-private.h 9 Sep 2004 10:20:17 -0000 1.4
+++ dbus-string-private.h 17 Jan 2005 03:53:40 -0000 1.5
@@ -53,6 +53,62 @@
unsigned int align_offset : 3; /**< str - align_offset is the actual malloc block */
} DBusRealString;
+
+/**
+ * @defgroup DBusStringInternals DBusString implementation details
+ * @ingroup DBusInternals
+ * @brief DBusString implementation details
+ *
+ * The guts of DBusString.
+ *
+ * @{
+ */
+
+/**
+ * This is the maximum max length (and thus also the maximum length)
+ * of a DBusString
+ */
+#define _DBUS_STRING_MAX_MAX_LENGTH (_DBUS_INT_MAX - _DBUS_STRING_ALLOCATION_PADDING)
+
+/**
+ * Checks a bunch of assertions about a string object
+ *
+ * @param real the DBusRealString
+ */
+#define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= ((real)->allocated - _DBUS_STRING_ALLOCATION_PADDING)); _dbus_assert ((real)->len <= (real)->max_length)
+
+/**
+ * Checks assertions about a string object that needs to be
+ * modifiable - may not be locked or const. Also declares
+ * the "real" variable pointing to DBusRealString.
+ * @param str the string
+ */
+#define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
+ DBUS_GENERIC_STRING_PREAMBLE (real); \
+ _dbus_assert (!(real)->constant); \
+ _dbus_assert (!(real)->locked)
+
+/**
+ * Checks assertions about a string object that may be locked but
+ * can't be const. i.e. a string object that we can free. Also
+ * declares the "real" variable pointing to DBusRealString.
+ *
+ * @param str the string
+ */
+#define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
+ DBUS_GENERIC_STRING_PREAMBLE (real); \
+ _dbus_assert (!(real)->constant)
+
+/**
+ * Checks assertions about a string that may be const or locked. Also
+ * declares the "real" variable pointing to DBusRealString.
+ * @param str the string.
+ */
+#define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
+ DBUS_GENERIC_STRING_PREAMBLE (real)
+
+/** @} */
+
DBUS_END_DECLS
#endif /* DBUS_STRING_PRIVATE_H */
--- NEW FILE: dbus-string-util.c ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-string-util.c Would be in dbus-string.c, but not used in libdbus
*
* Copyright (C) 2002, 2003, 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
*
*/
#include "dbus-internals.h"
#include "dbus-string.h"
#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
#include "dbus-string-private.h"
/**
* @addtogroup DBusString
* @{
*/
/**
* Copies the contents of a DBusString into a different
* buffer. The resulting buffer will be nul-terminated.
*
* @param str a string
* @param buffer a C buffer to copy data to
* @param avail_len maximum length of C buffer
*/
void
_dbus_string_copy_to_buffer (const DBusString *str,
char *buffer,
int avail_len)
{
int copy_len;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (avail_len >= 0);
copy_len = MIN (avail_len, real->len+1);
memcpy (buffer, real->str, copy_len);
if (avail_len > 0 && avail_len == copy_len)
buffer[avail_len-1] = '\0';
}
/**
* Returns whether a string ends with the given suffix
*
* @todo memcmp might make this faster.
*
* @param a the string
* @param c_str the C-style string
* @returns #TRUE if the string ends with the suffix
*/
dbus_bool_t
_dbus_string_ends_with_c_str (const DBusString *a,
const char *c_str)
{
const unsigned char *ap;
const unsigned char *bp;
const unsigned char *a_end;
unsigned long c_str_len;
const DBusRealString *real_a = (const DBusRealString*) a;
DBUS_GENERIC_STRING_PREAMBLE (real_a);
_dbus_assert (c_str != NULL);
c_str_len = strlen (c_str);
if (((unsigned long)real_a->len) < c_str_len)
return FALSE;
ap = real_a->str + (real_a->len - c_str_len);
bp = (const unsigned char*) c_str;
a_end = real_a->str + real_a->len;
while (ap != a_end)
{
if (*ap != *bp)
return FALSE;
++ap;
++bp;
}
_dbus_assert (*ap == '\0');
_dbus_assert (*bp == '\0');
return TRUE;
}
/**
* Find the given byte scanning backward from the given start.
* Sets *found to -1 if the byte is not found.
*
* @param str the string
* @param start the place to start scanning (will not find the byte at this point)
* @param byte the byte to find
* @param found return location for where it was found
* @returns #TRUE if found
*/
dbus_bool_t
_dbus_string_find_byte_backward (const DBusString *str,
int start,
unsigned char byte,
int *found)
{
int i;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (start <= real->len);
_dbus_assert (start >= 0);
_dbus_assert (found != NULL);
i = start - 1;
while (i >= 0)
{
if (real->str[i] == byte)
break;
--i;
}
if (found)
*found = i;
return i >= 0;
}
/**
* Skips whitespace from start, storing the first non-whitespace in *end.
* (whitespace is space, tab, newline, CR).
*
* @param str the string
* @param start where to start
* @param end where to store the first non-whitespace byte index
*/
void
_dbus_string_skip_white (const DBusString *str,
int start,
int *end)
{
int i;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (start <= real->len);
_dbus_assert (start >= 0);
i = start;
while (i < real->len)
{
if (!(real->str[i] == ' ' ||
real->str[i] == '\n' ||
real->str[i] == '\r' ||
real->str[i] == '\t'))
break;
++i;
}
_dbus_assert (i == real->len || !(real->str[i] == ' ' ||
real->str[i] == '\t'));
if (end)
*end = i;
}
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include <stdio.h>
static void
test_max_len (DBusString *str,
int max_len)
{
if (max_len > 0)
{
if (!_dbus_string_set_length (str, max_len - 1))
_dbus_assert_not_reached ("setting len to one less than max should have worked");
}
if (!_dbus_string_set_length (str, max_len))
_dbus_assert_not_reached ("setting len to max len should have worked");
if (_dbus_string_set_length (str, max_len + 1))
_dbus_assert_not_reached ("setting len to one more than max len should not have worked");
if (!_dbus_string_set_length (str, 0))
_dbus_assert_not_reached ("setting len to zero should have worked");
}
static void
test_hex_roundtrip (const unsigned char *data,
int len)
{
DBusString orig;
DBusString encoded;
DBusString decoded;
int end;
if (len < 0)
len = strlen (data);
if (!_dbus_string_init (&orig))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_init (&encoded))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_init (&decoded))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_append_len (&orig, data, len))
_dbus_assert_not_reached ("couldn't append orig data");
if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
_dbus_assert_not_reached ("could not encode");
if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0))
_dbus_assert_not_reached ("could not decode");
_dbus_assert (_dbus_string_get_length (&encoded) == end);
if (!_dbus_string_equal (&orig, &decoded))
{
const char *s;
printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
_dbus_string_get_length (&orig),
_dbus_string_get_length (&encoded),
_dbus_string_get_length (&decoded));
printf ("Original: %s\n", data);
s = _dbus_string_get_const_data (&decoded);
printf ("Decoded: %s\n", s);
_dbus_assert_not_reached ("original string not the same as string decoded from hex");
}
_dbus_string_free (&orig);
_dbus_string_free (&encoded);
_dbus_string_free (&decoded);
}
typedef void (* TestRoundtripFunc) (const unsigned char *data,
int len);
static void
test_roundtrips (TestRoundtripFunc func)
{
(* func) ("Hello this is a string\n", -1);
(* func) ("Hello this is a string\n1", -1);
(* func) ("Hello this is a string\n12", -1);
(* func) ("Hello this is a string\n123", -1);
(* func) ("Hello this is a string\n1234", -1);
(* func) ("Hello this is a string\n12345", -1);
(* func) ("", 0);
(* func) ("1", 1);
(* func) ("12", 2);
(* func) ("123", 3);
(* func) ("1234", 4);
(* func) ("12345", 5);
(* func) ("", 1);
(* func) ("1", 2);
(* func) ("12", 3);
(* func) ("123", 4);
(* func) ("1234", 5);
(* func) ("12345", 6);
{
unsigned char buf[512];
int i;
i = 0;
while (i < _DBUS_N_ELEMENTS (buf))
{
buf[i] = i;
++i;
}
i = 0;
while (i < _DBUS_N_ELEMENTS (buf))
{
(* func) (buf, i);
++i;
}
}
}
#ifdef DBUS_BUILD_TESTS
/* The max length thing is sort of a historical artifact
* from a feature that turned out to be dumb; perhaps
* we should purge it entirely. The problem with
* the feature is that it looks like memory allocation
* failure, but is not a transient or resolvable failure.
*/
static void
set_max_length (DBusString *str,
int max_length)
{
DBusRealString *real;
real = (DBusRealString*) str;
real->max_length = max_length;
}
#endif /* DBUS_BUILD_TESTS */
/**
* @ingroup DBusStringInternals
* Unit test for DBusString.
*
* @todo Need to write tests for _dbus_string_copy() and
* _dbus_string_move() moving to/from each of start/middle/end of a
* string. Also need tests for _dbus_string_move_len ()
*
* @returns #TRUE on success.
*/
dbus_bool_t
_dbus_string_test (void)
{
DBusString str;
DBusString other;
int i, end;
long v;
double d;
int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
char *s;
dbus_unichar_t ch;
i = 0;
while (i < _DBUS_N_ELEMENTS (lens))
{
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
set_max_length (&str, lens[i]);
test_max_len (&str, lens[i]);
_dbus_string_free (&str);
++i;
}
/* Test shortening and setting length */
i = 0;
while (i < _DBUS_N_ELEMENTS (lens))
{
int j;
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
set_max_length (&str, lens[i]);
if (!_dbus_string_set_length (&str, lens[i]))
_dbus_assert_not_reached ("failed to set string length");
j = lens[i];
while (j > 0)
{
_dbus_assert (_dbus_string_get_length (&str) == j);
if (j > 0)
{
_dbus_string_shorten (&str, 1);
_dbus_assert (_dbus_string_get_length (&str) == (j - 1));
}
--j;
}
_dbus_string_free (&str);
++i;
}
/* Test appending data */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
i = 0;
while (i < 10)
{
if (!_dbus_string_append (&str, "a"))
_dbus_assert_not_reached ("failed to append string to string\n");
_dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
if (!_dbus_string_append_byte (&str, 'b'))
_dbus_assert_not_reached ("failed to append byte to string\n");
_dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
++i;
}
_dbus_string_free (&str);
/* Check steal_data */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
i = _dbus_string_get_length (&str);
if (!_dbus_string_steal_data (&str, &s))
_dbus_assert_not_reached ("failed to steal data");
_dbus_assert (_dbus_string_get_length (&str) == 0);
_dbus_assert (((int)strlen (s)) == i);
dbus_free (s);
/* Check move */
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
i = _dbus_string_get_length (&str);
if (!_dbus_string_init (&other))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_move (&str, 0, &other, 0))
_dbus_assert_not_reached ("could not move");
_dbus_assert (_dbus_string_get_length (&str) == 0);
_dbus_assert (_dbus_string_get_length (&other) == i);
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
_dbus_assert_not_reached ("could not move");
_dbus_assert (_dbus_string_get_length (&str) == 0);
_dbus_assert (_dbus_string_get_length (&other) == i * 2);
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
_dbus_assert_not_reached ("could not move");
_dbus_assert (_dbus_string_get_length (&str) == 0);
_dbus_assert (_dbus_string_get_length (&other) == i * 3);
_dbus_string_free (&other);
/* Check copy */
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
i = _dbus_string_get_length (&str);
if (!_dbus_string_init (&other))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_copy (&str, 0, &other, 0))
_dbus_assert_not_reached ("could not copy");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i);
if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
_dbus_assert_not_reached ("could not copy");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i * 2);
_dbus_assert (_dbus_string_equal_c_str (&other,
"Hello WorldHello World"));
if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
_dbus_assert_not_reached ("could not copy");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i * 3);
_dbus_assert (_dbus_string_equal_c_str (&other,
"Hello WorldHello WorldHello World"));
_dbus_string_free (&str);
_dbus_string_free (&other);
/* Check replace */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append (&str, "Hello World"))
_dbus_assert_not_reached ("could not append to string");
i = _dbus_string_get_length (&str);
if (!_dbus_string_init (&other))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
&other, 0, _dbus_string_get_length (&other)))
_dbus_assert_not_reached ("could not replace");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i);
_dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
&other, 5, 1))
_dbus_assert_not_reached ("could not replace center space");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
_dbus_assert (_dbus_string_equal_c_str (&other,
"HelloHello WorldWorld"));
if (!_dbus_string_replace_len (&str, 1, 1,
&other,
_dbus_string_get_length (&other) - 1,
1))
_dbus_assert_not_reached ("could not replace end character");
_dbus_assert (_dbus_string_get_length (&str) == i);
_dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
_dbus_assert (_dbus_string_equal_c_str (&other,
"HelloHello WorldWorle"));
_dbus_string_free (&str);
_dbus_string_free (&other);
/* Check append/get unichar */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
ch = 0;
if (!_dbus_string_append_unichar (&str, 0xfffc))
_dbus_assert_not_reached ("failed to append unichar");
_dbus_string_get_unichar (&str, 0, &ch, &i);
_dbus_assert (ch == 0xfffc);
_dbus_assert (i == _dbus_string_get_length (&str));
_dbus_string_free (&str);
/* Check insert/set/get byte */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append (&str, "Hello"))
_dbus_assert_not_reached ("failed to append Hello");
_dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
_dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
_dbus_string_set_byte (&str, 1, 'q');
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
_dbus_assert_not_reached ("can't insert byte");
if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
_dbus_assert_not_reached ("can't insert byte");
if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
_dbus_assert_not_reached ("can't insert byte");
_dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
_dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
_dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
_dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
_dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
_dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
_dbus_string_free (&str);
/* Check append/parse int/double */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append_int (&str, 27))
_dbus_assert_not_reached ("failed to append int");
i = _dbus_string_get_length (&str);
if (!_dbus_string_parse_int (&str, 0, &v, &end))
_dbus_assert_not_reached ("failed to parse int");
_dbus_assert (v == 27);
_dbus_assert (end == i);
_dbus_string_free (&str);
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append_double (&str, 50.3))
_dbus_assert_not_reached ("failed to append float");
i = _dbus_string_get_length (&str);
if (!_dbus_string_parse_double (&str, 0, &d, &end))
_dbus_assert_not_reached ("failed to parse float");
_dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
_dbus_assert (end == i);
_dbus_string_free (&str);
/* Test find */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
if (!_dbus_string_append (&str, "Hello"))
_dbus_assert_not_reached ("couldn't append to string");
if (!_dbus_string_find (&str, 0, "He", &i))
_dbus_assert_not_reached ("didn't find 'He'");
_dbus_assert (i == 0);
if (!_dbus_string_find (&str, 0, "Hello", &i))
_dbus_assert_not_reached ("didn't find 'Hello'");
_dbus_assert (i == 0);
if (!_dbus_string_find (&str, 0, "ello", &i))
_dbus_assert_not_reached ("didn't find 'ello'");
_dbus_assert (i == 1);
if (!_dbus_string_find (&str, 0, "lo", &i))
_dbus_assert_not_reached ("didn't find 'lo'");
_dbus_assert (i == 3);
if (!_dbus_string_find (&str, 2, "lo", &i))
_dbus_assert_not_reached ("didn't find 'lo'");
_dbus_assert (i == 3);
if (_dbus_string_find (&str, 4, "lo", &i))
_dbus_assert_not_reached ("did find 'lo'");
if (!_dbus_string_find (&str, 0, "l", &i))
_dbus_assert_not_reached ("didn't find 'l'");
_dbus_assert (i == 2);
if (!_dbus_string_find (&str, 0, "H", &i))
_dbus_assert_not_reached ("didn't find 'H'");
_dbus_assert (i == 0);
if (!_dbus_string_find (&str, 0, "", &i))
_dbus_assert_not_reached ("didn't find ''");
_dbus_assert (i == 0);
if (_dbus_string_find (&str, 0, "Hello!", NULL))
_dbus_assert_not_reached ("Did find 'Hello!'");
if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
_dbus_assert_not_reached ("Did find 'Oh, Hello'");
if (_dbus_string_find (&str, 0, "ill", NULL))
_dbus_assert_not_reached ("Did find 'ill'");
if (_dbus_string_find (&str, 0, "q", NULL))
_dbus_assert_not_reached ("Did find 'q'");
if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
_dbus_assert_not_reached ("Didn't find 'He'");
if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
_dbus_assert_not_reached ("Did find 'Hello'");
if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
_dbus_assert_not_reached ("Did not find 'H'");
_dbus_assert (i == 0);
if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
_dbus_assert_not_reached ("Did not find 'o'");
_dbus_assert (i == _dbus_string_get_length (&str) - 1);
if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
_dbus_assert_not_reached ("Did find 'o'");
_dbus_assert (i == -1);
if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
_dbus_assert_not_reached ("Did find 'e'");
_dbus_assert (i == -1);
if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
_dbus_assert_not_reached ("Didn't find 'e'");
_dbus_assert (i == 1);
_dbus_string_free (&str);
/* Hex encoding */
_dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
if (!_dbus_string_init (&other))
_dbus_assert_not_reached ("could not init string");
if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
_dbus_assert_not_reached ("deccoded bogus hex string with no error");
_dbus_assert (end == 8);
_dbus_string_free (&other);
test_roundtrips (test_hex_roundtrip);
_dbus_string_free (&str);
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */
Index: dbus-string.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -d -r1.63 -r1.64
--- dbus-string.c 16 Jan 2005 15:51:55 -0000 1.63
+++ dbus-string.c 17 Jan 2005 03:53:40 -0000 1.64
@@ -69,61 +69,6 @@
*/
/**
- * @defgroup DBusStringInternals DBusString implementation details
- * @ingroup DBusInternals
- * @brief DBusString implementation details
- *
- * The guts of DBusString.
- *
- * @{
- */
-
-/**
- * This is the maximum max length (and thus also the maximum length)
- * of a DBusString
- */
-#define MAX_MAX_LENGTH (_DBUS_INT_MAX - _DBUS_STRING_ALLOCATION_PADDING)
-
-/**
- * Checks a bunch of assertions about a string object
- *
- * @param real the DBusRealString
- */
-#define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= ((real)->allocated - _DBUS_STRING_ALLOCATION_PADDING)); _dbus_assert ((real)->len <= (real)->max_length)
-
-/**
- * Checks assertions about a string object that needs to be
- * modifiable - may not be locked or const. Also declares
- * the "real" variable pointing to DBusRealString.
- * @param str the string
- */
-#define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
- DBUS_GENERIC_STRING_PREAMBLE (real); \
- _dbus_assert (!(real)->constant); \
- _dbus_assert (!(real)->locked)
-
-/**
- * Checks assertions about a string object that may be locked but
- * can't be const. i.e. a string object that we can free. Also
- * declares the "real" variable pointing to DBusRealString.
- *
- * @param str the string
- */
-#define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
- DBUS_GENERIC_STRING_PREAMBLE (real); \
- _dbus_assert (!(real)->constant)
-
-/**
- * Checks assertions about a string that may be const or locked. Also
- * declares the "real" variable pointing to DBusRealString.
- * @param str the string.
- */
-#define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
- DBUS_GENERIC_STRING_PREAMBLE (real)
-
-/** @} */
-
-/**
* @addtogroup DBusString
* @{
*/
@@ -207,7 +152,7 @@
real->len = 0;
real->str[real->len] = '\0';
- real->max_length = MAX_MAX_LENGTH;
+ real->max_length = _DBUS_STRING_MAX_MAX_LENGTH;
real->constant = FALSE;
real->locked = FALSE;
real->invalid = FALSE;
@@ -231,6 +176,7 @@
return _dbus_string_init_preallocated (str, 0);
}
+#ifdef DBUS_BUILD_TESTS
/* The max length thing is sort of a historical artifact
* from a feature that turned out to be dumb; perhaps
* we should purge it entirely. The problem with
@@ -247,6 +193,7 @@
real->max_length = max_length;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Initializes a constant string. The value parameter is not copied
@@ -286,7 +233,7 @@
_dbus_assert (str != NULL);
_dbus_assert (value != NULL);
- _dbus_assert (len <= MAX_MAX_LENGTH);
+ _dbus_assert (len <= _DBUS_STRING_MAX_MAX_LENGTH);
_dbus_assert (len >= 0);
real = (DBusRealString*) str;
@@ -376,8 +323,8 @@
/* at least double our old allocation to avoid O(n), avoiding
* overflow
*/
- if (real->allocated > (MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
- new_allocated = MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
+ if (real->allocated > (_DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
+ new_allocated = _DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
else
new_allocated = real->allocated * 2;
@@ -454,6 +401,7 @@
return TRUE;
}
+#ifndef _dbus_string_get_data
/**
* Gets the raw character buffer from the string. The returned buffer
* will be nul-terminated, but note that strings may contain binary
@@ -472,6 +420,7 @@
return real->str;
}
+#endif /* _dbus_string_get_data */
/* only do the function if we don't have the macro */
#ifndef _dbus_string_get_const_data
@@ -683,6 +632,7 @@
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Like _dbus_string_get_data_len(), but removes the gotten data from
* the original string. The caller must free the data returned. This
@@ -733,7 +683,7 @@
_dbus_string_free (&dest);
return TRUE;
}
-
+#endif /* DBUS_BUILD_TESTS */
/**
* Copies the data from the string into a char*
@@ -758,6 +708,7 @@
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Copies a segment of the string into a char*
*
@@ -802,30 +753,7 @@
_dbus_string_free (&dest);
return TRUE;
}
-
-/**
- * Copies the contents of a DBusString into a different
- * buffer. The resulting buffer will be nul-terminated.
- *
- * @param str a string
- * @param buffer a C buffer to copy data to
- * @param avail_len maximum length of C buffer
- */
-void
-_dbus_string_copy_to_buffer (const DBusString *str,
- char *buffer,
- int avail_len)
-{
- int copy_len;
- DBUS_CONST_STRING_PREAMBLE (str);
-
- _dbus_assert (avail_len >= 0);
-
- copy_len = MIN (avail_len, real->len+1);
- memcpy (buffer, real->str, copy_len);
- if (avail_len > 0 && avail_len == copy_len)
- buffer[avail_len-1] = '\0';
-}
+#endif /* DBUS_BUILD_TESTS */
/* Only have the function if we don't have the macro */
#ifndef _dbus_string_get_length
@@ -1046,6 +974,7 @@
return append (real, buffer, buffer_len);
}
+
/** assign 4 bytes from one string to another */
#define ASSIGN_4_OCTETS(p, octets) \
*((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
@@ -1074,6 +1003,7 @@
} while (0)
#endif /* DBUS_HAVE_INT64 */
+#ifdef DBUS_BUILD_TESTS
/**
* Appends 4 bytes aligned on a 4 byte boundary
* with any alignment padding initialized to 0.
@@ -1095,7 +1025,9 @@
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
+#ifdef DBUS_BUILD_TESTS
/**
* Appends 8 bytes aligned on an 8 byte boundary
* with any alignment padding initialized to 0.
@@ -1117,6 +1049,7 @@
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Inserts 4 bytes aligned on a 4 byte boundary
@@ -1299,6 +1232,7 @@
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Appends a single Unicode character, encoding the character
* in UTF-8 format.
@@ -1369,6 +1303,7 @@
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
static void
delete (DBusRealString *real,
@@ -1730,6 +1665,7 @@
((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
((Char) & 0xFFFF) != 0xFFFF)
+#ifdef DBUS_BUILD_TESTS
/**
* Gets a unicode character from a UTF-8 string. Does no validation;
* you must verify that the string is valid UTF-8 in advance and must
@@ -1776,6 +1712,7 @@
if (end_return)
*end_return = start + len;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Finds the given substring in the string,
@@ -1877,43 +1814,6 @@
}
/**
- * Find the given byte scanning backward from the given start.
- * Sets *found to -1 if the byte is not found.
- *
- * @param str the string
- * @param start the place to start scanning (will not find the byte at this point)
- * @param byte the byte to find
- * @param found return location for where it was found
- * @returns #TRUE if found
- */
-dbus_bool_t
-_dbus_string_find_byte_backward (const DBusString *str,
- int start,
- unsigned char byte,
- int *found)
-{
- int i;
- DBUS_CONST_STRING_PREAMBLE (str);
- _dbus_assert (start <= real->len);
- _dbus_assert (start >= 0);
- _dbus_assert (found != NULL);
-
- i = start - 1;
- while (i >= 0)
- {
- if (real->str[i] == byte)
- break;
-
- --i;
- }
-
- if (found)
- *found = i;
-
- return i >= 0;
-}
-
-/**
* Finds a blank (space or tab) in the string. Returns #TRUE
* if found, #FALSE otherwise. If a blank is not found sets
* *found to the length of the string.
@@ -1989,43 +1889,6 @@
}
/**
- * Skips whitespace from start, storing the first non-whitespace in *end.
- * (whitespace is space, tab, newline, CR).
- *
- * @param str the string
- * @param start where to start
- * @param end where to store the first non-whitespace byte index
- */
-void
-_dbus_string_skip_white (const DBusString *str,
- int start,
- int *end)
-{
- int i;
- DBUS_CONST_STRING_PREAMBLE (str);
- _dbus_assert (start <= real->len);
- _dbus_assert (start >= 0);
-
- i = start;
- while (i < real->len)
- {
- if (!(real->str[i] == ' ' ||
- real->str[i] == '\n' ||
- real->str[i] == '\r' ||
- real->str[i] == '\t'))
- break;
-
- ++i;
- }
-
- _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
- real->str[i] == '\t'));
-
- if (end)
- *end = i;
-}
-
-/**
* Assigns a newline-terminated or \\r\\n-terminated line from the front
* of the string to the given dest string. The dest string's previous
* contents are deleted. If the source string contains no newline,
@@ -2092,6 +1955,7 @@
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Deletes up to and including the first blank space
* in the string.
@@ -2108,7 +1972,9 @@
_dbus_string_delete (str, 0, i);
}
+#endif
+#ifdef DBUS_BUILD_TESTS
/**
* Deletes any leading blanks in the string
*
@@ -2124,6 +1990,7 @@
if (i > 0)
_dbus_string_delete (str, 0, i);
}
+#endif
/**
* Tests two DBusString for equality.
@@ -2164,6 +2031,7 @@
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Tests two DBusString for equality up to the given length.
* The strings may be shorter than the given length.
@@ -2208,6 +2076,7 @@
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Tests two sub-parts of two DBusString for equality. The specified
@@ -2302,6 +2171,7 @@
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Checks whether a string starts with the given C string.
*
@@ -2337,49 +2207,7 @@
else
return FALSE;
}
-
-/**
- * Returns whether a string ends with the given suffix
- *
- * @todo memcmp might make this faster.
- *
- * @param a the string
- * @param c_str the C-style string
- * @returns #TRUE if the string ends with the suffix
- */
-dbus_bool_t
-_dbus_string_ends_with_c_str (const DBusString *a,
- const char *c_str)
-{
- const unsigned char *ap;
- const unsigned char *bp;
- const unsigned char *a_end;
- unsigned long c_str_len;
- const DBusRealString *real_a = (const DBusRealString*) a;
- DBUS_GENERIC_STRING_PREAMBLE (real_a);
- _dbus_assert (c_str != NULL);
-
- c_str_len = strlen (c_str);
- if (((unsigned long)real_a->len) < c_str_len)
- return FALSE;
-
- ap = real_a->str + (real_a->len - c_str_len);
- bp = (const unsigned char*) c_str;
- a_end = real_a->str + real_a->len;
- while (ap != a_end)
- {
- if (*ap != *bp)
- return FALSE;
-
- ++ap;
- ++bp;
- }
-
- _dbus_assert (*ap == '\0');
- _dbus_assert (*bp == '\0');
-
- return TRUE;
-}
+#endif /* DBUS_BUILD_TESTS */
/**
* Encodes a string in hex, the way MD5 and SHA-1 are usually
@@ -2773,643 +2601,4 @@
}
/** @} */
-#ifdef DBUS_BUILD_TESTS
-#include "dbus-test.h"
-#include <stdio.h>
-
-/**
- * Parses a basic type defined by type contained in a DBusString. The
- * end_return parameter may be #NULL if you aren't interested in it. The
- * type is parsed and stored in value_return. Return parameters are not
- * initialized if the function returns #FALSE.
- *
- * @param str the string
- * @param type the type of the basic type
- * @param start the byte index of the start of the type
- * @param value_return return location of the value or #NULL
- * @param end_return return location of the end of the type, or #NULL
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_string_parse_basic_type (const DBusString *str,
- char type,
- int start,
- void *value,
- int *end_return)
-{
- int end = start;
-
- switch (type)
- {
- case DBUS_TYPE_BOOLEAN:
- {
- int len = _dbus_string_get_length (str) - start;
- if (len >= 5 && _dbus_string_find_to (str, start, start + 5, "false", NULL))
- {
- end += 5;
- *(unsigned char *) value = TRUE;
- }
- else if (len >= 4 && _dbus_string_find_to (str, start, start + 4, "true", NULL))
- {
- end += 4;
- *(unsigned char *) value = FALSE;
- }
- else
- _dbus_warn ("could not parse BOOLEAN\n");
- break;
- }
- case DBUS_TYPE_BYTE:
- {
- long val = 0;
-
- if (_dbus_string_get_byte (str, start) == '\'' &&
- _dbus_string_get_length (str) >= start + 4 &&
- _dbus_string_get_byte (str, start + 1) == '\\' &&
- _dbus_string_get_byte (str, start + 2) == '\'' &&
- _dbus_string_get_byte (str, start + 3) == '\'')
- {
- val = '\'';
- end += 4;
- }
- else if (_dbus_string_get_byte (str, start) == '\'' &&
- _dbus_string_get_length (str) >= start + 3 &&
- _dbus_string_get_byte (str, start + 2) == '\'')
- {
- val = _dbus_string_get_byte (str, start + 1);
- end += 3;
- }
- else
- {
- if (!_dbus_string_parse_int (str, start, &val, &end))
- _dbus_warn ("Failed to parse integer for BYTE\n");
- }
-
- if (val > 255)
- _dbus_warn ("A byte must be in range 0-255 not %ld\n", val);
-
- *(unsigned char *) value = val;
- break;
- }
- case DBUS_TYPE_INT32:
- {
- long val;
- if (_dbus_string_parse_int (str, start, &val, &end))
- *(dbus_int32_t *)value = val;
- break;
- }
- case DBUS_TYPE_UINT32:
- {
- unsigned long val;
- if (_dbus_string_parse_uint (str, start, &val, &end))
- *(dbus_uint32_t *)value = val;
- break;
- }
-#ifdef DBUS_HAVE_INT64
- case DBUS_TYPE_INT64:
- case DBUS_TYPE_UINT64:
- /* use stroll oull */
- _dbus_assert_not_reached ("string -> [u]int64 not supported yet");
- break;
-#endif /* DBUS_HAVE_INT64 */
- case DBUS_TYPE_DOUBLE:
- _dbus_string_parse_double (str, start, value, &end);
- break;
- default:
- _dbus_assert_not_reached ("not a basic type");
- break;
- }
- if (end_return)
- *end_return = end;
-
- return end != start;
-}
-
-static void
-test_max_len (DBusString *str,
- int max_len)
-{
- if (max_len > 0)
- {
- if (!_dbus_string_set_length (str, max_len - 1))
- _dbus_assert_not_reached ("setting len to one less than max should have worked");
- }
-
- if (!_dbus_string_set_length (str, max_len))
- _dbus_assert_not_reached ("setting len to max len should have worked");
-
- if (_dbus_string_set_length (str, max_len + 1))
- _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
-
- if (!_dbus_string_set_length (str, 0))
- _dbus_assert_not_reached ("setting len to zero should have worked");
-}
-
-static void
-test_hex_roundtrip (const unsigned char *data,
- int len)
-{
- DBusString orig;
- DBusString encoded;
- DBusString decoded;
- int end;
-
- if (len < 0)
- len = strlen (data);
-
- if (!_dbus_string_init (&orig))
- _dbus_assert_not_reached ("could not init string");
-
- if (!_dbus_string_init (&encoded))
- _dbus_assert_not_reached ("could not init string");
-
- if (!_dbus_string_init (&decoded))
- _dbus_assert_not_reached ("could not init string");
-
- if (!_dbus_string_append_len (&orig, data, len))
- _dbus_assert_not_reached ("couldn't append orig data");
-
- if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
- _dbus_assert_not_reached ("could not encode");
-
- if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0))
- _dbus_assert_not_reached ("could not decode");
-
- _dbus_assert (_dbus_string_get_length (&encoded) == end);
-
- if (!_dbus_string_equal (&orig, &decoded))
- {
- const char *s;
-
- printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
- _dbus_string_get_length (&orig),
- _dbus_string_get_length (&encoded),
- _dbus_string_get_length (&decoded));
- printf ("Original: %s\n", data);
- s = _dbus_string_get_const_data (&decoded);
- printf ("Decoded: %s\n", s);
- _dbus_assert_not_reached ("original string not the same as string decoded from hex");
- }
-
- _dbus_string_free (&orig);
- _dbus_string_free (&encoded);
- _dbus_string_free (&decoded);
-}
-
-typedef void (* TestRoundtripFunc) (const unsigned char *data,
- int len);
-static void
-test_roundtrips (TestRoundtripFunc func)
-{
- (* func) ("Hello this is a string\n", -1);
- (* func) ("Hello this is a string\n1", -1);
- (* func) ("Hello this is a string\n12", -1);
- (* func) ("Hello this is a string\n123", -1);
- (* func) ("Hello this is a string\n1234", -1);
- (* func) ("Hello this is a string\n12345", -1);
- (* func) ("", 0);
- (* func) ("1", 1);
- (* func) ("12", 2);
- (* func) ("123", 3);
- (* func) ("1234", 4);
- (* func) ("12345", 5);
- (* func) ("", 1);
- (* func) ("1", 2);
- (* func) ("12", 3);
- (* func) ("123", 4);
- (* func) ("1234", 5);
- (* func) ("12345", 6);
- {
- unsigned char buf[512];
- int i;
-
- i = 0;
- while (i < _DBUS_N_ELEMENTS (buf))
- {
- buf[i] = i;
- ++i;
- }
- i = 0;
- while (i < _DBUS_N_ELEMENTS (buf))
- {
- (* func) (buf, i);
- ++i;
- }
- }
-}
-
-
-/**
- * @ingroup DBusStringInternals
- * Unit test for DBusString.
- *
- * @todo Need to write tests for _dbus_string_copy() and
- * _dbus_string_move() moving to/from each of start/middle/end of a
- * string. Also need tests for _dbus_string_move_len ()
- *
- * @returns #TRUE on success.
- */
-dbus_bool_t
-_dbus_string_test (void)
-{
- DBusString str;
- DBusString other;
- int i, end;
- long v;
- double d;
- int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
- char *s;
- dbus_unichar_t ch;
-
- i = 0;
- while (i < _DBUS_N_ELEMENTS (lens))
- {
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- set_max_length (&str, lens[i]);
-
- test_max_len (&str, lens[i]);
- _dbus_string_free (&str);
-
- ++i;
- }
-
- /* Test shortening and setting length */
- i = 0;
- while (i < _DBUS_N_ELEMENTS (lens))
- {
- int j;
-
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- set_max_length (&str, lens[i]);
-
- if (!_dbus_string_set_length (&str, lens[i]))
- _dbus_assert_not_reached ("failed to set string length");
-
- j = lens[i];
- while (j > 0)
- {
- _dbus_assert (_dbus_string_get_length (&str) == j);
- if (j > 0)
- {
- _dbus_string_shorten (&str, 1);
- _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
- }
- --j;
- }
-
- _dbus_string_free (&str);
-
- ++i;
- }
-
- /* Test appending data */
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- i = 0;
- while (i < 10)
- {
- if (!_dbus_string_append (&str, "a"))
- _dbus_assert_not_reached ("failed to append string to string\n");
-
- _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
-
- if (!_dbus_string_append_byte (&str, 'b'))
- _dbus_assert_not_reached ("failed to append byte to string\n");
-
- _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
-
- ++i;
- }
-
- _dbus_string_free (&str);
-
- /* Check steal_data */
-
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- if (!_dbus_string_append (&str, "Hello World"))
- _dbus_assert_not_reached ("could not append to string");
-
- i = _dbus_string_get_length (&str);
-
- if (!_dbus_string_steal_data (&str, &s))
- _dbus_assert_not_reached ("failed to steal data");
-
- _dbus_assert (_dbus_string_get_length (&str) == 0);
- _dbus_assert (((int)strlen (s)) == i);
-
- dbus_free (s);
-
- /* Check move */
-
- if (!_dbus_string_append (&str, "Hello World"))
- _dbus_assert_not_reached ("could not append to string");
-
- i = _dbus_string_get_length (&str);
-
- if (!_dbus_string_init (&other))
- _dbus_assert_not_reached ("could not init string");
-
- if (!_dbus_string_move (&str, 0, &other, 0))
- _dbus_assert_not_reached ("could not move");
-
- _dbus_assert (_dbus_string_get_length (&str) == 0);
- _dbus_assert (_dbus_string_get_length (&other) == i);
-
- if (!_dbus_string_append (&str, "Hello World"))
- _dbus_assert_not_reached ("could not append to string");
-
- if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
- _dbus_assert_not_reached ("could not move");
-
- _dbus_assert (_dbus_string_get_length (&str) == 0);
- _dbus_assert (_dbus_string_get_length (&other) == i * 2);
-
- if (!_dbus_string_append (&str, "Hello World"))
- _dbus_assert_not_reached ("could not append to string");
-
- if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
- _dbus_assert_not_reached ("could not move");
-
- _dbus_assert (_dbus_string_get_length (&str) == 0);
- _dbus_assert (_dbus_string_get_length (&other) == i * 3);
-
- _dbus_string_free (&other);
-
- /* Check copy */
-
- if (!_dbus_string_append (&str, "Hello World"))
- _dbus_assert_not_reached ("could not append to string");
-
- i = _dbus_string_get_length (&str);
-
- if (!_dbus_string_init (&other))
- _dbus_assert_not_reached ("could not init string");
-
- if (!_dbus_string_copy (&str, 0, &other, 0))
- _dbus_assert_not_reached ("could not copy");
-
- _dbus_assert (_dbus_string_get_length (&str) == i);
- _dbus_assert (_dbus_string_get_length (&other) == i);
-
- if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
- _dbus_assert_not_reached ("could not copy");
-
- _dbus_assert (_dbus_string_get_length (&str) == i);
- _dbus_assert (_dbus_string_get_length (&other) == i * 2);
- _dbus_assert (_dbus_string_equal_c_str (&other,
- "Hello WorldHello World"));
-
- if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
- _dbus_assert_not_reached ("could not copy");
-
- _dbus_assert (_dbus_string_get_length (&str) == i);
- _dbus_assert (_dbus_string_get_length (&other) == i * 3);
- _dbus_assert (_dbus_string_equal_c_str (&other,
- "Hello WorldHello WorldHello World"));
-
- _dbus_string_free (&str);
- _dbus_string_free (&other);
-
- /* Check replace */
-
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- if (!_dbus_string_append (&str, "Hello World"))
- _dbus_assert_not_reached ("could not append to string");
-
- i = _dbus_string_get_length (&str);
-
- if (!_dbus_string_init (&other))
- _dbus_assert_not_reached ("could not init string");
-
- if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
- &other, 0, _dbus_string_get_length (&other)))
- _dbus_assert_not_reached ("could not replace");
-
- _dbus_assert (_dbus_string_get_length (&str) == i);
- _dbus_assert (_dbus_string_get_length (&other) == i);
- _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
-
- if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
- &other, 5, 1))
- _dbus_assert_not_reached ("could not replace center space");
-
- _dbus_assert (_dbus_string_get_length (&str) == i);
- _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
- _dbus_assert (_dbus_string_equal_c_str (&other,
- "HelloHello WorldWorld"));
-
-
- if (!_dbus_string_replace_len (&str, 1, 1,
- &other,
- _dbus_string_get_length (&other) - 1,
- 1))
- _dbus_assert_not_reached ("could not replace end character");
-
- _dbus_assert (_dbus_string_get_length (&str) == i);
- _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
- _dbus_assert (_dbus_string_equal_c_str (&other,
- "HelloHello WorldWorle"));
-
- _dbus_string_free (&str);
- _dbus_string_free (&other);
-
- /* Check append/get unichar */
-
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- ch = 0;
- if (!_dbus_string_append_unichar (&str, 0xfffc))
- _dbus_assert_not_reached ("failed to append unichar");
-
- _dbus_string_get_unichar (&str, 0, &ch, &i);
-
- _dbus_assert (ch == 0xfffc);
- _dbus_assert (i == _dbus_string_get_length (&str));
-
- _dbus_string_free (&str);
-
- /* Check insert/set/get byte */
-
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- if (!_dbus_string_append (&str, "Hello"))
- _dbus_assert_not_reached ("failed to append Hello");
-
- _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
- _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
- _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
- _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
- _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
-
- _dbus_string_set_byte (&str, 1, 'q');
- _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
-
- if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
- _dbus_assert_not_reached ("can't insert byte");
-
- if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
- _dbus_assert_not_reached ("can't insert byte");
-
- if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
- _dbus_assert_not_reached ("can't insert byte");
-
- _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
- _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
- _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
- _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
- _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
- _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
- _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
- _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
- _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
- _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
- _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
-
- _dbus_string_free (&str);
-
- /* Check append/parse int/double */
-
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- if (!_dbus_string_append_int (&str, 27))
- _dbus_assert_not_reached ("failed to append int");
-
- i = _dbus_string_get_length (&str);
-
- if (!_dbus_string_parse_int (&str, 0, &v, &end))
- _dbus_assert_not_reached ("failed to parse int");
-
- _dbus_assert (v == 27);
- _dbus_assert (end == i);
-
- _dbus_string_free (&str);
-
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- if (!_dbus_string_append_double (&str, 50.3))
- _dbus_assert_not_reached ("failed to append float");
-
- i = _dbus_string_get_length (&str);
-
- if (!_dbus_string_parse_double (&str, 0, &d, &end))
- _dbus_assert_not_reached ("failed to parse float");
-
- _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
- _dbus_assert (end == i);
-
- _dbus_string_free (&str);
-
- /* Test find */
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- if (!_dbus_string_append (&str, "Hello"))
- _dbus_assert_not_reached ("couldn't append to string");
-
- if (!_dbus_string_find (&str, 0, "He", &i))
- _dbus_assert_not_reached ("didn't find 'He'");
- _dbus_assert (i == 0);
-
- if (!_dbus_string_find (&str, 0, "Hello", &i))
- _dbus_assert_not_reached ("didn't find 'Hello'");
- _dbus_assert (i == 0);
-
- if (!_dbus_string_find (&str, 0, "ello", &i))
- _dbus_assert_not_reached ("didn't find 'ello'");
- _dbus_assert (i == 1);
-
- if (!_dbus_string_find (&str, 0, "lo", &i))
- _dbus_assert_not_reached ("didn't find 'lo'");
- _dbus_assert (i == 3);
-
- if (!_dbus_string_find (&str, 2, "lo", &i))
- _dbus_assert_not_reached ("didn't find 'lo'");
- _dbus_assert (i == 3);
-
- if (_dbus_string_find (&str, 4, "lo", &i))
- _dbus_assert_not_reached ("did find 'lo'");
-
- if (!_dbus_string_find (&str, 0, "l", &i))
- _dbus_assert_not_reached ("didn't find 'l'");
- _dbus_assert (i == 2);
-
- if (!_dbus_string_find (&str, 0, "H", &i))
- _dbus_assert_not_reached ("didn't find 'H'");
- _dbus_assert (i == 0);
-
- if (!_dbus_string_find (&str, 0, "", &i))
- _dbus_assert_not_reached ("didn't find ''");
- _dbus_assert (i == 0);
-
- if (_dbus_string_find (&str, 0, "Hello!", NULL))
- _dbus_assert_not_reached ("Did find 'Hello!'");
-
- if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
- _dbus_assert_not_reached ("Did find 'Oh, Hello'");
-
- if (_dbus_string_find (&str, 0, "ill", NULL))
- _dbus_assert_not_reached ("Did find 'ill'");
-
- if (_dbus_string_find (&str, 0, "q", NULL))
- _dbus_assert_not_reached ("Did find 'q'");
-
- if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
- _dbus_assert_not_reached ("Didn't find 'He'");
-
- if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
- _dbus_assert_not_reached ("Did find 'Hello'");
-
- if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
- _dbus_assert_not_reached ("Did not find 'H'");
- _dbus_assert (i == 0);
-
- if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
- _dbus_assert_not_reached ("Did not find 'o'");
- _dbus_assert (i == _dbus_string_get_length (&str) - 1);
-
- if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
- _dbus_assert_not_reached ("Did find 'o'");
- _dbus_assert (i == -1);
-
- if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
- _dbus_assert_not_reached ("Did find 'e'");
- _dbus_assert (i == -1);
-
- if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
- _dbus_assert_not_reached ("Didn't find 'e'");
- _dbus_assert (i == 1);
-
- _dbus_string_free (&str);
-
- /* Hex encoding */
- _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
- if (!_dbus_string_init (&other))
- _dbus_assert_not_reached ("could not init string");
-
- if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
- _dbus_assert_not_reached ("deccoded bogus hex string with no error");
-
- _dbus_assert (end == 8);
-
- _dbus_string_free (&other);
-
- test_roundtrips (test_hex_roundtrip);
-
- _dbus_string_free (&str);
-
- return TRUE;
-}
-
-#endif /* DBUS_BUILD_TESTS */
+/* tests are in dbus-string-util.c */
Index: dbus-string.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string.h,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- dbus-string.h 16 Jan 2005 02:23:56 -0000 1.36
+++ dbus-string.h 17 Jan 2005 03:53:40 -0000 1.37
@@ -54,6 +54,7 @@
* to inline non-exported symbols across files in the library.
* Note that these break type safety (due to the casts)
*/
+#define _dbus_string_get_data(s) ((char*)(((DBusString*)(s))->dummy1))
#define _dbus_string_get_length(s) (((DBusString*)(s))->dummy2)
#define _dbus_string_set_byte(s, i, b) ((((unsigned char*)(((DBusString*)(s))->dummy1))[(i)]) = (unsigned char) (b))
#define _dbus_string_get_byte(s, i) (((const unsigned char*)(((DBusString*)(s))->dummy1))[(i)])
@@ -71,7 +72,9 @@
int allocate_size);
void _dbus_string_free (DBusString *str);
void _dbus_string_lock (DBusString *str);
+#ifndef _dbus_string_get_data
char* _dbus_string_get_data (DBusString *str);
+#endif /* _dbus_string_get_data */
#ifndef _dbus_string_get_const_data
const char* _dbus_string_get_const_data (const DBusString *str);
#endif /* _dbus_string_get_const_data */
@@ -205,11 +208,6 @@
int start,
double *value,
int *end_return);
-dbus_bool_t _dbus_string_parse_basic_type (const DBusString *str,
- char type,
- int start,
- void *value,
- int *end_return);
dbus_bool_t _dbus_string_find (const DBusString *str,
int start,
const char *substr,
--- NEW FILE: dbus-sysdeps-util.c ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-sysdeps-util.c Would be in dbus-sysdeps.c, but not used in libdbus
*
* Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
* Copyright (C) 2003 CodeFactory AB
*
* 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
*
*/
#include "dbus-sysdeps.h"
#include "dbus-internals.h"
#include "dbus-protocol.h"
#include "dbus-string.h"
#define DBUS_USERDB_INCLUDES_PRIVATE 1
#include "dbus-userdb.h"
#include "dbus-test.h"
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <grp.h>
#include <sys/socket.h>
#include <dirent.h>
#include <sys/un.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
/**
* @addtogroup DBusInternalsUtils
* @{
*/
/**
* Does the chdir, fork, setsid, etc. to become a daemon process.
*
* @param pidfile #NULL, or pidfile to create
* @param print_pid_fd file descriptor to print pid to, or -1 for none
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
_dbus_become_daemon (const DBusString *pidfile,
int print_pid_fd,
DBusError *error)
{
const char *s;
pid_t child_pid;
int dev_null_fd;
_dbus_verbose ("Becoming a daemon...\n");
_dbus_verbose ("chdir to /\n");
if (chdir ("/") < 0)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Could not chdir() to root directory");
return FALSE;
}
_dbus_verbose ("forking...\n");
switch ((child_pid = fork ()))
{
case -1:
_dbus_verbose ("fork failed\n");
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to fork daemon: %s", _dbus_strerror (errno));
return FALSE;
break;
case 0:
_dbus_verbose ("in child, closing std file descriptors\n");
/* silently ignore failures here, if someone
* doesn't have /dev/null we may as well try
* to continue anyhow
*/
dev_null_fd = open ("/dev/null", O_RDWR);
if (dev_null_fd >= 0)
{
dup2 (dev_null_fd, 0);
dup2 (dev_null_fd, 1);
s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
if (s == NULL || *s == '\0')
dup2 (dev_null_fd, 2);
else
_dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
}
/* Get a predictable umask */
_dbus_verbose ("setting umask\n");
umask (022);
break;
default:
if (pidfile)
{
_dbus_verbose ("parent writing pid file\n");
if (!_dbus_write_pid_file (pidfile,
child_pid,
error))
{
_dbus_verbose ("pid file write failed, killing child\n");
kill (child_pid, SIGTERM);
return FALSE;
}
}
/* Write PID if requested */
if (print_pid_fd >= 0)
{
DBusString pid;
int bytes;
if (!_dbus_string_init (&pid))
{
_DBUS_SET_OOM (error);
kill (child_pid, SIGTERM);
return FALSE;
}
if (!_dbus_string_append_int (&pid, _dbus_getpid ()) ||
!_dbus_string_append (&pid, "\n"))
{
_dbus_string_free (&pid);
_DBUS_SET_OOM (error);
kill (child_pid, SIGTERM);
return FALSE;
}
bytes = _dbus_string_get_length (&pid);
if (_dbus_write (print_pid_fd, &pid, 0, bytes) != bytes)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Printing message bus PID: %s\n",
_dbus_strerror (errno));
_dbus_string_free (&pid);
kill (child_pid, SIGTERM);
return FALSE;
}
_dbus_string_free (&pid);
}
_dbus_verbose ("parent exiting\n");
_exit (0);
break;
}
_dbus_verbose ("calling setsid()\n");
if (setsid () == -1)
_dbus_assert_not_reached ("setsid() failed");
return TRUE;
}
/**
* Creates a file containing the process ID.
*
* @param filename the filename to write to
* @param pid our process ID
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
_dbus_write_pid_file (const DBusString *filename,
unsigned long pid,
DBusError *error)
{
const char *cfilename;
int fd;
FILE *f;
cfilename = _dbus_string_get_const_data (filename);
fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
if (fd < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to open \"%s\": %s", cfilename,
_dbus_strerror (errno));
return FALSE;
}
if ((f = fdopen (fd, "w")) == NULL)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
close (fd);
return FALSE;
}
if (fprintf (f, "%lu\n", pid) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to write to \"%s\": %s", cfilename,
_dbus_strerror (errno));
return FALSE;
}
if (fclose (f) == EOF)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to close \"%s\": %s", cfilename,
_dbus_strerror (errno));
return FALSE;
}
return TRUE;
}
/**
* Changes the user and group the bus is running as.
*
* @param uid the new user ID
* @param gid the new group ID
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
_dbus_change_identity (dbus_uid_t uid,
dbus_gid_t gid,
DBusError *error)
{
/* setgroups() only works if we are a privileged process,
* so we don't return error on failure; the only possible
* failure is that we don't have perms to do it.
* FIXME not sure this is right, maybe if setuid()
* is going to work then setgroups() should also work.
*/
if (setgroups (0, NULL) < 0)
_dbus_warn ("Failed to drop supplementary groups: %s\n",
_dbus_strerror (errno));
/* Set GID first, or the setuid may remove our permission
* to change the GID
*/
if (setgid (gid) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to set GID to %lu: %s", gid,
_dbus_strerror (errno));
return FALSE;
}
if (setuid (uid) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to set UID to %lu: %s", uid,
_dbus_strerror (errno));
return FALSE;
}
return TRUE;
}
/** Installs a UNIX signal handler
*
* @param sig the signal to handle
* @param handler the handler
*/
void
_dbus_set_signal_handler (int sig,
DBusSignalHandler handler)
{
struct sigaction act;
sigset_t empty_mask;
sigemptyset (&empty_mask);
act.sa_handler = handler;
act.sa_mask = empty_mask;
act.sa_flags = 0;
sigaction (sig, &act, 0);
}
/**
* Removes a directory; Directory must be empty
*
* @param filename directory filename
* @param error initialized error object
* @returns #TRUE on success
*/
dbus_bool_t
_dbus_delete_directory (const DBusString *filename,
DBusError *error)
{
const char *filename_c;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
filename_c = _dbus_string_get_const_data (filename);
if (rmdir (filename_c) != 0)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Failed to remove directory %s: %s\n",
filename_c, _dbus_strerror (errno));
return FALSE;
}
return TRUE;
}
/** Checks if a file exists
*
* @param file full path to the file
* @returns #TRUE if file exists
*/
dbus_bool_t
_dbus_file_exists (const char *file)
{
return (access (file, F_OK) == 0);
}
/** Checks if user is at the console
*
* @param username user to check
* @param error return location for errors
* @returns #TRUE is the user is at the consolei and there are no errors
*/
dbus_bool_t
_dbus_user_at_console (const char *username,
DBusError *error)
{
DBusString f;
dbus_bool_t result;
result = FALSE;
if (!_dbus_string_init (&f))
{
_DBUS_SET_OOM (error);
return FALSE;
}
if (!_dbus_string_append (&f, DBUS_CONSOLE_DIR))
{
_DBUS_SET_OOM (error);
goto out;
}
if (!_dbus_string_append (&f, username))
{
_DBUS_SET_OOM (error);
goto out;
}
result = _dbus_file_exists (_dbus_string_get_const_data (&f));
out:
_dbus_string_free (&f);
return result;
}
/**
* Checks whether the filename is an absolute path
*
* @param filename the filename
* @returns #TRUE if an absolute path
*/
dbus_bool_t
_dbus_path_is_absolute (const DBusString *filename)
{
if (_dbus_string_get_length (filename) > 0)
return _dbus_string_get_byte (filename, 0) == '/';
else
return FALSE;
}
/**
* stat() wrapper.
*
* @param filename the filename to stat
* @param statbuf the stat info to fill in
* @param error return location for error
* @returns #FALSE if error was set
*/
dbus_bool_t
_dbus_stat (const DBusString *filename,
DBusStat *statbuf,
DBusError *error)
{
const char *filename_c;
struct stat sb;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
filename_c = _dbus_string_get_const_data (filename);
if (stat (filename_c, &sb) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"%s", _dbus_strerror (errno));
return FALSE;
}
statbuf->mode = sb.st_mode;
statbuf->nlink = sb.st_nlink;
statbuf->uid = sb.st_uid;
statbuf->gid = sb.st_gid;
statbuf->size = sb.st_size;
statbuf->atime = sb.st_atime;
statbuf->mtime = sb.st_mtime;
statbuf->ctime = sb.st_ctime;
return TRUE;
}
/**
* Internals of directory iterator
*/
struct DBusDirIter
{
DIR *d; /**< The DIR* from opendir() */
};
/**
* Open a directory to iterate over.
*
* @param filename the directory name
* @param error exception return object or #NULL
* @returns new iterator, or #NULL on error
*/
DBusDirIter*
_dbus_directory_open (const DBusString *filename,
DBusError *error)
{
DIR *d;
DBusDirIter *iter;
const char *filename_c;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
filename_c = _dbus_string_get_const_data (filename);
d = opendir (filename_c);
if (d == NULL)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to read directory \"%s\": %s",
filename_c,
_dbus_strerror (errno));
return NULL;
}
iter = dbus_new0 (DBusDirIter, 1);
if (iter == NULL)
{
closedir (d);
dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
"Could not allocate memory for directory iterator");
return NULL;
}
iter->d = d;
return iter;
}
/**
* Get next file in the directory. Will not return "." or ".." on
* UNIX. If an error occurs, the contents of "filename" are
* undefined. The error is never set if the function succeeds.
*
* @todo for thread safety, I think we have to use
* readdir_r(). (GLib has the same issue, should file a bug.)
*
* @param iter the iterator
* @param filename string to be set to the next file in the dir
* @param error return location for error
* @returns #TRUE if filename was filled in with a new filename
*/
dbus_bool_t
_dbus_directory_get_next_file (DBusDirIter *iter,
DBusString *filename,
DBusError *error)
{
struct dirent *ent;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
again:
errno = 0;
ent = readdir (iter->d);
if (ent == NULL)
{
if (errno != 0)
dbus_set_error (error,
_dbus_error_from_errno (errno),
"%s", _dbus_strerror (errno));
return FALSE;
}
else if (ent->d_name[0] == '.' &&
(ent->d_name[1] == '\0' ||
(ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
goto again;
else
{
_dbus_string_set_length (filename, 0);
if (!_dbus_string_append (filename, ent->d_name))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
"No memory to read directory entry");
return FALSE;
}
else
return TRUE;
}
}
/**
* Closes a directory iteration.
*/
void
_dbus_directory_close (DBusDirIter *iter)
{
closedir (iter->d);
dbus_free (iter);
}
static dbus_bool_t
fill_user_info_from_group (struct group *g,
DBusGroupInfo *info,
DBusError *error)
{
_dbus_assert (g->gr_name != NULL);
info->gid = g->gr_gid;
info->groupname = _dbus_strdup (g->gr_name);
/* info->members = dbus_strdupv (g->gr_mem) */
if (info->groupname == NULL)
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return FALSE;
}
return TRUE;
}
static dbus_bool_t
fill_group_info (DBusGroupInfo *info,
dbus_gid_t gid,
const DBusString *groupname,
DBusError *error)
{
const char *group_c_str;
_dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
_dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
if (groupname)
group_c_str = _dbus_string_get_const_data (groupname);
else
group_c_str = NULL;
/* For now assuming that the getgrnam() and getgrgid() flavors
* always correspond to the pwnam flavors, if not we have
* to add more configure checks.
*/
#if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
{
struct group *g;
int result;
char buf[1024];
struct group g_str;
g = NULL;
#ifdef HAVE_POSIX_GETPWNAME_R
if (group_c_str)
result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
&g);
else
result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
&g);
#else
p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
result = 0;
#endif /* !HAVE_POSIX_GETPWNAME_R */
if (result == 0 && g == &g_str)
{
return fill_user_info_from_group (g, info, error);
}
else
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Group %s unknown or failed to look it up\n",
group_c_str ? group_c_str : "???");
return FALSE;
}
}
#else /* ! HAVE_GETPWNAM_R */
{
/* I guess we're screwed on thread safety here */
struct group *g;
g = getgrnam (group_c_str);
if (g != NULL)
{
return fill_user_info_from_group (g, info, error);
}
else
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Group %s unknown or failed to look it up\n",
group_c_str ? group_c_str : "???");
return FALSE;
}
}
#endif /* ! HAVE_GETPWNAM_R */
}
/**
* Initializes the given DBusGroupInfo struct
* with information about the given group name.
*
* @param info the group info struct
* @param groupname name of group
* @param error the error return
* @returns #FALSE if error is set
*/
dbus_bool_t
_dbus_group_info_fill (DBusGroupInfo *info,
const DBusString *groupname,
DBusError *error)
{
return fill_group_info (info, DBUS_GID_UNSET,
groupname, error);
}
/**
* Initializes the given DBusGroupInfo struct
* with information about the given group ID.
*
* @param info the group info struct
* @param gid group ID
* @param error the error return
* @returns #FALSE if error is set
*/
dbus_bool_t
_dbus_group_info_fill_gid (DBusGroupInfo *info,
dbus_gid_t gid,
DBusError *error)
{
return fill_group_info (info, gid, NULL, error);
}
/**
* Frees the members of info (but not info itself).
*
* @param info the group info
*/
void
_dbus_group_info_free (DBusGroupInfo *info)
{
dbus_free (info->groupname);
}
/** @} */ /* End of DBusInternalsUtils functions */
/**
* @addtogroup DBusString
*
* @{
*/
/**
* Get the directory name from a complete filename
* @param filename the filename
* @param dirname string to append directory name to
* @returns #FALSE if no memory
*/
dbus_bool_t
_dbus_string_get_dirname (const DBusString *filename,
DBusString *dirname)
{
int sep;
_dbus_assert (filename != dirname);
_dbus_assert (filename != NULL);
_dbus_assert (dirname != NULL);
/* Ignore any separators on the end */
sep = _dbus_string_get_length (filename);
if (sep == 0)
return _dbus_string_append (dirname, "."); /* empty string passed in */
while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
--sep;
_dbus_assert (sep >= 0);
if (sep == 0)
return _dbus_string_append (dirname, "/");
/* Now find the previous separator */
_dbus_string_find_byte_backward (filename, sep, '/', &sep);
if (sep < 0)
return _dbus_string_append (dirname, ".");
/* skip multiple separators */
while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
--sep;
_dbus_assert (sep >= 0);
if (sep == 0 &&
_dbus_string_get_byte (filename, 0) == '/')
return _dbus_string_append (dirname, "/");
else
return _dbus_string_copy_len (filename, 0, sep - 0,
dirname, _dbus_string_get_length (dirname));
}
/** @} */ /* DBusString stuff */
#ifdef DBUS_BUILD_TESTS
#include <stdlib.h>
static void
check_dirname (const char *filename,
const char *dirname)
{
DBusString f, d;
_dbus_string_init_const (&f, filename);
if (!_dbus_string_init (&d))
_dbus_assert_not_reached ("no memory");
if (!_dbus_string_get_dirname (&f, &d))
_dbus_assert_not_reached ("no memory");
if (!_dbus_string_equal_c_str (&d, dirname))
{
_dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
filename,
_dbus_string_get_const_data (&d),
dirname);
exit (1);
}
_dbus_string_free (&d);
}
static void
check_path_absolute (const char *path,
dbus_bool_t expected)
{
DBusString p;
_dbus_string_init_const (&p, path);
if (_dbus_path_is_absolute (&p) != expected)
{
_dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
path, expected, _dbus_path_is_absolute (&p));
exit (1);
}
}
/**
* Unit test for dbus-sysdeps.c.
*
* @returns #TRUE on success.
*/
dbus_bool_t
_dbus_sysdeps_test (void)
{
DBusString str;
double val;
int pos;
check_dirname ("foo", ".");
check_dirname ("foo/bar", "foo");
check_dirname ("foo//bar", "foo");
check_dirname ("foo///bar", "foo");
check_dirname ("foo/bar/", "foo");
check_dirname ("foo//bar/", "foo");
check_dirname ("foo///bar/", "foo");
check_dirname ("foo/bar//", "foo");
check_dirname ("foo//bar////", "foo");
check_dirname ("foo///bar///////", "foo");
check_dirname ("/foo", "/");
check_dirname ("////foo", "/");
check_dirname ("/foo/bar", "/foo");
check_dirname ("/foo//bar", "/foo");
check_dirname ("/foo///bar", "/foo");
check_dirname ("/", "/");
check_dirname ("///", "/");
check_dirname ("", ".");
_dbus_string_init_const (&str, "3.5");
if (!_dbus_string_parse_double (&str,
0, &val, &pos))
{
_dbus_warn ("Failed to parse double");
exit (1);
}
if (ABS(3.5 - val) > 1e-6)
{
_dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
exit (1);
}
if (pos != 3)
{
_dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
exit (1);
}
_dbus_string_init_const (&str, "0xff");
if (!_dbus_string_parse_double (&str,
0, &val, &pos))
{
_dbus_warn ("Failed to parse double");
exit (1);
}
if (ABS (0xff - val) > 1e-6)
{
_dbus_warn ("Failed to parse 0xff correctly, got: %f\n", val);
exit (1);
}
if (pos != 4)
{
_dbus_warn ("_dbus_string_parse_double of \"0xff\" returned wrong position %d", pos);
exit (1);
}
check_path_absolute ("/", TRUE);
check_path_absolute ("/foo", TRUE);
check_path_absolute ("", FALSE);
check_path_absolute ("foo", FALSE);
check_path_absolute ("foo/bar", FALSE);
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */
Index: dbus-sysdeps.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps.c,v
retrieving revision 1.87
retrieving revision 1.88
diff -u -d -r1.87 -r1.88
--- dbus-sysdeps.c 17 Jan 2005 01:20:02 -0000 1.87
+++ dbus-sysdeps.c 17 Jan 2005 03:53:40 -0000 1.88
@@ -1628,149 +1628,6 @@
dbus_free (info->homedir);
}
-static dbus_bool_t
-fill_user_info_from_group (struct group *g,
- DBusGroupInfo *info,
- DBusError *error)
-{
- _dbus_assert (g->gr_name != NULL);
-
- info->gid = g->gr_gid;
- info->groupname = _dbus_strdup (g->gr_name);
-
- /* info->members = dbus_strdupv (g->gr_mem) */
-
- if (info->groupname == NULL)
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static dbus_bool_t
-fill_group_info (DBusGroupInfo *info,
- dbus_gid_t gid,
- const DBusString *groupname,
- DBusError *error)
-{
- const char *group_c_str;
-
- _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
- _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
-
- if (groupname)
- group_c_str = _dbus_string_get_const_data (groupname);
- else
- group_c_str = NULL;
-
- /* For now assuming that the getgrnam() and getgrgid() flavors
- * always correspond to the pwnam flavors, if not we have
- * to add more configure checks.
- */
-
-#if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
- {
- struct group *g;
- int result;
- char buf[1024];
- struct group g_str;
-
- g = NULL;
-#ifdef HAVE_POSIX_GETPWNAME_R
-
- if (group_c_str)
- result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
- &g);
- else
- result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
- &g);
-#else
- p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
- result = 0;
-#endif /* !HAVE_POSIX_GETPWNAME_R */
- if (result == 0 && g == &g_str)
- {
- return fill_user_info_from_group (g, info, error);
- }
- else
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Group %s unknown or failed to look it up\n",
- group_c_str ? group_c_str : "???");
- return FALSE;
- }
- }
-#else /* ! HAVE_GETPWNAM_R */
- {
- /* I guess we're screwed on thread safety here */
- struct group *g;
-
- g = getgrnam (group_c_str);
-
- if (g != NULL)
- {
- return fill_user_info_from_group (g, info, error);
- }
- else
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Group %s unknown or failed to look it up\n",
- group_c_str ? group_c_str : "???");
- return FALSE;
- }
- }
-#endif /* ! HAVE_GETPWNAM_R */
-}
-
-/**
- * Initializes the given DBusGroupInfo struct
- * with information about the given group name.
- *
- * @param info the group info struct
- * @param groupname name of group
- * @param error the error return
- * @returns #FALSE if error is set
- */
-dbus_bool_t
-_dbus_group_info_fill (DBusGroupInfo *info,
- const DBusString *groupname,
- DBusError *error)
-{
- return fill_group_info (info, DBUS_GID_UNSET,
- groupname, error);
-
-}
-
-/**
- * Initializes the given DBusGroupInfo struct
- * with information about the given group ID.
- *
- * @param info the group info struct
- * @param gid group ID
- * @param error the error return
- * @returns #FALSE if error is set
- */
-dbus_bool_t
-_dbus_group_info_fill_gid (DBusGroupInfo *info,
- dbus_gid_t gid,
- DBusError *error)
-{
- return fill_group_info (info, gid, NULL, error);
-}
-
-/**
- * Frees the members of info (but not info itself).
- *
- * @param info the group info
- */
-void
-_dbus_group_info_free (DBusGroupInfo *info)
-{
- dbus_free (info->groupname);
-}
-
/**
* Sets fields in DBusCredentials to DBUS_PID_UNSET,
* DBUS_UID_UNSET, DBUS_GID_UNSET.
@@ -1849,6 +1706,7 @@
return getuid ();
}
+#ifdef DBUS_BUILD_TESTS
/** Gets our GID
* @returns process GID
*/
@@ -1857,6 +1715,7 @@
{
return getgid ();
}
+#endif
_DBUS_DEFINE_GLOBAL_LOCK (atomic);
@@ -2467,118 +2326,6 @@
_dbus_string_get_length (dir));
}
-/**
- * Internals of directory iterator
- */
-struct DBusDirIter
-{
- DIR *d; /**< The DIR* from opendir() */
-
-};
-
-/**
- * Open a directory to iterate over.
- *
- * @param filename the directory name
- * @param error exception return object or #NULL
- * @returns new iterator, or #NULL on error
- */
-DBusDirIter*
-_dbus_directory_open (const DBusString *filename,
- DBusError *error)
-{
- DIR *d;
- DBusDirIter *iter;
- const char *filename_c;
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- filename_c = _dbus_string_get_const_data (filename);
-
- d = opendir (filename_c);
- if (d == NULL)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Failed to read directory \"%s\": %s",
- filename_c,
- _dbus_strerror (errno));
- return NULL;
- }
- iter = dbus_new0 (DBusDirIter, 1);
- if (iter == NULL)
- {
- closedir (d);
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
- "Could not allocate memory for directory iterator");
- return NULL;
- }
-
- iter->d = d;
-
- return iter;
-}
-
-/**
- * Get next file in the directory. Will not return "." or ".." on
- * UNIX. If an error occurs, the contents of "filename" are
- * undefined. The error is never set if the function succeeds.
- *
- * @todo for thread safety, I think we have to use
- * readdir_r(). (GLib has the same issue, should file a bug.)
- *
- * @param iter the iterator
- * @param filename string to be set to the next file in the dir
- * @param error return location for error
- * @returns #TRUE if filename was filled in with a new filename
- */
-dbus_bool_t
-_dbus_directory_get_next_file (DBusDirIter *iter,
- DBusString *filename,
- DBusError *error)
-{
- struct dirent *ent;
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- again:
- errno = 0;
- ent = readdir (iter->d);
- if (ent == NULL)
- {
- if (errno != 0)
- dbus_set_error (error,
- _dbus_error_from_errno (errno),
- "%s", _dbus_strerror (errno));
- return FALSE;
- }
- else if (ent->d_name[0] == '.' &&
- (ent->d_name[1] == '\0' ||
- (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
- goto again;
- else
- {
- _dbus_string_set_length (filename, 0);
- if (!_dbus_string_append (filename, ent->d_name))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
- "No memory to read directory entry");
- return FALSE;
- }
- else
- return TRUE;
- }
-}
-
-/**
- * Closes a directory iteration.
- */
-void
-_dbus_directory_close (DBusDirIter *iter)
-{
- closedir (iter->d);
- dbus_free (iter);
-}
-
static dbus_bool_t
pseudorandom_generate_random_bytes (DBusString *str,
int n_bytes)
@@ -2859,62 +2606,6 @@
}
/**
- * Creates a full-duplex pipe (as in socketpair()).
- * Sets both ends of the pipe nonblocking.
- *
- * @param fd1 return location for one end
- * @param fd2 return location for the other end
- * @param blocking #TRUE if pipe should be blocking
- * @param error error return
- * @returns #FALSE on failure (if error is set)
- */
-dbus_bool_t
-_dbus_full_duplex_pipe (int *fd1,
- int *fd2,
- dbus_bool_t blocking,
- DBusError *error)
-{
-#ifdef HAVE_SOCKETPAIR
- int fds[2];
-
- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Could not create full-duplex pipe");
- return FALSE;
- }
-
- if (!blocking &&
- (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
- !_dbus_set_fd_nonblocking (fds[1], NULL)))
- {
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Could not set full-duplex pipe nonblocking");
-
- close (fds[0]);
- close (fds[1]);
-
- return FALSE;
- }
-
- *fd1 = fds[0];
- *fd2 = fds[1];
-
- _dbus_verbose ("full-duplex pipe %d <-> %d\n",
- *fd1, *fd2);
-
- return TRUE;
-#else
- _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "_dbus_full_duplex_pipe() not implemented on this OS");
- return FALSE;
-#endif
-}
-
-/**
* Closes a file descriptor.
*
* @param fd the file descriptor
@@ -3055,6 +2746,67 @@
return TRUE;
}
+/**
+ * Creates a full-duplex pipe (as in socketpair()).
+ * Sets both ends of the pipe nonblocking.
+ *
+ * @todo libdbus only uses this for the debug-pipe server, so in
+ * principle it could be in dbus-sysdeps-util.c, except that
+ * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
+ * debug-pipe server is used.
+ *
+ * @param fd1 return location for one end
+ * @param fd2 return location for the other end
+ * @param blocking #TRUE if pipe should be blocking
+ * @param error error return
+ * @returns #FALSE on failure (if error is set)
+ */
+dbus_bool_t
+_dbus_full_duplex_pipe (int *fd1,
+ int *fd2,
+ dbus_bool_t blocking,
+ DBusError *error)
+{
+#ifdef HAVE_SOCKETPAIR
+ int fds[2];
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Could not create full-duplex pipe");
+ return FALSE;
+ }
+
+ if (!blocking &&
+ (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
+ !_dbus_set_fd_nonblocking (fds[1], NULL)))
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Could not set full-duplex pipe nonblocking");
+
+ close (fds[0]);
+ close (fds[1]);
+
+ return FALSE;
+ }
+
+ *fd1 = fds[0];
+ *fd2 = fds[1];
+
+ _dbus_verbose ("full-duplex pipe %d <-> %d\n",
+ *fd1, *fd2);
+
+ return TRUE;
+#else
+ _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "_dbus_full_duplex_pipe() not implemented on this OS");
+ return FALSE;
+#endif
+}
+
/** @} end of sysdeps */
/* tests in dbus-sysdeps-util.c */
Index: dbus-userdb-util.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-userdb-util.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- dbus-userdb-util.c 17 Jan 2005 01:20:02 -0000 1.1
+++ dbus-userdb-util.c 17 Jan 2005 03:53:40 -0000 1.2
@@ -32,7 +32,6 @@
* @{
*/
-
/**
* Checks to see if the UID sent in is the console user
*
Index: dbus-userdb.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-userdb.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- dbus-userdb.c 17 Jan 2005 01:20:02 -0000 1.13
+++ dbus-userdb.c 17 Jan 2005 03:53:40 -0000 1.14
@@ -442,6 +442,7 @@
return NULL;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Increments refcount of user database.
* @param db the database
@@ -456,6 +457,7 @@
return db;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Decrements refcount of user database.
More information about the dbus-commit
mailing list