+ g_test_trap_subprocess ("/gsettings/no-read-binding/subprocess/pass", 0, 0);
+ g_test_trap_assert_passed ();
+}
+
+/* Test that binding a non-writable property only
+ * works in 'SET' mode.
+ */
+static void
+test_no_write_binding_fail (void)
+{
+ TestObject *obj;
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.binding");
+ obj = test_object_new ();
+
+ g_settings_bind (settings, "string", obj, "no-write", 0);
+}
+
+static void
+test_no_write_binding_pass (void)
+{
+ TestObject *obj;
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.binding");
+ obj = test_object_new ();
+
+ g_settings_bind (settings, "string", obj, "no-write", G_SETTINGS_BIND_SET);
+
+ exit (0);
+}
+
+static void
+test_no_write_binding (void)
+{
+ if (g_test_undefined ())
+ {
+ g_test_trap_subprocess ("/gsettings/no-write-binding/subprocess/fail", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*property*is not writable*");
+ }
+
+ g_test_trap_subprocess ("/gsettings/no-write-binding/subprocess/pass", 0, 0);
+ g_test_trap_assert_passed ();
+}
+
+static void
+key_changed_cb (GSettings *settings, const gchar *key, gpointer data)
+{
+ gboolean *b = data;
+ (*b) = TRUE;
+}
+
+/*
+ * Test that using a keyfile works
+ */
+static void
+test_keyfile (void)
+{
+ GSettingsBackend *kf_backend;
+ GSettings *settings;
+ GKeyFile *keyfile;
+ gchar *str;
+ gboolean writable;
+ GError *error = NULL;
+ gchar *data;
+ gsize len;
+ gboolean called = FALSE;
+
+ g_remove ("keyfile/gsettings.store");
+ g_rmdir ("keyfile");
+
+ kf_backend = g_keyfile_settings_backend_new ("keyfile/gsettings.store", "/", "root");
+ settings = g_settings_new_with_backend ("org.gtk.test", kf_backend);
+ g_object_unref (kf_backend);
+
+ g_settings_reset (settings, "greeting");
+ str = g_settings_get_string (settings, "greeting");
+ g_assert_cmpstr (str, ==, "Hello, earthlings");
+ g_free (str);
+
+ writable = g_settings_is_writable (settings, "greeting");
+ g_assert (writable);
+ g_settings_set (settings, "greeting", "s", "see if this works");
+
+ str = g_settings_get_string (settings, "greeting");
+ g_assert_cmpstr (str, ==, "see if this works");
+ g_free (str);
+
+ g_settings_delay (settings);
+ g_settings_set (settings, "farewell", "s", "cheerio");
+ g_settings_apply (settings);
+
+ keyfile = g_key_file_new ();
+ g_assert (g_key_file_load_from_file (keyfile, "keyfile/gsettings.store", 0, NULL));
+
+ str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
+ g_assert_cmpstr (str, ==, "'see if this works'");
+ g_free (str);
+
+ str = g_key_file_get_string (keyfile, "tests", "farewell", NULL);
+ g_assert_cmpstr (str, ==, "'cheerio'");
+ g_free (str);
+ g_key_file_free (keyfile);
+
+ g_settings_reset (settings, "greeting");
+ g_settings_apply (settings);
+ keyfile = g_key_file_new ();
+ g_assert (g_key_file_load_from_file (keyfile, "keyfile/gsettings.store", 0, NULL));
+
+ str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
+ g_assert (str == NULL);
+
+ called = FALSE;
+ g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
+
+ g_key_file_set_string (keyfile, "tests", "greeting", "'howdy'");
+ data = g_key_file_to_data (keyfile, &len, NULL);
+ g_file_set_contents ("keyfile/gsettings.store", data, len, &error);
+ g_assert_no_error (error);
+ while (!called)
+ g_main_context_iteration (NULL, FALSE);
+ g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
+
+ str = g_settings_get_string (settings, "greeting");
+ g_assert_cmpstr (str, ==, "howdy");
+ g_free (str);
+
+ g_settings_set (settings, "farewell", "s", "cheerio");
+
+ called = FALSE;
+ g_signal_connect (settings, "writable-changed::greeting", G_CALLBACK (key_changed_cb), &called);
+
+ g_chmod ("keyfile", 0500);
+ while (!called)
+ g_main_context_iteration (NULL, FALSE);
+ g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
+
+ writable = g_settings_is_writable (settings, "greeting");
+ g_assert (!writable);
+
+ g_key_file_free (keyfile);
+ g_free (data);
+
+ g_object_unref (settings);
+ g_chmod ("keyfile", 0777);
+}
+
+/* Test that getting child schemas works
+ */
+static void
+test_child_schema (void)
+{
+ GSettings *settings;
+ GSettings *child;
+ guint8 byte;
+
+ /* first establish some known conditions */
+ settings = g_settings_new ("org.gtk.test.basic-types");
+ g_settings_set (settings, "test-byte", "y", 36);
+
+ g_settings_get (settings, "test-byte", "y", &byte);
+ g_assert_cmpint (byte, ==, 36);
+
+ g_object_unref (settings);
+
+ settings = g_settings_new ("org.gtk.test");
+ child = g_settings_get_child (settings, "basic-types");
+ g_assert (child != NULL);
+
+ g_settings_get (child, "test-byte", "y", &byte);
+ g_assert_cmpint (byte, ==, 36);
+
+ g_object_unref (child);
+ g_object_unref (settings);
+}
+
+#include "../strinfo.c"
+
+static void
+test_strinfo (void)
+{
+ /* "foo" has a value of 1
+ * "bar" has a value of 2
+ * "baz" is an alias for "bar"
+ */
+ gchar array[] =
+ "\1\0\0\0" "\xff""foo" "\0\0\0\xff" "\2\0\0\0"
+ "\xff" "bar" "\0\0\0\xff" "\3\0\0\0" "\xfe""baz"
+ "\0\0\0\xff";
+ const guint32 *strinfo = (guint32 *) array;
+ guint length = sizeof array / 4;
+ guint result;
+
+ {
+ /* build it and compare */
+ GString *builder;
+
+ builder = g_string_new (NULL);
+ strinfo_builder_append_item (builder, "foo", 1);
+ strinfo_builder_append_item (builder, "bar", 2);
+ g_assert (strinfo_builder_append_alias (builder, "baz", "bar"));
+ g_assert_cmpint (builder->len % 4, ==, 0);
+ g_assert_cmpint (builder->len / 4, ==, length);
+ g_assert (memcmp (builder->str, strinfo, length * 4) == 0);
+ g_string_free (builder, TRUE);
+ }
+
+ g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "foo"),
+ ==, NULL);
+ g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "bar"),
+ ==, NULL);
+ g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "baz"),
+ ==, "bar");
+ g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "quux"),
+ ==, NULL);
+
+ g_assert (strinfo_enum_from_string (strinfo, length, "foo", &result));
+ g_assert_cmpint (result, ==, 1);
+ g_assert (strinfo_enum_from_string (strinfo, length, "bar", &result));
+ g_assert_cmpint (result, ==, 2);
+ g_assert (!strinfo_enum_from_string (strinfo, length, "baz", &result));
+ g_assert (!strinfo_enum_from_string (strinfo, length, "quux", &result));
+
+ g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 0), ==, NULL);
+ g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 1), ==, "foo");
+ g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 2), ==, "bar");
+ g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 3), ==, NULL);
+
+ g_assert (strinfo_is_string_valid (strinfo, length, "foo"));
+ g_assert (strinfo_is_string_valid (strinfo, length, "bar"));
+ g_assert (!strinfo_is_string_valid (strinfo, length, "baz"));
+ g_assert (!strinfo_is_string_valid (strinfo, length, "quux"));
+}
+
+static void
+test_enums_non_enum_key (void)
+{
+ GSettings *direct;
+
+ direct = g_settings_new ("org.gtk.test.enums.direct");
+ g_settings_get_enum (direct, "test");
+ g_assert_not_reached ();
+}
+
+static void
+test_enums_non_enum_value (void)
+{
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ g_settings_set_enum (settings, "test", 42);
+ g_assert_not_reached ();
+}
+
+static void
+test_enums_range (void)
+{
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ g_settings_set_string (settings, "test", "qux");
+ g_assert_not_reached ();
+}
+
+static void
+test_enums_non_flags (void)
+{
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ g_settings_get_flags (settings, "test");
+ g_assert_not_reached ();
+}
+
+static void
+test_enums (void)
+{
+ GSettings *settings, *direct;
+ gchar *str;
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ direct = g_settings_new ("org.gtk.test.enums.direct");
+
+ if (g_test_undefined () && !backend_set)
+ {
+ g_test_trap_subprocess ("/gsettings/enums/subprocess/non-enum-key", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*not associated with an enum*");
+
+ g_test_trap_subprocess ("/gsettings/enums/subprocess/non-enum-value", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*invalid enum value 42*");
+
+ g_test_trap_subprocess ("/gsettings/enums/subprocess/range", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
+
+ g_test_trap_subprocess ("/gsettings/enums/subprocess/non-flags", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*not associated with a flags*");
+ }
+
+ str = g_settings_get_string (settings, "test");
+ g_assert_cmpstr (str, ==, "bar");
+ g_free (str);
+
+ g_settings_set_enum (settings, "test", TEST_ENUM_FOO);
+
+ str = g_settings_get_string (settings, "test");
+ g_assert_cmpstr (str, ==, "foo");
+ g_free (str);
+
+ g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_FOO);
+
+ g_settings_set_string (direct, "test", "qux");
+
+ str = g_settings_get_string (direct, "test");
+ g_assert_cmpstr (str, ==, "qux");
+ g_free (str);
+
+ str = g_settings_get_string (settings, "test");
+ g_assert_cmpstr (str, ==, "quux");
+ g_free (str);
+
+ g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_QUUX);
+}
+
+static void
+test_flags_non_flags_key (void)
+{
+ GSettings *direct;
+
+ direct = g_settings_new ("org.gtk.test.enums.direct");
+ g_settings_get_flags (direct, "test");
+ g_assert_not_reached ();
+}
+
+static void
+test_flags_non_flags_value (void)
+{
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ g_settings_set_flags (settings, "f-test", 0x42);
+ g_assert_not_reached ();
+}
+
+static void
+test_flags_range (void)
+{
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ g_settings_set_strv (settings, "f-test",
+ (const gchar **) g_strsplit ("rock", ",", 0));
+ g_assert_not_reached ();
+}
+
+static void
+test_flags_non_enum (void)
+{
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ g_settings_get_enum (settings, "f-test");
+ g_assert_not_reached ();
+}
+
+static void
+test_flags (void)
+{
+ GSettings *settings, *direct;
+ gchar **strv;
+ gchar *str;
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ direct = g_settings_new ("org.gtk.test.enums.direct");
+
+ if (g_test_undefined () && !backend_set)
+ {
+ g_test_trap_subprocess ("/gsettings/flags/subprocess/non-flags-key", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*not associated with a flags*");
+
+ g_test_trap_subprocess ("/gsettings/flags/subprocess/non-flags-value", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*invalid flags value 0x00000042*");
+
+ g_test_trap_subprocess ("/gsettings/flags/subprocess/range", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
+
+ g_test_trap_subprocess ("/gsettings/flags/subprocess/non-enum", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*not associated with an enum*");
+ }
+
+ strv = g_settings_get_strv (settings, "f-test");
+ str = g_strjoinv (",", strv);
+ g_assert_cmpstr (str, ==, "");
+ g_strfreev (strv);
+ g_free (str);
+
+ g_settings_set_flags (settings, "f-test",
+ TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
+
+ strv = g_settings_get_strv (settings, "f-test");
+ str = g_strjoinv (",", strv);
+ g_assert_cmpstr (str, ==, "talking,walking");
+ g_strfreev (strv);
+ g_free (str);
+
+ g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
+ TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
+
+ strv = g_strsplit ("speaking,laughing", ",", 0);
+ g_settings_set_strv (direct, "f-test", (const gchar **) strv);
+ g_strfreev (strv);
+
+ strv = g_settings_get_strv (direct, "f-test");
+ str = g_strjoinv (",", strv);
+ g_assert_cmpstr (str, ==, "speaking,laughing");
+ g_strfreev (strv);
+ g_free (str);
+
+ strv = g_settings_get_strv (settings, "f-test");
+ str = g_strjoinv (",", strv);
+ g_assert_cmpstr (str, ==, "talking,laughing");
+ g_strfreev (strv);
+ g_free (str);
+
+ g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
+ TEST_FLAGS_TALKING | TEST_FLAGS_LAUGHING);
+}
+
+static void
+test_range_high (void)
+{
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.range");
+ g_settings_set_int (settings, "val", 45);
+ g_assert_not_reached ();
+}
+
+static void
+test_range_low (void)
+{
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test.range");
+ g_settings_set_int (settings, "val", 1);
+ g_assert_not_reached ();
+}
+
+static void
+test_range (void)
+{
+ GSettings *settings, *direct;
+ GVariant *value;
+
+ settings = g_settings_new ("org.gtk.test.range");
+ direct = g_settings_new ("org.gtk.test.range.direct");
+
+ if (g_test_undefined () && !backend_set)
+ {
+ g_test_trap_subprocess ("/gsettings/range/subprocess/high", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
+
+ g_test_trap_subprocess ("/gsettings/range/subprocess/low", 0, 0);
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
+ }
+
+ g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
+ g_settings_set_int (direct, "val", 22);
+ g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 22);
+ g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 22);
+ g_settings_set_int (direct, "val", 45);
+ g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 45);
+ g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
+ g_settings_set_int (direct, "val", 1);
+ g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 1);
+ g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ value = g_variant_new_int32 (1);
+ g_assert (!g_settings_range_check (settings, "val", value));
+ g_variant_unref (value);
+ value = g_variant_new_int32 (33);
+ g_assert (g_settings_range_check (settings, "val", value));
+ g_variant_unref (value);
+ value = g_variant_new_int32 (45);
+ g_assert (!g_settings_range_check (settings, "val", value));
+ g_variant_unref (value);
+G_GNUC_END_IGNORE_DEPRECATIONS
+}
+
+static gboolean
+strv_has_string (gchar **haystack,
+ const gchar *needle)
+{
+ guint n;
+
+ for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
+ {
+ if (g_strcmp0 (haystack[n], needle) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+strv_set_equal (gchar **strv, ...)
+{
+ gint count;
+ va_list list;
+ const gchar *str;
+ gboolean res;
+
+ res = TRUE;
+ count = 0;
+ va_start (list, strv);
+ while (1)
+ {
+ str = va_arg (list, const gchar *);
+ if (str == NULL)
+ break;
+ if (!strv_has_string (strv, str))
+ {
+ res = FALSE;
+ break;
+ }
+ count++;
+ }
+ va_end (list);
+
+ if (res)
+ res = g_strv_length ((gchar**)strv) == count;
+
+ return res;
+}
+
+static void
+test_list_items (void)
+{
+ GSettings *settings;
+ gchar **children;
+ gchar **keys;
+
+ settings = g_settings_new ("org.gtk.test");
+ children = g_settings_list_children (settings);
+ keys = g_settings_list_keys (settings);
+
+ g_assert (strv_set_equal (children, "basic-types", "complex-types", "localized", NULL));
+ g_assert (strv_set_equal (keys, "greeting", "farewell", NULL));
+
+ g_strfreev (children);
+ g_strfreev (keys);
+
+ g_object_unref (settings);
+}
+
+static void
+test_list_schemas (void)
+{
+ const gchar * const *schemas;
+ const gchar * const *relocs;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ relocs = g_settings_list_relocatable_schemas ();
+ schemas = g_settings_list_schemas ();
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ g_assert (strv_set_equal ((gchar **)relocs,
+ "org.gtk.test.no-path",
+ "org.gtk.test.extends.base",
+ "org.gtk.test.extends.extended",
+ NULL));
+
+ g_assert (strv_set_equal ((gchar **)schemas,
+ "org.gtk.test",
+ "org.gtk.test.basic-types",
+ "org.gtk.test.complex-types",
+ "org.gtk.test.localized",
+ "org.gtk.test.binding",
+ "org.gtk.test.enums",
+ "org.gtk.test.enums.direct",
+ "org.gtk.test.range",
+ "org.gtk.test.range.direct",
+ "org.gtk.test.mapped",
+ "org.gtk.test.descriptions",
+ NULL));
+}
+
+static gboolean
+map_func (GVariant *value,
+ gpointer *result,
+ gpointer user_data)
+{
+ gint *state = user_data;
+ gint v;
+
+ if (value)
+ v = g_variant_get_int32 (value);
+ else
+ v = -1;
+
+ if (*state == 0)
+ {
+ g_assert_cmpint (v, ==, 1);
+ (*state)++;
+ return FALSE;
+ }
+ else if (*state == 1)
+ {
+ g_assert_cmpint (v, ==, 0);
+ (*state)++;
+ return FALSE;
+ }
+ else
+ {
+ g_assert (value == NULL);
+ *result = g_variant_new_int32 (5);
+ return TRUE;
+ }
+}
+
+static void
+test_get_mapped (void)
+{
+ GSettings *settings;
+ gint state;
+ gpointer p;
+ gint val;
+
+ settings = g_settings_new ("org.gtk.test.mapped");
+ g_settings_set_int (settings, "val", 1);
+
+ state = 0;
+ p = g_settings_get_mapped (settings, "val", map_func, &state);
+ val = g_variant_get_int32 ((GVariant*)p);
+ g_assert_cmpint (val, ==, 5);
+
+ g_variant_unref (p);
+ g_object_unref (settings);
+}
+
+static void
+test_get_range (void)
+{
+ GSettings *settings;
+ GVariant *range;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ settings = g_settings_new ("org.gtk.test.range");
+ range = g_settings_get_range (settings, "val");
+ check_and_free (range, "('range', <(2, 44)>)");
+ g_object_unref (settings);
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ range = g_settings_get_range (settings, "test");
+ check_and_free (range, "('enum', <['foo', 'bar', 'baz', 'quux']>)");
+ g_object_unref (settings);
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ range = g_settings_get_range (settings, "f-test");
+ check_and_free (range, "('flags', "
+ "<['mourning', 'laughing', 'talking', 'walking']>)");
+ g_object_unref (settings);
+
+ settings = g_settings_new ("org.gtk.test");
+ range = g_settings_get_range (settings, "greeting");
+ check_and_free (range, "('type', <@as []>)");
+ g_object_unref (settings);
+G_GNUC_END_IGNORE_DEPRECATIONS
+}
+
+static void
+test_schema_source (void)
+{
+ GSettingsSchemaSource *parent;
+ GSettingsSchemaSource *source;
+ GSettingsBackend *backend;
+ GSettingsSchema *schema;
+ GError *error = NULL;
+ GSettings *settings;
+ gboolean enabled;
+
+ backend = g_settings_backend_get_default ();
+
+ /* make sure it fails properly */
+ parent = g_settings_schema_source_get_default ();
+ source = g_settings_schema_source_new_from_directory ("/path/that/does/not/exist", parent, TRUE, &error);
+ g_assert (source == NULL);
+ g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
+ g_clear_error (&error);
+
+ /* create a source with the parent */
+ source = g_settings_schema_source_new_from_directory ("schema-source", parent, TRUE, &error);
+ g_assert_no_error (error);
+ g_assert (source != NULL);
+
+ /* check recursive lookups are working */
+ schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
+ g_assert (schema != NULL);
+ g_settings_schema_unref (schema);
+
+ /* check recursive lookups for non-existent schemas */
+ schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", TRUE);
+ g_assert (schema == NULL);
+
+ /* check non-recursive for schema that only exists in lower layers */
+ schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
+ g_assert (schema == NULL);
+
+ /* check non-recursive lookup for non-existent */
+ schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", FALSE);
+ g_assert (schema == NULL);
+
+ /* check non-recursive for schema that exists in toplevel */
+ schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
+ g_assert (schema != NULL);
+ g_settings_schema_unref (schema);
+
+ /* check recursive for schema that exists in toplevel */
+ schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
+ g_assert (schema != NULL);
+
+ /* try to use it for something */
+ settings = g_settings_new_full (schema, backend, g_settings_schema_get_path (schema));
+ g_settings_schema_unref (schema);
+ enabled = FALSE;
+ g_settings_get (settings, "enabled", "b", &enabled);
+ g_assert (enabled);
+ g_object_unref (settings);
+
+ g_settings_schema_source_unref (source);
+
+ /* try again, but with no parent */
+ source = g_settings_schema_source_new_from_directory ("schema-source", NULL, FALSE, NULL);
+ g_assert (source != NULL);
+
+ /* should not find it this time, even if recursive... */
+ schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
+ g_assert (schema == NULL);
+ schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
+ g_assert (schema == NULL);
+
+ /* should still find our own... */
+ schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
+ g_assert (schema != NULL);
+ g_settings_schema_unref (schema);
+ schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
+ g_assert (schema != NULL);
+ g_settings_schema_unref (schema);
+
+ g_settings_schema_source_unref (source);
+}
+
+static void
+test_actions (void)
+{
+ GAction *string, *toggle;
+ gboolean c1, c2, c3;
+ GSettings *settings;
+ gchar *name;
+ GVariantType *param_type;
+ gboolean enabled;
+ GVariantType *state_type;
+ GVariant *state;
+
+ settings = g_settings_new ("org.gtk.test.basic-types");
+ string = g_settings_create_action (settings, "test-string");
+ toggle = g_settings_create_action (settings, "test-boolean");
+ g_object_unref (settings); /* should be held by the actions */
+
+ g_signal_connect (settings, "changed", G_CALLBACK (changed_cb2), &c1);
+ g_signal_connect (string, "notify::state", G_CALLBACK (changed_cb2), &c2);
+ g_signal_connect (toggle, "notify::state", G_CALLBACK (changed_cb2), &c3);
+
+ c1 = c2 = c3 = FALSE;
+ g_settings_set_string (settings, "test-string", "hello world");
+ check_and_free (g_action_get_state (string), "'hello world'");
+ g_assert (c1 && c2 && !c3);
+ c1 = c2 = c3 = FALSE;
+
+ g_action_activate (string, g_variant_new_string ("hihi"));
+ check_and_free (g_settings_get_value (settings, "test-string"), "'hihi'");
+ g_assert (c1 && c2 && !c3);
+ c1 = c2 = c3 = FALSE;
+
+ g_action_change_state (string, g_variant_new_string ("kthxbye"));
+ check_and_free (g_settings_get_value (settings, "test-string"), "'kthxbye'");
+ g_assert (c1 && c2 && !c3);
+ c1 = c2 = c3 = FALSE;
+
+ g_action_change_state (toggle, g_variant_new_boolean (TRUE));
+ g_assert (g_settings_get_boolean (settings, "test-boolean"));
+ g_assert (c1 && !c2 && c3);
+ c1 = c2 = c3 = FALSE;
+
+ g_action_activate (toggle, NULL);
+ g_assert (!g_settings_get_boolean (settings, "test-boolean"));
+ g_assert (c1 && !c2 && c3);
+
+ g_object_get (string,
+ "name", &name,
+ "parameter-type", ¶m_type,
+ "enabled", &enabled,
+ "state-type", &state_type,
+ "state", &state,
+ NULL);
+
+ g_assert_cmpstr (name, ==, "test-string");
+ g_assert (g_variant_type_equal (param_type, G_VARIANT_TYPE_STRING));
+ g_assert (enabled);
+ g_assert (g_variant_type_equal (state_type, G_VARIANT_TYPE_STRING));
+ g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "kthxbye");
+
+ g_free (name);
+ g_variant_unref (state);
+
+ g_object_unref (string);
+ g_object_unref (toggle);
+}
+
+static void
+test_null_backend (void)
+{
+ GSettingsBackend *backend;
+ GSettings *settings;
+ gchar *str;
+ gboolean writable;
+
+ backend = g_null_settings_backend_new ();
+ settings = g_settings_new_with_backend_and_path ("org.gtk.test", backend, "/tests/");
+
+ g_object_get (settings, "schema-id", &str, NULL);
+ g_assert_cmpstr (str, ==, "org.gtk.test");
+ g_free (str);
+
+ g_settings_get (settings, "greeting", "s", &str);
+ g_assert_cmpstr (str, ==, "Hello, earthlings");
+ g_free (str);
+
+ g_settings_set (settings, "greeting", "s", "goodbye world");
+ g_settings_get (settings, "greeting", "s", &str);
+ g_assert_cmpstr (str, ==, "Hello, earthlings");
+ g_free (str);
+
+ writable = g_settings_is_writable (settings, "greeting");
+ g_assert (!writable);
+
+ g_settings_reset (settings, "greeting");
+
+ g_settings_delay (settings);
+ g_settings_set (settings, "greeting", "s", "goodbye world");
+ g_settings_apply (settings);
+ g_settings_get (settings, "greeting", "s", &str);
+ g_assert_cmpstr (str, ==, "Hello, earthlings");
+ g_free (str);
+
+ g_object_unref (settings);
+ g_object_unref (backend);
+}
+
+static void
+test_memory_backend (void)
+{
+ GSettingsBackend *backend;
+
+ backend = g_memory_settings_backend_new ();
+ g_assert (G_IS_SETTINGS_BACKEND (backend));
+ g_object_unref (backend);
+}
+
+static void
+test_read_descriptions (void)
+{
+ GSettingsSchema *schema;
+ GSettingsSchemaKey *key;
+ GSettings *settings;
+
+ settings = g_settings_new ("org.gtk.test");
+ g_object_get (settings, "settings-schema", &schema, NULL);
+ key = g_settings_schema_get_key (schema, "greeting");
+
+ g_assert_cmpstr (g_settings_schema_key_get_summary (key), ==, "A greeting");
+ g_assert_cmpstr (g_settings_schema_key_get_description (key), ==, "Greeting of the invading martians");
+
+ g_settings_schema_key_unref (key);
+ g_settings_schema_unref (schema);
+
+ g_object_unref (settings);
+
+ settings = g_settings_new ("org.gtk.test.descriptions");
+ g_object_get (settings, "settings-schema", &schema, NULL);
+ key = g_settings_schema_get_key (schema, "a");
+
+ g_assert_cmpstr (g_settings_schema_key_get_summary (key), ==,
+ "a paragraph.\n\n"
+ "with some whitespace.\n\n"
+ "because not everyone has a great editor.\n\n"
+ "lots of space is as one.");
+
+ g_settings_schema_key_unref (key);
+ g_settings_schema_unref (schema);
+
+ g_object_unref (settings);
+}
+
+static void
+test_default_value (void)
+{
+ GSettings *settings;
+ GSettingsSchema *schema;
+ GSettingsSchemaKey *key;
+ GVariant *v;
+ const gchar *str;
+ gchar *s;
+
+ settings = g_settings_new ("org.gtk.test");
+ g_object_get (settings, "settings-schema", &schema, NULL);
+ key = g_settings_schema_get_key (schema, "greeting");
+ g_settings_schema_unref (schema);
+ g_settings_schema_key_ref (key);
+
+ g_assert (g_variant_type_equal (g_settings_schema_key_get_value_type (key), G_VARIANT_TYPE_STRING));
+
+ v = g_settings_schema_key_get_default_value (key);
+ str = g_variant_get_string (v, NULL);
+ g_assert_cmpstr (str, ==, "Hello, earthlings");
+ g_variant_unref (v);
+
+ g_settings_schema_key_unref (key);
+ g_settings_schema_key_unref (key);
+
+ g_settings_set (settings, "greeting", "s", "goodbye world");
+
+ v = g_settings_get_user_value (settings, "greeting");
+ str = g_variant_get_string (v, NULL);
+ g_assert_cmpstr (str, ==, "goodbye world");
+ g_variant_unref (v);
+
+ v = g_settings_get_default_value (settings, "greeting");
+ str = g_variant_get_string (v, NULL);
+ g_assert_cmpstr (str, ==, "Hello, earthlings");
+ g_variant_unref (v);
+
+ g_settings_reset (settings, "greeting");
+
+ v = g_settings_get_user_value (settings, "greeting");
+ g_assert_null (v);
+
+ s = g_settings_get_string (settings, "greeting");
+ g_assert_cmpstr (s, ==, "Hello, earthlings");
+ g_free (s);
+
+ g_object_unref (settings);
+}
+
+static void
+test_extended_schema (void)
+{
+ GSettings *settings;
+ gchar **keys;
+
+ settings = g_settings_new_with_path ("org.gtk.test.extends.extended", "/test/extendes/");
+ keys = g_settings_list_keys (settings);
+ g_assert (strv_set_equal (keys, "int32", "string", "another-int32", NULL));
+ g_strfreev (keys);
+ g_object_unref (settings);
+}
+
+int
+main (int argc, char *argv[])
+{
+ gchar *schema_text;
+ gchar *enums;
+ gint result;
+
+ setlocale (LC_ALL, "");
+
+ g_test_init (&argc, &argv, NULL);
+
+ if (!g_test_subprocess ())
+ {
+ backend_set = g_getenv ("GSETTINGS_BACKEND") != NULL;
+
+ g_setenv ("XDG_DATA_DIRS", ".", TRUE);
+ g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
+
+ if (!backend_set)
+ g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
+
+ g_remove ("org.gtk.test.enums.xml");
+ g_assert (g_spawn_command_line_sync ("../../gobject/glib-mkenums "
+ "--template " SRCDIR "/enums.xml.template "
+ SRCDIR "/testenum.h",
+ &enums, NULL, &result, NULL));
+ g_assert (result == 0);
+ g_assert (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
+ g_free (enums);
+
+ g_assert (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.xml.orig", &schema_text, NULL, NULL));
+ g_assert (g_file_set_contents ("org.gtk.test.gschema.xml", schema_text, -1, NULL));
+
+ g_remove ("gschemas.compiled");
+ g_assert (g_spawn_command_line_sync ("../glib-compile-schemas --targetdir=. "
+ "--schema-file=org.gtk.test.enums.xml "
+ "--schema-file=org.gtk.test.gschema.xml",
+ NULL, NULL, &result, NULL));
+ g_assert (result == 0);
+
+ g_remove ("schema-source/gschemas.compiled");
+ g_mkdir ("schema-source", 0777);
+ g_assert (g_spawn_command_line_sync ("../glib-compile-schemas --targetdir=schema-source "
+ "--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml",
+ NULL, NULL, &result, NULL));
+ g_assert (result == 0);
+ }
+
+ g_test_add_func ("/gsettings/basic", test_basic);
+
+ if (!backend_set)
+ {
+ g_test_add_func ("/gsettings/no-schema", test_no_schema);
+ g_test_add_func ("/gsettings/unknown-key", test_unknown_key);
+ g_test_add_func ("/gsettings/wrong-type", test_wrong_type);
+ g_test_add_func ("/gsettings/wrong-path", test_wrong_path);
+ g_test_add_func ("/gsettings/no-path", test_no_path);
+ }