summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog24
-rw-r--r--dbus/Makefile.am11
-rw-r--r--dbus/dbus-auth-util.c169
-rw-r--r--dbus/dbus-auth.c137
-rw-r--r--dbus/dbus-hash.c25
-rw-r--r--dbus/dbus-internals.c6
-rw-r--r--dbus/dbus-internals.h8
-rw-r--r--dbus/dbus-list.c10
-rw-r--r--dbus/dbus-marshal-basic.c29
-rw-r--r--dbus/dbus-marshal-basic.h5
-rw-r--r--dbus/dbus-marshal-recursive-util.c2963
-rw-r--r--dbus/dbus-marshal-recursive.c2923
-rw-r--r--dbus/dbus-message-builder.c109
-rw-r--r--dbus/dbus-message-internal.h2
-rw-r--r--dbus/dbus-message-private.h119
-rw-r--r--dbus/dbus-message-util.c1309
-rw-r--r--dbus/dbus-message.c1382
-rw-r--r--dbus/dbus-string-private.h56
-rw-r--r--dbus/dbus-string-util.c727
-rw-r--r--dbus/dbus-string.c871
-rw-r--r--dbus/dbus-string.h8
-rw-r--r--dbus/dbus-sysdeps-util.c871
-rw-r--r--dbus/dbus-sysdeps.c374
-rw-r--r--dbus/dbus-userdb-util.c1
-rw-r--r--dbus/dbus-userdb.c2
-rwxr-xr-xtest/unused-code-gc.py2
26 files changed, 6517 insertions, 5626 deletions
diff --git a/ChangeLog b/ChangeLog
index e8125720..580ec360 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,29 @@
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
+
+2005-01-16 Havoc Pennington <hp@redhat.com>
+
* dbus/dbus-userdb-util.c: split out part of dbus-userdb.c
* dbus/dbus-sysdeps.c (_dbus_uid_from_string): move here to pave
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index 429c9ad9..216b168d 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -62,15 +62,16 @@ DBUS_LIB_SOURCES= \
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 @@ DBUS_SHARED_SOURCES= \
### 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) \
diff --git a/dbus/dbus-auth-util.c b/dbus/dbus-auth-util.c
new file mode 100644
index 00000000..4d25cf0a
--- /dev/null
+++ b/dbus/dbus-auth-util.c
@@ -0,0 +1,169 @@
+/* -*- 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 */
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
index b0793e06..eb8d5742 100644
--- a/dbus/dbus-auth.c
+++ b/dbus/dbus-auth.c
@@ -2392,139 +2392,4 @@ _dbus_auth_set_context (DBusAuth *auth,
/** @} */
-#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 */
diff --git a/dbus/dbus-hash.c b/dbus/dbus-hash.c
index c2ebb0f0..fa2104b3 100644
--- a/dbus/dbus-hash.c
+++ b/dbus/dbus-hash.c
@@ -231,13 +231,17 @@ static DBusHashEntry* find_string_function (DBusHashTable *table,
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 @@ _dbus_hash_table_new (DBusHashType type,
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 @@ _dbus_hash_iter_get_string_key (DBusHashIter *iter)
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 @@ _dbus_hash_iter_get_two_strings_key (DBusHashIter *iter)
return real->entry->key;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* A low-level but efficient interface for manipulating the hash
@@ -849,6 +857,7 @@ string_hash (const char *str)
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 @@ two_strings_hash (const char *str)
return h;
}
+#endif /* DBUS_BUILD_TESTS */
/** Key comparison function */
typedef int (* KeyCompareFunc) (const void *key_a, const void *key_b);
@@ -928,6 +938,7 @@ find_string_function (DBusHashTable *table,
preallocated);
}
+#ifdef DBUS_BUILD_TESTS
static int
two_strings_cmp (const char *a,
const char *b)
@@ -945,7 +956,9 @@ two_strings_cmp (const char *a,
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 @@ find_two_strings_function (DBusHashTable *table,
(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 @@ rebuild_table (DBusHashTable *table)
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 @@ _dbus_hash_table_lookup_string (DBusHashTable *table,
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 @@ _dbus_hash_table_lookup_two_strings (DBusHashTable *table,
else
return NULL;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Looks up the value for a given integer in a hash table
@@ -1258,6 +1279,7 @@ _dbus_hash_table_remove_string (DBusHashTable *table,
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 @@ _dbus_hash_table_remove_two_strings (DBusHashTable *table,
else
return FALSE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Removes the hash entry for the given key. If no hash entry
@@ -1407,6 +1430,7 @@ _dbus_hash_table_insert_string (DBusHashTable *table,
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 @@ _dbus_hash_table_insert_two_strings (DBusHashTable *table,
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Creates a hash entry with the given key and value.
diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
index eba3174d..8d0a968b 100644
--- a/dbus/dbus-internals.c
+++ b/dbus/dbus-internals.c
@@ -174,6 +174,8 @@ _dbus_warn (const char *format,
va_end (args);
}
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+
static dbus_bool_t verbose_initted = FALSE;
/**
@@ -238,6 +240,8 @@ _dbus_verbose_reset_real (void)
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 @@ _dbus_string_array_contains (const char **array,
return FALSE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Returns a string describing the given name.
*
@@ -387,6 +392,7 @@ _dbus_header_field_to_string (int header_field)
return "unknown";
}
}
+#endif /* DBUS_BUILD_TESTS */
#ifndef DBUS_DISABLE_CHECKS
/** String used in _dbus_return_if_fail macro */
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
index 5d6f31f2..2ffd2341 100644
--- a/dbus/dbus-internals.h
+++ b/dbus/dbus-internals.h
@@ -39,9 +39,6 @@ DBUS_BEGIN_DECLS
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 @@ void _dbus_verbose_reset_real (void);
#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
diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c
index 00b03d41..949e70a8 100644
--- a/dbus/dbus-list.c
+++ b/dbus/dbus-list.c
@@ -126,6 +126,7 @@ link_before (DBusList **list,
}
}
+#ifdef DBUS_BUILD_TESTS
static void
link_after (DBusList **list,
DBusList *after_this_link,
@@ -145,6 +146,7 @@ link_after (DBusList **list,
link->next->prev = link;
}
}
+#endif /* DBUS_BUILD_TESTS */
/** @} */
@@ -313,6 +315,7 @@ _dbus_list_prepend_link (DBusList **list,
link_before (list, *list, link);
}
+#ifdef DBUS_BUILD_TESTS
/**
* Inserts data into the list before the given existing link.
*
@@ -341,7 +344,9 @@ _dbus_list_insert_before (DBusList **list,
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
+#ifdef DBUS_BUILD_TESTS
/**
* Inserts data into the list after the given existing link.
*
@@ -370,6 +375,7 @@ _dbus_list_insert_after (DBusList **list,
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Inserts a link into the list before the given existing link.
@@ -389,6 +395,7 @@ _dbus_list_insert_before_link (DBusList **list,
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 @@ _dbus_list_insert_after_link (DBusList **list,
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 @@ _dbus_list_pop_last (DBusList **list)
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 @@ _dbus_list_pop_last_link (DBusList **list)
return link;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Copies a list. This is a linear-time operation. If there isn't
diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c
index df154b54..94161af0 100644
--- a/dbus/dbus-marshal-basic.c
+++ b/dbus/dbus-marshal-basic.c
@@ -88,21 +88,6 @@ _dbus_pack_uint32 (dbus_uint32_t value,
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 @@ _dbus_unpack_uint32 (int byte_order,
}
#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,
diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h
index 870fc0f7..f416689c 100644
--- a/dbus/dbus-marshal-basic.h
+++ b/dbus/dbus-marshal-basic.h
@@ -152,11 +152,6 @@ typedef union
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);
diff --git a/dbus/dbus-marshal-recursive-util.c b/dbus/dbus-marshal-recursive-util.c
new file mode 100644
index 00000000..cd80ea07
--- /dev/null
+++ b/dbus/dbus-marshal-recursive-util.c
@@ -0,0 +1,2963 @@
+/* -*- 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 = &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 */
diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c
index 05b827a0..e25fe249 100644
--- a/dbus/dbus-marshal-recursive.c
+++ b/dbus/dbus-marshal-recursive.c
@@ -2710,2925 +2710,4 @@ _dbus_type_writer_set_enabled (DBusTypeWriter *writer,
/** @} */ /* 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 = &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 */
diff --git a/dbus/dbus-message-builder.c b/dbus/dbus-message-builder.c
index b5b7564e..58718f6d 100644
--- a/dbus/dbus-message-builder.c
+++ b/dbus/dbus-message-builder.c
@@ -335,6 +335,115 @@ append_string_field (DBusString *dest,
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,
diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h
index f03e13f6..86064d3d 100644
--- a/dbus/dbus-message-internal.h
+++ b/dbus/dbus-message-internal.h
@@ -71,4 +71,4 @@ long _dbus_message_loader_get_max_message_size (DBusMessageLoader
DBUS_END_DECLS
-#endif /* DBUS_MESSAGE_H */
+#endif /* DBUS_MESSAGE_INTERNAL_H */
diff --git a/dbus/dbus-message-private.h b/dbus/dbus-message-private.h
new file mode 100644
index 00000000..60b0daea
--- /dev/null
+++ b/dbus/dbus-message-private.h
@@ -0,0 +1,119 @@
+/* -*- 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 */
diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c
new file mode 100644
index 00000000..47370702
--- /dev/null
+++ b/dbus/dbus-message-util.c
@@ -0,0 +1,1309 @@
+/* -*- 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 (&copy->header.data));
+
+ _dbus_assert (_dbus_string_get_length (&message->body) ==
+ _dbus_string_get_length (&copy->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 */
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index fc83a07e..8bb48667 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -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_message_get_args_valist (DBusMessage *message,
_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_iter_get_fixed_array (DBusMessageIter *iter,
* 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 @@ dbus_message_iter_get_fixed_array (DBusMessageIter *iter,
* @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 @@ dbus_message_iter_get_args_valist (DBusMessageIter *iter,
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 @@ dbus_message_iter_get_args_valist (DBusMessageIter *iter,
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 @@ dbus_message_iter_get_args_valist (DBusMessageIter *iter,
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 @@ dbus_set_error_from_message (DBusError *error,
*
* @{
*/
-/**
- * @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 @@ dbus_message_type_to_string (int type)
}
/** @} */
-#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 (&copy->header.data));
-
- _dbus_assert (_dbus_string_get_length (&message->body) ==
- _dbus_string_get_length (&copy->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 */
diff --git a/dbus/dbus-string-private.h b/dbus/dbus-string-private.h
index a2fcd03b..a4b7e8c3 100644
--- a/dbus/dbus-string-private.h
+++ b/dbus/dbus-string-private.h
@@ -53,6 +53,62 @@ typedef struct
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 */
diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c
new file mode 100644
index 00000000..1ff2ec67
--- /dev/null
+++ b/dbus/dbus-string-util.c
@@ -0,0 +1,727 @@
+/* -*- 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 */
diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
index 52099d65..154193ce 100644
--- a/dbus/dbus-string.c
+++ b/dbus/dbus-string.c
@@ -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 @@ _dbus_string_init_preallocated (DBusString *str,
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 @@ _dbus_string_init (DBusString *str)
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 @@ set_max_length (DBusString *str,
real->max_length = max_length;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Initializes a constant string. The value parameter is not copied
@@ -286,7 +233,7 @@ _dbus_string_init_const_len (DBusString *str,
_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 @@ reallocate_for_length (DBusRealString *real,
/* 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 @@ open_gap (int len,
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 @@ _dbus_string_get_data (DBusString *str)
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 @@ _dbus_string_steal_data (DBusString *str,
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_steal_data_len (DBusString *str,
_dbus_string_free (&dest);
return TRUE;
}
-
+#endif /* DBUS_BUILD_TESTS */
/**
* Copies the data from the string into a char*
@@ -758,6 +708,7 @@ _dbus_string_copy_data (const DBusString *str,
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Copies a segment of the string into a char*
*
@@ -802,30 +753,7 @@ _dbus_string_copy_data_len (const DBusString *str,
_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 @@ _dbus_string_append (DBusString *str,
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 @@ do { \
} 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 @@ _dbus_string_append_4_aligned (DBusString *str,
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 @@ _dbus_string_append_8_aligned (DBusString *str,
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Inserts 4 bytes aligned on a 4 byte boundary
@@ -1299,6 +1232,7 @@ _dbus_string_append_byte (DBusString *str,
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Appends a single Unicode character, encoding the character
* in UTF-8 format.
@@ -1369,6 +1303,7 @@ _dbus_string_append_unichar (DBusString *str,
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
static void
delete (DBusRealString *real,
@@ -1730,6 +1665,7 @@ _dbus_string_replace_len (const DBusString *source,
((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 @@ _dbus_string_get_unichar (const DBusString *str,
if (end_return)
*end_return = start + len;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Finds the given substring in the string,
@@ -1877,43 +1814,6 @@ _dbus_string_find_to (const DBusString *str,
}
/**
- * 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 @@ _dbus_string_skip_blank (const DBusString *str,
}
/**
- * 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 @@ _dbus_string_pop_line (DBusString *source,
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_first_word (DBusString *str)
_dbus_string_delete (str, 0, i);
}
+#endif
+#ifdef DBUS_BUILD_TESTS
/**
* Deletes any leading blanks in the string
*
@@ -2124,6 +1990,7 @@ _dbus_string_delete_leading_blanks (DBusString *str)
if (i > 0)
_dbus_string_delete (str, 0, i);
}
+#endif
/**
* Tests two DBusString for equality.
@@ -2164,6 +2031,7 @@ _dbus_string_equal (const DBusString *a,
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 @@ _dbus_string_equal_len (const DBusString *a,
return TRUE;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Tests two sub-parts of two DBusString for equality. The specified
@@ -2302,6 +2171,7 @@ _dbus_string_equal_c_str (const DBusString *a,
return TRUE;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Checks whether a string starts with the given C string.
*
@@ -2337,49 +2207,7 @@ _dbus_string_starts_with_c_str (const DBusString *a,
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 @@ _dbus_string_zero (DBusString *str)
}
/** @} */
-#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 */
diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h
index df5f4232..52281210 100644
--- a/dbus/dbus-string.h
+++ b/dbus/dbus-string.h
@@ -54,6 +54,7 @@ struct DBusString
* 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 @@ dbus_bool_t _dbus_string_init_preallocated (DBusString *str,
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 @@ dbus_bool_t _dbus_string_parse_double (const DBusString *str,
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,
diff --git a/dbus/dbus-sysdeps-util.c b/dbus/dbus-sysdeps-util.c
new file mode 100644
index 00000000..52298f81
--- /dev/null
+++ b/dbus/dbus-sysdeps-util.c
@@ -0,0 +1,871 @@
+/* -*- 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 */
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 049c63ab..d951a8d6 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -1628,149 +1628,6 @@ _dbus_user_info_free (DBusUserInfo *info)
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 @@ _dbus_getuid (void)
return getuid ();
}
+#ifdef DBUS_BUILD_TESTS
/** Gets our GID
* @returns process GID
*/
@@ -1857,6 +1715,7 @@ _dbus_getgid (void)
{
return getgid ();
}
+#endif
_DBUS_DEFINE_GLOBAL_LOCK (atomic);
@@ -2467,118 +2326,6 @@ _dbus_concat_dir_and_file (DBusString *dir,
_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 @@ _dbus_exit (int code)
}
/**
- * 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 @@ _dbus_parse_uid (const DBusString *uid_str,
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 */
diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c
index 20287f91..10226007 100644
--- a/dbus/dbus-userdb-util.c
+++ b/dbus/dbus-userdb-util.c
@@ -32,7 +32,6 @@
* @{
*/
-
/**
* Checks to see if the UID sent in is the console user
*
diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c
index ff583204..85ee1b67 100644
--- a/dbus/dbus-userdb.c
+++ b/dbus/dbus-userdb.c
@@ -442,6 +442,7 @@ _dbus_user_database_new (void)
return NULL;
}
+#ifdef DBUS_BUILD_TESTS
/**
* Increments refcount of user database.
* @param db the database
@@ -456,6 +457,7 @@ _dbus_user_database_ref (DBusUserDatabase *db)
return db;
}
+#endif /* DBUS_BUILD_TESTS */
/**
* Decrements refcount of user database.
diff --git a/test/unused-code-gc.py b/test/unused-code-gc.py
index 7bc1930b..a58597f7 100755
--- a/test/unused-code-gc.py
+++ b/test/unused-code-gc.py
@@ -230,6 +230,8 @@ trace 'reachable' through hardcoded function calls, if a function is
called only through a vtable, it won't be marked reachable (and
neither will its children in the call graph).
+Also, the sizes mentioned are more or less completely bogus.
+
"""
print "The following are hardcoded in as vtable roots: %s" % vtable_roots