summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2012-07-06 21:40:39 -0400
committerRyan Lortie <desrt@desrt.ca>2012-07-06 21:40:39 -0400
commit7400ea5671d751cf771b0b3f1a0d712bc714674e (patch)
tree72d3a5a98ac2275b25e1f8f2f3cb317e88565fb5
parent17b92bd5d525db12b4e5f3b67374f34172275fd5 (diff)
downloaddconf-7400ea5671d751cf771b0b3f1a0d712bc714674e.tar.gz
gvdb test: test reader against corruption
Test the robustness of the gvdb-reader when faced with a corrupted GVDB file.
-rw-r--r--tests/gvdb.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/tests/gvdb.c b/tests/gvdb.c
index 5c23701..4f9c398 100644
--- a/tests/gvdb.c
+++ b/tests/gvdb.c
@@ -40,6 +40,9 @@ test_reader_empty (void)
g_assert_no_error (error);
g_assert (table != NULL);
+ table = gvdb_table_ref (table);
+ gvdb_table_unref (table);
+
g_assert (gvdb_table_is_valid (table));
for (i = 0; strings[i]; i++)
@@ -296,9 +299,181 @@ test_reader_walk_bigendian (void)
gvdb_table_unref (table);
}
+static void
+test_nested (void)
+{
+ GError *error = NULL;
+ GvdbTable *table;
+ GvdbTable *locks;
+ gboolean has;
+
+ table = gvdb_table_new (SRCDIR "/gvdbs/nested_gvdb", TRUE, &error);
+ g_assert_no_error (error);
+
+ verify_walk (table);
+
+ locks = gvdb_table_get_table (table, "/");
+ g_assert (locks == NULL);
+ locks = gvdb_table_get_table (table, "/values/");
+ g_assert (locks == NULL);
+ locks = gvdb_table_get_table (table, "/values/int32");
+ g_assert (locks == NULL);
+
+ locks = gvdb_table_get_table (table, ".locks");
+ g_assert (locks != NULL);
+
+ has = gvdb_table_has_value (locks, "/first/lck");
+ g_assert (!has);
+
+ has = gvdb_table_has_value (locks, "/first/lock");
+ g_assert (has);
+
+ has = gvdb_table_has_value (locks, "/second");
+ g_assert (has);
+
+ gvdb_table_unref (table);
+}
+
+/* This function exercises the API against @table but does not do any
+ * asserts on unexpected values (although it will assert on inconsistent
+ * values returned by the API).
+ */
+static void
+inspect_carefully (GvdbTable *table)
+{
+ const gchar * key_names[] = {
+ "/", "/values/", "/int32", "values/int32",
+ "/values/int32", "/values/boolean", "/values/string",
+ ".locks", "/first/lock", "/second", NULL
+ };
+ GString *log;
+ gint i;
+
+ for (i = 0; key_names[i]; i++)
+ {
+ const gchar *key = key_names[i];
+ GvdbTable *subtable;
+ GVariant *value;
+ gchar **list;
+ gboolean has;
+
+ has = gvdb_table_has_value (table, key);
+
+ list = gvdb_table_list (table, key);
+ g_assert (!has || list == NULL);
+ if (list)
+ {
+ gchar *joined = g_strjoinv (",", list);
+ g_strfreev (list);
+ g_free (joined);
+ }
+
+ value = gvdb_table_get_value (table, key);
+ g_assert_cmpint (value != NULL, ==, has);
+ if (value)
+ {
+ gchar *printed = g_variant_print (value, FALSE);
+ g_variant_unref (value);
+ g_free (printed);
+ }
+
+ value = gvdb_table_get_raw_value (table, key);
+ g_assert_cmpint (value != NULL, ==, has);
+ if (value)
+ {
+ gchar *printed = g_variant_print (value, FALSE);
+ g_variant_unref (value);
+ g_free (printed);
+ }
+
+ subtable = gvdb_table_get_table (table, key);
+ g_assert (!has || subtable == NULL);
+ if (subtable)
+ {
+ inspect_carefully (subtable);
+ gvdb_table_unref (subtable);
+ }
+ }
+
+ log = g_string_new (NULL);
+ accept_this_many_opens = -1;
+ gvdb_table_walk (table, "/", walk_open, walk_value, walk_close, log);
+ g_string_free (log, TRUE);
+}
+
+static void
+test_corrupted (gconstpointer user_data)
+{
+ gint percentage = GPOINTER_TO_INT (user_data);
+ GError *error = NULL;
+ GMappedFile *mapped;
+
+ mapped = g_mapped_file_new (SRCDIR "/gvdbs/nested_gvdb", FALSE, &error);
+ g_assert_no_error (error);
+ g_assert (mapped);
+
+ if (percentage)
+ {
+ GvdbTable *table;
+ const gchar *orig;
+ gsize length;
+ gchar *copy;
+ gint i;
+
+ orig = g_mapped_file_get_contents (mapped);
+ length = g_mapped_file_get_length (mapped);
+ copy = g_memdup (orig, length);
+
+ for (i = 0; i < 10000; i++)
+ {
+ gint j;
+
+ /* Make a broken copy, but leave the signature intact so that
+ * we don't get too many boring trivial failures.
+ */
+ for (j = 8; j < length; j++)
+ if (g_test_rand_int_range (0, 100) < percentage)
+ copy[j] = g_test_rand_int_range (0, 256);
+ else
+ copy[j] = orig[j];
+
+ table = gvdb_table_new_from_data (copy, length, FALSE, NULL, NULL, NULL, &error);
+
+ /* If we damaged the header, it may not open */
+ if (table)
+ {
+ inspect_carefully (table);
+ gvdb_table_unref (table);
+ }
+ else
+ {
+ g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
+ g_clear_error (&error);
+ }
+ }
+ }
+ else
+ {
+ GvdbTable *table;
+
+ table = gvdb_table_new_from_data (g_mapped_file_get_contents (mapped),
+ g_mapped_file_get_length (mapped),
+ FALSE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (table);
+
+ inspect_carefully (table);
+ gvdb_table_unref (table);
+ }
+
+ g_mapped_file_unref (mapped);
+}
+
int
main (int argc, char **argv)
{
+ gint i;
+
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/gvdb/reader/open-error", test_reader_open_error);
@@ -307,6 +482,13 @@ main (int argc, char **argv)
g_test_add_func ("/gvdb/reader/values/big-endian", test_reader_values_bigendian);
g_test_add_func ("/gvdb/reader/walk", test_reader_walk);
g_test_add_func ("/gvdb/reader/walk/big-endian", test_reader_walk_bigendian);
+ g_test_add_func ("/gvdb/reader/nested", test_nested);
+ for (i = 0; i < 20; i++)
+ {
+ gchar test_name[80];
+ g_snprintf (test_name, sizeof test_name, "/gvdb/reader/corrupted/%d%%", i);
+ g_test_add_data_func (test_name, GINT_TO_POINTER (i), test_corrupted);
+ }
return g_test_run ();
}