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