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
13static const gchar *locale_dir = ".";
14
15static 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
21typedef struct
22{
23 gchar *tmp_dir;
24} Fixture;
25
26static void
27setup (Fixture *fixture,
28 gconstpointer user_data)
29{
30 GError *error = NULL;
31
32 fixture->tmp_dir = g_dir_make_tmp (tmpl: "gio-test-gsettings_XXXXXX", error: &error);
33 g_assert_no_error (error);
34
35 g_test_message (format: "Using temporary directory: %s", fixture->tmp_dir);
36}
37
38static void
39teardown (Fixture *fixture,
40 gconstpointer user_data)
41{
42 g_assert_no_errno (g_rmdir (fixture->tmp_dir));
43 g_clear_pointer (&fixture->tmp_dir, g_free);
44}
45
46static void
47check_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 (mem: 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 */
63static void
64test_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 (schema_id: "org.gtk.test");
74
75 g_object_get (object: settings,
76 first_property_name: "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 (mem: str);
88 g_object_unref (object: b);
89 g_free (mem: path);
90
91 g_settings_get (settings, key: "greeting", format: "s", &str);
92 g_assert_cmpstr (str, ==, "Hello, earthlings");
93 g_free (mem: str);
94
95 g_settings_set (settings, key: "greeting", format: "s", "goodbye world");
96 g_settings_get (settings, key: "greeting", format: "s", &str);
97 g_assert_cmpstr (str, ==, "goodbye world");
98 g_free (mem: str);
99 str = NULL;
100
101 if (!backend_set && g_test_undefined ())
102 {
103 GSettings *tmp_settings = g_settings_new (schema_id: "org.gtk.test");
104
105 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
106 pattern: "*g_settings_set_value*expects type*");
107 g_settings_set (settings: tmp_settings, key: "greeting", format: "i", 555);
108 g_test_assert_expected_messages ();
109
110 g_object_unref (object: tmp_settings);
111 }
112
113 g_settings_get (settings, key: "greeting", format: "s", &str);
114 g_assert_cmpstr (str, ==, "goodbye world");
115 g_free (mem: str);
116 str = NULL;
117
118 g_settings_reset (settings, key: "greeting");
119 str = g_settings_get_string (settings, key: "greeting");
120 g_assert_cmpstr (str, ==, "Hello, earthlings");
121 g_free (mem: str);
122
123 g_settings_set (settings, key: "greeting", format: "s", "this is the end");
124 g_object_unref (object: settings);
125}
126
127/* Check that we get an error when getting a key
128 * that is not in the schema
129 */
130static void
131test_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 (schema_id: "org.gtk.test");
142 value = g_settings_get_value (settings, key: "no_such_key");
143
144 g_assert_null (value);
145
146 g_object_unref (object: settings);
147 return;
148 }
149 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 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 */
157static void
158test_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 (schema_id: "no.such.schema");
168
169 g_assert_null (settings);
170 return;
171 }
172 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 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 */
180static void
181test_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 (schema_id: "org.gtk.test");
190
191 g_test_expect_message (log_domain: "GLib", log_level: G_LOG_LEVEL_CRITICAL,
192 pattern: "*given value has a type of*");
193 g_test_expect_message (log_domain: "GLib", log_level: G_LOG_LEVEL_CRITICAL,
194 pattern: "*valid_format_string*");
195 g_settings_get (settings, key: "greeting", format: "o", &str);
196 g_test_assert_expected_messages ();
197
198 g_assert_null (str);
199
200 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
201 pattern: "*expects type 's'*");
202 g_settings_set (settings, key: "greeting", format: "o", "/a/path");
203 g_test_assert_expected_messages ();
204
205 g_object_unref (object: settings);
206}
207
208/* Check errors with explicit paths */
209static void
210test_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 (schema_id: "org.gtk.test", path: "/wrong-path/");
220 return;
221 }
222 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0);
223 g_test_trap_assert_failed ();
224 g_test_trap_assert_stderr ("*but path * specified by schema*");
225}
226
227static void
228test_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 (schema_id: "org.gtk.test.no-path");
238 return;
239 }
240 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 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 */
249static void
250test_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 (schema_id: "org.gtk.test.basic-types");
265
266 g_settings_get (settings, key: "test-boolean", format: "b", &b);
267 g_assert_cmpint (b, ==, 1);
268
269 g_settings_set (settings, key: "test-boolean", format: "b", 0);
270 g_settings_get (settings, key: "test-boolean", format: "b", &b);
271 g_assert_cmpint (b, ==, 0);
272
273 g_settings_get (settings, key: "test-byte", format: "y", &byte);
274 g_assert_cmpint (byte, ==, 25);
275
276 g_settings_set (settings, key: "test-byte", format: "y", G_MAXUINT8);
277 g_settings_get (settings, key: "test-byte", format: "y", &byte);
278 g_assert_cmpint (byte, ==, G_MAXUINT8);
279
280 g_settings_get (settings, key: "test-int16", format: "n", &i16);
281 g_assert_cmpint (i16, ==, -1234);
282
283 g_settings_set (settings, key: "test-int16", format: "n", G_MININT16);
284 g_settings_get (settings, key: "test-int16", format: "n", &i16);
285 g_assert_cmpint (i16, ==, G_MININT16);
286
287 g_settings_set (settings, key: "test-int16", format: "n", G_MAXINT16);
288 g_settings_get (settings, key: "test-int16", format: "n", &i16);
289 g_assert_cmpint (i16, ==, G_MAXINT16);
290
291 g_settings_get (settings, key: "test-uint16", format: "q", &u16);
292 g_assert_cmpuint (u16, ==, 1234);
293
294 g_settings_set (settings, key: "test-uint16", format: "q", G_MAXUINT16);
295 g_settings_get (settings, key: "test-uint16", format: "q", &u16);
296 g_assert_cmpuint (u16, ==, G_MAXUINT16);
297
298 g_settings_get (settings, key: "test-int32", format: "i", &i32);
299 g_assert_cmpint (i32, ==, -123456);
300
301 g_settings_set (settings, key: "test-int32", format: "i", G_MININT32);
302 g_settings_get (settings, key: "test-int32", format: "i", &i32);
303 g_assert_cmpint (i32, ==, G_MININT32);
304
305 g_settings_set (settings, key: "test-int32", format: "i", G_MAXINT32);
306 g_settings_get (settings, key: "test-int32", format: "i", &i32);
307 g_assert_cmpint (i32, ==, G_MAXINT32);
308
309 g_settings_get (settings, key: "test-uint32", format: "u", &u32);
310 g_assert_cmpuint (u32, ==, 123456);
311
312 g_settings_set (settings, key: "test-uint32", format: "u", G_MAXUINT32);
313 g_settings_get (settings, key: "test-uint32", format: "u", &u32);
314 g_assert_cmpuint (u32, ==, G_MAXUINT32);
315
316 g_settings_get (settings, key: "test-int64", format: "x", &i64);
317 g_assert_cmpuint (i64, ==, -123456789);
318
319 g_settings_set (settings, key: "test-int64", format: "x", G_MININT64);
320 g_settings_get (settings, key: "test-int64", format: "x", &i64);
321 g_assert_cmpuint (i64, ==, G_MININT64);
322
323 g_settings_set (settings, key: "test-int64", format: "x", G_MAXINT64);
324 g_settings_get (settings, key: "test-int64", format: "x", &i64);
325 g_assert_cmpuint (i64, ==, G_MAXINT64);
326
327 g_settings_get (settings, key: "test-uint64", format: "t", &u64);
328 g_assert_cmpuint (u64, ==, 123456789);
329
330 g_settings_set (settings, key: "test-uint64", format: "t", G_MAXUINT64);
331 g_settings_get (settings, key: "test-uint64", format: "t", &u64);
332 g_assert_cmpuint (u64, ==, G_MAXUINT64);
333
334 g_settings_get (settings, key: "test-double", format: "d", &d);
335 g_assert_cmpfloat (d, ==, 123.456);
336
337 g_settings_set (settings, key: "test-double", format: "d", G_MINDOUBLE);
338 g_settings_get (settings, key: "test-double", format: "d", &d);
339 g_assert_cmpfloat (d, ==, G_MINDOUBLE);
340
341 g_settings_set (settings, key: "test-double", format: "d", G_MAXDOUBLE);
342 g_settings_get (settings, key: "test-double", format: "d", &d);
343 g_assert_cmpfloat (d, ==, G_MAXDOUBLE);
344
345 g_settings_get (settings, key: "test-string", format: "s", &str);
346 g_assert_cmpstr (str, ==, "a string, it seems");
347 g_free (mem: str);
348 str = NULL;
349
350 g_settings_get (settings, key: "test-objectpath", format: "o", &str);
351 g_assert_cmpstr (str, ==, "/a/object/path");
352 g_object_unref (object: settings);
353 g_free (mem: str);
354 str = NULL;
355}
356
357/* Check that we can read an set complex types like
358 * tuples, arrays and dictionaries
359 */
360static void
361test_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 (schema_id: "org.gtk.test.complex-types");
370
371 g_settings_get (settings, key: "test-tuple", format: "(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 (mem: s) ;
376 s = NULL;
377
378 g_settings_set (settings, key: "test-tuple", format: "(s(ii))", "none", 0, 0);
379 g_settings_get (settings, key: "test-tuple", format: "(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 (mem: s);
384 s = NULL;
385
386 g_settings_get (settings, key: "test-array", format: "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, key: "test-dict", format: "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 (value: 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 (value: v);
413 g_variant_iter_free (iter);
414
415 v = g_settings_get_value (settings, key: "test-dict");
416 g_assert_cmpstr ((char *)g_variant_get_type (v), ==, "a{sau}");
417 g_variant_unref (value: v);
418
419 g_object_unref (object: settings);
420}
421
422static gboolean changed_cb_called;
423
424static void
425changed_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 */
436static void
437test_changes (void)
438{
439 GSettings *settings;
440 GSettings *settings2;
441
442 settings = g_settings_new (schema_id: "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, key: "greeting", format: "s", "new greeting");
450 g_assert_true (changed_cb_called);
451
452 settings2 = g_settings_new (schema_id: "org.gtk.test");
453
454 changed_cb_called = FALSE;
455
456 g_settings_set (settings: settings2, key: "greeting", format: "s", "hi");
457 g_assert_true (changed_cb_called);
458
459 g_object_unref (object: settings2);
460 g_object_unref (object: settings);
461}
462
463static gboolean changed_cb_called2;
464
465static void
466changed_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 */
482static void
483test_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 (schema_id: "org.gtk.test");
493 settings2 = g_settings_new (schema_id: "org.gtk.test");
494
495 g_settings_set (settings: settings2, key: "greeting", format: "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, key: "greeting", format: "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, key: "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, key: "greeting", format: "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, name: "greeting");
531 g_assert_true (writable);
532
533 g_settings_get (settings, key: "greeting", format: "s", &str);
534 g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
535 g_free (mem: str);
536 str = NULL;
537
538 v = g_settings_get_user_value (settings, key: "greeting");
539 s = g_variant_get_string (value: v, NULL);
540 g_assert_cmpstr (s, ==, "greetings from test_delay_apply");
541 g_variant_unref (value: v);
542
543 g_settings_get (settings: settings2, key: "greeting", format: "s", &str);
544 g_assert_cmpstr (str, ==, "top o' the morning");
545 g_free (mem: 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, key: "greeting", format: "s", &str);
560 g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
561 g_free (mem: str);
562 str = NULL;
563
564 g_settings_get (settings: settings2, key: "greeting", format: "s", &str);
565 g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
566 g_free (mem: 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, key: "greeting");
573 g_settings_apply (settings);
574
575 g_settings_get (settings, key: "greeting", format: "s", &str);
576 g_assert_cmpstr (str, ==, "Hello, earthlings");
577 g_free (mem: str);
578
579 g_object_unref (object: settings2);
580 g_object_unref (object: settings);
581}
582
583/* Test that reverting unapplied changes in a delay-apply
584 * settings instance works.
585 */
586static void
587test_delay_revert (void)
588{
589 GSettings *settings;
590 GSettings *settings2;
591 gchar *str;
592
593 settings = g_settings_new (schema_id: "org.gtk.test");
594 settings2 = g_settings_new (schema_id: "org.gtk.test");
595
596 g_settings_set (settings: settings2, key: "greeting", format: "s", "top o' the morning");
597
598 g_settings_get (settings, key: "greeting", format: "s", &str);
599 g_assert_cmpstr (str, ==, "top o' the morning");
600 g_free (mem: str);
601
602 g_settings_delay (settings);
603
604 g_settings_set (settings, key: "greeting", format: "s", "greetings from test_delay_revert");
605
606 g_settings_get (settings, key: "greeting", format: "s", &str);
607 g_assert_cmpstr (str, ==, "greetings from test_delay_revert");
608 g_free (mem: str);
609 str = NULL;
610
611 g_settings_get (settings: settings2, key: "greeting", format: "s", &str);
612 g_assert_cmpstr (str, ==, "top o' the morning");
613 g_free (mem: 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, key: "greeting", format: "s", &str);
623 g_assert_cmpstr (str, ==, "top o' the morning");
624 g_free (mem: str);
625 str = NULL;
626
627 g_settings_get (settings: settings2, key: "greeting", format: "s", &str);
628 g_assert_cmpstr (str, ==, "top o' the morning");
629 g_free (mem: str);
630 str = NULL;
631
632 g_object_unref (object: settings2);
633 g_object_unref (object: settings);
634}
635
636static void
637test_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 (schema_id: "org.gtk.test.basic-types");
646 g_settings_set (settings: base, key: "test-byte", format: "y", 36);
647
648 settings = g_settings_new (schema_id: "org.gtk.test");
649 g_settings_delay (settings);
650 g_object_get (object: settings, first_property_name: "delay-apply", &delay, NULL);
651 g_assert_true (delay);
652
653 child = g_settings_get_child (settings, name: "basic-types");
654 g_assert_nonnull (child);
655
656 g_object_get (object: child, first_property_name: "delay-apply", &delay, NULL);
657 g_assert_false (delay);
658
659 g_settings_get (settings: child, key: "test-byte", format: "y", &byte);
660 g_assert_cmpuint (byte, ==, 36);
661
662 g_settings_set (settings: child, key: "test-byte", format: "y", 42);
663
664 /* make sure the child was delayed too */
665 g_settings_get (settings: base, key: "test-byte", format: "y", &byte);
666 g_assert_cmpuint (byte, ==, 36);
667
668 g_object_unref (object: child);
669 g_object_unref (object: settings);
670 g_object_unref (object: base);
671}
672
673static void
674keys_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, key: "greeting", format: "s", &str);
688 g_assert_cmpstr (str, ==, "greetings from test_atomic");
689 g_free (mem: str);
690 str = NULL;
691
692 g_settings_get (settings, key: "farewell", format: "s", &str);
693 g_assert_cmpstr (str, ==, "atomic bye-bye");
694 g_free (mem: 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 */
702static void
703test_atomic (void)
704{
705 GSettings *settings;
706 GSettings *settings2;
707 gchar *str;
708
709 settings = g_settings_new (schema_id: "org.gtk.test");
710 settings2 = g_settings_new (schema_id: "org.gtk.test");
711
712 g_settings_set (settings: settings2, key: "greeting", format: "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, key: "greeting", format: "s", "greetings from test_atomic");
723 g_settings_set (settings, key: "farewell", format: "s", "atomic bye-bye");
724
725 g_settings_apply (settings);
726
727 g_settings_get (settings, key: "greeting", format: "s", &str);
728 g_assert_cmpstr (str, ==, "greetings from test_atomic");
729 g_free (mem: str);
730 str = NULL;
731
732 g_settings_get (settings, key: "farewell", format: "s", &str);
733 g_assert_cmpstr (str, ==, "atomic bye-bye");
734 g_free (mem: str);
735 str = NULL;
736
737 g_settings_get (settings: settings2, key: "greeting", format: "s", &str);
738 g_assert_cmpstr (str, ==, "greetings from test_atomic");
739 g_free (mem: str);
740 str = NULL;
741
742 g_settings_get (settings: settings2, key: "farewell", format: "s", &str);
743 g_assert_cmpstr (str, ==, "atomic bye-bye");
744 g_free (mem: str);
745 str = NULL;
746
747 g_object_unref (object: settings2);
748 g_object_unref (object: 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 */
775static void
776test_l10n (void)
777{
778 GSettings *settings;
779 gchar *str;
780 gchar *locale;
781
782 bindtextdomain (domainname: "test", dirname: locale_dir);
783 bind_textdomain_codeset (domainname: "test", codeset: "UTF-8");
784
785 locale = g_strdup (str: setlocale (LC_MESSAGES, NULL));
786
787 settings = g_settings_new (schema_id: "org.gtk.test.localized");
788
789 g_setenv (variable: "LC_MESSAGES", value: "C", TRUE);
790 setlocale (LC_MESSAGES, locale: "C");
791 str = g_settings_get_string (settings, key: "error-message");
792 g_setenv (variable: "LC_MESSAGES", value: locale, TRUE);
793 setlocale (LC_MESSAGES, locale: locale);
794
795 g_assert_cmpstr (str, ==, "Unnamed");
796 g_free (mem: str);
797 str = NULL;
798
799 g_setenv (variable: "LC_MESSAGES", value: "de_DE.UTF-8", TRUE);
800 setlocale (LC_MESSAGES, locale: "de_DE.UTF-8");
801 /* Only do the test if translation is actually working... */
802 if (g_str_equal (dgettext ("test", "\"Unnamed\""), v2: "\"Unbenannt\""))
803 {
804 str = g_settings_get_string (settings, key: "error-message");
805
806 g_assert_cmpstr (str, ==, "Unbenannt");
807 g_free (mem: str);
808 str = NULL;
809 }
810 else
811 g_printerr (format: "warning: translation is not working... skipping test. ");
812
813 g_setenv (variable: "LC_MESSAGES", value: locale, TRUE);
814 setlocale (LC_MESSAGES, locale: locale);
815 g_free (mem: locale);
816 g_object_unref (object: 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 */
826static void
827test_l10n_context (void)
828{
829 GSettings *settings;
830 gchar *str;
831 gchar *locale;
832
833 bindtextdomain (domainname: "test", dirname: locale_dir);
834 bind_textdomain_codeset (domainname: "test", codeset: "UTF-8");
835
836 locale = g_strdup (str: setlocale (LC_MESSAGES, NULL));
837
838 settings = g_settings_new (schema_id: "org.gtk.test.localized");
839
840 g_setenv (variable: "LC_MESSAGES", value: "C", TRUE);
841 setlocale (LC_MESSAGES, locale: "C");
842 g_settings_get (settings, key: "backspace", format: "s", &str);
843 g_setenv (variable: "LC_MESSAGES", value: locale, TRUE);
844 setlocale (LC_MESSAGES, locale: locale);
845
846 g_assert_cmpstr (str, ==, "BackSpace");
847 g_free (mem: str);
848 str = NULL;
849
850 g_setenv (variable: "LC_MESSAGES", value: "de_DE.UTF-8", TRUE);
851 setlocale (LC_MESSAGES, locale: "de_DE.UTF-8");
852 /* Only do the test if translation is actually working... */
853 if (g_str_equal (dgettext ("test", "\"Unnamed\""), v2: "\"Unbenannt\""))
854 {
855 g_settings_get (settings, key: "backspace", format: "s", &str);
856
857 g_assert_cmpstr (str, ==, "Löschen");
858 g_free (mem: str);
859 str = NULL;
860 }
861 else
862 g_printerr (format: "warning: translation is not working... skipping test. ");
863
864 g_setenv (variable: "LC_MESSAGES", value: locale, TRUE);
865 setlocale (LC_MESSAGES, locale: locale);
866 g_free (mem: locale);
867 g_object_unref (object: settings);
868}
869
870enum
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
891typedef 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
913typedef struct
914{
915 GObjectClass parent_class;
916} TestObjectClass;
917
918static GType test_object_get_type (void);
919G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
920
921static void
922test_object_init (TestObject *object)
923{
924}
925
926static void
927test_object_finalize (GObject *object)
928{
929 TestObject *testo = (TestObject*)object;
930 g_strfreev (str_array: testo->strv_prop);
931 g_free (mem: testo->string_prop);
932 G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
933}
934
935static void
936test_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, v_boolean: test_object->bool_prop);
947 break;
948 case PROP_ANTI_BOOL:
949 g_value_set_boolean (value, v_boolean: test_object->anti_bool_prop);
950 break;
951 case PROP_BYTE:
952 g_value_set_schar (value, v_char: test_object->byte_prop);
953 break;
954 case PROP_UINT16:
955 g_value_set_uint (value, v_uint: test_object->uint16_prop);
956 break;
957 case PROP_INT16:
958 g_value_set_int (value, v_int: test_object->int16_prop);
959 break;
960 case PROP_INT:
961 g_value_set_int (value, v_int: test_object->int_prop);
962 break;
963 case PROP_UINT:
964 g_value_set_uint (value, v_uint: test_object->uint_prop);
965 break;
966 case PROP_INT64:
967 g_value_set_int64 (value, v_int64: test_object->int64_prop);
968 break;
969 case PROP_UINT64:
970 g_value_set_uint64 (value, v_uint64: test_object->uint64_prop);
971 break;
972 case PROP_DOUBLE:
973 g_value_set_double (value, v_double: test_object->double_prop);
974 break;
975 case PROP_STRING:
976 g_value_set_string (value, v_string: test_object->string_prop);
977 break;
978 case PROP_NO_WRITE:
979 g_value_set_string (value, v_string: test_object->no_write_prop);
980 break;
981 case PROP_STRV:
982 g_value_set_boxed (value, v_boxed: test_object->strv_prop);
983 break;
984 case PROP_ENUM:
985 g_value_set_enum (value, v_enum: test_object->enum_prop);
986 break;
987 case PROP_FLAGS:
988 g_value_set_flags (value, v_flags: test_object->flags_prop);
989 break;
990 default:
991 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
992 break;
993 }
994}
995
996static void
997test_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 (mem: test_object->string_prop);
1038 test_object->string_prop = g_value_dup_string (value);
1039 break;
1040 case PROP_NO_READ:
1041 g_free (mem: 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 (str_array: 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
1060static GType
1061test_enum_get_type (void)
1062{
1063 static 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 (name: "TestEnum", const_static_values: values);
1076 g_once_init_leave (&define_type_id, type_id);
1077 }
1078
1079 return define_type_id;
1080}
1081
1082static GType
1083test_flags_get_type (void)
1084{
1085 static 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 (name: "TestFlags", const_static_values: values);
1098 g_once_init_leave (&define_type_id, type_id);
1099 }
1100
1101 return define_type_id;
1102}
1103
1104static void
1105test_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 (oclass: gobject_class, property_id: PROP_BOOL,
1114 pspec: g_param_spec_boolean (name: "bool", nick: "", blurb: "", FALSE, flags: G_PARAM_READWRITE));
1115 g_object_class_install_property (oclass: gobject_class, property_id: PROP_ANTI_BOOL,
1116 pspec: g_param_spec_boolean (name: "anti-bool", nick: "", blurb: "", FALSE, flags: G_PARAM_READWRITE));
1117 g_object_class_install_property (oclass: gobject_class, property_id: PROP_BYTE,
1118 pspec: g_param_spec_char (name: "byte", nick: "", blurb: "", G_MININT8, G_MAXINT8, default_value: 0, flags: G_PARAM_READWRITE));
1119 g_object_class_install_property (oclass: gobject_class, property_id: PROP_INT16,
1120 pspec: g_param_spec_int (name: "int16", nick: "", blurb: "", minimum: -G_MAXINT16, G_MAXINT16, default_value: 0, flags: G_PARAM_READWRITE));
1121 g_object_class_install_property (oclass: gobject_class, property_id: PROP_UINT16,
1122 pspec: g_param_spec_uint (name: "uint16", nick: "", blurb: "", minimum: 0, G_MAXUINT16, default_value: 0, flags: G_PARAM_READWRITE));
1123 g_object_class_install_property (oclass: gobject_class, property_id: PROP_INT,
1124 pspec: g_param_spec_int (name: "int", nick: "", blurb: "", G_MININT, G_MAXINT, default_value: 0, flags: G_PARAM_READWRITE));
1125 g_object_class_install_property (oclass: gobject_class, property_id: PROP_UINT,
1126 pspec: g_param_spec_uint (name: "uint", nick: "", blurb: "", minimum: 0, G_MAXUINT, default_value: 0, flags: G_PARAM_READWRITE));
1127 g_object_class_install_property (oclass: gobject_class, property_id: PROP_INT64,
1128 pspec: g_param_spec_int64 (name: "int64", nick: "", blurb: "", G_MININT64, G_MAXINT64, default_value: 0, flags: G_PARAM_READWRITE));
1129 g_object_class_install_property (oclass: gobject_class, property_id: PROP_UINT64,
1130 pspec: g_param_spec_uint64 (name: "uint64", nick: "", blurb: "", minimum: 0, G_MAXUINT64, default_value: 0, flags: G_PARAM_READWRITE));
1131 g_object_class_install_property (oclass: gobject_class, property_id: PROP_DOUBLE,
1132 pspec: g_param_spec_double (name: "double", nick: "", blurb: "", minimum: -G_MAXDOUBLE, G_MAXDOUBLE, default_value: 0.0, flags: G_PARAM_READWRITE));
1133 g_object_class_install_property (oclass: gobject_class, property_id: PROP_STRING,
1134 pspec: g_param_spec_string (name: "string", nick: "", blurb: "", NULL, flags: G_PARAM_READWRITE));
1135 g_object_class_install_property (oclass: gobject_class, property_id: PROP_NO_WRITE,
1136 pspec: g_param_spec_string (name: "no-write", nick: "", blurb: "", NULL, flags: G_PARAM_READABLE));
1137 g_object_class_install_property (oclass: gobject_class, property_id: PROP_NO_READ,
1138 pspec: g_param_spec_string (name: "no-read", nick: "", blurb: "", NULL, flags: G_PARAM_WRITABLE));
1139 g_object_class_install_property (oclass: gobject_class, property_id: PROP_STRV,
1140 pspec: g_param_spec_boxed (name: "strv", nick: "", blurb: "", G_TYPE_STRV, flags: G_PARAM_READWRITE));
1141 g_object_class_install_property (oclass: gobject_class, property_id: PROP_ENUM,
1142 pspec: g_param_spec_enum (name: "enum", nick: "", blurb: "", enum_type: test_enum_get_type (), default_value: TEST_ENUM_FOO, flags: G_PARAM_READWRITE));
1143 g_object_class_install_property (oclass: gobject_class, property_id: PROP_FLAGS,
1144 pspec: g_param_spec_flags (name: "flags", nick: "", blurb: "", flags_type: test_flags_get_type (), default_value: TEST_FLAGS_NONE, flags: G_PARAM_READWRITE));
1145}
1146
1147static TestObject *
1148test_object_new (void)
1149{
1150 return (TestObject*)g_object_new (object_type: 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 */
1157static void
1158test_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 (schema_id: "org.gtk.test.binding");
1178 obj = test_object_new ();
1179
1180 g_settings_bind (settings, key: "bool", object: obj, property: "bool", flags: G_SETTINGS_BIND_DEFAULT);
1181 g_object_set (object: obj, first_property_name: "bool", TRUE, NULL);
1182 g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
1183
1184 g_settings_set_boolean (settings, key: "bool", FALSE);
1185 b = TRUE;
1186 g_object_get (object: obj, first_property_name: "bool", &b, NULL);
1187 g_assert_cmpint (b, ==, FALSE);
1188
1189 g_settings_bind (settings, key: "anti-bool", object: obj, property: "anti-bool",
1190 flags: G_SETTINGS_BIND_INVERT_BOOLEAN);
1191 g_object_set (object: obj, first_property_name: "anti-bool", FALSE, NULL);
1192 g_assert_cmpint (g_settings_get_boolean (settings, "anti-bool"), ==, TRUE);
1193
1194 g_settings_set_boolean (settings, key: "anti-bool", FALSE);
1195 b = FALSE;
1196 g_object_get (object: obj, first_property_name: "anti-bool", &b, NULL);
1197 g_assert_cmpint (b, ==, TRUE);
1198
1199 g_settings_bind (settings, key: "byte", object: obj, property: "byte", flags: G_SETTINGS_BIND_DEFAULT);
1200
1201 g_object_set (object: obj, first_property_name: "byte", 123, NULL);
1202 y = 'c';
1203 g_settings_get (settings, key: "byte", format: "y", &y);
1204 g_assert_cmpint (y, ==, 123);
1205
1206 g_settings_set (settings, key: "byte", format: "y", 54);
1207 y = 'c';
1208 g_object_get (object: obj, first_property_name: "byte", &y, NULL);
1209 g_assert_cmpint (y, ==, 54);
1210
1211 g_settings_bind (settings, key: "int16", object: obj, property: "int16", flags: G_SETTINGS_BIND_DEFAULT);
1212
1213 g_object_set (object: obj, first_property_name: "int16", 1234, NULL);
1214 n = 4321;
1215 g_settings_get (settings, key: "int16", format: "n", &n);
1216 g_assert_cmpint (n, ==, 1234);
1217
1218 g_settings_set (settings, key: "int16", format: "n", 4321);
1219 n2 = 1111;
1220 g_object_get (object: obj, first_property_name: "int16", &n2, NULL);
1221 g_assert_cmpint (n2, ==, 4321);
1222
1223 g_settings_bind (settings, key: "uint16", object: obj, property: "uint16", flags: G_SETTINGS_BIND_DEFAULT);
1224
1225 g_object_set (object: obj, first_property_name: "uint16", (guint16) G_MAXUINT16, NULL);
1226 q = 1111;
1227 g_settings_get (settings, key: "uint16", format: "q", &q);
1228 g_assert_cmpuint (q, ==, G_MAXUINT16);
1229
1230 g_settings_set (settings, key: "uint16", format: "q", (guint16) G_MAXINT16);
1231 q2 = 1111;
1232 g_object_get (object: obj, first_property_name: "uint16", &q2, NULL);
1233 g_assert_cmpuint (q2, ==, (guint16) G_MAXINT16);
1234
1235 g_settings_bind (settings, key: "int", object: obj, property: "int", flags: G_SETTINGS_BIND_DEFAULT);
1236
1237 g_object_set (object: obj, first_property_name: "int", 12345, NULL);
1238 g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1239
1240 g_settings_set_int (settings, key: "int", value: 54321);
1241 i = 1111;
1242 g_object_get (object: obj, first_property_name: "int", &i, NULL);
1243 g_assert_cmpint (i, ==, 54321);
1244
1245 g_settings_bind (settings, key: "uint", object: obj, property: "uint", flags: G_SETTINGS_BIND_DEFAULT);
1246
1247 g_object_set (object: obj, first_property_name: "uint", 12345, NULL);
1248 g_assert_cmpuint (g_settings_get_uint (settings, "uint"), ==, 12345);
1249
1250 g_settings_set_uint (settings, key: "uint", value: 54321);
1251 u = 1111;
1252 g_object_get (object: obj, first_property_name: "uint", &u, NULL);
1253 g_assert_cmpuint (u, ==, 54321);
1254
1255 g_settings_bind (settings, key: "uint64", object: obj, property: "uint64", flags: G_SETTINGS_BIND_DEFAULT);
1256
1257 g_object_set (object: obj, first_property_name: "uint64", (guint64) 12345, NULL);
1258 g_assert_cmpuint (g_settings_get_uint64 (settings, "uint64"), ==, 12345);
1259
1260 g_settings_set_uint64 (settings, key: "uint64", value: 54321);
1261 u64 = 1111;
1262 g_object_get (object: obj, first_property_name: "uint64", &u64, NULL);
1263 g_assert_cmpuint (u64, ==, 54321);
1264
1265 g_settings_bind (settings, key: "int64", object: obj, property: "int64", flags: G_SETTINGS_BIND_DEFAULT);
1266
1267 g_object_set (object: obj, first_property_name: "int64", (gint64) G_MAXINT64, NULL);
1268 i64 = 1111;
1269 g_settings_get (settings, key: "int64", format: "x", &i64);
1270 g_assert_cmpint (i64, ==, G_MAXINT64);
1271
1272 g_settings_set (settings, key: "int64", format: "x", (gint64) G_MININT64);
1273 i64 = 1111;
1274 g_object_get (object: obj, first_property_name: "int64", &i64, NULL);
1275 g_assert_cmpint (i64, ==, G_MININT64);
1276
1277 g_settings_bind (settings, key: "uint64", object: obj, property: "uint64", flags: G_SETTINGS_BIND_DEFAULT);
1278
1279 g_object_set (object: obj, first_property_name: "uint64", (guint64) G_MAXUINT64, NULL);
1280 u64 = 1111;
1281 g_settings_get (settings, key: "uint64", format: "t", &u64);
1282 g_assert_cmpuint (u64, ==, G_MAXUINT64);
1283
1284 g_settings_set (settings, key: "uint64", format: "t", (guint64) G_MAXINT64);
1285 u64 = 1111;
1286 g_object_get (object: obj, first_property_name: "uint64", &u64, NULL);
1287 g_assert_cmpuint (u64, ==, (guint64) G_MAXINT64);
1288
1289 g_settings_bind (settings, key: "string", object: obj, property: "string", flags: G_SETTINGS_BIND_DEFAULT);
1290
1291 g_object_set (object: obj, first_property_name: "string", "bu ba", NULL);
1292 s = g_settings_get_string (settings, key: "string");
1293 g_assert_cmpstr (s, ==, "bu ba");
1294 g_free (mem: s);
1295
1296 g_settings_set_string (settings, key: "string", value: "bla bla");
1297 g_object_get (object: obj, first_property_name: "string", &s, NULL);
1298 g_assert_cmpstr (s, ==, "bla bla");
1299 g_free (mem: s);
1300
1301 g_settings_bind (settings, key: "chararray", object: obj, property: "string", flags: G_SETTINGS_BIND_DEFAULT);
1302
1303 g_object_set (object: obj, first_property_name: "string", "non-unicode:\315", NULL);
1304 value = g_settings_get_value (settings, key: "chararray");
1305 g_assert_cmpstr (g_variant_get_bytestring (value), ==, "non-unicode:\315");
1306 g_variant_unref (value);
1307
1308 g_settings_bind (settings, key: "double", object: obj, property: "double", flags: G_SETTINGS_BIND_DEFAULT);
1309
1310 g_object_set (object: obj, first_property_name: "double", G_MAXFLOAT, NULL);
1311 g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXFLOAT);
1312
1313 g_settings_set_double (settings, key: "double", G_MINFLOAT);
1314 d = 1.0;
1315 g_object_get (object: obj, first_property_name: "double", &d, NULL);
1316 g_assert_cmpfloat (d, ==, G_MINFLOAT);
1317
1318 g_object_set (object: obj, first_property_name: "double", G_MAXDOUBLE, NULL);
1319 g_assert_cmpfloat (g_settings_get_double (settings, "double"), ==, G_MAXDOUBLE);
1320
1321 g_settings_set_double (settings, key: "double", value: -G_MINDOUBLE);
1322 d = 1.0;
1323 g_object_get (object: obj, first_property_name: "double", &d, NULL);
1324 g_assert_cmpfloat (d, ==, -G_MINDOUBLE);
1325
1326 strv = g_strsplit (string: "plastic bag,middle class,polyethylene", delimiter: ",", max_tokens: 0);
1327 g_settings_bind (settings, key: "strv", object: obj, property: "strv", flags: G_SETTINGS_BIND_DEFAULT);
1328 g_object_set (object: obj, first_property_name: "strv", strv, NULL);
1329 g_strfreev (str_array: strv);
1330 strv = g_settings_get_strv (settings, key: "strv");
1331 s = g_strjoinv (separator: ",", str_array: strv);
1332 g_assert_cmpstr (s, ==, "plastic bag,middle class,polyethylene");
1333 g_strfreev (str_array: strv);
1334 g_free (mem: s);
1335 strv = g_strsplit (string: "decaffeinate,unleaded,keep all surfaces clean", delimiter: ",", max_tokens: 0);
1336 g_settings_set_strv (settings, key: "strv", value: (const gchar **) strv);
1337 g_strfreev (str_array: strv);
1338 g_object_get (object: obj, first_property_name: "strv", &strv, NULL);
1339 s = g_strjoinv (separator: ",", str_array: strv);
1340 g_assert_cmpstr (s, ==, "decaffeinate,unleaded,keep all surfaces clean");
1341 g_strfreev (str_array: strv);
1342 g_free (mem: s);
1343 g_settings_set_strv (settings, key: "strv", NULL);
1344 g_object_get (object: obj, first_property_name: "strv", &strv, NULL);
1345 g_assert_nonnull (strv);
1346 g_assert_cmpint (g_strv_length (strv), ==, 0);
1347 g_strfreev (str_array: strv);
1348
1349 g_settings_bind (settings, key: "enum", object: obj, property: "enum", flags: G_SETTINGS_BIND_DEFAULT);
1350 g_object_set (object: obj, first_property_name: "enum", TEST_ENUM_BAZ, NULL);
1351 s = g_settings_get_string (settings, key: "enum");
1352 g_assert_cmpstr (s, ==, "baz");
1353 g_free (mem: s);
1354 g_assert_cmpint (g_settings_get_enum (settings, "enum"), ==, TEST_ENUM_BAZ);
1355
1356 g_settings_set_enum (settings, key: "enum", value: TEST_ENUM_QUUX);
1357 i = 230;
1358 g_object_get (object: obj, first_property_name: "enum", &i, NULL);
1359 g_assert_cmpint (i, ==, TEST_ENUM_QUUX);
1360
1361 g_settings_set_string (settings, key: "enum", value: "baz");
1362 i = 230;
1363 g_object_get (object: obj, first_property_name: "enum", &i, NULL);
1364 g_assert_cmpint (i, ==, TEST_ENUM_BAZ);
1365
1366 g_settings_bind (settings, key: "flags", object: obj, property: "flags", flags: G_SETTINGS_BIND_DEFAULT);
1367 g_object_set (object: obj, first_property_name: "flags", TEST_FLAGS_MOURNING, NULL);
1368 strv = g_settings_get_strv (settings, key: "flags");
1369 g_assert_cmpint (g_strv_length (strv), ==, 1);
1370 g_assert_cmpstr (strv[0], ==, "mourning");
1371 g_strfreev (str_array: strv);
1372
1373 g_assert_cmpint (g_settings_get_flags (settings, "flags"), ==, TEST_FLAGS_MOURNING);
1374
1375 g_settings_set_flags (settings, key: "flags", value: TEST_FLAGS_MOURNING | TEST_FLAGS_WALKING);
1376 i = 230;
1377 g_object_get (object: obj, first_property_name: "flags", &i, NULL);
1378 g_assert_cmpint (i, ==, TEST_FLAGS_MOURNING | TEST_FLAGS_WALKING);
1379
1380 g_settings_bind (settings, key: "uint", object: obj, property: "uint", flags: G_SETTINGS_BIND_DEFAULT);
1381
1382 g_object_set (object: obj, first_property_name: "uint", 12345, NULL);
1383 g_assert_cmpuint (g_settings_get_uint (settings, "uint"), ==, 12345);
1384
1385 g_settings_set_uint (settings, key: "uint", value: 54321);
1386 u = 1111;
1387 g_object_get (object: obj, first_property_name: "uint", &u, NULL);
1388 g_assert_cmpuint (u, ==, 54321);
1389
1390 g_settings_bind (settings, key: "range", object: obj, property: "uint", flags: G_SETTINGS_BIND_DEFAULT);
1391 g_object_set (object: obj, first_property_name: "uint", 22, NULL);
1392 u = 1111;
1393 g_assert_cmpuint (g_settings_get_uint (settings, "range"), ==, 22);
1394 g_object_get (object: obj, first_property_name: "uint", &u, NULL);
1395 g_assert_cmpuint (u, ==, 22);
1396
1397 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
1398 pattern: "* is out of schema-specified range for*");
1399 g_object_set (object: obj, first_property_name: "uint", 45, NULL);
1400 g_test_assert_expected_messages ();
1401 u = 1111;
1402 g_object_get (object: obj, first_property_name: "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 (object: obj);
1408 g_object_unref (object: settings);
1409}
1410
1411static void
1412test_unbind (void)
1413{
1414 TestObject *obj;
1415 GSettings *settings;
1416
1417 settings = g_settings_new (schema_id: "org.gtk.test.binding");
1418 obj = test_object_new ();
1419
1420 g_settings_bind (settings, key: "int", object: obj, property: "int", flags: G_SETTINGS_BIND_DEFAULT);
1421
1422 g_object_set (object: obj, first_property_name: "int", 12345, NULL);
1423 g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1424
1425 g_settings_unbind (object: obj, property: "int");
1426
1427 g_object_set (object: obj, first_property_name: "int", 54321, NULL);
1428 g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 12345);
1429
1430 g_object_unref (object: obj);
1431 g_object_unref (object: settings);
1432}
1433
1434static void
1435test_bind_writable (void)
1436{
1437 TestObject *obj;
1438 GSettings *settings;
1439 gboolean b;
1440
1441 settings = g_settings_new (schema_id: "org.gtk.test.binding");
1442 obj = test_object_new ();
1443
1444 g_object_set (object: obj, first_property_name: "bool", FALSE, NULL);
1445
1446 g_settings_bind_writable (settings, key: "int", object: obj, property: "bool", FALSE);
1447
1448 g_object_get (object: obj, first_property_name: "bool", &b, NULL);
1449 g_assert_true (b);
1450
1451 g_settings_unbind (object: obj, property: "bool");
1452
1453 g_settings_bind_writable (settings, key: "int", object: obj, property: "bool", TRUE);
1454
1455 g_object_get (object: obj, first_property_name: "bool", &b, NULL);
1456 g_assert_false (b);
1457
1458 g_object_unref (object: obj);
1459 g_object_unref (object: 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 */
1466static void
1467test_directional_binding (void)
1468{
1469 TestObject *obj;
1470 GSettings *settings;
1471 gboolean b;
1472 gint i;
1473
1474 settings = g_settings_new (schema_id: "org.gtk.test.binding");
1475 obj = test_object_new ();
1476
1477 g_object_set (object: obj, first_property_name: "bool", FALSE, NULL);
1478 g_settings_set_boolean (settings, key: "bool", FALSE);
1479
1480 g_settings_bind (settings, key: "bool", object: obj, property: "bool", flags: G_SETTINGS_BIND_GET);
1481
1482 g_settings_set_boolean (settings, key: "bool", TRUE);
1483 g_object_get (object: obj, first_property_name: "bool", &b, NULL);
1484 g_assert_cmpint (b, ==, TRUE);
1485
1486 g_object_set (object: obj, first_property_name: "bool", FALSE, NULL);
1487 g_assert_cmpint (g_settings_get_boolean (settings, "bool"), ==, TRUE);
1488
1489 g_object_set (object: obj, first_property_name: "int", 20, NULL);
1490 g_settings_set_int (settings, key: "int", value: 20);
1491
1492 g_settings_bind (settings, key: "int", object: obj, property: "int", flags: G_SETTINGS_BIND_SET);
1493
1494 g_object_set (object: obj, first_property_name: "int", 32, NULL);
1495 g_assert_cmpint (g_settings_get_int (settings, "int"), ==, 32);
1496
1497 g_settings_set_int (settings, key: "int", value: 20);
1498 g_object_get (object: obj, first_property_name: "int", &i, NULL);
1499 g_assert_cmpint (i, ==, 32);
1500
1501 g_object_unref (object: obj);
1502 g_object_unref (object: settings);
1503}
1504
1505/* Test that type mismatch is caught when creating a binding */
1506static void
1507test_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 (schema_id: "org.gtk.test.binding");
1518 obj = test_object_new ();
1519
1520 g_settings_bind (settings, key: "string", object: obj, property: "int", flags: G_SETTINGS_BIND_DEFAULT);
1521
1522 g_object_unref (object: obj);
1523 g_object_unref (object: settings);
1524 return;
1525 }
1526 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0);
1527 g_test_trap_assert_failed ();
1528 g_test_trap_assert_stderr ("*not compatible*");
1529}
1530
1531static gboolean
1532string_to_bool (GValue *value,
1533 GVariant *variant,
1534 gpointer user_data)
1535{
1536 const gchar *s;
1537
1538 s = g_variant_get_string (value: variant, NULL);
1539 g_value_set_boolean (value, v_boolean: g_strcmp0 (str1: s, str2: "true") == 0);
1540
1541 return TRUE;
1542}
1543
1544static GVariant *
1545bool_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 (string: "true");
1551 else
1552 return g_variant_new_string (string: "false");
1553}
1554
1555static GVariant *
1556bool_to_bool (const GValue *value,
1557 const GVariantType *expected_type,
1558 gpointer user_data)
1559{
1560 return g_variant_new_boolean (value: g_value_get_boolean (value));
1561}
1562
1563/* Test custom bindings.
1564 * Translate strings to booleans and back
1565 */
1566static void
1567test_custom_binding (void)
1568{
1569 TestObject *obj;
1570 GSettings *settings;
1571 gchar *s;
1572 gboolean b;
1573
1574 settings = g_settings_new (schema_id: "org.gtk.test.binding");
1575 obj = test_object_new ();
1576
1577 g_settings_set_string (settings, key: "string", value: "true");
1578
1579 g_settings_bind_with_mapping (settings, key: "string",
1580 object: obj, property: "bool",
1581 flags: G_SETTINGS_BIND_DEFAULT,
1582 get_mapping: string_to_bool,
1583 set_mapping: bool_to_string,
1584 NULL, NULL);
1585
1586 g_settings_set_string (settings, key: "string", value: "false");
1587 g_object_get (object: obj, first_property_name: "bool", &b, NULL);
1588 g_assert_cmpint (b, ==, FALSE);
1589
1590 g_settings_set_string (settings, key: "string", value: "not true");
1591 g_object_get (object: obj, first_property_name: "bool", &b, NULL);
1592 g_assert_cmpint (b, ==, FALSE);
1593
1594 g_object_set (object: obj, first_property_name: "bool", TRUE, NULL);
1595 s = g_settings_get_string (settings, key: "string");
1596 g_assert_cmpstr (s, ==, "true");
1597 g_free (mem: s);
1598
1599 g_settings_bind_with_mapping (settings, key: "string",
1600 object: obj, property: "bool",
1601 flags: G_SETTINGS_BIND_DEFAULT,
1602 get_mapping: string_to_bool, set_mapping: bool_to_bool,
1603 NULL, NULL);
1604 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
1605 pattern: "*binding mapping function for key 'string' returned"
1606 " GVariant of type 'b' when type 's' was requested*");
1607 g_object_set (object: obj, first_property_name: "bool", FALSE, NULL);
1608 g_test_assert_expected_messages ();
1609
1610 g_object_unref (object: obj);
1611 g_object_unref (object: 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 */
1619static void
1620test_no_change_binding (void)
1621{
1622 TestObject *obj;
1623 GSettings *settings;
1624 gboolean b;
1625
1626 settings = g_settings_new (schema_id: "org.gtk.test.binding");
1627 obj = test_object_new ();
1628
1629 g_object_set (object: obj, first_property_name: "bool", TRUE, NULL);
1630 g_settings_set_boolean (settings, key: "bool", FALSE);
1631
1632 g_settings_bind (settings, key: "bool", object: obj, property: "bool", flags: G_SETTINGS_BIND_GET_NO_CHANGES);
1633
1634 g_object_get (object: obj, first_property_name: "bool", &b, NULL);
1635 g_assert_cmpint (b, ==, FALSE);
1636
1637 g_settings_set_boolean (settings, key: "bool", TRUE);
1638 g_object_get (object: obj, first_property_name: "bool", &b, NULL);
1639 g_assert_cmpint (b, ==, FALSE);
1640
1641 g_settings_set_boolean (settings, key: "bool", FALSE);
1642 g_object_set (object: obj, first_property_name: "bool", TRUE, NULL);
1643 b = g_settings_get_boolean (settings, key: "bool");
1644 g_assert_cmpint (b, ==, TRUE);
1645
1646 g_object_unref (object: obj);
1647 g_object_unref (object: settings);
1648}
1649
1650/* Test that binding a non-readable property only
1651 * works in 'GET' mode.
1652 */
1653static void
1654test_no_read_binding_fail (void)
1655{
1656 TestObject *obj;
1657 GSettings *settings;
1658
1659 settings = g_settings_new (schema_id: "org.gtk.test.binding");
1660 obj = test_object_new ();
1661
1662 g_settings_bind (settings, key: "string", object: obj, property: "no-read", flags: 0);
1663}
1664
1665static void
1666test_no_read_binding_pass (void)
1667{
1668 TestObject *obj;
1669 GSettings *settings;
1670
1671 settings = g_settings_new (schema_id: "org.gtk.test.binding");
1672 obj = test_object_new ();
1673
1674 g_settings_bind (settings, key: "string", object: obj, property: "no-read", flags: G_SETTINGS_BIND_GET);
1675
1676 exit (status: 0);
1677}
1678
1679static void
1680test_no_read_binding (void)
1681{
1682 if (g_test_undefined ())
1683 {
1684 g_test_trap_subprocess (test_path: "/gsettings/no-read-binding/subprocess/fail", usec_timeout: 0, test_flags: 0);
1685 g_test_trap_assert_failed ();
1686 g_test_trap_assert_stderr ("*property*is not readable*");
1687 }
1688
1689 g_test_trap_subprocess (test_path: "/gsettings/no-read-binding/subprocess/pass", usec_timeout: 0, test_flags: 0);
1690 g_test_trap_assert_passed ();
1691}
1692
1693/* Test that binding a non-writable property only
1694 * works in 'SET' mode.
1695 */
1696static void
1697test_no_write_binding_fail (void)
1698{
1699 TestObject *obj;
1700 GSettings *settings;
1701
1702 settings = g_settings_new (schema_id: "org.gtk.test.binding");
1703 obj = test_object_new ();
1704
1705 g_settings_bind (settings, key: "string", object: obj, property: "no-write", flags: 0);
1706}
1707
1708static void
1709test_no_write_binding_pass (void)
1710{
1711 TestObject *obj;
1712 GSettings *settings;
1713
1714 settings = g_settings_new (schema_id: "org.gtk.test.binding");
1715 obj = test_object_new ();
1716
1717 g_settings_bind (settings, key: "string", object: obj, property: "no-write", flags: G_SETTINGS_BIND_SET);
1718
1719 exit (status: 0);
1720}
1721
1722static void
1723test_no_write_binding (void)
1724{
1725 if (g_test_undefined ())
1726 {
1727 g_test_trap_subprocess (test_path: "/gsettings/no-write-binding/subprocess/fail", usec_timeout: 0, test_flags: 0);
1728 g_test_trap_assert_failed ();
1729 g_test_trap_assert_stderr ("*property*is not writable*");
1730 }
1731
1732 g_test_trap_subprocess (test_path: "/gsettings/no-write-binding/subprocess/pass", usec_timeout: 0, test_flags: 0);
1733 g_test_trap_assert_passed ();
1734}
1735
1736static void
1737key_changed_cb (GSettings *settings, const gchar *key, gpointer data)
1738{
1739 gboolean *b = data;
1740 (*b) = TRUE;
1741}
1742
1743typedef struct
1744{
1745 const gchar *path;
1746 const gchar *root_group;
1747 const gchar *keyfile_group;
1748 const gchar *root_path;
1749} KeyfileTestData;
1750
1751/*
1752 * Test that using a keyfile works
1753 */
1754static void
1755test_keyfile (Fixture *fixture,
1756 gconstpointer user_data)
1757{
1758 GSettingsBackend *kf_backend;
1759 GSettings *settings;
1760 GKeyFile *keyfile;
1761 gchar *str;
1762 gboolean writable;
1763 GError *error = NULL;
1764 gchar *data;
1765 gsize len;
1766 gboolean called = FALSE;
1767 gchar *keyfile_path = NULL, *store_path = NULL;
1768
1769 keyfile_path = g_build_filename (first_element: fixture->tmp_dir, "keyfile", NULL);
1770 store_path = g_build_filename (first_element: keyfile_path, "gsettings.store", NULL);
1771 kf_backend = g_keyfile_settings_backend_new (filename: store_path, root_path: "/", root_group: "root");
1772 settings = g_settings_new_with_backend (schema_id: "org.gtk.test", backend: kf_backend);
1773 g_object_unref (object: kf_backend);
1774
1775 g_settings_reset (settings, key: "greeting");
1776 str = g_settings_get_string (settings, key: "greeting");
1777 g_assert_cmpstr (str, ==, "Hello, earthlings");
1778 g_free (mem: str);
1779
1780 writable = g_settings_is_writable (settings, name: "greeting");
1781 g_assert_true (writable);
1782 g_settings_set (settings, key: "greeting", format: "s", "see if this works");
1783
1784 str = g_settings_get_string (settings, key: "greeting");
1785 g_assert_cmpstr (str, ==, "see if this works");
1786 g_free (mem: str);
1787
1788 g_settings_delay (settings);
1789 g_settings_set (settings, key: "farewell", format: "s", "cheerio");
1790 g_settings_apply (settings);
1791
1792 keyfile = g_key_file_new ();
1793 g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1794
1795 str = g_key_file_get_string (key_file: keyfile, group_name: "tests", key: "greeting", NULL);
1796 g_assert_cmpstr (str, ==, "'see if this works'");
1797 g_free (mem: str);
1798
1799 str = g_key_file_get_string (key_file: keyfile, group_name: "tests", key: "farewell", NULL);
1800 g_assert_cmpstr (str, ==, "'cheerio'");
1801 g_free (mem: str);
1802 g_key_file_free (key_file: keyfile);
1803
1804 g_settings_reset (settings, key: "greeting");
1805 g_settings_apply (settings);
1806 keyfile = g_key_file_new ();
1807 g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1808
1809 str = g_key_file_get_string (key_file: keyfile, group_name: "tests", key: "greeting", NULL);
1810 g_assert_null (str);
1811
1812 called = FALSE;
1813 g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
1814
1815 g_key_file_set_string (key_file: keyfile, group_name: "tests", key: "greeting", string: "'howdy'");
1816 data = g_key_file_to_data (key_file: keyfile, length: &len, NULL);
1817 g_file_set_contents (filename: store_path, contents: data, length: len, error: &error);
1818 g_assert_no_error (error);
1819 while (!called)
1820 g_main_context_iteration (NULL, FALSE);
1821 g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
1822
1823 str = g_settings_get_string (settings, key: "greeting");
1824 g_assert_cmpstr (str, ==, "howdy");
1825 g_free (mem: str);
1826
1827 /* Now check setting a string without quotes */
1828 called = FALSE;
1829 g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
1830
1831 g_key_file_set_string (key_file: keyfile, group_name: "tests", key: "greeting", string: "he\"l🤗uÅ„");
1832 g_free (mem: data);
1833 data = g_key_file_to_data (key_file: keyfile, length: &len, NULL);
1834 g_file_set_contents (filename: store_path, contents: data, length: len, error: &error);
1835 g_assert_no_error (error);
1836 while (!called)
1837 g_main_context_iteration (NULL, FALSE);
1838 g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
1839
1840 str = g_settings_get_string (settings, key: "greeting");
1841 g_assert_cmpstr (str, ==, "he\"l🤗uń");
1842 g_free (mem: str);
1843
1844 g_settings_set (settings, key: "farewell", format: "s", "cheerio");
1845
1846 /* Check that empty keys/groups are not allowed. */
1847 g_assert_false (g_settings_is_writable (settings, ""));
1848 g_assert_false (g_settings_is_writable (settings, "/"));
1849
1850 /* When executing as root, changing the mode of the keyfile will have
1851 * no effect on the writability of the settings.
1852 */
1853 if (geteuid () != 0)
1854 {
1855 called = FALSE;
1856 g_signal_connect (settings, "writable-changed::greeting",
1857 G_CALLBACK (key_changed_cb), &called);
1858
1859 g_assert_no_errno (g_chmod (keyfile_path, 0500));
1860 while (!called)
1861 g_main_context_iteration (NULL, FALSE);
1862 g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
1863
1864 writable = g_settings_is_writable (settings, name: "greeting");
1865 g_assert_false (writable);
1866 }
1867
1868 g_key_file_free (key_file: keyfile);
1869 g_free (mem: data);
1870
1871 g_object_unref (object: settings);
1872
1873 /* Clean up the temporary directory. */
1874 g_assert_no_errno (g_chmod (keyfile_path, 0777));
1875 g_assert_no_errno (g_remove (store_path));
1876 g_assert_no_errno (g_rmdir (keyfile_path));
1877 g_free (mem: store_path);
1878 g_free (mem: keyfile_path);
1879}
1880
1881/*
1882 * Test that using a keyfile works with a schema with no path set.
1883 */
1884static void
1885test_keyfile_no_path (Fixture *fixture,
1886 gconstpointer user_data)
1887{
1888 const KeyfileTestData *test_data = user_data;
1889 GSettingsBackend *kf_backend;
1890 GSettings *settings;
1891 GKeyFile *keyfile;
1892 gboolean writable;
1893 gchar *key = NULL;
1894 GError *error = NULL;
1895 gchar *keyfile_path = NULL, *store_path = NULL;
1896
1897 keyfile_path = g_build_filename (first_element: fixture->tmp_dir, "keyfile", NULL);
1898 store_path = g_build_filename (first_element: keyfile_path, "gsettings.store", NULL);
1899 kf_backend = g_keyfile_settings_backend_new (filename: store_path, root_path: test_data->root_path, root_group: test_data->root_group);
1900 settings = g_settings_new_with_backend_and_path (schema_id: "org.gtk.test.no-path", backend: kf_backend, path: test_data->path);
1901 g_object_unref (object: kf_backend);
1902
1903 g_settings_reset (settings, key: "test-boolean");
1904 g_assert_true (g_settings_get_boolean (settings, "test-boolean"));
1905
1906 writable = g_settings_is_writable (settings, name: "test-boolean");
1907 g_assert_true (writable);
1908 g_settings_set (settings, key: "test-boolean", format: "b", FALSE);
1909
1910 g_assert_false (g_settings_get_boolean (settings, "test-boolean"));
1911
1912 g_settings_delay (settings);
1913 g_settings_set (settings, key: "test-boolean", format: "b", TRUE);
1914 g_settings_apply (settings);
1915
1916 keyfile = g_key_file_new ();
1917 g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1918
1919 g_assert_true (g_key_file_get_boolean (keyfile, test_data->keyfile_group, "test-boolean", NULL));
1920
1921 g_key_file_free (key_file: keyfile);
1922
1923 g_settings_reset (settings, key: "test-boolean");
1924 g_settings_apply (settings);
1925 keyfile = g_key_file_new ();
1926 g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
1927
1928 g_assert_false (g_key_file_get_string (keyfile, test_data->keyfile_group, "test-boolean", &error));
1929 g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
1930 g_clear_error (err: &error);
1931
1932 /* Check that empty keys/groups are not allowed. */
1933 g_assert_false (g_settings_is_writable (settings, ""));
1934 g_assert_false (g_settings_is_writable (settings, "/"));
1935
1936 /* Keys which ghost the root group name are not allowed. This can only be
1937 * tested when the path is `/` as otherwise it acts as a prefix and prevents
1938 * any ghosting. */
1939 if (g_str_equal (v1: test_data->path, v2: "/"))
1940 {
1941 key = g_strdup_printf (format: "%s/%s", test_data->root_group, "");
1942 g_assert_false (g_settings_is_writable (settings, key));
1943 g_free (mem: key);
1944
1945 key = g_strdup_printf (format: "%s/%s", test_data->root_group, "/");
1946 g_assert_false (g_settings_is_writable (settings, key));
1947 g_free (mem: key);
1948
1949 key = g_strdup_printf (format: "%s/%s", test_data->root_group, "test-boolean");
1950 g_assert_false (g_settings_is_writable (settings, key));
1951 g_free (mem: key);
1952 }
1953
1954 g_key_file_free (key_file: keyfile);
1955 g_object_unref (object: settings);
1956
1957 /* Clean up the temporary directory. */
1958 g_assert_no_errno (g_chmod (keyfile_path, 0777));
1959 g_assert_no_errno (g_remove (store_path));
1960 g_assert_no_errno (g_rmdir (keyfile_path));
1961 g_free (mem: store_path);
1962 g_free (mem: keyfile_path);
1963}
1964
1965/*
1966 * Test that a keyfile rejects writes to keys outside its root path.
1967 */
1968static void
1969test_keyfile_outside_root_path (Fixture *fixture,
1970 gconstpointer user_data)
1971{
1972 GSettingsBackend *kf_backend;
1973 GSettings *settings;
1974 gchar *keyfile_path = NULL, *store_path = NULL;
1975
1976 keyfile_path = g_build_filename (first_element: fixture->tmp_dir, "keyfile", NULL);
1977 store_path = g_build_filename (first_element: keyfile_path, "gsettings.store", NULL);
1978 kf_backend = g_keyfile_settings_backend_new (filename: store_path, root_path: "/tests/basic-types/", root_group: "root");
1979 settings = g_settings_new_with_backend_and_path (schema_id: "org.gtk.test.no-path", backend: kf_backend, path: "/tests/");
1980 g_object_unref (object: kf_backend);
1981
1982 g_assert_false (g_settings_is_writable (settings, "test-boolean"));
1983
1984 g_object_unref (object: settings);
1985
1986 /* Clean up the temporary directory. The keyfile probably doesn’t exist, so
1987 * don’t error on failure. */
1988 g_remove (filename: store_path);
1989 g_assert_no_errno (g_rmdir (keyfile_path));
1990 g_free (mem: store_path);
1991 g_free (mem: keyfile_path);
1992}
1993
1994/*
1995 * Test that a keyfile rejects writes to keys in the root if no root group is set.
1996 */
1997static void
1998test_keyfile_no_root_group (Fixture *fixture,
1999 gconstpointer user_data)
2000{
2001 GSettingsBackend *kf_backend;
2002 GSettings *settings;
2003 gchar *keyfile_path = NULL, *store_path = NULL;
2004
2005 keyfile_path = g_build_filename (first_element: fixture->tmp_dir, "keyfile", NULL);
2006 store_path = g_build_filename (first_element: keyfile_path, "gsettings.store", NULL);
2007 kf_backend = g_keyfile_settings_backend_new (filename: store_path, root_path: "/", NULL);
2008 settings = g_settings_new_with_backend_and_path (schema_id: "org.gtk.test.no-path", backend: kf_backend, path: "/");
2009 g_object_unref (object: kf_backend);
2010
2011 g_assert_false (g_settings_is_writable (settings, "test-boolean"));
2012 g_assert_true (g_settings_is_writable (settings, "child/test-boolean"));
2013
2014 g_object_unref (object: settings);
2015
2016 /* Clean up the temporary directory. The keyfile probably doesn’t exist, so
2017 * don’t error on failure. */
2018 g_remove (filename: store_path);
2019 g_assert_no_errno (g_rmdir (keyfile_path));
2020 g_free (mem: store_path);
2021 g_free (mem: keyfile_path);
2022}
2023
2024/* Test that getting child schemas works
2025 */
2026static void
2027test_child_schema (void)
2028{
2029 GSettings *settings;
2030 GSettings *child;
2031 guint8 byte;
2032
2033 /* first establish some known conditions */
2034 settings = g_settings_new (schema_id: "org.gtk.test.basic-types");
2035 g_settings_set (settings, key: "test-byte", format: "y", 36);
2036
2037 g_settings_get (settings, key: "test-byte", format: "y", &byte);
2038 g_assert_cmpint (byte, ==, 36);
2039
2040 g_object_unref (object: settings);
2041
2042 settings = g_settings_new (schema_id: "org.gtk.test");
2043 child = g_settings_get_child (settings, name: "basic-types");
2044 g_assert_nonnull (child);
2045
2046 g_settings_get (settings: child, key: "test-byte", format: "y", &byte);
2047 g_assert_cmpint (byte, ==, 36);
2048
2049 g_object_unref (object: child);
2050 g_object_unref (object: settings);
2051}
2052
2053#include "../strinfo.c"
2054
2055static void
2056test_strinfo (void)
2057{
2058 /* "foo" has a value of 1
2059 * "bar" has a value of 2
2060 * "baz" is an alias for "bar"
2061 */
2062 gchar array[] =
2063 "\1\0\0\0" "\xff""foo" "\0\0\0\xff" "\2\0\0\0"
2064 "\xff" "bar" "\0\0\0\xff" "\3\0\0\0" "\xfe""baz"
2065 "\0\0\0\xff";
2066 const guint32 *strinfo = (guint32 *) array;
2067 guint length = sizeof array / 4;
2068 guint result = 0;
2069
2070 {
2071 /* build it and compare */
2072 GString *builder;
2073
2074 builder = g_string_new (NULL);
2075 strinfo_builder_append_item (builder, string: "foo", value: 1);
2076 strinfo_builder_append_item (builder, string: "bar", value: 2);
2077 g_assert_true (strinfo_builder_append_alias (builder, "baz", "bar"));
2078 g_assert_cmpmem (builder->str, builder->len, strinfo, length * 4);
2079 g_string_free (string: builder, TRUE);
2080 }
2081
2082 g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "foo"),
2083 ==, NULL);
2084 g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "bar"),
2085 ==, NULL);
2086 g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "baz"),
2087 ==, "bar");
2088 g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "quux"),
2089 ==, NULL);
2090
2091 g_assert_true (strinfo_enum_from_string (strinfo, length, "foo", &result));
2092 g_assert_cmpint (result, ==, 1);
2093 g_assert_true (strinfo_enum_from_string (strinfo, length, "bar", &result));
2094 g_assert_cmpint (result, ==, 2);
2095 g_assert_false (strinfo_enum_from_string (strinfo, length, "baz", &result));
2096 g_assert_false (strinfo_enum_from_string (strinfo, length, "quux", &result));
2097
2098 g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 0), ==, NULL);
2099 g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 1), ==, "foo");
2100 g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 2), ==, "bar");
2101 g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 3), ==, NULL);
2102
2103 g_assert_true (strinfo_is_string_valid (strinfo, length, "foo"));
2104 g_assert_true (strinfo_is_string_valid (strinfo, length, "bar"));
2105 g_assert_false (strinfo_is_string_valid (strinfo, length, "baz"));
2106 g_assert_false (strinfo_is_string_valid (strinfo, length, "quux"));
2107}
2108
2109static void
2110test_enums_non_enum_key (void)
2111{
2112 GSettings *direct;
2113
2114 direct = g_settings_new (schema_id: "org.gtk.test.enums.direct");
2115 g_settings_get_enum (settings: direct, key: "test");
2116 g_assert_not_reached ();
2117}
2118
2119static void
2120test_enums_non_enum_value (void)
2121{
2122 GSettings *settings;
2123
2124 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2125 g_settings_set_enum (settings, key: "test", value: 42);
2126 g_assert_not_reached ();
2127}
2128
2129static void
2130test_enums_range (void)
2131{
2132 GSettings *settings;
2133
2134 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2135 g_settings_set_string (settings, key: "test", value: "qux");
2136 g_assert_not_reached ();
2137}
2138
2139static void
2140test_enums_non_flags (void)
2141{
2142 GSettings *settings;
2143
2144 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2145 g_settings_get_flags (settings, key: "test");
2146 g_assert_not_reached ();
2147}
2148
2149static void
2150test_enums (void)
2151{
2152 GSettings *settings, *direct;
2153 gchar *str;
2154
2155 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2156 direct = g_settings_new (schema_id: "org.gtk.test.enums.direct");
2157
2158 if (g_test_undefined () && !backend_set)
2159 {
2160 g_test_trap_subprocess (test_path: "/gsettings/enums/subprocess/non-enum-key", usec_timeout: 0, test_flags: 0);
2161 g_test_trap_assert_failed ();
2162 g_test_trap_assert_stderr ("*not associated with an enum*");
2163
2164 g_test_trap_subprocess (test_path: "/gsettings/enums/subprocess/non-enum-value", usec_timeout: 0, test_flags: 0);
2165 g_test_trap_assert_failed ();
2166 g_test_trap_assert_stderr ("*invalid enum value 42*");
2167
2168 g_test_trap_subprocess (test_path: "/gsettings/enums/subprocess/range", usec_timeout: 0, test_flags: 0);
2169 g_test_trap_assert_failed ();
2170 g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2171
2172 g_test_trap_subprocess (test_path: "/gsettings/enums/subprocess/non-flags", usec_timeout: 0, test_flags: 0);
2173 g_test_trap_assert_failed ();
2174 g_test_trap_assert_stderr ("*not associated with a flags*");
2175 }
2176
2177 str = g_settings_get_string (settings, key: "test");
2178 g_assert_cmpstr (str, ==, "bar");
2179 g_free (mem: str);
2180
2181 g_settings_set_enum (settings, key: "test", value: TEST_ENUM_FOO);
2182
2183 str = g_settings_get_string (settings, key: "test");
2184 g_assert_cmpstr (str, ==, "foo");
2185 g_free (mem: str);
2186
2187 g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_FOO);
2188
2189 g_settings_set_string (settings: direct, key: "test", value: "qux");
2190
2191 str = g_settings_get_string (settings: direct, key: "test");
2192 g_assert_cmpstr (str, ==, "qux");
2193 g_free (mem: str);
2194
2195 str = g_settings_get_string (settings, key: "test");
2196 g_assert_cmpstr (str, ==, "quux");
2197 g_free (mem: str);
2198
2199 g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_QUUX);
2200
2201 g_object_unref (object: direct);
2202 g_object_unref (object: settings);
2203}
2204
2205static void
2206test_flags_non_flags_key (void)
2207{
2208 GSettings *direct;
2209
2210 direct = g_settings_new (schema_id: "org.gtk.test.enums.direct");
2211 g_settings_get_flags (settings: direct, key: "test");
2212 g_assert_not_reached ();
2213}
2214
2215static void
2216test_flags_non_flags_value (void)
2217{
2218 GSettings *settings;
2219
2220 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2221 g_settings_set_flags (settings, key: "f-test", value: 0x42);
2222 g_assert_not_reached ();
2223}
2224
2225static void
2226test_flags_range (void)
2227{
2228 GSettings *settings;
2229
2230 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2231 g_settings_set_strv (settings, key: "f-test",
2232 value: (const gchar **) g_strsplit (string: "rock", delimiter: ",", max_tokens: 0));
2233 g_assert_not_reached ();
2234}
2235
2236static void
2237test_flags_non_enum (void)
2238{
2239 GSettings *settings;
2240
2241 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2242 g_settings_get_enum (settings, key: "f-test");
2243 g_assert_not_reached ();
2244}
2245
2246static void
2247test_flags (void)
2248{
2249 GSettings *settings, *direct;
2250 gchar **strv;
2251 gchar *str;
2252
2253 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2254 direct = g_settings_new (schema_id: "org.gtk.test.enums.direct");
2255
2256 if (g_test_undefined () && !backend_set)
2257 {
2258 g_test_trap_subprocess (test_path: "/gsettings/flags/subprocess/non-flags-key", usec_timeout: 0, test_flags: 0);
2259 g_test_trap_assert_failed ();
2260 g_test_trap_assert_stderr ("*not associated with a flags*");
2261
2262 g_test_trap_subprocess (test_path: "/gsettings/flags/subprocess/non-flags-value", usec_timeout: 0, test_flags: 0);
2263 g_test_trap_assert_failed ();
2264 g_test_trap_assert_stderr ("*invalid flags value 0x00000042*");
2265
2266 g_test_trap_subprocess (test_path: "/gsettings/flags/subprocess/range", usec_timeout: 0, test_flags: 0);
2267 g_test_trap_assert_failed ();
2268 g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2269
2270 g_test_trap_subprocess (test_path: "/gsettings/flags/subprocess/non-enum", usec_timeout: 0, test_flags: 0);
2271 g_test_trap_assert_failed ();
2272 g_test_trap_assert_stderr ("*not associated with an enum*");
2273 }
2274
2275 strv = g_settings_get_strv (settings, key: "f-test");
2276 str = g_strjoinv (separator: ",", str_array: strv);
2277 g_assert_cmpstr (str, ==, "");
2278 g_strfreev (str_array: strv);
2279 g_free (mem: str);
2280
2281 g_settings_set_flags (settings, key: "f-test",
2282 value: TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
2283
2284 strv = g_settings_get_strv (settings, key: "f-test");
2285 str = g_strjoinv (separator: ",", str_array: strv);
2286 g_assert_cmpstr (str, ==, "talking,walking");
2287 g_strfreev (str_array: strv);
2288 g_free (mem: str);
2289
2290 g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
2291 TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
2292
2293 strv = g_strsplit (string: "speaking,laughing", delimiter: ",", max_tokens: 0);
2294 g_settings_set_strv (settings: direct, key: "f-test", value: (const gchar **) strv);
2295 g_strfreev (str_array: strv);
2296
2297 strv = g_settings_get_strv (settings: direct, key: "f-test");
2298 str = g_strjoinv (separator: ",", str_array: strv);
2299 g_assert_cmpstr (str, ==, "speaking,laughing");
2300 g_strfreev (str_array: strv);
2301 g_free (mem: str);
2302
2303 strv = g_settings_get_strv (settings, key: "f-test");
2304 str = g_strjoinv (separator: ",", str_array: strv);
2305 g_assert_cmpstr (str, ==, "talking,laughing");
2306 g_strfreev (str_array: strv);
2307 g_free (mem: str);
2308
2309 g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
2310 TEST_FLAGS_TALKING | TEST_FLAGS_LAUGHING);
2311
2312 g_object_unref (object: direct);
2313 g_object_unref (object: settings);
2314}
2315
2316static void
2317test_range_high (void)
2318{
2319 GSettings *settings;
2320
2321 settings = g_settings_new (schema_id: "org.gtk.test.range");
2322 g_settings_set_int (settings, key: "val", value: 45);
2323 g_assert_not_reached ();
2324}
2325
2326static void
2327test_range_low (void)
2328{
2329 GSettings *settings;
2330
2331 settings = g_settings_new (schema_id: "org.gtk.test.range");
2332 g_settings_set_int (settings, key: "val", value: 1);
2333 g_assert_not_reached ();
2334}
2335
2336static void
2337test_range (void)
2338{
2339 GSettings *settings, *direct;
2340 GVariant *value;
2341
2342 settings = g_settings_new (schema_id: "org.gtk.test.range");
2343 direct = g_settings_new (schema_id: "org.gtk.test.range.direct");
2344
2345 if (g_test_undefined () && !backend_set)
2346 {
2347 g_test_trap_subprocess (test_path: "/gsettings/range/subprocess/high", usec_timeout: 0, test_flags: 0);
2348 g_test_trap_assert_failed ();
2349 g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2350
2351 g_test_trap_subprocess (test_path: "/gsettings/range/subprocess/low", usec_timeout: 0, test_flags: 0);
2352 g_test_trap_assert_failed ();
2353 g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
2354 }
2355
2356 g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
2357 g_settings_set_int (settings: direct, key: "val", value: 22);
2358 g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 22);
2359 g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 22);
2360 g_settings_set_int (settings: direct, key: "val", value: 45);
2361 g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 45);
2362 g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
2363 g_settings_set_int (settings: direct, key: "val", value: 1);
2364 g_assert_cmpint (g_settings_get_int (direct, "val"), ==, 1);
2365 g_assert_cmpint (g_settings_get_int (settings, "val"), ==, 33);
2366
2367G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2368 value = g_variant_new_int32 (value: 1);
2369 g_assert_false (g_settings_range_check (settings, "val", value));
2370 g_variant_unref (value);
2371 value = g_variant_new_int32 (value: 33);
2372 g_assert_true (g_settings_range_check (settings, "val", value));
2373 g_variant_unref (value);
2374 value = g_variant_new_int32 (value: 45);
2375 g_assert_false (g_settings_range_check (settings, "val", value));
2376 g_variant_unref (value);
2377G_GNUC_END_IGNORE_DEPRECATIONS
2378
2379 g_object_unref (object: direct);
2380 g_object_unref (object: settings);
2381}
2382
2383static gboolean
2384strv_has_string (gchar **haystack,
2385 const gchar *needle)
2386{
2387 guint n;
2388
2389 for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
2390 {
2391 if (g_strcmp0 (str1: haystack[n], str2: needle) == 0)
2392 return TRUE;
2393 }
2394 return FALSE;
2395}
2396
2397static gboolean
2398strv_set_equal (gchar **strv, ...)
2399{
2400 gint count;
2401 va_list list;
2402 const gchar *str;
2403 gboolean res;
2404
2405 res = TRUE;
2406 count = 0;
2407 va_start (list, strv);
2408 while (1)
2409 {
2410 str = va_arg (list, const gchar *);
2411 if (str == NULL)
2412 break;
2413 if (!strv_has_string (haystack: strv, needle: str))
2414 {
2415 res = FALSE;
2416 break;
2417 }
2418 count++;
2419 }
2420 va_end (list);
2421
2422 if (res)
2423 res = g_strv_length (str_array: (gchar**)strv) == count;
2424
2425 return res;
2426}
2427
2428static void
2429test_list_items (void)
2430{
2431 GSettingsSchema *schema;
2432 GSettings *settings;
2433 gchar **children;
2434 gchar **keys;
2435
2436 settings = g_settings_new (schema_id: "org.gtk.test");
2437 g_object_get (object: settings, first_property_name: "settings-schema", &schema, NULL);
2438 children = g_settings_list_children (settings);
2439 keys = g_settings_schema_list_keys (schema);
2440
2441 g_assert_true (strv_set_equal (children, "basic-types", "complex-types", "localized", NULL));
2442 g_assert_true (strv_set_equal (keys, "greeting", "farewell", NULL));
2443
2444 g_strfreev (str_array: children);
2445 g_strfreev (str_array: keys);
2446
2447 g_settings_schema_unref (schema);
2448 g_object_unref (object: settings);
2449}
2450
2451static void
2452test_list_schemas (void)
2453{
2454 const gchar * const *schemas;
2455 const gchar * const *relocs;
2456
2457G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2458 relocs = g_settings_list_relocatable_schemas ();
2459 schemas = g_settings_list_schemas ();
2460G_GNUC_END_IGNORE_DEPRECATIONS
2461
2462 g_assert_true (strv_set_equal ((gchar **)relocs,
2463 "org.gtk.test.no-path",
2464 "org.gtk.test.extends.base",
2465 "org.gtk.test.extends.extended",
2466 NULL));
2467
2468 g_assert_true (strv_set_equal ((gchar **)schemas,
2469 "org.gtk.test",
2470 "org.gtk.test.basic-types",
2471 "org.gtk.test.complex-types",
2472 "org.gtk.test.localized",
2473 "org.gtk.test.binding",
2474 "org.gtk.test.enums",
2475 "org.gtk.test.enums.direct",
2476 "org.gtk.test.range",
2477 "org.gtk.test.range.direct",
2478 "org.gtk.test.mapped",
2479 "org.gtk.test.descriptions",
2480 "org.gtk.test.per-desktop",
2481 NULL));
2482}
2483
2484static gboolean
2485map_func (GVariant *value,
2486 gpointer *result,
2487 gpointer user_data)
2488{
2489 gint *state = user_data;
2490 gint v;
2491
2492 if (value)
2493 v = g_variant_get_int32 (value);
2494 else
2495 v = -1;
2496
2497 if (*state == 0)
2498 {
2499 g_assert_cmpint (v, ==, 1);
2500 (*state)++;
2501 return FALSE;
2502 }
2503 else if (*state == 1)
2504 {
2505 g_assert_cmpint (v, ==, 0);
2506 (*state)++;
2507 return FALSE;
2508 }
2509 else
2510 {
2511 g_assert_null (value);
2512 *result = g_variant_new_int32 (value: 5);
2513 return TRUE;
2514 }
2515}
2516
2517static void
2518test_get_mapped (void)
2519{
2520 GSettings *settings;
2521 gint state;
2522 gpointer p;
2523 gint val;
2524
2525 settings = g_settings_new (schema_id: "org.gtk.test.mapped");
2526 g_settings_set_int (settings, key: "val", value: 1);
2527
2528 state = 0;
2529 p = g_settings_get_mapped (settings, key: "val", mapping: map_func, user_data: &state);
2530 val = g_variant_get_int32 (value: (GVariant*)p);
2531 g_assert_cmpint (val, ==, 5);
2532
2533 g_variant_unref (value: p);
2534 g_object_unref (object: settings);
2535}
2536
2537static void
2538test_get_range (void)
2539{
2540 GSettings *settings;
2541 GVariant *range;
2542
2543G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2544 settings = g_settings_new (schema_id: "org.gtk.test.range");
2545 range = g_settings_get_range (settings, key: "val");
2546 check_and_free (value: range, expected: "('range', <(2, 44)>)");
2547 g_object_unref (object: settings);
2548
2549 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2550 range = g_settings_get_range (settings, key: "test");
2551 check_and_free (value: range, expected: "('enum', <['foo', 'bar', 'baz', 'quux']>)");
2552 g_object_unref (object: settings);
2553
2554 settings = g_settings_new (schema_id: "org.gtk.test.enums");
2555 range = g_settings_get_range (settings, key: "f-test");
2556 check_and_free (value: range, expected: "('flags', "
2557 "<['mourning', 'laughing', 'talking', 'walking']>)");
2558 g_object_unref (object: settings);
2559
2560 settings = g_settings_new (schema_id: "org.gtk.test");
2561 range = g_settings_get_range (settings, key: "greeting");
2562 check_and_free (value: range, expected: "('type', <@as []>)");
2563 g_object_unref (object: settings);
2564G_GNUC_END_IGNORE_DEPRECATIONS
2565}
2566
2567static void
2568test_schema_source (void)
2569{
2570 GSettingsSchemaSource *parent;
2571 GSettingsSchemaSource *source;
2572 GSettingsBackend *backend;
2573 GSettingsSchema *schema;
2574 GError *error = NULL;
2575 GSettings *settings;
2576 gboolean enabled;
2577
2578 backend = g_settings_backend_get_default ();
2579
2580 /* make sure it fails properly */
2581 parent = g_settings_schema_source_get_default ();
2582 source = g_settings_schema_source_new_from_directory (directory: "/path/that/does/not/exist", parent, TRUE, error: &error);
2583 g_assert_null (source);
2584 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
2585 g_clear_error (err: &error);
2586
2587 /* Test error handling of corrupt compiled files. */
2588 source = g_settings_schema_source_new_from_directory (directory: "schema-source-corrupt", parent, TRUE, error: &error);
2589 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
2590 g_assert_null (source);
2591 g_clear_error (err: &error);
2592
2593 /* Test error handling of empty compiled files. */
2594 source = g_settings_schema_source_new_from_directory (directory: "schema-source-empty", parent, TRUE, error: &error);
2595 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
2596 g_assert_null (source);
2597 g_clear_error (err: &error);
2598
2599 /* create a source with the parent */
2600 source = g_settings_schema_source_new_from_directory (directory: "schema-source", parent, TRUE, error: &error);
2601 g_assert_no_error (error);
2602 g_assert_nonnull (source);
2603
2604 /* check recursive lookups are working */
2605 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.test", TRUE);
2606 g_assert_nonnull (schema);
2607 g_settings_schema_unref (schema);
2608
2609 /* check recursive lookups for non-existent schemas */
2610 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.doesnotexist", TRUE);
2611 g_assert_null (schema);
2612
2613 /* check non-recursive for schema that only exists in lower layers */
2614 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.test", FALSE);
2615 g_assert_null (schema);
2616
2617 /* check non-recursive lookup for non-existent */
2618 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.doesnotexist", FALSE);
2619 g_assert_null (schema);
2620
2621 /* check non-recursive for schema that exists in toplevel */
2622 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.schemasourcecheck", FALSE);
2623 g_assert_nonnull (schema);
2624 g_settings_schema_unref (schema);
2625
2626 /* check recursive for schema that exists in toplevel */
2627 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.schemasourcecheck", TRUE);
2628 g_assert_nonnull (schema);
2629
2630 /* try to use it for something */
2631 settings = g_settings_new_full (schema, backend, path: g_settings_schema_get_path (schema));
2632 g_settings_schema_unref (schema);
2633 enabled = FALSE;
2634 g_settings_get (settings, key: "enabled", format: "b", &enabled);
2635 g_assert_true (enabled);
2636 g_object_unref (object: settings);
2637
2638 g_settings_schema_source_unref (source);
2639
2640 /* try again, but with no parent */
2641 source = g_settings_schema_source_new_from_directory (directory: "schema-source", NULL, FALSE, NULL);
2642 g_assert_nonnull (source);
2643
2644 /* should not find it this time, even if recursive... */
2645 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.test", FALSE);
2646 g_assert_null (schema);
2647 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.test", TRUE);
2648 g_assert_null (schema);
2649
2650 /* should still find our own... */
2651 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.schemasourcecheck", TRUE);
2652 g_assert_nonnull (schema);
2653 g_settings_schema_unref (schema);
2654 schema = g_settings_schema_source_lookup (source, schema_id: "org.gtk.schemasourcecheck", FALSE);
2655 g_assert_nonnull (schema);
2656 g_settings_schema_unref (schema);
2657
2658 g_settings_schema_source_unref (source);
2659 g_object_unref (object: backend);
2660}
2661
2662static void
2663test_schema_list_keys (void)
2664{
2665 gchar **keys;
2666 GSettingsSchemaSource *src = g_settings_schema_source_get_default ();
2667 GSettingsSchema *schema = g_settings_schema_source_lookup (source: src, schema_id: "org.gtk.test", TRUE);
2668 g_assert_nonnull (schema);
2669
2670 keys = g_settings_schema_list_keys (schema);
2671
2672 g_assert_true (strv_set_equal ((gchar **)keys,
2673 "greeting",
2674 "farewell",
2675 NULL));
2676
2677 g_strfreev (str_array: keys);
2678 g_settings_schema_unref (schema);
2679}
2680
2681static void
2682test_actions (void)
2683{
2684 GAction *string, *toggle;
2685 gboolean c1, c2, c3;
2686 GSettings *settings;
2687 gchar *name;
2688 GVariantType *param_type;
2689 gboolean enabled;
2690 GVariantType *state_type;
2691 GVariant *state;
2692
2693 settings = g_settings_new (schema_id: "org.gtk.test.basic-types");
2694 string = g_settings_create_action (settings, key: "test-string");
2695 toggle = g_settings_create_action (settings, key: "test-boolean");
2696 g_object_unref (object: settings); /* should be held by the actions */
2697
2698 g_signal_connect (settings, "changed", G_CALLBACK (changed_cb2), &c1);
2699 g_signal_connect (string, "notify::state", G_CALLBACK (changed_cb2), &c2);
2700 g_signal_connect (toggle, "notify::state", G_CALLBACK (changed_cb2), &c3);
2701
2702 c1 = c2 = c3 = FALSE;
2703 g_settings_set_string (settings, key: "test-string", value: "hello world");
2704 check_and_free (value: g_action_get_state (action: string), expected: "'hello world'");
2705 g_assert_true (c1 && c2 && !c3);
2706 c1 = c2 = c3 = FALSE;
2707
2708 g_action_activate (action: string, parameter: g_variant_new_string (string: "hihi"));
2709 check_and_free (value: g_settings_get_value (settings, key: "test-string"), expected: "'hihi'");
2710 g_assert_true (c1 && c2 && !c3);
2711 c1 = c2 = c3 = FALSE;
2712
2713 g_action_change_state (action: string, value: g_variant_new_string (string: "kthxbye"));
2714 check_and_free (value: g_settings_get_value (settings, key: "test-string"), expected: "'kthxbye'");
2715 g_assert_true (c1 && c2 && !c3);
2716 c1 = c2 = c3 = FALSE;
2717
2718 g_action_change_state (action: toggle, value: g_variant_new_boolean (TRUE));
2719 g_assert_true (g_settings_get_boolean (settings, "test-boolean"));
2720 g_assert_true (c1 && !c2 && c3);
2721 c1 = c2 = c3 = FALSE;
2722
2723 g_action_activate (action: toggle, NULL);
2724 g_assert_false (g_settings_get_boolean (settings, "test-boolean"));
2725 g_assert_true (c1 && !c2 && c3);
2726
2727 g_object_get (object: string,
2728 first_property_name: "name", &name,
2729 "parameter-type", &param_type,
2730 "enabled", &enabled,
2731 "state-type", &state_type,
2732 "state", &state,
2733 NULL);
2734
2735 g_assert_cmpstr (name, ==, "test-string");
2736 g_assert_true (g_variant_type_equal (param_type, G_VARIANT_TYPE_STRING));
2737 g_assert_true (enabled);
2738 g_assert_true (g_variant_type_equal (state_type, G_VARIANT_TYPE_STRING));
2739 g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "kthxbye");
2740
2741 g_free (mem: name);
2742 g_variant_type_free (type: param_type);
2743 g_variant_type_free (type: state_type);
2744 g_variant_unref (value: state);
2745
2746 g_object_unref (object: string);
2747 g_object_unref (object: toggle);
2748}
2749
2750static void
2751test_null_backend (void)
2752{
2753 GSettingsBackend *backend;
2754 GSettings *settings;
2755 gchar *str;
2756 gboolean writable;
2757
2758 backend = g_null_settings_backend_new ();
2759 settings = g_settings_new_with_backend_and_path (schema_id: "org.gtk.test", backend, path: "/tests/");
2760
2761 g_object_get (object: settings, first_property_name: "schema-id", &str, NULL);
2762 g_assert_cmpstr (str, ==, "org.gtk.test");
2763 g_free (mem: str);
2764
2765 g_settings_get (settings, key: "greeting", format: "s", &str);
2766 g_assert_cmpstr (str, ==, "Hello, earthlings");
2767 g_free (mem: str);
2768
2769 g_settings_set (settings, key: "greeting", format: "s", "goodbye world");
2770 g_settings_get (settings, key: "greeting", format: "s", &str);
2771 g_assert_cmpstr (str, ==, "Hello, earthlings");
2772 g_free (mem: str);
2773
2774 writable = g_settings_is_writable (settings, name: "greeting");
2775 g_assert_false (writable);
2776
2777 g_settings_reset (settings, key: "greeting");
2778
2779 g_settings_delay (settings);
2780 g_settings_set (settings, key: "greeting", format: "s", "goodbye world");
2781 g_settings_apply (settings);
2782 g_settings_get (settings, key: "greeting", format: "s", &str);
2783 g_assert_cmpstr (str, ==, "Hello, earthlings");
2784 g_free (mem: str);
2785
2786 g_object_unref (object: settings);
2787 g_object_unref (object: backend);
2788}
2789
2790static void
2791test_memory_backend (void)
2792{
2793 GSettingsBackend *backend;
2794
2795 backend = g_memory_settings_backend_new ();
2796 g_assert_true (G_IS_SETTINGS_BACKEND (backend));
2797 g_object_unref (object: backend);
2798}
2799
2800static void
2801test_read_descriptions (void)
2802{
2803 GSettingsSchema *schema;
2804 GSettingsSchemaKey *key;
2805 GSettings *settings;
2806
2807 settings = g_settings_new (schema_id: "org.gtk.test");
2808 g_object_get (object: settings, first_property_name: "settings-schema", &schema, NULL);
2809 key = g_settings_schema_get_key (schema, name: "greeting");
2810
2811 g_assert_cmpstr (g_settings_schema_key_get_summary (key), ==, "A greeting");
2812 g_assert_cmpstr (g_settings_schema_key_get_description (key), ==, "Greeting of the invading martians");
2813
2814 g_settings_schema_key_unref (key);
2815 g_settings_schema_unref (schema);
2816
2817 g_object_unref (object: settings);
2818
2819 settings = g_settings_new (schema_id: "org.gtk.test.descriptions");
2820 g_object_get (object: settings, first_property_name: "settings-schema", &schema, NULL);
2821 key = g_settings_schema_get_key (schema, name: "a");
2822
2823 g_assert_cmpstr (g_settings_schema_key_get_summary (key), ==,
2824 "a paragraph.\n\n"
2825 "with some whitespace.\n\n"
2826 "because not everyone has a great editor.\n\n"
2827 "lots of space is as one.");
2828
2829 g_settings_schema_key_unref (key);
2830 g_settings_schema_unref (schema);
2831
2832 g_object_unref (object: settings);
2833}
2834
2835static void
2836test_default_value (void)
2837{
2838 GSettings *settings;
2839 GSettingsSchema *schema;
2840 GSettingsSchemaKey *key;
2841 GVariant *v;
2842 const gchar *str;
2843 gchar *s;
2844
2845 settings = g_settings_new (schema_id: "org.gtk.test");
2846 g_object_get (object: settings, first_property_name: "settings-schema", &schema, NULL);
2847 key = g_settings_schema_get_key (schema, name: "greeting");
2848 g_settings_schema_unref (schema);
2849 g_settings_schema_key_ref (key);
2850
2851 g_assert_true (g_variant_type_equal (g_settings_schema_key_get_value_type (key), G_VARIANT_TYPE_STRING));
2852
2853 v = g_settings_schema_key_get_default_value (key);
2854 str = g_variant_get_string (value: v, NULL);
2855 g_assert_cmpstr (str, ==, "Hello, earthlings");
2856 g_variant_unref (value: v);
2857
2858 g_settings_schema_key_unref (key);
2859 g_settings_schema_key_unref (key);
2860
2861 g_settings_set (settings, key: "greeting", format: "s", "goodbye world");
2862
2863 v = g_settings_get_user_value (settings, key: "greeting");
2864 str = g_variant_get_string (value: v, NULL);
2865 g_assert_cmpstr (str, ==, "goodbye world");
2866 g_variant_unref (value: v);
2867
2868 v = g_settings_get_default_value (settings, key: "greeting");
2869 str = g_variant_get_string (value: v, NULL);
2870 g_assert_cmpstr (str, ==, "Hello, earthlings");
2871 g_variant_unref (value: v);
2872
2873 g_settings_reset (settings, key: "greeting");
2874
2875 v = g_settings_get_user_value (settings, key: "greeting");
2876 g_assert_null (v);
2877
2878 s = g_settings_get_string (settings, key: "greeting");
2879 g_assert_cmpstr (s, ==, "Hello, earthlings");
2880 g_free (mem: s);
2881
2882 g_object_unref (object: settings);
2883}
2884
2885static gboolean
2886string_map_func (GVariant *value,
2887 gpointer *result,
2888 gpointer user_data)
2889{
2890 const gchar *str;
2891
2892 str = g_variant_get_string (value, NULL);
2893 *result = g_variant_new_string (string: str);
2894
2895 return TRUE;
2896}
2897
2898/* Test that per-desktop values from org.gtk.test.gschema.override
2899 * does not change default value if current desktop is not listed in
2900 * $XDG_CURRENT_DESKTOP.
2901 */
2902static void
2903test_per_desktop (void)
2904{
2905 GSettings *settings;
2906 TestObject *obj;
2907 gpointer p;
2908 gchar *str;
2909
2910 settings = g_settings_new (schema_id: "org.gtk.test.per-desktop");
2911 obj = test_object_new ();
2912
2913 if (!g_test_subprocess ())
2914 {
2915 g_test_trap_subprocess (test_path: "/gsettings/per-desktop/subprocess", usec_timeout: 0, test_flags: 0);
2916 g_test_trap_assert_passed ();
2917 }
2918
2919 str = g_settings_get_string (settings, key: "desktop");
2920 g_assert_cmpstr (str, ==, "GNOME");
2921 g_free (mem: str);
2922
2923 p = g_settings_get_mapped (settings, key: "desktop", mapping: string_map_func, NULL);
2924
2925 str = g_variant_dup_string (value: p, NULL);
2926 g_assert_cmpstr (str, ==, "GNOME");
2927 g_free (mem: str);
2928
2929 g_variant_unref (value: p);
2930
2931 g_settings_bind (settings, key: "desktop", object: obj, property: "string", flags: G_SETTINGS_BIND_DEFAULT);
2932
2933 g_object_get (object: obj, first_property_name: "string", &str, NULL);
2934 g_assert_cmpstr (str, ==, "GNOME");
2935 g_free (mem: str);
2936
2937 g_object_unref (object: settings);
2938 g_object_unref (object: obj);
2939}
2940
2941/* Test that per-desktop values from org.gtk.test.gschema.override
2942 * are successfully loaded based on the value of $XDG_CURRENT_DESKTOP.
2943 */
2944static void
2945test_per_desktop_subprocess (void)
2946{
2947 GSettings *settings;
2948 TestObject *obj;
2949 gpointer p;
2950 gchar *str;
2951
2952 g_setenv (variable: "XDG_CURRENT_DESKTOP", value: "GNOME-Classic:GNOME", TRUE);
2953
2954 settings = g_settings_new (schema_id: "org.gtk.test.per-desktop");
2955 obj = test_object_new ();
2956
2957 str = g_settings_get_string (settings, key: "desktop");
2958 g_assert_cmpstr (str, ==, "GNOME Classic");
2959 g_free (mem: str);
2960
2961 p = g_settings_get_mapped (settings, key: "desktop", mapping: string_map_func, NULL);
2962
2963 str = g_variant_dup_string (value: p, NULL);
2964 g_assert_cmpstr (str, ==, "GNOME Classic");
2965 g_free (mem: str);
2966
2967 g_variant_unref (value: p);
2968
2969 g_settings_bind (settings, key: "desktop", object: obj, property: "string", flags: G_SETTINGS_BIND_DEFAULT);
2970
2971 g_object_get (object: obj, first_property_name: "string", &str, NULL);
2972 g_assert_cmpstr (str, ==, "GNOME Classic");
2973 g_free (mem: str);
2974
2975 g_object_unref (object: settings);
2976 g_object_unref (object: obj);
2977}
2978
2979static void
2980test_extended_schema (void)
2981{
2982 GSettingsSchema *schema;
2983 GSettings *settings;
2984 gchar **keys;
2985
2986 settings = g_settings_new_with_path (schema_id: "org.gtk.test.extends.extended", path: "/test/extendes/");
2987 g_object_get (object: settings, first_property_name: "settings-schema", &schema, NULL);
2988 keys = g_settings_schema_list_keys (schema);
2989 g_assert_true (strv_set_equal (keys, "int32", "string", "another-int32", NULL));
2990 g_strfreev (str_array: keys);
2991 g_object_unref (object: settings);
2992 g_settings_schema_unref (schema);
2993}
2994
2995int
2996main (int argc, char *argv[])
2997{
2998 gchar *schema_text;
2999 gchar *override_text;
3000 gchar *enums;
3001 gint result;
3002 const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" };
3003 const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" };
3004 const KeyfileTestData keyfile_test_data_long_path = {
3005 "/tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch/",
3006 "root",
3007 "tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch",
3008 "/"
3009 };
3010
3011/* Meson build sets this */
3012#ifdef TEST_LOCALE_PATH
3013 if (g_str_has_suffix (TEST_LOCALE_PATH, suffix: "LC_MESSAGES"))
3014 {
3015 locale_dir = TEST_LOCALE_PATH G_DIR_SEPARATOR_S ".." G_DIR_SEPARATOR_S "..";
3016 }
3017#endif
3018
3019 setlocale (LC_ALL, locale: "");
3020
3021 g_test_init (argc: &argc, argv: &argv, NULL);
3022
3023 if (!g_test_subprocess ())
3024 {
3025 GError *local_error = NULL;
3026 /* A GVDB header is 6 guint32s, and requires a magic number in the first
3027 * two guint32s. A set of zero bytes of a greater length is considered
3028 * corrupt. */
3029 const guint8 gschemas_compiled_corrupt[sizeof (guint32) * 7] = { 0, };
3030
3031 backend_set = g_getenv (variable: "GSETTINGS_BACKEND") != NULL;
3032
3033 g_setenv (variable: "XDG_DATA_DIRS", value: ".", TRUE);
3034 g_setenv (variable: "XDG_DATA_HOME", value: ".", TRUE);
3035 g_setenv (variable: "GSETTINGS_SCHEMA_DIR", value: ".", TRUE);
3036 g_setenv (variable: "XDG_CURRENT_DESKTOP", value: "", TRUE);
3037
3038 if (!backend_set)
3039 g_setenv (variable: "GSETTINGS_BACKEND", value: "memory", TRUE);
3040
3041 g_remove (filename: "org.gtk.test.enums.xml");
3042 /* #GLIB_MKENUMS is defined in meson.build */
3043 g_assert_true (g_spawn_command_line_sync (GLIB_MKENUMS " "
3044 "--template " SRCDIR "/enums.xml.template "
3045 SRCDIR "/testenum.h",
3046 &enums, NULL, &result, NULL));
3047 g_assert_cmpint (result, ==, 0);
3048 g_assert_true (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
3049 g_free (mem: enums);
3050
3051 g_assert_true (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.xml.orig", &schema_text, NULL, NULL));
3052 g_assert_true (g_file_set_contents ("org.gtk.test.gschema.xml", schema_text, -1, NULL));
3053 g_free (mem: schema_text);
3054
3055 g_assert_true (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.override.orig", &override_text, NULL, NULL));
3056 g_assert_true (g_file_set_contents ("org.gtk.test.gschema.override", override_text, -1, NULL));
3057 g_free (mem: override_text);
3058
3059 g_remove (filename: "gschemas.compiled");
3060 /* #GLIB_COMPILE_SCHEMAS is defined in meson.build */
3061 g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=. "
3062 "--schema-file=org.gtk.test.enums.xml "
3063 "--schema-file=org.gtk.test.gschema.xml "
3064 "--override-file=org.gtk.test.gschema.override",
3065 NULL, NULL, &result, NULL));
3066 g_assert_cmpint (result, ==, 0);
3067
3068 g_remove (filename: "schema-source/gschemas.compiled");
3069 g_mkdir (path: "schema-source", mode: 0777);
3070 g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=schema-source "
3071 "--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml",
3072 NULL, NULL, &result, NULL));
3073 g_assert_cmpint (result, ==, 0);
3074
3075 g_remove (filename: "schema-source-corrupt/gschemas.compiled");
3076 g_mkdir (path: "schema-source-corrupt", mode: 0777);
3077 g_file_set_contents (filename: "schema-source-corrupt/gschemas.compiled",
3078 contents: (const gchar *) gschemas_compiled_corrupt,
3079 length: sizeof (gschemas_compiled_corrupt),
3080 error: &local_error);
3081 g_assert_no_error (local_error);
3082
3083 g_remove (filename: "schema-source-empty/gschemas.compiled");
3084 g_mkdir (path: "schema-source-empty", mode: 0777);
3085 g_file_set_contents (filename: "schema-source-empty/gschemas.compiled",
3086 contents: "", length: 0,
3087 error: &local_error);
3088 g_assert_no_error (local_error);
3089 }
3090
3091 g_test_add_func (testpath: "/gsettings/basic", test_func: test_basic);
3092
3093 if (!backend_set)
3094 {
3095 g_test_add_func (testpath: "/gsettings/no-schema", test_func: test_no_schema);
3096 g_test_add_func (testpath: "/gsettings/unknown-key", test_func: test_unknown_key);
3097 g_test_add_func (testpath: "/gsettings/wrong-type", test_func: test_wrong_type);
3098 g_test_add_func (testpath: "/gsettings/wrong-path", test_func: test_wrong_path);
3099 g_test_add_func (testpath: "/gsettings/no-path", test_func: test_no_path);
3100 }
3101
3102 g_test_add_func (testpath: "/gsettings/basic-types", test_func: test_basic_types);
3103 g_test_add_func (testpath: "/gsettings/complex-types", test_func: test_complex_types);
3104 g_test_add_func (testpath: "/gsettings/changes", test_func: test_changes);
3105
3106 g_test_add_func (testpath: "/gsettings/l10n", test_func: test_l10n);
3107 g_test_add_func (testpath: "/gsettings/l10n-context", test_func: test_l10n_context);
3108
3109 g_test_add_func (testpath: "/gsettings/delay-apply", test_func: test_delay_apply);
3110 g_test_add_func (testpath: "/gsettings/delay-revert", test_func: test_delay_revert);
3111 g_test_add_func (testpath: "/gsettings/delay-child", test_func: test_delay_child);
3112 g_test_add_func (testpath: "/gsettings/atomic", test_func: test_atomic);
3113
3114 g_test_add_func (testpath: "/gsettings/simple-binding", test_func: test_simple_binding);
3115 g_test_add_func (testpath: "/gsettings/directional-binding", test_func: test_directional_binding);
3116 g_test_add_func (testpath: "/gsettings/custom-binding", test_func: test_custom_binding);
3117 g_test_add_func (testpath: "/gsettings/no-change-binding", test_func: test_no_change_binding);
3118 g_test_add_func (testpath: "/gsettings/unbinding", test_func: test_unbind);
3119 g_test_add_func (testpath: "/gsettings/writable-binding", test_func: test_bind_writable);
3120
3121 if (!backend_set)
3122 {
3123 g_test_add_func (testpath: "/gsettings/typesafe-binding", test_func: test_typesafe_binding);
3124 g_test_add_func (testpath: "/gsettings/no-read-binding", test_func: test_no_read_binding);
3125 g_test_add_func (testpath: "/gsettings/no-read-binding/subprocess/fail", test_func: test_no_read_binding_fail);
3126 g_test_add_func (testpath: "/gsettings/no-read-binding/subprocess/pass", test_func: test_no_read_binding_pass);
3127 g_test_add_func (testpath: "/gsettings/no-write-binding", test_func: test_no_write_binding);
3128 g_test_add_func (testpath: "/gsettings/no-write-binding/subprocess/fail", test_func: test_no_write_binding_fail);
3129 g_test_add_func (testpath: "/gsettings/no-write-binding/subprocess/pass", test_func: test_no_write_binding_pass);
3130 }
3131
3132 g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown);
3133 g_test_add ("/gsettings/keyfile/explicit-path", Fixture, &keyfile_test_data_explicit_path, setup, test_keyfile_no_path, teardown);
3134 g_test_add ("/gsettings/keyfile/empty-path", Fixture, &keyfile_test_data_empty_path, setup, test_keyfile_no_path, teardown);
3135 g_test_add ("/gsettings/keyfile/long-path", Fixture, &keyfile_test_data_long_path, setup, test_keyfile_no_path, teardown);
3136 g_test_add ("/gsettings/keyfile/outside-root-path", Fixture, NULL, setup, test_keyfile_outside_root_path, teardown);
3137 g_test_add ("/gsettings/keyfile/no-root-group", Fixture, NULL, setup, test_keyfile_no_root_group, teardown);
3138 g_test_add_func (testpath: "/gsettings/child-schema", test_func: test_child_schema);
3139 g_test_add_func (testpath: "/gsettings/strinfo", test_func: test_strinfo);
3140 g_test_add_func (testpath: "/gsettings/enums", test_func: test_enums);
3141 g_test_add_func (testpath: "/gsettings/enums/subprocess/non-enum-key", test_func: test_enums_non_enum_key);
3142 g_test_add_func (testpath: "/gsettings/enums/subprocess/non-enum-value", test_func: test_enums_non_enum_value);
3143 g_test_add_func (testpath: "/gsettings/enums/subprocess/range", test_func: test_enums_range);
3144 g_test_add_func (testpath: "/gsettings/enums/subprocess/non-flags", test_func: test_enums_non_flags);
3145 g_test_add_func (testpath: "/gsettings/flags", test_func: test_flags);
3146 g_test_add_func (testpath: "/gsettings/flags/subprocess/non-flags-key", test_func: test_flags_non_flags_key);
3147 g_test_add_func (testpath: "/gsettings/flags/subprocess/non-flags-value", test_func: test_flags_non_flags_value);
3148 g_test_add_func (testpath: "/gsettings/flags/subprocess/range", test_func: test_flags_range);
3149 g_test_add_func (testpath: "/gsettings/flags/subprocess/non-enum", test_func: test_flags_non_enum);
3150 g_test_add_func (testpath: "/gsettings/range", test_func: test_range);
3151 g_test_add_func (testpath: "/gsettings/range/subprocess/high", test_func: test_range_high);
3152 g_test_add_func (testpath: "/gsettings/range/subprocess/low", test_func: test_range_low);
3153 g_test_add_func (testpath: "/gsettings/list-items", test_func: test_list_items);
3154 g_test_add_func (testpath: "/gsettings/list-schemas", test_func: test_list_schemas);
3155 g_test_add_func (testpath: "/gsettings/mapped", test_func: test_get_mapped);
3156 g_test_add_func (testpath: "/gsettings/get-range", test_func: test_get_range);
3157 g_test_add_func (testpath: "/gsettings/schema-source", test_func: test_schema_source);
3158 g_test_add_func (testpath: "/gsettings/schema-list-keys", test_func: test_schema_list_keys);
3159 g_test_add_func (testpath: "/gsettings/actions", test_func: test_actions);
3160 g_test_add_func (testpath: "/gsettings/null-backend", test_func: test_null_backend);
3161 g_test_add_func (testpath: "/gsettings/memory-backend", test_func: test_memory_backend);
3162 g_test_add_func (testpath: "/gsettings/read-descriptions", test_func: test_read_descriptions);
3163 g_test_add_func (testpath: "/gsettings/test-extended-schema", test_func: test_extended_schema);
3164 g_test_add_func (testpath: "/gsettings/default-value", test_func: test_default_value);
3165 g_test_add_func (testpath: "/gsettings/per-desktop", test_func: test_per_desktop);
3166 g_test_add_func (testpath: "/gsettings/per-desktop/subprocess", test_func: test_per_desktop_subprocess);
3167
3168 result = g_test_run ();
3169
3170 g_settings_sync ();
3171
3172 /* FIXME: Due to the way #GSettings objects can be used without specifying a
3173 * backend, the default backend is leaked. In order to be able to run this
3174 * test under valgrind and get meaningful checking for real leaks, use this
3175 * hack to drop the final reference to the default #GSettingsBackend.
3176 *
3177 * This should not be used in production code. */
3178 {
3179 GSettingsBackend *backend;
3180
3181 backend = g_settings_backend_get_default ();
3182 g_object_unref (object: backend); /* reference from the *_get_default() call */
3183 g_assert_finalize_object (backend); /* singleton reference owned by GLib */
3184 }
3185
3186 return result;
3187}
3188

source code of gtk/subprojects/glib/gio/tests/gsettings.c