Add several more settings tests
[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   guint u;
916   gint64 i64;
917   guint64 u64;
918   gdouble d;
919   gchar *s;
920   GVariant *value;
921
922   settings = g_settings_new ("org.gtk.test.binding");
923   obj = test_object_new ();
924
925   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_DEFAULT);
926
927   g_object_set (obj, "bool", TRUE, NULL);
928   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
929
930   g_settings_set_boolean (settings, "bool", FALSE);
931   g_object_get (obj, "bool", &b, NULL);
932   g_assert_cmpint (b, ==, FALSE);
933
934   g_settings_bind (settings, "byte", obj, "byte", G_SETTINGS_BIND_DEFAULT);
935
936   g_object_set (obj, "byte", 123, NULL);
937   g_settings_get (settings, "byte", "y", &y);
938   g_assert_cmpint (y, ==, 123);
939
940   g_settings_set (settings, "byte", "y", 54);
941   g_object_get (obj, "byte", &y, NULL);
942   g_assert_cmpint (y, ==, 54);
943
944   g_settings_bind (settings, "int16", obj, "int16", G_SETTINGS_BIND_DEFAULT);
945
946   g_object_set (obj, "int16", 1234, NULL);
947   g_settings_get (settings, "int16", "n", &i);
948   g_assert_cmpint (i, ==, 1234);
949
950   g_settings_set (settings, "int16", "n", 4321);
951   g_object_get (obj, "int16", &i, NULL);
952   g_assert_cmpint (i, ==, 4321);
953
954   g_settings_bind (settings, "uint16", obj, "uint16", G_SETTINGS_BIND_DEFAULT);
955
956   g_object_set (obj, "uint16", (guint16) G_MAXUINT16, NULL);
957   g_settings_get (settings, "uint16", "q", &u);
958   g_assert_cmpuint (u, ==, G_MAXUINT16);
959
960   g_settings_set (settings, "uint16", "q", (guint16) G_MAXINT16);
961   g_object_get (obj, "uint16", &u, NULL);
962   g_assert_cmpuint (u, ==, (guint16) G_MAXINT16);
963
964   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
965
966   g_object_set (obj, "int", 12345, NULL);
967   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
968
969   g_settings_set_int (settings, "int", 54321);
970   g_object_get (obj, "int", &i, NULL);
971   g_assert_cmpint (i, ==, 54321);
972
973   g_settings_bind (settings, "int64", obj, "int64", G_SETTINGS_BIND_DEFAULT);
974
975   g_object_set (obj, "int64", (gint64) G_MAXINT64, NULL);
976   g_settings_get (settings, "int64", "x", &i64);
977   g_assert_cmpint (i64, ==, G_MAXINT64);
978
979   g_settings_set (settings, "int64", "x", (gint64) G_MININT64);
980   g_object_get (obj, "int64", &i64, NULL);
981   g_assert_cmpint (i64, ==, G_MININT64);
982
983   g_settings_bind (settings, "uint64", obj, "uint64", G_SETTINGS_BIND_DEFAULT);
984
985   g_object_set (obj, "uint64", (guint64) G_MAXUINT64, NULL);
986   g_settings_get (settings, "uint64", "t", &u64);
987   g_assert_cmpuint (u64, ==, G_MAXUINT64);
988
989   g_settings_set (settings, "uint64", "t", (guint64) G_MAXINT64);
990   g_object_get (obj, "uint64", &u64, NULL);
991   g_assert_cmpuint (u64, ==, (guint64) G_MAXINT64);
992
993   g_settings_bind (settings, "string", obj, "string", G_SETTINGS_BIND_DEFAULT);
994
995   g_object_set (obj, "string", "bu ba", NULL);
996   s = g_settings_get_string (settings, "string");
997   g_assert_cmpstr (s, ==, "bu ba");
998   g_free (s);
999
1000   g_settings_set_string (settings, "string", "bla bla");
1001   g_object_get (obj, "string", &s, NULL);
1002   g_assert_cmpstr (s, ==, "bla bla");
1003   g_free (s);
1004
1005   g_settings_bind (settings, "chararray", obj, "string", G_SETTINGS_BIND_DEFAULT);
1006
1007   g_object_set (obj, "string", "non-unicode:\315", NULL);
1008   value = g_settings_get_value (settings, "chararray");
1009   g_assert_cmpstr (g_variant_get_byte_array (value, NULL), ==, "non-unicode:\315");
1010   g_variant_unref (value);
1011
1012   g_settings_bind (settings, "double", obj, "double", G_SETTINGS_BIND_DEFAULT);
1013
1014   g_object_set (obj, "double", G_MAXFLOAT, NULL);
1015   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXFLOAT);
1016
1017   g_settings_set_double (settings, "double", G_MINFLOAT);
1018   g_object_get (obj, "double", &d, NULL);
1019   g_assert_cmpfloat (d, ==, G_MINFLOAT);
1020
1021   g_object_set (obj, "double", G_MAXDOUBLE, NULL);
1022   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXDOUBLE);
1023
1024   g_settings_set_double (settings, "double", -G_MINDOUBLE);
1025   g_object_get (obj, "double", &d, NULL);
1026   g_assert_cmpfloat (d, ==, -G_MINDOUBLE);
1027
1028   g_settings_bind (settings, "enum", obj, "enum", G_SETTINGS_BIND_DEFAULT);
1029   g_object_set (obj, "enum", TEST_ENUM_BAZ, NULL);
1030   g_assert_cmpstr (g_settings_get_string (settings, "enum"), ==, "baz");
1031   g_assert_cmpint (g_settings_get_enum (settings, "enum"), ==, TEST_ENUM_BAZ);
1032
1033   g_settings_set_enum (settings, "enum", TEST_ENUM_QUUX);
1034   g_object_get (obj, "enum", &i, NULL);
1035   g_assert_cmpint (i, ==, TEST_ENUM_QUUX);
1036
1037   g_settings_set_string (settings, "enum", "baz");
1038   g_object_get (obj, "enum", &i, NULL);
1039   g_assert_cmpint (i, ==, TEST_ENUM_BAZ);
1040
1041   g_object_unref (obj);
1042   g_object_unref (settings);
1043 }
1044
1045 static void
1046 test_unbind (void)
1047 {
1048   TestObject *obj;
1049   GSettings *settings;
1050
1051   settings = g_settings_new ("org.gtk.test.binding");
1052   obj = test_object_new ();
1053
1054   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
1055
1056   g_object_set (obj, "int", 12345, NULL);
1057   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1058
1059   g_settings_unbind (obj, "int");
1060
1061   g_object_set (obj, "int", 54321, NULL);
1062   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1063
1064   g_object_unref (obj);
1065   g_object_unref (settings);
1066 }
1067
1068 static void
1069 test_bind_writable (void)
1070 {
1071   TestObject *obj;
1072   GSettings *settings;
1073   gboolean b;
1074
1075   settings = g_settings_new ("org.gtk.test.binding");
1076   obj = test_object_new ();
1077
1078   g_object_set (obj, "bool", FALSE, NULL);
1079
1080   g_settings_bind_writable (settings, "int", obj, "bool", FALSE);
1081
1082   g_object_get (obj, "bool", &b, NULL);
1083   g_assert (b);
1084
1085   g_settings_unbind (obj, "bool");
1086
1087   g_settings_bind_writable (settings, "int", obj, "bool", TRUE);
1088
1089   g_object_get (obj, "bool", &b, NULL);
1090   g_assert (!b);
1091
1092   g_object_unref (obj);
1093   g_object_unref (settings);
1094 }
1095
1096 /* Test one-way bindings.
1097  * Verify that changes on one side show up on the other,
1098  * but not vice versa
1099  */
1100 static void
1101 test_directional_binding (void)
1102 {
1103   TestObject *obj;
1104   GSettings *settings;
1105   gboolean b;
1106   gint i;
1107
1108   settings = g_settings_new ("org.gtk.test.binding");
1109   obj = test_object_new ();
1110
1111   g_object_set (obj, "bool", FALSE, NULL);
1112   g_settings_set_boolean (settings, "bool", FALSE);
1113
1114   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET);
1115
1116   g_settings_set_boolean (settings, "bool", TRUE);
1117   g_object_get (obj, "bool", &b, NULL);
1118   g_assert_cmpint (b, ==, TRUE);
1119
1120   g_object_set (obj, "bool", FALSE, NULL);
1121   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
1122
1123   g_object_set (obj, "int", 20, NULL);
1124   g_settings_set_int (settings, "int", 20);
1125
1126   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_SET);
1127
1128   g_object_set (obj, "int", 32, NULL);
1129   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 32);
1130
1131   g_settings_set_int (settings, "int", 20);
1132   g_object_get (obj, "int", &i, NULL);
1133   g_assert_cmpint (i, ==, 32);
1134
1135   g_object_unref (obj);
1136   g_object_unref (settings);
1137 }
1138
1139 /* Test that type mismatch is caught when creating a binding
1140  */
1141 static void
1142 test_typesafe_binding (void)
1143 {
1144   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1145     {
1146       TestObject *obj;
1147       GSettings *settings;
1148
1149       settings = g_settings_new ("org.gtk.test.binding");
1150       obj = test_object_new ();
1151
1152       g_settings_bind (settings, "string", obj, "int", G_SETTINGS_BIND_DEFAULT);
1153
1154       g_object_unref (obj);
1155       g_object_unref (settings);
1156     }
1157   g_test_trap_assert_failed ();
1158   g_test_trap_assert_stderr ("*not compatible*");
1159 }
1160
1161 static gboolean
1162 string_to_bool (GValue   *value,
1163                 GVariant *variant,
1164                 gpointer  user_data)
1165 {
1166   const gchar *s;
1167
1168   s = g_variant_get_string (variant, NULL);
1169   g_value_set_boolean (value, g_strcmp0 (s, "true") == 0);
1170
1171   return TRUE;
1172 }
1173
1174 static GVariant *
1175 bool_to_string (const GValue       *value,
1176                 const GVariantType *expected_type,
1177                 gpointer            user_data)
1178 {
1179   if (g_value_get_boolean (value))
1180     return g_variant_new_string ("true");
1181   else
1182     return g_variant_new_string ("false");
1183 }
1184
1185 /* Test custom bindings.
1186  * Translate strings to booleans and back
1187  */
1188 static void
1189 test_custom_binding (void)
1190 {
1191   TestObject *obj;
1192   GSettings *settings;
1193   gchar *s;
1194   gboolean b;
1195
1196   settings = g_settings_new ("org.gtk.test.binding");
1197   obj = test_object_new ();
1198
1199   g_settings_set_string (settings, "string", "true");
1200
1201   g_settings_bind_with_mapping (settings, "string",
1202                                 obj, "bool",
1203                                 G_SETTINGS_BIND_DEFAULT,
1204                                 string_to_bool,
1205                                 bool_to_string,
1206                                 NULL, NULL);
1207
1208   g_settings_set_string (settings, "string", "false");
1209   g_object_get (obj, "bool", &b, NULL);
1210   g_assert_cmpint (b, ==, FALSE);
1211
1212   g_settings_set_string (settings, "string", "not true");
1213   g_object_get (obj, "bool", &b, NULL);
1214   g_assert_cmpint (b, ==, FALSE);
1215
1216   g_object_set (obj, "bool", TRUE, NULL);
1217   s = g_settings_get_string (settings, "string");
1218   g_assert_cmpstr (s, ==, "true");
1219   g_free (s);
1220
1221   g_object_unref (obj);
1222   g_object_unref (settings);
1223 }
1224
1225 /* Test that with G_SETTINGS_BIND_NO_CHANGES, the
1226  * initial settings value is transported to the object
1227  * side, but later settings changes do not affect the
1228  * object
1229  */
1230 static void
1231 test_no_change_binding (void)
1232 {
1233   TestObject *obj;
1234   GSettings *settings;
1235   gboolean b;
1236
1237   settings = g_settings_new ("org.gtk.test.binding");
1238   obj = test_object_new ();
1239
1240   g_object_set (obj, "bool", TRUE, NULL);
1241   g_settings_set_boolean (settings, "bool", FALSE);
1242
1243   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET_NO_CHANGES);
1244
1245   g_object_get (obj, "bool", &b, NULL);
1246   g_assert_cmpint (b, ==, FALSE);
1247
1248   g_settings_set_boolean (settings, "bool", TRUE);
1249   g_object_get (obj, "bool", &b, NULL);
1250   g_assert_cmpint (b, ==, FALSE);
1251
1252   g_settings_set_boolean (settings, "bool", FALSE);
1253   g_object_set (obj, "bool", TRUE, NULL);
1254   b = g_settings_get_boolean (settings, "bool");
1255   g_assert_cmpint (b, ==, TRUE);
1256
1257   g_object_unref (obj);
1258   g_object_unref (settings);
1259 }
1260
1261 /* Test that binding a non-readable property only
1262  * works in 'GET' mode.
1263  */
1264 static void
1265 test_no_read_binding (void)
1266 {
1267   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1268     {
1269       TestObject *obj;
1270       GSettings *settings;
1271
1272       settings = g_settings_new ("org.gtk.test.binding");
1273       obj = test_object_new ();
1274
1275       g_settings_bind (settings, "string", obj, "no-read", 0);
1276     }
1277   g_test_trap_assert_failed ();
1278   g_test_trap_assert_stderr ("*property*is not readable*");
1279
1280   if (g_test_trap_fork (0, 0))
1281     {
1282       TestObject *obj;
1283       GSettings *settings;
1284
1285       settings = g_settings_new ("org.gtk.test.binding");
1286       obj = test_object_new ();
1287
1288       g_settings_bind (settings, "string", obj, "no-read", G_SETTINGS_BIND_GET);
1289
1290       exit (0);
1291     }
1292   g_test_trap_assert_passed ();
1293 }
1294
1295 /* Test that binding a non-writable property only
1296  * works in 'SET' mode.
1297  */
1298 static void
1299 test_no_write_binding (void)
1300 {
1301   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1302     {
1303       TestObject *obj;
1304       GSettings *settings;
1305
1306       settings = g_settings_new ("org.gtk.test.binding");
1307       obj = test_object_new ();
1308
1309       g_settings_bind (settings, "string", obj, "no-write", 0);
1310     }
1311   g_test_trap_assert_failed ();
1312   g_test_trap_assert_stderr ("*property*is not writable*");
1313
1314   if (g_test_trap_fork (0, 0))
1315     {
1316       TestObject *obj;
1317       GSettings *settings;
1318
1319       settings = g_settings_new ("org.gtk.test.binding");
1320       obj = test_object_new ();
1321
1322       g_settings_bind (settings, "string", obj, "no-write", G_SETTINGS_BIND_SET);
1323
1324       exit (0);
1325     }
1326   g_test_trap_assert_passed ();
1327 }
1328
1329 /*
1330  * Test that using a keyfile works
1331  */
1332 static void
1333 test_keyfile (void)
1334 {
1335   GSettingsBackend *kf_backend;
1336   GSettings *settings;
1337   GKeyFile *keyfile;
1338   gchar *str;
1339
1340   g_remove ("gsettings.store");
1341
1342   kf_backend = g_keyfile_settings_backend_new ("gsettings.store", "/", "root");
1343   settings = g_settings_new_with_backend ("org.gtk.test", kf_backend);
1344   g_object_unref (kf_backend);
1345
1346   g_settings_set (settings, "greeting", "s", "see if this works");
1347
1348   keyfile = g_key_file_new ();
1349   g_assert (g_key_file_load_from_file (keyfile, "gsettings.store", 0, NULL));
1350
1351   str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
1352   g_assert_cmpstr (str, ==, "'see if this works'");
1353
1354   g_free (str);
1355   g_key_file_free (keyfile);
1356   g_object_unref (settings);
1357 }
1358
1359 /* Test that getting child schemas works
1360  */
1361 static void
1362 test_child_schema (void)
1363 {
1364   GSettings *settings;
1365   GSettings *child;
1366   guint8 byte;
1367
1368   /* first establish some known conditions */
1369   settings = g_settings_new ("org.gtk.test.basic-types");
1370   g_settings_set (settings, "test-byte", "y", 36);
1371
1372   g_settings_get (settings, "test-byte", "y", &byte);
1373   g_assert_cmpint (byte, ==, 36);
1374
1375   g_object_unref (settings);
1376
1377   settings = g_settings_new ("org.gtk.test");
1378   child = g_settings_get_child (settings, "basic-types");
1379   g_assert (child != NULL);
1380
1381   g_settings_get (child, "test-byte", "y", &byte);
1382   g_assert_cmpint (byte, ==, 36);
1383
1384   g_object_unref (child);
1385   g_object_unref (settings);
1386 }
1387
1388 static gboolean
1389 glib_translations_work (void)
1390 {
1391   gchar *locale;
1392   gchar *orig = "Unnamed";
1393   gchar *str;
1394
1395   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
1396   setlocale (LC_MESSAGES, "de");
1397   str = dgettext ("glib20", orig);
1398   setlocale (LC_MESSAGES, locale);
1399   g_free (locale);
1400
1401   return str != orig;
1402 }
1403
1404 #include "../strinfo.c"
1405
1406 static void
1407 test_strinfo (void)
1408 {
1409   /*  "foo" has a value of 1
1410    *  "bar" has a value of 2
1411    *  "baz" is an alias for "bar"
1412    */
1413   gchar array[] =
1414     "\1\0\0\0"      "\xff""foo"     "\0\0\0\xff"    "\2\0\0\0"
1415     "\xff" "bar"    "\0\0\0\xff"    "\3\0\0\0"      "\xfe""baz"
1416     "\0\0\0\xff";
1417   const guint32 *strinfo = (guint32 *) array;
1418   guint length = sizeof array / 4;
1419   guint result;
1420
1421   {
1422     /* build it and compare */
1423     GString *builder;
1424
1425     builder = g_string_new (NULL);
1426     strinfo_builder_append_item (builder, "foo", 1);
1427     strinfo_builder_append_item (builder, "bar", 2);
1428     g_assert (strinfo_builder_append_alias (builder, "baz", "bar"));
1429     g_assert_cmpint (builder->len % 4, ==, 0);
1430     g_assert_cmpint (builder->len / 4, ==, length);
1431     g_assert (memcmp (builder->str, strinfo, length * 4) == 0);
1432     g_string_free (builder, TRUE);
1433   }
1434
1435   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "foo"),
1436                    ==, NULL);
1437   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "bar"),
1438                    ==, NULL);
1439   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "baz"),
1440                    ==, "bar");
1441   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "quux"),
1442                    ==, NULL);
1443
1444   g_assert (strinfo_enum_from_string (strinfo, length, "foo", &result));
1445   g_assert_cmpint (result, ==, 1);
1446   g_assert (strinfo_enum_from_string (strinfo, length, "bar", &result));
1447   g_assert_cmpint (result, ==, 2);
1448   g_assert (!strinfo_enum_from_string (strinfo, length, "baz", &result));
1449   g_assert (!strinfo_enum_from_string (strinfo, length, "quux", &result));
1450
1451   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 0), ==, NULL);
1452   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 1), ==, "foo");
1453   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 2), ==, "bar");
1454   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 3), ==, NULL);
1455
1456   g_assert (strinfo_is_string_valid (strinfo, length, "foo"));
1457   g_assert (strinfo_is_string_valid (strinfo, length, "bar"));
1458   g_assert (!strinfo_is_string_valid (strinfo, length, "baz"));
1459   g_assert (!strinfo_is_string_valid (strinfo, length, "quux"));
1460 }
1461
1462 static void
1463 test_enums (void)
1464 {
1465   GSettings *settings, *direct;
1466   gchar *str;
1467
1468   settings = g_settings_new ("org.gtk.test.enums");
1469   direct = g_settings_new ("org.gtk.test.enums.direct");
1470
1471   if (!backend_set)
1472     {
1473       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1474         g_settings_get_enum (direct, "test");
1475       g_test_trap_assert_failed ();
1476       g_test_trap_assert_stderr ("*not associated with an enum*");
1477
1478       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1479         g_settings_set_enum (settings, "test", 42);
1480       g_test_trap_assert_failed ();
1481       g_test_trap_assert_stderr ("*invalid enum value 42*");
1482
1483       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1484         g_settings_set_string (settings, "test", "qux");
1485       g_test_trap_assert_failed ();
1486       g_test_trap_assert_stderr ("*g_settings_range_check*");
1487
1488       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1489         g_settings_get_flags (settings, "test");
1490       g_test_trap_assert_failed ();
1491       g_test_trap_assert_stderr ("*not associated with a flags*");
1492     }
1493
1494   str = g_settings_get_string (settings, "test");
1495   g_assert_cmpstr (str, ==, "bar");
1496   g_free (str);
1497
1498   g_settings_set_enum (settings, "test", TEST_ENUM_FOO);
1499
1500   str = g_settings_get_string (settings, "test");
1501   g_assert_cmpstr (str, ==, "foo");
1502   g_free (str);
1503
1504   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_FOO);
1505
1506   g_settings_set_string (direct, "test", "qux");
1507
1508   str = g_settings_get_string (direct, "test");
1509   g_assert_cmpstr (str, ==, "qux");
1510   g_free (str);
1511
1512   str = g_settings_get_string (settings, "test");
1513   g_assert_cmpstr (str, ==, "quux");
1514   g_free (str);
1515
1516   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_QUUX);
1517 }
1518
1519 static void
1520 test_flags (void)
1521 {
1522   GSettings *settings, *direct;
1523   gchar **strv;
1524   gchar *str;
1525
1526   settings = g_settings_new ("org.gtk.test.enums");
1527   direct = g_settings_new ("org.gtk.test.enums.direct");
1528
1529   if (!backend_set)
1530     {
1531       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1532         g_settings_get_flags (direct, "test");
1533       g_test_trap_assert_failed ();
1534       g_test_trap_assert_stderr ("*not associated with a flags*");
1535
1536       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1537         g_settings_set_flags (settings, "f-test", 0x42);
1538       g_test_trap_assert_failed ();
1539       g_test_trap_assert_stderr ("*invalid flags value 0x00000042*");
1540
1541       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1542         g_settings_set_strv (settings, "f-test",
1543                              (const gchar **) g_strsplit ("rock", ",", 0));
1544       g_test_trap_assert_failed ();
1545       g_test_trap_assert_stderr ("*g_settings_range_check*");
1546
1547       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1548         g_settings_get_enum (settings, "f-test");
1549       g_test_trap_assert_failed ();
1550       g_test_trap_assert_stderr ("*not associated with an enum*");
1551     }
1552
1553   strv = g_settings_get_strv (settings, "f-test");
1554   str = g_strjoinv (",", strv);
1555   g_assert_cmpstr (str, ==, "");
1556   g_strfreev (strv);
1557   g_free (str);
1558
1559   g_settings_set_flags (settings, "f-test",
1560                         TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
1561
1562   strv = g_settings_get_strv (settings, "f-test");
1563   str = g_strjoinv (",", strv);
1564   g_assert_cmpstr (str, ==, "talking,walking");
1565   g_strfreev (strv);
1566   g_free (str);
1567
1568   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
1569                    TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
1570
1571   strv = g_strsplit ("speaking,laughing", ",", 0);
1572   g_settings_set_strv (direct, "f-test", (const gchar **) strv);
1573   g_strfreev (strv);
1574
1575   strv = g_settings_get_strv (direct, "f-test");
1576   str = g_strjoinv (",", strv);
1577   g_assert_cmpstr (str, ==, "speaking,laughing");
1578   g_strfreev (strv);
1579   g_free (str);
1580
1581   strv = g_settings_get_strv (settings, "f-test");
1582   str = g_strjoinv (",", strv);
1583   g_assert_cmpstr (str, ==, "talking,laughing");
1584   g_strfreev (strv);
1585   g_free (str);
1586
1587   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
1588                    TEST_FLAGS_TALKING | TEST_FLAGS_LAUGHING);
1589 }
1590
1591 static void
1592 test_range (void)
1593 {
1594   GSettings *settings, *direct;
1595
1596   settings = g_settings_new ("org.gtk.test.range");
1597   direct = g_settings_new ("org.gtk.test.range.direct");
1598
1599   if (!backend_set)
1600     {
1601       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1602         g_settings_set_int (settings, "val", 45);
1603       g_test_trap_assert_failed ();
1604       g_test_trap_assert_stderr ("*g_settings_range_check*");
1605
1606       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
1607         g_settings_set_int (settings, "val", 1);
1608       g_test_trap_assert_failed ();
1609       g_test_trap_assert_stderr ("*g_settings_range_check*");
1610     }
1611
1612   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
1613   g_settings_set_int (direct, "val", 22);
1614   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 22);
1615   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 22);
1616   g_settings_set_int (direct, "val", 45);
1617   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 45);
1618   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
1619   g_settings_set_int (direct, "val", 1);
1620   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 1);
1621   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
1622 }
1623
1624 static gboolean
1625 strv_has_string (const gchar **haystack,
1626                  const gchar  *needle)
1627 {
1628   guint n;
1629
1630   for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
1631     {
1632       if (g_strcmp0 (haystack[n], needle) == 0)
1633         return TRUE;
1634     }
1635   return FALSE;
1636 }
1637
1638 static gboolean
1639 strv_set_equal (const gchar **strv, ...)
1640 {
1641   gint count;
1642   va_list list;
1643   const gchar *str;
1644   gboolean res;
1645
1646   res = TRUE;
1647   count = 0;
1648   va_start (list, strv);
1649   while (1)
1650     {
1651       str = va_arg (list, const gchar *);
1652       if (str == NULL)
1653         break;
1654       if (!strv_has_string (strv, str))
1655         {
1656           res = FALSE;
1657           break;
1658         }
1659       count++;
1660     }
1661   va_end (list);
1662
1663   if (res)
1664     res = g_strv_length ((gchar**)strv) == count;
1665
1666   return res;
1667 }
1668
1669 static void
1670 test_list_items (void)
1671 {
1672   GSettings *settings;
1673   const gchar **items;
1674
1675   settings = g_settings_new ("org.gtk.test");
1676   items = g_settings_list_items (settings);
1677
1678   g_assert (strv_set_equal (items, "greeting", "farewell", "basic-types/", "complex-types/", "localized/", NULL));
1679
1680   g_free (items);
1681
1682   g_object_unref (settings);
1683 }
1684
1685 static gboolean
1686 map_func (GVariant *value,
1687           gpointer *result,
1688           gpointer  user_data)
1689 {
1690   gint *state = user_data;
1691   gint v;
1692
1693   if (value)
1694     v = g_variant_get_int32 (value);
1695   else
1696     v = -1;
1697
1698   if (*state == 0)
1699     {
1700       g_assert_cmpint (v, ==, 1);
1701       (*state)++;
1702       return FALSE;
1703     }
1704   else if (*state == 1)
1705     {
1706       g_assert_cmpint (v, ==, 0);
1707       (*state)++;
1708       return FALSE;
1709     }
1710   else
1711     {
1712       g_assert (value == NULL);
1713       *result = g_variant_new_int32 (5);
1714       return TRUE;
1715     }
1716 }
1717
1718 static void
1719 test_get_mapped (void)
1720 {
1721   GSettings *settings;
1722   gint state;
1723   gpointer p;
1724   gint val;
1725
1726   settings = g_settings_new ("org.gtk.test.mapped");
1727   g_settings_set_int (settings, "val", 1);
1728
1729   state = 0;
1730   p = g_settings_get_mapped (settings, "val", map_func, &state);
1731   val = g_variant_get_int32 ((GVariant*)p);
1732   g_assert_cmpint (val, ==, 5);
1733
1734   g_variant_unref (p);
1735   g_object_unref (settings);
1736 }
1737
1738 int
1739 main (int argc, char *argv[])
1740 {
1741   gchar *enums;
1742   gint result;
1743
1744   setlocale (LC_ALL, "");
1745
1746   backend_set = g_getenv ("GSETTINGS_BACKEND") != NULL;
1747
1748   g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
1749
1750   if (!backend_set)
1751     g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
1752
1753   g_type_init ();
1754   g_test_init (&argc, &argv, NULL);
1755
1756   g_remove ("org.gtk.test.enums.xml");
1757   g_assert (g_spawn_command_line_sync ("../../gobject/glib-mkenums "
1758                                        "--template " SRCDIR "/enums.xml.template "
1759                                        SRCDIR "/testenum.h",
1760                                        &enums, NULL, &result, NULL));
1761   g_assert (result == 0);
1762   g_assert (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
1763   g_free (enums);
1764
1765   g_remove ("gschemas.compiled");
1766   g_assert (g_spawn_command_line_sync ("../glib-compile-schemas --targetdir=. "
1767                                        "--schema-file=org.gtk.test.enums.xml "
1768                                        "--schema-file=" SRCDIR "/org.gtk.test.gschema.xml",
1769                                        NULL, NULL, &result, NULL));
1770   g_assert (result == 0);
1771
1772   g_test_add_func ("/gsettings/basic", test_basic);
1773
1774   if (!backend_set)
1775     {
1776       g_test_add_func ("/gsettings/no-schema", test_no_schema);
1777       g_test_add_func ("/gsettings/unknown-key", test_unknown_key);
1778       g_test_add_func ("/gsettings/wrong-type", test_wrong_type);
1779       g_test_add_func ("/gsettings/wrong-path", test_wrong_path);
1780       g_test_add_func ("/gsettings/no-path", test_no_path);
1781     }
1782
1783   g_test_add_func ("/gsettings/basic-types", test_basic_types);
1784   g_test_add_func ("/gsettings/complex-types", test_complex_types);
1785   g_test_add_func ("/gsettings/changes", test_changes);
1786
1787   if (glib_translations_work ())
1788     {
1789       g_test_add_func ("/gsettings/l10n", test_l10n);
1790       g_test_add_func ("/gsettings/l10n-context", test_l10n_context);
1791     }
1792
1793   g_test_add_func ("/gsettings/delay-apply", test_delay_apply);
1794   g_test_add_func ("/gsettings/delay-revert", test_delay_revert);
1795   g_test_add_func ("/gsettings/atomic", test_atomic);
1796
1797   g_test_add_func ("/gsettings/simple-binding", test_simple_binding);
1798   g_test_add_func ("/gsettings/directional-binding", test_directional_binding);
1799   g_test_add_func ("/gsettings/custom-binding", test_custom_binding);
1800   g_test_add_func ("/gsettings/no-change-binding", test_no_change_binding);
1801   g_test_add_func ("/gsettings/unbinding", test_unbind);
1802   g_test_add_func ("/gsettings/writable-binding", test_bind_writable);
1803
1804   if (!backend_set)
1805     {
1806       g_test_add_func ("/gsettings/typesafe-binding", test_typesafe_binding);
1807       g_test_add_func ("/gsettings/no-read-binding", test_no_read_binding);
1808       g_test_add_func ("/gsettings/no-write-binding", test_no_write_binding);
1809     }
1810
1811   g_test_add_func ("/gsettings/keyfile", test_keyfile);
1812   g_test_add_func ("/gsettings/child-schema", test_child_schema);
1813   g_test_add_func ("/gsettings/strinfo", test_strinfo);
1814   g_test_add_func ("/gsettings/enums", test_enums);
1815   g_test_add_func ("/gsettings/flags", test_flags);
1816   g_test_add_func ("/gsettings/range", test_range);
1817   g_test_add_func ("/gsettings/list-items", test_list_items);
1818   g_test_add_func ("/gsettings/mapped", test_get_mapped);
1819
1820   result = g_test_run ();
1821
1822   g_settings_sync ();
1823
1824   return result;
1825 }