Change libgirepository to libgirepository2
[platform/upstream/glib.git] / gobject / tests / param.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/.
25  */
26
27 #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
28 #define GLIB_DISABLE_DEPRECATION_WARNINGS
29 #endif
30
31 #include <glib-object.h>
32 #include <stdlib.h>
33
34 static void
35 test_param_spec_char (void)
36 {
37   GParamSpec *pspec;
38   GValue value = G_VALUE_INIT;
39
40   pspec = g_param_spec_char ("char", "nick", "blurb",
41                              20, 40, 30, G_PARAM_READWRITE);
42
43   g_assert_cmpstr (g_param_spec_get_name (pspec), ==, "char");
44   g_assert_cmpstr (g_param_spec_get_nick (pspec), ==, "nick");
45   g_assert_cmpstr (g_param_spec_get_blurb (pspec), ==, "blurb");
46
47   g_value_init (&value, G_TYPE_CHAR);
48   g_value_set_char (&value, 30);
49
50   g_assert_true (g_param_value_defaults (pspec, &value));
51
52   g_value_set_char (&value, 0);
53   g_assert_false (g_param_value_is_valid (pspec, &value));
54   g_assert_true (g_param_value_validate (pspec, &value));
55   g_assert_cmpint (g_value_get_char (&value), ==, 20);
56
57   g_value_set_char (&value, 20);
58   g_assert_true (g_param_value_is_valid (pspec, &value));
59   g_assert_false (g_param_value_validate (pspec, &value));
60   g_assert_cmpint (g_value_get_char (&value), ==, 20);
61
62   g_value_set_char (&value, 40);
63   g_assert_true (g_param_value_is_valid (pspec, &value));
64   g_assert_false (g_param_value_validate (pspec, &value));
65   g_assert_cmpint (g_value_get_char (&value), ==, 40);
66
67   g_value_set_char (&value, 60);
68   g_assert_false (g_param_value_is_valid (pspec, &value));
69   g_assert_true (g_param_value_validate (pspec, &value));
70   g_assert_cmpint (g_value_get_char (&value), ==, 40);
71
72   g_value_set_schar (&value, 0);
73   g_assert_false (g_param_value_is_valid (pspec, &value));
74   g_assert_true (g_param_value_validate (pspec, &value));
75   g_assert_cmpint (g_value_get_schar (&value), ==, 20);
76
77   g_value_set_schar (&value, 20);
78   g_assert_true (g_param_value_is_valid (pspec, &value));
79   g_assert_false (g_param_value_validate (pspec, &value));
80   g_assert_cmpint (g_value_get_schar (&value), ==, 20);
81
82   g_value_set_schar (&value, 40);
83   g_assert_true (g_param_value_is_valid (pspec, &value));
84   g_assert_false (g_param_value_validate (pspec, &value));
85   g_assert_cmpint (g_value_get_schar (&value), ==, 40);
86
87   g_value_set_schar (&value, 60);
88   g_assert_false (g_param_value_is_valid (pspec, &value));
89   g_assert_true (g_param_value_validate (pspec, &value));
90   g_assert_cmpint (g_value_get_schar (&value), ==, 40);
91
92   g_param_spec_unref (pspec);
93 }
94
95 static void
96 test_param_spec_uchar (void)
97 {
98   GParamSpec *pspec;
99   GValue value = G_VALUE_INIT;
100
101   pspec = g_param_spec_uchar ("char", NULL, NULL,
102                              20, 40, 30, G_PARAM_READWRITE);
103
104   g_assert_cmpstr (g_param_spec_get_name (pspec), ==, "char");
105
106   g_value_init (&value, G_TYPE_UCHAR);
107
108   g_value_set_uchar (&value, 0);
109   g_assert_false (g_param_value_is_valid (pspec, &value));
110   g_assert_true (g_param_value_validate (pspec, &value));
111   g_assert_cmpint (g_value_get_uchar (&value), ==, 20);
112
113   g_value_set_uchar (&value, 20);
114   g_assert_true (g_param_value_is_valid (pspec, &value));
115   g_assert_false (g_param_value_validate (pspec, &value));
116   g_assert_cmpint (g_value_get_uchar (&value), ==, 20);
117
118   g_param_spec_unref (pspec);
119 }
120
121 static void
122 test_param_spec_int (void)
123 {
124   GParamSpec *pspec;
125   GValue value = G_VALUE_INIT;
126
127   pspec = g_param_spec_int ("int", NULL, NULL,
128                             20, 40, 30, G_PARAM_READWRITE);
129
130   g_param_value_set_default (pspec, &value);
131   g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_INT);
132   g_assert_cmpint (g_value_get_int (&value), ==, 30);
133   g_assert_true (g_param_value_defaults (pspec, &value));
134
135   g_value_set_int (&value, 0);
136   g_assert_false (g_param_value_is_valid (pspec, &value));
137   g_assert_true (g_param_value_validate (pspec, &value));
138   g_assert_cmpint (g_value_get_int (&value), ==, 20);
139
140   g_param_spec_unref (pspec);
141 }
142
143 static void
144 test_param_spec_uint (void)
145 {
146   GParamSpec *pspec;
147   GValue value = G_VALUE_INIT;
148
149   pspec = g_param_spec_uint ("uint", NULL, NULL,
150                              20, 40, 30, G_PARAM_READWRITE);
151
152   g_param_value_set_default (pspec, &value);
153   g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_UINT);
154   g_assert_cmpint (g_value_get_uint (&value), ==, 30);
155   g_assert_true (g_param_value_defaults (pspec, &value));
156
157   g_value_set_uint (&value, 0);
158   g_assert_false (g_param_value_is_valid (pspec, &value));
159   g_assert_true (g_param_value_validate (pspec, &value));
160   g_assert_cmpint (g_value_get_uint (&value), ==, 20);
161
162   g_param_spec_unref (pspec);
163 }
164
165 static void
166 test_param_spec_long (void)
167 {
168   GParamSpec *pspec;
169   GValue value = G_VALUE_INIT;
170
171   pspec = g_param_spec_long ("long", NULL, NULL,
172                              20, 40, 30, G_PARAM_READWRITE);
173
174   g_param_value_set_default (pspec, &value);
175   g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_LONG);
176   g_assert_cmpint (g_value_get_long (&value), ==, 30);
177   g_assert_true (g_param_value_defaults (pspec, &value));
178
179   g_value_set_long (&value, 0);
180   g_assert_false (g_param_value_is_valid (pspec, &value));
181   g_assert_true (g_param_value_validate (pspec, &value));
182   g_assert_cmpint (g_value_get_long (&value), ==, 20);
183
184   g_param_spec_unref (pspec);
185 }
186
187 static void
188 test_param_spec_ulong (void)
189 {
190   GParamSpec *pspec;
191   GValue value = G_VALUE_INIT;
192
193   pspec = g_param_spec_ulong ("ulong", NULL, NULL,
194                               20, 40, 30, G_PARAM_READWRITE);
195
196   g_param_value_set_default (pspec, &value);
197   g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_ULONG);
198   g_assert_cmpint (g_value_get_ulong (&value), ==, 30);
199   g_assert_true (g_param_value_defaults (pspec, &value));
200
201   g_value_set_ulong (&value, 0);
202   g_assert_false (g_param_value_is_valid (pspec, &value));
203   g_assert_true (g_param_value_validate (pspec, &value));
204   g_assert_cmpint (g_value_get_ulong (&value), ==, 20);
205
206   g_param_spec_unref (pspec);
207 }
208
209 static void
210 test_param_spec_int64 (void)
211 {
212   GParamSpec *pspec;
213   GValue value = G_VALUE_INIT;
214
215   pspec = g_param_spec_int64 ("int64", NULL, NULL,
216                               20, 40, 30, G_PARAM_READWRITE);
217
218   g_param_value_set_default (pspec, &value);
219   g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_INT64);
220   g_assert_cmpint (g_value_get_int64 (&value), ==, 30);
221   g_assert_true (g_param_value_defaults (pspec, &value));
222
223   g_value_set_int64 (&value, 0);
224   g_assert_false (g_param_value_is_valid (pspec, &value));
225   g_assert_true (g_param_value_validate (pspec, &value));
226   g_assert_cmpint (g_value_get_int64 (&value), ==, 20);
227
228   g_param_spec_unref (pspec);
229 }
230
231 static void
232 test_param_spec_uint64 (void)
233 {
234   GParamSpec *pspec;
235   GValue value = G_VALUE_INIT;
236
237   pspec = g_param_spec_uint64 ("uint64", NULL, NULL,
238                                20, 40, 30, G_PARAM_READWRITE);
239
240   g_param_value_set_default (pspec, &value);
241   g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_UINT64);
242   g_assert_cmpint (g_value_get_uint64 (&value), ==, 30);
243   g_assert_true (g_param_value_defaults (pspec, &value));
244
245   g_value_set_uint64 (&value, 0);
246   g_assert_false (g_param_value_is_valid (pspec, &value));
247   g_assert_true (g_param_value_validate (pspec, &value));
248   g_assert_cmpint (g_value_get_uint64 (&value), ==, 20);
249
250   g_param_spec_unref (pspec);
251 }
252
253 static void
254 test_param_spec_float (void)
255 {
256   GParamSpec *pspec;
257   GValue value = G_VALUE_INIT;
258
259   pspec = g_param_spec_float ("float", NULL, NULL,
260                               20.0, 40.0, 30.0, G_PARAM_READWRITE);
261
262   g_param_value_set_default (pspec, &value);
263   g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_FLOAT);
264   g_assert_cmpfloat (g_value_get_float (&value), ==, 30.0);
265   g_assert_true (g_param_value_defaults (pspec, &value));
266
267   g_value_set_float (&value, 0.0);
268   g_assert_false (g_param_value_is_valid (pspec, &value));
269   g_assert_true (g_param_value_validate (pspec, &value));
270   g_assert_cmpint (g_value_get_float (&value), ==, 20.0);
271
272   g_param_spec_unref (pspec);
273 }
274
275 static void
276 test_param_spec_double (void)
277 {
278   GParamSpec *pspec;
279   GValue value = G_VALUE_INIT;
280
281   pspec = g_param_spec_double ("double", NULL, NULL,
282                                20.0, 40.0, 30.0, G_PARAM_READWRITE);
283
284   g_param_value_set_default (pspec, &value);
285   g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_DOUBLE);
286   g_assert_cmpfloat (g_value_get_double (&value), ==, 30.0);
287   g_assert_true (g_param_value_defaults (pspec, &value));
288
289   g_value_set_double (&value, 0.0);
290   g_assert_false (g_param_value_is_valid (pspec, &value));
291   g_assert_true (g_param_value_validate (pspec, &value));
292   g_assert_cmpint (g_value_get_double (&value), ==, 20.0);
293
294   g_param_spec_unref (pspec);
295 }
296
297 static void
298 test_param_spec_unichar (void)
299 {
300   GParamSpec *pspec;
301   GValue value = G_VALUE_INIT;
302
303   pspec = g_param_spec_unichar ("unichar", NULL, NULL,
304                                 0x1F4A9, G_PARAM_READWRITE);
305
306   g_assert_cmpstr (g_param_spec_get_name (pspec), ==, "unichar");
307
308   g_value_init (&value, G_TYPE_UINT);
309
310   /* Unicode codepoints can’t be 0x110000 or above, as that’s not representable
311    * in UTF-16. */
312   g_value_set_uint (&value, 0x110000);
313   g_assert_false (g_param_value_is_valid (pspec, &value));
314   g_assert_true (g_param_value_validate (pspec, &value));
315   g_assert_cmpint (g_value_get_uint (&value), ==, 0);
316
317   g_value_set_uint (&value, 0x20);
318   g_assert_true (g_param_value_is_valid (pspec, &value));
319   g_assert_false (g_param_value_validate (pspec, &value));
320   g_assert_cmpint (g_value_get_uint (&value), ==, 0x20);
321
322   g_param_spec_unref (pspec);
323 }
324
325 static void
326 test_param_spec_param (void)
327 {
328   GParamSpec *wrapped_pspec_uint;
329   GParamSpec *pspec;
330   GValue value = G_VALUE_INIT;
331
332   wrapped_pspec_uint = g_param_spec_uint ("uint", NULL, NULL,
333                                           0, G_MAXUINT, 5, G_PARAM_READWRITE);
334
335   pspec = g_param_spec_param ("param", NULL, NULL,
336                               G_TYPE_PARAM_UINT, G_PARAM_READWRITE);
337
338   g_assert_cmpstr (g_param_spec_get_name (pspec), ==, "param");
339
340   g_value_init (&value, G_TYPE_PARAM_UINT);
341
342   g_value_set_param (&value, wrapped_pspec_uint);
343   g_assert_true (g_param_value_is_valid (pspec, &value));
344   g_assert_false (g_param_value_validate (pspec, &value));
345   g_assert_true (g_value_get_param (&value) == wrapped_pspec_uint);
346
347   g_value_unset (&value);
348   g_param_spec_unref (pspec);
349   g_param_spec_unref (wrapped_pspec_uint);
350 }
351
352 static void
353 test_param_spec_null_param (void)
354 {
355   GParamSpec *pspec;
356   GValue value = G_VALUE_INIT;
357
358   pspec = g_param_spec_param ("param", NULL, NULL,
359                               G_TYPE_PARAM_POINTER, G_PARAM_READWRITE);
360
361   g_assert_cmpstr (g_param_spec_get_name (pspec), ==, "param");
362
363   g_value_init (&value, G_TYPE_PARAM_POINTER);
364   g_assert_false (g_param_value_is_valid (pspec, &value));
365   g_assert_false (g_param_value_validate (pspec, &value));
366
367   g_value_unset (&value);
368   g_param_spec_unref (pspec);
369 }
370
371 static void
372 test_param_spec_string (void)
373 {
374   GParamSpec *pspec;
375   GValue value = G_VALUE_INIT;
376
377   pspec = g_param_spec_string ("string", "nick", "blurb",
378                                NULL, G_PARAM_READWRITE);
379   g_value_init (&value, G_TYPE_STRING);
380
381   g_value_set_string (&value, "foobar");
382   g_assert_true (g_param_value_is_valid (pspec, &value));
383   g_assert_false (g_param_value_validate (pspec, &value));
384
385   g_value_set_string (&value, "");
386   g_assert_true (g_param_value_is_valid (pspec, &value));
387   g_assert_false (g_param_value_validate (pspec, &value));
388   g_assert_nonnull (g_value_get_string (&value));
389
390   /* test ensure_non_null */
391
392   G_PARAM_SPEC_STRING (pspec)->ensure_non_null = TRUE;
393
394   g_value_set_string (&value, NULL);
395   g_assert_false (g_param_value_is_valid (pspec, &value));
396   g_assert_true (g_param_value_validate (pspec, &value));
397   g_assert_nonnull (g_value_get_string (&value));
398
399   G_PARAM_SPEC_STRING (pspec)->ensure_non_null = FALSE;
400
401   /* test null_fold_if_empty */
402
403   G_PARAM_SPEC_STRING (pspec)->null_fold_if_empty = TRUE;
404
405   g_value_set_string (&value, "");
406   g_assert_false (g_param_value_is_valid (pspec, &value));
407   g_assert_true (g_param_value_validate (pspec, &value));
408   g_assert_null (g_value_get_string (&value));
409
410   g_value_set_static_string (&value, "");
411   g_assert_false (g_param_value_is_valid (pspec, &value));
412   g_assert_true (g_param_value_validate (pspec, &value));
413   g_assert_null (g_value_get_string (&value));
414
415   G_PARAM_SPEC_STRING (pspec)->null_fold_if_empty = FALSE;
416
417   /* test cset_first */
418
419   G_PARAM_SPEC_STRING (pspec)->cset_first = g_strdup ("abc");
420   G_PARAM_SPEC_STRING (pspec)->substitutor = '-';
421
422   g_value_set_string (&value, "ABC");
423   g_assert_false (g_param_value_is_valid (pspec, &value));
424   g_assert_true (g_param_value_validate (pspec, &value));
425   g_assert_cmpint (g_value_get_string (&value)[0], ==, '-');
426
427   g_value_set_static_string (&value, "ABC");
428   g_assert_false (g_param_value_is_valid (pspec, &value));
429   g_assert_true (g_param_value_validate (pspec, &value));
430   g_assert_cmpint (g_value_get_string (&value)[0], ==, '-');
431
432   /* test cset_nth */
433
434   G_PARAM_SPEC_STRING (pspec)->cset_nth = g_strdup ("abc");
435
436   g_value_set_string (&value, "aBC");
437   g_assert_false (g_param_value_is_valid (pspec, &value));
438   g_assert_true (g_param_value_validate (pspec, &value));
439   g_assert_cmpint (g_value_get_string (&value)[1], ==, '-');
440
441   g_value_set_static_string (&value, "aBC");
442   g_assert_false (g_param_value_is_valid (pspec, &value));
443   g_assert_true (g_param_value_validate (pspec, &value));
444   g_assert_cmpint (g_value_get_string (&value)[1], ==, '-');
445
446   g_value_unset (&value);
447   g_param_spec_unref (pspec);
448 }
449
450 static void
451 test_param_spec_override (void)
452 {
453   GParamSpec *ospec, *pspec;
454   GValue value = G_VALUE_INIT;
455
456   ospec = g_param_spec_char ("char", "nick", "blurb",
457                              20, 40, 30, G_PARAM_READWRITE);
458
459   pspec = g_param_spec_override ("override", ospec);
460
461   g_assert_cmpstr (g_param_spec_get_name (pspec), ==, "override");
462   g_assert_cmpstr (g_param_spec_get_nick (pspec), ==, "nick");
463   g_assert_cmpstr (g_param_spec_get_blurb (pspec), ==, "blurb");
464
465   g_value_init (&value, G_TYPE_CHAR);
466   g_value_set_char (&value, 30);
467
468   g_assert_true (g_param_value_defaults (pspec, &value));
469
470   g_value_set_char (&value, 0);
471   g_assert_false (g_param_value_is_valid (pspec, &value));
472   g_assert_true (g_param_value_validate (pspec, &value));
473   g_assert_cmpint (g_value_get_char (&value), ==, 20);
474
475   g_value_set_char (&value, 20);
476   g_assert_true (g_param_value_is_valid (pspec, &value));
477   g_assert_false (g_param_value_validate (pspec, &value));
478   g_assert_cmpint (g_value_get_char (&value), ==, 20);
479
480   g_value_set_char (&value, 40);
481   g_assert_true (g_param_value_is_valid (pspec, &value));
482   g_assert_false (g_param_value_validate (pspec, &value));
483   g_assert_cmpint (g_value_get_char (&value), ==, 40);
484
485   g_value_set_char (&value, 60);
486   g_assert_false (g_param_value_is_valid (pspec, &value));
487   g_assert_true (g_param_value_validate (pspec, &value));
488   g_assert_cmpint (g_value_get_char (&value), ==, 40);
489
490   g_param_spec_unref (pspec);
491   g_param_spec_unref (ospec);
492 }
493
494 static void
495 test_param_spec_gtype (void)
496 {
497   GParamSpec *pspec;
498   GValue value = G_VALUE_INIT;
499
500   pspec = g_param_spec_gtype ("gtype", "nick", "blurb",
501                               G_TYPE_PARAM, G_PARAM_READWRITE);
502
503   g_value_init (&value, G_TYPE_GTYPE);
504   g_value_set_gtype (&value, G_TYPE_PARAM);
505
506   g_assert_true (g_param_value_defaults (pspec, &value));
507
508   g_value_set_gtype (&value, G_TYPE_INT);
509   g_assert_false (g_param_value_is_valid (pspec, &value));
510   g_assert_true (g_param_value_validate (pspec, &value));
511   g_assert_cmpint (g_value_get_gtype (&value), ==, G_TYPE_PARAM);
512
513   g_value_set_gtype (&value, G_TYPE_PARAM_INT);
514   g_assert_true (g_param_value_is_valid (pspec, &value));
515   g_assert_false (g_param_value_validate (pspec, &value));
516   g_assert_cmpint (g_value_get_gtype (&value), ==, G_TYPE_PARAM_INT);
517
518   g_param_spec_unref (pspec);
519 }
520
521 static void
522 test_param_spec_variant (void)
523 {
524   GParamSpec *pspec;
525   GValue value = G_VALUE_INIT;
526   GValue value2 = G_VALUE_INIT;
527   GValue value3 = G_VALUE_INIT;
528   GValue value4 = G_VALUE_INIT;
529   GValue value5 = G_VALUE_INIT;
530
531   pspec = g_param_spec_variant ("variant", "nick", "blurb",
532                                 G_VARIANT_TYPE ("i"),
533                                 g_variant_new_int32 (42),
534                                 G_PARAM_READWRITE);
535
536   g_value_init (&value, G_TYPE_VARIANT);
537   g_value_set_variant (&value, g_variant_new_int32 (42));
538
539   g_value_init (&value2, G_TYPE_VARIANT);
540   g_value_set_variant (&value2, g_variant_new_int32 (43));
541
542   g_value_init (&value3, G_TYPE_VARIANT);
543   g_value_set_variant (&value3, g_variant_new_int16 (42));
544
545   g_value_init (&value4, G_TYPE_VARIANT);
546   g_value_set_variant (&value4, g_variant_new_parsed ("[@u 15, @u 10]"));
547
548   g_value_init (&value5, G_TYPE_VARIANT);
549   g_value_set_variant (&value5, NULL);
550
551   g_assert_true (g_param_value_defaults (pspec, &value));
552   g_assert_false (g_param_value_defaults (pspec, &value2));
553   g_assert_false (g_param_value_defaults (pspec, &value3));
554   g_assert_false (g_param_value_defaults (pspec, &value4));
555   g_assert_false (g_param_value_defaults (pspec, &value5));
556
557   g_assert_true (g_param_value_is_valid (pspec, &value));
558   g_assert_false (g_param_value_validate (pspec, &value));
559
560   g_value_reset (&value);
561   g_value_set_variant (&value, g_variant_new_uint32 (41));
562   g_assert_false (g_param_value_is_valid (pspec, &value));
563   g_assert_true (g_param_value_validate (pspec, &value));
564   g_assert_true (g_param_value_is_valid (pspec, &value));
565   g_assert_cmpint (g_variant_get_int32 (g_value_get_variant (&value)), ==, 42);
566   g_value_unset (&value);
567
568   g_value_unset (&value5);
569   g_value_unset (&value4);
570   g_value_unset (&value3);
571   g_value_unset (&value2);
572
573   g_param_spec_unref (pspec);
574 }
575
576 /* Test g_param_values_cmp() for #GParamSpecVariant. */
577 static void
578 test_param_spec_variant_cmp (void)
579 {
580   const struct
581     {
582       const GVariantType *pspec_type;
583       const gchar *v1;
584       enum
585         {
586           LESS_THAN = -1,
587           EQUAL = 0,
588           GREATER_THAN = 1,
589           NOT_EQUAL,
590         } expected_result;
591       const gchar *v2;
592     }
593   vectors[] =
594     {
595       { G_VARIANT_TYPE ("i"), "@i 1", LESS_THAN, "@i 2" },
596       { G_VARIANT_TYPE ("i"), "@i 2", EQUAL, "@i 2" },
597       { G_VARIANT_TYPE ("i"), "@i 3", GREATER_THAN, "@i 2" },
598       { G_VARIANT_TYPE ("i"), NULL, LESS_THAN, "@i 2" },
599       { G_VARIANT_TYPE ("i"), NULL, EQUAL, NULL },
600       { G_VARIANT_TYPE ("i"), "@i 1", GREATER_THAN, NULL },
601       { G_VARIANT_TYPE ("i"), "@u 1", LESS_THAN, "@u 2" },
602       { G_VARIANT_TYPE ("i"), "@as ['hi']", NOT_EQUAL, "@u 2" },
603       { G_VARIANT_TYPE ("i"), "@as ['hi']", NOT_EQUAL, "@as ['there']" },
604       { G_VARIANT_TYPE ("i"), "@as ['hi']", EQUAL, "@as ['hi']" },
605     };
606   gsize i;
607
608   for (i = 0; i < G_N_ELEMENTS (vectors); i++)
609     {
610       GParamSpec *pspec;
611       GValue v1 = G_VALUE_INIT;
612       GValue v2 = G_VALUE_INIT;
613       gint cmp;
614
615       pspec = g_param_spec_variant ("variant", "nick", "blurb",
616                                     vectors[i].pspec_type,
617                                     NULL,
618                                     G_PARAM_READWRITE);
619
620       g_value_init (&v1, G_TYPE_VARIANT);
621       g_value_set_variant (&v1,
622                            (vectors[i].v1 != NULL) ?
623                            g_variant_new_parsed (vectors[i].v1) : NULL);
624
625       g_value_init (&v2, G_TYPE_VARIANT);
626       g_value_set_variant (&v2,
627                            (vectors[i].v2 != NULL) ?
628                            g_variant_new_parsed (vectors[i].v2) : NULL);
629
630       cmp = g_param_values_cmp (pspec, &v1, &v2);
631
632       switch (vectors[i].expected_result)
633         {
634         case LESS_THAN:
635         case EQUAL:
636         case GREATER_THAN:
637           g_assert_cmpint (cmp, ==, vectors[i].expected_result);
638           break;
639         case NOT_EQUAL:
640           g_assert_cmpint (cmp, !=, 0);
641           break;
642         default:
643           g_assert_not_reached ();
644         }
645
646       g_value_unset (&v2);
647       g_value_unset (&v1);
648       g_param_spec_unref (pspec);
649     }
650 }
651
652 static void
653 test_param_value (void)
654 {
655   GParamSpec *p, *p2;
656   GParamSpec *pp;
657   GValue value = G_VALUE_INIT;
658
659   g_value_init (&value, G_TYPE_PARAM);
660   g_assert_true (G_VALUE_HOLDS_PARAM (&value));
661
662   p = g_param_spec_int ("my-int", "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
663
664   g_value_take_param (&value, p);
665   p2 = g_value_get_param (&value);
666   g_assert_true (p2 == p);
667
668   pp = g_param_spec_uint ("my-uint", "My UInt", "Blurb", 0, 10, 5, G_PARAM_READWRITE);
669   g_value_set_param (&value, pp);
670
671   p2 = g_value_dup_param (&value);
672   g_assert_true (p2 == pp); /* param specs use ref/unref for copy/free */
673   g_param_spec_unref (p2);
674
675   g_value_unset (&value);
676   g_param_spec_unref (pp);
677 }
678
679 static gint destroy_count;
680
681 static void
682 my_destroy (gpointer data)
683 {
684   destroy_count++;
685 }
686
687 static void
688 test_param_qdata (void)
689 {
690   GParamSpec *p;
691   gchar *bla;
692   GQuark q;
693
694   q = g_quark_from_string ("bla");
695
696   p = g_param_spec_int ("my-int", "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
697   g_param_spec_set_qdata (p, q, "bla");
698   bla = g_param_spec_get_qdata (p, q);
699   g_assert_cmpstr (bla, ==, "bla");
700
701   g_assert_cmpint (destroy_count, ==, 0);
702   g_param_spec_set_qdata_full (p, q, "bla", my_destroy);
703   g_param_spec_set_qdata_full (p, q, "blabla", my_destroy);
704   g_assert_cmpint (destroy_count, ==, 1);
705   g_assert_cmpstr (g_param_spec_steal_qdata (p, q), ==, "blabla");
706   g_assert_cmpint (destroy_count, ==, 1);
707   g_assert_null (g_param_spec_get_qdata (p, q));
708
709   g_param_spec_ref_sink (p);
710
711   g_param_spec_unref (p);
712 }
713
714 static void
715 test_param_validate (void)
716 {
717   GParamSpec *p;
718   GValue value = G_VALUE_INIT;
719
720   p = g_param_spec_int ("my-int", "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
721
722   g_value_init (&value, G_TYPE_INT);
723   g_value_set_int (&value, 100);
724   g_assert_false (g_param_value_defaults (p, &value));
725   g_assert_true (g_param_value_validate (p, &value));
726   g_assert_cmpint (g_value_get_int (&value), ==, 20);
727
728   g_param_value_set_default (p, &value);
729   g_assert_true (g_param_value_defaults (p, &value));
730   g_assert_cmpint (g_value_get_int (&value), ==, 10);
731
732   g_param_spec_unref (p);
733 }
734
735 static void
736 test_param_strings (void)
737 {
738   GParamSpec *p;
739
740   /* test canonicalization */
741   p = g_param_spec_int ("my_int", "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
742
743   g_assert_cmpstr (g_param_spec_get_name (p), ==, "my-int");
744   g_assert_cmpstr (g_param_spec_get_nick (p), ==, "My Int");
745   g_assert_cmpstr (g_param_spec_get_blurb (p), ==, "Blurb");
746
747   g_param_spec_unref (p);
748
749   /* test nick defaults to name */
750   p = g_param_spec_int ("my-int", NULL, NULL, 0, 20, 10, G_PARAM_READWRITE);
751
752   g_assert_cmpstr (g_param_spec_get_name (p), ==, "my-int");
753   g_assert_cmpstr (g_param_spec_get_nick (p), ==, "my-int");
754   g_assert_null (g_param_spec_get_blurb (p));
755
756   g_param_spec_unref (p);
757 }
758
759 static void
760 test_param_invalid_name (gconstpointer test_data)
761 {
762   const gchar *invalid_name = test_data;
763
764   g_test_summary ("Test that properties cannot be created with invalid names");
765
766   if (g_test_subprocess ())
767     {
768       GParamSpec *p;
769       p = g_param_spec_int (invalid_name, "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
770       g_param_spec_unref (p);
771       return;
772     }
773
774   g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
775   g_test_trap_assert_failed ();
776   g_test_trap_assert_stderr ("*CRITICAL*g_param_spec_is_valid_name (name)*");
777 }
778
779 static void
780 test_param_convert (void)
781 {
782   GParamSpec *p;
783   GValue v1 = G_VALUE_INIT;
784   GValue v2 = G_VALUE_INIT;
785
786   p = g_param_spec_int ("my-int", "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
787   g_value_init (&v1, G_TYPE_UINT);
788   g_value_set_uint (&v1, 43);
789
790   g_value_init (&v2, G_TYPE_INT);
791   g_value_set_int (&v2, -4);
792
793   g_assert_false (g_param_value_convert (p, &v1, &v2, TRUE));
794   g_assert_cmpint (g_value_get_int (&v2), ==, -4);
795
796   g_assert_true (g_param_value_convert (p, &v1, &v2, FALSE));
797   g_assert_cmpint (g_value_get_int (&v2), ==, 20);
798
799   g_param_spec_unref (p);
800 }
801
802 static void
803 test_value_transform (void)
804 {
805   GValue src = G_VALUE_INIT;
806   GValue dest = G_VALUE_INIT;
807
808 #define CHECK_INT_CONVERSION(type, getter, value)                       \
809   g_assert_true (g_value_type_transformable (G_TYPE_INT, type));        \
810   g_value_init (&src, G_TYPE_INT);                                      \
811   g_value_init (&dest, type);                                           \
812   g_value_set_int (&src, value);                                        \
813   g_assert_true (g_value_transform (&src, &dest));                      \
814   g_assert_cmpint (g_value_get_##getter (&dest), ==, value);            \
815   g_value_unset (&src);                                                 \
816   g_value_unset (&dest);
817
818   /* Keep a check for an integer in the range of 0-127 so we're
819    * still testing g_value_get_char().  See
820    * https://bugzilla.gnome.org/show_bug.cgi?id=659870
821    * for why it is broken.
822    */
823   CHECK_INT_CONVERSION(G_TYPE_CHAR, char, 124)
824
825   CHECK_INT_CONVERSION(G_TYPE_CHAR, schar, -124)
826   CHECK_INT_CONVERSION(G_TYPE_CHAR, schar, 124)
827   CHECK_INT_CONVERSION(G_TYPE_UCHAR, uchar, 0)
828   CHECK_INT_CONVERSION(G_TYPE_UCHAR, uchar, 255)
829   CHECK_INT_CONVERSION(G_TYPE_INT, int, -12345)
830   CHECK_INT_CONVERSION(G_TYPE_INT, int, 12345)
831   CHECK_INT_CONVERSION(G_TYPE_UINT, uint, 0)
832   CHECK_INT_CONVERSION(G_TYPE_UINT, uint, 12345)
833   CHECK_INT_CONVERSION(G_TYPE_LONG, long, -12345678)
834   CHECK_INT_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
835   CHECK_INT_CONVERSION(G_TYPE_INT64, int64, -12345678)
836   CHECK_INT_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
837   CHECK_INT_CONVERSION(G_TYPE_FLOAT, float, 12345678)
838   CHECK_INT_CONVERSION(G_TYPE_DOUBLE, double, 12345678)
839
840 #define CHECK_UINT_CONVERSION(type, getter, value)                      \
841   g_assert_true (g_value_type_transformable (G_TYPE_UINT, type));       \
842   g_value_init (&src, G_TYPE_UINT);                                     \
843   g_value_init (&dest, type);                                           \
844   g_value_set_uint (&src, value);                                       \
845   g_assert_true (g_value_transform (&src, &dest));                      \
846   g_assert_cmpuint (g_value_get_##getter (&dest), ==, value);           \
847   g_value_unset (&src);                                                 \
848   g_value_unset (&dest);
849
850   CHECK_UINT_CONVERSION(G_TYPE_CHAR, char, 124)
851   CHECK_UINT_CONVERSION(G_TYPE_CHAR, char, 124)
852   CHECK_UINT_CONVERSION(G_TYPE_UCHAR, uchar, 0)
853   CHECK_UINT_CONVERSION(G_TYPE_UCHAR, uchar, 255)
854   CHECK_UINT_CONVERSION(G_TYPE_INT, int, 12345)
855   CHECK_UINT_CONVERSION(G_TYPE_INT, int, 12345)
856   CHECK_UINT_CONVERSION(G_TYPE_UINT, uint, 0)
857   CHECK_UINT_CONVERSION(G_TYPE_UINT, uint, 12345)
858   CHECK_UINT_CONVERSION(G_TYPE_LONG, long, 12345678)
859   CHECK_UINT_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
860   CHECK_UINT_CONVERSION(G_TYPE_INT64, int64, 12345678)
861   CHECK_UINT_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
862   CHECK_UINT_CONVERSION(G_TYPE_FLOAT, float, 12345678)
863   CHECK_UINT_CONVERSION(G_TYPE_DOUBLE, double, 12345678)
864
865 #define CHECK_LONG_CONVERSION(type, getter, value)                      \
866   g_assert_true (g_value_type_transformable (G_TYPE_LONG, type));       \
867   g_value_init (&src, G_TYPE_LONG);                                     \
868   g_value_init (&dest, type);                                           \
869   g_value_set_long (&src, value);                                       \
870   g_assert_true (g_value_transform (&src, &dest));                      \
871   g_assert_cmpint (g_value_get_##getter (&dest), ==, value);            \
872   g_value_unset (&src);                                                 \
873   g_value_unset (&dest);
874
875   CHECK_LONG_CONVERSION(G_TYPE_CHAR, schar, -124)
876   CHECK_LONG_CONVERSION(G_TYPE_CHAR, schar, 124)
877   CHECK_LONG_CONVERSION(G_TYPE_UCHAR, uchar, 0)
878   CHECK_LONG_CONVERSION(G_TYPE_UCHAR, uchar, 255)
879   CHECK_LONG_CONVERSION(G_TYPE_INT, int, -12345)
880   CHECK_LONG_CONVERSION(G_TYPE_INT, int, 12345)
881   CHECK_LONG_CONVERSION(G_TYPE_UINT, uint, 0)
882   CHECK_LONG_CONVERSION(G_TYPE_UINT, uint, 12345)
883   CHECK_LONG_CONVERSION(G_TYPE_LONG, long, -12345678)
884   CHECK_LONG_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
885   CHECK_LONG_CONVERSION(G_TYPE_INT64, int64, -12345678)
886   CHECK_LONG_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
887   CHECK_LONG_CONVERSION(G_TYPE_FLOAT, float, 12345678)
888   CHECK_LONG_CONVERSION(G_TYPE_DOUBLE, double, 12345678)
889
890 #define CHECK_ULONG_CONVERSION(type, getter, value)                     \
891   g_assert_true (g_value_type_transformable (G_TYPE_ULONG, type));      \
892   g_value_init (&src, G_TYPE_ULONG);                                    \
893   g_value_init (&dest, type);                                           \
894   g_value_set_ulong (&src, value);                                      \
895   g_assert_true (g_value_transform (&src, &dest));                      \
896   g_assert_cmpuint (g_value_get_##getter (&dest), ==, value);           \
897   g_value_unset (&src);                                                 \
898   g_value_unset (&dest);
899
900   CHECK_ULONG_CONVERSION(G_TYPE_CHAR, char, 124)
901   CHECK_ULONG_CONVERSION(G_TYPE_CHAR, char, 124)
902   CHECK_ULONG_CONVERSION(G_TYPE_UCHAR, uchar, 0)
903   CHECK_ULONG_CONVERSION(G_TYPE_UCHAR, uchar, 255)
904   CHECK_ULONG_CONVERSION(G_TYPE_INT, int, -12345)
905   CHECK_ULONG_CONVERSION(G_TYPE_INT, int, 12345)
906   CHECK_ULONG_CONVERSION(G_TYPE_UINT, uint, 0)
907   CHECK_ULONG_CONVERSION(G_TYPE_UINT, uint, 12345)
908   CHECK_ULONG_CONVERSION(G_TYPE_LONG, long, 12345678)
909   CHECK_ULONG_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
910   CHECK_ULONG_CONVERSION(G_TYPE_INT64, int64, 12345678)
911   CHECK_ULONG_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
912   CHECK_ULONG_CONVERSION(G_TYPE_FLOAT, float, 12345678)
913   CHECK_ULONG_CONVERSION(G_TYPE_DOUBLE, double, 12345678)
914
915 #define CHECK_INT64_CONVERSION(type, getter, value)                     \
916   g_assert_true (g_value_type_transformable (G_TYPE_INT64, type));      \
917   g_value_init (&src, G_TYPE_INT64);                                    \
918   g_value_init (&dest, type);                                           \
919   g_value_set_int64 (&src, value);                                      \
920   g_assert_true (g_value_transform (&src, &dest));                      \
921   g_assert_cmpint (g_value_get_##getter (&dest), ==, value);            \
922   g_value_unset (&src);                                                 \
923   g_value_unset (&dest);
924
925   CHECK_INT64_CONVERSION(G_TYPE_CHAR, schar, -124)
926   CHECK_INT64_CONVERSION(G_TYPE_CHAR, schar, 124)
927   CHECK_INT64_CONVERSION(G_TYPE_UCHAR, uchar, 0)
928   CHECK_INT64_CONVERSION(G_TYPE_UCHAR, uchar, 255)
929   CHECK_INT64_CONVERSION(G_TYPE_INT, int, -12345)
930   CHECK_INT64_CONVERSION(G_TYPE_INT, int, 12345)
931   CHECK_INT64_CONVERSION(G_TYPE_UINT, uint, 0)
932   CHECK_INT64_CONVERSION(G_TYPE_UINT, uint, 12345)
933   CHECK_INT64_CONVERSION(G_TYPE_LONG, long, -12345678)
934   CHECK_INT64_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
935   CHECK_INT64_CONVERSION(G_TYPE_INT64, int64, -12345678)
936   CHECK_INT64_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
937   CHECK_INT64_CONVERSION(G_TYPE_FLOAT, float, 12345678)
938   CHECK_INT64_CONVERSION(G_TYPE_DOUBLE, double, 12345678)
939
940 #define CHECK_UINT64_CONVERSION(type, getter, value)                    \
941   g_assert_true (g_value_type_transformable (G_TYPE_UINT64, type));     \
942   g_value_init (&src, G_TYPE_UINT64);                                   \
943   g_value_init (&dest, type);                                           \
944   g_value_set_uint64 (&src, value);                                     \
945   g_assert_true (g_value_transform (&src, &dest));                      \
946   g_assert_cmpuint (g_value_get_##getter (&dest), ==, value);           \
947   g_value_unset (&src);                                                 \
948   g_value_unset (&dest);
949
950   CHECK_UINT64_CONVERSION(G_TYPE_CHAR, schar, -124)
951   CHECK_UINT64_CONVERSION(G_TYPE_CHAR, schar, 124)
952   CHECK_UINT64_CONVERSION(G_TYPE_UCHAR, uchar, 0)
953   CHECK_UINT64_CONVERSION(G_TYPE_UCHAR, uchar, 255)
954   CHECK_UINT64_CONVERSION(G_TYPE_INT, int, -12345)
955   CHECK_UINT64_CONVERSION(G_TYPE_INT, int, 12345)
956   CHECK_UINT64_CONVERSION(G_TYPE_UINT, uint, 0)
957   CHECK_UINT64_CONVERSION(G_TYPE_UINT, uint, 12345)
958   CHECK_UINT64_CONVERSION(G_TYPE_LONG, long, -12345678)
959   CHECK_UINT64_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
960   CHECK_UINT64_CONVERSION(G_TYPE_INT64, int64, -12345678)
961   CHECK_UINT64_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
962   CHECK_UINT64_CONVERSION(G_TYPE_FLOAT, float, 12345678)
963   CHECK_UINT64_CONVERSION(G_TYPE_DOUBLE, double, 12345678)
964
965 #define CHECK_FLOAT_CONVERSION(type, getter, value)                    \
966   g_assert_true (g_value_type_transformable (G_TYPE_FLOAT, type));     \
967   g_value_init (&src, G_TYPE_FLOAT);                                   \
968   g_value_init (&dest, type);                                          \
969   g_value_set_float (&src, value);                                     \
970   g_assert_true (g_value_transform (&src, &dest));                     \
971   g_assert_cmpfloat (g_value_get_##getter (&dest), ==, value);         \
972   g_value_unset (&src);                                                \
973   g_value_unset (&dest);
974
975   CHECK_FLOAT_CONVERSION(G_TYPE_CHAR, schar, -124)
976   CHECK_FLOAT_CONVERSION(G_TYPE_CHAR, schar, 124)
977   CHECK_FLOAT_CONVERSION(G_TYPE_UCHAR, uchar, 0)
978   CHECK_FLOAT_CONVERSION(G_TYPE_UCHAR, uchar, 255)
979   CHECK_FLOAT_CONVERSION(G_TYPE_INT, int, -12345)
980   CHECK_FLOAT_CONVERSION(G_TYPE_INT, int, 12345)
981   CHECK_FLOAT_CONVERSION(G_TYPE_UINT, uint, 0)
982   CHECK_FLOAT_CONVERSION(G_TYPE_UINT, uint, 12345)
983   CHECK_FLOAT_CONVERSION(G_TYPE_LONG, long, -12345678)
984   CHECK_FLOAT_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
985   CHECK_FLOAT_CONVERSION(G_TYPE_INT64, int64, -12345678)
986   CHECK_FLOAT_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
987   CHECK_FLOAT_CONVERSION(G_TYPE_FLOAT, float, 12345678)
988   CHECK_FLOAT_CONVERSION(G_TYPE_DOUBLE, double, 12345678)
989
990 #define CHECK_DOUBLE_CONVERSION(type, getter, value)                    \
991   g_assert_true (g_value_type_transformable (G_TYPE_DOUBLE, type));     \
992   g_value_init (&src, G_TYPE_DOUBLE);                                   \
993   g_value_init (&dest, type);                                           \
994   g_value_set_double (&src, value);                                     \
995   g_assert_true (g_value_transform (&src, &dest));                      \
996   g_assert_cmpfloat (g_value_get_##getter (&dest), ==, value);          \
997   g_value_unset (&src);                                                 \
998   g_value_unset (&dest);
999
1000   CHECK_DOUBLE_CONVERSION(G_TYPE_CHAR, schar, -124)
1001   CHECK_DOUBLE_CONVERSION(G_TYPE_CHAR, schar, 124)
1002   CHECK_DOUBLE_CONVERSION(G_TYPE_UCHAR, uchar, 0)
1003   CHECK_DOUBLE_CONVERSION(G_TYPE_UCHAR, uchar, 255)
1004   CHECK_DOUBLE_CONVERSION(G_TYPE_INT, int, -12345)
1005   CHECK_DOUBLE_CONVERSION(G_TYPE_INT, int, 12345)
1006   CHECK_DOUBLE_CONVERSION(G_TYPE_UINT, uint, 0)
1007   CHECK_DOUBLE_CONVERSION(G_TYPE_UINT, uint, 12345)
1008   CHECK_DOUBLE_CONVERSION(G_TYPE_LONG, long, -12345678)
1009   CHECK_DOUBLE_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
1010   CHECK_DOUBLE_CONVERSION(G_TYPE_INT64, int64, -12345678)
1011   CHECK_DOUBLE_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
1012   CHECK_DOUBLE_CONVERSION(G_TYPE_FLOAT, float, 12345678)
1013   CHECK_DOUBLE_CONVERSION(G_TYPE_DOUBLE, double, 12345678)
1014
1015 #define CHECK_BOOLEAN_CONVERSION(type, setter, value)                   \
1016   g_assert_true (g_value_type_transformable (type, G_TYPE_BOOLEAN));    \
1017   g_value_init (&src, type);                                            \
1018   g_value_init (&dest, G_TYPE_BOOLEAN);                                 \
1019   g_value_set_##setter (&src, value);                                   \
1020   g_assert_true (g_value_transform (&src, &dest));                      \
1021   g_assert_cmpint (g_value_get_boolean (&dest), ==, TRUE);              \
1022   g_value_set_##setter (&src, 0);                                       \
1023   g_assert_true (g_value_transform (&src, &dest));                      \
1024   g_assert_cmpint (g_value_get_boolean (&dest), ==, FALSE);             \
1025   g_value_unset (&src);                                                 \
1026   g_value_unset (&dest);
1027
1028   CHECK_BOOLEAN_CONVERSION(G_TYPE_INT, int, -12345)
1029   CHECK_BOOLEAN_CONVERSION(G_TYPE_UINT, uint, 12345)
1030   CHECK_BOOLEAN_CONVERSION(G_TYPE_LONG, long, -12345678)
1031   CHECK_BOOLEAN_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
1032   CHECK_BOOLEAN_CONVERSION(G_TYPE_INT64, int64, -12345678)
1033   CHECK_BOOLEAN_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
1034
1035 #define CHECK_STRING_CONVERSION(int_type, setter, int_value)            \
1036   g_assert_true (g_value_type_transformable (int_type, G_TYPE_STRING)); \
1037   g_value_init (&src, int_type);                                        \
1038   g_value_init (&dest, G_TYPE_STRING);                                  \
1039   g_value_set_##setter (&src, int_value);                               \
1040   g_assert_true (g_value_transform (&src, &dest));                      \
1041   g_assert_cmpstr (g_value_get_string (&dest), ==, #int_value);         \
1042   g_value_unset (&src);                                                 \
1043   g_value_unset (&dest);
1044
1045   CHECK_STRING_CONVERSION(G_TYPE_INT, int, -12345)
1046   CHECK_STRING_CONVERSION(G_TYPE_UINT, uint, 12345)
1047   CHECK_STRING_CONVERSION(G_TYPE_LONG, long, -12345678)
1048   CHECK_STRING_CONVERSION(G_TYPE_ULONG, ulong, 12345678)
1049   CHECK_STRING_CONVERSION(G_TYPE_INT64, int64, -12345678)
1050   CHECK_STRING_CONVERSION(G_TYPE_UINT64, uint64, 12345678)
1051   CHECK_STRING_CONVERSION(G_TYPE_FLOAT, float, 0.500000)
1052   CHECK_STRING_CONVERSION(G_TYPE_DOUBLE, double, -1.234567)
1053
1054   g_assert_false (g_value_type_transformable (G_TYPE_STRING, G_TYPE_CHAR));
1055   g_value_init (&src, G_TYPE_STRING);
1056   g_value_init (&dest, G_TYPE_CHAR);
1057   g_value_set_static_string (&src, "bla");
1058   g_value_set_schar (&dest, 'c');
1059   g_assert_false (g_value_transform (&src, &dest));
1060   g_assert_cmpint (g_value_get_schar (&dest), ==, 'c');
1061   g_value_unset (&src);
1062   g_value_unset (&dest);
1063 }
1064
1065
1066 /* We create some dummy objects with a simple relationship:
1067  *
1068  *           GObject
1069  *          /       \
1070  * TestObjectA     TestObjectC
1071  *      |
1072  * TestObjectB
1073  *
1074  * ie: TestObjectB is a subclass of TestObjectA and TestObjectC is
1075  * related to neither.
1076  */
1077
1078 static GType test_object_a_get_type (void);
1079 typedef GObject TestObjectA; typedef GObjectClass TestObjectAClass;
1080 G_DEFINE_TYPE (TestObjectA, test_object_a, G_TYPE_OBJECT)
1081 static void test_object_a_class_init (TestObjectAClass *class) { }
1082 static void test_object_a_init (TestObjectA *a) { }
1083
1084 static GType test_object_b_get_type (void);
1085 typedef GObject TestObjectB; typedef GObjectClass TestObjectBClass;
1086 G_DEFINE_TYPE (TestObjectB, test_object_b, test_object_a_get_type ())
1087 static void test_object_b_class_init (TestObjectBClass *class) { }
1088 static void test_object_b_init (TestObjectB *b) { }
1089
1090 static GType test_object_c_get_type (void);
1091 typedef GObject TestObjectC; typedef GObjectClass TestObjectCClass;
1092 G_DEFINE_TYPE (TestObjectC, test_object_c, G_TYPE_OBJECT)
1093 static void test_object_c_class_init (TestObjectCClass *class) { }
1094 static void test_object_c_init (TestObjectC *c) { }
1095
1096 /* We create an interface and programmatically populate it with
1097  * properties of each of the above type, with various flag combinations.
1098  *
1099  * Properties are named like "type-perm" where type is 'a', 'b' or 'c'
1100  * and perm is a series of characters, indicating the permissions:
1101  *
1102  *   - 'r': readable
1103  *   - 'w': writable
1104  *   - 'c': construct
1105  *   - 'C': construct-only
1106  *
1107  * It doesn't make sense to have a property that is neither readable nor
1108  * writable.  It is also not valid to have construct or construct-only
1109  * on read-only params.  Finally, it is invalid to have both construct
1110  * and construct-only specified, so we do not consider those cases.
1111  * That gives us 7 possible permissions:
1112  *
1113  *     'r', 'w', 'rw', 'wc', 'rwc', 'wC', 'rwC'
1114  *
1115  * And 9 impossible ones:
1116  *
1117  *     '', 'c', 'rc', 'C', 'rC', 'cC', 'rcC', 'wcC', rwcC'
1118  *
1119  * For a total of 16 combinations.
1120  *
1121  * That gives a total of 48 (16 * 3) possible flag/type combinations, of
1122  * which 27 (9 * 3) are impossible to install.
1123  *
1124  * That gives 21 (7 * 3) properties that will be installed.
1125  */
1126 typedef GTypeInterface TestInterfaceInterface;
1127 static GType test_interface_get_type (void);
1128 //typedef struct _TestInterface TestInterface;
1129 G_DEFINE_INTERFACE (TestInterface, test_interface, G_TYPE_OBJECT)
1130 static void
1131 test_interface_default_init (TestInterfaceInterface *iface)
1132 {
1133   const gchar *names[] = { "a", "b", "c" };
1134   const gchar *perms[] = { NULL, "r",  "w",  "rw",
1135                            NULL, NULL, "wc", "rwc",
1136                            NULL, NULL, "wC", "rwC",
1137                            NULL, NULL, NULL, NULL };
1138   const GType types[] = { test_object_a_get_type (), test_object_b_get_type (), test_object_c_get_type () };
1139   guint i, j;
1140
1141   for (i = 0; i < G_N_ELEMENTS (types); i++)
1142     for (j = 0; j < G_N_ELEMENTS (perms); j++)
1143       {
1144         gchar prop_name[10];
1145         GParamSpec *pspec;
1146
1147         if (perms[j] == NULL)
1148           {
1149             if (!g_test_undefined ())
1150               continue;
1151
1152             /* we think that this is impossible.  make sure. */
1153             pspec = g_param_spec_object ("xyz", "xyz", "xyz", types[i], j);
1154
1155             g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1156                                    "*assertion*pspec->flags*failed*");
1157             g_object_interface_install_property (iface, pspec);
1158             g_test_assert_expected_messages ();
1159
1160             continue;
1161           }
1162
1163         /* install the property */
1164         g_snprintf (prop_name, sizeof prop_name, "%s-%s", names[i], perms[j]);
1165         pspec = g_param_spec_object (prop_name, prop_name, prop_name, types[i], j);
1166         g_object_interface_install_property (iface, pspec);
1167       }
1168 }
1169
1170 /* We now have 21 properties.  Each property may be correctly
1171  * implemented with the following types:
1172  *
1173  *   Properties         Valid Types       Reason
1174  *
1175  *   a-r                a, b              Read only can provide subclasses
1176  *   a-w, wc, wC        a, GObject        Write only can accept superclasses
1177  *   a-rw, rwc, rwC     a                 Read-write must be exactly equal
1178  *
1179  *   b-r                b                 (as above)
1180  *   b-w, wc, wC        b, a, GObject
1181  *   b-rw, rwc, rwC     b
1182  *
1183  *   c-r                c                 (as above)
1184  *   c-wo, wc, wC       c, GObject
1185  *   c-rw, rwc, rwC     c
1186  *
1187  * We can express this in a 48-by-4 table where each row represents an
1188  * installed property and each column represents a type.  The value in
1189  * the table represents if it is valid to subclass the row's property
1190  * with the type of the column:
1191  *
1192  *   - 0:   invalid because the interface property doesn't exist (invalid flags)
1193  *   - 'v': valid
1194  *   - '=': invalid because of the type not being exactly equal
1195  *   - '<': invalid because of the type not being a subclass
1196  *   - '>': invalid because of the type not being a superclass
1197  *
1198  * We organise the table by interface property type ('a', 'b', 'c') then
1199  * by interface property flags.
1200  */
1201
1202 static gint valid_impl_types[48][4] = {
1203                     /* a    b    c    GObject */
1204     /* 'a-' */       { 0, },
1205     /* 'a-r' */      { 'v', 'v', '<', '<' },
1206     /* 'a-w' */      { 'v', '>', '>', 'v' },
1207     /* 'a-rw' */     { 'v', '=', '=', '=' },
1208     /* 'a-c */       { 0, },
1209     /* 'a-rc' */     { 0, },
1210     /* 'a-wc' */     { 'v', '>', '>', 'v' },
1211     /* 'a-rwc' */    { 'v', '=', '=', '=' },
1212     /* 'a-C */       { 0, },
1213     /* 'a-rC' */     { 0, },
1214     /* 'a-wC' */     { 'v', '>', '>', 'v' },
1215     /* 'a-rwC' */    { 'v', '=', '=', '=' },
1216     /* 'a-cC */      { 0, },
1217     /* 'a-rcC' */    { 0, },
1218     /* 'a-wcC' */    { 0, },
1219     /* 'a-rwcC' */   { 0, },
1220
1221     /* 'b-' */       { 0, },
1222     /* 'b-r' */      { '<', 'v', '<', '<' },
1223     /* 'b-w' */      { 'v', 'v', '>', 'v' },
1224     /* 'b-rw' */     { '=', 'v', '=', '=' },
1225     /* 'b-c */       { 0, },
1226     /* 'b-rc' */     { 0, },
1227     /* 'b-wc' */     { 'v', 'v', '>', 'v' },
1228     /* 'b-rwc' */    { '=', 'v', '=', '=' },
1229     /* 'b-C */       { 0, },
1230     /* 'b-rC' */     { 0, },
1231     /* 'b-wC' */     { 'v', 'v', '>', 'v' },
1232     /* 'b-rwC' */    { '=', 'v', '=', '=' },
1233     /* 'b-cC */      { 0, },
1234     /* 'b-rcC' */    { 0, },
1235     /* 'b-wcC' */    { 0, },
1236     /* 'b-rwcC' */   { 0, },
1237
1238     /* 'c-' */       { 0, },
1239     /* 'c-r' */      { '<', '<', 'v', '<' },
1240     /* 'c-w' */      { '>', '>', 'v', 'v' },
1241     /* 'c-rw' */     { '=', '=', 'v', '=' },
1242     /* 'c-c */       { 0, },
1243     /* 'c-rc' */     { 0, },
1244     /* 'c-wc' */     { '>', '>', 'v', 'v' },
1245     /* 'c-rwc' */    { '=', '=', 'v', '=' },
1246     /* 'c-C */       { 0, },
1247     /* 'c-rC' */     { 0, },
1248     /* 'c-wC' */     { '>', '>', 'v', 'v' },
1249     /* 'c-rwC' */    { '=', '=', 'v', '=' },
1250     /* 'c-cC */      { 0, },
1251     /* 'c-rcC' */    { 0, },
1252     /* 'c-wcC' */    { 0, },
1253     /* 'c-rwcC' */   { 0, }
1254 };
1255
1256 /* We also try to change the flags.  We must ensure that all
1257  * implementations provide all functionality promised by the interface.
1258  * We must therefore never remove readability or writability (but we can
1259  * add them).  Construct-only is a restrictions that applies to
1260  * writability, so we can never add it unless writability was never
1261  * present in the first place, in which case "writable at construct
1262  * only" is still better than "not writable".
1263  *
1264  * The 'construct' flag is of interest only to the implementation.  It
1265  * may be changed at any time.
1266  *
1267  *   Properties         Valid Access      Reason
1268  *
1269  *   *-r                r, rw, rwc, rwC   Must keep readable, but can restrict newly-added writable
1270  *   *-w                w, rw, rwc        Must keep writable unrestricted
1271  *   *-rw               rw, rwc           Must not add any restrictions
1272  *   *-rwc              rw, rwc           Must not add any restrictions
1273  *   *-rwC              rw, rwc, rwC      Can remove 'construct-only' restriction
1274  *   *-wc               rwc, rw, w, wc    Can add readability
1275  *   *-wC               rwC, rw, w, wC    Can add readability or remove 'construct only' restriction
1276  *                        rwc, wc
1277  *
1278  * We can represent this with a 16-by-16 table.  The rows represent the
1279  * flags of the property on the interface.  The columns is the flags to
1280  * try to use when overriding the property.  The cell contents are:
1281  *
1282  *   - 0:   invalid because the interface property doesn't exist (invalid flags)
1283  *   - 'v': valid
1284  *   - 'i': invalid because the implementation flags are invalid
1285  *   - 'f': invalid because of the removal of functionality
1286  *   - 'r': invalid because of the addition of restrictions (ie: construct-only)
1287  *
1288  * We also ensure that removal of functionality is reported before
1289  * addition of restrictions, since this is a more basic problem.
1290  */
1291 static gint valid_impl_flags[16][16] = {
1292                  /* ''   r    w    rw   c    rc   wc   rwc  C    rC   wC   rwC  cC   rcC  wcC  rwcC */
1293     /* '*-' */    { 0, },
1294     /* '*-r' */   { 'i', 'v', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'i', 'i' },
1295     /* '*-w' */   { 'i', 'f', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'r', 'r', 'i', 'i', 'i', 'i' },
1296     /* '*-rw' */  { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'r', 'i', 'i', 'i', 'i' },
1297     /* '*-c */    { 0, },
1298     /* '*-rc' */  { 0, },
1299     /* '*-wc' */  { 'i', 'f', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'r', 'r', 'i', 'i', 'i', 'i' },
1300     /* '*-rwc' */ { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'r', 'i', 'i', 'i', 'i' },
1301     /* '*-C */    { 0, },
1302     /* '*-rC' */  { 0, },
1303     /* '*-wC' */  { 'i', 'f', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'i', 'i' },
1304     /* '*-rwC' */ { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'i', 'i' },
1305 };
1306
1307 static guint change_this_flag;
1308 static guint change_this_type;
1309 static guint use_this_flag;
1310 static guint use_this_type;
1311
1312 typedef GObjectClass TestImplementationClass;
1313 typedef GObject TestImplementation;
1314
1315 static void test_implementation_init (TestImplementation *impl) { }
1316 static void test_implementation_iface_init (TestInterfaceInterface *iface) { }
1317
1318 static GType test_implementation_get_type (void);
1319 G_DEFINE_TYPE_WITH_CODE (TestImplementation, test_implementation, G_TYPE_OBJECT,
1320                          G_IMPLEMENT_INTERFACE (test_interface_get_type (), test_implementation_iface_init))
1321
1322 static void test_implementation_class_init (TestImplementationClass *class)
1323 {
1324   const gchar *names[] = { "a", "b", "c" };
1325   const gchar *perms[] = { NULL, "r",  "w",  "rw",
1326                            NULL, NULL, "wc", "rwc",
1327                            NULL, NULL, "wC", "rwC",
1328                            NULL, NULL, NULL, NULL };
1329   const GType types[] = { test_object_a_get_type (), test_object_b_get_type (),
1330                           test_object_c_get_type (), G_TYPE_OBJECT };
1331   gchar prop_name[10];
1332   GParamSpec *pspec;
1333   guint i, j;
1334
1335   class->get_property = GINT_TO_POINTER (1);
1336   class->set_property = GINT_TO_POINTER (1);
1337
1338   /* Install all of the non-modified properties or else GObject will
1339    * complain about non-implemented properties.
1340    */
1341   for (i = 0; i < 3; i++)
1342     for (j = 0; j < G_N_ELEMENTS (perms); j++)
1343       {
1344         if (i == change_this_type && j == change_this_flag)
1345           continue;
1346
1347         if (perms[j] != NULL)
1348           {
1349             /* override the property without making changes */
1350             g_snprintf (prop_name, sizeof prop_name, "%s-%s", names[i], perms[j]);
1351             g_object_class_override_property (class, 1, prop_name);
1352           }
1353       }
1354
1355   /* Now try installing our modified property */
1356   if (perms[change_this_flag] == NULL)
1357     g_error ("Interface property does not exist");
1358
1359   g_snprintf (prop_name, sizeof prop_name, "%s-%s", names[change_this_type], perms[change_this_flag]);
1360   pspec = g_param_spec_object (prop_name, prop_name, prop_name, types[use_this_type], use_this_flag);
1361   g_object_class_install_property (class, 1, pspec);
1362 }
1363
1364 typedef struct {
1365   gint change_this_flag;
1366   gint change_this_type;
1367   gint use_this_flag;
1368   gint use_this_type;
1369 } TestParamImplementData;
1370
1371 static void
1372 test_param_implement_child (gconstpointer user_data)
1373 {
1374   TestParamImplementData *data = (gpointer) user_data;
1375
1376   /* GObject oddity: GObjectClass must be initialised before we can
1377    * initialise a GTypeInterface.
1378    */
1379   g_type_class_ref (G_TYPE_OBJECT);
1380
1381   /* Bring up the interface first. */
1382   g_type_default_interface_ref (test_interface_get_type ());
1383
1384   /* Copy the flags into the global vars so
1385    * test_implementation_class_init() will see them.
1386    */
1387   change_this_flag = data->change_this_flag;
1388   change_this_type = data->change_this_type;
1389   use_this_flag = data->use_this_flag;
1390   use_this_type = data->use_this_type;
1391
1392   g_type_class_ref (test_implementation_get_type ());
1393 }
1394
1395 static void
1396 test_param_implement (void)
1397 {
1398   gchar *test_path;
1399
1400   /* This test is slow. */
1401   if (!g_test_slow ())
1402     {
1403       g_test_skip ("Skipping slow /param/implement test");
1404       return;
1405     }
1406
1407   for (change_this_flag = 0; change_this_flag < 16; change_this_flag++)
1408     for (change_this_type = 0; change_this_type < 3; change_this_type++)
1409       for (use_this_flag = 0; use_this_flag < 16; use_this_flag++)
1410         for (use_this_type = 0; use_this_type < 4; use_this_type++)
1411           {
1412             if (!g_test_undefined ())
1413               {
1414                 /* only test the valid (defined) cases, e.g. under valgrind */
1415                 if (valid_impl_flags[change_this_flag][use_this_flag] != 'v')
1416                   continue;
1417
1418                 if (valid_impl_types[change_this_type * 16 + change_this_flag][use_this_type] != 'v')
1419                   continue;
1420               }
1421
1422             test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
1423                                          change_this_flag, change_this_type,
1424                                          use_this_flag, use_this_type);
1425             g_test_trap_subprocess (test_path, G_TIME_SPAN_SECOND,
1426                                     G_TEST_SUBPROCESS_DEFAULT);
1427             g_free (test_path);
1428
1429             /* We want to ensure that any flags mismatch problems are reported first. */
1430             switch (valid_impl_flags[change_this_flag][use_this_flag])
1431               {
1432               case 0:
1433                 /* make sure the other table agrees */
1434                 g_assert_cmpint (valid_impl_types[change_this_type * 16 + change_this_flag][use_this_type], ==, 0);
1435                 g_test_trap_assert_failed ();
1436                 g_test_trap_assert_stderr ("*Interface property does not exist*");
1437                 continue;
1438
1439               case 'i':
1440                 g_test_trap_assert_failed ();
1441                 g_test_trap_assert_stderr ("*pspec->flags*");
1442                 continue;
1443
1444               case 'f':
1445                 g_test_trap_assert_failed ();
1446                 g_test_trap_assert_stderr ("*remove functionality*");
1447                 continue;
1448
1449               case 'r':
1450                 g_test_trap_assert_failed ();
1451                 g_test_trap_assert_stderr ("*introduce additional restrictions*");
1452                 continue;
1453
1454               case 'v':
1455                 break;
1456               }
1457
1458             /* Next, we check if there should have been a type error. */
1459             switch (valid_impl_types[change_this_type * 16 + change_this_flag][use_this_type])
1460               {
1461               case 0:
1462                 /* this should have been caught above */
1463                 g_assert_not_reached ();
1464
1465               case '=':
1466                 g_test_trap_assert_failed ();
1467                 g_test_trap_assert_stderr ("*exactly equal*");
1468                 continue;
1469
1470               case '<':
1471                 g_test_trap_assert_failed ();
1472                 g_test_trap_assert_stderr ("*equal to or more restrictive*");
1473                 continue;
1474
1475               case '>':
1476                 g_test_trap_assert_failed ();
1477                 g_test_trap_assert_stderr ("*equal to or less restrictive*");
1478                 continue;
1479
1480               case 'v':
1481                 break;
1482               }
1483
1484             g_test_trap_assert_passed ();
1485           }
1486 }
1487
1488 static void
1489 test_param_default (void)
1490 {
1491   GParamSpec *param;
1492   const GValue *def;
1493
1494   param = g_param_spec_int ("my-int", "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
1495   def = g_param_spec_get_default_value (param);
1496
1497   g_assert_true (G_VALUE_HOLDS (def, G_TYPE_INT));
1498   g_assert_cmpint (g_value_get_int (def), ==, 10);
1499
1500   g_param_spec_unref (param);
1501 }
1502
1503 static void
1504 test_param_is_valid_name (void)
1505 {
1506   const gchar *valid_names[] =
1507     {
1508       "property",
1509       "i",
1510       "multiple-segments",
1511       "segment0-SEGMENT1",
1512       "using_underscores",
1513     };
1514   const gchar *invalid_names[] =
1515     {
1516       "",
1517       "7zip",
1518       "my_int:hello",
1519     };
1520   gsize i;
1521
1522   for (i = 0; i < G_N_ELEMENTS (valid_names); i++)
1523     g_assert_true (g_param_spec_is_valid_name (valid_names[i]));
1524
1525   for (i = 0; i < G_N_ELEMENTS (invalid_names); i++)
1526     g_assert_false (g_param_spec_is_valid_name (invalid_names[i]));
1527 }
1528
1529 static void
1530 param_int_init (GParamSpec *pspec)
1531 {
1532   GParamSpecInt *ispec = (GParamSpecInt *)pspec;
1533
1534   ispec->minimum = 0x7fffffff;
1535   ispec->maximum = 0x80000000;
1536   ispec->default_value = 0;
1537 }
1538
1539 static void
1540 param_int_set_default (GParamSpec *pspec,
1541                        GValue     *value)
1542 {
1543   value->data[0].v_int = ((GParamSpecInt *)pspec)->default_value;
1544 }
1545
1546 static gboolean
1547 param_int_validate (GParamSpec *pspec,
1548                     GValue     *value)
1549 {
1550   GParamSpecInt *ispec = (GParamSpecInt *)pspec;
1551   int oval = value->data[0].v_int;
1552
1553   value->data[0].v_int = CLAMP (value->data[0].v_int, ispec->minimum, ispec->maximum);
1554
1555   return value->data[0].v_int != oval;
1556 }
1557
1558 static int
1559 param_int_values_cmp (GParamSpec   *pspec,
1560                       const GValue *value1,
1561                       const GValue *value2)
1562 {
1563   if (value1->data[0].v_int < value2->data[0].v_int)
1564     return -1;
1565   else
1566     return value1->data[0].v_int > value2->data[0].v_int;
1567 }
1568
1569 static GType custom_type;
1570
1571 /* Register a pspec that has a validate vfunc, but not
1572  * value_is_valid, to test the fallback in g_param_value_is_valid
1573  */
1574 static void
1575 register_custom_pspec (void)
1576 {
1577   const GParamSpecTypeInfo pspec_info = {
1578     sizeof (GParamSpecInt),   /* instance_size */
1579     16,                       /* n_preallocs */
1580     param_int_init,           /* instance_init */
1581     G_TYPE_INT,               /* value_type */
1582     NULL,                     /* finalize */
1583     param_int_set_default,    /* value_set_default */
1584     param_int_validate,       /* value_validate */
1585     param_int_values_cmp,     /* values_cmp */
1586   };
1587
1588   custom_type = g_param_type_register_static ("GParamInt2", &pspec_info);
1589 }
1590
1591 static GParamSpec *
1592 g_param_spec_custom (const char   *name,
1593                      int           minimum,
1594                      int           maximum,
1595                      int           default_value,
1596                       GParamFlags  flags)
1597 {
1598   GParamSpecInt *ispec;
1599
1600   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1601
1602   ispec = g_param_spec_internal (custom_type, name, NULL, NULL, flags);
1603   if (ispec == NULL)
1604     return NULL;
1605
1606   ispec->minimum = minimum;
1607   ispec->maximum = maximum;
1608   ispec->default_value = default_value;
1609
1610   return G_PARAM_SPEC (ispec);
1611 }
1612
1613 static void
1614 test_param_spec_custom (void)
1615 {
1616   GParamSpec *pspec;
1617   GValue value = G_VALUE_INIT;
1618
1619   register_custom_pspec ();
1620
1621   pspec = g_param_spec_custom ("myint", 10, 30, 20, G_PARAM_READWRITE);
1622
1623   g_value_init (&value, G_TYPE_INT);
1624
1625   g_value_set_int (&value, 40);
1626
1627   g_assert_false (g_param_value_is_valid (pspec, &value));
1628   g_assert_cmpint (g_value_get_int (&value), ==, 40);
1629
1630   g_param_spec_unref (pspec);
1631 }
1632
1633 static void
1634 test_param_spec_pool (void)
1635 {
1636   GParamSpecPool *pool = g_param_spec_pool_new (FALSE);
1637   GParamSpec *pspec = g_param_spec_ref_sink (g_param_spec_int ("int", NULL, NULL, -1, 100, -1, G_PARAM_READWRITE));
1638   GParamSpec *check = NULL;
1639
1640   g_param_spec_pool_insert (pool, pspec, G_TYPE_OBJECT);
1641   check = g_param_spec_pool_lookup (pool, "int", G_TYPE_OBJECT, FALSE);
1642   g_assert_true (check->owner_type == G_TYPE_OBJECT);
1643
1644   g_param_spec_pool_remove (pool, pspec);
1645   g_assert_null (g_param_spec_pool_lookup (pool, "int", G_TYPE_OBJECT, FALSE));
1646
1647   g_param_spec_pool_free (pool);
1648   g_param_spec_unref (pspec);
1649 }
1650
1651 int
1652 main (int argc, char *argv[])
1653 {
1654   TestParamImplementData data, *test_data;
1655   gchar *test_path;
1656
1657   g_test_init (&argc, &argv, NULL);
1658
1659   g_test_add_func ("/param/value", test_param_value);
1660   g_test_add_func ("/param/strings", test_param_strings);
1661   g_test_add_data_func ("/param/invalid-name/colon", "my_int:hello", test_param_invalid_name);
1662   g_test_add_data_func ("/param/invalid-name/first-char", "7zip", test_param_invalid_name);
1663   g_test_add_data_func ("/param/invalid-name/empty", "", test_param_invalid_name);
1664   g_test_add_func ("/param/qdata", test_param_qdata);
1665   g_test_add_func ("/param/validate", test_param_validate);
1666   g_test_add_func ("/param/convert", test_param_convert);
1667
1668   g_test_add_func ("/param/implement", test_param_implement);
1669
1670   for (data.change_this_flag = 0; data.change_this_flag < 16; data.change_this_flag++)
1671     for (data.change_this_type = 0; data.change_this_type < 3; data.change_this_type++)
1672       for (data.use_this_flag = 0; data.use_this_flag < 16; data.use_this_flag++)
1673         for (data.use_this_type = 0; data.use_this_type < 4; data.use_this_type++)
1674           {
1675             test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
1676                                          data.change_this_flag, data.change_this_type,
1677                                          data.use_this_flag, data.use_this_type);
1678             test_data = g_memdup2 (&data, sizeof (TestParamImplementData));
1679             g_test_add_data_func_full (test_path, g_steal_pointer (&test_data), test_param_implement_child, g_free);
1680             g_free (test_path);
1681           }
1682
1683   g_test_add_func ("/value/transform", test_value_transform);
1684   g_test_add_func ("/param/default", test_param_default);
1685   g_test_add_func ("/param/is-valid-name", test_param_is_valid_name);
1686   g_test_add_func ("/paramspec/char", test_param_spec_char);
1687   g_test_add_func ("/paramspec/uchar", test_param_spec_uchar);
1688   g_test_add_func ("/paramspec/int", test_param_spec_int);
1689   g_test_add_func ("/paramspec/uint", test_param_spec_uint);
1690   g_test_add_func ("/paramspec/long", test_param_spec_long);
1691   g_test_add_func ("/paramspec/ulong", test_param_spec_ulong);
1692   g_test_add_func ("/paramspec/int64", test_param_spec_int64);
1693   g_test_add_func ("/paramspec/uint64", test_param_spec_uint64);
1694   g_test_add_func ("/paramspec/float", test_param_spec_float);
1695   g_test_add_func ("/paramspec/double", test_param_spec_double);
1696   g_test_add_func ("/paramspec/unichar", test_param_spec_unichar);
1697   g_test_add_func ("/paramspec/param", test_param_spec_param);
1698   g_test_add_func ("/paramspec/null-param", test_param_spec_null_param);
1699   g_test_add_func ("/paramspec/string", test_param_spec_string);
1700   g_test_add_func ("/paramspec/override", test_param_spec_override);
1701   g_test_add_func ("/paramspec/gtype", test_param_spec_gtype);
1702   g_test_add_func ("/paramspec/variant", test_param_spec_variant);
1703   g_test_add_func ("/paramspec/variant/cmp", test_param_spec_variant_cmp);
1704   g_test_add_func ("/paramspec/custom", test_param_spec_custom);
1705   g_test_add_func ("/paramspec/pool", test_param_spec_pool);
1706
1707   return g_test_run ();
1708 }