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