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\"luń");
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\"luń");
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", ¶m_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