• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdlib.h>
2 #include <locale.h>
3 #include <libintl.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <gio/gio.h>
7 #include <gstdio.h>
8 #define G_SETTINGS_ENABLE_BACKEND
9 #include <gio/gsettingsbackend.h>
10 
11 #include "testenum.h"
12 
13 static const gchar *locale_dir = ".";
14 
15 static gboolean backend_set;
16 
17 /* These tests rely on the schemas in org.gtk.test.gschema.xml
18  * to be compiled and installed in the same directory.
19  */
20 
21 typedef struct
22 {
23   gchar *tmp_dir;
24 } Fixture;
25 
26 static void
setup(Fixture * fixture,gconstpointer user_data)27 setup (Fixture       *fixture,
28        gconstpointer  user_data)
29 {
30   GError *error = NULL;
31 
32   fixture->tmp_dir = g_dir_make_tmp ("gio-test-gsettings_XXXXXX", &error);
33   g_assert_no_error (error);
34 
35   g_test_message ("Using temporary directory: %s", fixture->tmp_dir);
36 }
37 
38 static void
teardown(Fixture * fixture,gconstpointer user_data)39 teardown (Fixture       *fixture,
40           gconstpointer  user_data)
41 {
42   g_assert_cmpint (g_rmdir (fixture->tmp_dir), ==, 0);
43   g_clear_pointer (&fixture->tmp_dir, g_free);
44 }
45 
46 static void
check_and_free(GVariant * value,const gchar * expected)47 check_and_free (GVariant    *value,
48                 const gchar *expected)
49 {
50   gchar *printed;
51 
52   printed = g_variant_print (value, TRUE);
53   g_assert_cmpstr (printed, ==, expected);
54   g_free (printed);
55 
56   g_variant_unref (value);
57 }
58 
59 
60 /* Just to get warmed up: Read and set a string, and
61  * verify that can read the changed string back
62  */
63 static void
test_basic(void)64 test_basic (void)
65 {
66   gchar *str = NULL;
67   GObject *b;
68   gchar *path;
69   gboolean has_unapplied;
70   gboolean delay_apply;
71   GSettings *settings;
72 
73   settings = g_settings_new ("org.gtk.test");
74 
75   g_object_get (settings,
76                 "schema-id", &str,
77                 "backend", &b,
78                 "path", &path,
79                 "has-unapplied", &has_unapplied,
80                 "delay-apply", &delay_apply,
81                 NULL);
82   g_assert_cmpstr (str, ==, "org.gtk.test");
83   g_assert_nonnull (b);
84   g_assert_cmpstr (path, ==, "/tests/");
85   g_assert_false (has_unapplied);
86   g_assert_false (delay_apply);
87   g_free (str);
88   g_object_unref (b);
89   g_free (path);
90 
91   g_settings_get (settings, "greeting", "s", &str);
92   g_assert_cmpstr (str, ==, "Hello, earthlings");
93   g_free (str);
94 
95   g_settings_set (settings, "greeting", "s", "goodbye world");
96   g_settings_get (settings, "greeting", "s", &str);
97   g_assert_cmpstr (str, ==, "goodbye world");
98   g_free (str);
99   str = NULL;
100 
101   if (!backend_set && g_test_undefined ())
102     {
103       GSettings *tmp_settings = g_settings_new ("org.gtk.test");
104 
105       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
106                              "*g_settings_set_value*expects type*");
107       g_settings_set (tmp_settings, "greeting", "i", 555);
108       g_test_assert_expected_messages ();
109 
110       g_object_unref (tmp_settings);
111     }
112 
113   g_settings_get (settings, "greeting", "s", &str);
114   g_assert_cmpstr (str, ==, "goodbye world");
115   g_free (str);
116   str = NULL;
117 
118   g_settings_reset (settings, "greeting");
119   str = g_settings_get_string (settings, "greeting");
120   g_assert_cmpstr (str, ==, "Hello, earthlings");
121   g_free (str);
122 
123   g_settings_set (settings, "greeting", "s", "this is the end");
124   g_object_unref (settings);
125 }
126 
127 /* Check that we get an error when getting a key
128  * that is not in the schema
129  */
130 static void
test_unknown_key(void)131 test_unknown_key (void)
132 {
133   if (!g_test_undefined ())
134     return;
135 
136   if (g_test_subprocess ())
137     {
138       GSettings *settings;
139       GVariant *value;
140 
141       settings = g_settings_new ("org.gtk.test");
142       value = g_settings_get_value (settings, "no_such_key");
143 
144       g_assert_null (value);
145 
146       g_object_unref (settings);
147       return;
148     }
149   g_test_trap_subprocess (NULL, 0, 0);
150   g_test_trap_assert_failed ();
151   g_test_trap_assert_stderr ("*does not contain*");
152 }
153 
154 /* Check that we get an error when the schema
155  * has not been installed
156  */
157 static void
test_no_schema(void)158 test_no_schema (void)
159 {
160   if (!g_test_undefined ())
161     return;
162 
163   if (g_test_subprocess ())
164     {
165       GSettings *settings;
166 
167       settings = g_settings_new ("no.such.schema");
168 
169       g_assert_null (settings);
170       return;
171     }
172   g_test_trap_subprocess (NULL, 0, 0);
173   g_test_trap_assert_failed ();
174   g_test_trap_assert_stderr ("*Settings schema 'no.such.schema' is not installed*");
175 }
176 
177 /* Check that we get an error when passing a type string
178  * that does not match the schema
179  */
180 static void
test_wrong_type(void)181 test_wrong_type (void)
182 {
183   GSettings *settings;
184   gchar *str = NULL;
185 
186   if (!g_test_undefined ())
187     return;
188 
189   settings = g_settings_new ("org.gtk.test");
190 
191   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL,
192                          "*given value has a type of*");
193   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL,
194                          "*valid_format_string*");
195   g_settings_get (settings, "greeting", "o", &str);
196   g_test_assert_expected_messages ();
197 
198   g_assert_null (str);
199 
200   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
201                          "*expects type 's'*");
202   g_settings_set (settings, "greeting", "o", "/a/path");
203   g_test_assert_expected_messages ();
204 
205   g_object_unref (settings);
206 }
207 
208 /* Check errors with explicit paths */
209 static void
test_wrong_path(void)210 test_wrong_path (void)
211 {
212   if (!g_test_undefined ())
213     return;
214 
215   if (g_test_subprocess ())
216     {
217       GSettings *settings G_GNUC_UNUSED;
218 
219       settings = g_settings_new_with_path ("org.gtk.test", "/wrong-path/");
220       return;
221     }
222   g_test_trap_subprocess (NULL, 0, 0);
223   g_test_trap_assert_failed ();
224   g_test_trap_assert_stderr ("*but path * specified by schema*");
225 }
226 
227 static void
test_no_path(void)228 test_no_path (void)
229 {
230   if (!g_test_undefined ())
231     return;
232 
233   if (g_test_subprocess ())
234     {
235       GSettings *settings G_GNUC_UNUSED;
236 
237       settings = g_settings_new ("org.gtk.test.no-path");
238       return;
239     }
240   g_test_trap_subprocess (NULL, 0, 0);
241   g_test_trap_assert_failed ();
242   g_test_trap_assert_stderr ("*attempting to create schema * without a path**");
243 }
244 
245 
246 /* Check that we can successfully read and set the full
247  * range of all basic types
248  */
249 static void
test_basic_types(void)250 test_basic_types (void)
251 {
252   GSettings *settings;
253   gboolean b;
254   guint8 byte;
255   gint16 i16;
256   guint16 u16;
257   gint32 i32;
258   guint32 u32;
259   gint64 i64;
260   guint64 u64;
261   gdouble d;
262   gchar *str;
263 
264   settings = g_settings_new ("org.gtk.test.basic-types");
265 
266   g_settings_get (settings, "test-boolean", "b", &b);
267   g_assert_cmpint (b, ==, 1);
268 
269   g_settings_set (settings, "test-boolean", "b", 0);
270   g_settings_get (settings, "test-boolean", "b", &b);
271   g_assert_cmpint (b, ==, 0);
272 
273   g_settings_get (settings, "test-byte", "y", &byte);
274   g_assert_cmpint (byte, ==, 25);
275 
276   g_settings_set (settings, "test-byte", "y", G_MAXUINT8);
277   g_settings_get (settings, "test-byte", "y", &byte);
278   g_assert_cmpint (byte, ==, G_MAXUINT8);
279 
280   g_settings_get (settings, "test-int16", "n", &i16);
281   g_assert_cmpint (i16, ==, -1234);
282 
283   g_settings_set (settings, "test-int16", "n", G_MININT16);
284   g_settings_get (settings, "test-int16", "n", &i16);
285   g_assert_cmpint (i16, ==, G_MININT16);
286 
287   g_settings_set (settings, "test-int16", "n", G_MAXINT16);
288   g_settings_get (settings, "test-int16", "n", &i16);
289   g_assert_cmpint (i16, ==, G_MAXINT16);
290 
291   g_settings_get (settings, "test-uint16", "q", &u16);
292   g_assert_cmpuint (u16, ==, 1234);
293 
294   g_settings_set (settings, "test-uint16", "q", G_MAXUINT16);
295   g_settings_get (settings, "test-uint16", "q", &u16);
296   g_assert_cmpuint (u16, ==, G_MAXUINT16);
297 
298   g_settings_get (settings, "test-int32", "i", &i32);
299   g_assert_cmpint (i32, ==, -123456);
300 
301   g_settings_set (settings, "test-int32", "i", G_MININT32);
302   g_settings_get (settings, "test-int32", "i", &i32);
303   g_assert_cmpint (i32, ==, G_MININT32);
304 
305   g_settings_set (settings, "test-int32", "i", G_MAXINT32);
306   g_settings_get (settings, "test-int32", "i", &i32);
307   g_assert_cmpint (i32, ==, G_MAXINT32);
308 
309   g_settings_get (settings, "test-uint32", "u", &u32);
310   g_assert_cmpuint (u32, ==, 123456);
311 
312   g_settings_set (settings, "test-uint32", "u", G_MAXUINT32);
313   g_settings_get (settings, "test-uint32", "u", &u32);
314   g_assert_cmpuint (u32, ==, G_MAXUINT32);
315 
316   g_settings_get (settings, "test-int64", "x", &i64);
317   g_assert_cmpuint (i64, ==, -123456789);
318 
319   g_settings_set (settings, "test-int64", "x", G_MININT64);
320   g_settings_get (settings, "test-int64", "x", &i64);
321   g_assert_cmpuint (i64, ==, G_MININT64);
322 
323   g_settings_set (settings, "test-int64", "x", G_MAXINT64);
324   g_settings_get (settings, "test-int64", "x", &i64);
325   g_assert_cmpuint (i64, ==, G_MAXINT64);
326 
327   g_settings_get (settings, "test-uint64", "t", &u64);
328   g_assert_cmpuint (u64, ==, 123456789);
329 
330   g_settings_set (settings, "test-uint64", "t", G_MAXUINT64);
331   g_settings_get (settings, "test-uint64", "t", &u64);
332   g_assert_cmpuint (u64, ==, G_MAXUINT64);
333 
334   g_settings_get (settings, "test-double", "d", &d);
335   g_assert_cmpfloat (d, ==, 123.456);
336 
337   g_settings_set (settings, "test-double", "d", G_MINDOUBLE);
338   g_settings_get (settings, "test-double", "d", &d);
339   g_assert_cmpfloat (d, ==, G_MINDOUBLE);
340 
341   g_settings_set (settings, "test-double", "d", G_MAXDOUBLE);
342   g_settings_get (settings, "test-double", "d", &d);
343   g_assert_cmpfloat (d, ==, G_MAXDOUBLE);
344 
345   g_settings_get (settings, "test-string", "s", &str);
346   g_assert_cmpstr (str, ==, "a string, it seems");
347   g_free (str);
348   str = NULL;
349 
350   g_settings_get (settings, "test-objectpath", "o", &str);
351   g_assert_cmpstr (str, ==, "/a/object/path");
352   g_object_unref (settings);
353   g_free (str);
354   str = NULL;
355 }
356 
357 /* Check that we can read an set complex types like
358  * tuples, arrays and dictionaries
359  */
360 static void
test_complex_types(void)361 test_complex_types (void)
362 {
363   GSettings *settings;
364   gchar *s;
365   gint i1, i2;
366   GVariantIter *iter = NULL;
367   GVariant *v = NULL;
368 
369   settings = g_settings_new ("org.gtk.test.complex-types");
370 
371   g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
372   g_assert_cmpstr (s, ==, "one");
373   g_assert_cmpint (i1,==, 2);
374   g_assert_cmpint (i2,==, 3);
375   g_free (s) ;
376   s = NULL;
377 
378   g_settings_set (settings, "test-tuple", "(s(ii))", "none", 0, 0);
379   g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
380   g_assert_cmpstr (s, ==, "none");
381   g_assert_cmpint (i1,==, 0);
382   g_assert_cmpint (i2,==, 0);
383   g_free (s);
384   s = NULL;
385 
386   g_settings_get (settings, "test-array", "ai", &iter);
387   g_assert_cmpint (g_variant_iter_n_children (iter), ==, 6);
388   g_assert_true (g_variant_iter_next (iter, "i", &i1));
389   g_assert_cmpint (i1, ==, 0);
390   g_assert_true (g_variant_iter_next (iter, "i", &i1));
391   g_assert_cmpint (i1, ==, 1);
392   g_assert_true (g_variant_iter_next (iter, "i", &i1));
393   g_assert_cmpint (i1, ==, 2);
394   g_assert_true (g_variant_iter_next (iter, "i", &i1));
395   g_assert_cmpint (i1, ==, 3);
396   g_assert_true (g_variant_iter_next (iter, "i", &i1));
397   g_assert_cmpint (i1, ==, 4);
398   g_assert_true (g_variant_iter_next (iter, "i", &i1));
399   g_assert_cmpint (i1, ==, 5);
400   g_assert_false (g_variant_iter_next (iter, "i", &i1));
401   g_variant_iter_free (iter);
402 
403   g_settings_get (settings, "test-dict", "a{sau}", &iter);
404   g_assert_cmpint (g_variant_iter_n_children (iter), ==, 2);
405   g_assert_true (g_variant_iter_next (iter, "{&s@au}", &s, &v));
406   g_assert_cmpstr (s, ==, "AC");
407   g_assert_cmpstr ((char *)g_variant_get_type (v), ==, "au");
408   g_variant_unref (v);
409   g_assert_true (g_variant_iter_next (iter, "{&s@au}", &s, &v));
410   g_assert_cmpstr (s, ==, "IV");
411   g_assert_cmpstr ((char *)g_variant_get_type (v), ==, "au");
412   g_variant_unref (v);
413   g_variant_iter_free (iter);
414 
415   v = g_settings_get_value (settings, "test-dict");
416   g_assert_cmpstr ((char *)g_variant_get_type (v), ==, "a{sau}");
417   g_variant_unref (v);
418 
419   g_object_unref (settings);
420 }
421 
422 static gboolean changed_cb_called;
423 
424 static void
changed_cb(GSettings * settings,const gchar * key,gpointer data)425 changed_cb (GSettings   *settings,
426             const gchar *key,
427             gpointer     data)
428 {
429   changed_cb_called = TRUE;
430 
431   g_assert_cmpstr (key, ==, data);
432 }
433 
434 /* Test that basic change notification with the changed signal works.
435  */
436 static void
test_changes(void)437 test_changes (void)
438 {
439   GSettings *settings;
440   GSettings *settings2;
441 
442   settings = g_settings_new ("org.gtk.test");
443 
444   g_signal_connect (settings, "changed",
445                     G_CALLBACK (changed_cb), "greeting");
446 
447   changed_cb_called = FALSE;
448 
449   g_settings_set (settings, "greeting", "s", "new greeting");
450   g_assert_true (changed_cb_called);
451 
452   settings2 = g_settings_new ("org.gtk.test");
453 
454   changed_cb_called = FALSE;
455 
456   g_settings_set (settings2, "greeting", "s", "hi");
457   g_assert_true (changed_cb_called);
458 
459   g_object_unref (settings2);
460   g_object_unref (settings);
461 }
462 
463 static gboolean changed_cb_called2;
464 
465 static void
changed_cb2(GSettings * settings,const gchar * key,gpointer data)466 changed_cb2 (GSettings   *settings,
467              const gchar *key,
468              gpointer     data)
469 {
470   gboolean *p = data;
471 
472   *p = TRUE;
473 }
474 
475 /* Test that changes done to a delay-mode instance
476  * don't appear to the outside world until apply. Also
477  * check that we get change notification when they are
478  * applied.
479  * Also test that the has-unapplied property is properly
480  * maintained.
481  */
482 static void
test_delay_apply(void)483 test_delay_apply (void)
484 {
485   GSettings *settings;
486   GSettings *settings2;
487   gchar *str;
488   gboolean writable;
489   GVariant *v;
490   const gchar *s;
491 
492   settings = g_settings_new ("org.gtk.test");
493   settings2 = g_settings_new ("org.gtk.test");
494 
495   g_settings_set (settings2, "greeting", "s", "top o' the morning");
496 
497   changed_cb_called = FALSE;
498   changed_cb_called2 = FALSE;
499 
500   g_signal_connect (settings, "changed",
501                     G_CALLBACK (changed_cb2), &changed_cb_called);
502   g_signal_connect (settings2, "changed",
503                     G_CALLBACK (changed_cb2), &changed_cb_called2);
504 
505   g_settings_delay (settings);
506 
507   g_settings_set (settings, "greeting", "s", "greetings from test_delay_apply");
508 
509   g_assert_true (changed_cb_called);
510   g_assert_false (changed_cb_called2);
511 
512   /* Try resetting the key and ensure a notification is emitted on the delayed #GSettings object. */
513   changed_cb_called = FALSE;
514   changed_cb_called2 = FALSE;
515 
516   g_settings_reset (settings, "greeting");
517 
518   g_assert_true (changed_cb_called);
519   g_assert_false (changed_cb_called2);
520 
521   /* Locally change the greeting again. */
522   changed_cb_called = FALSE;
523   changed_cb_called2 = FALSE;
524 
525   g_settings_set (settings, "greeting", "s", "greetings from test_delay_apply");
526 
527   g_assert_true (changed_cb_called);
528   g_assert_false (changed_cb_called2);
529 
530   writable = g_settings_is_writable (settings, "greeting");
531   g_assert_true (writable);
532 
533   g_settings_get (settings, "greeting", "s", &str);
534   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
535   g_free (str);
536   str = NULL;
537 
538   v = g_settings_get_user_value (settings, "greeting");
539   s = g_variant_get_string (v, NULL);
540   g_assert_cmpstr (s, ==, "greetings from test_delay_apply");
541   g_variant_unref (v);
542 
543   g_settings_get (settings2, "greeting", "s", &str);
544   g_assert_cmpstr (str, ==, "top o' the morning");
545   g_free (str);
546   str = NULL;
547 
548   g_assert_true (g_settings_get_has_unapplied (settings));
549   g_assert_false (g_settings_get_has_unapplied (settings2));
550 
551   changed_cb_called = FALSE;
552   changed_cb_called2 = FALSE;
553 
554   g_settings_apply (settings);
555 
556   g_assert_false (changed_cb_called);
557   g_assert_true (changed_cb_called2);
558 
559   g_settings_get (settings, "greeting", "s", &str);
560   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
561   g_free (str);
562   str = NULL;
563 
564   g_settings_get (settings2, "greeting", "s", &str);
565   g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
566   g_free (str);
567   str = NULL;
568 
569   g_assert_false (g_settings_get_has_unapplied (settings));
570   g_assert_false (g_settings_get_has_unapplied (settings2));
571 
572   g_settings_reset (settings, "greeting");
573   g_settings_apply (settings);
574 
575   g_settings_get (settings, "greeting", "s", &str);
576   g_assert_cmpstr (str, ==, "Hello, earthlings");
577   g_free (str);
578 
579   g_object_unref (settings2);
580   g_object_unref (settings);
581 }
582 
583 /* Test that reverting unapplied changes in a delay-apply
584  * settings instance works.
585  */
586 static void
test_delay_revert(void)587 test_delay_revert (void)
588 {
589   GSettings *settings;
590   GSettings *settings2;
591   gchar *str;
592 
593   settings = g_settings_new ("org.gtk.test");
594   settings2 = g_settings_new ("org.gtk.test");
595 
596   g_settings_set (settings2, "greeting", "s", "top o' the morning");
597 
598   g_settings_get (settings, "greeting", "s", &str);
599   g_assert_cmpstr (str, ==, "top o' the morning");
600   g_free (str);
601 
602   g_settings_delay (settings);
603 
604   g_settings_set (settings, "greeting", "s", "greetings from test_delay_revert");
605 
606   g_settings_get (settings, "greeting", "s", &str);
607   g_assert_cmpstr (str, ==, "greetings from test_delay_revert");
608   g_free (str);
609   str = NULL;
610 
611   g_settings_get (settings2, "greeting", "s", &str);
612   g_assert_cmpstr (str, ==, "top o' the morning");
613   g_free (str);
614   str = NULL;
615 
616   g_assert_true (g_settings_get_has_unapplied (settings));
617 
618   g_settings_revert (settings);
619 
620   g_assert_false (g_settings_get_has_unapplied (settings));
621 
622   g_settings_get (settings, "greeting", "s", &str);
623   g_assert_cmpstr (str, ==, "top o' the morning");
624   g_free (str);
625   str = NULL;
626 
627   g_settings_get (settings2, "greeting", "s", &str);
628   g_assert_cmpstr (str, ==, "top o' the morning");
629   g_free (str);
630   str = NULL;
631 
632   g_object_unref (settings2);
633   g_object_unref (settings);
634 }
635 
636 static void
test_delay_child(void)637 test_delay_child (void)
638 {
639   GSettings *base;
640   GSettings *settings;
641   GSettings *child;
642   guint8 byte;
643   gboolean delay;
644 
645   base = g_settings_new ("org.gtk.test.basic-types");
646   g_settings_set (base, "test-byte", "y", 36);
647 
648   settings = g_settings_new ("org.gtk.test");
649   g_settings_delay (settings);
650   g_object_get (settings, "delay-apply", &delay, NULL);
651   g_assert_true (delay);
652 
653   child = g_settings_get_child (settings, "basic-types");
654   g_assert_nonnull (child);
655 
656   g_object_get (child, "delay-apply", &delay, NULL);
657   g_assert_false (delay);
658 
659   g_settings_get (child, "test-byte", "y", &byte);
660   g_assert_cmpuint (byte, ==, 36);
661 
662   g_settings_set (child, "test-byte", "y", 42);
663 
664   /* make sure the child was delayed too */
665   g_settings_get (base, "test-byte", "y", &byte);
666   g_assert_cmpuint (byte, ==, 36);
667 
668   g_object_unref (child);
669   g_object_unref (settings);
670   g_object_unref (base);
671 }
672 
673 static void
keys_changed_cb(GSettings * settings,const GQuark * keys,gint n_keys)674 keys_changed_cb (GSettings    *settings,
675                  const GQuark *keys,
676                  gint          n_keys)
677 {
678   gchar *str;
679 
680   g_assert_cmpint (n_keys, ==, 2);
681 
682   g_assert_true ((keys[0] == g_quark_from_static_string ("greeting") &&
683                   keys[1] == g_quark_from_static_string ("farewell")) ||
684                  (keys[1] == g_quark_from_static_string ("greeting") &&
685                   keys[0] == g_quark_from_static_string ("farewell")));
686 
687   g_settings_get (settings, "greeting", "s", &str);
688   g_assert_cmpstr (str, ==, "greetings from test_atomic");
689   g_free (str);
690   str = NULL;
691 
692   g_settings_get (settings, "farewell", "s", &str);
693   g_assert_cmpstr (str, ==, "atomic bye-bye");
694   g_free (str);
695   str = NULL;
696 }
697 
698 /* Check that delay-applied changes appear atomically.
699  * More specifically, verify that all changed keys appear
700  * with their new value while handling the change-event signal.
701  */
702 static void
test_atomic(void)703 test_atomic (void)
704 {
705   GSettings *settings;
706   GSettings *settings2;
707   gchar *str;
708 
709   settings = g_settings_new ("org.gtk.test");
710   settings2 = g_settings_new ("org.gtk.test");
711 
712   g_settings_set (settings2, "greeting", "s", "top o' the morning");
713 
714   changed_cb_called = FALSE;
715   changed_cb_called2 = FALSE;
716 
717   g_signal_connect (settings2, "change-event",
718                     G_CALLBACK (keys_changed_cb), NULL);
719 
720   g_settings_delay (settings);
721 
722   g_settings_set (settings, "greeting", "s", "greetings from test_atomic");
723   g_settings_set (settings, "farewell", "s", "atomic bye-bye");
724 
725   g_settings_apply (settings);
726 
727   g_settings_get (settings, "greeting", "s", &str);
728   g_assert_cmpstr (str, ==, "greetings from test_atomic");
729   g_free (str);
730   str = NULL;
731 
732   g_settings_get (settings, "farewell", "s", &str);
733   g_assert_cmpstr (str, ==, "atomic bye-bye");
734   g_free (str);
735   str = NULL;
736 
737   g_settings_get (settings2, "greeting", "s", &str);
738   g_assert_cmpstr (str, ==, "greetings from test_atomic");
739   g_free (str);
740   str = NULL;
741 
742   g_settings_get (settings2, "farewell", "s", &str);
743   g_assert_cmpstr (str, ==, "atomic bye-bye");
744   g_free (str);
745   str = NULL;
746 
747   g_object_unref (settings2);
748   g_object_unref (settings);
749 }
750 
751 /* On Windows the interaction between the C library locale and libintl
752  * (from GNU gettext) is not like on POSIX, so just skip these tests
753  * for now.
754  *
755  * There are several issues:
756  *
757  * 1) The C library doesn't use LC_MESSAGES, that is implemented only
758  * in libintl (defined in its <libintl.h>).
759  *
760  * 2) The locale names that setlocale() accepts and returns aren't in
761  * the "de_DE" style, but like "German_Germany".
762  *
763  * 3) libintl looks at the Win32 thread locale and not the C library
764  * locale. (And even if libintl would use the C library's locale, as
765  * there are several alternative C library DLLs, libintl might be
766  * linked to a different one than the application code, so they
767  * wouldn't have the same C library locale anyway.)
768  */
769 
770 /* Test that translations work for schema defaults.
771  *
772  * This test relies on the de.po file in the same directory
773  * to be compiled into ./de/LC_MESSAGES/test.mo
774  */
775 static void
test_l10n(void)776 test_l10n (void)
777 {
778   GSettings *settings;
779   gchar *str;
780   gchar *locale;
781 
782   bindtextdomain ("test", locale_dir);
783   bind_textdomain_codeset ("test", "UTF-8");
784 
785   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
786 
787   settings = g_settings_new ("org.gtk.test.localized");
788 
789   g_setenv ("LC_MESSAGES", "C", TRUE);
790   setlocale (LC_MESSAGES, "C");
791   str = g_settings_get_string (settings, "error-message");
792   g_setenv ("LC_MESSAGES", locale, TRUE);
793   setlocale (LC_MESSAGES, locale);
794 
795   g_assert_cmpstr (str, ==, "Unnamed");
796   g_free (str);
797   str = NULL;
798 
799   g_setenv ("LC_MESSAGES", "de_DE.UTF-8", TRUE);
800   setlocale (LC_MESSAGES, "de_DE.UTF-8");
801   /* Only do the test if translation is actually working... */
802   if (g_str_equal (dgettext ("test", "\"Unnamed\""), "\"Unbenannt\""))
803     {
804       str = g_settings_get_string (settings, "error-message");
805 
806       g_assert_cmpstr (str, ==, "Unbenannt");
807       g_free (str);
808       str = NULL;
809     }
810   else
811     g_printerr ("warning: translation is not working... skipping test. ");
812 
813   g_setenv ("LC_MESSAGES", locale, TRUE);
814   setlocale (LC_MESSAGES, locale);
815   g_free (locale);
816   g_object_unref (settings);
817 }
818 
819 /* Test that message context works as expected with translated
820  * schema defaults. Also, verify that non-ASCII UTF-8 content
821  * works.
822  *
823  * This test relies on the de.po file in the same directory
824  * to be compiled into ./de/LC_MESSAGES/test.mo
825  */
826 static void
test_l10n_context(void)827 test_l10n_context (void)
828 {
829   GSettings *settings;
830   gchar *str;
831   gchar *locale;
832 
833   bindtextdomain ("test", locale_dir);
834   bind_textdomain_codeset ("test", "UTF-8");
835 
836   locale = g_strdup (setlocale (LC_MESSAGES, NULL));
837 
838   settings = g_settings_new ("org.gtk.test.localized");
839 
840   g_setenv ("LC_MESSAGES", "C", TRUE);
841   setlocale (LC_MESSAGES, "C");
842   g_settings_get (settings, "backspace", "s", &str);
843   g_setenv ("LC_MESSAGES", locale, TRUE);
844   setlocale (LC_MESSAGES, locale);
845 
846   g_assert_cmpstr (str, ==, "BackSpace");
847   g_free (str);
848   str = NULL;
849 
850   g_setenv ("LC_MESSAGES", "de_DE.UTF-8", TRUE);
851   setlocale (LC_MESSAGES, "de_DE.UTF-8");
852   /* Only do the test if translation is actually working... */
853   if (g_str_equal (dgettext ("test", "\"Unnamed\""), "\"Unbenannt\""))
854     {
855       g_settings_get (settings, "backspace", "s", &str);
856 
857       g_assert_cmpstr (str, ==, "Löschen");
858       g_free (str);
859       str = NULL;
860     }
861   else
862     g_printerr ("warning: translation is not working... skipping test.  ");
863 
864   g_setenv ("LC_MESSAGES", locale, TRUE);
865   setlocale (LC_MESSAGES, locale);
866   g_free (locale);
867   g_object_unref (settings);
868 }
869 
870 enum
871 {
872   PROP_0,
873   PROP_BOOL,
874   PROP_ANTI_BOOL,
875   PROP_BYTE,
876   PROP_INT16,
877   PROP_UINT16,
878   PROP_INT,
879   PROP_UINT,
880   PROP_INT64,
881   PROP_UINT64,
882   PROP_DOUBLE,
883   PROP_STRING,
884   PROP_NO_READ,
885   PROP_NO_WRITE,
886   PROP_STRV,
887   PROP_ENUM,
888   PROP_FLAGS
889 };
890 
891 typedef struct
892 {
893   GObject parent_instance;
894 
895   gboolean bool_prop;
896   gboolean anti_bool_prop;
897   gint8 byte_prop;
898   gint int16_prop;
899   guint16 uint16_prop;
900   gint int_prop;
901   guint uint_prop;
902   gint64 int64_prop;
903   guint64 uint64_prop;
904   gdouble double_prop;
905   gchar *string_prop;
906   gchar *no_read_prop;
907   gchar *no_write_prop;
908   gchar **strv_prop;
909   guint enum_prop;
910   guint flags_prop;
911 } TestObject;
912 
913 typedef struct
914 {
915   GObjectClass parent_class;
916 } TestObjectClass;
917 
918 static GType test_object_get_type (void);
G_DEFINE_TYPE(TestObject,test_object,G_TYPE_OBJECT)919 G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
920 
921 static void
922 test_object_init (TestObject *object)
923 {
924 }
925 
926 static void
test_object_finalize(GObject * object)927 test_object_finalize (GObject *object)
928 {
929   TestObject *testo = (TestObject*)object;
930   g_strfreev (testo->strv_prop);
931   g_free (testo->string_prop);
932   G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
933 }
934 
935 static void
test_object_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)936 test_object_get_property (GObject    *object,
937                           guint       prop_id,
938                           GValue     *value,
939                           GParamSpec *pspec)
940 {
941   TestObject *test_object = (TestObject *)object;
942 
943   switch (prop_id)
944     {
945     case PROP_BOOL:
946       g_value_set_boolean (value, test_object->bool_prop);
947       break;
948     case PROP_ANTI_BOOL:
949       g_value_set_boolean (value, test_object->anti_bool_prop);
950       break;
951     case PROP_BYTE:
952       g_value_set_schar (value, test_object->byte_prop);
953       break;
954     case PROP_UINT16:
955       g_value_set_uint (value, test_object->uint16_prop);
956       break;
957     case PROP_INT16:
958       g_value_set_int (value, test_object->int16_prop);
959       break;
960     case PROP_INT:
961       g_value_set_int (value, test_object->int_prop);
962       break;
963     case PROP_UINT:
964       g_value_set_uint (value, test_object->uint_prop);
965       break;
966     case PROP_INT64:
967       g_value_set_int64 (value, test_object->int64_prop);
968       break;
969     case PROP_UINT64:
970       g_value_set_uint64 (value, test_object->uint64_prop);
971       break;
972     case PROP_DOUBLE:
973       g_value_set_double (value, test_object->double_prop);
974       break;
975     case PROP_STRING:
976       g_value_set_string (value, test_object->string_prop);
977       break;
978     case PROP_NO_WRITE:
979       g_value_set_string (value, test_object->no_write_prop);
980       break;
981     case PROP_STRV:
982       g_value_set_boxed (value, test_object->strv_prop);
983       break;
984     case PROP_ENUM:
985       g_value_set_enum (value, test_object->enum_prop);
986       break;
987     case PROP_FLAGS:
988       g_value_set_flags (value, test_object->flags_prop);
989       break;
990     default:
991       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
992       break;
993     }
994 }
995 
996 static void
test_object_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)997 test_object_set_property (GObject      *object,
998                           guint         prop_id,
999                           const GValue *value,
1000                           GParamSpec   *pspec)
1001 {
1002   TestObject *test_object = (TestObject *)object;
1003 
1004   switch (prop_id)
1005     {
1006     case PROP_BOOL:
1007       test_object->bool_prop = g_value_get_boolean (value);
1008       break;
1009     case PROP_ANTI_BOOL:
1010       test_object->anti_bool_prop = g_value_get_boolean (value);
1011       break;
1012     case PROP_BYTE:
1013       test_object->byte_prop = g_value_get_schar (value);
1014       break;
1015     case PROP_INT16:
1016       test_object->int16_prop = g_value_get_int (value);
1017       break;
1018     case PROP_UINT16:
1019       test_object->uint16_prop = g_value_get_uint (value);
1020       break;
1021     case PROP_INT:
1022       test_object->int_prop = g_value_get_int (value);
1023       break;
1024     case PROP_UINT:
1025       test_object->uint_prop = g_value_get_uint (value);
1026       break;
1027     case PROP_INT64:
1028       test_object->int64_prop = g_value_get_int64 (value);
1029       break;
1030     case PROP_UINT64:
1031       test_object->uint64_prop = g_value_get_uint64 (value);
1032       break;
1033     case PROP_DOUBLE:
1034       test_object->double_prop = g_value_get_double (value);
1035       break;
1036     case PROP_STRING:
1037       g_free (test_object->string_prop);
1038       test_object->string_prop = g_value_dup_string (value);
1039       break;
1040     case PROP_NO_READ:
1041       g_free (test_object->no_read_prop);
1042       test_object->no_read_prop = g_value_dup_string (value);
1043       break;
1044     case PROP_STRV:
1045       g_strfreev (test_object->strv_prop);
1046       test_object->strv_prop = g_value_dup_boxed (value);
1047       break;
1048     case PROP_ENUM:
1049       test_object->enum_prop = g_value_get_enum (value);
1050       break;
1051     case PROP_FLAGS:
1052       test_object->flags_prop = g_value_get_flags (value);
1053       break;
1054     default:
1055       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1056       break;
1057     }
1058 }
1059 
1060 static GType
test_enum_get_type(void)1061 test_enum_get_type (void)
1062 {
1063   static volatile gsize define_type_id = 0;
1064 
1065   if (g_once_init_enter (&define_type_id))
1066     {
1067       static const GEnumValue values[] = {
1068         { TEST_ENUM_FOO, "TEST_ENUM_FOO", "foo" },
1069         { TEST_ENUM_BAR, "TEST_ENUM_BAR", "bar" },
1070         { TEST_ENUM_BAZ, "TEST_ENUM_BAZ", "baz" },
1071         { TEST_ENUM_QUUX, "TEST_ENUM_QUUX", "quux" },
1072         { 0, NULL, NULL }
1073       };
1074 
1075       GType type_id = g_enum_register_static ("TestEnum", values);
1076       g_once_init_leave (&define_type_id, type_id);
1077     }
1078 
1079   return define_type_id;
1080 }
1081 
1082 static GType
test_flags_get_type(void)1083 test_flags_get_type (void)
1084 {
1085   static volatile gsize define_type_id = 0;
1086 
1087   if (g_once_init_enter (&define_type_id))
1088     {
1089       static const GFlagsValue values[] = {
1090         { TEST_FLAGS_NONE, "TEST_FLAGS_NONE", "none" },
1091         { TEST_FLAGS_MOURNING, "TEST_FLAGS_MOURNING", "mourning" },
1092         { TEST_FLAGS_LAUGHING, "TEST_FLAGS_LAUGHING", "laughing" },
1093         { TEST_FLAGS_WALKING, "TEST_FLAGS_WALKING", "walking" },
1094         { 0, NULL, NULL }
1095       };
1096 
1097       GType type_id = g_flags_register_static ("TestFlags", values);
1098       g_once_init_leave (&define_type_id, type_id);
1099     }
1100 
1101   return define_type_id;
1102 }
1103 
1104 static void
test_object_class_init(TestObjectClass * class)1105 test_object_class_init (TestObjectClass *class)
1106 {
1107   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
1108 
1109   gobject_class->get_property = test_object_get_property;
1110   gobject_class->set_property = test_object_set_property;
1111   gobject_class->finalize = test_object_finalize;
1112 
1113   g_object_class_install_property (gobject_class, PROP_BOOL,
1114     g_param_spec_boolean ("bool", "", "", FALSE, G_PARAM_READWRITE));
1115   g_object_class_install_property (gobject_class, PROP_ANTI_BOOL,
1116     g_param_spec_boolean ("anti-bool", "", "", FALSE, G_PARAM_READWRITE));
1117   g_object_class_install_property (gobject_class, PROP_BYTE,
1118     g_param_spec_char ("byte", "", "", G_MININT8, G_MAXINT8, 0, G_PARAM_READWRITE));
1119   g_object_class_install_property (gobject_class, PROP_INT16,
1120     g_param_spec_int ("int16", "", "", -G_MAXINT16, G_MAXINT16, 0, G_PARAM_READWRITE));
1121   g_object_class_install_property (gobject_class, PROP_UINT16,
1122     g_param_spec_uint ("uint16", "", "", 0, G_MAXUINT16, 0, G_PARAM_READWRITE));
1123   g_object_class_install_property (gobject_class, PROP_INT,
1124     g_param_spec_int ("int", "", "", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
1125   g_object_class_install_property (gobject_class, PROP_UINT,
1126     g_param_spec_uint ("uint", "", "", 0, G_MAXUINT, 0, G_PARAM_READWRITE));
1127   g_object_class_install_property (gobject_class, PROP_INT64,
1128     g_param_spec_int64 ("int64", "", "", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE));
1129   g_object_class_install_property (gobject_class, PROP_UINT64,
1130     g_param_spec_uint64 ("uint64", "", "", 0, G_MAXUINT64, 0, G_PARAM_READWRITE));
1131   g_object_class_install_property (gobject_class, PROP_DOUBLE,
1132     g_param_spec_double ("double", "", "", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE));
1133   g_object_class_install_property (gobject_class, PROP_STRING,
1134     g_param_spec_string ("string", "", "", NULL, G_PARAM_READWRITE));
1135   g_object_class_install_property (gobject_class, PROP_NO_WRITE,
1136     g_param_spec_string ("no-write", "", "", NULL, G_PARAM_READABLE));
1137   g_object_class_install_property (gobject_class, PROP_NO_READ,
1138     g_param_spec_string ("no-read", "", "", NULL, G_PARAM_WRITABLE));
1139   g_object_class_install_property (gobject_class, PROP_STRV,
1140     g_param_spec_boxed ("strv", "", "", G_TYPE_STRV, G_PARAM_READWRITE));
1141   g_object_class_install_property (gobject_class, PROP_ENUM,
1142     g_param_spec_enum ("enum", "", "", test_enum_get_type (), TEST_ENUM_FOO, G_PARAM_READWRITE));
1143   g_object_class_install_property (gobject_class, PROP_FLAGS,
1144     g_param_spec_flags ("flags", "", "", test_flags_get_type (), TEST_FLAGS_NONE, G_PARAM_READWRITE));
1145 }
1146 
1147 static TestObject *
test_object_new(void)1148 test_object_new (void)
1149 {
1150   return (TestObject*)g_object_new (test_object_get_type (), NULL);
1151 }
1152 
1153 /* Test basic binding functionality for simple types.
1154  * Verify that with bidirectional bindings, changes on either side
1155  * are notified on the other end.
1156  */
1157 static void
test_simple_binding(void)1158 test_simple_binding (void)
1159 {
1160   TestObject *obj;
1161   GSettings *settings;
1162   gboolean b;
1163   gchar y;
1164   gint i;
1165   guint u;
1166   gint16 n;
1167   guint16 q;
1168   gint n2;
1169   guint q2;
1170   gint64 i64;
1171   guint64 u64;
1172   gdouble d;
1173   gchar *s;
1174   GVariant *value;
1175   gchar **strv;
1176 
1177   settings = g_settings_new ("org.gtk.test.binding");
1178   obj = test_object_new ();
1179 
1180   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_DEFAULT);
1181   g_object_set (obj, "bool", TRUE, NULL);
1182   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
1183 
1184   g_settings_set_boolean (settings, "bool", FALSE);
1185   b = TRUE;
1186   g_object_get (obj, "bool", &b, NULL);
1187   g_assert_cmpint (b, ==, FALSE);
1188 
1189   g_settings_bind (settings, "anti-bool", obj, "anti-bool",
1190                    G_SETTINGS_BIND_INVERT_BOOLEAN);
1191   g_object_set (obj, "anti-bool", FALSE, NULL);
1192   g_assert_cmpint (g_settings_get_boolean (settings, "anti-bool"), ==, TRUE);
1193 
1194   g_settings_set_boolean (settings, "anti-bool", FALSE);
1195   b = FALSE;
1196   g_object_get (obj, "anti-bool", &b, NULL);
1197   g_assert_cmpint (b, ==, TRUE);
1198 
1199   g_settings_bind (settings, "byte", obj, "byte", G_SETTINGS_BIND_DEFAULT);
1200 
1201   g_object_set (obj, "byte", 123, NULL);
1202   y = 'c';
1203   g_settings_get (settings, "byte", "y", &y);
1204   g_assert_cmpint (y, ==, 123);
1205 
1206   g_settings_set (settings, "byte", "y", 54);
1207   y = 'c';
1208   g_object_get (obj, "byte", &y, NULL);
1209   g_assert_cmpint (y, ==, 54);
1210 
1211   g_settings_bind (settings, "int16", obj, "int16", G_SETTINGS_BIND_DEFAULT);
1212 
1213   g_object_set (obj, "int16", 1234, NULL);
1214   n = 4321;
1215   g_settings_get (settings, "int16", "n", &n);
1216   g_assert_cmpint (n, ==, 1234);
1217 
1218   g_settings_set (settings, "int16", "n", 4321);
1219   n2 = 1111;
1220   g_object_get (obj, "int16", &n2, NULL);
1221   g_assert_cmpint (n2, ==, 4321);
1222 
1223   g_settings_bind (settings, "uint16", obj, "uint16", G_SETTINGS_BIND_DEFAULT);
1224 
1225   g_object_set (obj, "uint16", (guint16) G_MAXUINT16, NULL);
1226   q = 1111;
1227   g_settings_get (settings, "uint16", "q", &q);
1228   g_assert_cmpuint (q, ==, G_MAXUINT16);
1229 
1230   g_settings_set (settings, "uint16", "q", (guint16) G_MAXINT16);
1231   q2 = 1111;
1232   g_object_get (obj, "uint16", &q2, NULL);
1233   g_assert_cmpuint (q2, ==, (guint16) G_MAXINT16);
1234 
1235   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
1236 
1237   g_object_set (obj, "int", 12345, NULL);
1238   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1239 
1240   g_settings_set_int (settings, "int", 54321);
1241   i = 1111;
1242   g_object_get (obj, "int", &i, NULL);
1243   g_assert_cmpint (i, ==, 54321);
1244 
1245   g_settings_bind (settings, "uint", obj, "uint", G_SETTINGS_BIND_DEFAULT);
1246 
1247   g_object_set (obj, "uint", 12345, NULL);
1248   g_assert_cmpuint (g_settings_get_uint (settings, "uint"), ==, 12345);
1249 
1250   g_settings_set_uint (settings, "uint", 54321);
1251   u = 1111;
1252   g_object_get (obj, "uint", &u, NULL);
1253   g_assert_cmpuint (u, ==, 54321);
1254 
1255   g_settings_bind (settings, "uint64", obj, "uint64", G_SETTINGS_BIND_DEFAULT);
1256 
1257   g_object_set (obj, "uint64", (guint64) 12345, NULL);
1258   g_assert_cmpuint (g_settings_get_uint64 (settings, "uint64"), ==, 12345);
1259 
1260   g_settings_set_uint64 (settings, "uint64", 54321);
1261   u64 = 1111;
1262   g_object_get (obj, "uint64", &u64, NULL);
1263   g_assert_cmpuint (u64, ==, 54321);
1264 
1265   g_settings_bind (settings, "int64", obj, "int64", G_SETTINGS_BIND_DEFAULT);
1266 
1267   g_object_set (obj, "int64", (gint64) G_MAXINT64, NULL);
1268   i64 = 1111;
1269   g_settings_get (settings, "int64", "x", &i64);
1270   g_assert_cmpint (i64, ==, G_MAXINT64);
1271 
1272   g_settings_set (settings, "int64", "x", (gint64) G_MININT64);
1273   i64 = 1111;
1274   g_object_get (obj, "int64", &i64, NULL);
1275   g_assert_cmpint (i64, ==, G_MININT64);
1276 
1277   g_settings_bind (settings, "uint64", obj, "uint64", G_SETTINGS_BIND_DEFAULT);
1278 
1279   g_object_set (obj, "uint64", (guint64) G_MAXUINT64, NULL);
1280   u64 = 1111;
1281   g_settings_get (settings, "uint64", "t", &u64);
1282   g_assert_cmpuint (u64, ==, G_MAXUINT64);
1283 
1284   g_settings_set (settings, "uint64", "t", (guint64) G_MAXINT64);
1285   u64 = 1111;
1286   g_object_get (obj, "uint64", &u64, NULL);
1287   g_assert_cmpuint (u64, ==, (guint64) G_MAXINT64);
1288 
1289   g_settings_bind (settings, "string", obj, "string", G_SETTINGS_BIND_DEFAULT);
1290 
1291   g_object_set (obj, "string", "bu ba", NULL);
1292   s = g_settings_get_string (settings, "string");
1293   g_assert_cmpstr (s, ==, "bu ba");
1294   g_free (s);
1295 
1296   g_settings_set_string (settings, "string", "bla bla");
1297   g_object_get (obj, "string", &s, NULL);
1298   g_assert_cmpstr (s, ==, "bla bla");
1299   g_free (s);
1300 
1301   g_settings_bind (settings, "chararray", obj, "string", G_SETTINGS_BIND_DEFAULT);
1302 
1303   g_object_set (obj, "string", "non-unicode:\315", NULL);
1304   value = g_settings_get_value (settings, "chararray");
1305   g_assert_cmpstr (g_variant_get_bytestring (value), ==, "non-unicode:\315");
1306   g_variant_unref (value);
1307 
1308   g_settings_bind (settings, "double", obj, "double", G_SETTINGS_BIND_DEFAULT);
1309 
1310   g_object_set (obj, "double", G_MAXFLOAT, NULL);
1311   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXFLOAT);
1312 
1313   g_settings_set_double (settings, "double", G_MINFLOAT);
1314   d = 1.0;
1315   g_object_get (obj, "double", &d, NULL);
1316   g_assert_cmpfloat (d, ==, G_MINFLOAT);
1317 
1318   g_object_set (obj, "double", G_MAXDOUBLE, NULL);
1319   g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXDOUBLE);
1320 
1321   g_settings_set_double (settings, "double", -G_MINDOUBLE);
1322   d = 1.0;
1323   g_object_get (obj, "double", &d, NULL);
1324   g_assert_cmpfloat (d, ==, -G_MINDOUBLE);
1325 
1326   strv = g_strsplit ("plastic bag,middle class,polyethylene", ",", 0);
1327   g_settings_bind (settings, "strv", obj, "strv", G_SETTINGS_BIND_DEFAULT);
1328   g_object_set (obj, "strv", strv, NULL);
1329   g_strfreev (strv);
1330   strv = g_settings_get_strv (settings, "strv");
1331   s = g_strjoinv (",", strv);
1332   g_assert_cmpstr (s, ==, "plastic bag,middle class,polyethylene");
1333   g_strfreev (strv);
1334   g_free (s);
1335   strv = g_strsplit ("decaffeinate,unleaded,keep all surfaces clean", ",", 0);
1336   g_settings_set_strv (settings, "strv", (const gchar **) strv);
1337   g_strfreev (strv);
1338   g_object_get (obj, "strv", &strv, NULL);
1339   s = g_strjoinv (",", strv);
1340   g_assert_cmpstr (s, ==, "decaffeinate,unleaded,keep all surfaces clean");
1341   g_strfreev (strv);
1342   g_free (s);
1343   g_settings_set_strv (settings, "strv", NULL);
1344   g_object_get (obj, "strv", &strv, NULL);
1345   g_assert_nonnull (strv);
1346   g_assert_cmpint (g_strv_length (strv), ==, 0);
1347   g_strfreev (strv);
1348 
1349   g_settings_bind (settings, "enum", obj, "enum", G_SETTINGS_BIND_DEFAULT);
1350   g_object_set (obj, "enum", TEST_ENUM_BAZ, NULL);
1351   s = g_settings_get_string (settings, "enum");
1352   g_assert_cmpstr (s, ==, "baz");
1353   g_free (s);
1354   g_assert_cmpint (g_settings_get_enum (settings, "enum"), ==, TEST_ENUM_BAZ);
1355 
1356   g_settings_set_enum (settings, "enum", TEST_ENUM_QUUX);
1357   i = 230;
1358   g_object_get (obj, "enum", &i, NULL);
1359   g_assert_cmpint (i, ==, TEST_ENUM_QUUX);
1360 
1361   g_settings_set_string (settings, "enum", "baz");
1362   i = 230;
1363   g_object_get (obj, "enum", &i, NULL);
1364   g_assert_cmpint (i, ==, TEST_ENUM_BAZ);
1365 
1366   g_settings_bind (settings, "flags", obj, "flags", G_SETTINGS_BIND_DEFAULT);
1367   g_object_set (obj, "flags", TEST_FLAGS_MOURNING, NULL);
1368   strv = g_settings_get_strv (settings, "flags");
1369   g_assert_cmpint (g_strv_length (strv), ==, 1);
1370   g_assert_cmpstr (strv[0], ==, "mourning");
1371   g_strfreev (strv);
1372 
1373   g_assert_cmpint (g_settings_get_flags (settings, "flags"), ==, TEST_FLAGS_MOURNING);
1374 
1375   g_settings_set_flags (settings, "flags", TEST_FLAGS_MOURNING | TEST_FLAGS_WALKING);
1376   i = 230;
1377   g_object_get (obj, "flags", &i, NULL);
1378   g_assert_cmpint (i, ==, TEST_FLAGS_MOURNING | TEST_FLAGS_WALKING);
1379 
1380   g_settings_bind (settings, "uint", obj, "uint", G_SETTINGS_BIND_DEFAULT);
1381 
1382   g_object_set (obj, "uint", 12345, NULL);
1383   g_assert_cmpuint (g_settings_get_uint (settings, "uint"), ==, 12345);
1384 
1385   g_settings_set_uint (settings, "uint", 54321);
1386   u = 1111;
1387   g_object_get (obj, "uint", &u, NULL);
1388   g_assert_cmpuint (u, ==, 54321);
1389 
1390   g_settings_bind (settings, "range", obj, "uint", G_SETTINGS_BIND_DEFAULT);
1391   g_object_set (obj, "uint", 22, NULL);
1392   u = 1111;
1393   g_assert_cmpuint (g_settings_get_uint (settings, "range"), ==, 22);
1394   g_object_get (obj, "uint", &u, NULL);
1395   g_assert_cmpuint (u, ==, 22);
1396 
1397   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1398                          "* is out of schema-specified range for*");
1399   g_object_set (obj, "uint", 45, NULL);
1400   g_test_assert_expected_messages ();
1401   u = 1111;
1402   g_object_get (obj, "uint", &u, NULL);
1403   g_assert_cmpuint (g_settings_get_uint (settings, "range"), ==, 22);
1404   /* The value of the object is currently not reset back to its initial value
1405   g_assert_cmpuint (u, ==, 22); */
1406 
1407   g_object_unref (obj);
1408   g_object_unref (settings);
1409 }
1410 
1411 static void
test_unbind(void)1412 test_unbind (void)
1413 {
1414   TestObject *obj;
1415   GSettings *settings;
1416 
1417   settings = g_settings_new ("org.gtk.test.binding");
1418   obj = test_object_new ();
1419 
1420   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_DEFAULT);
1421 
1422   g_object_set (obj, "int", 12345, NULL);
1423   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1424 
1425   g_settings_unbind (obj, "int");
1426 
1427   g_object_set (obj, "int", 54321, NULL);
1428   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1429 
1430   g_object_unref (obj);
1431   g_object_unref (settings);
1432 }
1433 
1434 static void
test_bind_writable(void)1435 test_bind_writable (void)
1436 {
1437   TestObject *obj;
1438   GSettings *settings;
1439   gboolean b;
1440 
1441   settings = g_settings_new ("org.gtk.test.binding");
1442   obj = test_object_new ();
1443 
1444   g_object_set (obj, "bool", FALSE, NULL);
1445 
1446   g_settings_bind_writable (settings, "int", obj, "bool", FALSE);
1447 
1448   g_object_get (obj, "bool", &b, NULL);
1449   g_assert_true (b);
1450 
1451   g_settings_unbind (obj, "bool");
1452 
1453   g_settings_bind_writable (settings, "int", obj, "bool", TRUE);
1454 
1455   g_object_get (obj, "bool", &b, NULL);
1456   g_assert_false (b);
1457 
1458   g_object_unref (obj);
1459   g_object_unref (settings);
1460 }
1461 
1462 /* Test one-way bindings.
1463  * Verify that changes on one side show up on the other,
1464  * but not vice versa
1465  */
1466 static void
test_directional_binding(void)1467 test_directional_binding (void)
1468 {
1469   TestObject *obj;
1470   GSettings *settings;
1471   gboolean b;
1472   gint i;
1473 
1474   settings = g_settings_new ("org.gtk.test.binding");
1475   obj = test_object_new ();
1476 
1477   g_object_set (obj, "bool", FALSE, NULL);
1478   g_settings_set_boolean (settings, "bool", FALSE);
1479 
1480   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET);
1481 
1482   g_settings_set_boolean (settings, "bool", TRUE);
1483   g_object_get (obj, "bool", &b, NULL);
1484   g_assert_cmpint (b, ==, TRUE);
1485 
1486   g_object_set (obj, "bool", FALSE, NULL);
1487   g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
1488 
1489   g_object_set (obj, "int", 20, NULL);
1490   g_settings_set_int (settings, "int", 20);
1491 
1492   g_settings_bind (settings, "int", obj, "int", G_SETTINGS_BIND_SET);
1493 
1494   g_object_set (obj, "int", 32, NULL);
1495   g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 32);
1496 
1497   g_settings_set_int (settings, "int", 20);
1498   g_object_get (obj, "int", &i, NULL);
1499   g_assert_cmpint (i, ==, 32);
1500 
1501   g_object_unref (obj);
1502   g_object_unref (settings);
1503 }
1504 
1505 /* Test that type mismatch is caught when creating a binding */
1506 static void
test_typesafe_binding(void)1507 test_typesafe_binding (void)
1508 {
1509   if (!g_test_undefined ())
1510     return;
1511 
1512   if (g_test_subprocess ())
1513     {
1514       TestObject *obj;
1515       GSettings *settings;
1516 
1517       settings = g_settings_new ("org.gtk.test.binding");
1518       obj = test_object_new ();
1519 
1520       g_settings_bind (settings, "string", obj, "int", G_SETTINGS_BIND_DEFAULT);
1521 
1522       g_object_unref (obj);
1523       g_object_unref (settings);
1524       return;
1525     }
1526   g_test_trap_subprocess (NULL, 0, 0);
1527   g_test_trap_assert_failed ();
1528   g_test_trap_assert_stderr ("*not compatible*");
1529 }
1530 
1531 static gboolean
string_to_bool(GValue * value,GVariant * variant,gpointer user_data)1532 string_to_bool (GValue   *value,
1533                 GVariant *variant,
1534                 gpointer  user_data)
1535 {
1536   const gchar *s;
1537 
1538   s = g_variant_get_string (variant, NULL);
1539   g_value_set_boolean (value, g_strcmp0 (s, "true") == 0);
1540 
1541   return TRUE;
1542 }
1543 
1544 static GVariant *
bool_to_string(const GValue * value,const GVariantType * expected_type,gpointer user_data)1545 bool_to_string (const GValue       *value,
1546                 const GVariantType *expected_type,
1547                 gpointer            user_data)
1548 {
1549   if (g_value_get_boolean (value))
1550     return g_variant_new_string ("true");
1551   else
1552     return g_variant_new_string ("false");
1553 }
1554 
1555 static GVariant *
bool_to_bool(const GValue * value,const GVariantType * expected_type,gpointer user_data)1556 bool_to_bool (const GValue       *value,
1557               const GVariantType *expected_type,
1558               gpointer            user_data)
1559 {
1560   return g_variant_new_boolean (g_value_get_boolean (value));
1561 }
1562 
1563 /* Test custom bindings.
1564  * Translate strings to booleans and back
1565  */
1566 static void
test_custom_binding(void)1567 test_custom_binding (void)
1568 {
1569   TestObject *obj;
1570   GSettings *settings;
1571   gchar *s;
1572   gboolean b;
1573 
1574   settings = g_settings_new ("org.gtk.test.binding");
1575   obj = test_object_new ();
1576 
1577   g_settings_set_string (settings, "string", "true");
1578 
1579   g_settings_bind_with_mapping (settings, "string",
1580                                 obj, "bool",
1581                                 G_SETTINGS_BIND_DEFAULT,
1582                                 string_to_bool,
1583                                 bool_to_string,
1584                                 NULL, NULL);
1585 
1586   g_settings_set_string (settings, "string", "false");
1587   g_object_get (obj, "bool", &b, NULL);
1588   g_assert_cmpint (b, ==, FALSE);
1589 
1590   g_settings_set_string (settings, "string", "not true");
1591   g_object_get (obj, "bool", &b, NULL);
1592   g_assert_cmpint (b, ==, FALSE);
1593 
1594   g_object_set (obj, "bool", TRUE, NULL);
1595   s = g_settings_get_string (settings, "string");
1596   g_assert_cmpstr (s, ==, "true");
1597   g_free (s);
1598 
1599   g_settings_bind_with_mapping (settings, "string",
1600                                 obj, "bool",
1601                                 G_SETTINGS_BIND_DEFAULT,
1602                                 string_to_bool, bool_to_bool,
1603                                 NULL, NULL);
1604   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1605                          "*binding mapping function for key 'string' returned"
1606                          " GVariant of type 'b' when type 's' was requested*");
1607   g_object_set (obj, "bool", FALSE, NULL);
1608   g_test_assert_expected_messages ();
1609 
1610   g_object_unref (obj);
1611   g_object_unref (settings);
1612 }
1613 
1614 /* Test that with G_SETTINGS_BIND_NO_CHANGES, the
1615  * initial settings value is transported to the object
1616  * side, but later settings changes do not affect the
1617  * object
1618  */
1619 static void
test_no_change_binding(void)1620 test_no_change_binding (void)
1621 {
1622   TestObject *obj;
1623   GSettings *settings;
1624   gboolean b;
1625 
1626   settings = g_settings_new ("org.gtk.test.binding");
1627   obj = test_object_new ();
1628 
1629   g_object_set (obj, "bool", TRUE, NULL);
1630   g_settings_set_boolean (settings, "bool", FALSE);
1631 
1632   g_settings_bind (settings, "bool", obj, "bool", G_SETTINGS_BIND_GET_NO_CHANGES);
1633 
1634   g_object_get (obj, "bool", &b, NULL);
1635   g_assert_cmpint (b, ==, FALSE);
1636 
1637   g_settings_set_boolean (settings, "bool", TRUE);
1638   g_object_get (obj, "bool", &b, NULL);
1639   g_assert_cmpint (b, ==, FALSE);
1640 
1641   g_settings_set_boolean (settings, "bool", FALSE);
1642   g_object_set (obj, "bool", TRUE, NULL);
1643   b = g_settings_get_boolean (settings, "bool");
1644   g_assert_cmpint (b, ==, TRUE);
1645 
1646   g_object_unref (obj);
1647   g_object_unref (settings);
1648 }
1649 
1650 /* Test that binding a non-readable property only
1651  * works in 'GET' mode.
1652  */
1653 static void
test_no_read_binding_fail(void)1654 test_no_read_binding_fail (void)
1655 {
1656   TestObject *obj;
1657   GSettings *settings;
1658 
1659   settings = g_settings_new ("org.gtk.test.binding");
1660   obj = test_object_new ();
1661 
1662   g_settings_bind (settings, "string", obj, "no-read", 0);
1663 }
1664 
1665 static void
test_no_read_binding_pass(void)1666 test_no_read_binding_pass (void)
1667 {
1668   TestObject *obj;
1669   GSettings *settings;
1670 
1671   settings = g_settings_new ("org.gtk.test.binding");
1672   obj = test_object_new ();
1673 
1674   g_settings_bind (settings, "string", obj, "no-read", G_SETTINGS_BIND_GET);
1675 
1676   exit (0);
1677 }
1678 
1679 static void
test_no_read_binding(void)1680 test_no_read_binding (void)
1681 {
1682   if (g_test_undefined ())
1683     {
1684       g_test_trap_subprocess ("/gsettings/no-read-binding/subprocess/fail", 0, 0);
1685       g_test_trap_assert_failed ();
1686       g_test_trap_assert_stderr ("*property*is not readable*");
1687     }
1688 
1689   g_test_trap_subprocess ("/gsettings/no-read-binding/subprocess/pass", 0, 0);
1690   g_test_trap_assert_passed ();
1691 }
1692 
1693 /* Test that binding a non-writable property only
1694  * works in 'SET' mode.
1695  */
1696 static void
test_no_write_binding_fail(void)1697 test_no_write_binding_fail (void)
1698 {
1699   TestObject *obj;
1700   GSettings *settings;
1701 
1702   settings = g_settings_new ("org.gtk.test.binding");
1703   obj = test_object_new ();
1704 
1705   g_settings_bind (settings, "string", obj, "no-write", 0);
1706 }
1707 
1708 static void
test_no_write_binding_pass(void)1709 test_no_write_binding_pass (void)
1710 {
1711   TestObject *obj;
1712   GSettings *settings;
1713 
1714   settings = g_settings_new ("org.gtk.test.binding");
1715   obj = test_object_new ();
1716 
1717   g_settings_bind (settings, "string", obj, "no-write", G_SETTINGS_BIND_SET);
1718 
1719   exit (0);
1720 }
1721 
1722 static void
test_no_write_binding(void)1723 test_no_write_binding (void)
1724 {
1725   if (g_test_undefined ())
1726     {
1727       g_test_trap_subprocess ("/gsettings/no-write-binding/subprocess/fail", 0, 0);
1728       g_test_trap_assert_failed ();
1729       g_test_trap_assert_stderr ("*property*is not writable*");
1730     }
1731 
1732   g_test_trap_subprocess ("/gsettings/no-write-binding/subprocess/pass", 0, 0);
1733   g_test_trap_assert_passed ();
1734 }
1735 
1736 static void
key_changed_cb(GSettings * settings,const gchar * key,gpointer data)1737 key_changed_cb (GSettings *settings, const gchar *key, gpointer data)
1738 {
1739   gboolean *b = data;
1740   (*b) = TRUE;
1741 }
1742 
1743 /*
1744  * Test that using a keyfile works
1745  */
1746 static void
test_keyfile(Fixture * fixture,gconstpointer user_data)1747 test_keyfile (Fixture       *fixture,
1748               gconstpointer  user_data)
1749 {
1750   GSettingsBackend *kf_backend;
1751   GSettings *settings;
1752   GKeyFile *keyfile;
1753   gchar *str;
1754   gboolean writable;
1755   GError *error = NULL;
1756   gchar *data;
1757   gsize len;
1758   gboolean called = FALSE;
1759   gchar *keyfile_path = NULL, *store_path = NULL;
1760 
1761   keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
1762   store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
1763   kf_backend = g_keyfile_settings_backend_new (store_path, "/", "root");
1764   settings = g_settings_new_with_backend ("org.gtk.test", kf_backend);
1765   g_object_unref (kf_backend);
1766 
1767   g_settings_reset (settings, "greeting");
1768   str = g_settings_get_string (settings, "greeting");
1769   g_assert_cmpstr (str, ==, "Hello, earthlings");
1770   g_free (str);
1771 
1772   writable = g_settings_is_writable (settings, "greeting");
1773   g_assert_true (writable);
1774   g_settings_set (settings, "greeting", "s", "see if this works");
1775 
1776   str = g_settings_get_string (settings, "greeting");
1777   g_assert_cmpstr (str, ==, "see if this works");
1778   g_free (str);
1779 
1780   g_settings_delay (settings);
1781   g_settings_set (settings, "farewell", "s", "cheerio");
1782   g_settings_apply (settings);
1783 
1784   keyfile = g_key_file_new ();
1785   g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1786 
1787   str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
1788   g_assert_cmpstr (str, ==, "'see if this works'");
1789   g_free (str);
1790 
1791   str = g_key_file_get_string (keyfile, "tests", "farewell", NULL);
1792   g_assert_cmpstr (str, ==, "'cheerio'");
1793   g_free (str);
1794   g_key_file_free (keyfile);
1795 
1796   g_settings_reset (settings, "greeting");
1797   g_settings_apply (settings);
1798   keyfile = g_key_file_new ();
1799   g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1800 
1801   str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
1802   g_assert_null (str);
1803 
1804   called = FALSE;
1805   g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
1806 
1807   g_key_file_set_string (keyfile, "tests", "greeting", "'howdy'");
1808   data = g_key_file_to_data (keyfile, &len, NULL);
1809   g_file_set_contents (store_path, data, len, &error);
1810   g_assert_no_error (error);
1811   while (!called)
1812     g_main_context_iteration (NULL, FALSE);
1813   g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
1814 
1815   str = g_settings_get_string (settings, "greeting");
1816   g_assert_cmpstr (str, ==, "howdy");
1817   g_free (str);
1818 
1819   /* Now check setting a string without quotes */
1820   called = FALSE;
1821   g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
1822 
1823   g_key_file_set_string (keyfile, "tests", "greeting", "he\"l��uń");
1824   g_free (data);
1825   data = g_key_file_to_data (keyfile, &len, NULL);
1826   g_file_set_contents (store_path, data, len, &error);
1827   g_assert_no_error (error);
1828   while (!called)
1829     g_main_context_iteration (NULL, FALSE);
1830   g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
1831 
1832   str = g_settings_get_string (settings, "greeting");
1833   g_assert_cmpstr (str, ==, "he\"l��uń");
1834   g_free (str);
1835 
1836   g_settings_set (settings, "farewell", "s", "cheerio");
1837 
1838   /* When executing as root, changing the mode of the keyfile will have
1839    * no effect on the writability of the settings.
1840    */
1841   if (geteuid () != 0)
1842     {
1843       called = FALSE;
1844       g_signal_connect (settings, "writable-changed::greeting",
1845                         G_CALLBACK (key_changed_cb), &called);
1846 
1847       g_chmod (keyfile_path, 0500);
1848       while (!called)
1849         g_main_context_iteration (NULL, FALSE);
1850       g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
1851 
1852       writable = g_settings_is_writable (settings, "greeting");
1853       g_assert_false (writable);
1854     }
1855 
1856   g_key_file_free (keyfile);
1857   g_free (data);
1858 
1859   g_object_unref (settings);
1860 
1861   /* Clean up the temporary directory. */
1862   g_chmod (keyfile_path, 0777);
1863   g_assert_cmpint (g_remove (store_path), ==, 0);
1864   g_rmdir (keyfile_path);
1865   g_free (store_path);
1866   g_free (keyfile_path);
1867 }
1868 
1869 /* Test that getting child schemas works
1870  */
1871 static void
test_child_schema(void)1872 test_child_schema (void)
1873 {
1874   GSettings *settings;
1875   GSettings *child;
1876   guint8 byte;
1877 
1878   /* first establish some known conditions */
1879   settings = g_settings_new ("org.gtk.test.basic-types");
1880   g_settings_set (settings, "test-byte", "y", 36);
1881 
1882   g_settings_get (settings, "test-byte", "y", &byte);
1883   g_assert_cmpint (byte, ==, 36);
1884 
1885   g_object_unref (settings);
1886 
1887   settings = g_settings_new ("org.gtk.test");
1888   child = g_settings_get_child (settings, "basic-types");
1889   g_assert_nonnull (child);
1890 
1891   g_settings_get (child, "test-byte", "y", &byte);
1892   g_assert_cmpint (byte, ==, 36);
1893 
1894   g_object_unref (child);
1895   g_object_unref (settings);
1896 }
1897 
1898 #include "../strinfo.c"
1899 
1900 static void
test_strinfo(void)1901 test_strinfo (void)
1902 {
1903   /*  "foo" has a value of 1
1904    *  "bar" has a value of 2
1905    *  "baz" is an alias for "bar"
1906    */
1907   gchar array[] =
1908     "\1\0\0\0"      "\xff""foo"     "\0\0\0\xff"    "\2\0\0\0"
1909     "\xff" "bar"    "\0\0\0\xff"    "\3\0\0\0"      "\xfe""baz"
1910     "\0\0\0\xff";
1911   const guint32 *strinfo = (guint32 *) array;
1912   guint length = sizeof array / 4;
1913   guint result = 0;
1914 
1915   {
1916     /* build it and compare */
1917     GString *builder;
1918 
1919     builder = g_string_new (NULL);
1920     strinfo_builder_append_item (builder, "foo", 1);
1921     strinfo_builder_append_item (builder, "bar", 2);
1922     g_assert_true (strinfo_builder_append_alias (builder, "baz", "bar"));
1923     g_assert_cmpmem (builder->str, builder->len, strinfo, length * 4);
1924     g_string_free (builder, TRUE);
1925   }
1926 
1927   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "foo"),
1928                    ==, NULL);
1929   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "bar"),
1930                    ==, NULL);
1931   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "baz"),
1932                    ==, "bar");
1933   g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "quux"),
1934                    ==, NULL);
1935 
1936   g_assert_true (strinfo_enum_from_string (strinfo, length, "foo", &result));
1937   g_assert_cmpint (result, ==, 1);
1938   g_assert_true (strinfo_enum_from_string (strinfo, length, "bar", &result));
1939   g_assert_cmpint (result, ==, 2);
1940   g_assert_false (strinfo_enum_from_string (strinfo, length, "baz", &result));
1941   g_assert_false (strinfo_enum_from_string (strinfo, length, "quux", &result));
1942 
1943   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 0), ==, NULL);
1944   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 1), ==, "foo");
1945   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 2), ==, "bar");
1946   g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 3), ==, NULL);
1947 
1948   g_assert_true (strinfo_is_string_valid (strinfo, length, "foo"));
1949   g_assert_true (strinfo_is_string_valid (strinfo, length, "bar"));
1950   g_assert_false (strinfo_is_string_valid (strinfo, length, "baz"));
1951   g_assert_false (strinfo_is_string_valid (strinfo, length, "quux"));
1952 }
1953 
1954 static void
test_enums_non_enum_key(void)1955 test_enums_non_enum_key (void)
1956 {
1957   GSettings *direct;
1958 
1959   direct = g_settings_new ("org.gtk.test.enums.direct");
1960   g_settings_get_enum (direct, "test");
1961   g_assert_not_reached ();
1962 }
1963 
1964 static void
test_enums_non_enum_value(void)1965 test_enums_non_enum_value (void)
1966 {
1967   GSettings *settings;
1968 
1969   settings = g_settings_new ("org.gtk.test.enums");
1970   g_settings_set_enum (settings, "test", 42);
1971   g_assert_not_reached ();
1972 }
1973 
1974 static void
test_enums_range(void)1975 test_enums_range (void)
1976 {
1977   GSettings *settings;
1978 
1979   settings = g_settings_new ("org.gtk.test.enums");
1980   g_settings_set_string (settings, "test", "qux");
1981   g_assert_not_reached ();
1982 }
1983 
1984 static void
test_enums_non_flags(void)1985 test_enums_non_flags (void)
1986 {
1987   GSettings *settings;
1988 
1989   settings = g_settings_new ("org.gtk.test.enums");
1990   g_settings_get_flags (settings, "test");
1991   g_assert_not_reached ();
1992 }
1993 
1994 static void
test_enums(void)1995 test_enums (void)
1996 {
1997   GSettings *settings, *direct;
1998   gchar *str;
1999 
2000   settings = g_settings_new ("org.gtk.test.enums");
2001   direct = g_settings_new ("org.gtk.test.enums.direct");
2002 
2003   if (g_test_undefined () && !backend_set)
2004     {
2005       g_test_trap_subprocess ("/gsettings/enums/subprocess/non-enum-key", 0, 0);
2006       g_test_trap_assert_failed ();
2007       g_test_trap_assert_stderr ("*not associated with an enum*");
2008 
2009       g_test_trap_subprocess ("/gsettings/enums/subprocess/non-enum-value", 0, 0);
2010       g_test_trap_assert_failed ();
2011       g_test_trap_assert_stderr ("*invalid enum value 42*");
2012 
2013       g_test_trap_subprocess ("/gsettings/enums/subprocess/range", 0, 0);
2014       g_test_trap_assert_failed ();
2015       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2016 
2017       g_test_trap_subprocess ("/gsettings/enums/subprocess/non-flags", 0, 0);
2018       g_test_trap_assert_failed ();
2019       g_test_trap_assert_stderr ("*not associated with a flags*");
2020     }
2021 
2022   str = g_settings_get_string (settings, "test");
2023   g_assert_cmpstr (str, ==, "bar");
2024   g_free (str);
2025 
2026   g_settings_set_enum (settings, "test", TEST_ENUM_FOO);
2027 
2028   str = g_settings_get_string (settings, "test");
2029   g_assert_cmpstr (str, ==, "foo");
2030   g_free (str);
2031 
2032   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_FOO);
2033 
2034   g_settings_set_string (direct, "test", "qux");
2035 
2036   str = g_settings_get_string (direct, "test");
2037   g_assert_cmpstr (str, ==, "qux");
2038   g_free (str);
2039 
2040   str = g_settings_get_string (settings, "test");
2041   g_assert_cmpstr (str, ==, "quux");
2042   g_free (str);
2043 
2044   g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_QUUX);
2045 
2046   g_object_unref (direct);
2047   g_object_unref (settings);
2048 }
2049 
2050 static void
test_flags_non_flags_key(void)2051 test_flags_non_flags_key (void)
2052 {
2053   GSettings *direct;
2054 
2055   direct = g_settings_new ("org.gtk.test.enums.direct");
2056   g_settings_get_flags (direct, "test");
2057   g_assert_not_reached ();
2058 }
2059 
2060 static void
test_flags_non_flags_value(void)2061 test_flags_non_flags_value (void)
2062 {
2063   GSettings *settings;
2064 
2065   settings = g_settings_new ("org.gtk.test.enums");
2066   g_settings_set_flags (settings, "f-test", 0x42);
2067   g_assert_not_reached ();
2068 }
2069 
2070 static void
test_flags_range(void)2071 test_flags_range (void)
2072 {
2073   GSettings *settings;
2074 
2075   settings = g_settings_new ("org.gtk.test.enums");
2076   g_settings_set_strv (settings, "f-test",
2077                        (const gchar **) g_strsplit ("rock", ",", 0));
2078   g_assert_not_reached ();
2079 }
2080 
2081 static void
test_flags_non_enum(void)2082 test_flags_non_enum (void)
2083 {
2084   GSettings *settings;
2085 
2086   settings = g_settings_new ("org.gtk.test.enums");
2087   g_settings_get_enum (settings, "f-test");
2088   g_assert_not_reached ();
2089 }
2090 
2091 static void
test_flags(void)2092 test_flags (void)
2093 {
2094   GSettings *settings, *direct;
2095   gchar **strv;
2096   gchar *str;
2097 
2098   settings = g_settings_new ("org.gtk.test.enums");
2099   direct = g_settings_new ("org.gtk.test.enums.direct");
2100 
2101   if (g_test_undefined () && !backend_set)
2102     {
2103       g_test_trap_subprocess ("/gsettings/flags/subprocess/non-flags-key", 0, 0);
2104       g_test_trap_assert_failed ();
2105       g_test_trap_assert_stderr ("*not associated with a flags*");
2106 
2107       g_test_trap_subprocess ("/gsettings/flags/subprocess/non-flags-value", 0, 0);
2108       g_test_trap_assert_failed ();
2109       g_test_trap_assert_stderr ("*invalid flags value 0x00000042*");
2110 
2111       g_test_trap_subprocess ("/gsettings/flags/subprocess/range", 0, 0);
2112       g_test_trap_assert_failed ();
2113       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2114 
2115       g_test_trap_subprocess ("/gsettings/flags/subprocess/non-enum", 0, 0);
2116       g_test_trap_assert_failed ();
2117       g_test_trap_assert_stderr ("*not associated with an enum*");
2118     }
2119 
2120   strv = g_settings_get_strv (settings, "f-test");
2121   str = g_strjoinv (",", strv);
2122   g_assert_cmpstr (str, ==, "");
2123   g_strfreev (strv);
2124   g_free (str);
2125 
2126   g_settings_set_flags (settings, "f-test",
2127                         TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
2128 
2129   strv = g_settings_get_strv (settings, "f-test");
2130   str = g_strjoinv (",", strv);
2131   g_assert_cmpstr (str, ==, "talking,walking");
2132   g_strfreev (strv);
2133   g_free (str);
2134 
2135   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
2136                    TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
2137 
2138   strv = g_strsplit ("speaking,laughing", ",", 0);
2139   g_settings_set_strv (direct, "f-test", (const gchar **) strv);
2140   g_strfreev (strv);
2141 
2142   strv = g_settings_get_strv (direct, "f-test");
2143   str = g_strjoinv (",", strv);
2144   g_assert_cmpstr (str, ==, "speaking,laughing");
2145   g_strfreev (strv);
2146   g_free (str);
2147 
2148   strv = g_settings_get_strv (settings, "f-test");
2149   str = g_strjoinv (",", strv);
2150   g_assert_cmpstr (str, ==, "talking,laughing");
2151   g_strfreev (strv);
2152   g_free (str);
2153 
2154   g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
2155                    TEST_FLAGS_TALKING | TEST_FLAGS_LAUGHING);
2156 
2157   g_object_unref (direct);
2158   g_object_unref (settings);
2159 }
2160 
2161 static void
test_range_high(void)2162 test_range_high (void)
2163 {
2164   GSettings *settings;
2165 
2166   settings = g_settings_new ("org.gtk.test.range");
2167   g_settings_set_int (settings, "val", 45);
2168   g_assert_not_reached ();
2169 }
2170 
2171 static void
test_range_low(void)2172 test_range_low (void)
2173 {
2174   GSettings *settings;
2175 
2176   settings = g_settings_new ("org.gtk.test.range");
2177   g_settings_set_int (settings, "val", 1);
2178   g_assert_not_reached ();
2179 }
2180 
2181 static void
test_range(void)2182 test_range (void)
2183 {
2184   GSettings *settings, *direct;
2185   GVariant *value;
2186 
2187   settings = g_settings_new ("org.gtk.test.range");
2188   direct = g_settings_new ("org.gtk.test.range.direct");
2189 
2190   if (g_test_undefined () && !backend_set)
2191     {
2192       g_test_trap_subprocess ("/gsettings/range/subprocess/high", 0, 0);
2193       g_test_trap_assert_failed ();
2194       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2195 
2196       g_test_trap_subprocess ("/gsettings/range/subprocess/low", 0, 0);
2197       g_test_trap_assert_failed ();
2198       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2199     }
2200 
2201   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
2202   g_settings_set_int (direct, "val", 22);
2203   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 22);
2204   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 22);
2205   g_settings_set_int (direct, "val", 45);
2206   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 45);
2207   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
2208   g_settings_set_int (direct, "val", 1);
2209   g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 1);
2210   g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
2211 
2212 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2213   value = g_variant_new_int32 (1);
2214   g_assert_false (g_settings_range_check (settings, "val", value));
2215   g_variant_unref (value);
2216   value = g_variant_new_int32 (33);
2217   g_assert_true (g_settings_range_check (settings, "val", value));
2218   g_variant_unref (value);
2219   value = g_variant_new_int32 (45);
2220   g_assert_false (g_settings_range_check (settings, "val", value));
2221   g_variant_unref (value);
2222 G_GNUC_END_IGNORE_DEPRECATIONS
2223 
2224   g_object_unref (direct);
2225   g_object_unref (settings);
2226 }
2227 
2228 static gboolean
strv_has_string(gchar ** haystack,const gchar * needle)2229 strv_has_string (gchar       **haystack,
2230                  const gchar  *needle)
2231 {
2232   guint n;
2233 
2234   for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
2235     {
2236       if (g_strcmp0 (haystack[n], needle) == 0)
2237         return TRUE;
2238     }
2239   return FALSE;
2240 }
2241 
2242 static gboolean
strv_set_equal(gchar ** strv,...)2243 strv_set_equal (gchar **strv, ...)
2244 {
2245   gint count;
2246   va_list list;
2247   const gchar *str;
2248   gboolean res;
2249 
2250   res = TRUE;
2251   count = 0;
2252   va_start (list, strv);
2253   while (1)
2254     {
2255       str = va_arg (list, const gchar *);
2256       if (str == NULL)
2257         break;
2258       if (!strv_has_string (strv, str))
2259         {
2260           res = FALSE;
2261           break;
2262         }
2263       count++;
2264     }
2265   va_end (list);
2266 
2267   if (res)
2268     res = g_strv_length ((gchar**)strv) == count;
2269 
2270   return res;
2271 }
2272 
2273 static void
test_list_items(void)2274 test_list_items (void)
2275 {
2276   GSettingsSchema *schema;
2277   GSettings *settings;
2278   gchar **children;
2279   gchar **keys;
2280 
2281   settings = g_settings_new ("org.gtk.test");
2282   g_object_get (settings, "settings-schema", &schema, NULL);
2283   children = g_settings_list_children (settings);
2284   keys = g_settings_schema_list_keys (schema);
2285 
2286   g_assert_true (strv_set_equal (children, "basic-types", "complex-types", "localized", NULL));
2287   g_assert_true (strv_set_equal (keys, "greeting", "farewell", NULL));
2288 
2289   g_strfreev (children);
2290   g_strfreev (keys);
2291 
2292   g_settings_schema_unref (schema);
2293   g_object_unref (settings);
2294 }
2295 
2296 static void
test_list_schemas(void)2297 test_list_schemas (void)
2298 {
2299   const gchar * const *schemas;
2300   const gchar * const *relocs;
2301 
2302 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2303   relocs = g_settings_list_relocatable_schemas ();
2304   schemas = g_settings_list_schemas ();
2305 G_GNUC_END_IGNORE_DEPRECATIONS
2306 
2307   g_assert_true (strv_set_equal ((gchar **)relocs,
2308                                  "org.gtk.test.no-path",
2309                                  "org.gtk.test.extends.base",
2310                                  "org.gtk.test.extends.extended",
2311                                  NULL));
2312 
2313   g_assert_true (strv_set_equal ((gchar **)schemas,
2314                                  "org.gtk.test",
2315                                  "org.gtk.test.basic-types",
2316                                  "org.gtk.test.complex-types",
2317                                  "org.gtk.test.localized",
2318                                  "org.gtk.test.binding",
2319                                  "org.gtk.test.enums",
2320                                  "org.gtk.test.enums.direct",
2321                                  "org.gtk.test.range",
2322                                  "org.gtk.test.range.direct",
2323                                  "org.gtk.test.mapped",
2324                                  "org.gtk.test.descriptions",
2325                                  "org.gtk.test.per-desktop",
2326                                  NULL));
2327 }
2328 
2329 static gboolean
map_func(GVariant * value,gpointer * result,gpointer user_data)2330 map_func (GVariant *value,
2331           gpointer *result,
2332           gpointer  user_data)
2333 {
2334   gint *state = user_data;
2335   gint v;
2336 
2337   if (value)
2338     v = g_variant_get_int32 (value);
2339   else
2340     v = -1;
2341 
2342   if (*state == 0)
2343     {
2344       g_assert_cmpint (v, ==, 1);
2345       (*state)++;
2346       return FALSE;
2347     }
2348   else if (*state == 1)
2349     {
2350       g_assert_cmpint (v, ==, 0);
2351       (*state)++;
2352       return FALSE;
2353     }
2354   else
2355     {
2356       g_assert_null (value);
2357       *result = g_variant_new_int32 (5);
2358       return TRUE;
2359     }
2360 }
2361 
2362 static void
test_get_mapped(void)2363 test_get_mapped (void)
2364 {
2365   GSettings *settings;
2366   gint state;
2367   gpointer p;
2368   gint val;
2369 
2370   settings = g_settings_new ("org.gtk.test.mapped");
2371   g_settings_set_int (settings, "val", 1);
2372 
2373   state = 0;
2374   p = g_settings_get_mapped (settings, "val", map_func, &state);
2375   val = g_variant_get_int32 ((GVariant*)p);
2376   g_assert_cmpint (val, ==, 5);
2377 
2378   g_variant_unref (p);
2379   g_object_unref (settings);
2380 }
2381 
2382 static void
test_get_range(void)2383 test_get_range (void)
2384 {
2385   GSettings *settings;
2386   GVariant *range;
2387 
2388 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2389   settings = g_settings_new ("org.gtk.test.range");
2390   range = g_settings_get_range (settings, "val");
2391   check_and_free (range, "('range', <(2, 44)>)");
2392   g_object_unref (settings);
2393 
2394   settings = g_settings_new ("org.gtk.test.enums");
2395   range = g_settings_get_range (settings, "test");
2396   check_and_free (range, "('enum', <['foo', 'bar', 'baz', 'quux']>)");
2397   g_object_unref (settings);
2398 
2399   settings = g_settings_new ("org.gtk.test.enums");
2400   range = g_settings_get_range (settings, "f-test");
2401   check_and_free (range, "('flags', "
2402                   "<['mourning', 'laughing', 'talking', 'walking']>)");
2403   g_object_unref (settings);
2404 
2405   settings = g_settings_new ("org.gtk.test");
2406   range = g_settings_get_range (settings, "greeting");
2407   check_and_free (range, "('type', <@as []>)");
2408   g_object_unref (settings);
2409 G_GNUC_END_IGNORE_DEPRECATIONS
2410 }
2411 
2412 static void
test_schema_source(void)2413 test_schema_source (void)
2414 {
2415   GSettingsSchemaSource *parent;
2416   GSettingsSchemaSource *source;
2417   GSettingsBackend *backend;
2418   GSettingsSchema *schema;
2419   GError *error = NULL;
2420   GSettings *settings;
2421   gboolean enabled;
2422 
2423   backend = g_settings_backend_get_default ();
2424 
2425   /* make sure it fails properly */
2426   parent = g_settings_schema_source_get_default ();
2427   source = g_settings_schema_source_new_from_directory ("/path/that/does/not/exist", parent,  TRUE, &error);
2428   g_assert_null (source);
2429   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
2430   g_clear_error (&error);
2431 
2432   /* Test error handling of corrupt compiled files. */
2433   source = g_settings_schema_source_new_from_directory ("schema-source-corrupt", parent, TRUE, &error);
2434   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
2435   g_assert_null (source);
2436   g_clear_error (&error);
2437 
2438   /* Test error handling of empty compiled files. */
2439   source = g_settings_schema_source_new_from_directory ("schema-source-empty", parent, TRUE, &error);
2440   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
2441   g_assert_null (source);
2442   g_clear_error (&error);
2443 
2444   /* create a source with the parent */
2445   source = g_settings_schema_source_new_from_directory ("schema-source", parent, TRUE, &error);
2446   g_assert_no_error (error);
2447   g_assert_nonnull (source);
2448 
2449   /* check recursive lookups are working */
2450   schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
2451   g_assert_nonnull (schema);
2452   g_settings_schema_unref (schema);
2453 
2454   /* check recursive lookups for non-existent schemas */
2455   schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", TRUE);
2456   g_assert_null (schema);
2457 
2458   /* check non-recursive for schema that only exists in lower layers */
2459   schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
2460   g_assert_null (schema);
2461 
2462   /* check non-recursive lookup for non-existent */
2463   schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", FALSE);
2464   g_assert_null (schema);
2465 
2466   /* check non-recursive for schema that exists in toplevel */
2467   schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
2468   g_assert_nonnull (schema);
2469   g_settings_schema_unref (schema);
2470 
2471   /* check recursive for schema that exists in toplevel */
2472   schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
2473   g_assert_nonnull (schema);
2474 
2475   /* try to use it for something */
2476   settings = g_settings_new_full (schema, backend, g_settings_schema_get_path (schema));
2477   g_settings_schema_unref (schema);
2478   enabled = FALSE;
2479   g_settings_get (settings, "enabled", "b", &enabled);
2480   g_assert_true (enabled);
2481   g_object_unref (settings);
2482 
2483   g_settings_schema_source_unref (source);
2484 
2485   /* try again, but with no parent */
2486   source = g_settings_schema_source_new_from_directory ("schema-source", NULL, FALSE, NULL);
2487   g_assert_nonnull (source);
2488 
2489   /* should not find it this time, even if recursive... */
2490   schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
2491   g_assert_null (schema);
2492   schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
2493   g_assert_null (schema);
2494 
2495   /* should still find our own... */
2496   schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
2497   g_assert_nonnull (schema);
2498   g_settings_schema_unref (schema);
2499   schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
2500   g_assert_nonnull (schema);
2501   g_settings_schema_unref (schema);
2502 
2503   g_settings_schema_source_unref (source);
2504   g_object_unref (backend);
2505 }
2506 
2507 static void
test_schema_list_keys(void)2508 test_schema_list_keys (void)
2509 {
2510   gchar                 **keys;
2511   GSettingsSchemaSource  *src    = g_settings_schema_source_get_default ();
2512   GSettingsSchema        *schema = g_settings_schema_source_lookup (src, "org.gtk.test", TRUE);
2513   g_assert_nonnull (schema);
2514 
2515   keys = g_settings_schema_list_keys (schema);
2516 
2517   g_assert_true (strv_set_equal ((gchar **)keys,
2518                                  "greeting",
2519                                  "farewell",
2520                                  NULL));
2521 
2522   g_strfreev (keys);
2523   g_settings_schema_unref (schema);
2524 }
2525 
2526 static void
test_actions(void)2527 test_actions (void)
2528 {
2529   GAction *string, *toggle;
2530   gboolean c1, c2, c3;
2531   GSettings *settings;
2532   gchar *name;
2533   GVariantType *param_type;
2534   gboolean enabled;
2535   GVariantType *state_type;
2536   GVariant *state;
2537 
2538   settings = g_settings_new ("org.gtk.test.basic-types");
2539   string = g_settings_create_action (settings, "test-string");
2540   toggle = g_settings_create_action (settings, "test-boolean");
2541   g_object_unref (settings); /* should be held by the actions */
2542 
2543   g_signal_connect (settings, "changed", G_CALLBACK (changed_cb2), &c1);
2544   g_signal_connect (string, "notify::state", G_CALLBACK (changed_cb2), &c2);
2545   g_signal_connect (toggle, "notify::state", G_CALLBACK (changed_cb2), &c3);
2546 
2547   c1 = c2 = c3 = FALSE;
2548   g_settings_set_string (settings, "test-string", "hello world");
2549   check_and_free (g_action_get_state (string), "'hello world'");
2550   g_assert_true (c1 && c2 && !c3);
2551   c1 = c2 = c3 = FALSE;
2552 
2553   g_action_activate (string, g_variant_new_string ("hihi"));
2554   check_and_free (g_settings_get_value (settings, "test-string"), "'hihi'");
2555   g_assert_true (c1 && c2 && !c3);
2556   c1 = c2 = c3 = FALSE;
2557 
2558   g_action_change_state (string, g_variant_new_string ("kthxbye"));
2559   check_and_free (g_settings_get_value (settings, "test-string"), "'kthxbye'");
2560   g_assert_true (c1 && c2 && !c3);
2561   c1 = c2 = c3 = FALSE;
2562 
2563   g_action_change_state (toggle, g_variant_new_boolean (TRUE));
2564   g_assert_true (g_settings_get_boolean (settings, "test-boolean"));
2565   g_assert_true (c1 && !c2 && c3);
2566   c1 = c2 = c3 = FALSE;
2567 
2568   g_action_activate (toggle, NULL);
2569   g_assert_false (g_settings_get_boolean (settings, "test-boolean"));
2570   g_assert_true (c1 && !c2 && c3);
2571 
2572   g_object_get (string,
2573                 "name", &name,
2574                 "parameter-type", &param_type,
2575                 "enabled", &enabled,
2576                 "state-type", &state_type,
2577                 "state", &state,
2578                 NULL);
2579 
2580   g_assert_cmpstr (name, ==, "test-string");
2581   g_assert_true (g_variant_type_equal (param_type, G_VARIANT_TYPE_STRING));
2582   g_assert_true (enabled);
2583   g_assert_true (g_variant_type_equal (state_type, G_VARIANT_TYPE_STRING));
2584   g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "kthxbye");
2585 
2586   g_free (name);
2587   g_variant_type_free (param_type);
2588   g_variant_type_free (state_type);
2589   g_variant_unref (state);
2590 
2591   g_object_unref (string);
2592   g_object_unref (toggle);
2593 }
2594 
2595 static void
test_null_backend(void)2596 test_null_backend (void)
2597 {
2598   GSettingsBackend *backend;
2599   GSettings *settings;
2600   gchar *str;
2601   gboolean writable;
2602 
2603   backend = g_null_settings_backend_new ();
2604   settings = g_settings_new_with_backend_and_path ("org.gtk.test", backend, "/tests/");
2605 
2606   g_object_get (settings, "schema-id", &str, NULL);
2607   g_assert_cmpstr (str, ==, "org.gtk.test");
2608   g_free (str);
2609 
2610   g_settings_get (settings, "greeting", "s", &str);
2611   g_assert_cmpstr (str, ==, "Hello, earthlings");
2612   g_free (str);
2613 
2614   g_settings_set (settings, "greeting", "s", "goodbye world");
2615   g_settings_get (settings, "greeting", "s", &str);
2616   g_assert_cmpstr (str, ==, "Hello, earthlings");
2617   g_free (str);
2618 
2619   writable = g_settings_is_writable (settings, "greeting");
2620   g_assert_false (writable);
2621 
2622   g_settings_reset (settings, "greeting");
2623 
2624   g_settings_delay (settings);
2625   g_settings_set (settings, "greeting", "s", "goodbye world");
2626   g_settings_apply (settings);
2627   g_settings_get (settings, "greeting", "s", &str);
2628   g_assert_cmpstr (str, ==, "Hello, earthlings");
2629   g_free (str);
2630 
2631   g_object_unref (settings);
2632   g_object_unref (backend);
2633 }
2634 
2635 static void
test_memory_backend(void)2636 test_memory_backend (void)
2637 {
2638   GSettingsBackend *backend;
2639 
2640   backend = g_memory_settings_backend_new ();
2641   g_assert_true (G_IS_SETTINGS_BACKEND (backend));
2642   g_object_unref (backend);
2643 }
2644 
2645 static void
test_read_descriptions(void)2646 test_read_descriptions (void)
2647 {
2648   GSettingsSchema *schema;
2649   GSettingsSchemaKey *key;
2650   GSettings *settings;
2651 
2652   settings = g_settings_new ("org.gtk.test");
2653   g_object_get (settings, "settings-schema", &schema, NULL);
2654   key = g_settings_schema_get_key (schema, "greeting");
2655 
2656   g_assert_cmpstr (g_settings_schema_key_get_summary (key), ==, "A greeting");
2657   g_assert_cmpstr (g_settings_schema_key_get_description (key), ==, "Greeting of the invading martians");
2658 
2659   g_settings_schema_key_unref (key);
2660   g_settings_schema_unref (schema);
2661 
2662   g_object_unref (settings);
2663 
2664   settings = g_settings_new ("org.gtk.test.descriptions");
2665   g_object_get (settings, "settings-schema", &schema, NULL);
2666   key = g_settings_schema_get_key (schema, "a");
2667 
2668   g_assert_cmpstr (g_settings_schema_key_get_summary (key), ==,
2669                    "a paragraph.\n\n"
2670                    "with some whitespace.\n\n"
2671                    "because not everyone has a great editor.\n\n"
2672                    "lots of space is as one.");
2673 
2674   g_settings_schema_key_unref (key);
2675   g_settings_schema_unref (schema);
2676 
2677   g_object_unref (settings);
2678 }
2679 
2680 static void
test_default_value(void)2681 test_default_value (void)
2682 {
2683   GSettings *settings;
2684   GSettingsSchema *schema;
2685   GSettingsSchemaKey *key;
2686   GVariant *v;
2687   const gchar *str;
2688   gchar *s;
2689 
2690   settings = g_settings_new ("org.gtk.test");
2691   g_object_get (settings, "settings-schema", &schema, NULL);
2692   key = g_settings_schema_get_key (schema, "greeting");
2693   g_settings_schema_unref (schema);
2694   g_settings_schema_key_ref (key);
2695 
2696   g_assert_true (g_variant_type_equal (g_settings_schema_key_get_value_type (key), G_VARIANT_TYPE_STRING));
2697 
2698   v = g_settings_schema_key_get_default_value (key);
2699   str = g_variant_get_string (v, NULL);
2700   g_assert_cmpstr (str, ==, "Hello, earthlings");
2701   g_variant_unref (v);
2702 
2703   g_settings_schema_key_unref (key);
2704   g_settings_schema_key_unref (key);
2705 
2706   g_settings_set (settings, "greeting", "s", "goodbye world");
2707 
2708   v = g_settings_get_user_value (settings, "greeting");
2709   str = g_variant_get_string (v, NULL);
2710   g_assert_cmpstr (str, ==, "goodbye world");
2711   g_variant_unref (v);
2712 
2713   v = g_settings_get_default_value (settings, "greeting");
2714   str = g_variant_get_string (v, NULL);
2715   g_assert_cmpstr (str, ==, "Hello, earthlings");
2716   g_variant_unref (v);
2717 
2718   g_settings_reset (settings, "greeting");
2719 
2720   v = g_settings_get_user_value (settings, "greeting");
2721   g_assert_null (v);
2722 
2723   s = g_settings_get_string (settings, "greeting");
2724   g_assert_cmpstr (s, ==, "Hello, earthlings");
2725   g_free (s);
2726 
2727   g_object_unref (settings);
2728 }
2729 
2730 static gboolean
string_map_func(GVariant * value,gpointer * result,gpointer user_data)2731 string_map_func (GVariant *value,
2732                  gpointer *result,
2733                  gpointer  user_data)
2734 {
2735   const gchar *str;
2736 
2737   str = g_variant_get_string (value, NULL);
2738   *result = g_variant_new_string (str);
2739 
2740   return TRUE;
2741 }
2742 
2743 /* Test that per-desktop values from org.gtk.test.gschema.override
2744  * does not change default value if current desktop is not listed in
2745  * $XDG_CURRENT_DESKTOP.
2746  */
2747 static void
test_per_desktop(void)2748 test_per_desktop (void)
2749 {
2750   GSettings *settings;
2751   TestObject *obj;
2752   gpointer p;
2753   gchar *str;
2754 
2755   settings = g_settings_new ("org.gtk.test.per-desktop");
2756   obj = test_object_new ();
2757 
2758   if (!g_test_subprocess ())
2759     {
2760       g_test_trap_subprocess ("/gsettings/per-desktop/subprocess", 0, 0);
2761       g_test_trap_assert_passed ();
2762     }
2763 
2764   str = g_settings_get_string (settings, "desktop");
2765   g_assert_cmpstr (str, ==, "GNOME");
2766   g_free (str);
2767 
2768   p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL);
2769 
2770   str = g_variant_dup_string (p, NULL);
2771   g_assert_cmpstr (str, ==, "GNOME");
2772   g_free (str);
2773 
2774   g_variant_unref (p);
2775 
2776   g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT);
2777 
2778   g_object_get (obj, "string", &str, NULL);
2779   g_assert_cmpstr (str, ==, "GNOME");
2780   g_free (str);
2781 
2782   g_object_unref (settings);
2783   g_object_unref (obj);
2784 }
2785 
2786 /* Test that per-desktop values from org.gtk.test.gschema.override
2787  * are successfully loaded based on the value of $XDG_CURRENT_DESKTOP.
2788  */
2789 static void
test_per_desktop_subprocess(void)2790 test_per_desktop_subprocess (void)
2791 {
2792   GSettings *settings;
2793   TestObject *obj;
2794   gpointer p;
2795   gchar *str;
2796 
2797   g_setenv ("XDG_CURRENT_DESKTOP", "GNOME-Classic:GNOME", TRUE);
2798 
2799   settings = g_settings_new ("org.gtk.test.per-desktop");
2800   obj = test_object_new ();
2801 
2802   str = g_settings_get_string (settings, "desktop");
2803   g_assert_cmpstr (str, ==, "GNOME Classic");
2804   g_free (str);
2805 
2806   p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL);
2807 
2808   str = g_variant_dup_string (p, NULL);
2809   g_assert_cmpstr (str, ==, "GNOME Classic");
2810   g_free (str);
2811 
2812   g_variant_unref (p);
2813 
2814   g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT);
2815 
2816   g_object_get (obj, "string", &str, NULL);
2817   g_assert_cmpstr (str, ==, "GNOME Classic");
2818   g_free (str);
2819 
2820   g_object_unref (settings);
2821   g_object_unref (obj);
2822 }
2823 
2824 static void
test_extended_schema(void)2825 test_extended_schema (void)
2826 {
2827   GSettingsSchema *schema;
2828   GSettings *settings;
2829   gchar **keys;
2830 
2831   settings = g_settings_new_with_path ("org.gtk.test.extends.extended", "/test/extendes/");
2832   g_object_get (settings, "settings-schema", &schema, NULL);
2833   keys = g_settings_schema_list_keys (schema);
2834   g_assert_true (strv_set_equal (keys, "int32", "string", "another-int32", NULL));
2835   g_strfreev (keys);
2836   g_object_unref (settings);
2837   g_settings_schema_unref (schema);
2838 }
2839 
2840 int
main(int argc,char * argv[])2841 main (int argc, char *argv[])
2842 {
2843   gchar *schema_text;
2844   gchar *override_text;
2845   gchar *enums;
2846   gint result;
2847 
2848 /* Meson build sets this */
2849 #ifdef TEST_LOCALE_PATH
2850   if (g_str_has_suffix (TEST_LOCALE_PATH, "LC_MESSAGES"))
2851     {
2852       locale_dir = TEST_LOCALE_PATH G_DIR_SEPARATOR_S ".." G_DIR_SEPARATOR_S "..";
2853     }
2854 #endif
2855 
2856   setlocale (LC_ALL, "");
2857 
2858   g_test_init (&argc, &argv, NULL);
2859 
2860   if (!g_test_subprocess ())
2861     {
2862       GError *local_error = NULL;
2863       /* A GVDB header is 6 guint32s, and requires a magic number in the first
2864        * two guint32s. A set of zero bytes of a greater length is considered
2865        * corrupt. */
2866       const guint8 gschemas_compiled_corrupt[sizeof (guint32) * 7] = { 0, };
2867 
2868       backend_set = g_getenv ("GSETTINGS_BACKEND") != NULL;
2869 
2870       g_setenv ("XDG_DATA_DIRS", ".", TRUE);
2871       g_setenv ("XDG_DATA_HOME", ".", TRUE);
2872       g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
2873       g_setenv ("XDG_CURRENT_DESKTOP", "", TRUE);
2874 
2875       if (!backend_set)
2876         g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
2877 
2878       g_remove ("org.gtk.test.enums.xml");
2879       /* #GLIB_MKENUMS is defined in meson.build */
2880       g_assert_true (g_spawn_command_line_sync (GLIB_MKENUMS " "
2881                                                 "--template " SRCDIR "/enums.xml.template "
2882                                                 SRCDIR "/testenum.h",
2883                                                 &enums, NULL, &result, NULL));
2884       g_assert_cmpint (result, ==, 0);
2885       g_assert_true (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
2886       g_free (enums);
2887 
2888       g_assert_true (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.xml.orig", &schema_text, NULL, NULL));
2889       g_assert_true (g_file_set_contents ("org.gtk.test.gschema.xml", schema_text, -1, NULL));
2890       g_free (schema_text);
2891 
2892       g_assert_true (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.override.orig", &override_text, NULL, NULL));
2893       g_assert_true (g_file_set_contents ("org.gtk.test.gschema.override", override_text, -1, NULL));
2894       g_free (override_text);
2895 
2896       g_remove ("gschemas.compiled");
2897       /* #GLIB_COMPILE_SCHEMAS is defined in meson.build */
2898       g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=. "
2899                                                 "--schema-file=org.gtk.test.enums.xml "
2900                                                 "--schema-file=org.gtk.test.gschema.xml "
2901                                                 "--override-file=org.gtk.test.gschema.override",
2902                                                 NULL, NULL, &result, NULL));
2903       g_assert_cmpint (result, ==, 0);
2904 
2905       g_remove ("schema-source/gschemas.compiled");
2906       g_mkdir ("schema-source", 0777);
2907       g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=schema-source "
2908                                                 "--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml",
2909                                                 NULL, NULL, &result, NULL));
2910       g_assert_cmpint (result, ==, 0);
2911 
2912       g_remove ("schema-source-corrupt/gschemas.compiled");
2913       g_mkdir ("schema-source-corrupt", 0777);
2914       g_file_set_contents ("schema-source-corrupt/gschemas.compiled",
2915                            (const gchar *) gschemas_compiled_corrupt,
2916                            sizeof (gschemas_compiled_corrupt),
2917                            &local_error);
2918       g_assert_no_error (local_error);
2919 
2920       g_remove ("schema-source-empty/gschemas.compiled");
2921       g_mkdir ("schema-source-empty", 0777);
2922       g_file_set_contents ("schema-source-empty/gschemas.compiled",
2923                            "", 0,
2924                            &local_error);
2925       g_assert_no_error (local_error);
2926    }
2927 
2928   g_test_add_func ("/gsettings/basic", test_basic);
2929 
2930   if (!backend_set)
2931     {
2932       g_test_add_func ("/gsettings/no-schema", test_no_schema);
2933       g_test_add_func ("/gsettings/unknown-key", test_unknown_key);
2934       g_test_add_func ("/gsettings/wrong-type", test_wrong_type);
2935       g_test_add_func ("/gsettings/wrong-path", test_wrong_path);
2936       g_test_add_func ("/gsettings/no-path", test_no_path);
2937     }
2938 
2939   g_test_add_func ("/gsettings/basic-types", test_basic_types);
2940   g_test_add_func ("/gsettings/complex-types", test_complex_types);
2941   g_test_add_func ("/gsettings/changes", test_changes);
2942 
2943   g_test_add_func ("/gsettings/l10n", test_l10n);
2944   g_test_add_func ("/gsettings/l10n-context", test_l10n_context);
2945 
2946   g_test_add_func ("/gsettings/delay-apply", test_delay_apply);
2947   g_test_add_func ("/gsettings/delay-revert", test_delay_revert);
2948   g_test_add_func ("/gsettings/delay-child", test_delay_child);
2949   g_test_add_func ("/gsettings/atomic", test_atomic);
2950 
2951   g_test_add_func ("/gsettings/simple-binding", test_simple_binding);
2952   g_test_add_func ("/gsettings/directional-binding", test_directional_binding);
2953   g_test_add_func ("/gsettings/custom-binding", test_custom_binding);
2954   g_test_add_func ("/gsettings/no-change-binding", test_no_change_binding);
2955   g_test_add_func ("/gsettings/unbinding", test_unbind);
2956   g_test_add_func ("/gsettings/writable-binding", test_bind_writable);
2957 
2958   if (!backend_set)
2959     {
2960       g_test_add_func ("/gsettings/typesafe-binding", test_typesafe_binding);
2961       g_test_add_func ("/gsettings/no-read-binding", test_no_read_binding);
2962       g_test_add_func ("/gsettings/no-read-binding/subprocess/fail", test_no_read_binding_fail);
2963       g_test_add_func ("/gsettings/no-read-binding/subprocess/pass", test_no_read_binding_pass);
2964       g_test_add_func ("/gsettings/no-write-binding", test_no_write_binding);
2965       g_test_add_func ("/gsettings/no-write-binding/subprocess/fail", test_no_write_binding_fail);
2966       g_test_add_func ("/gsettings/no-write-binding/subprocess/pass", test_no_write_binding_pass);
2967     }
2968 
2969   g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown);
2970   g_test_add_func ("/gsettings/child-schema", test_child_schema);
2971   g_test_add_func ("/gsettings/strinfo", test_strinfo);
2972   g_test_add_func ("/gsettings/enums", test_enums);
2973   g_test_add_func ("/gsettings/enums/subprocess/non-enum-key", test_enums_non_enum_key);
2974   g_test_add_func ("/gsettings/enums/subprocess/non-enum-value", test_enums_non_enum_value);
2975   g_test_add_func ("/gsettings/enums/subprocess/range", test_enums_range);
2976   g_test_add_func ("/gsettings/enums/subprocess/non-flags", test_enums_non_flags);
2977   g_test_add_func ("/gsettings/flags", test_flags);
2978   g_test_add_func ("/gsettings/flags/subprocess/non-flags-key", test_flags_non_flags_key);
2979   g_test_add_func ("/gsettings/flags/subprocess/non-flags-value", test_flags_non_flags_value);
2980   g_test_add_func ("/gsettings/flags/subprocess/range", test_flags_range);
2981   g_test_add_func ("/gsettings/flags/subprocess/non-enum", test_flags_non_enum);
2982   g_test_add_func ("/gsettings/range", test_range);
2983   g_test_add_func ("/gsettings/range/subprocess/high", test_range_high);
2984   g_test_add_func ("/gsettings/range/subprocess/low", test_range_low);
2985   g_test_add_func ("/gsettings/list-items", test_list_items);
2986   g_test_add_func ("/gsettings/list-schemas", test_list_schemas);
2987   g_test_add_func ("/gsettings/mapped", test_get_mapped);
2988   g_test_add_func ("/gsettings/get-range", test_get_range);
2989   g_test_add_func ("/gsettings/schema-source", test_schema_source);
2990   g_test_add_func ("/gsettings/schema-list-keys", test_schema_list_keys);
2991   g_test_add_func ("/gsettings/actions", test_actions);
2992   g_test_add_func ("/gsettings/null-backend", test_null_backend);
2993   g_test_add_func ("/gsettings/memory-backend", test_memory_backend);
2994   g_test_add_func ("/gsettings/read-descriptions", test_read_descriptions);
2995   g_test_add_func ("/gsettings/test-extended-schema", test_extended_schema);
2996   g_test_add_func ("/gsettings/default-value", test_default_value);
2997   g_test_add_func ("/gsettings/per-desktop", test_per_desktop);
2998   g_test_add_func ("/gsettings/per-desktop/subprocess", test_per_desktop_subprocess);
2999 
3000   result = g_test_run ();
3001 
3002   g_settings_sync ();
3003 
3004   return result;
3005 }
3006