Correct the sense of an assertion
[platform/upstream/glib.git] / gio / tests / gsettings.c
1 #include <stdlib.h>
2 #include <locale.h>
3 #include <libintl.h>
4 #include <gio.h>
5 #include <gstdio.h>
6
7 /* These tests rely on the schemas in org.gtk.test.gschema.xml
8  * to be compiled and installed in the same directory.
9  */
10
11 /* Just to get warmed up: Read and set a string, and
12  * verify that can read the changed string back
13  */
14 static void
15 test_basic (void)
16 {
17   gchar *str = NULL;
18   GSettings *settings;
19
20   settings = g_settings_new ("org.gtk.test");
21
22   g_settings_get (settings, "greeting", "s", &str);
23   g_assert_cmpstr (str, ==, "Hello, earthlings");
24
25   g_settings_set (settings, "greeting", "s", "goodbye world");
26   g_settings_get (settings, "greeting", "s", &str);
27   g_assert_cmpstr (str, ==, "goodbye world");
28   g_free (str);
29   str = NULL;
30
31   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
32     {
33       settings = g_settings_new ("org.gtk.test");
34       g_settings_set (settings, "greeting", "i", 555);
35       abort ();
36     }
37   g_test_trap_assert_failed ();
38   g_test_trap_assert_stderr ("*correct_type*");
39
40   g_settings_get (settings, "greeting", "s", &str);
41   g_assert_cmpstr (str, ==, "goodbye world");
42   g_free (str);
43   str = NULL;
44
45   g_settings_set (settings, "greeting", "s", "this is the end");
46   g_object_unref (settings);
47 }
48
49 /* Check that we get an error when getting a key
50  * that is not in the schema
51  */
52 static void
53 test_unknown_key (void)
54 {
55   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
56     {
57       GSettings *settings;
58       GVariant *value;
59
60       settings = g_settings_new ("org.gtk.test");
61       value = g_settings_get_value (settings, "no_such_key");
62
63       g_assert (value == NULL);
64
65       g_object_unref (settings);
66     }
67   g_test_trap_assert_failed ();
68   g_test_trap_assert_stderr ("*does not contain*");
69 }
70
71 /* Check that we get an error when the schema
72  * has not been installed
73  */
74 void
75 test_no_schema (void)
76 {
77   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
78     {
79       GSettings *settings;
80
81       settings = g_settings_new ("no.such.schema");
82
83       g_assert (settings == NULL);
84     }
85
86   g_test_trap_assert_failed ();
87   g_test_trap_assert_stderr ("*Settings schema 'no.such.schema' is not installed*");
88 }
89
90 /* Check that we get an error when passing a type string
91  * that does not match the schema
92  */
93 static void
94 test_wrong_type (void)
95 {
96   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
97     {
98       GSettings *settings;
99       gchar *str = NULL;
100
101       settings = g_settings_new ("org.gtk.test");
102
103       g_settings_get (settings, "greeting", "o", &str);
104
105       g_assert (str == NULL);
106     }
107   g_test_trap_assert_failed ();
108   g_test_trap_assert_stderr ("*CRITICAL*");
109
110   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
111     {
112       GSettings *settings;
113
114       settings = g_settings_new ("org.gtk.test");
115
116       g_settings_set (settings, "greetings", "o", "/a/path");
117     }
118   g_test_trap_assert_failed ();
119   g_test_trap_assert_stderr ("*CRITICAL*");
120 }
121
122 /* Check that we can successfully read and set the full
123  * range of all basic types
124  */
125 static void
126 test_basic_types (void)
127 {
128   GSettings *settings;
129   gboolean b;
130   guint8 byte;
131   gint16 i16;
132   guint16 u16;
133   gint32 i32;
134   guint32 u32;
135   gint64 i64;
136   guint64 u64;
137   gdouble d;
138   gchar *str;
139
140   settings = g_settings_new ("org.gtk.test.basic-types");
141
142   g_settings_get (settings, "test-boolean", "b", &b);
143   g_assert_cmpint (b, ==, 1);
144
145   g_settings_set (settings, "test-boolean", "b", 0);
146   g_settings_get (settings, "test-boolean", "b", &b);
147   g_assert_cmpint (b, ==, 0);
148
149   g_settings_get (settings, "test-byte", "y", &byte);
150   g_assert_cmpint (byte, ==, 25);
151
152   g_settings_set (settings, "test-byte", "y", G_MAXUINT8);
153   g_settings_get (settings, "test-byte", "y", &byte);
154   g_assert_cmpint (byte, ==, G_MAXUINT8);
155
156   g_settings_get (settings, "test-int16", "n", &i16);
157   g_assert_cmpint (i16, ==, -1234);
158
159   g_settings_set (settings, "test-int16", "n", G_MININT16);
160   g_settings_get (settings, "test-int16", "n", &i16);
161   g_assert_cmpint (i16, ==, G_MININT16);
162
163   g_settings_set (settings, "test-int16", "n", G_MAXINT16);
164   g_settings_get (settings, "test-int16", "n", &i16);
165   g_assert_cmpint (i16, ==, G_MAXINT16);
166
167   g_settings_get (settings, "test-uint16", "q", &u16);
168   g_assert_cmpuint (u16, ==, 1234);
169
170   g_settings_set (settings, "test-uint16", "q", G_MAXUINT16);
171   g_settings_get (settings, "test-uint16", "q", &u16);
172   g_assert_cmpuint (u16, ==, G_MAXUINT16);
173
174   g_settings_get (settings, "test-int32", "i", &i32);
175   g_assert_cmpint (i32, ==, -123456);
176
177   g_settings_set (settings, "test-int32", "i", G_MININT32);
178   g_settings_get (settings, "test-int32", "i", &i32);
179   g_assert_cmpint (i32, ==, G_MININT32);
180
181   g_settings_set (settings, "test-int32", "i", G_MAXINT32);
182   g_settings_get (settings, "test-int32", "i", &i32);
183   g_assert_cmpint (i32, ==, G_MAXINT32);
184
185   g_settings_get (settings, "test-uint32", "u", &u32);
186   g_assert_cmpuint (u32, ==, 123456);
187
188   g_settings_set (settings, "test-uint32", "u", G_MAXUINT32);
189   g_settings_get (settings, "test-uint32", "u", &u32);
190   g_assert_cmpuint (u32, ==, G_MAXUINT32);
191
192   g_settings_get (settings, "test-int64", "x", &i64);
193   g_assert_cmpuint (i64, ==, -123456789);
194
195   g_settings_set (settings, "test-int64", "x", G_MININT64);
196   g_settings_get (settings, "test-int64", "x", &i64);
197   g_assert_cmpuint (i64, ==, G_MININT64);
198
199   g_settings_set (settings, "test-int64", "x", G_MAXINT64);
200   g_settings_get (settings, "test-int64", "x", &i64);
201   g_assert_cmpuint (i64, ==, G_MAXINT64);
202
203   g_settings_get (settings, "test-uint64", "t", &u64);
204   g_assert_cmpuint (u64, ==, 123456789);
205
206   g_settings_set (settings, "test-uint64", "t", G_MAXUINT64);
207   g_settings_get (settings, "test-uint64", "t", &u64);
208   g_assert_cmpuint (u64, ==, G_MAXUINT64);
209
210   g_settings_get (settings, "test-double", "d", &d);
211   g_assert_cmpfloat (d, ==, 123.456);
212
213   g_settings_set (settings, "test-double", "d", G_MINDOUBLE);
214   g_settings_get (settings, "test-double", "d", &d);
215   g_assert_cmpfloat (d, ==, G_MINDOUBLE);
216
217   g_settings_set (settings, "test-double", "d", G_MAXDOUBLE);
218   g_settings_get (settings, "test-double", "d", &d);
219   g_assert_cmpfloat (d, ==, G_MAXDOUBLE);
220
221   g_settings_get (settings, "test-string", "s", &str);
222   g_assert_cmpstr (str, ==, "a string, it seems");
223   g_free (str);
224   str = NULL;
225
226   g_settings_get (settings, "test-objectpath", "o", &str);
227   g_assert_cmpstr (str, ==, "/a/object/path");
228   g_object_unref (settings);
229   g_free (str);
230   str = NULL;
231 }
232
233 /* Check that we can read an set complex types like
234  * tuples, arrays and dictionaries
235  */
236 static void
237 test_complex_types (void)
238 {
239   GSettings *settings;
240   gchar *s;
241   gint i1, i2;
242   GVariantIter *iter = NULL;
243
244   settings = g_settings_new ("org.gtk.test.complex-types");
245
246   g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
247   g_assert_cmpstr (s, ==, "one");
248   g_assert_cmpint (i1,==, 2);
249   g_assert_cmpint (i2,==, 3);
250   g_free (s) ;
251   s = NULL;
252
253   g_settings_set (settings, "test-tuple", "(s(ii))", "none", 0, 0);
254   g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
255   g_assert_cmpstr (s, ==, "none");
256   g_assert_cmpint (i1,==, 0);
257   g_assert_cmpint (i2,==, 0);
258   g_free (s);
259   s = NULL;
260
261   g_settings_get (settings, "test-array", "ai", &iter);
262   g_assert_cmpint (g_variant_iter_n_children (iter), ==, 6);
263   g_assert (g_variant_iter_next (iter, "i", &i1));
264   g_assert_cmpint (i1, ==, 0);
265   g_assert (g_variant_iter_next (iter, "i", &i1));
266   g_assert_cmpint (i1, ==, 1);
267   g_assert (g_variant_iter_next (iter, "i", &i1));
268   g_assert_cmpint (i1, ==, 2);
269   g_assert (g_variant_iter_next (iter, "i", &i1));
270   g_assert_cmpint (i1, ==, 3);
271   g_assert (g_variant_iter_next (iter, "i", &i1));
272   g_assert_cmpint (i1, ==, 4);
273   g_assert (g_variant_iter_next (iter, "i", &i1));
274   g_assert_cmpint (i1, ==, 5);
275   g_assert (!g_variant_iter_next (iter, "i", &i1));
276   g_variant_iter_free (iter);
277
278   g_object_unref (settings);
279 }
280
281 static gboolean changed_cb_called;
282
283 static void
284 changed_cb (GSettings   *settings,
285             const gchar *key,
286             gpointer     data)
287 {
288   changed_cb_called = TRUE;
289
290   g_assert_cmpstr (key, ==, data);
291 }
292
293 /* Test that basic change notification with the changed signal works.
294  */
295 void
296 test_changes (void)
297 {
298   GSettings *settings;
299   GSettings *settings2;
300
301   settings = g_settings_new ("org.gtk.test");
302
303   g_signal_connect (settings, "changed",
304                     G_CALLBACK (changed_cb), "greeting");
305
306   changed_cb_called = FALSE;
307
308   g_settings_set (settings, "greeting", "s", "new greeting");
309   g_assert (changed_cb_called);
310
311   settings2 = g_settings_new ("org.gtk.test");
312
313   changed_cb_called = FALSE;
314
315   g_settings_set (settings2, "greeting", "s", "hi");
316   g_assert (changed_cb_called);
317
318   g_object_unref (settings2);
319   g_object_unref (settings);
320 }
321
322 static gboolean changed_cb_called2;
323
324 static void
325 changed_cb2 (GSettings   *settings,
326              const gchar *key,
327              gpointer     data)
328 {
329   gboolean *p = data;
330
331   *p = TRUE;
332 }
333
334 /* Test that changes done to a delay-mode instance
335  * don't appear to the outside world until apply. Also
336  * check that we get change notification when they are
337  * applied.
338  * Also test that the has-unapplied property is properly
339  * maintained.
340  */
341 void
342 test_delay_apply (void)
343 {
344   GSettings *settings;
345   GSettings *settings2;
346   gchar *str;
347
348   settings = g_settings_new ("org.gtk.test");
349   settings2 = g_settings_new ("org.gtk.test");
350
351   g_settings_set (settings2, "greeting", "s", "top o' the morning");
352
353   changed_cb_called = FALSE;
354   changed_cb_called2 = FALSE;
355
356   g_signal_connect (settings, "changed",
357                     G_CALLBACK (changed_cb2), &changed_cb_called);
358   g_signal_connect (settings2, "changed",
359                     G_CALLBACK (changed_cb2), &changed_cb_called2);
360
361   g_settings_delay (settings);
362
363   g_settings_set (settings, "greeting", "s", "greetings from test_delay_apply");
364
365   g_assert (changed_cb_called);
366   g_assert (!changed_cb_called2);
367
368   g_settings_get (settings, "greeting", "s", &str);
369   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
370   g_free (str);
371   str = NULL;
372
373   g_settings_get (settings2, "greeting", "s", &str);
374   g_assert_cmpstr (str, ==, "top o' the morning");
375   g_free (str);
376   str = NULL;
377
378   g_assert (g_settings_get_has_unapplied (settings));
379   g_assert (!g_settings_get_has_unapplied (settings2));
380
381   changed_cb_called = FALSE;
382   changed_cb_called2 = FALSE;
383
384   g_settings_apply (settings);
385
386   g_assert (!changed_cb_called);
387   g_assert (changed_cb_called2);
388
389   g_settings_get (settings, "greeting", "s", &str);
390   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
391   g_free (str);
392   str = NULL;
393
394   g_settings_get (settings2, "greeting", "s", &str);
395   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
396   g_free (str);
397   str = NULL;
398
399   g_assert (!g_settings_get_has_unapplied (settings));
400   g_assert (!g_settings_get_has_unapplied (settings2));
401
402   g_object_unref (settings2);
403   g_object_unref (settings);
404 }
405
406 /* Test that reverting unapplied changes in a delay-apply
407  * settings instance works.
408  */
409 static void
410 test_delay_revert (void)
411 {
412   GSettings *settings;
413   GSettings *settings2;
414   gchar *str;
415
416   settings = g_settings_new ("org.gtk.test");
417   settings2 = g_settings_new ("org.gtk.test");
418
419   g_settings_set (settings2, "greeting", "s", "top o' the morning");
420
421   g_settings_delay (settings);
422
423   g_settings_set (settings, "greeting", "s", "greetings from test_delay_revert");
424
425   g_settings_get (settings, "greeting", "s", &str);
426   g_assert_cmpstr (str, ==, "greetings from test_delay_revert");
427   g_free (str);
428   str = NULL;
429
430   g_settings_get (settings2, "greeting", "s", &str);
431   g_assert_cmpstr (str, ==, "top o' the morning");
432   g_free (str);
433   str = NULL;
434
435   g_assert (g_settings_get_has_unapplied (settings));
436
437   g_settings_revert (settings);
438
439   g_assert (!g_settings_get_has_unapplied (settings));
440
441   g_settings_get (settings, "greeting", "s", &str);
442   g_assert_cmpstr (str, ==, "top o' the morning");
443   g_free (str);
444   str = NULL;
445
446   g_settings_get (settings2, "greeting", "s", &str);
447   g_assert_cmpstr (str, ==, "top o' the morning");
448   g_free (str);
449   str = NULL;
450
451   g_object_unref (settings2);
452   g_object_unref (settings);
453 }
454
455 static void
456 keys_changed_cb (GSettings    *settings,
457                  const GQuark *keys,
458                  gint          n_keys)
459 {
460   gchar *str;
461
462   g_assert_cmpint (n_keys, ==, 2);
463
464   g_assert ((keys[0] == g_quark_from_static_string ("greeting") &&
465              keys[1] == g_quark_from_static_string ("farewell")) ||
466             (keys[1] == g_quark_from_static_string ("greeting") &&
467              keys[0] == g_quark_from_static_string ("farewell")));
468
469   g_settings_get (settings, "greeting", "s", &str);
470   g_assert_cmpstr (str, ==, "greetings from test_atomic");
471   g_free (str);
472   str = NULL;
473
474   g_settings_get (settings, "farewell", "s", &str);
475   g_assert_cmpstr (str, ==, "atomic bye-bye");
476   g_free (str);
477   str = NULL;
478 }
479
480 /* Check that delay-applied changes appear atomically.
481  * More specifically, verify that all changed keys appear
482  * with their new value while handling the change-event signal.
483  */
484 static void
485 test_atomic (void)
486 {
487   GSettings *settings;
488   GSettings *settings2;
489   gchar *str;
490
491   settings = g_settings_new ("org.gtk.test");
492   settings2 = g_settings_new ("org.gtk.test");
493
494   g_settings_set (settings2, "greeting", "s", "top o' the morning");
495
496   changed_cb_called = FALSE;
497   changed_cb_called2 = FALSE;
498
499   g_signal_connect (settings2, "change-event",
500                     G_CALLBACK (keys_changed_cb), NULL);
501
502   g_settings_delay (settings);
503
504   g_settings_set (settings, "greeting", "s", "greetings from test_atomic");
505   g_settings_set (settings, "farewell", "s", "atomic bye-bye");
506
507   g_settings_apply (settings);
508
509   g_settings_get (settings, "greeting", "s", &str);
510   g_assert_cmpstr (str, ==, "greetings from test_atomic");
511   g_free (str);
512   str = NULL;
513
514   g_settings_get (settings, "farewell", "s", &str);
515   g_assert_cmpstr (str, ==, "atomic bye-bye");
516   g_free (str);
517   str = NULL;
518
519   g_settings_get (settings2, "greeting", "s", &str);
520   g_assert_cmpstr (str, ==, "greetings from test_atomic");
521   g_free (str);
522   str = NULL;
523
524   g_settings_get (settings2, "farewell", "s", &str);
525   g_assert_cmpstr (str, ==, "atomic bye-bye");
526   g_free (str);
527   str = NULL;
528
529   g_object_unref (settings2);
530   g_object_unref (settings);
531 }
532
533 /* Test that translations work for schema defaults.
534  *
535  * This test relies on the de.po file in the same directory
536  * to be compiled into ./de/LC_MESSAGES/test.mo
537  */
538 static void
539 test_l10n (void)
540 {
541   GSettings *settings;
542   gchar *str;
543   gchar *locale;
544
545   bindtextdomain ("test", ".");
546   bind_textdomain_codeset ("test", "UTF-8");
547
548   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
549
550   settings = g_settings_new ("org.gtk.test.localized");
551
552   setlocale (LC_MESSAGES, "C");
553   str = g_settings_get_string (settings, "error-message");
554   setlocale (LC_MESSAGES, locale);
555
556   g_assert_cmpstr (str, ==, "Unnamed");
557   g_free (str);
558   str = NULL;
559
560   setlocale (LC_MESSAGES, "de_DE");
561   str = g_settings_get_string (settings, "error-message");
562   setlocale (LC_MESSAGES, locale);
563
564   g_assert_cmpstr (str, ==, "Unbenannt");
565   g_object_unref (settings);
566   g_free (str);
567   str = NULL;
568
569   g_free (locale);
570 }
571
572 /* Test that message context works as expected with translated
573  * schema defaults. Also, verify that non-ASCII UTF-8 content
574  * works.
575  *
576  * This test relies on the de.po file in the same directory
577  * to be compiled into ./de/LC_MESSAGES/test.mo
578  */
579 static void
580 test_l10n_context (void)
581 {
582   GSettings *settings;
583   gchar *str;
584   gchar *locale;
585
586   bindtextdomain ("test", ".");
587   bind_textdomain_codeset ("test", "UTF-8");
588
589   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
590
591   settings = g_settings_new ("org.gtk.test.localized");
592
593   setlocale (LC_MESSAGES, "C");
594   g_settings_get (settings, "backspace", "s", &str);
595   setlocale (LC_MESSAGES, locale);
596
597   g_assert_cmpstr (str, ==, "BackSpace");
598   g_free (str);
599   str = NULL;
600
601   setlocale (LC_MESSAGES, "de_DE");
602   g_settings_get (settings, "backspace", "s", &str);
603   setlocale (LC_MESSAGES, locale);
604
605   g_assert_cmpstr (str, ==, "Löschen");
606   g_object_unref (settings);
607   g_free (str);
608   str = NULL;
609
610   g_free (locale);
611 }
612
613 enum
614 {
615   PROP_0,
616   PROP_BOOL,
617   PROP_INT,
618   PROP_DOUBLE,
619   PROP_STRING
620 };
621
622 typedef struct
623 {
624   GObject parent_instance;
625
626   gboolean bool_prop;
627   gint int_prop;
628   gdouble double_prop;
629   gchar *string_prop;
630 } TestObject;
631
632 typedef struct
633 {
634   GObjectClass parent_class;
635 } TestObjectClass;
636
637 G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
638
639 static void
640 test_object_init (TestObject *object)
641 {
642 }
643
644 static void
645 test_object_finalize (GObject *object)
646 {
647   TestObject *testo = (TestObject*)object;
648   g_free (testo->string_prop);
649   G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
650 }
651
652 static void
653 test_object_get_property (GObject    *object,
654                           guint       prop_id,
655                           GValue     *value,
656                           GParamSpec *pspec)
657 {
658   TestObject *test_object = (TestObject *)object;
659
660   switch (prop_id)
661     {
662     case PROP_BOOL:
663       g_value_set_boolean (value, test_object->bool_prop);
664       break;
665     case PROP_INT:
666       g_value_set_int (value, test_object->int_prop);
667       break;
668     case PROP_DOUBLE:
669       g_value_set_double (value, test_object->double_prop);
670       break;
671     case PROP_STRING:
672       g_value_set_string (value, test_object->string_prop);
673       break;
674     default:
675       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
676       break;
677     }
678 }
679
680 static void
681 test_object_set_property (GObject      *object,
682                           guint         prop_id,
683                           const GValue *value,
684                           GParamSpec   *pspec)
685 {
686   TestObject *test_object = (TestObject *)object;
687
688   switch (prop_id)
689     {
690     case PROP_BOOL:
691       test_object->bool_prop = g_value_get_boolean (value);
692       break;
693     case PROP_INT:
694       test_object->int_prop = g_value_get_int (value);
695       break;
696     case PROP_DOUBLE:
697       test_object->double_prop = g_value_get_double (value);
698       break;
699     case PROP_STRING:
700       g_free (test_object->string_prop);
701       test_object->string_prop = g_value_dup_string (value);
702       break;
703     default:
704       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
705       break;
706     }
707 }
708
709 static void
710 test_object_class_init (TestObjectClass *class)
711 {
712   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
713
714   gobject_class->get_property = test_object_get_property;
715   gobject_class->set_property = test_object_set_property;
716   gobject_class->finalize = test_object_finalize;
717
718   g_object_class_install_property (gobject_class, PROP_BOOL,
719     g_param_spec_boolean ("bool", "", "", FALSE, G_PARAM_READWRITE));
720   g_object_class_install_property (gobject_class, PROP_INT,
721     g_param_spec_int ("int", "", "", -G_MAXINT, G_MAXINT, 0, G_PARAM_READWRITE));
722   g_object_class_install_property (gobject_class, PROP_DOUBLE,
723     g_param_spec_double ("double", "", "", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE));
724   g_object_class_install_property (gobject_class, PROP_STRING,
725     g_param_spec_string ("string", "", "", NULL, G_PARAM_READWRITE));
726 }
727
728 static TestObject *
729 test_object_new (void)
730 {
731   return (TestObject*)g_object_new (test_object_get_type (), NULL);
732 }
733
734 /* Test basic binding functionality for simple types.
735  * Verify that with bidirectional bindings, changes on either side
736  * are notified on the other end.
737  */
738 static void
739 test_simple_binding (void)
740 {
741   TestObject *obj;
742   GSettings *settings;
743   gboolean b;
744   gint i;
745   gdouble d;
746   gchar *s;
747
748   settings = g_settings_new ("org.gtk.test.binding");
749   obj = test_object_new ();
750
751   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_DEFAULT);
752
753   g_object_set (obj, "bool", TRUE, NULL);
754   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
755
756   g_settings_set_boolean (settings, "bool", FALSE);
757   g_object_get (obj, "bool", &b, NULL);
758   g_assert_cmpint (b, ==, FALSE);
759
760   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
761
762   g_object_set (obj, "int", 12345, NULL);
763   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
764
765   g_settings_set_int (settings, "int", 54321);
766   g_object_get (obj, "int", &i, NULL);
767   g_assert_cmpint (i, ==, 54321);
768
769   g_settings_bind (settings, "string", obj, "string", G_SETTINGS_BIND_DEFAULT);
770
771   g_object_set (obj, "string", "bu ba", NULL);
772   s = g_settings_get_string (settings, "string");
773   g_assert_cmpstr (s, ==, "bu ba");
774   g_free (s);
775
776   g_settings_set_string (settings, "string", "bla bla");
777   g_object_get (obj, "string", &s, NULL);
778   g_assert_cmpstr (s, ==, "bla bla");
779   g_free (s);
780
781   g_settings_bind (settings, "double", obj, "double", G_SETTINGS_BIND_DEFAULT);
782
783   g_object_set (obj, "double", 203e7, NULL);
784   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, 203e7);
785
786   g_settings_set_double (settings, "double", 207e3);
787   g_object_get (obj, "double", &d, NULL);
788   g_assert_cmpfloat (d, ==, 207e3);
789
790   g_object_unref (obj);
791   g_object_unref (settings);
792 }
793
794 /* Test one-way bindings.
795  * Verify that changes on one side show up on the other,
796  * but not vice versa
797  */
798 static void
799 test_directional_binding (void)
800 {
801   TestObject *obj;
802   GSettings *settings;
803   gboolean b;
804   gint i;
805
806   settings = g_settings_new ("org.gtk.test.binding");
807   obj = test_object_new ();
808
809   g_object_set (obj, "bool", FALSE, NULL);
810   g_settings_set_boolean (settings, "bool", FALSE);
811
812   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET);
813
814   g_settings_set_boolean (settings, "bool", TRUE);
815   g_object_get (obj, "bool", &b, NULL);
816   g_assert_cmpint (b, ==, TRUE);
817
818   g_object_set (obj, "bool", FALSE, NULL);
819   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
820
821   g_object_set (obj, "int", 20, NULL);
822   g_settings_set_int (settings, "int", 20);
823
824   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_SET);
825
826   g_object_set (obj, "int", 32, NULL);
827   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 32);
828
829   g_settings_set_int (settings, "int", 20);
830   g_object_get (obj, "int", &i, NULL);
831   g_assert_cmpint (i, ==, 32);
832
833   g_object_unref (obj);
834   g_object_unref (settings);
835 }
836
837 /* Test that type mismatch is caught when creating a binding
838  */
839 static void
840 test_typesafe_binding (void)
841 {
842   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
843     {
844       TestObject *obj;
845       GSettings *settings;
846
847       settings = g_settings_new ("org.gtk.test.binding");
848       obj = test_object_new ();
849
850       g_settings_bind (settings, "string", obj, "int", G_SETTINGS_BIND_DEFAULT);
851
852       g_object_unref (obj);
853       g_object_unref (settings);
854     }
855   g_test_trap_assert_failed ();
856   g_test_trap_assert_stderr ("*not compatible*");
857 }
858
859 static gboolean
860 string_to_bool (GValue   *value,
861                 GVariant *variant,
862                 gpointer  user_data)
863 {
864   const gchar *s;
865
866   s = g_variant_get_string (variant, NULL);
867   g_value_set_boolean (value, g_strcmp0 (s, "true") == 0);
868
869   return TRUE;
870 }
871
872 static GVariant *
873 bool_to_string (const GValue       *value,
874                 const GVariantType *expected_type,
875                 gpointer            user_data)
876 {
877   if (g_value_get_boolean (value))
878     return g_variant_new_string ("true");
879   else
880     return g_variant_new_string ("false");
881 }
882
883 /* Test custom bindings.
884  * Translate strings to booleans and back
885  */
886 static void
887 test_custom_binding (void)
888 {
889   TestObject *obj;
890   GSettings *settings;
891   gchar *s;
892   gboolean b;
893
894   settings = g_settings_new ("org.gtk.test.binding");
895   obj = test_object_new ();
896
897   g_settings_set_string (settings, "string", "true");
898
899   g_settings_bind_with_mapping (settings, "string",
900                                 obj, "bool",
901                                 G_SETTINGS_BIND_DEFAULT,
902                                 string_to_bool,
903                                 bool_to_string,
904                                 NULL, NULL);
905
906   g_settings_set_string (settings, "string", "false");
907   g_object_get (obj, "bool", &b, NULL);
908   g_assert_cmpint (b, ==, FALSE);
909
910   g_settings_set_string (settings, "string", "not true");
911   g_object_get (obj, "bool", &b, NULL);
912   g_assert_cmpint (b, ==, FALSE);
913
914   g_object_set (obj, "bool", TRUE, NULL);
915   s = g_settings_get_string (settings, "string");
916   g_assert_cmpstr (s, ==, "true");
917
918   g_object_unref (obj);
919   g_object_unref (settings);
920 }
921
922 /* Test that with G_SETTINGS_BIND_NO_CHANGES, the
923  * initial settings value is transported to the object
924  * side, but later settings changes do not affect the
925  * object
926  */
927 static void
928 test_no_change_binding (void)
929 {
930   TestObject *obj;
931   GSettings *settings;
932   gboolean b;
933
934   settings = g_settings_new ("org.gtk.test.binding");
935   obj = test_object_new ();
936
937   g_object_set (obj, "bool", TRUE, NULL);
938   g_settings_set_boolean (settings, "bool", FALSE);
939
940   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET_NO_CHANGES);
941
942   g_object_get (obj, "bool", &b, NULL);
943   g_assert_cmpint (b, ==, FALSE);
944
945   g_settings_set_boolean (settings, "bool", TRUE);
946   g_object_get (obj, "bool", &b, NULL);
947   g_assert_cmpint (b, ==, FALSE);
948
949   g_settings_set_boolean (settings, "bool", FALSE);
950   g_object_set (obj, "bool", TRUE, NULL);
951   b = g_settings_get_boolean (settings, "bool");
952   g_assert_cmpint (b, ==, TRUE);
953
954   g_object_unref (obj);
955   g_object_unref (settings);
956 }
957
958 int
959 main (int argc, char *argv[])
960 {
961   g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
962   g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
963
964   g_remove ("./store");
965
966   g_type_init ();
967   g_test_init (&argc, &argv, NULL);
968
969   g_test_add_func ("/gsettings/basic", test_basic);
970   g_test_add_func ("/gsettings/no-schema", test_no_schema);
971   g_test_add_func ("/gsettings/unknown-key", test_unknown_key);
972   g_test_add_func ("/gsettings/wrong-type", test_wrong_type);
973   g_test_add_func ("/gsettings/basic-types", test_basic_types);
974   g_test_add_func ("/gsettings/complex-types", test_complex_types);
975   g_test_add_func ("/gsettings/changes", test_changes);
976   g_test_add_func ("/gsettings/l10n", test_l10n);
977   g_test_add_func ("/gsettings/l10n-context", test_l10n_context);
978   g_test_add_func ("/gsettings/delay-apply", test_delay_apply);
979   g_test_add_func ("/gsettings/delay-revert", test_delay_revert);
980   g_test_add_func ("/gsettings/atomic", test_atomic);
981   g_test_add_func ("/gsettings/simple-binding", test_simple_binding);
982   g_test_add_func ("/gsettings/directional-binding", test_directional_binding);
983   g_test_add_func ("/gsettings/typesafe-binding", test_typesafe_binding);
984   g_test_add_func ("/gsettings/custom-binding", test_custom_binding);
985   g_test_add_func ("/gsettings/no-change-binding", test_no_change_binding);
986
987   return g_test_run ();
988 }