summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/dconf-mock-gvdb.c123
-rw-r--r--tests/dconf-mock-shm.c46
-rw-r--r--tests/dconf-mock.h12
-rw-r--r--tests/engine.c97
4 files changed, 270 insertions, 8 deletions
diff --git a/tests/dconf-mock-gvdb.c b/tests/dconf-mock-gvdb.c
index 96695ad..50ffbac 100644
--- a/tests/dconf-mock-gvdb.c
+++ b/tests/dconf-mock-gvdb.c
@@ -1,36 +1,136 @@
#include "../gvdb/gvdb-reader.h"
+#include "dconf-mock.h"
+
+/* The global dconf_mock_gvdb_tables hashtable is modified all the time
+ * so we need to hold the lock while we access it.
+ *
+ * The hashtables contained within it are never modified, however. They
+ * can be safely accessed without a lock.
+ */
+
+static GHashTable *dconf_mock_gvdb_tables;
+static GMutex dconf_mock_gvdb_lock;
+
+typedef struct
+{
+ GVariant *value;
+ GHashTable *table;
+} DConfMockGvdbItem;
+
+static void
+dconf_mock_gvdb_item_free (gpointer data)
+{
+ DConfMockGvdbItem *item = data;
+
+ if (item->value)
+ g_variant_unref (item->value);
+
+ if (item->table)
+ g_hash_table_unref (item->table);
+
+ g_slice_free (DConfMockGvdbItem, item);
+}
+
+static void
+dconf_mock_gvdb_init (void)
+{
+ if (dconf_mock_gvdb_tables == NULL)
+ dconf_mock_gvdb_tables = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) g_hash_table_unref);
+}
+
+DConfMockGvdbTable *
+dconf_mock_gvdb_table_new (void)
+{
+ GHashTable *hash_table;
+
+ hash_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, dconf_mock_gvdb_item_free);
+
+ return (DConfMockGvdbTable *) hash_table;
+}
+
+void
+dconf_mock_gvdb_table_insert (DConfMockGvdbTable *table,
+ const gchar *name,
+ GVariant *value,
+ DConfMockGvdbTable *subtable)
+{
+ GHashTable *hash_table = (GHashTable *) table;
+ DConfMockGvdbItem *item;
+
+ g_assert (value == NULL || subtable == NULL);
+
+ item = g_slice_new (DConfMockGvdbItem);
+ item->value = value ? g_variant_ref_sink (value) : NULL;
+ item->table = (GHashTable *) subtable;
+
+ g_hash_table_insert (hash_table, g_strdup (name), item);
+}
+
+void
+dconf_mock_gvdb_install (const gchar *filename,
+ DConfMockGvdbTable *table)
+{
+ g_mutex_lock (&dconf_mock_gvdb_lock);
+ dconf_mock_gvdb_init ();
+
+ if (table)
+ g_hash_table_insert (dconf_mock_gvdb_tables, g_strdup (filename), table);
+ else
+ g_hash_table_remove (dconf_mock_gvdb_tables, filename);
+
+ g_mutex_unlock (&dconf_mock_gvdb_lock);
+}
void
gvdb_table_unref (GvdbTable *table)
{
+ GHashTable *hash_table = (GHashTable *) table;
+
+ g_hash_table_unref (hash_table);
}
GvdbTable *
gvdb_table_get_table (GvdbTable *table,
const gchar *key)
{
- return NULL;
+ GHashTable *hash_table = (GHashTable *) table;
+ DConfMockGvdbItem *item;
+
+ item = g_hash_table_lookup (hash_table, key);
+
+ return (GvdbTable *) (item ? g_hash_table_ref (item->table) : NULL);
}
gboolean
gvdb_table_has_value (GvdbTable *table,
const gchar *key)
{
- return FALSE;
+ GHashTable *hash_table = (GHashTable *) table;
+ DConfMockGvdbItem *item;
+
+ item = g_hash_table_lookup (hash_table, key);
+
+ return item && item->value;
}
GVariant *
gvdb_table_get_value (GvdbTable *table,
const gchar *key)
{
- return NULL;
+ GHashTable *hash_table = (GHashTable *) table;
+ DConfMockGvdbItem *item;
+
+ item = g_hash_table_lookup (hash_table, key);
+
+ return item ? g_variant_ref (item->value) : NULL;
}
gchar **
gvdb_table_list (GvdbTable *table,
const gchar *key)
{
- return NULL;
+ g_assert_not_reached ();
}
GvdbTable *
@@ -38,8 +138,19 @@ gvdb_table_new (const gchar *filename,
gboolean trusted,
GError **error)
{
- g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "not implemented");
- return NULL;
+ GHashTable *hash_table;
+
+ g_mutex_lock (&dconf_mock_gvdb_lock);
+ dconf_mock_gvdb_init ();
+ hash_table = g_hash_table_lookup (dconf_mock_gvdb_tables, filename);
+ if (hash_table)
+ g_hash_table_ref (hash_table);
+ g_mutex_unlock (&dconf_mock_gvdb_lock);
+
+ if (hash_table == NULL)
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT, "this gvdb does not exist");
+
+ return (GvdbTable *) hash_table;
}
gboolean
diff --git a/tests/dconf-mock-shm.c b/tests/dconf-mock-shm.c
index 3e9c38d..588667e 100644
--- a/tests/dconf-mock-shm.c
+++ b/tests/dconf-mock-shm.c
@@ -10,6 +10,7 @@ typedef struct
static GHashTable *dconf_mock_shm_table;
static GMutex dconf_mock_shm_lock;
+static GString *dconf_mock_shm_log;
static void
dconf_mock_shm_unref (gpointer data)
@@ -36,7 +37,10 @@ dconf_shm_open (const gchar *name)
g_mutex_lock (&dconf_mock_shm_lock);
if G_UNLIKELY (dconf_mock_shm_table == NULL)
- dconf_mock_shm_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, dconf_mock_shm_unref);
+ {
+ dconf_mock_shm_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, dconf_mock_shm_unref);
+ dconf_mock_shm_log = g_string_new (NULL);
+ }
shm = g_hash_table_lookup (dconf_mock_shm_table, name);
if (shm == NULL)
@@ -48,6 +52,8 @@ dconf_shm_open (const gchar *name)
/* before unlocking... */
dconf_mock_shm_ref (shm);
+ g_string_append_printf (dconf_mock_shm_log, "open %s;", name);
+
g_mutex_unlock (&dconf_mock_shm_lock);
return &shm->flagged;
@@ -57,7 +63,32 @@ void
dconf_shm_close (guint8 *shm)
{
if (shm)
- dconf_mock_shm_unref (shm);
+ {
+ g_mutex_lock (&dconf_mock_shm_lock);
+ g_string_append (dconf_mock_shm_log, "close;");
+ g_mutex_unlock (&dconf_mock_shm_lock);
+
+ dconf_mock_shm_unref (shm);
+ }
+}
+
+gint
+dconf_mock_shm_flag (const gchar *name)
+{
+ DConfMockShm *shm;
+ gint count = 0;
+
+ g_mutex_lock (&dconf_mock_shm_lock);
+ shm = g_hash_table_lookup (dconf_mock_shm_table, name);
+ if (shm)
+ {
+ shm->flagged = 1;
+ count = shm->ref_count;
+ g_hash_table_remove (dconf_mock_shm_table, name);
+ }
+ g_mutex_unlock (&dconf_mock_shm_lock);
+
+ return count;
}
void
@@ -77,6 +108,17 @@ dconf_mock_shm_reset (void)
g_assert_cmpint (shm->ref_count, ==, 1);
g_hash_table_iter_remove (&iter);
}
+
+ g_string_truncate (dconf_mock_shm_log, 0);
}
g_mutex_unlock (&dconf_mock_shm_lock);
}
+
+void
+dconf_mock_shm_assert_log (const gchar *expected_log)
+{
+ g_mutex_lock (&dconf_mock_shm_lock);
+ g_assert_cmpstr (dconf_mock_shm_log->str, ==, expected_log);
+ g_string_truncate (dconf_mock_shm_log, 0);
+ g_mutex_unlock (&dconf_mock_shm_lock);
+}
diff --git a/tests/dconf-mock.h b/tests/dconf-mock.h
index 8ce7f1f..81c41c4 100644
--- a/tests/dconf-mock.h
+++ b/tests/dconf-mock.h
@@ -2,5 +2,17 @@
#define __dconf_mock_h__
void dconf_mock_shm_reset (void);
+gint dconf_mock_shm_flag (const gchar *name);
+void dconf_mock_shm_assert_log (const gchar *expected_log);
+
+typedef struct _DConfMockGvdbTable DConfMockGvdbTable;
+
+DConfMockGvdbTable * dconf_mock_gvdb_table_new (void);
+void dconf_mock_gvdb_table_insert (DConfMockGvdbTable *table,
+ const gchar *name,
+ GVariant *value,
+ DConfMockGvdbTable *subtable);
+void dconf_mock_gvdb_install (const gchar *filename,
+ DConfMockGvdbTable *table);
#endif
diff --git a/tests/engine.c b/tests/engine.c
index ea29e37..4ac0a2e 100644
--- a/tests/engine.c
+++ b/tests/engine.c
@@ -224,9 +224,105 @@ test_signal_threadsafety (void)
dconf_mock_shm_reset ();
}
+static void
+test_user_source (void)
+{
+ DConfEngineSource *source;
+ DConfMockGvdbTable *table;
+ DConfMockGvdbTable *locks;
+ gboolean reopened;
+
+ source = dconf_engine_source_new ("user-db:user");
+ g_assert (source != NULL);
+
+ /* Create the source from a clean slate */
+ dconf_engine_source_init (source);
+ g_assert (source->values == NULL);
+ g_assert (source->locks == NULL);
+ dconf_mock_shm_assert_log ("open user;");
+
+ /* Try to refresh it. There must be no IO at this point. */
+ reopened = dconf_engine_source_refresh (source);
+ g_assert (!reopened);
+ dconf_mock_shm_assert_log ("");
+
+ /* Add a real database. */
+ table = dconf_mock_gvdb_table_new ();
+ dconf_mock_gvdb_table_insert (table, "/values/int32", g_variant_new_int32 (123456), NULL);
+ dconf_mock_gvdb_install ("/HOME/.config/dconf/user", table);
+
+ /* Try to refresh it again.
+ * Because we didn't flag the change there must still be no IO.
+ */
+ reopened = dconf_engine_source_refresh (source);
+ g_assert (!reopened);
+ g_assert (source->values == NULL);
+ g_assert (source->locks == NULL);
+ dconf_mock_shm_assert_log ("");
+
+ /* Now flag it and reopen. */
+ dconf_mock_shm_flag ("user");
+ reopened = dconf_engine_source_refresh (source);
+ g_assert (reopened);
+ g_assert (source->values != NULL);
+ g_assert (source->locks == NULL);
+ g_assert (gvdb_table_has_value (source->values, "/values/int32"));
+ dconf_mock_shm_assert_log ("close;open user;");
+
+ /* Do it again -- should get the same result, after some IO */
+ dconf_mock_shm_flag ("user");
+ reopened = dconf_engine_source_refresh (source);
+ g_assert (reopened);
+ g_assert (source->values != NULL);
+ g_assert (source->locks == NULL);
+ dconf_mock_shm_assert_log ("close;open user;");
+
+ /* "Delete" the gvdb and make sure dconf notices after a flag */
+ dconf_mock_gvdb_install ("/HOME/.config/dconf/user", NULL);
+ dconf_mock_shm_flag ("user");
+ reopened = dconf_engine_source_refresh (source);
+ g_assert (reopened);
+ g_assert (source->values == NULL);
+ g_assert (source->locks == NULL);
+ dconf_mock_shm_assert_log ("close;open user;");
+
+ /* Add a gvdb with a lock */
+ table = dconf_mock_gvdb_table_new ();
+ locks = dconf_mock_gvdb_table_new ();
+ dconf_mock_gvdb_table_insert (table, "/values/int32", g_variant_new_int32 (123456), NULL);
+ dconf_mock_gvdb_table_insert (locks, "/values/int32", g_variant_new_boolean (TRUE), NULL);
+ dconf_mock_gvdb_table_insert (table, ".locks", NULL, locks);
+ dconf_mock_gvdb_install ("/HOME/.config/dconf/user", table);
+
+ /* Reopen and check if we have the lock */
+ dconf_mock_shm_flag ("user");
+ reopened = dconf_engine_source_refresh (source);
+ g_assert (reopened);
+ g_assert (source->values != NULL);
+ g_assert (source->locks != NULL);
+ g_assert (gvdb_table_has_value (source->values, "/values/int32"));
+ g_assert (gvdb_table_has_value (source->locks, "/values/int32"));
+ dconf_mock_shm_assert_log ("close;open user;");
+
+ /* Reopen one last time */
+ dconf_mock_shm_flag ("user");
+ reopened = dconf_engine_source_refresh (source);
+ g_assert (reopened);
+ g_assert (source->values != NULL);
+ g_assert (source->locks != NULL);
+ dconf_mock_shm_assert_log ("close;open user;");
+
+ dconf_engine_source_free (source);
+ dconf_mock_shm_assert_log ("close;");
+
+ dconf_mock_gvdb_install ("/HOME/.config/dconf/user", NULL);
+ dconf_mock_shm_reset ();
+}
+
int
main (int argc, char **argv)
{
+ g_setenv ("XDG_CONFIG_HOME", "/HOME/.config", TRUE);
g_unsetenv ("DCONF_PROFILE");
main_thread = g_thread_self ();
@@ -235,6 +331,7 @@ main (int argc, char **argv)
g_test_add_func ("/engine/profile-parser", test_profile_parser);
g_test_add_func ("/engine/signal-threadsafety", test_signal_threadsafety);
+ g_test_add_func ("/engine/sources/user", test_user_source);
return g_test_run ();
}