Imported Upstream version 2.67.4
[platform/upstream/glib.git] / gio / tests / gsettings.c
1 #include <stdlib.h>
2 #include <locale.h>
3 #include <libintl.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <gio/gio.h>
7 #include <gstdio.h>
8 #define G_SETTINGS_ENABLE_BACKEND
9 #include <gio/gsettingsbackend.h>
10
11 #include "testenum.h"
12
13 static const gchar *locale_dir = ".";
14
15 static gboolean backend_set;
16
17 /* These tests rely on the schemas in org.gtk.test.gschema.xml
18  * to be compiled and installed in the same directory.
19  */
20
21 typedef struct
22 {
23   gchar *tmp_dir;
24 } Fixture;
25
26 static void
27 setup (Fixture       *fixture,
28        gconstpointer  user_data)
29 {
30   GError *error = NULL;
31
32   fixture->tmp_dir = g_dir_make_tmp ("gio-test-gsettings_XXXXXX", &error);
33   g_assert_no_error (error);
34
35   g_test_message ("Using temporary directory: %s", fixture->tmp_dir);
36 }
37
38 static void
39 teardown (Fixture       *fixture,
40           gconstpointer  user_data)
41 {
42   g_assert_no_errno (g_rmdir (fixture->tmp_dir));
43   g_clear_pointer (&fixture->tmp_dir, g_free);
44 }
45
46 static void
47 check_and_free (GVariant    *value,
48                 const gchar *expected)
49 {
50   gchar *printed;
51
52   printed = g_variant_print (value, TRUE);
53   g_assert_cmpstr (printed, ==, expected);
54   g_free (printed);
55
56   g_variant_unref (value);
57 }
58
59
60 /* Just to get warmed up: Read and set a string, and
61  * verify that can read the changed string back
62  */
63 static void
64 test_basic (void)
65 {
66   gchar *str = NULL;
67   GObject *b;
68   gchar *path;
69   gboolean has_unapplied;
70   gboolean delay_apply;
71   GSettings *settings;
72
73   settings = g_settings_new ("org.gtk.test");
74
75   g_object_get (settings,
76                 "schema-id", &str,
77                 "backend", &b,
78                 "path", &path,
79                 "has-unapplied", &has_unapplied,
80                 "delay-apply", &delay_apply,
81                 NULL);
82   g_assert_cmpstr (str, ==, "org.gtk.test");
83   g_assert_nonnull (b);
84   g_assert_cmpstr (path, ==, "/tests/");
85   g_assert_false (has_unapplied);
86   g_assert_false (delay_apply);
87   g_free (str);
88   g_object_unref (b);
89   g_free (path);
90
91   g_settings_get (settings, "greeting", "s", &str);
92   g_assert_cmpstr (str, ==, "Hello, earthlings");
93   g_free (str);
94
95   g_settings_set (settings, "greeting", "s", "goodbye world");
96   g_settings_get (settings, "greeting", "s", &str);
97   g_assert_cmpstr (str, ==, "goodbye world");
98   g_free (str);
99   str = NULL;
100
101   if (!backend_set && g_test_undefined ())
102     {
103       GSettings *tmp_settings = g_settings_new ("org.gtk.test");
104
105       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
106                              "*g_settings_set_value*expects type*");
107       g_settings_set (tmp_settings, "greeting", "i", 555);
108       g_test_assert_expected_messages ();
109
110       g_object_unref (tmp_settings);
111     }
112
113   g_settings_get (settings, "greeting", "s", &str);
114   g_assert_cmpstr (str, ==, "goodbye world");
115   g_free (str);
116   str = NULL;
117
118   g_settings_reset (settings, "greeting");
119   str = g_settings_get_string (settings, "greeting");
120   g_assert_cmpstr (str, ==, "Hello, earthlings");
121   g_free (str);
122
123   g_settings_set (settings, "greeting", "s", "this is the end");
124   g_object_unref (settings);
125 }
126
127 /* Check that we get an error when getting a key
128  * that is not in the schema
129  */
130 static void
131 test_unknown_key (void)
132 {
133   if (!g_test_undefined ())
134     return;
135
136   if (g_test_subprocess ())
137     {
138       GSettings *settings;
139       GVariant *value;
140
141       settings = g_settings_new ("org.gtk.test");
142       value = g_settings_get_value (settings, "no_such_key");
143
144       g_assert_null (value);
145
146       g_object_unref (settings);
147       return;
148     }
149   g_test_trap_subprocess (NULL, 0, 0);
150   g_test_trap_assert_failed ();
151   g_test_trap_assert_stderr ("*does not contain*");
152 }
153
154 /* Check that we get an error when the schema
155  * has not been installed
156  */
157 static void
158 test_no_schema (void)
159 {
160   if (!g_test_undefined ())
161     return;
162
163   if (g_test_subprocess ())
164     {
165       GSettings *settings;
166
167       settings = g_settings_new ("no.such.schema");
168
169       g_assert_null (settings);
170       return;
171     }
172   g_test_trap_subprocess (NULL, 0, 0);
173   g_test_trap_assert_failed ();
174   g_test_trap_assert_stderr ("*Settings schema 'no.such.schema' is not installed*");
175 }
176
177 /* Check that we get an error when passing a type string
178  * that does not match the schema
179  */
180 static void
181 test_wrong_type (void)
182 {
183   GSettings *settings;
184   gchar *str = NULL;
185
186   if (!g_test_undefined ())
187     return;
188
189   settings = g_settings_new ("org.gtk.test");
190
191   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL,
192                          "*given value has a type of*");
193   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL,
194                          "*valid_format_string*");
195   g_settings_get (settings, "greeting", "o", &str);
196   g_test_assert_expected_messages ();
197
198   g_assert_null (str);
199
200   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
201                          "*expects type 's'*");
202   g_settings_set (settings, "greeting", "o", "/a/path");
203   g_test_assert_expected_messages ();
204
205   g_object_unref (settings);
206 }
207
208 /* Check errors with explicit paths */
209 static void
210 test_wrong_path (void)
211 {
212   if (!g_test_undefined ())
213     return;
214
215   if (g_test_subprocess ())
216     {
217       GSettings *settings G_GNUC_UNUSED;
218
219       settings = g_settings_new_with_path ("org.gtk.test", "/wrong-path/");
220       return;
221     }
222   g_test_trap_subprocess (NULL, 0, 0);
223   g_test_trap_assert_failed ();
224   g_test_trap_assert_stderr ("*but path * specified by schema*");
225 }
226
227 static void
228 test_no_path (void)
229 {
230   if (!g_test_undefined ())
231     return;
232
233   if (g_test_subprocess ())
234     {
235       GSettings *settings G_GNUC_UNUSED;
236
237       settings = g_settings_new ("org.gtk.test.no-path");
238       return;
239     }
240   g_test_trap_subprocess (NULL, 0, 0);
241   g_test_trap_assert_failed ();
242   g_test_trap_assert_stderr ("*attempting to create schema * without a path**");
243 }
244
245
246 /* Check that we can successfully read and set the full
247  * range of all basic types
248  */
249 static void
250 test_basic_types (void)
251 {
252   GSettings *settings;
253   gboolean b;
254   guint8 byte;
255   gint16 i16;
256   guint16 u16;
257   gint32 i32;
258   guint32 u32;
259   gint64 i64;
260   guint64 u64;
261   gdouble d;
262   gchar *str;
263
264   settings = g_settings_new ("org.gtk.test.basic-types");
265
266   g_settings_get (settings, "test-boolean", "b", &b);
267   g_assert_cmpint (b, ==, 1);
268
269   g_settings_set (settings, "test-boolean", "b", 0);
270   g_settings_get (settings, "test-boolean", "b", &b);
271   g_assert_cmpint (b, ==, 0);
272
273   g_settings_get (settings, "test-byte", "y", &byte);
274   g_assert_cmpint (byte, ==, 25);
275
276   g_settings_set (settings, "test-byte", "y", G_MAXUINT8);
277   g_settings_get (settings, "test-byte", "y", &byte);
278   g_assert_cmpint (byte, ==, G_MAXUINT8);
279
280   g_settings_get (settings, "test-int16", "n", &i16);
281   g_assert_cmpint (i16, ==, -1234);
282
283   g_settings_set (settings, "test-int16", "n", G_MININT16);
284   g_settings_get (settings, "test-int16", "n", &i16);
285   g_assert_cmpint (i16, ==, G_MININT16);
286
287   g_settings_set (settings, "test-int16", "n", G_MAXINT16);
288   g_settings_get (settings, "test-int16", "n", &i16);
289   g_assert_cmpint (i16, ==, G_MAXINT16);
290
291   g_settings_get (settings, "test-uint16", "q", &u16);
292   g_assert_cmpuint (u16, ==, 1234);
293
294   g_settings_set (settings, "test-uint16", "q", G_MAXUINT16);
295   g_settings_get (settings, "test-uint16", "q", &u16);
296   g_assert_cmpuint (u16, ==, G_MAXUINT16);
297
298   g_settings_get (settings, "test-int32", "i", &i32);
299   g_assert_cmpint (i32, ==, -123456);
300
301   g_settings_set (settings, "test-int32", "i", G_MININT32);
302   g_settings_get (settings, "test-int32", "i", &i32);
303   g_assert_cmpint (i32, ==, G_MININT32);
304
305   g_settings_set (settings, "test-int32", "i", G_MAXINT32);
306   g_settings_get (settings, "test-int32", "i", &i32);
307   g_assert_cmpint (i32, ==, G_MAXINT32);
308
309   g_settings_get (settings, "test-uint32", "u", &u32);
310   g_assert_cmpuint (u32, ==, 123456);
311
312   g_settings_set (settings, "test-uint32", "u", G_MAXUINT32);
313   g_settings_get (settings, "test-uint32", "u", &u32);
314   g_assert_cmpuint (u32, ==, G_MAXUINT32);
315
316   g_settings_get (settings, "test-int64", "x", &i64);
317   g_assert_cmpuint (i64, ==, -123456789);
318
319   g_settings_set (settings, "test-int64", "x", G_MININT64);
320   g_settings_get (settings, "test-int64", "x", &i64);
321   g_assert_cmpuint (i64, ==, G_MININT64);
322
323   g_settings_set (settings, "test-int64", "x", G_MAXINT64);
324   g_settings_get (settings, "test-int64", "x", &i64);
325   g_assert_cmpuint (i64, ==, G_MAXINT64);
326
327   g_settings_get (settings, "test-uint64", "t", &u64);
328   g_assert_cmpuint (u64, ==, 123456789);
329
330   g_settings_set (settings, "test-uint64", "t", G_MAXUINT64);
331   g_settings_get (settings, "test-uint64", "t", &u64);
332   g_assert_cmpuint (u64, ==, G_MAXUINT64);
333
334   g_settings_get (settings, "test-double", "d", &d);
335   g_assert_cmpfloat (d, ==, 123.456);
336
337   g_settings_set (settings, "test-double", "d", G_MINDOUBLE);
338   g_settings_get (settings, "test-double", "d", &d);
339   g_assert_cmpfloat (d, ==, G_MINDOUBLE);
340
341   g_settings_set (settings, "test-double", "d", G_MAXDOUBLE);
342   g_settings_get (settings, "test-double", "d", &d);
343   g_assert_cmpfloat (d, ==, G_MAXDOUBLE);
344
345   g_settings_get (settings, "test-string", "s", &str);
346   g_assert_cmpstr (str, ==, "a string, it seems");
347   g_free (str);
348   str = NULL;
349
350   g_settings_get (settings, "test-objectpath", "o", &str);
351   g_assert_cmpstr (str, ==, "/a/object/path");
352   g_object_unref (settings);
353   g_free (str);
354   str = NULL;
355 }
356
357 /* Check that we can read an set complex types like
358  * tuples, arrays and dictionaries
359  */
360 static void
361 test_complex_types (void)
362 {
363   GSettings *settings;
364   gchar *s;
365   gint i1, i2;
366   GVariantIter *iter = NULL;
367   GVariant *v = NULL;
368
369   settings = g_settings_new ("org.gtk.test.complex-types");
370
371   g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
372   g_assert_cmpstr (s, ==, "one");
373   g_assert_cmpint (i1,==, 2);
374   g_assert_cmpint (i2,==, 3);
375   g_free (s) ;
376   s = NULL;
377
378   g_settings_set (settings, "test-tuple", "(s(ii))", "none", 0, 0);
379   g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
380   g_assert_cmpstr (s, ==, "none");
381   g_assert_cmpint (i1,==, 0);
382   g_assert_cmpint (i2,==, 0);
383   g_free (s);
384   s = NULL;
385
386   g_settings_get (settings, "test-array", "ai", &iter);
387   g_assert_cmpint (g_variant_iter_n_children (iter), ==, 6);
388   g_assert_true (g_variant_iter_next (iter, "i", &i1));
389   g_assert_cmpint (i1, ==, 0);
390   g_assert_true (g_variant_iter_next (iter, "i", &i1));
391   g_assert_cmpint (i1, ==, 1);
392   g_assert_true (g_variant_iter_next (iter, "i", &i1));
393   g_assert_cmpint (i1, ==, 2);
394   g_assert_true (g_variant_iter_next (iter, "i", &i1));
395   g_assert_cmpint (i1, ==, 3);
396   g_assert_true (g_variant_iter_next (iter, "i", &i1));
397   g_assert_cmpint (i1, ==, 4);
398   g_assert_true (g_variant_iter_next (iter, "i", &i1));
399   g_assert_cmpint (i1, ==, 5);
400   g_assert_false (g_variant_iter_next (iter, "i", &i1));
401   g_variant_iter_free (iter);
402
403   g_settings_get (settings, "test-dict", "a{sau}", &iter);
404   g_assert_cmpint (g_variant_iter_n_children (iter), ==, 2);
405   g_assert_true (g_variant_iter_next (iter, "{&s@au}", &s, &v));
406   g_assert_cmpstr (s, ==, "AC");
407   g_assert_cmpstr ((char *)g_variant_get_type (v), ==, "au");
408   g_variant_unref (v);
409   g_assert_true (g_variant_iter_next (iter, "{&s@au}", &s, &v));
410   g_assert_cmpstr (s, ==, "IV");
411   g_assert_cmpstr ((char *)g_variant_get_type (v), ==, "au");
412   g_variant_unref (v);
413   g_variant_iter_free (iter);
414
415   v = g_settings_get_value (settings, "test-dict");
416   g_assert_cmpstr ((char *)g_variant_get_type (v), ==, "a{sau}");
417   g_variant_unref (v);
418
419   g_object_unref (settings);
420 }
421
422 static gboolean changed_cb_called;
423
424 static void
425 changed_cb (GSettings   *settings,
426             const gchar *key,
427             gpointer     data)
428 {
429   changed_cb_called = TRUE;
430
431   g_assert_cmpstr (key, ==, data);
432 }
433
434 /* Test that basic change notification with the changed signal works.
435  */
436 static void
437 test_changes (void)
438 {
439   GSettings *settings;
440   GSettings *settings2;
441
442   settings = g_settings_new ("org.gtk.test");
443
444   g_signal_connect (settings, "changed",
445                     G_CALLBACK (changed_cb), "greeting");
446
447   changed_cb_called = FALSE;
448
449   g_settings_set (settings, "greeting", "s", "new greeting");
450   g_assert_true (changed_cb_called);
451
452   settings2 = g_settings_new ("org.gtk.test");
453
454   changed_cb_called = FALSE;
455
456   g_settings_set (settings2, "greeting", "s", "hi");
457   g_assert_true (changed_cb_called);
458
459   g_object_unref (settings2);
460   g_object_unref (settings);
461 }
462
463 static gboolean changed_cb_called2;
464
465 static void
466 changed_cb2 (GSettings   *settings,
467              const gchar *key,
468              gpointer     data)
469 {
470   gboolean *p = data;
471
472   *p = TRUE;
473 }
474
475 /* Test that changes done to a delay-mode instance
476  * don't appear to the outside world until apply. Also
477  * check that we get change notification when they are
478  * applied.
479  * Also test that the has-unapplied property is properly
480  * maintained.
481  */
482 static void
483 test_delay_apply (void)
484 {
485   GSettings *settings;
486   GSettings *settings2;
487   gchar *str;
488   gboolean writable;
489   GVariant *v;
490   const gchar *s;
491
492   settings = g_settings_new ("org.gtk.test");
493   settings2 = g_settings_new ("org.gtk.test");
494
495   g_settings_set (settings2, "greeting", "s", "top o' the morning");
496
497   changed_cb_called = FALSE;
498   changed_cb_called2 = FALSE;
499
500   g_signal_connect (settings, "changed",
501                     G_CALLBACK (changed_cb2), &changed_cb_called);
502   g_signal_connect (settings2, "changed",
503                     G_CALLBACK (changed_cb2), &changed_cb_called2);
504
505   g_settings_delay (settings);
506
507   g_settings_set (settings, "greeting", "s", "greetings from test_delay_apply");
508
509   g_assert_true (changed_cb_called);
510   g_assert_false (changed_cb_called2);
511
512   /* Try resetting the key and ensure a notification is emitted on the delayed #GSettings object. */
513   changed_cb_called = FALSE;
514   changed_cb_called2 = FALSE;
515
516   g_settings_reset (settings, "greeting");
517
518   g_assert_true (changed_cb_called);
519   g_assert_false (changed_cb_called2);
520
521   /* Locally change the greeting again. */
522   changed_cb_called = FALSE;
523   changed_cb_called2 = FALSE;
524
525   g_settings_set (settings, "greeting", "s", "greetings from test_delay_apply");
526
527   g_assert_true (changed_cb_called);
528   g_assert_false (changed_cb_called2);
529
530   writable = g_settings_is_writable (settings, "greeting");
531   g_assert_true (writable);
532
533   g_settings_get (settings, "greeting", "s", &str);
534   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
535   g_free (str);
536   str = NULL;
537
538   v = g_settings_get_user_value (settings, "greeting");
539   s = g_variant_get_string (v, NULL);
540   g_assert_cmpstr (s, ==, "greetings from test_delay_apply");
541   g_variant_unref (v);
542
543   g_settings_get (settings2, "greeting", "s", &str);
544   g_assert_cmpstr (str, ==, "top o' the morning");
545   g_free (str);
546   str = NULL;
547
548   g_assert_true (g_settings_get_has_unapplied (settings));
549   g_assert_false (g_settings_get_has_unapplied (settings2));
550
551   changed_cb_called = FALSE;
552   changed_cb_called2 = FALSE;
553
554   g_settings_apply (settings);
555
556   g_assert_false (changed_cb_called);
557   g_assert_true (changed_cb_called2);
558
559   g_settings_get (settings, "greeting", "s", &str);
560   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
561   g_free (str);
562   str = NULL;
563
564   g_settings_get (settings2, "greeting", "s", &str);
565   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
566   g_free (str);
567   str = NULL;
568
569   g_assert_false (g_settings_get_has_unapplied (settings));
570   g_assert_false (g_settings_get_has_unapplied (settings2));
571
572   g_settings_reset (settings, "greeting");
573   g_settings_apply (settings);
574
575   g_settings_get (settings, "greeting", "s", &str);
576   g_assert_cmpstr (str, ==, "Hello, earthlings");
577   g_free (str);
578
579   g_object_unref (settings2);
580   g_object_unref (settings);
581 }
582
583 /* Test that reverting unapplied changes in a delay-apply
584  * settings instance works.
585  */
586 static void
587 test_delay_revert (void)
588 {
589   GSettings *settings;
590   GSettings *settings2;
591   gchar *str;
592
593   settings = g_settings_new ("org.gtk.test");
594   settings2 = g_settings_new ("org.gtk.test");
595
596   g_settings_set (settings2, "greeting", "s", "top o' the morning");
597
598   g_settings_get (settings, "greeting", "s", &str);
599   g_assert_cmpstr (str, ==, "top o' the morning");
600   g_free (str);
601
602   g_settings_delay (settings);
603
604   g_settings_set (settings, "greeting", "s", "greetings from test_delay_revert");
605
606   g_settings_get (settings, "greeting", "s", &str);
607   g_assert_cmpstr (str, ==, "greetings from test_delay_revert");
608   g_free (str);
609   str = NULL;
610
611   g_settings_get (settings2, "greeting", "s", &str);
612   g_assert_cmpstr (str, ==, "top o' the morning");
613   g_free (str);
614   str = NULL;
615
616   g_assert_true (g_settings_get_has_unapplied (settings));
617
618   g_settings_revert (settings);
619
620   g_assert_false (g_settings_get_has_unapplied (settings));
621
622   g_settings_get (settings, "greeting", "s", &str);
623   g_assert_cmpstr (str, ==, "top o' the morning");
624   g_free (str);
625   str = NULL;
626
627   g_settings_get (settings2, "greeting", "s", &str);
628   g_assert_cmpstr (str, ==, "top o' the morning");
629   g_free (str);
630   str = NULL;
631
632   g_object_unref (settings2);
633   g_object_unref (settings);
634 }
635
636 static void
637 test_delay_child (void)
638 {
639   GSettings *base;
640   GSettings *settings;
641   GSettings *child;
642   guint8 byte;
643   gboolean delay;
644
645   base = g_settings_new ("org.gtk.test.basic-types");
646   g_settings_set (base, "test-byte", "y", 36);
647
648   settings = g_settings_new ("org.gtk.test");
649   g_settings_delay (settings);
650   g_object_get (settings, "delay-apply", &delay, NULL);
651   g_assert_true (delay);
652
653   child = g_settings_get_child (settings, "basic-types");
654   g_assert_nonnull (child);
655
656   g_object_get (child, "delay-apply", &delay, NULL);
657   g_assert_false (delay);
658
659   g_settings_get (child, "test-byte", "y", &byte);
660   g_assert_cmpuint (byte, ==, 36);
661
662   g_settings_set (child, "test-byte", "y", 42);
663
664   /* make sure the child was delayed too */
665   g_settings_get (base, "test-byte", "y", &byte);
666   g_assert_cmpuint (byte, ==, 36);
667
668   g_object_unref (child);
669   g_object_unref (settings);
670   g_object_unref (base);
671 }
672
673 static void
674 keys_changed_cb (GSettings    *settings,
675                  const GQuark *keys,
676                  gint          n_keys)
677 {
678   gchar *str;
679
680   g_assert_cmpint (n_keys, ==, 2);
681
682   g_assert_true ((keys[0] == g_quark_from_static_string ("greeting") &&
683                   keys[1] == g_quark_from_static_string ("farewell")) ||
684                  (keys[1] == g_quark_from_static_string ("greeting") &&
685                   keys[0] == g_quark_from_static_string ("farewell")));
686
687   g_settings_get (settings, "greeting", "s", &str);
688   g_assert_cmpstr (str, ==, "greetings from test_atomic");
689   g_free (str);
690   str = NULL;
691
692   g_settings_get (settings, "farewell", "s", &str);
693   g_assert_cmpstr (str, ==, "atomic bye-bye");
694   g_free (str);
695   str = NULL;
696 }
697
698 /* Check that delay-applied changes appear atomically.
699  * More specifically, verify that all changed keys appear
700  * with their new value while handling the change-event signal.
701  */
702 static void
703 test_atomic (void)
704 {
705   GSettings *settings;
706   GSettings *settings2;
707   gchar *str;
708
709   settings = g_settings_new ("org.gtk.test");
710   settings2 = g_settings_new ("org.gtk.test");
711
712   g_settings_set (settings2, "greeting", "s", "top o' the morning");
713
714   changed_cb_called = FALSE;
715   changed_cb_called2 = FALSE;
716
717   g_signal_connect (settings2, "change-event",
718                     G_CALLBACK (keys_changed_cb), NULL);
719
720   g_settings_delay (settings);
721
722   g_settings_set (settings, "greeting", "s", "greetings from test_atomic");
723   g_settings_set (settings, "farewell", "s", "atomic bye-bye");
724
725   g_settings_apply (settings);
726
727   g_settings_get (settings, "greeting", "s", &str);
728   g_assert_cmpstr (str, ==, "greetings from test_atomic");
729   g_free (str);
730   str = NULL;
731
732   g_settings_get (settings, "farewell", "s", &str);
733   g_assert_cmpstr (str, ==, "atomic bye-bye");
734   g_free (str);
735   str = NULL;
736
737   g_settings_get (settings2, "greeting", "s", &str);
738   g_assert_cmpstr (str, ==, "greetings from test_atomic");
739   g_free (str);
740   str = NULL;
741
742   g_settings_get (settings2, "farewell", "s", &str);
743   g_assert_cmpstr (str, ==, "atomic bye-bye");
744   g_free (str);
745   str = NULL;
746
747   g_object_unref (settings2);
748   g_object_unref (settings);
749 }
750
751 /* On Windows the interaction between the C library locale and libintl
752  * (from GNU gettext) is not like on POSIX, so just skip these tests
753  * for now.
754  *
755  * There are several issues:
756  *
757  * 1) The C library doesn't use LC_MESSAGES, that is implemented only
758  * in libintl (defined in its <libintl.h>).
759  *
760  * 2) The locale names that setlocale() accepts and returns aren't in
761  * the "de_DE" style, but like "German_Germany".
762  *
763  * 3) libintl looks at the Win32 thread locale and not the C library
764  * locale. (And even if libintl would use the C library's locale, as
765  * there are several alternative C library DLLs, libintl might be
766  * linked to a different one than the application code, so they
767  * wouldn't have the same C library locale anyway.)
768  */
769
770 /* Test that translations work for schema defaults.
771  *
772  * This test relies on the de.po file in the same directory
773  * to be compiled into ./de/LC_MESSAGES/test.mo
774  */
775 static void
776 test_l10n (void)
777 {
778   GSettings *settings;
779   gchar *str;
780   gchar *locale;
781
782   bindtextdomain ("test", locale_dir);
783   bind_textdomain_codeset ("test", "UTF-8");
784
785   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
786
787   settings = g_settings_new ("org.gtk.test.localized");
788
789   g_setenv ("LC_MESSAGES", "C", TRUE);
790   setlocale (LC_MESSAGES, "C");
791   str = g_settings_get_string (settings, "error-message");
792   g_setenv ("LC_MESSAGES", locale, TRUE);
793   setlocale (LC_MESSAGES, locale);
794
795   g_assert_cmpstr (str, ==, "Unnamed");
796   g_free (str);
797   str = NULL;
798
799   g_setenv ("LC_MESSAGES", "de_DE.UTF-8", TRUE);
800   setlocale (LC_MESSAGES, "de_DE.UTF-8");
801   /* Only do the test if translation is actually working... */
802   if (g_str_equal (dgettext ("test", "\"Unnamed\""), "\"Unbenannt\""))
803     {
804       str = g_settings_get_string (settings, "error-message");
805
806       g_assert_cmpstr (str, ==, "Unbenannt");
807       g_free (str);
808       str = NULL;
809     }
810   else
811     g_printerr ("warning: translation is not working... skipping test. ");
812
813   g_setenv ("LC_MESSAGES", locale, TRUE);
814   setlocale (LC_MESSAGES, locale);
815   g_free (locale);
816   g_object_unref (settings);
817 }
818
819 /* Test that message context works as expected with translated
820  * schema defaults. Also, verify that non-ASCII UTF-8 content
821  * works.
822  *
823  * This test relies on the de.po file in the same directory
824  * to be compiled into ./de/LC_MESSAGES/test.mo
825  */
826 static void
827 test_l10n_context (void)
828 {
829   GSettings *settings;
830   gchar *str;
831   gchar *locale;
832
833   bindtextdomain ("test", locale_dir);
834   bind_textdomain_codeset ("test", "UTF-8");
835
836   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
837
838   settings = g_settings_new ("org.gtk.test.localized");
839
840   g_setenv ("LC_MESSAGES", "C", TRUE);
841   setlocale (LC_MESSAGES, "C");
842   g_settings_get (settings, "backspace", "s", &str);
843   g_setenv ("LC_MESSAGES", locale, TRUE);
844   setlocale (LC_MESSAGES, locale);
845
846   g_assert_cmpstr (str, ==, "BackSpace");
847   g_free (str);
848   str = NULL;
849
850   g_setenv ("LC_MESSAGES", "de_DE.UTF-8", TRUE);
851   setlocale (LC_MESSAGES, "de_DE.UTF-8");
852   /* Only do the test if translation is actually working... */
853   if (g_str_equal (dgettext ("test", "\"Unnamed\""), "\"Unbenannt\""))
854     {
855       g_settings_get (settings, "backspace", "s", &str);
856
857       g_assert_cmpstr (str, ==, "Löschen");
858       g_free (str);
859       str = NULL;
860     }
861   else
862     g_printerr ("warning: translation is not working... skipping test.  ");
863
864   g_setenv ("LC_MESSAGES", locale, TRUE);
865   setlocale (LC_MESSAGES, locale);
866   g_free (locale);
867   g_object_unref (settings);
868 }
869
870 enum
871 {
872   PROP_0,
873   PROP_BOOL,
874   PROP_ANTI_BOOL,
875   PROP_BYTE,
876   PROP_INT16,
877   PROP_UINT16,
878   PROP_INT,
879   PROP_UINT,
880   PROP_INT64,
881   PROP_UINT64,
882   PROP_DOUBLE,
883   PROP_STRING,
884   PROP_NO_READ,
885   PROP_NO_WRITE,
886   PROP_STRV,
887   PROP_ENUM,
888   PROP_FLAGS
889 };
890
891 typedef struct
892 {
893   GObject parent_instance;
894
895   gboolean bool_prop;
896   gboolean anti_bool_prop;
897   gint8 byte_prop;
898   gint int16_prop;
899   guint16 uint16_prop;
900   gint int_prop;
901   guint uint_prop;
902   gint64 int64_prop;
903   guint64 uint64_prop;
904   gdouble double_prop;
905   gchar *string_prop;
906   gchar *no_read_prop;
907   gchar *no_write_prop;
908   gchar **strv_prop;
909   guint enum_prop;
910   guint flags_prop;
911 } TestObject;
912
913 typedef struct
914 {
915   GObjectClass parent_class;
916 } TestObjectClass;
917
918 static GType test_object_get_type (void);
919 G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
920
921 static void
922 test_object_init (TestObject *object)
923 {
924 }
925
926 static void
927 test_object_finalize (GObject *object)
928 {
929   TestObject *testo = (TestObject*)object;
930   g_strfreev (testo->strv_prop);
931   g_free (testo->string_prop);
932   G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
933 }
934
935 static void
936 test_object_get_property (GObject    *object,
937                           guint       prop_id,
938                           GValue     *value,
939                           GParamSpec *pspec)
940 {
941   TestObject *test_object = (TestObject *)object;
942
943   switch (prop_id)
944     {
945     case PROP_BOOL:
946       g_value_set_boolean (value, test_object->bool_prop);
947       break;
948     case PROP_ANTI_BOOL:
949       g_value_set_boolean (value, test_object->anti_bool_prop);
950       break;
951     case PROP_BYTE:
952       g_value_set_schar (value, test_object->byte_prop);
953       break;
954     case PROP_UINT16:
955       g_value_set_uint (value, test_object->uint16_prop);
956       break;
957     case PROP_INT16:
958       g_value_set_int (value, test_object->int16_prop);
959       break;
960     case PROP_INT:
961       g_value_set_int (value, test_object->int_prop);
962       break;
963     case PROP_UINT:
964       g_value_set_uint (value, test_object->uint_prop);
965       break;
966     case PROP_INT64:
967       g_value_set_int64 (value, test_object->int64_prop);
968       break;
969     case PROP_UINT64:
970       g_value_set_uint64 (value, test_object->uint64_prop);
971       break;
972     case PROP_DOUBLE:
973       g_value_set_double (value, test_object->double_prop);
974       break;
975     case PROP_STRING:
976       g_value_set_string (value, test_object->string_prop);
977       break;
978     case PROP_NO_WRITE:
979       g_value_set_string (value, test_object->no_write_prop);
980       break;
981     case PROP_STRV:
982       g_value_set_boxed (value, test_object->strv_prop);
983       break;
984     case PROP_ENUM:
985       g_value_set_enum (value, test_object->enum_prop);
986       break;
987     case PROP_FLAGS:
988       g_value_set_flags (value, test_object->flags_prop);
989       break;
990     default:
991       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
992       break;
993     }
994 }
995
996 static void
997 test_object_set_property (GObject      *object,
998                           guint         prop_id,
999                           const GValue *value,
1000                           GParamSpec   *pspec)
1001 {
1002   TestObject *test_object = (TestObject *)object;
1003
1004   switch (prop_id)
1005     {
1006     case PROP_BOOL:
1007       test_object->bool_prop = g_value_get_boolean (value);
1008       break;
1009     case PROP_ANTI_BOOL:
1010       test_object->anti_bool_prop = g_value_get_boolean (value);
1011       break;
1012     case PROP_BYTE:
1013       test_object->byte_prop = g_value_get_schar (value);
1014       break;
1015     case PROP_INT16:
1016       test_object->int16_prop = g_value_get_int (value);
1017       break;
1018     case PROP_UINT16:
1019       test_object->uint16_prop = g_value_get_uint (value);
1020       break;
1021     case PROP_INT:
1022       test_object->int_prop = g_value_get_int (value);
1023       break;
1024     case PROP_UINT:
1025       test_object->uint_prop = g_value_get_uint (value);
1026       break;
1027     case PROP_INT64:
1028       test_object->int64_prop = g_value_get_int64 (value);
1029       break;
1030     case PROP_UINT64:
1031       test_object->uint64_prop = g_value_get_uint64 (value);
1032       break;
1033     case PROP_DOUBLE:
1034       test_object->double_prop = g_value_get_double (value);
1035       break;
1036     case PROP_STRING:
1037       g_free (test_object->string_prop);
1038       test_object->string_prop = g_value_dup_string (value);
1039       break;
1040     case PROP_NO_READ:
1041       g_free (test_object->no_read_prop);
1042       test_object->no_read_prop = g_value_dup_string (value);
1043       break;
1044     case PROP_STRV:
1045       g_strfreev (test_object->strv_prop);
1046       test_object->strv_prop = g_value_dup_boxed (value);
1047       break;
1048     case PROP_ENUM:
1049       test_object->enum_prop = g_value_get_enum (value);
1050       break;
1051     case PROP_FLAGS:
1052       test_object->flags_prop = g_value_get_flags (value);
1053       break;
1054     default:
1055       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1056       break;
1057     }
1058 }
1059
1060 static GType
1061 test_enum_get_type (void)
1062 {
1063   static gsize define_type_id = 0;
1064
1065   if (g_once_init_enter (&define_type_id))
1066     {
1067       static const GEnumValue values[] = {
1068         { TEST_ENUM_FOO, "TEST_ENUM_FOO", "foo" },
1069         { TEST_ENUM_BAR, "TEST_ENUM_BAR", "bar" },
1070         { TEST_ENUM_BAZ, "TEST_ENUM_BAZ", "baz" },
1071         { TEST_ENUM_QUUX, "TEST_ENUM_QUUX", "quux" },
1072         { 0, NULL, NULL }
1073       };
1074
1075       GType type_id = g_enum_register_static ("TestEnum", values);
1076       g_once_init_leave (&define_type_id, type_id);
1077     }
1078
1079   return define_type_id;
1080 }
1081
1082 static GType
1083 test_flags_get_type (void)
1084 {
1085   static gsize define_type_id = 0;
1086
1087   if (g_once_init_enter (&define_type_id))
1088     {
1089       static const GFlagsValue values[] = {
1090         { TEST_FLAGS_NONE, "TEST_FLAGS_NONE", "none" },
1091         { TEST_FLAGS_MOURNING, "TEST_FLAGS_MOURNING", "mourning" },
1092         { TEST_FLAGS_LAUGHING, "TEST_FLAGS_LAUGHING", "laughing" },
1093         { TEST_FLAGS_WALKING, "TEST_FLAGS_WALKING", "walking" },
1094         { 0, NULL, NULL }
1095       };
1096
1097       GType type_id = g_flags_register_static ("TestFlags", values);
1098       g_once_init_leave (&define_type_id, type_id);
1099     }
1100
1101   return define_type_id;
1102 }
1103
1104 static void
1105 test_object_class_init (TestObjectClass *class)
1106 {
1107   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
1108
1109   gobject_class->get_property = test_object_get_property;
1110   gobject_class->set_property = test_object_set_property;
1111   gobject_class->finalize = test_object_finalize;
1112
1113   g_object_class_install_property (gobject_class, PROP_BOOL,
1114     g_param_spec_boolean ("bool", "", "", FALSE, G_PARAM_READWRITE));
1115   g_object_class_install_property (gobject_class, PROP_ANTI_BOOL,
1116     g_param_spec_boolean ("anti-bool", "", "", FALSE, G_PARAM_READWRITE));
1117   g_object_class_install_property (gobject_class, PROP_BYTE,
1118     g_param_spec_char ("byte", "", "", G_MININT8, G_MAXINT8, 0, G_PARAM_READWRITE));
1119   g_object_class_install_property (gobject_class, PROP_INT16,
1120     g_param_spec_int ("int16", "", "", -G_MAXINT16, G_MAXINT16, 0, G_PARAM_READWRITE));
1121   g_object_class_install_property (gobject_class, PROP_UINT16,
1122     g_param_spec_uint ("uint16", "", "", 0, G_MAXUINT16, 0, G_PARAM_READWRITE));
1123   g_object_class_install_property (gobject_class, PROP_INT,
1124     g_param_spec_int ("int", "", "", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
1125   g_object_class_install_property (gobject_class, PROP_UINT,
1126     g_param_spec_uint ("uint", "", "", 0, G_MAXUINT, 0, G_PARAM_READWRITE));
1127   g_object_class_install_property (gobject_class, PROP_INT64,
1128     g_param_spec_int64 ("int64", "", "", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE));
1129   g_object_class_install_property (gobject_class, PROP_UINT64,
1130     g_param_spec_uint64 ("uint64", "", "", 0, G_MAXUINT64, 0, G_PARAM_READWRITE));
1131   g_object_class_install_property (gobject_class, PROP_DOUBLE,
1132     g_param_spec_double ("double", "", "", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE));
1133   g_object_class_install_property (gobject_class, PROP_STRING,
1134     g_param_spec_string ("string", "", "", NULL, G_PARAM_READWRITE));
1135   g_object_class_install_property (gobject_class, PROP_NO_WRITE,
1136     g_param_spec_string ("no-write", "", "", NULL, G_PARAM_READABLE));
1137   g_object_class_install_property (gobject_class, PROP_NO_READ,
1138     g_param_spec_string ("no-read", "", "", NULL, G_PARAM_WRITABLE));
1139   g_object_class_install_property (gobject_class, PROP_STRV,
1140     g_param_spec_boxed ("strv", "", "", G_TYPE_STRV, G_PARAM_READWRITE));
1141   g_object_class_install_property (gobject_class, PROP_ENUM,
1142     g_param_spec_enum ("enum", "", "", test_enum_get_type (), TEST_ENUM_FOO, G_PARAM_READWRITE));
1143   g_object_class_install_property (gobject_class, PROP_FLAGS,
1144     g_param_spec_flags ("flags", "", "", test_flags_get_type (), TEST_FLAGS_NONE, G_PARAM_READWRITE));
1145 }
1146
1147 static TestObject *
1148 test_object_new (void)
1149 {
1150   return (TestObject*)g_object_new (test_object_get_type (), NULL);
1151 }
1152
1153 /* Test basic binding functionality for simple types.
1154  * Verify that with bidirectional bindings, changes on either side
1155  * are notified on the other end.
1156  */
1157 static void
1158 test_simple_binding (void)
1159 {
1160   TestObject *obj;
1161   GSettings *settings;
1162   gboolean b;
1163   gchar y;
1164   gint i;
1165   guint u;
1166   gint16 n;
1167   guint16 q;
1168   gint n2;
1169   guint q2;
1170   gint64 i64;
1171   guint64 u64;
1172   gdouble d;
1173   gchar *s;
1174   GVariant *value;
1175   gchar **strv;
1176
1177   settings = g_settings_new ("org.gtk.test.binding");
1178   obj = test_object_new ();
1179
1180   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_DEFAULT);
1181   g_object_set (obj, "bool", TRUE, NULL);
1182   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
1183
1184   g_settings_set_boolean (settings, "bool", FALSE);
1185   b = TRUE;
1186   g_object_get (obj, "bool", &b, NULL);
1187   g_assert_cmpint (b, ==, FALSE);
1188
1189   g_settings_bind (settings, "anti-bool", obj, "anti-bool",
1190                    G_SETTINGS_BIND_INVERT_BOOLEAN);
1191   g_object_set (obj, "anti-bool", FALSE, NULL);
1192   g_assert_cmpint (g_settings_get_boolean (settings, "anti-bool"), ==, TRUE);
1193
1194   g_settings_set_boolean (settings, "anti-bool", FALSE);
1195   b = FALSE;
1196   g_object_get (obj, "anti-bool", &b, NULL);
1197   g_assert_cmpint (b, ==, TRUE);
1198
1199   g_settings_bind (settings, "byte", obj, "byte", G_SETTINGS_BIND_DEFAULT);
1200
1201   g_object_set (obj, "byte", 123, NULL);
1202   y = 'c';
1203   g_settings_get (settings, "byte", "y", &y);
1204   g_assert_cmpint (y, ==, 123);
1205
1206   g_settings_set (settings, "byte", "y", 54);
1207   y = 'c';
1208   g_object_get (obj, "byte", &y, NULL);
1209   g_assert_cmpint (y, ==, 54);
1210
1211   g_settings_bind (settings, "int16", obj, "int16", G_SETTINGS_BIND_DEFAULT);
1212
1213   g_object_set (obj, "int16", 1234, NULL);
1214   n = 4321;
1215   g_settings_get (settings, "int16", "n", &n);
1216   g_assert_cmpint (n, ==, 1234);
1217
1218   g_settings_set (settings, "int16", "n", 4321);
1219   n2 = 1111;
1220   g_object_get (obj, "int16", &n2, NULL);
1221   g_assert_cmpint (n2, ==, 4321);
1222
1223   g_settings_bind (settings, "uint16", obj, "uint16", G_SETTINGS_BIND_DEFAULT);
1224
1225   g_object_set (obj, "uint16", (guint16) G_MAXUINT16, NULL);
1226   q = 1111;
1227   g_settings_get (settings, "uint16", "q", &q);
1228   g_assert_cmpuint (q, ==, G_MAXUINT16);
1229
1230   g_settings_set (settings, "uint16", "q", (guint16) G_MAXINT16);
1231   q2 = 1111;
1232   g_object_get (obj, "uint16", &q2, NULL);
1233   g_assert_cmpuint (q2, ==, (guint16) G_MAXINT16);
1234
1235   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
1236
1237   g_object_set (obj, "int", 12345, NULL);
1238   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1239
1240   g_settings_set_int (settings, "int", 54321);
1241   i = 1111;
1242   g_object_get (obj, "int", &i, NULL);
1243   g_assert_cmpint (i, ==, 54321);
1244
1245   g_settings_bind (settings, "uint", obj, "uint", G_SETTINGS_BIND_DEFAULT);
1246
1247   g_object_set (obj, "uint", 12345, NULL);
1248   g_assert_cmpuint (g_settings_get_uint (settings, "uint"), ==, 12345);
1249
1250   g_settings_set_uint (settings, "uint", 54321);
1251   u = 1111;
1252   g_object_get (obj, "uint", &u, NULL);
1253   g_assert_cmpuint (u, ==, 54321);
1254
1255   g_settings_bind (settings, "uint64", obj, "uint64", G_SETTINGS_BIND_DEFAULT);
1256
1257   g_object_set (obj, "uint64", (guint64) 12345, NULL);
1258   g_assert_cmpuint (g_settings_get_uint64 (settings, "uint64"), ==, 12345);
1259
1260   g_settings_set_uint64 (settings, "uint64", 54321);
1261   u64 = 1111;
1262   g_object_get (obj, "uint64", &u64, NULL);
1263   g_assert_cmpuint (u64, ==, 54321);
1264
1265   g_settings_bind (settings, "int64", obj, "int64", G_SETTINGS_BIND_DEFAULT);
1266
1267   g_object_set (obj, "int64", (gint64) G_MAXINT64, NULL);
1268   i64 = 1111;
1269   g_settings_get (settings, "int64", "x", &i64);
1270   g_assert_cmpint (i64, ==, G_MAXINT64);
1271
1272   g_settings_set (settings, "int64", "x", (gint64) G_MININT64);
1273   i64 = 1111;
1274   g_object_get (obj, "int64", &i64, NULL);
1275   g_assert_cmpint (i64, ==, G_MININT64);
1276
1277   g_settings_bind (settings, "uint64", obj, "uint64", G_SETTINGS_BIND_DEFAULT);
1278
1279   g_object_set (obj, "uint64", (guint64) G_MAXUINT64, NULL);
1280   u64 = 1111;
1281   g_settings_get (settings, "uint64", "t", &u64);
1282   g_assert_cmpuint (u64, ==, G_MAXUINT64);
1283
1284   g_settings_set (settings, "uint64", "t", (guint64) G_MAXINT64);
1285   u64 = 1111;
1286   g_object_get (obj, "uint64", &u64, NULL);
1287   g_assert_cmpuint (u64, ==, (guint64) G_MAXINT64);
1288
1289   g_settings_bind (settings, "string", obj, "string", G_SETTINGS_BIND_DEFAULT);
1290
1291   g_object_set (obj, "string", "bu ba", NULL);
1292   s = g_settings_get_string (settings, "string");
1293   g_assert_cmpstr (s, ==, "bu ba");
1294   g_free (s);
1295
1296   g_settings_set_string (settings, "string", "bla bla");
1297   g_object_get (obj, "string", &s, NULL);
1298   g_assert_cmpstr (s, ==, "bla bla");
1299   g_free (s);
1300
1301   g_settings_bind (settings, "chararray", obj, "string", G_SETTINGS_BIND_DEFAULT);
1302
1303   g_object_set (obj, "string", "non-unicode:\315", NULL);
1304   value = g_settings_get_value (settings, "chararray");
1305   g_assert_cmpstr (g_variant_get_bytestring (value), ==, "non-unicode:\315");
1306   g_variant_unref (value);
1307
1308   g_settings_bind (settings, "double", obj, "double", G_SETTINGS_BIND_DEFAULT);
1309
1310   g_object_set (obj, "double", G_MAXFLOAT, NULL);
1311   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXFLOAT);
1312
1313   g_settings_set_double (settings, "double", G_MINFLOAT);
1314   d = 1.0;
1315   g_object_get (obj, "double", &d, NULL);
1316   g_assert_cmpfloat (d, ==, G_MINFLOAT);
1317
1318   g_object_set (obj, "double", G_MAXDOUBLE, NULL);
1319   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXDOUBLE);
1320
1321   g_settings_set_double (settings, "double", -G_MINDOUBLE);
1322   d = 1.0;
1323   g_object_get (obj, "double", &d, NULL);
1324   g_assert_cmpfloat (d, ==, -G_MINDOUBLE);
1325
1326   strv = g_strsplit ("plastic bag,middle class,polyethylene", ",", 0);
1327   g_settings_bind (settings, "strv", obj, "strv", G_SETTINGS_BIND_DEFAULT);
1328   g_object_set (obj, "strv", strv, NULL);
1329   g_strfreev (strv);
1330   strv = g_settings_get_strv (settings, "strv");
1331   s = g_strjoinv (",", strv);
1332   g_assert_cmpstr (s, ==, "plastic bag,middle class,polyethylene");
1333   g_strfreev (strv);
1334   g_free (s);
1335   strv = g_strsplit ("decaffeinate,unleaded,keep all surfaces clean", ",", 0);
1336   g_settings_set_strv (settings, "strv", (const gchar **) strv);
1337   g_strfreev (strv);
1338   g_object_get (obj, "strv", &strv, NULL);
1339   s = g_strjoinv (",", strv);
1340   g_assert_cmpstr (s, ==, "decaffeinate,unleaded,keep all surfaces clean");
1341   g_strfreev (strv);
1342   g_free (s);
1343   g_settings_set_strv (settings, "strv", NULL);
1344   g_object_get (obj, "strv", &strv, NULL);
1345   g_assert_nonnull (strv);
1346   g_assert_cmpint (g_strv_length (strv), ==, 0);
1347   g_strfreev (strv);
1348
1349   g_settings_bind (settings, "enum", obj, "enum", G_SETTINGS_BIND_DEFAULT);
1350   g_object_set (obj, "enum", TEST_ENUM_BAZ, NULL);
1351   s = g_settings_get_string (settings, "enum");
1352   g_assert_cmpstr (s, ==, "baz");
1353   g_free (s);
1354   g_assert_cmpint (g_settings_get_enum (settings, "enum"), ==, TEST_ENUM_BAZ);
1355
1356   g_settings_set_enum (settings, "enum", TEST_ENUM_QUUX);
1357   i = 230;
1358   g_object_get (obj, "enum", &i, NULL);
1359   g_assert_cmpint (i, ==, TEST_ENUM_QUUX);
1360
1361   g_settings_set_string (settings, "enum", "baz");
1362   i = 230;
1363   g_object_get (obj, "enum", &i, NULL);
1364   g_assert_cmpint (i, ==, TEST_ENUM_BAZ);
1365
1366   g_settings_bind (settings, "flags", obj, "flags", G_SETTINGS_BIND_DEFAULT);
1367   g_object_set (obj, "flags", TEST_FLAGS_MOURNING, NULL);
1368   strv = g_settings_get_strv (settings, "flags");
1369   g_assert_cmpint (g_strv_length (strv), ==, 1);
1370   g_assert_cmpstr (strv[0], ==, "mourning");
1371   g_strfreev (strv);
1372
1373   g_assert_cmpint (g_settings_get_flags (settings, "flags"), ==, TEST_FLAGS_MOURNING);
1374
1375   g_settings_set_flags (settings, "flags", TEST_FLAGS_MOURNING | TEST_FLAGS_WALKING);
1376   i = 230;
1377   g_object_get (obj, "flags", &i, NULL);
1378   g_assert_cmpint (i, ==, TEST_FLAGS_MOURNING | TEST_FLAGS_WALKING);
1379
1380   g_settings_bind (settings, "uint", obj, "uint", G_SETTINGS_BIND_DEFAULT);
1381
1382   g_object_set (obj, "uint", 12345, NULL);
1383   g_assert_cmpuint (g_settings_get_uint (settings, "uint"), ==, 12345);
1384
1385   g_settings_set_uint (settings, "uint", 54321);
1386   u = 1111;
1387   g_object_get (obj, "uint", &u, NULL);
1388   g_assert_cmpuint (u, ==, 54321);
1389
1390   g_settings_bind (settings, "range", obj, "uint", G_SETTINGS_BIND_DEFAULT);
1391   g_object_set (obj, "uint", 22, NULL);
1392   u = 1111;
1393   g_assert_cmpuint (g_settings_get_uint (settings, "range"), ==, 22);
1394   g_object_get (obj, "uint", &u, NULL);
1395   g_assert_cmpuint (u, ==, 22);
1396
1397   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1398                          "* is out of schema-specified range for*");
1399   g_object_set (obj, "uint", 45, NULL);
1400   g_test_assert_expected_messages ();
1401   u = 1111;
1402   g_object_get (obj, "uint", &u, NULL);
1403   g_assert_cmpuint (g_settings_get_uint (settings, "range"), ==, 22);
1404   /* The value of the object is currently not reset back to its initial value
1405   g_assert_cmpuint (u, ==, 22); */
1406
1407   g_object_unref (obj);
1408   g_object_unref (settings);
1409 }
1410
1411 static void
1412 test_unbind (void)
1413 {
1414   TestObject *obj;
1415   GSettings *settings;
1416
1417   settings = g_settings_new ("org.gtk.test.binding");
1418   obj = test_object_new ();
1419
1420   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
1421
1422   g_object_set (obj, "int", 12345, NULL);
1423   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1424
1425   g_settings_unbind (obj, "int");
1426
1427   g_object_set (obj, "int", 54321, NULL);
1428   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1429
1430   g_object_unref (obj);
1431   g_object_unref (settings);
1432 }
1433
1434 static void
1435 test_bind_writable (void)
1436 {
1437   TestObject *obj;
1438   GSettings *settings;
1439   gboolean b;
1440
1441   settings = g_settings_new ("org.gtk.test.binding");
1442   obj = test_object_new ();
1443
1444   g_object_set (obj, "bool", FALSE, NULL);
1445
1446   g_settings_bind_writable (settings, "int", obj, "bool", FALSE);
1447
1448   g_object_get (obj, "bool", &b, NULL);
1449   g_assert_true (b);
1450
1451   g_settings_unbind (obj, "bool");
1452
1453   g_settings_bind_writable (settings, "int", obj, "bool", TRUE);
1454
1455   g_object_get (obj, "bool", &b, NULL);
1456   g_assert_false (b);
1457
1458   g_object_unref (obj);
1459   g_object_unref (settings);
1460 }
1461
1462 /* Test one-way bindings.
1463  * Verify that changes on one side show up on the other,
1464  * but not vice versa
1465  */
1466 static void
1467 test_directional_binding (void)
1468 {
1469   TestObject *obj;
1470   GSettings *settings;
1471   gboolean b;
1472   gint i;
1473
1474   settings = g_settings_new ("org.gtk.test.binding");
1475   obj = test_object_new ();
1476
1477   g_object_set (obj, "bool", FALSE, NULL);
1478   g_settings_set_boolean (settings, "bool", FALSE);
1479
1480   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET);
1481
1482   g_settings_set_boolean (settings, "bool", TRUE);
1483   g_object_get (obj, "bool", &b, NULL);
1484   g_assert_cmpint (b, ==, TRUE);
1485
1486   g_object_set (obj, "bool", FALSE, NULL);
1487   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
1488
1489   g_object_set (obj, "int", 20, NULL);
1490   g_settings_set_int (settings, "int", 20);
1491
1492   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_SET);
1493
1494   g_object_set (obj, "int", 32, NULL);
1495   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 32);
1496
1497   g_settings_set_int (settings, "int", 20);
1498   g_object_get (obj, "int", &i, NULL);
1499   g_assert_cmpint (i, ==, 32);
1500
1501   g_object_unref (obj);
1502   g_object_unref (settings);
1503 }
1504
1505 /* Test that type mismatch is caught when creating a binding */
1506 static void
1507 test_typesafe_binding (void)
1508 {
1509   if (!g_test_undefined ())
1510     return;
1511
1512   if (g_test_subprocess ())
1513     {
1514       TestObject *obj;
1515       GSettings *settings;
1516
1517       settings = g_settings_new ("org.gtk.test.binding");
1518       obj = test_object_new ();
1519
1520       g_settings_bind (settings, "string", obj, "int", G_SETTINGS_BIND_DEFAULT);
1521
1522       g_object_unref (obj);
1523       g_object_unref (settings);
1524       return;
1525     }
1526   g_test_trap_subprocess (NULL, 0, 0);
1527   g_test_trap_assert_failed ();
1528   g_test_trap_assert_stderr ("*not compatible*");
1529 }
1530
1531 static gboolean
1532 string_to_bool (GValue   *value,
1533                 GVariant *variant,
1534                 gpointer  user_data)
1535 {
1536   const gchar *s;
1537
1538   s = g_variant_get_string (variant, NULL);
1539   g_value_set_boolean (value, g_strcmp0 (s, "true") == 0);
1540
1541   return TRUE;
1542 }
1543
1544 static GVariant *
1545 bool_to_string (const GValue       *value,
1546                 const GVariantType *expected_type,
1547                 gpointer            user_data)
1548 {
1549   if (g_value_get_boolean (value))
1550     return g_variant_new_string ("true");
1551   else
1552     return g_variant_new_string ("false");
1553 }
1554
1555 static GVariant *
1556 bool_to_bool (const GValue       *value,
1557               const GVariantType *expected_type,
1558               gpointer            user_data)
1559 {
1560   return g_variant_new_boolean (g_value_get_boolean (value));
1561 }
1562
1563 /* Test custom bindings.
1564  * Translate strings to booleans and back
1565  */
1566 static void
1567 test_custom_binding (void)
1568 {
1569   TestObject *obj;
1570   GSettings *settings;
1571   gchar *s;
1572   gboolean b;
1573
1574   settings = g_settings_new ("org.gtk.test.binding");
1575   obj = test_object_new ();
1576
1577   g_settings_set_string (settings, "string", "true");
1578
1579   g_settings_bind_with_mapping (settings, "string",
1580                                 obj, "bool",
1581                                 G_SETTINGS_BIND_DEFAULT,
1582                                 string_to_bool,
1583                                 bool_to_string,
1584                                 NULL, NULL);
1585
1586   g_settings_set_string (settings, "string", "false");
1587   g_object_get (obj, "bool", &b, NULL);
1588   g_assert_cmpint (b, ==, FALSE);
1589
1590   g_settings_set_string (settings, "string", "not true");
1591   g_object_get (obj, "bool", &b, NULL);
1592   g_assert_cmpint (b, ==, FALSE);
1593
1594   g_object_set (obj, "bool", TRUE, NULL);
1595   s = g_settings_get_string (settings, "string");
1596   g_assert_cmpstr (s, ==, "true");
1597   g_free (s);
1598
1599   g_settings_bind_with_mapping (settings, "string",
1600                                 obj, "bool",
1601                                 G_SETTINGS_BIND_DEFAULT,
1602                                 string_to_bool, bool_to_bool,
1603                                 NULL, NULL);
1604   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1605                          "*binding mapping function for key 'string' returned"
1606                          " GVariant of type 'b' when type 's' was requested*");
1607   g_object_set (obj, "bool", FALSE, NULL);
1608   g_test_assert_expected_messages ();
1609
1610   g_object_unref (obj);
1611   g_object_unref (settings);
1612 }
1613
1614 /* Test that with G_SETTINGS_BIND_NO_CHANGES, the
1615  * initial settings value is transported to the object
1616  * side, but later settings changes do not affect the
1617  * object
1618  */
1619 static void
1620 test_no_change_binding (void)
1621 {
1622   TestObject *obj;
1623   GSettings *settings;
1624   gboolean b;
1625
1626   settings = g_settings_new ("org.gtk.test.binding");
1627   obj = test_object_new ();
1628
1629   g_object_set (obj, "bool", TRUE, NULL);
1630   g_settings_set_boolean (settings, "bool", FALSE);
1631
1632   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET_NO_CHANGES);
1633
1634   g_object_get (obj, "bool", &b, NULL);
1635   g_assert_cmpint (b, ==, FALSE);
1636
1637   g_settings_set_boolean (settings, "bool", TRUE);
1638   g_object_get (obj, "bool", &b, NULL);
1639   g_assert_cmpint (b, ==, FALSE);
1640
1641   g_settings_set_boolean (settings, "bool", FALSE);
1642   g_object_set (obj, "bool", TRUE, NULL);
1643   b = g_settings_get_boolean (settings, "bool");
1644   g_assert_cmpint (b, ==, TRUE);
1645
1646   g_object_unref (obj);
1647   g_object_unref (settings);
1648 }
1649
1650 /* Test that binding a non-readable property only
1651  * works in 'GET' mode.
1652  */
1653 static void
1654 test_no_read_binding_fail (void)
1655 {
1656   TestObject *obj;
1657   GSettings *settings;
1658
1659   settings = g_settings_new ("org.gtk.test.binding");
1660   obj = test_object_new ();
1661
1662   g_settings_bind (settings, "string", obj, "no-read", 0);
1663 }
1664
1665 static void
1666 test_no_read_binding_pass (void)
1667 {
1668   TestObject *obj;
1669   GSettings *settings;
1670
1671   settings = g_settings_new ("org.gtk.test.binding");
1672   obj = test_object_new ();
1673
1674   g_settings_bind (settings, "string", obj, "no-read", G_SETTINGS_BIND_GET);
1675
1676   exit (0);
1677 }
1678
1679 static void
1680 test_no_read_binding (void)
1681 {
1682   if (g_test_undefined ())
1683     {
1684       g_test_trap_subprocess ("/gsettings/no-read-binding/subprocess/fail", 0, 0);
1685       g_test_trap_assert_failed ();
1686       g_test_trap_assert_stderr ("*property*is not readable*");
1687     }
1688
1689   g_test_trap_subprocess ("/gsettings/no-read-binding/subprocess/pass", 0, 0);
1690   g_test_trap_assert_passed ();
1691 }
1692
1693 /* Test that binding a non-writable property only
1694  * works in 'SET' mode.
1695  */
1696 static void
1697 test_no_write_binding_fail (void)
1698 {
1699   TestObject *obj;
1700   GSettings *settings;
1701
1702   settings = g_settings_new ("org.gtk.test.binding");
1703   obj = test_object_new ();
1704
1705   g_settings_bind (settings, "string", obj, "no-write", 0);
1706 }
1707
1708 static void
1709 test_no_write_binding_pass (void)
1710 {
1711   TestObject *obj;
1712   GSettings *settings;
1713
1714   settings = g_settings_new ("org.gtk.test.binding");
1715   obj = test_object_new ();
1716
1717   g_settings_bind (settings, "string", obj, "no-write", G_SETTINGS_BIND_SET);
1718
1719   exit (0);
1720 }
1721
1722 static void
1723 test_no_write_binding (void)
1724 {
1725   if (g_test_undefined ())
1726     {
1727       g_test_trap_subprocess ("/gsettings/no-write-binding/subprocess/fail", 0, 0);
1728       g_test_trap_assert_failed ();
1729       g_test_trap_assert_stderr ("*property*is not writable*");
1730     }
1731
1732   g_test_trap_subprocess ("/gsettings/no-write-binding/subprocess/pass", 0, 0);
1733   g_test_trap_assert_passed ();
1734 }
1735
1736 static void
1737 key_changed_cb (GSettings *settings, const gchar *key, gpointer data)
1738 {
1739   gboolean *b = data;
1740   (*b) = TRUE;
1741 }
1742
1743 typedef struct
1744 {
1745   const gchar *path;
1746   const gchar *root_group;
1747   const gchar *keyfile_group;
1748   const gchar *root_path;
1749 } KeyfileTestData;
1750
1751 /*
1752  * Test that using a keyfile works
1753  */
1754 static void
1755 test_keyfile (Fixture       *fixture,
1756               gconstpointer  user_data)
1757 {
1758   GSettingsBackend *kf_backend;
1759   GSettings *settings;
1760   GKeyFile *keyfile;
1761   gchar *str;
1762   gboolean writable;
1763   GError *error = NULL;
1764   gchar *data;
1765   gsize len;
1766   gboolean called = FALSE;
1767   gchar *keyfile_path = NULL, *store_path = NULL;
1768
1769   keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
1770   store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
1771   kf_backend = g_keyfile_settings_backend_new (store_path, "/", "root");
1772   settings = g_settings_new_with_backend ("org.gtk.test", kf_backend);
1773   g_object_unref (kf_backend);
1774
1775   g_settings_reset (settings, "greeting");
1776   str = g_settings_get_string (settings, "greeting");
1777   g_assert_cmpstr (str, ==, "Hello, earthlings");
1778   g_free (str);
1779
1780   writable = g_settings_is_writable (settings, "greeting");
1781   g_assert_true (writable);
1782   g_settings_set (settings, "greeting", "s", "see if this works");
1783
1784   str = g_settings_get_string (settings, "greeting");
1785   g_assert_cmpstr (str, ==, "see if this works");
1786   g_free (str);
1787
1788   g_settings_delay (settings);
1789   g_settings_set (settings, "farewell", "s", "cheerio");
1790   g_settings_apply (settings);
1791
1792   keyfile = g_key_file_new ();
1793   g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1794
1795   str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
1796   g_assert_cmpstr (str, ==, "'see if this works'");
1797   g_free (str);
1798
1799   str = g_key_file_get_string (keyfile, "tests", "farewell", NULL);
1800   g_assert_cmpstr (str, ==, "'cheerio'");
1801   g_free (str);
1802   g_key_file_free (keyfile);
1803
1804   g_settings_reset (settings, "greeting");
1805   g_settings_apply (settings);
1806   keyfile = g_key_file_new ();
1807   g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1808
1809   str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
1810   g_assert_null (str);
1811
1812   called = FALSE;
1813   g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
1814
1815   g_key_file_set_string (keyfile, "tests", "greeting", "'howdy'");
1816   data = g_key_file_to_data (keyfile, &len, NULL);
1817   g_file_set_contents (store_path, data, len, &error);
1818   g_assert_no_error (error);
1819   while (!called)
1820     g_main_context_iteration (NULL, FALSE);
1821   g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
1822
1823   str = g_settings_get_string (settings, "greeting");
1824   g_assert_cmpstr (str, ==, "howdy");
1825   g_free (str);
1826
1827   /* Now check setting a string without quotes */
1828   called = FALSE;
1829   g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
1830
1831   g_key_file_set_string (keyfile, "tests", "greeting", "he\"l🤗uÅ„");
1832   g_free (data);
1833   data = g_key_file_to_data (keyfile, &len, NULL);
1834   g_file_set_contents (store_path, data, len, &error);
1835   g_assert_no_error (error);
1836   while (!called)
1837     g_main_context_iteration (NULL, FALSE);
1838   g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
1839
1840   str = g_settings_get_string (settings, "greeting");
1841   g_assert_cmpstr (str, ==, "he\"l🤗uÅ„");
1842   g_free (str);
1843
1844   g_settings_set (settings, "farewell", "s", "cheerio");
1845
1846   /* Check that empty keys/groups are not allowed. */
1847   g_assert_false (g_settings_is_writable (settings, ""));
1848   g_assert_false (g_settings_is_writable (settings, "/"));
1849
1850   /* When executing as root, changing the mode of the keyfile will have
1851    * no effect on the writability of the settings.
1852    */
1853   if (geteuid () != 0)
1854     {
1855       called = FALSE;
1856       g_signal_connect (settings, "writable-changed::greeting",
1857                         G_CALLBACK (key_changed_cb), &called);
1858
1859       g_assert_no_errno (g_chmod (keyfile_path, 0500));
1860       while (!called)
1861         g_main_context_iteration (NULL, FALSE);
1862       g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
1863
1864       writable = g_settings_is_writable (settings, "greeting");
1865       g_assert_false (writable);
1866     }
1867
1868   g_key_file_free (keyfile);
1869   g_free (data);
1870
1871   g_object_unref (settings);
1872
1873   /* Clean up the temporary directory. */
1874   g_assert_no_errno (g_chmod (keyfile_path, 0777));
1875   g_assert_no_errno (g_remove (store_path));
1876   g_assert_no_errno (g_rmdir (keyfile_path));
1877   g_free (store_path);
1878   g_free (keyfile_path);
1879 }
1880
1881 /*
1882  * Test that using a keyfile works with a schema with no path set.
1883  */
1884 static void
1885 test_keyfile_no_path (Fixture       *fixture,
1886                       gconstpointer  user_data)
1887 {
1888   const KeyfileTestData *test_data = user_data;
1889   GSettingsBackend *kf_backend;
1890   GSettings *settings;
1891   GKeyFile *keyfile;
1892   gboolean writable;
1893   gchar *key = NULL;
1894   GError *error = NULL;
1895   gchar *keyfile_path = NULL, *store_path = NULL;
1896
1897   keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
1898   store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
1899   kf_backend = g_keyfile_settings_backend_new (store_path, test_data->root_path, test_data->root_group);
1900   settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, test_data->path);
1901   g_object_unref (kf_backend);
1902
1903   g_settings_reset (settings, "test-boolean");
1904   g_assert_true (g_settings_get_boolean (settings, "test-boolean"));
1905
1906   writable = g_settings_is_writable (settings, "test-boolean");
1907   g_assert_true (writable);
1908   g_settings_set (settings, "test-boolean", "b", FALSE);
1909
1910   g_assert_false (g_settings_get_boolean (settings, "test-boolean"));
1911
1912   g_settings_delay (settings);
1913   g_settings_set (settings, "test-boolean", "b", TRUE);
1914   g_settings_apply (settings);
1915
1916   keyfile = g_key_file_new ();
1917   g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1918
1919   g_assert_true (g_key_file_get_boolean (keyfile, test_data->keyfile_group, "test-boolean", NULL));
1920
1921   g_key_file_free (keyfile);
1922
1923   g_settings_reset (settings, "test-boolean");
1924   g_settings_apply (settings);
1925   keyfile = g_key_file_new ();
1926   g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1927
1928   g_assert_false (g_key_file_get_string (keyfile, test_data->keyfile_group, "test-boolean", &error));
1929   g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
1930   g_clear_error (&error);
1931
1932   /* Check that empty keys/groups are not allowed. */
1933   g_assert_false (g_settings_is_writable (settings, ""));
1934   g_assert_false (g_settings_is_writable (settings, "/"));
1935
1936   /* Keys which ghost the root group name are not allowed. This can only be
1937    * tested when the path is `/` as otherwise it acts as a prefix and prevents
1938    * any ghosting. */
1939   if (g_str_equal (test_data->path, "/"))
1940     {
1941       key = g_strdup_printf ("%s/%s", test_data->root_group, "");
1942       g_assert_false (g_settings_is_writable (settings, key));
1943       g_free (key);
1944
1945       key = g_strdup_printf ("%s/%s", test_data->root_group, "/");
1946       g_assert_false (g_settings_is_writable (settings, key));
1947       g_free (key);
1948
1949       key = g_strdup_printf ("%s/%s", test_data->root_group, "test-boolean");
1950       g_assert_false (g_settings_is_writable (settings, key));
1951       g_free (key);
1952     }
1953
1954   g_key_file_free (keyfile);
1955   g_object_unref (settings);
1956
1957   /* Clean up the temporary directory. */
1958   g_assert_no_errno (g_chmod (keyfile_path, 0777));
1959   g_assert_no_errno (g_remove (store_path));
1960   g_assert_no_errno (g_rmdir (keyfile_path));
1961   g_free (store_path);
1962   g_free (keyfile_path);
1963 }
1964
1965 /*
1966  * Test that a keyfile rejects writes to keys outside its root path.
1967  */
1968 static void
1969 test_keyfile_outside_root_path (Fixture       *fixture,
1970                                 gconstpointer  user_data)
1971 {
1972   GSettingsBackend *kf_backend;
1973   GSettings *settings;
1974   gchar *keyfile_path = NULL, *store_path = NULL;
1975
1976   keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
1977   store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
1978   kf_backend = g_keyfile_settings_backend_new (store_path, "/tests/basic-types/", "root");
1979   settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/tests/");
1980   g_object_unref (kf_backend);
1981
1982   g_assert_false (g_settings_is_writable (settings, "test-boolean"));
1983
1984   g_object_unref (settings);
1985
1986   /* Clean up the temporary directory. The keyfile probably doesn’t exist, so
1987    * don’t error on failure. */
1988   g_remove (store_path);
1989   g_assert_no_errno (g_rmdir (keyfile_path));
1990   g_free (store_path);
1991   g_free (keyfile_path);
1992 }
1993
1994 /*
1995  * Test that a keyfile rejects writes to keys in the root if no root group is set.
1996  */
1997 static void
1998 test_keyfile_no_root_group (Fixture       *fixture,
1999                             gconstpointer  user_data)
2000 {
2001   GSettingsBackend *kf_backend;
2002   GSettings *settings;
2003   gchar *keyfile_path = NULL, *store_path = NULL;
2004
2005   keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
2006   store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
2007   kf_backend = g_keyfile_settings_backend_new (store_path, "/", NULL);
2008   settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/");
2009   g_object_unref (kf_backend);
2010
2011   g_assert_false (g_settings_is_writable (settings, "test-boolean"));
2012   g_assert_true (g_settings_is_writable (settings, "child/test-boolean"));
2013
2014   g_object_unref (settings);
2015
2016   /* Clean up the temporary directory. The keyfile probably doesn’t exist, so
2017    * don’t error on failure. */
2018   g_remove (store_path);
2019   g_assert_no_errno (g_rmdir (keyfile_path));
2020   g_free (store_path);
2021   g_free (keyfile_path);
2022 }
2023
2024 /* Test that getting child schemas works
2025  */
2026 static void
2027 test_child_schema (void)
2028 {
2029   GSettings *settings;
2030   GSettings *child;
2031   guint8 byte;
2032
2033   /* first establish some known conditions */
2034   settings = g_settings_new ("org.gtk.test.basic-types");
2035   g_settings_set (settings, "test-byte", "y", 36);
2036
2037   g_settings_get (settings, "test-byte", "y", &byte);
2038   g_assert_cmpint (byte, ==, 36);
2039
2040   g_object_unref (settings);
2041
2042   settings = g_settings_new ("org.gtk.test");
2043   child = g_settings_get_child (settings, "basic-types");
2044   g_assert_nonnull (child);
2045
2046   g_settings_get (child, "test-byte", "y", &byte);
2047   g_assert_cmpint (byte, ==, 36);
2048
2049   g_object_unref (child);
2050   g_object_unref (settings);
2051 }
2052
2053 #include "../strinfo.c"
2054
2055 static void
2056 test_strinfo (void)
2057 {
2058   /*  "foo" has a value of 1
2059    *  "bar" has a value of 2
2060    *  "baz" is an alias for "bar"
2061    */
2062   gchar array[] =
2063     "\1\0\0\0"      "\xff""foo"     "\0\0\0\xff"    "\2\0\0\0"
2064     "\xff" "bar"    "\0\0\0\xff"    "\3\0\0\0"      "\xfe""baz"
2065     "\0\0\0\xff";
2066   const guint32 *strinfo = (guint32 *) array;
2067   guint length = sizeof array / 4;
2068   guint result = 0;
2069
2070   {
2071     /* build it and compare */
2072     GString *builder;
2073
2074     builder = g_string_new (NULL);
2075     strinfo_builder_append_item (builder, "foo", 1);
2076     strinfo_builder_append_item (builder, "bar", 2);
2077     g_assert_true (strinfo_builder_append_alias (builder, "baz", "bar"));
2078     g_assert_cmpmem (builder->str, builder->len, strinfo, length * 4);
2079     g_string_free (builder, TRUE);
2080   }
2081
2082   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "foo"),
2083                    ==, NULL);
2084   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "bar"),
2085                    ==, NULL);
2086   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "baz"),
2087                    ==, "bar");
2088   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "quux"),
2089                    ==, NULL);
2090
2091   g_assert_true (strinfo_enum_from_string (strinfo, length, "foo", &result));
2092   g_assert_cmpint (result, ==, 1);
2093   g_assert_true (strinfo_enum_from_string (strinfo, length, "bar", &result));
2094   g_assert_cmpint (result, ==, 2);
2095   g_assert_false (strinfo_enum_from_string (strinfo, length, "baz", &result));
2096   g_assert_false (strinfo_enum_from_string (strinfo, length, "quux", &result));
2097
2098   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 0), ==, NULL);
2099   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 1), ==, "foo");
2100   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 2), ==, "bar");
2101   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 3), ==, NULL);
2102
2103   g_assert_true (strinfo_is_string_valid (strinfo, length, "foo"));
2104   g_assert_true (strinfo_is_string_valid (strinfo, length, "bar"));
2105   g_assert_false (strinfo_is_string_valid (strinfo, length, "baz"));
2106   g_assert_false (strinfo_is_string_valid (strinfo, length, "quux"));
2107 }
2108
2109 static void
2110 test_enums_non_enum_key (void)
2111 {
2112   GSettings *direct;
2113
2114   direct = g_settings_new ("org.gtk.test.enums.direct");
2115   g_settings_get_enum (direct, "test");
2116   g_assert_not_reached ();
2117 }
2118
2119 static void
2120 test_enums_non_enum_value (void)
2121 {
2122   GSettings *settings;
2123
2124   settings = g_settings_new ("org.gtk.test.enums");
2125   g_settings_set_enum (settings, "test", 42);
2126   g_assert_not_reached ();
2127 }
2128
2129 static void
2130 test_enums_range (void)
2131 {
2132   GSettings *settings;
2133
2134   settings = g_settings_new ("org.gtk.test.enums");
2135   g_settings_set_string (settings, "test", "qux");
2136   g_assert_not_reached ();
2137 }
2138
2139 static void
2140 test_enums_non_flags (void)
2141 {
2142   GSettings *settings;
2143
2144   settings = g_settings_new ("org.gtk.test.enums");
2145   g_settings_get_flags (settings, "test");
2146   g_assert_not_reached ();
2147 }
2148
2149 static void
2150 test_enums (void)
2151 {
2152   GSettings *settings, *direct;
2153   gchar *str;
2154
2155   settings = g_settings_new ("org.gtk.test.enums");
2156   direct = g_settings_new ("org.gtk.test.enums.direct");
2157
2158   if (g_test_undefined () && !backend_set)
2159     {
2160       g_test_trap_subprocess ("/gsettings/enums/subprocess/non-enum-key", 0, 0);
2161       g_test_trap_assert_failed ();
2162       g_test_trap_assert_stderr ("*not associated with an enum*");
2163
2164       g_test_trap_subprocess ("/gsettings/enums/subprocess/non-enum-value", 0, 0);
2165       g_test_trap_assert_failed ();
2166       g_test_trap_assert_stderr ("*invalid enum value 42*");
2167
2168       g_test_trap_subprocess ("/gsettings/enums/subprocess/range", 0, 0);
2169       g_test_trap_assert_failed ();
2170       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2171
2172       g_test_trap_subprocess ("/gsettings/enums/subprocess/non-flags", 0, 0);
2173       g_test_trap_assert_failed ();
2174       g_test_trap_assert_stderr ("*not associated with a flags*");
2175     }
2176
2177   str = g_settings_get_string (settings, "test");
2178   g_assert_cmpstr (str, ==, "bar");
2179   g_free (str);
2180
2181   g_settings_set_enum (settings, "test", TEST_ENUM_FOO);
2182
2183   str = g_settings_get_string (settings, "test");
2184   g_assert_cmpstr (str, ==, "foo");
2185   g_free (str);
2186
2187   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_FOO);
2188
2189   g_settings_set_string (direct, "test", "qux");
2190
2191   str = g_settings_get_string (direct, "test");
2192   g_assert_cmpstr (str, ==, "qux");
2193   g_free (str);
2194
2195   str = g_settings_get_string (settings, "test");
2196   g_assert_cmpstr (str, ==, "quux");
2197   g_free (str);
2198
2199   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_QUUX);
2200
2201   g_object_unref (direct);
2202   g_object_unref (settings);
2203 }
2204
2205 static void
2206 test_flags_non_flags_key (void)
2207 {
2208   GSettings *direct;
2209
2210   direct = g_settings_new ("org.gtk.test.enums.direct");
2211   g_settings_get_flags (direct, "test");
2212   g_assert_not_reached ();
2213 }
2214
2215 static void
2216 test_flags_non_flags_value (void)
2217 {
2218   GSettings *settings;
2219
2220   settings = g_settings_new ("org.gtk.test.enums");
2221   g_settings_set_flags (settings, "f-test", 0x42);
2222   g_assert_not_reached ();
2223 }
2224
2225 static void
2226 test_flags_range (void)
2227 {
2228   GSettings *settings;
2229
2230   settings = g_settings_new ("org.gtk.test.enums");
2231   g_settings_set_strv (settings, "f-test",
2232                        (const gchar **) g_strsplit ("rock", ",", 0));
2233   g_assert_not_reached ();
2234 }
2235
2236 static void
2237 test_flags_non_enum (void)
2238 {
2239   GSettings *settings;
2240
2241   settings = g_settings_new ("org.gtk.test.enums");
2242   g_settings_get_enum (settings, "f-test");
2243   g_assert_not_reached ();
2244 }
2245
2246 static void
2247 test_flags (void)
2248 {
2249   GSettings *settings, *direct;
2250   gchar **strv;
2251   gchar *str;
2252
2253   settings = g_settings_new ("org.gtk.test.enums");
2254   direct = g_settings_new ("org.gtk.test.enums.direct");
2255
2256   if (g_test_undefined () && !backend_set)
2257     {
2258       g_test_trap_subprocess ("/gsettings/flags/subprocess/non-flags-key", 0, 0);
2259       g_test_trap_assert_failed ();
2260       g_test_trap_assert_stderr ("*not associated with a flags*");
2261
2262       g_test_trap_subprocess ("/gsettings/flags/subprocess/non-flags-value", 0, 0);
2263       g_test_trap_assert_failed ();
2264       g_test_trap_assert_stderr ("*invalid flags value 0x00000042*");
2265
2266       g_test_trap_subprocess ("/gsettings/flags/subprocess/range", 0, 0);
2267       g_test_trap_assert_failed ();
2268       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2269
2270       g_test_trap_subprocess ("/gsettings/flags/subprocess/non-enum", 0, 0);
2271       g_test_trap_assert_failed ();
2272       g_test_trap_assert_stderr ("*not associated with an enum*");
2273     }
2274
2275   strv = g_settings_get_strv (settings, "f-test");
2276   str = g_strjoinv (",", strv);
2277   g_assert_cmpstr (str, ==, "");
2278   g_strfreev (strv);
2279   g_free (str);
2280
2281   g_settings_set_flags (settings, "f-test",
2282                         TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
2283
2284   strv = g_settings_get_strv (settings, "f-test");
2285   str = g_strjoinv (",", strv);
2286   g_assert_cmpstr (str, ==, "talking,walking");
2287   g_strfreev (strv);
2288   g_free (str);
2289
2290   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
2291                    TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
2292
2293   strv = g_strsplit ("speaking,laughing", ",", 0);
2294   g_settings_set_strv (direct, "f-test", (const gchar **) strv);
2295   g_strfreev (strv);
2296
2297   strv = g_settings_get_strv (direct, "f-test");
2298   str = g_strjoinv (",", strv);
2299   g_assert_cmpstr (str, ==, "speaking,laughing");
2300   g_strfreev (strv);
2301   g_free (str);
2302
2303   strv = g_settings_get_strv (settings, "f-test");
2304   str = g_strjoinv (",", strv);
2305   g_assert_cmpstr (str, ==, "talking,laughing");
2306   g_strfreev (strv);
2307   g_free (str);
2308
2309   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
2310                    TEST_FLAGS_TALKING | TEST_FLAGS_LAUGHING);
2311
2312   g_object_unref (direct);
2313   g_object_unref (settings);
2314 }
2315
2316 static void
2317 test_range_high (void)
2318 {
2319   GSettings *settings;
2320
2321   settings = g_settings_new ("org.gtk.test.range");
2322   g_settings_set_int (settings, "val", 45);
2323   g_assert_not_reached ();
2324 }
2325
2326 static void
2327 test_range_low (void)
2328 {
2329   GSettings *settings;
2330
2331   settings = g_settings_new ("org.gtk.test.range");
2332   g_settings_set_int (settings, "val", 1);
2333   g_assert_not_reached ();
2334 }
2335
2336 static void
2337 test_range (void)
2338 {
2339   GSettings *settings, *direct;
2340   GVariant *value;
2341
2342   settings = g_settings_new ("org.gtk.test.range");
2343   direct = g_settings_new ("org.gtk.test.range.direct");
2344
2345   if (g_test_undefined () && !backend_set)
2346     {
2347       g_test_trap_subprocess ("/gsettings/range/subprocess/high", 0, 0);
2348       g_test_trap_assert_failed ();
2349       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2350
2351       g_test_trap_subprocess ("/gsettings/range/subprocess/low", 0, 0);
2352       g_test_trap_assert_failed ();
2353       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2354     }
2355
2356   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
2357   g_settings_set_int (direct, "val", 22);
2358   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 22);
2359   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 22);
2360   g_settings_set_int (direct, "val", 45);
2361   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 45);
2362   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
2363   g_settings_set_int (direct, "val", 1);
2364   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 1);
2365   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
2366
2367 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2368   value = g_variant_new_int32 (1);
2369   g_assert_false (g_settings_range_check (settings, "val", value));
2370   g_variant_unref (value);
2371   value = g_variant_new_int32 (33);
2372   g_assert_true (g_settings_range_check (settings, "val", value));
2373   g_variant_unref (value);
2374   value = g_variant_new_int32 (45);
2375   g_assert_false (g_settings_range_check (settings, "val", value));
2376   g_variant_unref (value);
2377 G_GNUC_END_IGNORE_DEPRECATIONS
2378
2379   g_object_unref (direct);
2380   g_object_unref (settings);
2381 }
2382
2383 static gboolean
2384 strv_has_string (gchar       **haystack,
2385                  const gchar  *needle)
2386 {
2387   guint n;
2388
2389   for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
2390     {
2391       if (g_strcmp0 (haystack[n], needle) == 0)
2392         return TRUE;
2393     }
2394   return FALSE;
2395 }
2396
2397 static gboolean
2398 strv_set_equal (gchar **strv, ...)
2399 {
2400   gint count;
2401   va_list list;
2402   const gchar *str;
2403   gboolean res;
2404
2405   res = TRUE;
2406   count = 0;
2407   va_start (list, strv);
2408   while (1)
2409     {
2410       str = va_arg (list, const gchar *);
2411       if (str == NULL)
2412         break;
2413       if (!strv_has_string (strv, str))
2414         {
2415           res = FALSE;
2416           break;
2417         }
2418       count++;
2419     }
2420   va_end (list);
2421
2422   if (res)
2423     res = g_strv_length ((gchar**)strv) == count;
2424
2425   return res;
2426 }
2427
2428 static void
2429 test_list_items (void)
2430 {
2431   GSettingsSchema *schema;
2432   GSettings *settings;
2433   gchar **children;
2434   gchar **keys;
2435
2436   settings = g_settings_new ("org.gtk.test");
2437   g_object_get (settings, "settings-schema", &schema, NULL);
2438   children = g_settings_list_children (settings);
2439   keys = g_settings_schema_list_keys (schema);
2440
2441   g_assert_true (strv_set_equal (children, "basic-types", "complex-types", "localized", NULL));
2442   g_assert_true (strv_set_equal (keys, "greeting", "farewell", NULL));
2443
2444   g_strfreev (children);
2445   g_strfreev (keys);
2446
2447   g_settings_schema_unref (schema);
2448   g_object_unref (settings);
2449 }
2450
2451 static void
2452 test_list_schemas (void)
2453 {
2454   const gchar * const *schemas;
2455   const gchar * const *relocs;
2456
2457 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2458   relocs = g_settings_list_relocatable_schemas ();
2459   schemas = g_settings_list_schemas ();
2460 G_GNUC_END_IGNORE_DEPRECATIONS
2461
2462   g_assert_true (strv_set_equal ((gchar **)relocs,
2463                                  "org.gtk.test.no-path",
2464                                  "org.gtk.test.extends.base",
2465                                  "org.gtk.test.extends.extended",
2466                                  NULL));
2467
2468   g_assert_true (strv_set_equal ((gchar **)schemas,
2469                                  "org.gtk.test",
2470                                  "org.gtk.test.basic-types",
2471                                  "org.gtk.test.complex-types",
2472                                  "org.gtk.test.localized",
2473                                  "org.gtk.test.binding",
2474                                  "org.gtk.test.enums",
2475                                  "org.gtk.test.enums.direct",
2476                                  "org.gtk.test.range",
2477                                  "org.gtk.test.range.direct",
2478                                  "org.gtk.test.mapped",
2479                                  "org.gtk.test.descriptions",
2480                                  "org.gtk.test.per-desktop",
2481                                  NULL));
2482 }
2483
2484 static gboolean
2485 map_func (GVariant *value,
2486           gpointer *result,
2487           gpointer  user_data)
2488 {
2489   gint *state = user_data;
2490   gint v;
2491
2492   if (value)
2493     v = g_variant_get_int32 (value);
2494   else
2495     v = -1;
2496
2497   if (*state == 0)
2498     {
2499       g_assert_cmpint (v, ==, 1);
2500       (*state)++;
2501       return FALSE;
2502     }
2503   else if (*state == 1)
2504     {
2505       g_assert_cmpint (v, ==, 0);
2506       (*state)++;
2507       return FALSE;
2508     }
2509   else
2510     {
2511       g_assert_null (value);
2512       *result = g_variant_new_int32 (5);
2513       return TRUE;
2514     }
2515 }
2516
2517 static void
2518 test_get_mapped (void)
2519 {
2520   GSettings *settings;
2521   gint state;
2522   gpointer p;
2523   gint val;
2524
2525   settings = g_settings_new ("org.gtk.test.mapped");
2526   g_settings_set_int (settings, "val", 1);
2527
2528   state = 0;
2529   p = g_settings_get_mapped (settings, "val", map_func, &state);
2530   val = g_variant_get_int32 ((GVariant*)p);
2531   g_assert_cmpint (val, ==, 5);
2532
2533   g_variant_unref (p);
2534   g_object_unref (settings);
2535 }
2536
2537 static void
2538 test_get_range (void)
2539 {
2540   GSettings *settings;
2541   GVariant *range;
2542
2543 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2544   settings = g_settings_new ("org.gtk.test.range");
2545   range = g_settings_get_range (settings, "val");
2546   check_and_free (range, "('range', <(2, 44)>)");
2547   g_object_unref (settings);
2548
2549   settings = g_settings_new ("org.gtk.test.enums");
2550   range = g_settings_get_range (settings, "test");
2551   check_and_free (range, "('enum', <['foo', 'bar', 'baz', 'quux']>)");
2552   g_object_unref (settings);
2553
2554   settings = g_settings_new ("org.gtk.test.enums");
2555   range = g_settings_get_range (settings, "f-test");
2556   check_and_free (range, "('flags', "
2557                   "<['mourning', 'laughing', 'talking', 'walking']>)");
2558   g_object_unref (settings);
2559
2560   settings = g_settings_new ("org.gtk.test");
2561   range = g_settings_get_range (settings, "greeting");
2562   check_and_free (range, "('type', <@as []>)");
2563   g_object_unref (settings);
2564 G_GNUC_END_IGNORE_DEPRECATIONS
2565 }
2566
2567 static void
2568 test_schema_source (void)
2569 {
2570   GSettingsSchemaSource *parent;
2571   GSettingsSchemaSource *source;
2572   GSettingsBackend *backend;
2573   GSettingsSchema *schema;
2574   GError *error = NULL;
2575   GSettings *settings;
2576   gboolean enabled;
2577
2578   backend = g_settings_backend_get_default ();
2579
2580   /* make sure it fails properly */
2581   parent = g_settings_schema_source_get_default ();
2582   source = g_settings_schema_source_new_from_directory ("/path/that/does/not/exist", parent,  TRUE, &error);
2583   g_assert_null (source);
2584   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
2585   g_clear_error (&error);
2586
2587   /* Test error handling of corrupt compiled files. */
2588   source = g_settings_schema_source_new_from_directory ("schema-source-corrupt", parent, TRUE, &error);
2589   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
2590   g_assert_null (source);
2591   g_clear_error (&error);
2592
2593   /* Test error handling of empty compiled files. */
2594   source = g_settings_schema_source_new_from_directory ("schema-source-empty", parent, TRUE, &error);
2595   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
2596   g_assert_null (source);
2597   g_clear_error (&error);
2598
2599   /* create a source with the parent */
2600   source = g_settings_schema_source_new_from_directory ("schema-source", parent, TRUE, &error);
2601   g_assert_no_error (error);
2602   g_assert_nonnull (source);
2603
2604   /* check recursive lookups are working */
2605   schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
2606   g_assert_nonnull (schema);
2607   g_settings_schema_unref (schema);
2608
2609   /* check recursive lookups for non-existent schemas */
2610   schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", TRUE);
2611   g_assert_null (schema);
2612
2613   /* check non-recursive for schema that only exists in lower layers */
2614   schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
2615   g_assert_null (schema);
2616
2617   /* check non-recursive lookup for non-existent */
2618   schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", FALSE);
2619   g_assert_null (schema);
2620
2621   /* check non-recursive for schema that exists in toplevel */
2622   schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
2623   g_assert_nonnull (schema);
2624   g_settings_schema_unref (schema);
2625
2626   /* check recursive for schema that exists in toplevel */
2627   schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
2628   g_assert_nonnull (schema);
2629
2630   /* try to use it for something */
2631   settings = g_settings_new_full (schema, backend, g_settings_schema_get_path (schema));
2632   g_settings_schema_unref (schema);
2633   enabled = FALSE;
2634   g_settings_get (settings, "enabled", "b", &enabled);
2635   g_assert_true (enabled);
2636   g_object_unref (settings);
2637
2638   g_settings_schema_source_unref (source);
2639
2640   /* try again, but with no parent */
2641   source = g_settings_schema_source_new_from_directory ("schema-source", NULL, FALSE, NULL);
2642   g_assert_nonnull (source);
2643
2644   /* should not find it this time, even if recursive... */
2645   schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
2646   g_assert_null (schema);
2647   schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
2648   g_assert_null (schema);
2649
2650   /* should still find our own... */
2651   schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
2652   g_assert_nonnull (schema);
2653   g_settings_schema_unref (schema);
2654   schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
2655   g_assert_nonnull (schema);
2656   g_settings_schema_unref (schema);
2657
2658   g_settings_schema_source_unref (source);
2659   g_object_unref (backend);
2660 }
2661
2662 static void
2663 test_schema_list_keys (void)
2664 {
2665   gchar                 **keys;
2666   GSettingsSchemaSource  *src    = g_settings_schema_source_get_default ();
2667   GSettingsSchema        *schema = g_settings_schema_source_lookup (src, "org.gtk.test", TRUE);
2668   g_assert_nonnull (schema);
2669
2670   keys = g_settings_schema_list_keys (schema);
2671
2672   g_assert_true (strv_set_equal ((gchar **)keys,
2673                                  "greeting",
2674                                  "farewell",
2675                                  NULL));
2676
2677   g_strfreev (keys);
2678   g_settings_schema_unref (schema);
2679 }
2680
2681 static void
2682 test_actions (void)
2683 {
2684   GAction *string, *toggle;
2685   gboolean c1, c2, c3;
2686   GSettings *settings;
2687   gchar *name;
2688   GVariantType *param_type;
2689   gboolean enabled;
2690   GVariantType *state_type;
2691   GVariant *state;
2692
2693   settings = g_settings_new ("org.gtk.test.basic-types");
2694   string = g_settings_create_action (settings, "test-string");
2695   toggle = g_settings_create_action (settings, "test-boolean");
2696   g_object_unref (settings); /* should be held by the actions */
2697
2698   g_signal_connect (settings, "changed", G_CALLBACK (changed_cb2), &c1);
2699   g_signal_connect (string, "notify::state", G_CALLBACK (changed_cb2), &c2);
2700   g_signal_connect (toggle, "notify::state", G_CALLBACK (changed_cb2), &c3);
2701
2702   c1 = c2 = c3 = FALSE;
2703   g_settings_set_string (settings, "test-string", "hello world");
2704   check_and_free (g_action_get_state (string), "'hello world'");
2705   g_assert_true (c1 && c2 && !c3);
2706   c1 = c2 = c3 = FALSE;
2707
2708   g_action_activate (string, g_variant_new_string ("hihi"));
2709   check_and_free (g_settings_get_value (settings, "test-string"), "'hihi'");
2710   g_assert_true (c1 && c2 && !c3);
2711   c1 = c2 = c3 = FALSE;
2712
2713   g_action_change_state (string, g_variant_new_string ("kthxbye"));
2714   check_and_free (g_settings_get_value (settings, "test-string"), "'kthxbye'");
2715   g_assert_true (c1 && c2 && !c3);
2716   c1 = c2 = c3 = FALSE;
2717
2718   g_action_change_state (toggle, g_variant_new_boolean (TRUE));
2719   g_assert_true (g_settings_get_boolean (settings, "test-boolean"));
2720   g_assert_true (c1 && !c2 && c3);
2721   c1 = c2 = c3 = FALSE;
2722
2723   g_action_activate (toggle, NULL);
2724   g_assert_false (g_settings_get_boolean (settings, "test-boolean"));
2725   g_assert_true (c1 && !c2 && c3);
2726
2727   g_object_get (string,
2728                 "name", &name,
2729                 "parameter-type", &param_type,
2730                 "enabled", &enabled,
2731                 "state-type", &state_type,
2732                 "state", &state,
2733                 NULL);
2734
2735   g_assert_cmpstr (name, ==, "test-string");
2736   g_assert_true (g_variant_type_equal (param_type, G_VARIANT_TYPE_STRING));
2737   g_assert_true (enabled);
2738   g_assert_true (g_variant_type_equal (state_type, G_VARIANT_TYPE_STRING));
2739   g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "kthxbye");
2740
2741   g_free (name);
2742   g_variant_type_free (param_type);
2743   g_variant_type_free (state_type);
2744   g_variant_unref (state);
2745
2746   g_object_unref (string);
2747   g_object_unref (toggle);
2748 }
2749
2750 static void
2751 test_null_backend (void)
2752 {
2753   GSettingsBackend *backend;
2754   GSettings *settings;
2755   gchar *str;
2756   gboolean writable;
2757
2758   backend = g_null_settings_backend_new ();
2759   settings = g_settings_new_with_backend_and_path ("org.gtk.test", backend, "/tests/");
2760
2761   g_object_get (settings, "schema-id", &str, NULL);
2762   g_assert_cmpstr (str, ==, "org.gtk.test");
2763   g_free (str);
2764
2765   g_settings_get (settings, "greeting", "s", &str);
2766   g_assert_cmpstr (str, ==, "Hello, earthlings");
2767   g_free (str);
2768
2769   g_settings_set (settings, "greeting", "s", "goodbye world");
2770   g_settings_get (settings, "greeting", "s", &str);
2771   g_assert_cmpstr (str, ==, "Hello, earthlings");
2772   g_free (str);
2773
2774   writable = g_settings_is_writable (settings, "greeting");
2775   g_assert_false (writable);
2776
2777   g_settings_reset (settings, "greeting");
2778
2779   g_settings_delay (settings);
2780   g_settings_set (settings, "greeting", "s", "goodbye world");
2781   g_settings_apply (settings);
2782   g_settings_get (settings, "greeting", "s", &str);
2783   g_assert_cmpstr (str, ==, "Hello, earthlings");
2784   g_free (str);
2785
2786   g_object_unref (settings);
2787   g_object_unref (backend);
2788 }
2789
2790 static void
2791 test_memory_backend (void)
2792 {
2793   GSettingsBackend *backend;
2794
2795   backend = g_memory_settings_backend_new ();
2796   g_assert_true (G_IS_SETTINGS_BACKEND (backend));
2797   g_object_unref (backend);
2798 }
2799
2800 static void
2801 test_read_descriptions (void)
2802 {
2803   GSettingsSchema *schema;
2804   GSettingsSchemaKey *key;
2805   GSettings *settings;
2806
2807   settings = g_settings_new ("org.gtk.test");
2808   g_object_get (settings, "settings-schema", &schema, NULL);
2809   key = g_settings_schema_get_key (schema, "greeting");
2810
2811   g_assert_cmpstr (g_settings_schema_key_get_summary (key), ==, "A greeting");
2812   g_assert_cmpstr (g_settings_schema_key_get_description (key), ==, "Greeting of the invading martians");
2813
2814   g_settings_schema_key_unref (key);
2815   g_settings_schema_unref (schema);
2816
2817   g_object_unref (settings);
2818
2819   settings = g_settings_new ("org.gtk.test.descriptions");
2820   g_object_get (settings, "settings-schema", &schema, NULL);
2821   key = g_settings_schema_get_key (schema, "a");
2822
2823   g_assert_cmpstr (g_settings_schema_key_get_summary (key), ==,
2824                    "a paragraph.\n\n"
2825                    "with some whitespace.\n\n"
2826                    "because not everyone has a great editor.\n\n"
2827                    "lots of space is as one.");
2828
2829   g_settings_schema_key_unref (key);
2830   g_settings_schema_unref (schema);
2831
2832   g_object_unref (settings);
2833 }
2834
2835 static void
2836 test_default_value (void)
2837 {
2838   GSettings *settings;
2839   GSettingsSchema *schema;
2840   GSettingsSchemaKey *key;
2841   GVariant *v;
2842   const gchar *str;
2843   gchar *s;
2844
2845   settings = g_settings_new ("org.gtk.test");
2846   g_object_get (settings, "settings-schema", &schema, NULL);
2847   key = g_settings_schema_get_key (schema, "greeting");
2848   g_settings_schema_unref (schema);
2849   g_settings_schema_key_ref (key);
2850
2851   g_assert_true (g_variant_type_equal (g_settings_schema_key_get_value_type (key), G_VARIANT_TYPE_STRING));
2852
2853   v = g_settings_schema_key_get_default_value (key);
2854   str = g_variant_get_string (v, NULL);
2855   g_assert_cmpstr (str, ==, "Hello, earthlings");
2856   g_variant_unref (v);
2857
2858   g_settings_schema_key_unref (key);
2859   g_settings_schema_key_unref (key);
2860
2861   g_settings_set (settings, "greeting", "s", "goodbye world");
2862
2863   v = g_settings_get_user_value (settings, "greeting");
2864   str = g_variant_get_string (v, NULL);
2865   g_assert_cmpstr (str, ==, "goodbye world");
2866   g_variant_unref (v);
2867
2868   v = g_settings_get_default_value (settings, "greeting");
2869   str = g_variant_get_string (v, NULL);
2870   g_assert_cmpstr (str, ==, "Hello, earthlings");
2871   g_variant_unref (v);
2872
2873   g_settings_reset (settings, "greeting");
2874
2875   v = g_settings_get_user_value (settings, "greeting");
2876   g_assert_null (v);
2877
2878   s = g_settings_get_string (settings, "greeting");
2879   g_assert_cmpstr (s, ==, "Hello, earthlings");
2880   g_free (s);
2881
2882   g_object_unref (settings);
2883 }
2884
2885 static gboolean
2886 string_map_func (GVariant *value,
2887                  gpointer *result,
2888                  gpointer  user_data)
2889 {
2890   const gchar *str;
2891
2892   str = g_variant_get_string (value, NULL);
2893   *result = g_variant_new_string (str);
2894
2895   return TRUE;
2896 }
2897
2898 /* Test that per-desktop values from org.gtk.test.gschema.override
2899  * does not change default value if current desktop is not listed in
2900  * $XDG_CURRENT_DESKTOP.
2901  */
2902 static void
2903 test_per_desktop (void)
2904 {
2905   GSettings *settings;
2906   TestObject *obj;
2907   gpointer p;
2908   gchar *str;
2909
2910   settings = g_settings_new ("org.gtk.test.per-desktop");
2911   obj = test_object_new ();
2912
2913   if (!g_test_subprocess ())
2914     {
2915       g_test_trap_subprocess ("/gsettings/per-desktop/subprocess", 0, 0);
2916       g_test_trap_assert_passed ();
2917     }
2918
2919   str = g_settings_get_string (settings, "desktop");
2920   g_assert_cmpstr (str, ==, "GNOME");
2921   g_free (str);
2922
2923   p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL);
2924
2925   str = g_variant_dup_string (p, NULL);
2926   g_assert_cmpstr (str, ==, "GNOME");
2927   g_free (str);
2928
2929   g_variant_unref (p);
2930
2931   g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT);
2932
2933   g_object_get (obj, "string", &str, NULL);
2934   g_assert_cmpstr (str, ==, "GNOME");
2935   g_free (str);
2936
2937   g_object_unref (settings);
2938   g_object_unref (obj);
2939 }
2940
2941 /* Test that per-desktop values from org.gtk.test.gschema.override
2942  * are successfully loaded based on the value of $XDG_CURRENT_DESKTOP.
2943  */
2944 static void
2945 test_per_desktop_subprocess (void)
2946 {
2947   GSettings *settings;
2948   TestObject *obj;
2949   gpointer p;
2950   gchar *str;
2951
2952   g_setenv ("XDG_CURRENT_DESKTOP", "GNOME-Classic:GNOME", TRUE);
2953
2954   settings = g_settings_new ("org.gtk.test.per-desktop");
2955   obj = test_object_new ();
2956
2957   str = g_settings_get_string (settings, "desktop");
2958   g_assert_cmpstr (str, ==, "GNOME Classic");
2959   g_free (str);
2960
2961   p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL);
2962
2963   str = g_variant_dup_string (p, NULL);
2964   g_assert_cmpstr (str, ==, "GNOME Classic");
2965   g_free (str);
2966
2967   g_variant_unref (p);
2968
2969   g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT);
2970
2971   g_object_get (obj, "string", &str, NULL);
2972   g_assert_cmpstr (str, ==, "GNOME Classic");
2973   g_free (str);
2974
2975   g_object_unref (settings);
2976   g_object_unref (obj);
2977 }
2978
2979 static void
2980 test_extended_schema (void)
2981 {
2982   GSettingsSchema *schema;
2983   GSettings *settings;
2984   gchar **keys;
2985
2986   settings = g_settings_new_with_path ("org.gtk.test.extends.extended", "/test/extendes/");
2987   g_object_get (settings, "settings-schema", &schema, NULL);
2988   keys = g_settings_schema_list_keys (schema);
2989   g_assert_true (strv_set_equal (keys, "int32", "string", "another-int32", NULL));
2990   g_strfreev (keys);
2991   g_object_unref (settings);
2992   g_settings_schema_unref (schema);
2993 }
2994
2995 int
2996 main (int argc, char *argv[])
2997 {
2998   gchar *schema_text;
2999   gchar *override_text;
3000   gchar *enums;
3001   gint result;
3002   const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" };
3003   const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" };
3004   const KeyfileTestData keyfile_test_data_long_path = {
3005     "/tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch/",
3006     "root",
3007     "tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch",
3008     "/"
3009   };
3010
3011 /* Meson build sets this */
3012 #ifdef TEST_LOCALE_PATH
3013   if (g_str_has_suffix (TEST_LOCALE_PATH, "LC_MESSAGES"))
3014     {
3015       locale_dir = TEST_LOCALE_PATH G_DIR_SEPARATOR_S ".." G_DIR_SEPARATOR_S "..";
3016     }
3017 #endif
3018
3019   setlocale (LC_ALL, "");
3020
3021   g_test_init (&argc, &argv, NULL);
3022
3023   if (!g_test_subprocess ())
3024     {
3025       GError *local_error = NULL;
3026       /* A GVDB header is 6 guint32s, and requires a magic number in the first
3027        * two guint32s. A set of zero bytes of a greater length is considered
3028        * corrupt. */
3029       const guint8 gschemas_compiled_corrupt[sizeof (guint32) * 7] = { 0, };
3030
3031       backend_set = g_getenv ("GSETTINGS_BACKEND") != NULL;
3032
3033       g_setenv ("XDG_DATA_DIRS", ".", TRUE);
3034       g_setenv ("XDG_DATA_HOME", ".", TRUE);
3035       g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
3036       g_setenv ("XDG_CURRENT_DESKTOP", "", TRUE);
3037
3038       if (!backend_set)
3039         g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
3040
3041       g_remove ("org.gtk.test.enums.xml");
3042       /* #GLIB_MKENUMS is defined in meson.build */
3043       g_assert_true (g_spawn_command_line_sync (GLIB_MKENUMS " "
3044                                                 "--template " SRCDIR "/enums.xml.template "
3045                                                 SRCDIR "/testenum.h",
3046                                                 &enums, NULL, &result, NULL));
3047       g_assert_cmpint (result, ==, 0);
3048       g_assert_true (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
3049       g_free (enums);
3050
3051       g_assert_true (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.xml.orig", &schema_text, NULL, NULL));
3052       g_assert_true (g_file_set_contents ("org.gtk.test.gschema.xml", schema_text, -1, NULL));
3053       g_free (schema_text);
3054
3055       g_assert_true (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.override.orig", &override_text, NULL, NULL));
3056       g_assert_true (g_file_set_contents ("org.gtk.test.gschema.override", override_text, -1, NULL));
3057       g_free (override_text);
3058
3059       g_remove ("gschemas.compiled");
3060       /* #GLIB_COMPILE_SCHEMAS is defined in meson.build */
3061       g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=. "
3062                                                 "--schema-file=org.gtk.test.enums.xml "
3063                                                 "--schema-file=org.gtk.test.gschema.xml "
3064                                                 "--override-file=org.gtk.test.gschema.override",
3065                                                 NULL, NULL, &result, NULL));
3066       g_assert_cmpint (result, ==, 0);
3067
3068       g_remove ("schema-source/gschemas.compiled");
3069       g_mkdir ("schema-source", 0777);
3070       g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=schema-source "
3071                                                 "--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml",
3072                                                 NULL, NULL, &result, NULL));
3073       g_assert_cmpint (result, ==, 0);
3074
3075       g_remove ("schema-source-corrupt/gschemas.compiled");
3076       g_mkdir ("schema-source-corrupt", 0777);
3077       g_file_set_contents ("schema-source-corrupt/gschemas.compiled",
3078                            (const gchar *) gschemas_compiled_corrupt,
3079                            sizeof (gschemas_compiled_corrupt),
3080                            &local_error);
3081       g_assert_no_error (local_error);
3082
3083       g_remove ("schema-source-empty/gschemas.compiled");
3084       g_mkdir ("schema-source-empty", 0777);
3085       g_file_set_contents ("schema-source-empty/gschemas.compiled",
3086                            "", 0,
3087                            &local_error);
3088       g_assert_no_error (local_error);
3089    }
3090
3091   g_test_add_func ("/gsettings/basic", test_basic);
3092
3093   if (!backend_set)
3094     {
3095       g_test_add_func ("/gsettings/no-schema", test_no_schema);
3096       g_test_add_func ("/gsettings/unknown-key", test_unknown_key);
3097       g_test_add_func ("/gsettings/wrong-type", test_wrong_type);
3098       g_test_add_func ("/gsettings/wrong-path", test_wrong_path);
3099       g_test_add_func ("/gsettings/no-path", test_no_path);
3100     }
3101
3102   g_test_add_func ("/gsettings/basic-types", test_basic_types);
3103   g_test_add_func ("/gsettings/complex-types", test_complex_types);
3104   g_test_add_func ("/gsettings/changes", test_changes);
3105
3106   g_test_add_func ("/gsettings/l10n", test_l10n);
3107   g_test_add_func ("/gsettings/l10n-context", test_l10n_context);
3108
3109   g_test_add_func ("/gsettings/delay-apply", test_delay_apply);
3110   g_test_add_func ("/gsettings/delay-revert", test_delay_revert);
3111   g_test_add_func ("/gsettings/delay-child", test_delay_child);
3112   g_test_add_func ("/gsettings/atomic", test_atomic);
3113
3114   g_test_add_func ("/gsettings/simple-binding", test_simple_binding);
3115   g_test_add_func ("/gsettings/directional-binding", test_directional_binding);
3116   g_test_add_func ("/gsettings/custom-binding", test_custom_binding);
3117   g_test_add_func ("/gsettings/no-change-binding", test_no_change_binding);
3118   g_test_add_func ("/gsettings/unbinding", test_unbind);
3119   g_test_add_func ("/gsettings/writable-binding", test_bind_writable);
3120
3121   if (!backend_set)
3122     {
3123       g_test_add_func ("/gsettings/typesafe-binding", test_typesafe_binding);
3124       g_test_add_func ("/gsettings/no-read-binding", test_no_read_binding);
3125       g_test_add_func ("/gsettings/no-read-binding/subprocess/fail", test_no_read_binding_fail);
3126       g_test_add_func ("/gsettings/no-read-binding/subprocess/pass", test_no_read_binding_pass);
3127       g_test_add_func ("/gsettings/no-write-binding", test_no_write_binding);
3128       g_test_add_func ("/gsettings/no-write-binding/subprocess/fail", test_no_write_binding_fail);
3129       g_test_add_func ("/gsettings/no-write-binding/subprocess/pass", test_no_write_binding_pass);
3130     }
3131
3132   g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown);
3133   g_test_add ("/gsettings/keyfile/explicit-path", Fixture, &keyfile_test_data_explicit_path, setup, test_keyfile_no_path, teardown);
3134   g_test_add ("/gsettings/keyfile/empty-path", Fixture, &keyfile_test_data_empty_path, setup, test_keyfile_no_path, teardown);
3135   g_test_add ("/gsettings/keyfile/long-path", Fixture, &keyfile_test_data_long_path, setup, test_keyfile_no_path, teardown);
3136   g_test_add ("/gsettings/keyfile/outside-root-path", Fixture, NULL, setup, test_keyfile_outside_root_path, teardown);
3137   g_test_add ("/gsettings/keyfile/no-root-group", Fixture, NULL, setup, test_keyfile_no_root_group, teardown);
3138   g_test_add_func ("/gsettings/child-schema", test_child_schema);
3139   g_test_add_func ("/gsettings/strinfo", test_strinfo);
3140   g_test_add_func ("/gsettings/enums", test_enums);
3141   g_test_add_func ("/gsettings/enums/subprocess/non-enum-key", test_enums_non_enum_key);
3142   g_test_add_func ("/gsettings/enums/subprocess/non-enum-value", test_enums_non_enum_value);
3143   g_test_add_func ("/gsettings/enums/subprocess/range", test_enums_range);
3144   g_test_add_func ("/gsettings/enums/subprocess/non-flags", test_enums_non_flags);
3145   g_test_add_func ("/gsettings/flags", test_flags);
3146   g_test_add_func ("/gsettings/flags/subprocess/non-flags-key", test_flags_non_flags_key);
3147   g_test_add_func ("/gsettings/flags/subprocess/non-flags-value", test_flags_non_flags_value);
3148   g_test_add_func ("/gsettings/flags/subprocess/range", test_flags_range);
3149   g_test_add_func ("/gsettings/flags/subprocess/non-enum", test_flags_non_enum);
3150   g_test_add_func ("/gsettings/range", test_range);
3151   g_test_add_func ("/gsettings/range/subprocess/high", test_range_high);
3152   g_test_add_func ("/gsettings/range/subprocess/low", test_range_low);
3153   g_test_add_func ("/gsettings/list-items", test_list_items);
3154   g_test_add_func ("/gsettings/list-schemas", test_list_schemas);
3155   g_test_add_func ("/gsettings/mapped", test_get_mapped);
3156   g_test_add_func ("/gsettings/get-range", test_get_range);
3157   g_test_add_func ("/gsettings/schema-source", test_schema_source);
3158   g_test_add_func ("/gsettings/schema-list-keys", test_schema_list_keys);
3159   g_test_add_func ("/gsettings/actions", test_actions);
3160   g_test_add_func ("/gsettings/null-backend", test_null_backend);
3161   g_test_add_func ("/gsettings/memory-backend", test_memory_backend);
3162   g_test_add_func ("/gsettings/read-descriptions", test_read_descriptions);
3163   g_test_add_func ("/gsettings/test-extended-schema", test_extended_schema);
3164   g_test_add_func ("/gsettings/default-value", test_default_value);
3165   g_test_add_func ("/gsettings/per-desktop", test_per_desktop);
3166   g_test_add_func ("/gsettings/per-desktop/subprocess", test_per_desktop_subprocess);
3167
3168   result = g_test_run ();
3169
3170   g_settings_sync ();
3171
3172   /* FIXME: Due to the way #GSettings objects can be used without specifying a
3173    * backend, the default backend is leaked. In order to be able to run this
3174    * test under valgrind and get meaningful checking for real leaks, use this
3175    * hack to drop the final reference to the default #GSettingsBackend.
3176    *
3177    * This should not be used in production code. */
3178     {
3179       GSettingsBackend *backend;
3180
3181       backend = g_settings_backend_get_default ();
3182       g_object_unref (backend);  /* reference from the *_get_default() call */
3183       g_assert_finalize_object (backend);  /* singleton reference owned by GLib */
3184     }
3185
3186   return result;
3187 }