Bug 624991 - GSettings mapping for G_TYPE_STRV
[platform/upstream/glib.git] / gio / tests / gsettings.c
1 #include <stdlib.h>
2 #include <locale.h>
3 #include <libintl.h>
4 #include <gio/gio.h>
5 #include <gstdio.h>
6 #define G_SETTINGS_ENABLE_BACKEND
7 #include <gio/gsettingsbackend.h>
8
9 #include "testenum.h"
10
11 static gboolean backend_set;
12
13 /* These tests rely on the schemas in org.gtk.test.gschema.xml
14  * to be compiled and installed in the same directory.
15  */
16
17 /* Just to get warmed up: Read and set a string, and
18  * verify that can read the changed string back
19  */
20 static void
21 test_basic (void)
22 {
23   gchar *str = NULL;
24   GSettings *settings;
25
26   settings = g_settings_new ("org.gtk.test");
27
28   g_object_get (settings, "schema", &str, NULL);
29   g_assert_cmpstr (str, ==, "org.gtk.test");
30
31   g_settings_get (settings, "greeting", "s", &str);
32   g_assert_cmpstr (str, ==, "Hello, earthlings");
33   g_free (str);
34
35   g_settings_set (settings, "greeting", "s", "goodbye world");
36   g_settings_get (settings, "greeting", "s", &str);
37   g_assert_cmpstr (str, ==, "goodbye world");
38   g_free (str);
39   str = NULL;
40
41   if (!backend_set)
42     {
43       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
44         {
45           settings = g_settings_new ("org.gtk.test");
46           g_settings_set (settings, "greeting", "i", 555);
47           abort ();
48         }
49       g_test_trap_assert_failed ();
50       g_test_trap_assert_stderr ("*g_settings_type_check*");
51     }
52
53   g_settings_get (settings, "greeting", "s", &str);
54   g_assert_cmpstr (str, ==, "goodbye world");
55   g_free (str);
56   str = NULL;
57
58   g_settings_set (settings, "greeting", "s", "this is the end");
59   g_object_unref (settings);
60 }
61
62 /* Check that we get an error when getting a key
63  * that is not in the schema
64  */
65 static void
66 test_unknown_key (void)
67 {
68   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
69     {
70       GSettings *settings;
71       GVariant *value;
72
73       settings = g_settings_new ("org.gtk.test");
74       value = g_settings_get_value (settings, "no_such_key");
75
76       g_assert (value == NULL);
77
78       g_object_unref (settings);
79     }
80   g_test_trap_assert_failed ();
81   g_test_trap_assert_stderr ("*does not contain*");
82 }
83
84 /* Check that we get an error when the schema
85  * has not been installed
86  */
87 void
88 test_no_schema (void)
89 {
90   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
91     {
92       GSettings *settings;
93
94       settings = g_settings_new ("no.such.schema");
95
96       g_assert (settings == NULL);
97     }
98
99   g_test_trap_assert_failed ();
100   g_test_trap_assert_stderr ("*Settings schema 'no.such.schema' is not installed*");
101 }
102
103 /* Check that we get an error when passing a type string
104  * that does not match the schema
105  */
106 static void
107 test_wrong_type (void)
108 {
109   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
110     {
111       GSettings *settings;
112       gchar *str = NULL;
113
114       settings = g_settings_new ("org.gtk.test");
115
116       g_settings_get (settings, "greeting", "o", &str);
117
118       g_assert (str == NULL);
119     }
120   g_test_trap_assert_failed ();
121   g_test_trap_assert_stderr ("*CRITICAL*");
122
123   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
124     {
125       GSettings *settings;
126
127       settings = g_settings_new ("org.gtk.test");
128
129       g_settings_set (settings, "greeting", "o", "/a/path");
130     }
131   g_test_trap_assert_failed ();
132   g_test_trap_assert_stderr ("*CRITICAL*");
133 }
134
135 /* Check errors with explicit paths */
136 static void
137 test_wrong_path (void)
138 {
139   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
140     {
141       GSettings *settings;
142
143       settings = g_settings_new_with_path ("org.gtk.test", "/wrong-path/");
144     }
145
146   g_test_trap_assert_failed ();
147   g_test_trap_assert_stderr ("*but path * specified by schema*");
148 }
149
150 static void
151 test_no_path (void)
152 {
153   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
154     {
155       GSettings *settings;
156
157       settings = g_settings_new ("org.gtk.test.no-path");
158     }
159
160   g_test_trap_assert_failed ();
161   g_test_trap_assert_stderr ("*attempting to create schema * without a path**");
162 }
163
164
165 /* Check that we can successfully read and set the full
166  * range of all basic types
167  */
168 static void
169 test_basic_types (void)
170 {
171   GSettings *settings;
172   gboolean b;
173   guint8 byte;
174   gint16 i16;
175   guint16 u16;
176   gint32 i32;
177   guint32 u32;
178   gint64 i64;
179   guint64 u64;
180   gdouble d;
181   gchar *str;
182
183   settings = g_settings_new ("org.gtk.test.basic-types");
184
185   g_settings_get (settings, "test-boolean", "b", &b);
186   g_assert_cmpint (b, ==, 1);
187
188   g_settings_set (settings, "test-boolean", "b", 0);
189   g_settings_get (settings, "test-boolean", "b", &b);
190   g_assert_cmpint (b, ==, 0);
191
192   g_settings_get (settings, "test-byte", "y", &byte);
193   g_assert_cmpint (byte, ==, 25);
194
195   g_settings_set (settings, "test-byte", "y", G_MAXUINT8);
196   g_settings_get (settings, "test-byte", "y", &byte);
197   g_assert_cmpint (byte, ==, G_MAXUINT8);
198
199   g_settings_get (settings, "test-int16", "n", &i16);
200   g_assert_cmpint (i16, ==, -1234);
201
202   g_settings_set (settings, "test-int16", "n", G_MININT16);
203   g_settings_get (settings, "test-int16", "n", &i16);
204   g_assert_cmpint (i16, ==, G_MININT16);
205
206   g_settings_set (settings, "test-int16", "n", G_MAXINT16);
207   g_settings_get (settings, "test-int16", "n", &i16);
208   g_assert_cmpint (i16, ==, G_MAXINT16);
209
210   g_settings_get (settings, "test-uint16", "q", &u16);
211   g_assert_cmpuint (u16, ==, 1234);
212
213   g_settings_set (settings, "test-uint16", "q", G_MAXUINT16);
214   g_settings_get (settings, "test-uint16", "q", &u16);
215   g_assert_cmpuint (u16, ==, G_MAXUINT16);
216
217   g_settings_get (settings, "test-int32", "i", &i32);
218   g_assert_cmpint (i32, ==, -123456);
219
220   g_settings_set (settings, "test-int32", "i", G_MININT32);
221   g_settings_get (settings, "test-int32", "i", &i32);
222   g_assert_cmpint (i32, ==, G_MININT32);
223
224   g_settings_set (settings, "test-int32", "i", G_MAXINT32);
225   g_settings_get (settings, "test-int32", "i", &i32);
226   g_assert_cmpint (i32, ==, G_MAXINT32);
227
228   g_settings_get (settings, "test-uint32", "u", &u32);
229   g_assert_cmpuint (u32, ==, 123456);
230
231   g_settings_set (settings, "test-uint32", "u", G_MAXUINT32);
232   g_settings_get (settings, "test-uint32", "u", &u32);
233   g_assert_cmpuint (u32, ==, G_MAXUINT32);
234
235   g_settings_get (settings, "test-int64", "x", &i64);
236   g_assert_cmpuint (i64, ==, -123456789);
237
238   g_settings_set (settings, "test-int64", "x", G_MININT64);
239   g_settings_get (settings, "test-int64", "x", &i64);
240   g_assert_cmpuint (i64, ==, G_MININT64);
241
242   g_settings_set (settings, "test-int64", "x", G_MAXINT64);
243   g_settings_get (settings, "test-int64", "x", &i64);
244   g_assert_cmpuint (i64, ==, G_MAXINT64);
245
246   g_settings_get (settings, "test-uint64", "t", &u64);
247   g_assert_cmpuint (u64, ==, 123456789);
248
249   g_settings_set (settings, "test-uint64", "t", G_MAXUINT64);
250   g_settings_get (settings, "test-uint64", "t", &u64);
251   g_assert_cmpuint (u64, ==, G_MAXUINT64);
252
253   g_settings_get (settings, "test-double", "d", &d);
254   g_assert_cmpfloat (d, ==, 123.456);
255
256   g_settings_set (settings, "test-double", "d", G_MINDOUBLE);
257   g_settings_get (settings, "test-double", "d", &d);
258   g_assert_cmpfloat (d, ==, G_MINDOUBLE);
259
260   g_settings_set (settings, "test-double", "d", G_MAXDOUBLE);
261   g_settings_get (settings, "test-double", "d", &d);
262   g_assert_cmpfloat (d, ==, G_MAXDOUBLE);
263
264   g_settings_get (settings, "test-string", "s", &str);
265   g_assert_cmpstr (str, ==, "a string, it seems");
266   g_free (str);
267   str = NULL;
268
269   g_settings_get (settings, "test-objectpath", "o", &str);
270   g_assert_cmpstr (str, ==, "/a/object/path");
271   g_object_unref (settings);
272   g_free (str);
273   str = NULL;
274 }
275
276 /* Check that we can read an set complex types like
277  * tuples, arrays and dictionaries
278  */
279 static void
280 test_complex_types (void)
281 {
282   GSettings *settings;
283   gchar *s;
284   gint i1, i2;
285   GVariantIter *iter = NULL;
286
287   settings = g_settings_new ("org.gtk.test.complex-types");
288
289   g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
290   g_assert_cmpstr (s, ==, "one");
291   g_assert_cmpint (i1,==, 2);
292   g_assert_cmpint (i2,==, 3);
293   g_free (s) ;
294   s = NULL;
295
296   g_settings_set (settings, "test-tuple", "(s(ii))", "none", 0, 0);
297   g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
298   g_assert_cmpstr (s, ==, "none");
299   g_assert_cmpint (i1,==, 0);
300   g_assert_cmpint (i2,==, 0);
301   g_free (s);
302   s = NULL;
303
304   g_settings_get (settings, "test-array", "ai", &iter);
305   g_assert_cmpint (g_variant_iter_n_children (iter), ==, 6);
306   g_assert (g_variant_iter_next (iter, "i", &i1));
307   g_assert_cmpint (i1, ==, 0);
308   g_assert (g_variant_iter_next (iter, "i", &i1));
309   g_assert_cmpint (i1, ==, 1);
310   g_assert (g_variant_iter_next (iter, "i", &i1));
311   g_assert_cmpint (i1, ==, 2);
312   g_assert (g_variant_iter_next (iter, "i", &i1));
313   g_assert_cmpint (i1, ==, 3);
314   g_assert (g_variant_iter_next (iter, "i", &i1));
315   g_assert_cmpint (i1, ==, 4);
316   g_assert (g_variant_iter_next (iter, "i", &i1));
317   g_assert_cmpint (i1, ==, 5);
318   g_assert (!g_variant_iter_next (iter, "i", &i1));
319   g_variant_iter_free (iter);
320
321   g_object_unref (settings);
322 }
323
324 static gboolean changed_cb_called;
325
326 static void
327 changed_cb (GSettings   *settings,
328             const gchar *key,
329             gpointer     data)
330 {
331   changed_cb_called = TRUE;
332
333   g_assert_cmpstr (key, ==, data);
334 }
335
336 /* Test that basic change notification with the changed signal works.
337  */
338 void
339 test_changes (void)
340 {
341   GSettings *settings;
342   GSettings *settings2;
343
344   settings = g_settings_new ("org.gtk.test");
345
346   g_signal_connect (settings, "changed",
347                     G_CALLBACK (changed_cb), "greeting");
348
349   changed_cb_called = FALSE;
350
351   g_settings_set (settings, "greeting", "s", "new greeting");
352   g_assert (changed_cb_called);
353
354   settings2 = g_settings_new ("org.gtk.test");
355
356   changed_cb_called = FALSE;
357
358   g_settings_set (settings2, "greeting", "s", "hi");
359   g_assert (changed_cb_called);
360
361   g_object_unref (settings2);
362   g_object_unref (settings);
363 }
364
365 static gboolean changed_cb_called2;
366
367 static void
368 changed_cb2 (GSettings   *settings,
369              const gchar *key,
370              gpointer     data)
371 {
372   gboolean *p = data;
373
374   *p = TRUE;
375 }
376
377 /* Test that changes done to a delay-mode instance
378  * don't appear to the outside world until apply. Also
379  * check that we get change notification when they are
380  * applied.
381  * Also test that the has-unapplied property is properly
382  * maintained.
383  */
384 void
385 test_delay_apply (void)
386 {
387   GSettings *settings;
388   GSettings *settings2;
389   gchar *str;
390
391   settings = g_settings_new ("org.gtk.test");
392   settings2 = g_settings_new ("org.gtk.test");
393
394   g_settings_set (settings2, "greeting", "s", "top o' the morning");
395
396   changed_cb_called = FALSE;
397   changed_cb_called2 = FALSE;
398
399   g_signal_connect (settings, "changed",
400                     G_CALLBACK (changed_cb2), &changed_cb_called);
401   g_signal_connect (settings2, "changed",
402                     G_CALLBACK (changed_cb2), &changed_cb_called2);
403
404   g_settings_delay (settings);
405
406   g_settings_set (settings, "greeting", "s", "greetings from test_delay_apply");
407
408   g_assert (changed_cb_called);
409   g_assert (!changed_cb_called2);
410
411   g_settings_get (settings, "greeting", "s", &str);
412   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
413   g_free (str);
414   str = NULL;
415
416   g_settings_get (settings2, "greeting", "s", &str);
417   g_assert_cmpstr (str, ==, "top o' the morning");
418   g_free (str);
419   str = NULL;
420
421   g_assert (g_settings_get_has_unapplied (settings));
422   g_assert (!g_settings_get_has_unapplied (settings2));
423
424   changed_cb_called = FALSE;
425   changed_cb_called2 = FALSE;
426
427   g_settings_apply (settings);
428
429   g_assert (!changed_cb_called);
430   g_assert (changed_cb_called2);
431
432   g_settings_get (settings, "greeting", "s", &str);
433   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
434   g_free (str);
435   str = NULL;
436
437   g_settings_get (settings2, "greeting", "s", &str);
438   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
439   g_free (str);
440   str = NULL;
441
442   g_assert (!g_settings_get_has_unapplied (settings));
443   g_assert (!g_settings_get_has_unapplied (settings2));
444
445   g_object_unref (settings2);
446   g_object_unref (settings);
447 }
448
449 /* Test that reverting unapplied changes in a delay-apply
450  * settings instance works.
451  */
452 static void
453 test_delay_revert (void)
454 {
455   GSettings *settings;
456   GSettings *settings2;
457   gchar *str;
458
459   settings = g_settings_new ("org.gtk.test");
460   settings2 = g_settings_new ("org.gtk.test");
461
462   g_settings_set (settings2, "greeting", "s", "top o' the morning");
463
464   g_settings_delay (settings);
465
466   g_settings_set (settings, "greeting", "s", "greetings from test_delay_revert");
467
468   g_settings_get (settings, "greeting", "s", &str);
469   g_assert_cmpstr (str, ==, "greetings from test_delay_revert");
470   g_free (str);
471   str = NULL;
472
473   g_settings_get (settings2, "greeting", "s", &str);
474   g_assert_cmpstr (str, ==, "top o' the morning");
475   g_free (str);
476   str = NULL;
477
478   g_assert (g_settings_get_has_unapplied (settings));
479
480   g_settings_revert (settings);
481
482   g_assert (!g_settings_get_has_unapplied (settings));
483
484   g_settings_get (settings, "greeting", "s", &str);
485   g_assert_cmpstr (str, ==, "top o' the morning");
486   g_free (str);
487   str = NULL;
488
489   g_settings_get (settings2, "greeting", "s", &str);
490   g_assert_cmpstr (str, ==, "top o' the morning");
491   g_free (str);
492   str = NULL;
493
494   g_object_unref (settings2);
495   g_object_unref (settings);
496 }
497
498 static void
499 keys_changed_cb (GSettings    *settings,
500                  const GQuark *keys,
501                  gint          n_keys)
502 {
503   gchar *str;
504
505   g_assert_cmpint (n_keys, ==, 2);
506
507   g_assert ((keys[0] == g_quark_from_static_string ("greeting") &&
508              keys[1] == g_quark_from_static_string ("farewell")) ||
509             (keys[1] == g_quark_from_static_string ("greeting") &&
510              keys[0] == g_quark_from_static_string ("farewell")));
511
512   g_settings_get (settings, "greeting", "s", &str);
513   g_assert_cmpstr (str, ==, "greetings from test_atomic");
514   g_free (str);
515   str = NULL;
516
517   g_settings_get (settings, "farewell", "s", &str);
518   g_assert_cmpstr (str, ==, "atomic bye-bye");
519   g_free (str);
520   str = NULL;
521 }
522
523 /* Check that delay-applied changes appear atomically.
524  * More specifically, verify that all changed keys appear
525  * with their new value while handling the change-event signal.
526  */
527 static void
528 test_atomic (void)
529 {
530   GSettings *settings;
531   GSettings *settings2;
532   gchar *str;
533
534   settings = g_settings_new ("org.gtk.test");
535   settings2 = g_settings_new ("org.gtk.test");
536
537   g_settings_set (settings2, "greeting", "s", "top o' the morning");
538
539   changed_cb_called = FALSE;
540   changed_cb_called2 = FALSE;
541
542   g_signal_connect (settings2, "change-event",
543                     G_CALLBACK (keys_changed_cb), NULL);
544
545   g_settings_delay (settings);
546
547   g_settings_set (settings, "greeting", "s", "greetings from test_atomic");
548   g_settings_set (settings, "farewell", "s", "atomic bye-bye");
549
550   g_settings_apply (settings);
551
552   g_settings_get (settings, "greeting", "s", &str);
553   g_assert_cmpstr (str, ==, "greetings from test_atomic");
554   g_free (str);
555   str = NULL;
556
557   g_settings_get (settings, "farewell", "s", &str);
558   g_assert_cmpstr (str, ==, "atomic bye-bye");
559   g_free (str);
560   str = NULL;
561
562   g_settings_get (settings2, "greeting", "s", &str);
563   g_assert_cmpstr (str, ==, "greetings from test_atomic");
564   g_free (str);
565   str = NULL;
566
567   g_settings_get (settings2, "farewell", "s", &str);
568   g_assert_cmpstr (str, ==, "atomic bye-bye");
569   g_free (str);
570   str = NULL;
571
572   g_object_unref (settings2);
573   g_object_unref (settings);
574 }
575
576 /* On Windows the interaction between the C library locale and libintl
577  * (from GNU gettext) is not like on POSIX, so just skip these tests
578  * for now.
579  *
580  * There are several issues:
581  *
582  * 1) The C library doesn't use LC_MESSAGES, that is implemented only
583  * in libintl (defined in its <libintl.h>).
584  *
585  * 2) The locale names that setlocale() accepts and returns aren't in
586  * the "de_DE" style, but like "German_Germany".
587  *
588  * 3) libintl looks at the Win32 thread locale and not the C library
589  * locale. (And even if libintl would use the C library's locale, as
590  * there are several alternative C library DLLs, libintl might be
591  * linked to a different one than the application code, so they
592  * wouldn't have the same C library locale anyway.)
593  */
594
595 /* Test that translations work for schema defaults.
596  *
597  * This test relies on the de.po file in the same directory
598  * to be compiled into ./de/LC_MESSAGES/test.mo
599  */
600 static void
601 test_l10n (void)
602 {
603   GSettings *settings;
604   gchar *str;
605   gchar *locale;
606
607   bindtextdomain ("test", ".");
608   bind_textdomain_codeset ("test", "UTF-8");
609
610   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
611
612   settings = g_settings_new ("org.gtk.test.localized");
613
614   setlocale (LC_MESSAGES, "C");
615   str = g_settings_get_string (settings, "error-message");
616   setlocale (LC_MESSAGES, locale);
617
618   g_assert_cmpstr (str, ==, "Unnamed");
619   g_free (str);
620   str = NULL;
621
622   setlocale (LC_MESSAGES, "de_DE");
623   str = g_settings_get_string (settings, "error-message");
624   setlocale (LC_MESSAGES, locale);
625
626   g_assert_cmpstr (str, ==, "Unbenannt");
627   g_object_unref (settings);
628   g_free (str);
629   str = NULL;
630
631   g_free (locale);
632 }
633
634 /* Test that message context works as expected with translated
635  * schema defaults. Also, verify that non-ASCII UTF-8 content
636  * works.
637  *
638  * This test relies on the de.po file in the same directory
639  * to be compiled into ./de/LC_MESSAGES/test.mo
640  */
641 static void
642 test_l10n_context (void)
643 {
644   GSettings *settings;
645   gchar *str;
646   gchar *locale;
647
648   bindtextdomain ("test", ".");
649   bind_textdomain_codeset ("test", "UTF-8");
650
651   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
652
653   settings = g_settings_new ("org.gtk.test.localized");
654
655   setlocale (LC_MESSAGES, "C");
656   g_settings_get (settings, "backspace", "s", &str);
657   setlocale (LC_MESSAGES, locale);
658
659   g_assert_cmpstr (str, ==, "BackSpace");
660   g_free (str);
661   str = NULL;
662
663   setlocale (LC_MESSAGES, "de_DE");
664   g_settings_get (settings, "backspace", "s", &str);
665   setlocale (LC_MESSAGES, locale);
666
667   g_assert_cmpstr (str, ==, "Löschen");
668   g_object_unref (settings);
669   g_free (str);
670   str = NULL;
671
672   g_free (locale);
673 }
674
675 enum
676 {
677   PROP_0,
678   PROP_BOOL,
679   PROP_BYTE,
680   PROP_INT16,
681   PROP_UINT16,
682   PROP_INT,
683   PROP_UINT,
684   PROP_INT64,
685   PROP_UINT64,
686   PROP_DOUBLE,
687   PROP_STRING,
688   PROP_NO_READ,
689   PROP_NO_WRITE,
690   PROP_STRV,
691   PROP_ENUM
692 };
693
694 typedef struct
695 {
696   GObject parent_instance;
697
698   gboolean bool_prop;
699   gchar byte_prop;
700   gint int16_prop;
701   guint16 uint16_prop;
702   gint int_prop;
703   guint uint_prop;
704   gint64 int64_prop;
705   guint64 uint64_prop;
706   gdouble double_prop;
707   gchar *string_prop;
708   gchar *no_read_prop;
709   gchar *no_write_prop;
710   gchar **strv_prop;
711   guint enum_prop;
712 } TestObject;
713
714 typedef struct
715 {
716   GObjectClass parent_class;
717 } TestObjectClass;
718
719 G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
720
721 static void
722 test_object_init (TestObject *object)
723 {
724 }
725
726 static void
727 test_object_finalize (GObject *object)
728 {
729   TestObject *testo = (TestObject*)object;
730   g_strfreev (testo->strv_prop);
731   g_free (testo->string_prop);
732   G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
733 }
734
735 static void
736 test_object_get_property (GObject    *object,
737                           guint       prop_id,
738                           GValue     *value,
739                           GParamSpec *pspec)
740 {
741   TestObject *test_object = (TestObject *)object;
742
743   switch (prop_id)
744     {
745     case PROP_BOOL:
746       g_value_set_boolean (value, test_object->bool_prop);
747       break;
748     case PROP_BYTE:
749       g_value_set_char (value, test_object->byte_prop);
750       break;
751     case PROP_UINT16:
752       g_value_set_uint (value, test_object->uint16_prop);
753       break;
754     case PROP_INT16:
755       g_value_set_int (value, test_object->int16_prop);
756       break;
757     case PROP_INT:
758       g_value_set_int (value, test_object->int_prop);
759       break;
760     case PROP_UINT:
761       g_value_set_uint (value, test_object->uint_prop);
762       break;
763     case PROP_INT64:
764       g_value_set_int64 (value, test_object->int64_prop);
765       break;
766     case PROP_UINT64:
767       g_value_set_uint64 (value, test_object->uint64_prop);
768       break;
769     case PROP_DOUBLE:
770       g_value_set_double (value, test_object->double_prop);
771       break;
772     case PROP_STRING:
773       g_value_set_string (value, test_object->string_prop);
774       break;
775     case PROP_NO_WRITE:
776       g_value_set_string (value, test_object->no_write_prop);
777       break;
778     case PROP_STRV:
779       g_value_set_boxed (value, test_object->strv_prop);
780       break;
781     case PROP_ENUM:
782       g_value_set_enum (value, test_object->enum_prop);
783       break;
784     default:
785       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
786       break;
787     }
788 }
789
790 static void
791 test_object_set_property (GObject      *object,
792                           guint         prop_id,
793                           const GValue *value,
794                           GParamSpec   *pspec)
795 {
796   TestObject *test_object = (TestObject *)object;
797
798   switch (prop_id)
799     {
800     case PROP_BOOL:
801       test_object->bool_prop = g_value_get_boolean (value);
802       break;
803     case PROP_BYTE:
804       test_object->byte_prop = g_value_get_char (value);
805       break;
806     case PROP_INT16:
807       test_object->int16_prop = g_value_get_int (value);
808       break;
809     case PROP_UINT16:
810       test_object->uint16_prop = g_value_get_uint (value);
811       break;
812     case PROP_INT:
813       test_object->int_prop = g_value_get_int (value);
814       break;
815     case PROP_UINT:
816       test_object->uint_prop = g_value_get_uint (value);
817       break;
818     case PROP_INT64:
819       test_object->int64_prop = g_value_get_int64 (value);
820       break;
821     case PROP_UINT64:
822       test_object->uint64_prop = g_value_get_uint64 (value);
823       break;
824     case PROP_DOUBLE:
825       test_object->double_prop = g_value_get_double (value);
826       break;
827     case PROP_STRING:
828       g_free (test_object->string_prop);
829       test_object->string_prop = g_value_dup_string (value);
830       break;
831     case PROP_NO_READ:
832       g_free (test_object->no_read_prop);
833       test_object->no_read_prop = g_value_dup_string (value);
834       break;
835     case PROP_STRV:
836       g_strfreev (test_object->strv_prop);
837       test_object->strv_prop = g_value_dup_boxed (value);
838       break;
839     case PROP_ENUM:
840       test_object->enum_prop = g_value_get_enum (value);
841       break;
842     default:
843       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
844       break;
845     }
846 }
847
848 static GType
849 test_enum_get_type (void)
850 {
851   static volatile gsize define_type_id = 0;
852
853   if (g_once_init_enter (&define_type_id))
854     {
855       static const GEnumValue values[] = {
856         { TEST_ENUM_FOO, "TEST_ENUM_FOO", "foo" },
857         { TEST_ENUM_BAR, "TEST_ENUM_BAR", "bar" },
858         { TEST_ENUM_BAZ, "TEST_ENUM_BAZ", "baz" },
859         { TEST_ENUM_QUUX, "TEST_ENUM_QUUX", "quux" },
860         { 0, NULL, NULL }
861       };
862
863       GType type_id = g_enum_register_static ("TestEnum", values);
864       g_once_init_leave (&define_type_id, type_id);
865     }
866
867   return define_type_id;
868 }
869
870 static void
871 test_object_class_init (TestObjectClass *class)
872 {
873   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
874
875   gobject_class->get_property = test_object_get_property;
876   gobject_class->set_property = test_object_set_property;
877   gobject_class->finalize = test_object_finalize;
878
879   g_object_class_install_property (gobject_class, PROP_BOOL,
880     g_param_spec_boolean ("bool", "", "", FALSE, G_PARAM_READWRITE));
881   g_object_class_install_property (gobject_class, PROP_BYTE,
882     g_param_spec_char ("byte", "", "", G_MININT8, G_MAXINT8, 0, G_PARAM_READWRITE));
883   g_object_class_install_property (gobject_class, PROP_INT16,
884     g_param_spec_int ("int16", "", "", -G_MAXINT16, G_MAXINT16, 0, G_PARAM_READWRITE));
885   g_object_class_install_property (gobject_class, PROP_UINT16,
886     g_param_spec_uint ("uint16", "", "", 0, G_MAXUINT16, 0, G_PARAM_READWRITE));
887   g_object_class_install_property (gobject_class, PROP_INT,
888     g_param_spec_int ("int", "", "", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
889   g_object_class_install_property (gobject_class, PROP_UINT,
890     g_param_spec_uint ("uint", "", "", 0, G_MAXUINT, 0, G_PARAM_READWRITE));
891   g_object_class_install_property (gobject_class, PROP_INT64,
892     g_param_spec_int64 ("int64", "", "", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE));
893   g_object_class_install_property (gobject_class, PROP_UINT64,
894     g_param_spec_uint64 ("uint64", "", "", 0, G_MAXUINT64, 0, G_PARAM_READWRITE));
895   g_object_class_install_property (gobject_class, PROP_DOUBLE,
896     g_param_spec_double ("double", "", "", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE));
897   g_object_class_install_property (gobject_class, PROP_STRING,
898     g_param_spec_string ("string", "", "", NULL, G_PARAM_READWRITE));
899   g_object_class_install_property (gobject_class, PROP_NO_WRITE,
900     g_param_spec_string ("no-write", "", "", NULL, G_PARAM_READABLE));
901   g_object_class_install_property (gobject_class, PROP_NO_READ,
902     g_param_spec_string ("no-read", "", "", NULL, G_PARAM_WRITABLE));
903   g_object_class_install_property (gobject_class, PROP_STRV,
904     g_param_spec_boxed ("strv", "", "", G_TYPE_STRV, G_PARAM_READWRITE));
905   g_object_class_install_property (gobject_class, PROP_ENUM,
906     g_param_spec_enum ("enum", "", "", test_enum_get_type (), TEST_ENUM_FOO, G_PARAM_READWRITE));
907 }
908
909 static TestObject *
910 test_object_new (void)
911 {
912   return (TestObject*)g_object_new (test_object_get_type (), NULL);
913 }
914
915 /* Test basic binding functionality for simple types.
916  * Verify that with bidirectional bindings, changes on either side
917  * are notified on the other end.
918  */
919 static void
920 test_simple_binding (void)
921 {
922   TestObject *obj;
923   GSettings *settings;
924   gboolean b;
925   gchar y;
926   gint i;
927   gint16 n;
928   guint16 q;
929   gint64 i64;
930   guint64 u64;
931   gdouble d;
932   gchar *s;
933   GVariant *value;
934   gchar **strv;
935
936   settings = g_settings_new ("org.gtk.test.binding");
937   obj = test_object_new ();
938
939   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_DEFAULT);
940
941   g_object_set (obj, "bool", TRUE, NULL);
942   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
943
944   g_settings_set_boolean (settings, "bool", FALSE);
945   b = TRUE;
946   g_object_get (obj, "bool", &b, NULL);
947   g_assert_cmpint (b, ==, FALSE);
948
949   g_settings_bind (settings, "byte", obj, "byte", G_SETTINGS_BIND_DEFAULT);
950
951   g_object_set (obj, "byte", 123, NULL);
952   y = 'c';
953   g_settings_get (settings, "byte", "y", &y);
954   g_assert_cmpint (y, ==, 123);
955
956   g_settings_set (settings, "byte", "y", 54);
957   y = 'c';
958   g_object_get (obj, "byte", &y, NULL);
959   g_assert_cmpint (y, ==, 54);
960
961   g_settings_bind (settings, "int16", obj, "int16", G_SETTINGS_BIND_DEFAULT);
962
963   g_object_set (obj, "int16", 1234, NULL);
964   n = 4321;
965   g_settings_get (settings, "int16", "n", &n);
966   g_assert_cmpint (n, ==, 1234);
967
968   g_settings_set (settings, "int16", "n", 4321);
969   n = 1111;
970   g_object_get (obj, "int16", &n, NULL);
971   g_assert_cmpint (n, ==, 4321);
972
973   g_settings_bind (settings, "uint16", obj, "uint16", G_SETTINGS_BIND_DEFAULT);
974
975   g_object_set (obj, "uint16", (guint16) G_MAXUINT16, NULL);
976   q = 1111;
977   g_settings_get (settings, "uint16", "q", &q);
978   g_assert_cmpuint (q, ==, G_MAXUINT16);
979
980   g_settings_set (settings, "uint16", "q", (guint16) G_MAXINT16);
981   q = 1111;
982   g_object_get (obj, "uint16", &q, NULL);
983   g_assert_cmpuint (q, ==, (guint16) G_MAXINT16);
984
985   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
986
987   g_object_set (obj, "int", 12345, NULL);
988   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
989
990   g_settings_set_int (settings, "int", 54321);
991   i = 1111;
992   g_object_get (obj, "int", &i, NULL);
993   g_assert_cmpint (i, ==, 54321);
994
995   g_settings_bind (settings, "int64", obj, "int64", G_SETTINGS_BIND_DEFAULT);
996
997   g_object_set (obj, "int64", (gint64) G_MAXINT64, NULL);
998   i64 = 1111;
999   g_settings_get (settings, "int64", "x", &i64);
1000   g_assert_cmpint (i64, ==, G_MAXINT64);
1001
1002   g_settings_set (settings, "int64", "x", (gint64) G_MININT64);
1003   i64 = 1111;
1004   g_object_get (obj, "int64", &i64, NULL);
1005   g_assert_cmpint (i64, ==, G_MININT64);
1006
1007   g_settings_bind (settings, "uint64", obj, "uint64", G_SETTINGS_BIND_DEFAULT);
1008
1009   g_object_set (obj, "uint64", (guint64) G_MAXUINT64, NULL);
1010   u64 = 1111;
1011   g_settings_get (settings, "uint64", "t", &u64);
1012   g_assert_cmpuint (u64, ==, G_MAXUINT64);
1013
1014   g_settings_set (settings, "uint64", "t", (guint64) G_MAXINT64);
1015   u64 = 1111;
1016   g_object_get (obj, "uint64", &u64, NULL);
1017   g_assert_cmpuint (u64, ==, (guint64) G_MAXINT64);
1018
1019   g_settings_bind (settings, "string", obj, "string", G_SETTINGS_BIND_DEFAULT);
1020
1021   g_object_set (obj, "string", "bu ba", NULL);
1022   s = g_settings_get_string (settings, "string");
1023   g_assert_cmpstr (s, ==, "bu ba");
1024   g_free (s);
1025
1026   g_settings_set_string (settings, "string", "bla bla");
1027   g_object_get (obj, "string", &s, NULL);
1028   g_assert_cmpstr (s, ==, "bla bla");
1029   g_free (s);
1030
1031   g_settings_bind (settings, "chararray", obj, "string", G_SETTINGS_BIND_DEFAULT);
1032
1033   g_object_set (obj, "string", "non-unicode:\315", NULL);
1034   value = g_settings_get_value (settings, "chararray");
1035   g_assert_cmpstr (g_variant_get_bytestring (value), ==, "non-unicode:\315");
1036   g_variant_unref (value);
1037
1038   g_settings_bind (settings, "double", obj, "double", G_SETTINGS_BIND_DEFAULT);
1039
1040   g_object_set (obj, "double", G_MAXFLOAT, NULL);
1041   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXFLOAT);
1042
1043   g_settings_set_double (settings, "double", G_MINFLOAT);
1044   d = 1.0;
1045   g_object_get (obj, "double", &d, NULL);
1046   g_assert_cmpfloat (d, ==, G_MINFLOAT);
1047
1048   g_object_set (obj, "double", G_MAXDOUBLE, NULL);
1049   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXDOUBLE);
1050
1051   g_settings_set_double (settings, "double", -G_MINDOUBLE);
1052   d = 1.0;
1053   g_object_get (obj, "double", &d, NULL);
1054   g_assert_cmpfloat (d, ==, -G_MINDOUBLE);
1055
1056   strv = g_strsplit ("plastic bag,middle class,polyethylene", ",", 0);
1057   g_settings_bind (settings, "strv", obj, "strv", G_SETTINGS_BIND_DEFAULT);
1058   g_object_set (obj, "strv", strv, NULL);
1059   g_strfreev (strv);
1060   strv = g_settings_get_strv (settings, "strv");
1061   s = g_strjoinv (",", strv);
1062   g_assert_cmpstr (s, ==, "plastic bag,middle class,polyethylene");
1063   g_strfreev (strv);
1064   g_free (s);
1065   strv = g_strsplit ("decaffeinate,unleaded,keep all surfaces clean", ",", 0);
1066   g_settings_set_strv (settings, "strv", (const gchar **) strv);
1067   g_strfreev (strv);
1068   g_object_get (obj, "strv", &strv, NULL);
1069   s = g_strjoinv (",", strv);
1070   g_assert_cmpstr (s, ==, "decaffeinate,unleaded,keep all surfaces clean");
1071   g_strfreev (strv);
1072   g_free (s);
1073
1074   g_settings_bind (settings, "enum", obj, "enum", G_SETTINGS_BIND_DEFAULT);
1075   g_object_set (obj, "enum", TEST_ENUM_BAZ, NULL);
1076   g_assert_cmpstr (g_settings_get_string (settings, "enum"), ==, "baz");
1077   g_assert_cmpint (g_settings_get_enum (settings, "enum"), ==, TEST_ENUM_BAZ);
1078
1079   g_settings_set_enum (settings, "enum", TEST_ENUM_QUUX);
1080   i = 230;
1081   g_object_get (obj, "enum", &i, NULL);
1082   g_assert_cmpint (i, ==, TEST_ENUM_QUUX);
1083
1084   g_settings_set_string (settings, "enum", "baz");
1085   i = 230;
1086   g_object_get (obj, "enum", &i, NULL);
1087   g_assert_cmpint (i, ==, TEST_ENUM_BAZ);
1088
1089   g_object_unref (obj);
1090   g_object_unref (settings);
1091 }
1092
1093 static void
1094 test_unbind (void)
1095 {
1096   TestObject *obj;
1097   GSettings *settings;
1098
1099   settings = g_settings_new ("org.gtk.test.binding");
1100   obj = test_object_new ();
1101
1102   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
1103
1104   g_object_set (obj, "int", 12345, NULL);
1105   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1106
1107   g_settings_unbind (obj, "int");
1108
1109   g_object_set (obj, "int", 54321, NULL);
1110   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1111
1112   g_object_unref (obj);
1113   g_object_unref (settings);
1114 }
1115
1116 static void
1117 test_bind_writable (void)
1118 {
1119   TestObject *obj;
1120   GSettings *settings;
1121   gboolean b;
1122
1123   settings = g_settings_new ("org.gtk.test.binding");
1124   obj = test_object_new ();
1125
1126   g_object_set (obj, "bool", FALSE, NULL);
1127
1128   g_settings_bind_writable (settings, "int", obj, "bool", FALSE);
1129
1130   g_object_get (obj, "bool", &b, NULL);
1131   g_assert (b);
1132
1133   g_settings_unbind (obj, "bool");
1134
1135   g_settings_bind_writable (settings, "int", obj, "bool", TRUE);
1136
1137   g_object_get (obj, "bool", &b, NULL);
1138   g_assert (!b);
1139
1140   g_object_unref (obj);
1141   g_object_unref (settings);
1142 }
1143
1144 /* Test one-way bindings.
1145  * Verify that changes on one side show up on the other,
1146  * but not vice versa
1147  */
1148 static void
1149 test_directional_binding (void)
1150 {
1151   TestObject *obj;
1152   GSettings *settings;
1153   gboolean b;
1154   gint i;
1155
1156   settings = g_settings_new ("org.gtk.test.binding");
1157   obj = test_object_new ();
1158
1159   g_object_set (obj, "bool", FALSE, NULL);
1160   g_settings_set_boolean (settings, "bool", FALSE);
1161
1162   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET);
1163
1164   g_settings_set_boolean (settings, "bool", TRUE);
1165   g_object_get (obj, "bool", &b, NULL);
1166   g_assert_cmpint (b, ==, TRUE);
1167
1168   g_object_set (obj, "bool", FALSE, NULL);
1169   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
1170
1171   g_object_set (obj, "int", 20, NULL);
1172   g_settings_set_int (settings, "int", 20);
1173
1174   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_SET);
1175
1176   g_object_set (obj, "int", 32, NULL);
1177   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 32);
1178
1179   g_settings_set_int (settings, "int", 20);
1180   g_object_get (obj, "int", &i, NULL);
1181   g_assert_cmpint (i, ==, 32);
1182
1183   g_object_unref (obj);
1184   g_object_unref (settings);
1185 }
1186
1187 /* Test that type mismatch is caught when creating a binding
1188  */
1189 static void
1190 test_typesafe_binding (void)
1191 {
1192   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1193     {
1194       TestObject *obj;
1195       GSettings *settings;
1196
1197       settings = g_settings_new ("org.gtk.test.binding");
1198       obj = test_object_new ();
1199
1200       g_settings_bind (settings, "string", obj, "int", G_SETTINGS_BIND_DEFAULT);
1201
1202       g_object_unref (obj);
1203       g_object_unref (settings);
1204     }
1205   g_test_trap_assert_failed ();
1206   g_test_trap_assert_stderr ("*not compatible*");
1207 }
1208
1209 static gboolean
1210 string_to_bool (GValue   *value,
1211                 GVariant *variant,
1212                 gpointer  user_data)
1213 {
1214   const gchar *s;
1215
1216   s = g_variant_get_string (variant, NULL);
1217   g_value_set_boolean (value, g_strcmp0 (s, "true") == 0);
1218
1219   return TRUE;
1220 }
1221
1222 static GVariant *
1223 bool_to_string (const GValue       *value,
1224                 const GVariantType *expected_type,
1225                 gpointer            user_data)
1226 {
1227   if (g_value_get_boolean (value))
1228     return g_variant_new_string ("true");
1229   else
1230     return g_variant_new_string ("false");
1231 }
1232
1233 /* Test custom bindings.
1234  * Translate strings to booleans and back
1235  */
1236 static void
1237 test_custom_binding (void)
1238 {
1239   TestObject *obj;
1240   GSettings *settings;
1241   gchar *s;
1242   gboolean b;
1243
1244   settings = g_settings_new ("org.gtk.test.binding");
1245   obj = test_object_new ();
1246
1247   g_settings_set_string (settings, "string", "true");
1248
1249   g_settings_bind_with_mapping (settings, "string",
1250                                 obj, "bool",
1251                                 G_SETTINGS_BIND_DEFAULT,
1252                                 string_to_bool,
1253                                 bool_to_string,
1254                                 NULL, NULL);
1255
1256   g_settings_set_string (settings, "string", "false");
1257   g_object_get (obj, "bool", &b, NULL);
1258   g_assert_cmpint (b, ==, FALSE);
1259
1260   g_settings_set_string (settings, "string", "not true");
1261   g_object_get (obj, "bool", &b, NULL);
1262   g_assert_cmpint (b, ==, FALSE);
1263
1264   g_object_set (obj, "bool", TRUE, NULL);
1265   s = g_settings_get_string (settings, "string");
1266   g_assert_cmpstr (s, ==, "true");
1267   g_free (s);
1268
1269   g_object_unref (obj);
1270   g_object_unref (settings);
1271 }
1272
1273 /* Test that with G_SETTINGS_BIND_NO_CHANGES, the
1274  * initial settings value is transported to the object
1275  * side, but later settings changes do not affect the
1276  * object
1277  */
1278 static void
1279 test_no_change_binding (void)
1280 {
1281   TestObject *obj;
1282   GSettings *settings;
1283   gboolean b;
1284
1285   settings = g_settings_new ("org.gtk.test.binding");
1286   obj = test_object_new ();
1287
1288   g_object_set (obj, "bool", TRUE, NULL);
1289   g_settings_set_boolean (settings, "bool", FALSE);
1290
1291   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET_NO_CHANGES);
1292
1293   g_object_get (obj, "bool", &b, NULL);
1294   g_assert_cmpint (b, ==, FALSE);
1295
1296   g_settings_set_boolean (settings, "bool", TRUE);
1297   g_object_get (obj, "bool", &b, NULL);
1298   g_assert_cmpint (b, ==, FALSE);
1299
1300   g_settings_set_boolean (settings, "bool", FALSE);
1301   g_object_set (obj, "bool", TRUE, NULL);
1302   b = g_settings_get_boolean (settings, "bool");
1303   g_assert_cmpint (b, ==, TRUE);
1304
1305   g_object_unref (obj);
1306   g_object_unref (settings);
1307 }
1308
1309 /* Test that binding a non-readable property only
1310  * works in 'GET' mode.
1311  */
1312 static void
1313 test_no_read_binding (void)
1314 {
1315   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1316     {
1317       TestObject *obj;
1318       GSettings *settings;
1319
1320       settings = g_settings_new ("org.gtk.test.binding");
1321       obj = test_object_new ();
1322
1323       g_settings_bind (settings, "string", obj, "no-read", 0);
1324     }
1325   g_test_trap_assert_failed ();
1326   g_test_trap_assert_stderr ("*property*is not readable*");
1327
1328   if (g_test_trap_fork (0, 0))
1329     {
1330       TestObject *obj;
1331       GSettings *settings;
1332
1333       settings = g_settings_new ("org.gtk.test.binding");
1334       obj = test_object_new ();
1335
1336       g_settings_bind (settings, "string", obj, "no-read", G_SETTINGS_BIND_GET);
1337
1338       exit (0);
1339     }
1340   g_test_trap_assert_passed ();
1341 }
1342
1343 /* Test that binding a non-writable property only
1344  * works in 'SET' mode.
1345  */
1346 static void
1347 test_no_write_binding (void)
1348 {
1349   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1350     {
1351       TestObject *obj;
1352       GSettings *settings;
1353
1354       settings = g_settings_new ("org.gtk.test.binding");
1355       obj = test_object_new ();
1356
1357       g_settings_bind (settings, "string", obj, "no-write", 0);
1358     }
1359   g_test_trap_assert_failed ();
1360   g_test_trap_assert_stderr ("*property*is not writable*");
1361
1362   if (g_test_trap_fork (0, 0))
1363     {
1364       TestObject *obj;
1365       GSettings *settings;
1366
1367       settings = g_settings_new ("org.gtk.test.binding");
1368       obj = test_object_new ();
1369
1370       g_settings_bind (settings, "string", obj, "no-write", G_SETTINGS_BIND_SET);
1371
1372       exit (0);
1373     }
1374   g_test_trap_assert_passed ();
1375 }
1376
1377 /*
1378  * Test that using a keyfile works
1379  */
1380 static void
1381 test_keyfile (void)
1382 {
1383   GSettingsBackend *kf_backend;
1384   GSettings *settings;
1385   GKeyFile *keyfile;
1386   gchar *str;
1387
1388   g_remove ("gsettings.store");
1389
1390   kf_backend = g_keyfile_settings_backend_new ("gsettings.store", "/", "root");
1391   settings = g_settings_new_with_backend ("org.gtk.test", kf_backend);
1392   g_object_unref (kf_backend);
1393
1394   g_settings_set (settings, "greeting", "s", "see if this works");
1395
1396   keyfile = g_key_file_new ();
1397   g_assert (g_key_file_load_from_file (keyfile, "gsettings.store", 0, NULL));
1398
1399   str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
1400   g_assert_cmpstr (str, ==, "'see if this works'");
1401
1402   g_free (str);
1403   g_key_file_free (keyfile);
1404   g_object_unref (settings);
1405 }
1406
1407 /* Test that getting child schemas works
1408  */
1409 static void
1410 test_child_schema (void)
1411 {
1412   GSettings *settings;
1413   GSettings *child;
1414   guint8 byte;
1415
1416   /* first establish some known conditions */
1417   settings = g_settings_new ("org.gtk.test.basic-types");
1418   g_settings_set (settings, "test-byte", "y", 36);
1419
1420   g_settings_get (settings, "test-byte", "y", &byte);
1421   g_assert_cmpint (byte, ==, 36);
1422
1423   g_object_unref (settings);
1424
1425   settings = g_settings_new ("org.gtk.test");
1426   child = g_settings_get_child (settings, "basic-types");
1427   g_assert (child != NULL);
1428
1429   g_settings_get (child, "test-byte", "y", &byte);
1430   g_assert_cmpint (byte, ==, 36);
1431
1432   g_object_unref (child);
1433   g_object_unref (settings);
1434 }
1435
1436 static gboolean
1437 glib_translations_work (void)
1438 {
1439   gchar *locale;
1440   gchar *orig = "Unnamed";
1441   gchar *str;
1442
1443   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
1444   setlocale (LC_MESSAGES, "de");
1445   str = dgettext ("glib20", orig);
1446   setlocale (LC_MESSAGES, locale);
1447   g_free (locale);
1448
1449   return str != orig;
1450 }
1451
1452 #include "../strinfo.c"
1453
1454 static void
1455 test_strinfo (void)
1456 {
1457   /*  "foo" has a value of 1
1458    *  "bar" has a value of 2
1459    *  "baz" is an alias for "bar"
1460    */
1461   gchar array[] =
1462     "\1\0\0\0"      "\xff""foo"     "\0\0\0\xff"    "\2\0\0\0"
1463     "\xff" "bar"    "\0\0\0\xff"    "\3\0\0\0"      "\xfe""baz"
1464     "\0\0\0\xff";
1465   const guint32 *strinfo = (guint32 *) array;
1466   guint length = sizeof array / 4;
1467   guint result;
1468
1469   {
1470     /* build it and compare */
1471     GString *builder;
1472
1473     builder = g_string_new (NULL);
1474     strinfo_builder_append_item (builder, "foo", 1);
1475     strinfo_builder_append_item (builder, "bar", 2);
1476     g_assert (strinfo_builder_append_alias (builder, "baz", "bar"));
1477     g_assert_cmpint (builder->len % 4, ==, 0);
1478     g_assert_cmpint (builder->len / 4, ==, length);
1479     g_assert (memcmp (builder->str, strinfo, length * 4) == 0);
1480     g_string_free (builder, TRUE);
1481   }
1482
1483   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "foo"),
1484                    ==, NULL);
1485   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "bar"),
1486                    ==, NULL);
1487   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "baz"),
1488                    ==, "bar");
1489   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "quux"),
1490                    ==, NULL);
1491
1492   g_assert (strinfo_enum_from_string (strinfo, length, "foo", &result));
1493   g_assert_cmpint (result, ==, 1);
1494   g_assert (strinfo_enum_from_string (strinfo, length, "bar", &result));
1495   g_assert_cmpint (result, ==, 2);
1496   g_assert (!strinfo_enum_from_string (strinfo, length, "baz", &result));
1497   g_assert (!strinfo_enum_from_string (strinfo, length, "quux", &result));
1498
1499   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 0), ==, NULL);
1500   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 1), ==, "foo");
1501   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 2), ==, "bar");
1502   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 3), ==, NULL);
1503
1504   g_assert (strinfo_is_string_valid (strinfo, length, "foo"));
1505   g_assert (strinfo_is_string_valid (strinfo, length, "bar"));
1506   g_assert (!strinfo_is_string_valid (strinfo, length, "baz"));
1507   g_assert (!strinfo_is_string_valid (strinfo, length, "quux"));
1508 }
1509
1510 static void
1511 test_enums (void)
1512 {
1513   GSettings *settings, *direct;
1514   gchar *str;
1515
1516   settings = g_settings_new ("org.gtk.test.enums");
1517   direct = g_settings_new ("org.gtk.test.enums.direct");
1518
1519   if (!backend_set)
1520     {
1521       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1522         g_settings_get_enum (direct, "test");
1523       g_test_trap_assert_failed ();
1524       g_test_trap_assert_stderr ("*not associated with an enum*");
1525
1526       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1527         g_settings_set_enum (settings, "test", 42);
1528       g_test_trap_assert_failed ();
1529       g_test_trap_assert_stderr ("*invalid enum value 42*");
1530
1531       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1532         g_settings_set_string (settings, "test", "qux");
1533       g_test_trap_assert_failed ();
1534       g_test_trap_assert_stderr ("*g_settings_range_check*");
1535
1536       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1537         g_settings_get_flags (settings, "test");
1538       g_test_trap_assert_failed ();
1539       g_test_trap_assert_stderr ("*not associated with a flags*");
1540     }
1541
1542   str = g_settings_get_string (settings, "test");
1543   g_assert_cmpstr (str, ==, "bar");
1544   g_free (str);
1545
1546   g_settings_set_enum (settings, "test", TEST_ENUM_FOO);
1547
1548   str = g_settings_get_string (settings, "test");
1549   g_assert_cmpstr (str, ==, "foo");
1550   g_free (str);
1551
1552   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_FOO);
1553
1554   g_settings_set_string (direct, "test", "qux");
1555
1556   str = g_settings_get_string (direct, "test");
1557   g_assert_cmpstr (str, ==, "qux");
1558   g_free (str);
1559
1560   str = g_settings_get_string (settings, "test");
1561   g_assert_cmpstr (str, ==, "quux");
1562   g_free (str);
1563
1564   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_QUUX);
1565 }
1566
1567 static void
1568 test_flags (void)
1569 {
1570   GSettings *settings, *direct;
1571   gchar **strv;
1572   gchar *str;
1573
1574   settings = g_settings_new ("org.gtk.test.enums");
1575   direct = g_settings_new ("org.gtk.test.enums.direct");
1576
1577   if (!backend_set)
1578     {
1579       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1580         g_settings_get_flags (direct, "test");
1581       g_test_trap_assert_failed ();
1582       g_test_trap_assert_stderr ("*not associated with a flags*");
1583
1584       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1585         g_settings_set_flags (settings, "f-test", 0x42);
1586       g_test_trap_assert_failed ();
1587       g_test_trap_assert_stderr ("*invalid flags value 0x00000042*");
1588
1589       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1590         g_settings_set_strv (settings, "f-test",
1591                              (const gchar **) g_strsplit ("rock", ",", 0));
1592       g_test_trap_assert_failed ();
1593       g_test_trap_assert_stderr ("*g_settings_range_check*");
1594
1595       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1596         g_settings_get_enum (settings, "f-test");
1597       g_test_trap_assert_failed ();
1598       g_test_trap_assert_stderr ("*not associated with an enum*");
1599     }
1600
1601   strv = g_settings_get_strv (settings, "f-test");
1602   str = g_strjoinv (",", strv);
1603   g_assert_cmpstr (str, ==, "");
1604   g_strfreev (strv);
1605   g_free (str);
1606
1607   g_settings_set_flags (settings, "f-test",
1608                         TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
1609
1610   strv = g_settings_get_strv (settings, "f-test");
1611   str = g_strjoinv (",", strv);
1612   g_assert_cmpstr (str, ==, "talking,walking");
1613   g_strfreev (strv);
1614   g_free (str);
1615
1616   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
1617                    TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
1618
1619   strv = g_strsplit ("speaking,laughing", ",", 0);
1620   g_settings_set_strv (direct, "f-test", (const gchar **) strv);
1621   g_strfreev (strv);
1622
1623   strv = g_settings_get_strv (direct, "f-test");
1624   str = g_strjoinv (",", strv);
1625   g_assert_cmpstr (str, ==, "speaking,laughing");
1626   g_strfreev (strv);
1627   g_free (str);
1628
1629   strv = g_settings_get_strv (settings, "f-test");
1630   str = g_strjoinv (",", strv);
1631   g_assert_cmpstr (str, ==, "talking,laughing");
1632   g_strfreev (strv);
1633   g_free (str);
1634
1635   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
1636                    TEST_FLAGS_TALKING | TEST_FLAGS_LAUGHING);
1637 }
1638
1639 static void
1640 test_range (void)
1641 {
1642   GSettings *settings, *direct;
1643
1644   settings = g_settings_new ("org.gtk.test.range");
1645   direct = g_settings_new ("org.gtk.test.range.direct");
1646
1647   if (!backend_set)
1648     {
1649       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1650         g_settings_set_int (settings, "val", 45);
1651       g_test_trap_assert_failed ();
1652       g_test_trap_assert_stderr ("*g_settings_range_check*");
1653
1654       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1655         g_settings_set_int (settings, "val", 1);
1656       g_test_trap_assert_failed ();
1657       g_test_trap_assert_stderr ("*g_settings_range_check*");
1658     }
1659
1660   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
1661   g_settings_set_int (direct, "val", 22);
1662   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 22);
1663   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 22);
1664   g_settings_set_int (direct, "val", 45);
1665   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 45);
1666   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
1667   g_settings_set_int (direct, "val", 1);
1668   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 1);
1669   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
1670 }
1671
1672 static gboolean
1673 strv_has_string (const gchar **haystack,
1674                  const gchar  *needle)
1675 {
1676   guint n;
1677
1678   for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
1679     {
1680       if (g_strcmp0 (haystack[n], needle) == 0)
1681         return TRUE;
1682     }
1683   return FALSE;
1684 }
1685
1686 static gboolean
1687 strv_set_equal (const gchar **strv, ...)
1688 {
1689   gint count;
1690   va_list list;
1691   const gchar *str;
1692   gboolean res;
1693
1694   res = TRUE;
1695   count = 0;
1696   va_start (list, strv);
1697   while (1)
1698     {
1699       str = va_arg (list, const gchar *);
1700       if (str == NULL)
1701         break;
1702       if (!strv_has_string (strv, str))
1703         {
1704           res = FALSE;
1705           break;
1706         }
1707       count++;
1708     }
1709   va_end (list);
1710
1711   if (res)
1712     res = g_strv_length ((gchar**)strv) == count;
1713
1714   return res;
1715 }
1716
1717 static void
1718 test_list_items (void)
1719 {
1720   GSettings *settings;
1721   const gchar **items;
1722
1723   settings = g_settings_new ("org.gtk.test");
1724   items = g_settings_list_items (settings);
1725
1726   g_assert (strv_set_equal (items, "greeting", "farewell", "basic-types/", "complex-types/", "localized/", NULL));
1727
1728   g_free (items);
1729
1730   g_object_unref (settings);
1731 }
1732
1733 static gboolean
1734 map_func (GVariant *value,
1735           gpointer *result,
1736           gpointer  user_data)
1737 {
1738   gint *state = user_data;
1739   gint v;
1740
1741   if (value)
1742     v = g_variant_get_int32 (value);
1743   else
1744     v = -1;
1745
1746   if (*state == 0)
1747     {
1748       g_assert_cmpint (v, ==, 1);
1749       (*state)++;
1750       return FALSE;
1751     }
1752   else if (*state == 1)
1753     {
1754       g_assert_cmpint (v, ==, 0);
1755       (*state)++;
1756       return FALSE;
1757     }
1758   else
1759     {
1760       g_assert (value == NULL);
1761       *result = g_variant_new_int32 (5);
1762       return TRUE;
1763     }
1764 }
1765
1766 static void
1767 test_get_mapped (void)
1768 {
1769   GSettings *settings;
1770   gint state;
1771   gpointer p;
1772   gint val;
1773
1774   settings = g_settings_new ("org.gtk.test.mapped");
1775   g_settings_set_int (settings, "val", 1);
1776
1777   state = 0;
1778   p = g_settings_get_mapped (settings, "val", map_func, &state);
1779   val = g_variant_get_int32 ((GVariant*)p);
1780   g_assert_cmpint (val, ==, 5);
1781
1782   g_variant_unref (p);
1783   g_object_unref (settings);
1784 }
1785
1786 int
1787 main (int argc, char *argv[])
1788 {
1789   gchar *enums;
1790   gint result;
1791
1792   setlocale (LC_ALL, "");
1793
1794   backend_set = g_getenv ("GSETTINGS_BACKEND") != NULL;
1795
1796   g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
1797
1798   if (!backend_set)
1799     g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
1800
1801   g_type_init ();
1802   g_test_init (&argc, &argv, NULL);
1803
1804   g_remove ("org.gtk.test.enums.xml");
1805   g_assert (g_spawn_command_line_sync ("../../gobject/glib-mkenums "
1806                                        "--template " SRCDIR "/enums.xml.template "
1807                                        SRCDIR "/testenum.h",
1808                                        &enums, NULL, &result, NULL));
1809   g_assert (result == 0);
1810   g_assert (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
1811   g_free (enums);
1812
1813   g_remove ("gschemas.compiled");
1814   g_assert (g_spawn_command_line_sync ("../glib-compile-schemas --targetdir=. "
1815                                        "--schema-file=org.gtk.test.enums.xml "
1816                                        "--schema-file=" SRCDIR "/org.gtk.test.gschema.xml",
1817                                        NULL, NULL, &result, NULL));
1818   g_assert (result == 0);
1819
1820   g_test_add_func ("/gsettings/basic", test_basic);
1821
1822   if (!backend_set)
1823     {
1824       g_test_add_func ("/gsettings/no-schema", test_no_schema);
1825       g_test_add_func ("/gsettings/unknown-key", test_unknown_key);
1826       g_test_add_func ("/gsettings/wrong-type", test_wrong_type);
1827       g_test_add_func ("/gsettings/wrong-path", test_wrong_path);
1828       g_test_add_func ("/gsettings/no-path", test_no_path);
1829     }
1830
1831   g_test_add_func ("/gsettings/basic-types", test_basic_types);
1832   g_test_add_func ("/gsettings/complex-types", test_complex_types);
1833   g_test_add_func ("/gsettings/changes", test_changes);
1834
1835   if (glib_translations_work ())
1836     {
1837       g_test_add_func ("/gsettings/l10n", test_l10n);
1838       g_test_add_func ("/gsettings/l10n-context", test_l10n_context);
1839     }
1840
1841   g_test_add_func ("/gsettings/delay-apply", test_delay_apply);
1842   g_test_add_func ("/gsettings/delay-revert", test_delay_revert);
1843   g_test_add_func ("/gsettings/atomic", test_atomic);
1844
1845   g_test_add_func ("/gsettings/simple-binding", test_simple_binding);
1846   g_test_add_func ("/gsettings/directional-binding", test_directional_binding);
1847   g_test_add_func ("/gsettings/custom-binding", test_custom_binding);
1848   g_test_add_func ("/gsettings/no-change-binding", test_no_change_binding);
1849   g_test_add_func ("/gsettings/unbinding", test_unbind);
1850   g_test_add_func ("/gsettings/writable-binding", test_bind_writable);
1851
1852   if (!backend_set)
1853     {
1854       g_test_add_func ("/gsettings/typesafe-binding", test_typesafe_binding);
1855       g_test_add_func ("/gsettings/no-read-binding", test_no_read_binding);
1856       g_test_add_func ("/gsettings/no-write-binding", test_no_write_binding);
1857     }
1858
1859   g_test_add_func ("/gsettings/keyfile", test_keyfile);
1860   g_test_add_func ("/gsettings/child-schema", test_child_schema);
1861   g_test_add_func ("/gsettings/strinfo", test_strinfo);
1862   g_test_add_func ("/gsettings/enums", test_enums);
1863   g_test_add_func ("/gsettings/flags", test_flags);
1864   g_test_add_func ("/gsettings/range", test_range);
1865   g_test_add_func ("/gsettings/list-items", test_list_items);
1866   g_test_add_func ("/gsettings/mapped", test_get_mapped);
1867
1868   result = g_test_run ();
1869
1870   g_settings_sync ();
1871
1872   return result;
1873 }