Use proper variables
[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_ENUM
691 };
692
693 typedef struct
694 {
695   GObject parent_instance;
696
697   gboolean bool_prop;
698   gchar byte_prop;
699   gint int16_prop;
700   guint16 uint16_prop;
701   gint int_prop;
702   guint uint_prop;
703   gint64 int64_prop;
704   guint64 uint64_prop;
705   gdouble double_prop;
706   gchar *string_prop;
707   gchar *no_read_prop;
708   gchar *no_write_prop;
709   guint enum_prop;
710 } TestObject;
711
712 typedef struct
713 {
714   GObjectClass parent_class;
715 } TestObjectClass;
716
717 G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
718
719 static void
720 test_object_init (TestObject *object)
721 {
722 }
723
724 static void
725 test_object_finalize (GObject *object)
726 {
727   TestObject *testo = (TestObject*)object;
728   g_free (testo->string_prop);
729   G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
730 }
731
732 static void
733 test_object_get_property (GObject    *object,
734                           guint       prop_id,
735                           GValue     *value,
736                           GParamSpec *pspec)
737 {
738   TestObject *test_object = (TestObject *)object;
739
740   switch (prop_id)
741     {
742     case PROP_BOOL:
743       g_value_set_boolean (value, test_object->bool_prop);
744       break;
745     case PROP_BYTE:
746       g_value_set_char (value, test_object->byte_prop);
747       break;
748     case PROP_UINT16:
749       g_value_set_uint (value, test_object->uint16_prop);
750       break;
751     case PROP_INT16:
752       g_value_set_int (value, test_object->int16_prop);
753       break;
754     case PROP_INT:
755       g_value_set_int (value, test_object->int_prop);
756       break;
757     case PROP_UINT:
758       g_value_set_uint (value, test_object->uint_prop);
759       break;
760     case PROP_INT64:
761       g_value_set_int64 (value, test_object->int64_prop);
762       break;
763     case PROP_UINT64:
764       g_value_set_uint64 (value, test_object->uint64_prop);
765       break;
766     case PROP_DOUBLE:
767       g_value_set_double (value, test_object->double_prop);
768       break;
769     case PROP_STRING:
770       g_value_set_string (value, test_object->string_prop);
771       break;
772     case PROP_NO_WRITE:
773       g_value_set_string (value, test_object->no_write_prop);
774       break;
775     case PROP_ENUM:
776       g_value_set_enum (value, test_object->enum_prop);
777       break;
778     default:
779       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
780       break;
781     }
782 }
783
784 static void
785 test_object_set_property (GObject      *object,
786                           guint         prop_id,
787                           const GValue *value,
788                           GParamSpec   *pspec)
789 {
790   TestObject *test_object = (TestObject *)object;
791
792   switch (prop_id)
793     {
794     case PROP_BOOL:
795       test_object->bool_prop = g_value_get_boolean (value);
796       break;
797     case PROP_BYTE:
798       test_object->byte_prop = g_value_get_char (value);
799       break;
800     case PROP_INT16:
801       test_object->int16_prop = g_value_get_int (value);
802       break;
803     case PROP_UINT16:
804       test_object->uint16_prop = g_value_get_uint (value);
805       break;
806     case PROP_INT:
807       test_object->int_prop = g_value_get_int (value);
808       break;
809     case PROP_UINT:
810       test_object->uint_prop = g_value_get_uint (value);
811       break;
812     case PROP_INT64:
813       test_object->int64_prop = g_value_get_int64 (value);
814       break;
815     case PROP_UINT64:
816       test_object->uint64_prop = g_value_get_uint64 (value);
817       break;
818     case PROP_DOUBLE:
819       test_object->double_prop = g_value_get_double (value);
820       break;
821     case PROP_STRING:
822       g_free (test_object->string_prop);
823       test_object->string_prop = g_value_dup_string (value);
824       break;
825     case PROP_NO_READ:
826       g_free (test_object->no_read_prop);
827       test_object->no_read_prop = g_value_dup_string (value);
828       break;
829     case PROP_ENUM:
830       test_object->enum_prop = g_value_get_enum (value);
831       break;
832     default:
833       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
834       break;
835     }
836 }
837
838 static GType
839 test_enum_get_type (void)
840 {
841   static volatile gsize define_type_id = 0;
842
843   if (g_once_init_enter (&define_type_id))
844     {
845       static const GEnumValue values[] = {
846         { TEST_ENUM_FOO, "TEST_ENUM_FOO", "foo" },
847         { TEST_ENUM_BAR, "TEST_ENUM_BAR", "bar" },
848         { TEST_ENUM_BAZ, "TEST_ENUM_BAZ", "baz" },
849         { TEST_ENUM_QUUX, "TEST_ENUM_QUUX", "quux" },
850         { 0, NULL, NULL }
851       };
852
853       GType type_id = g_enum_register_static ("TestEnum", values);
854       g_once_init_leave (&define_type_id, type_id);
855     }
856
857   return define_type_id;
858 }
859
860 static void
861 test_object_class_init (TestObjectClass *class)
862 {
863   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
864
865   gobject_class->get_property = test_object_get_property;
866   gobject_class->set_property = test_object_set_property;
867   gobject_class->finalize = test_object_finalize;
868
869   g_object_class_install_property (gobject_class, PROP_BOOL,
870     g_param_spec_boolean ("bool", "", "", FALSE, G_PARAM_READWRITE));
871   g_object_class_install_property (gobject_class, PROP_BYTE,
872     g_param_spec_char ("byte", "", "", G_MININT8, G_MAXINT8, 0, G_PARAM_READWRITE));
873   g_object_class_install_property (gobject_class, PROP_INT16,
874     g_param_spec_int ("int16", "", "", -G_MAXINT16, G_MAXINT16, 0, G_PARAM_READWRITE));
875   g_object_class_install_property (gobject_class, PROP_UINT16,
876     g_param_spec_uint ("uint16", "", "", 0, G_MAXUINT16, 0, G_PARAM_READWRITE));
877   g_object_class_install_property (gobject_class, PROP_INT,
878     g_param_spec_int ("int", "", "", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
879   g_object_class_install_property (gobject_class, PROP_UINT,
880     g_param_spec_uint ("uint", "", "", 0, G_MAXUINT, 0, G_PARAM_READWRITE));
881   g_object_class_install_property (gobject_class, PROP_INT64,
882     g_param_spec_int64 ("int64", "", "", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE));
883   g_object_class_install_property (gobject_class, PROP_UINT64,
884     g_param_spec_uint64 ("uint64", "", "", 0, G_MAXUINT64, 0, G_PARAM_READWRITE));
885   g_object_class_install_property (gobject_class, PROP_DOUBLE,
886     g_param_spec_double ("double", "", "", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE));
887   g_object_class_install_property (gobject_class, PROP_STRING,
888     g_param_spec_string ("string", "", "", NULL, G_PARAM_READWRITE));
889   g_object_class_install_property (gobject_class, PROP_NO_WRITE,
890     g_param_spec_string ("no-write", "", "", NULL, G_PARAM_READABLE));
891   g_object_class_install_property (gobject_class, PROP_NO_READ,
892     g_param_spec_string ("no-read", "", "", NULL, G_PARAM_WRITABLE));
893   g_object_class_install_property (gobject_class, PROP_ENUM,
894     g_param_spec_enum ("enum", "", "", test_enum_get_type (), TEST_ENUM_FOO, G_PARAM_READWRITE));
895 }
896
897 static TestObject *
898 test_object_new (void)
899 {
900   return (TestObject*)g_object_new (test_object_get_type (), NULL);
901 }
902
903 /* Test basic binding functionality for simple types.
904  * Verify that with bidirectional bindings, changes on either side
905  * are notified on the other end.
906  */
907 static void
908 test_simple_binding (void)
909 {
910   TestObject *obj;
911   GSettings *settings;
912   gboolean b;
913   gchar y;
914   gint i;
915   gint16 n;
916   guint16 q;
917   gint64 i64;
918   guint64 u64;
919   gdouble d;
920   gchar *s;
921   GVariant *value;
922
923   settings = g_settings_new ("org.gtk.test.binding");
924   obj = test_object_new ();
925
926   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_DEFAULT);
927
928   g_object_set (obj, "bool", TRUE, NULL);
929   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
930
931   g_settings_set_boolean (settings, "bool", FALSE);
932   b = TRUE;
933   g_object_get (obj, "bool", &b, NULL);
934   g_assert_cmpint (b, ==, FALSE);
935
936   g_settings_bind (settings, "byte", obj, "byte", G_SETTINGS_BIND_DEFAULT);
937
938   g_object_set (obj, "byte", 123, NULL);
939   y = 'c';
940   g_settings_get (settings, "byte", "y", &y);
941   g_assert_cmpint (y, ==, 123);
942
943   g_settings_set (settings, "byte", "y", 54);
944   y = 'c';
945   g_object_get (obj, "byte", &y, NULL);
946   g_assert_cmpint (y, ==, 54);
947
948   g_settings_bind (settings, "int16", obj, "int16", G_SETTINGS_BIND_DEFAULT);
949
950   g_object_set (obj, "int16", 1234, NULL);
951   n = 4321;
952   g_settings_get (settings, "int16", "n", &n);
953   g_assert_cmpint (n, ==, 1234);
954
955   g_settings_set (settings, "int16", "n", 4321);
956   n = 1111;
957   g_object_get (obj, "int16", &n, NULL);
958   g_assert_cmpint (n, ==, 4321);
959
960   g_settings_bind (settings, "uint16", obj, "uint16", G_SETTINGS_BIND_DEFAULT);
961
962   g_object_set (obj, "uint16", (guint16) G_MAXUINT16, NULL);
963   q = 1111;
964   g_settings_get (settings, "uint16", "q", &q);
965   g_assert_cmpuint (q, ==, G_MAXUINT16);
966
967   g_settings_set (settings, "uint16", "q", (guint16) G_MAXINT16);
968   q = 1111;
969   g_object_get (obj, "uint16", &q, NULL);
970   g_assert_cmpuint (q, ==, (guint16) G_MAXINT16);
971
972   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
973
974   g_object_set (obj, "int", 12345, NULL);
975   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
976
977   g_settings_set_int (settings, "int", 54321);
978   i = 1111;
979   g_object_get (obj, "int", &i, NULL);
980   g_assert_cmpint (i, ==, 54321);
981
982   g_settings_bind (settings, "int64", obj, "int64", G_SETTINGS_BIND_DEFAULT);
983
984   g_object_set (obj, "int64", (gint64) G_MAXINT64, NULL);
985   i64 = 1111;
986   g_settings_get (settings, "int64", "x", &i64);
987   g_assert_cmpint (i64, ==, G_MAXINT64);
988
989   g_settings_set (settings, "int64", "x", (gint64) G_MININT64);
990   i64 = 1111;
991   g_object_get (obj, "int64", &i64, NULL);
992   g_assert_cmpint (i64, ==, G_MININT64);
993
994   g_settings_bind (settings, "uint64", obj, "uint64", G_SETTINGS_BIND_DEFAULT);
995
996   g_object_set (obj, "uint64", (guint64) G_MAXUINT64, NULL);
997   u64 = 1111;
998   g_settings_get (settings, "uint64", "t", &u64);
999   g_assert_cmpuint (u64, ==, G_MAXUINT64);
1000
1001   g_settings_set (settings, "uint64", "t", (guint64) G_MAXINT64);
1002   u64 = 1111;
1003   g_object_get (obj, "uint64", &u64, NULL);
1004   g_assert_cmpuint (u64, ==, (guint64) G_MAXINT64);
1005
1006   g_settings_bind (settings, "string", obj, "string", G_SETTINGS_BIND_DEFAULT);
1007
1008   g_object_set (obj, "string", "bu ba", NULL);
1009   s = g_settings_get_string (settings, "string");
1010   g_assert_cmpstr (s, ==, "bu ba");
1011   g_free (s);
1012
1013   g_settings_set_string (settings, "string", "bla bla");
1014   g_object_get (obj, "string", &s, NULL);
1015   g_assert_cmpstr (s, ==, "bla bla");
1016   g_free (s);
1017
1018   g_settings_bind (settings, "chararray", obj, "string", G_SETTINGS_BIND_DEFAULT);
1019
1020   g_object_set (obj, "string", "non-unicode:\315", NULL);
1021   value = g_settings_get_value (settings, "chararray");
1022   g_assert_cmpstr (g_variant_get_bytestring (value), ==, "non-unicode:\315");
1023   g_variant_unref (value);
1024
1025   g_settings_bind (settings, "double", obj, "double", G_SETTINGS_BIND_DEFAULT);
1026
1027   g_object_set (obj, "double", G_MAXFLOAT, NULL);
1028   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXFLOAT);
1029
1030   g_settings_set_double (settings, "double", G_MINFLOAT);
1031   d = 1.0;
1032   g_object_get (obj, "double", &d, NULL);
1033   g_assert_cmpfloat (d, ==, G_MINFLOAT);
1034
1035   g_object_set (obj, "double", G_MAXDOUBLE, NULL);
1036   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXDOUBLE);
1037
1038   g_settings_set_double (settings, "double", -G_MINDOUBLE);
1039   d = 1.0;
1040   g_object_get (obj, "double", &d, NULL);
1041   g_assert_cmpfloat (d, ==, -G_MINDOUBLE);
1042
1043   g_settings_bind (settings, "enum", obj, "enum", G_SETTINGS_BIND_DEFAULT);
1044   g_object_set (obj, "enum", TEST_ENUM_BAZ, NULL);
1045   g_assert_cmpstr (g_settings_get_string (settings, "enum"), ==, "baz");
1046   g_assert_cmpint (g_settings_get_enum (settings, "enum"), ==, TEST_ENUM_BAZ);
1047
1048   g_settings_set_enum (settings, "enum", TEST_ENUM_QUUX);
1049   i = 230;
1050   g_object_get (obj, "enum", &i, NULL);
1051   g_assert_cmpint (i, ==, TEST_ENUM_QUUX);
1052
1053   g_settings_set_string (settings, "enum", "baz");
1054   i = 230;
1055   g_object_get (obj, "enum", &i, NULL);
1056   g_assert_cmpint (i, ==, TEST_ENUM_BAZ);
1057
1058   g_object_unref (obj);
1059   g_object_unref (settings);
1060 }
1061
1062 static void
1063 test_unbind (void)
1064 {
1065   TestObject *obj;
1066   GSettings *settings;
1067
1068   settings = g_settings_new ("org.gtk.test.binding");
1069   obj = test_object_new ();
1070
1071   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
1072
1073   g_object_set (obj, "int", 12345, NULL);
1074   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1075
1076   g_settings_unbind (obj, "int");
1077
1078   g_object_set (obj, "int", 54321, NULL);
1079   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1080
1081   g_object_unref (obj);
1082   g_object_unref (settings);
1083 }
1084
1085 static void
1086 test_bind_writable (void)
1087 {
1088   TestObject *obj;
1089   GSettings *settings;
1090   gboolean b;
1091
1092   settings = g_settings_new ("org.gtk.test.binding");
1093   obj = test_object_new ();
1094
1095   g_object_set (obj, "bool", FALSE, NULL);
1096
1097   g_settings_bind_writable (settings, "int", obj, "bool", FALSE);
1098
1099   g_object_get (obj, "bool", &b, NULL);
1100   g_assert (b);
1101
1102   g_settings_unbind (obj, "bool");
1103
1104   g_settings_bind_writable (settings, "int", obj, "bool", TRUE);
1105
1106   g_object_get (obj, "bool", &b, NULL);
1107   g_assert (!b);
1108
1109   g_object_unref (obj);
1110   g_object_unref (settings);
1111 }
1112
1113 /* Test one-way bindings.
1114  * Verify that changes on one side show up on the other,
1115  * but not vice versa
1116  */
1117 static void
1118 test_directional_binding (void)
1119 {
1120   TestObject *obj;
1121   GSettings *settings;
1122   gboolean b;
1123   gint i;
1124
1125   settings = g_settings_new ("org.gtk.test.binding");
1126   obj = test_object_new ();
1127
1128   g_object_set (obj, "bool", FALSE, NULL);
1129   g_settings_set_boolean (settings, "bool", FALSE);
1130
1131   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET);
1132
1133   g_settings_set_boolean (settings, "bool", TRUE);
1134   g_object_get (obj, "bool", &b, NULL);
1135   g_assert_cmpint (b, ==, TRUE);
1136
1137   g_object_set (obj, "bool", FALSE, NULL);
1138   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
1139
1140   g_object_set (obj, "int", 20, NULL);
1141   g_settings_set_int (settings, "int", 20);
1142
1143   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_SET);
1144
1145   g_object_set (obj, "int", 32, NULL);
1146   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 32);
1147
1148   g_settings_set_int (settings, "int", 20);
1149   g_object_get (obj, "int", &i, NULL);
1150   g_assert_cmpint (i, ==, 32);
1151
1152   g_object_unref (obj);
1153   g_object_unref (settings);
1154 }
1155
1156 /* Test that type mismatch is caught when creating a binding
1157  */
1158 static void
1159 test_typesafe_binding (void)
1160 {
1161   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1162     {
1163       TestObject *obj;
1164       GSettings *settings;
1165
1166       settings = g_settings_new ("org.gtk.test.binding");
1167       obj = test_object_new ();
1168
1169       g_settings_bind (settings, "string", obj, "int", G_SETTINGS_BIND_DEFAULT);
1170
1171       g_object_unref (obj);
1172       g_object_unref (settings);
1173     }
1174   g_test_trap_assert_failed ();
1175   g_test_trap_assert_stderr ("*not compatible*");
1176 }
1177
1178 static gboolean
1179 string_to_bool (GValue   *value,
1180                 GVariant *variant,
1181                 gpointer  user_data)
1182 {
1183   const gchar *s;
1184
1185   s = g_variant_get_string (variant, NULL);
1186   g_value_set_boolean (value, g_strcmp0 (s, "true") == 0);
1187
1188   return TRUE;
1189 }
1190
1191 static GVariant *
1192 bool_to_string (const GValue       *value,
1193                 const GVariantType *expected_type,
1194                 gpointer            user_data)
1195 {
1196   if (g_value_get_boolean (value))
1197     return g_variant_new_string ("true");
1198   else
1199     return g_variant_new_string ("false");
1200 }
1201
1202 /* Test custom bindings.
1203  * Translate strings to booleans and back
1204  */
1205 static void
1206 test_custom_binding (void)
1207 {
1208   TestObject *obj;
1209   GSettings *settings;
1210   gchar *s;
1211   gboolean b;
1212
1213   settings = g_settings_new ("org.gtk.test.binding");
1214   obj = test_object_new ();
1215
1216   g_settings_set_string (settings, "string", "true");
1217
1218   g_settings_bind_with_mapping (settings, "string",
1219                                 obj, "bool",
1220                                 G_SETTINGS_BIND_DEFAULT,
1221                                 string_to_bool,
1222                                 bool_to_string,
1223                                 NULL, NULL);
1224
1225   g_settings_set_string (settings, "string", "false");
1226   g_object_get (obj, "bool", &b, NULL);
1227   g_assert_cmpint (b, ==, FALSE);
1228
1229   g_settings_set_string (settings, "string", "not true");
1230   g_object_get (obj, "bool", &b, NULL);
1231   g_assert_cmpint (b, ==, FALSE);
1232
1233   g_object_set (obj, "bool", TRUE, NULL);
1234   s = g_settings_get_string (settings, "string");
1235   g_assert_cmpstr (s, ==, "true");
1236   g_free (s);
1237
1238   g_object_unref (obj);
1239   g_object_unref (settings);
1240 }
1241
1242 /* Test that with G_SETTINGS_BIND_NO_CHANGES, the
1243  * initial settings value is transported to the object
1244  * side, but later settings changes do not affect the
1245  * object
1246  */
1247 static void
1248 test_no_change_binding (void)
1249 {
1250   TestObject *obj;
1251   GSettings *settings;
1252   gboolean b;
1253
1254   settings = g_settings_new ("org.gtk.test.binding");
1255   obj = test_object_new ();
1256
1257   g_object_set (obj, "bool", TRUE, NULL);
1258   g_settings_set_boolean (settings, "bool", FALSE);
1259
1260   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET_NO_CHANGES);
1261
1262   g_object_get (obj, "bool", &b, NULL);
1263   g_assert_cmpint (b, ==, FALSE);
1264
1265   g_settings_set_boolean (settings, "bool", TRUE);
1266   g_object_get (obj, "bool", &b, NULL);
1267   g_assert_cmpint (b, ==, FALSE);
1268
1269   g_settings_set_boolean (settings, "bool", FALSE);
1270   g_object_set (obj, "bool", TRUE, NULL);
1271   b = g_settings_get_boolean (settings, "bool");
1272   g_assert_cmpint (b, ==, TRUE);
1273
1274   g_object_unref (obj);
1275   g_object_unref (settings);
1276 }
1277
1278 /* Test that binding a non-readable property only
1279  * works in 'GET' mode.
1280  */
1281 static void
1282 test_no_read_binding (void)
1283 {
1284   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1285     {
1286       TestObject *obj;
1287       GSettings *settings;
1288
1289       settings = g_settings_new ("org.gtk.test.binding");
1290       obj = test_object_new ();
1291
1292       g_settings_bind (settings, "string", obj, "no-read", 0);
1293     }
1294   g_test_trap_assert_failed ();
1295   g_test_trap_assert_stderr ("*property*is not readable*");
1296
1297   if (g_test_trap_fork (0, 0))
1298     {
1299       TestObject *obj;
1300       GSettings *settings;
1301
1302       settings = g_settings_new ("org.gtk.test.binding");
1303       obj = test_object_new ();
1304
1305       g_settings_bind (settings, "string", obj, "no-read", G_SETTINGS_BIND_GET);
1306
1307       exit (0);
1308     }
1309   g_test_trap_assert_passed ();
1310 }
1311
1312 /* Test that binding a non-writable property only
1313  * works in 'SET' mode.
1314  */
1315 static void
1316 test_no_write_binding (void)
1317 {
1318   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1319     {
1320       TestObject *obj;
1321       GSettings *settings;
1322
1323       settings = g_settings_new ("org.gtk.test.binding");
1324       obj = test_object_new ();
1325
1326       g_settings_bind (settings, "string", obj, "no-write", 0);
1327     }
1328   g_test_trap_assert_failed ();
1329   g_test_trap_assert_stderr ("*property*is not writable*");
1330
1331   if (g_test_trap_fork (0, 0))
1332     {
1333       TestObject *obj;
1334       GSettings *settings;
1335
1336       settings = g_settings_new ("org.gtk.test.binding");
1337       obj = test_object_new ();
1338
1339       g_settings_bind (settings, "string", obj, "no-write", G_SETTINGS_BIND_SET);
1340
1341       exit (0);
1342     }
1343   g_test_trap_assert_passed ();
1344 }
1345
1346 /*
1347  * Test that using a keyfile works
1348  */
1349 static void
1350 test_keyfile (void)
1351 {
1352   GSettingsBackend *kf_backend;
1353   GSettings *settings;
1354   GKeyFile *keyfile;
1355   gchar *str;
1356
1357   g_remove ("gsettings.store");
1358
1359   kf_backend = g_keyfile_settings_backend_new ("gsettings.store", "/", "root");
1360   settings = g_settings_new_with_backend ("org.gtk.test", kf_backend);
1361   g_object_unref (kf_backend);
1362
1363   g_settings_set (settings, "greeting", "s", "see if this works");
1364
1365   keyfile = g_key_file_new ();
1366   g_assert (g_key_file_load_from_file (keyfile, "gsettings.store", 0, NULL));
1367
1368   str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
1369   g_assert_cmpstr (str, ==, "'see if this works'");
1370
1371   g_free (str);
1372   g_key_file_free (keyfile);
1373   g_object_unref (settings);
1374 }
1375
1376 /* Test that getting child schemas works
1377  */
1378 static void
1379 test_child_schema (void)
1380 {
1381   GSettings *settings;
1382   GSettings *child;
1383   guint8 byte;
1384
1385   /* first establish some known conditions */
1386   settings = g_settings_new ("org.gtk.test.basic-types");
1387   g_settings_set (settings, "test-byte", "y", 36);
1388
1389   g_settings_get (settings, "test-byte", "y", &byte);
1390   g_assert_cmpint (byte, ==, 36);
1391
1392   g_object_unref (settings);
1393
1394   settings = g_settings_new ("org.gtk.test");
1395   child = g_settings_get_child (settings, "basic-types");
1396   g_assert (child != NULL);
1397
1398   g_settings_get (child, "test-byte", "y", &byte);
1399   g_assert_cmpint (byte, ==, 36);
1400
1401   g_object_unref (child);
1402   g_object_unref (settings);
1403 }
1404
1405 static gboolean
1406 glib_translations_work (void)
1407 {
1408   gchar *locale;
1409   gchar *orig = "Unnamed";
1410   gchar *str;
1411
1412   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
1413   setlocale (LC_MESSAGES, "de");
1414   str = dgettext ("glib20", orig);
1415   setlocale (LC_MESSAGES, locale);
1416   g_free (locale);
1417
1418   return str != orig;
1419 }
1420
1421 #include "../strinfo.c"
1422
1423 static void
1424 test_strinfo (void)
1425 {
1426   /*  "foo" has a value of 1
1427    *  "bar" has a value of 2
1428    *  "baz" is an alias for "bar"
1429    */
1430   gchar array[] =
1431     "\1\0\0\0"      "\xff""foo"     "\0\0\0\xff"    "\2\0\0\0"
1432     "\xff" "bar"    "\0\0\0\xff"    "\3\0\0\0"      "\xfe""baz"
1433     "\0\0\0\xff";
1434   const guint32 *strinfo = (guint32 *) array;
1435   guint length = sizeof array / 4;
1436   guint result;
1437
1438   {
1439     /* build it and compare */
1440     GString *builder;
1441
1442     builder = g_string_new (NULL);
1443     strinfo_builder_append_item (builder, "foo", 1);
1444     strinfo_builder_append_item (builder, "bar", 2);
1445     g_assert (strinfo_builder_append_alias (builder, "baz", "bar"));
1446     g_assert_cmpint (builder->len % 4, ==, 0);
1447     g_assert_cmpint (builder->len / 4, ==, length);
1448     g_assert (memcmp (builder->str, strinfo, length * 4) == 0);
1449     g_string_free (builder, TRUE);
1450   }
1451
1452   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "foo"),
1453                    ==, NULL);
1454   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "bar"),
1455                    ==, NULL);
1456   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "baz"),
1457                    ==, "bar");
1458   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "quux"),
1459                    ==, NULL);
1460
1461   g_assert (strinfo_enum_from_string (strinfo, length, "foo", &result));
1462   g_assert_cmpint (result, ==, 1);
1463   g_assert (strinfo_enum_from_string (strinfo, length, "bar", &result));
1464   g_assert_cmpint (result, ==, 2);
1465   g_assert (!strinfo_enum_from_string (strinfo, length, "baz", &result));
1466   g_assert (!strinfo_enum_from_string (strinfo, length, "quux", &result));
1467
1468   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 0), ==, NULL);
1469   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 1), ==, "foo");
1470   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 2), ==, "bar");
1471   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 3), ==, NULL);
1472
1473   g_assert (strinfo_is_string_valid (strinfo, length, "foo"));
1474   g_assert (strinfo_is_string_valid (strinfo, length, "bar"));
1475   g_assert (!strinfo_is_string_valid (strinfo, length, "baz"));
1476   g_assert (!strinfo_is_string_valid (strinfo, length, "quux"));
1477 }
1478
1479 static void
1480 test_enums (void)
1481 {
1482   GSettings *settings, *direct;
1483   gchar *str;
1484
1485   settings = g_settings_new ("org.gtk.test.enums");
1486   direct = g_settings_new ("org.gtk.test.enums.direct");
1487
1488   if (!backend_set)
1489     {
1490       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1491         g_settings_get_enum (direct, "test");
1492       g_test_trap_assert_failed ();
1493       g_test_trap_assert_stderr ("*not associated with an enum*");
1494
1495       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1496         g_settings_set_enum (settings, "test", 42);
1497       g_test_trap_assert_failed ();
1498       g_test_trap_assert_stderr ("*invalid enum value 42*");
1499
1500       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1501         g_settings_set_string (settings, "test", "qux");
1502       g_test_trap_assert_failed ();
1503       g_test_trap_assert_stderr ("*g_settings_range_check*");
1504
1505       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1506         g_settings_get_flags (settings, "test");
1507       g_test_trap_assert_failed ();
1508       g_test_trap_assert_stderr ("*not associated with a flags*");
1509     }
1510
1511   str = g_settings_get_string (settings, "test");
1512   g_assert_cmpstr (str, ==, "bar");
1513   g_free (str);
1514
1515   g_settings_set_enum (settings, "test", TEST_ENUM_FOO);
1516
1517   str = g_settings_get_string (settings, "test");
1518   g_assert_cmpstr (str, ==, "foo");
1519   g_free (str);
1520
1521   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_FOO);
1522
1523   g_settings_set_string (direct, "test", "qux");
1524
1525   str = g_settings_get_string (direct, "test");
1526   g_assert_cmpstr (str, ==, "qux");
1527   g_free (str);
1528
1529   str = g_settings_get_string (settings, "test");
1530   g_assert_cmpstr (str, ==, "quux");
1531   g_free (str);
1532
1533   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_QUUX);
1534 }
1535
1536 static void
1537 test_flags (void)
1538 {
1539   GSettings *settings, *direct;
1540   gchar **strv;
1541   gchar *str;
1542
1543   settings = g_settings_new ("org.gtk.test.enums");
1544   direct = g_settings_new ("org.gtk.test.enums.direct");
1545
1546   if (!backend_set)
1547     {
1548       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1549         g_settings_get_flags (direct, "test");
1550       g_test_trap_assert_failed ();
1551       g_test_trap_assert_stderr ("*not associated with a flags*");
1552
1553       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1554         g_settings_set_flags (settings, "f-test", 0x42);
1555       g_test_trap_assert_failed ();
1556       g_test_trap_assert_stderr ("*invalid flags value 0x00000042*");
1557
1558       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1559         g_settings_set_strv (settings, "f-test",
1560                              (const gchar **) g_strsplit ("rock", ",", 0));
1561       g_test_trap_assert_failed ();
1562       g_test_trap_assert_stderr ("*g_settings_range_check*");
1563
1564       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1565         g_settings_get_enum (settings, "f-test");
1566       g_test_trap_assert_failed ();
1567       g_test_trap_assert_stderr ("*not associated with an enum*");
1568     }
1569
1570   strv = g_settings_get_strv (settings, "f-test");
1571   str = g_strjoinv (",", strv);
1572   g_assert_cmpstr (str, ==, "");
1573   g_strfreev (strv);
1574   g_free (str);
1575
1576   g_settings_set_flags (settings, "f-test",
1577                         TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
1578
1579   strv = g_settings_get_strv (settings, "f-test");
1580   str = g_strjoinv (",", strv);
1581   g_assert_cmpstr (str, ==, "talking,walking");
1582   g_strfreev (strv);
1583   g_free (str);
1584
1585   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
1586                    TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
1587
1588   strv = g_strsplit ("speaking,laughing", ",", 0);
1589   g_settings_set_strv (direct, "f-test", (const gchar **) strv);
1590   g_strfreev (strv);
1591
1592   strv = g_settings_get_strv (direct, "f-test");
1593   str = g_strjoinv (",", strv);
1594   g_assert_cmpstr (str, ==, "speaking,laughing");
1595   g_strfreev (strv);
1596   g_free (str);
1597
1598   strv = g_settings_get_strv (settings, "f-test");
1599   str = g_strjoinv (",", strv);
1600   g_assert_cmpstr (str, ==, "talking,laughing");
1601   g_strfreev (strv);
1602   g_free (str);
1603
1604   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
1605                    TEST_FLAGS_TALKING | TEST_FLAGS_LAUGHING);
1606 }
1607
1608 static void
1609 test_range (void)
1610 {
1611   GSettings *settings, *direct;
1612
1613   settings = g_settings_new ("org.gtk.test.range");
1614   direct = g_settings_new ("org.gtk.test.range.direct");
1615
1616   if (!backend_set)
1617     {
1618       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1619         g_settings_set_int (settings, "val", 45);
1620       g_test_trap_assert_failed ();
1621       g_test_trap_assert_stderr ("*g_settings_range_check*");
1622
1623       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1624         g_settings_set_int (settings, "val", 1);
1625       g_test_trap_assert_failed ();
1626       g_test_trap_assert_stderr ("*g_settings_range_check*");
1627     }
1628
1629   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
1630   g_settings_set_int (direct, "val", 22);
1631   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 22);
1632   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 22);
1633   g_settings_set_int (direct, "val", 45);
1634   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 45);
1635   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
1636   g_settings_set_int (direct, "val", 1);
1637   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 1);
1638   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
1639 }
1640
1641 static gboolean
1642 strv_has_string (const gchar **haystack,
1643                  const gchar  *needle)
1644 {
1645   guint n;
1646
1647   for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
1648     {
1649       if (g_strcmp0 (haystack[n], needle) == 0)
1650         return TRUE;
1651     }
1652   return FALSE;
1653 }
1654
1655 static gboolean
1656 strv_set_equal (const gchar **strv, ...)
1657 {
1658   gint count;
1659   va_list list;
1660   const gchar *str;
1661   gboolean res;
1662
1663   res = TRUE;
1664   count = 0;
1665   va_start (list, strv);
1666   while (1)
1667     {
1668       str = va_arg (list, const gchar *);
1669       if (str == NULL)
1670         break;
1671       if (!strv_has_string (strv, str))
1672         {
1673           res = FALSE;
1674           break;
1675         }
1676       count++;
1677     }
1678   va_end (list);
1679
1680   if (res)
1681     res = g_strv_length ((gchar**)strv) == count;
1682
1683   return res;
1684 }
1685
1686 static void
1687 test_list_items (void)
1688 {
1689   GSettings *settings;
1690   const gchar **items;
1691
1692   settings = g_settings_new ("org.gtk.test");
1693   items = g_settings_list_items (settings);
1694
1695   g_assert (strv_set_equal (items, "greeting", "farewell", "basic-types/", "complex-types/", "localized/", NULL));
1696
1697   g_free (items);
1698
1699   g_object_unref (settings);
1700 }
1701
1702 static gboolean
1703 map_func (GVariant *value,
1704           gpointer *result,
1705           gpointer  user_data)
1706 {
1707   gint *state = user_data;
1708   gint v;
1709
1710   if (value)
1711     v = g_variant_get_int32 (value);
1712   else
1713     v = -1;
1714
1715   if (*state == 0)
1716     {
1717       g_assert_cmpint (v, ==, 1);
1718       (*state)++;
1719       return FALSE;
1720     }
1721   else if (*state == 1)
1722     {
1723       g_assert_cmpint (v, ==, 0);
1724       (*state)++;
1725       return FALSE;
1726     }
1727   else
1728     {
1729       g_assert (value == NULL);
1730       *result = g_variant_new_int32 (5);
1731       return TRUE;
1732     }
1733 }
1734
1735 static void
1736 test_get_mapped (void)
1737 {
1738   GSettings *settings;
1739   gint state;
1740   gpointer p;
1741   gint val;
1742
1743   settings = g_settings_new ("org.gtk.test.mapped");
1744   g_settings_set_int (settings, "val", 1);
1745
1746   state = 0;
1747   p = g_settings_get_mapped (settings, "val", map_func, &state);
1748   val = g_variant_get_int32 ((GVariant*)p);
1749   g_assert_cmpint (val, ==, 5);
1750
1751   g_variant_unref (p);
1752   g_object_unref (settings);
1753 }
1754
1755 int
1756 main (int argc, char *argv[])
1757 {
1758   gchar *enums;
1759   gint result;
1760
1761   setlocale (LC_ALL, "");
1762
1763   backend_set = g_getenv ("GSETTINGS_BACKEND") != NULL;
1764
1765   g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
1766
1767   if (!backend_set)
1768     g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
1769
1770   g_type_init ();
1771   g_test_init (&argc, &argv, NULL);
1772
1773   g_remove ("org.gtk.test.enums.xml");
1774   g_assert (g_spawn_command_line_sync ("../../gobject/glib-mkenums "
1775                                        "--template " SRCDIR "/enums.xml.template "
1776                                        SRCDIR "/testenum.h",
1777                                        &enums, NULL, &result, NULL));
1778   g_assert (result == 0);
1779   g_assert (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
1780   g_free (enums);
1781
1782   g_remove ("gschemas.compiled");
1783   g_assert (g_spawn_command_line_sync ("../glib-compile-schemas --targetdir=. "
1784                                        "--schema-file=org.gtk.test.enums.xml "
1785                                        "--schema-file=" SRCDIR "/org.gtk.test.gschema.xml",
1786                                        NULL, NULL, &result, NULL));
1787   g_assert (result == 0);
1788
1789   g_test_add_func ("/gsettings/basic", test_basic);
1790
1791   if (!backend_set)
1792     {
1793       g_test_add_func ("/gsettings/no-schema", test_no_schema);
1794       g_test_add_func ("/gsettings/unknown-key", test_unknown_key);
1795       g_test_add_func ("/gsettings/wrong-type", test_wrong_type);
1796       g_test_add_func ("/gsettings/wrong-path", test_wrong_path);
1797       g_test_add_func ("/gsettings/no-path", test_no_path);
1798     }
1799
1800   g_test_add_func ("/gsettings/basic-types", test_basic_types);
1801   g_test_add_func ("/gsettings/complex-types", test_complex_types);
1802   g_test_add_func ("/gsettings/changes", test_changes);
1803
1804   if (glib_translations_work ())
1805     {
1806       g_test_add_func ("/gsettings/l10n", test_l10n);
1807       g_test_add_func ("/gsettings/l10n-context", test_l10n_context);
1808     }
1809
1810   g_test_add_func ("/gsettings/delay-apply", test_delay_apply);
1811   g_test_add_func ("/gsettings/delay-revert", test_delay_revert);
1812   g_test_add_func ("/gsettings/atomic", test_atomic);
1813
1814   g_test_add_func ("/gsettings/simple-binding", test_simple_binding);
1815   g_test_add_func ("/gsettings/directional-binding", test_directional_binding);
1816   g_test_add_func ("/gsettings/custom-binding", test_custom_binding);
1817   g_test_add_func ("/gsettings/no-change-binding", test_no_change_binding);
1818   g_test_add_func ("/gsettings/unbinding", test_unbind);
1819   g_test_add_func ("/gsettings/writable-binding", test_bind_writable);
1820
1821   if (!backend_set)
1822     {
1823       g_test_add_func ("/gsettings/typesafe-binding", test_typesafe_binding);
1824       g_test_add_func ("/gsettings/no-read-binding", test_no_read_binding);
1825       g_test_add_func ("/gsettings/no-write-binding", test_no_write_binding);
1826     }
1827
1828   g_test_add_func ("/gsettings/keyfile", test_keyfile);
1829   g_test_add_func ("/gsettings/child-schema", test_child_schema);
1830   g_test_add_func ("/gsettings/strinfo", test_strinfo);
1831   g_test_add_func ("/gsettings/enums", test_enums);
1832   g_test_add_func ("/gsettings/flags", test_flags);
1833   g_test_add_func ("/gsettings/range", test_range);
1834   g_test_add_func ("/gsettings/list-items", test_list_items);
1835   g_test_add_func ("/gsettings/mapped", test_get_mapped);
1836
1837   result = g_test_run ();
1838
1839   g_settings_sync ();
1840
1841   return result;
1842 }