(root)/
glib-2.79.0/
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              g_param_spec_unref (pspec);
    1161              continue;
    1162            }
    1163  
    1164          /* install the property */
    1165          g_snprintf (prop_name, sizeof prop_name, "%s-%s", names[i], perms[j]);
    1166          pspec = g_param_spec_object (prop_name, prop_name, prop_name, types[i], j);
    1167          g_object_interface_install_property (iface, pspec);
    1168        }
    1169  }
    1170  
    1171  /* We now have 21 properties.  Each property may be correctly
    1172   * implemented with the following types:
    1173   *
    1174   *   Properties         Valid Types       Reason
    1175   *
    1176   *   a-r                a, b              Read only can provide subclasses
    1177   *   a-w, wc, wC        a, GObject        Write only can accept superclasses
    1178   *   a-rw, rwc, rwC     a                 Read-write must be exactly equal
    1179   *
    1180   *   b-r                b                 (as above)
    1181   *   b-w, wc, wC        b, a, GObject
    1182   *   b-rw, rwc, rwC     b
    1183   *
    1184   *   c-r                c                 (as above)
    1185   *   c-wo, wc, wC       c, GObject
    1186   *   c-rw, rwc, rwC     c
    1187   *
    1188   * We can express this in a 48-by-4 table where each row represents an
    1189   * installed property and each column represents a type.  The value in
    1190   * the table represents if it is valid to subclass the row's property
    1191   * with the type of the column:
    1192   *
    1193   *   - 0:   invalid because the interface property doesn't exist (invalid flags)
    1194   *   - 'v': valid
    1195   *   - '=': invalid because of the type not being exactly equal
    1196   *   - '<': invalid because of the type not being a subclass
    1197   *   - '>': invalid because of the type not being a superclass
    1198   *
    1199   * We organise the table by interface property type ('a', 'b', 'c') then
    1200   * by interface property flags.
    1201   */
    1202  
    1203  static gint valid_impl_types[48][4] = {
    1204                      /* a    b    c    GObject */
    1205      /* 'a-' */       { 0, },
    1206      /* 'a-r' */      { 'v', 'v', '<', '<' },
    1207      /* 'a-w' */      { 'v', '>', '>', 'v' },
    1208      /* 'a-rw' */     { 'v', '=', '=', '=' },
    1209      /* 'a-c */       { 0, },
    1210      /* 'a-rc' */     { 0, },
    1211      /* 'a-wc' */     { 'v', '>', '>', 'v' },
    1212      /* 'a-rwc' */    { 'v', '=', '=', '=' },
    1213      /* 'a-C */       { 0, },
    1214      /* 'a-rC' */     { 0, },
    1215      /* 'a-wC' */     { 'v', '>', '>', 'v' },
    1216      /* 'a-rwC' */    { 'v', '=', '=', '=' },
    1217      /* 'a-cC */      { 0, },
    1218      /* 'a-rcC' */    { 0, },
    1219      /* 'a-wcC' */    { 0, },
    1220      /* 'a-rwcC' */   { 0, },
    1221  
    1222      /* 'b-' */       { 0, },
    1223      /* 'b-r' */      { '<', 'v', '<', '<' },
    1224      /* 'b-w' */      { 'v', 'v', '>', 'v' },
    1225      /* 'b-rw' */     { '=', 'v', '=', '=' },
    1226      /* 'b-c */       { 0, },
    1227      /* 'b-rc' */     { 0, },
    1228      /* 'b-wc' */     { 'v', 'v', '>', 'v' },
    1229      /* 'b-rwc' */    { '=', 'v', '=', '=' },
    1230      /* 'b-C */       { 0, },
    1231      /* 'b-rC' */     { 0, },
    1232      /* 'b-wC' */     { 'v', 'v', '>', 'v' },
    1233      /* 'b-rwC' */    { '=', 'v', '=', '=' },
    1234      /* 'b-cC */      { 0, },
    1235      /* 'b-rcC' */    { 0, },
    1236      /* 'b-wcC' */    { 0, },
    1237      /* 'b-rwcC' */   { 0, },
    1238  
    1239      /* 'c-' */       { 0, },
    1240      /* 'c-r' */      { '<', '<', 'v', '<' },
    1241      /* 'c-w' */      { '>', '>', 'v', 'v' },
    1242      /* 'c-rw' */     { '=', '=', 'v', '=' },
    1243      /* 'c-c */       { 0, },
    1244      /* 'c-rc' */     { 0, },
    1245      /* 'c-wc' */     { '>', '>', 'v', 'v' },
    1246      /* 'c-rwc' */    { '=', '=', 'v', '=' },
    1247      /* 'c-C */       { 0, },
    1248      /* 'c-rC' */     { 0, },
    1249      /* 'c-wC' */     { '>', '>', 'v', 'v' },
    1250      /* 'c-rwC' */    { '=', '=', 'v', '=' },
    1251      /* 'c-cC */      { 0, },
    1252      /* 'c-rcC' */    { 0, },
    1253      /* 'c-wcC' */    { 0, },
    1254      /* 'c-rwcC' */   { 0, }
    1255  };
    1256  
    1257  /* We also try to change the flags.  We must ensure that all
    1258   * implementations provide all functionality promised by the interface.
    1259   * We must therefore never remove readability or writability (but we can
    1260   * add them).  Construct-only is a restrictions that applies to
    1261   * writability, so we can never add it unless writability was never
    1262   * present in the first place, in which case "writable at construct
    1263   * only" is still better than "not writable".
    1264   *
    1265   * The 'construct' flag is of interest only to the implementation.  It
    1266   * may be changed at any time.
    1267   *
    1268   *   Properties         Valid Access      Reason
    1269   *
    1270   *   *-r                r, rw, rwc, rwC   Must keep readable, but can restrict newly-added writable
    1271   *   *-w                w, rw, rwc        Must keep writable unrestricted
    1272   *   *-rw               rw, rwc           Must not add any restrictions
    1273   *   *-rwc              rw, rwc           Must not add any restrictions
    1274   *   *-rwC              rw, rwc, rwC      Can remove 'construct-only' restriction
    1275   *   *-wc               rwc, rw, w, wc    Can add readability
    1276   *   *-wC               rwC, rw, w, wC    Can add readability or remove 'construct only' restriction
    1277   *                        rwc, wc
    1278   *
    1279   * We can represent this with a 16-by-16 table.  The rows represent the
    1280   * flags of the property on the interface.  The columns is the flags to
    1281   * try to use when overriding the property.  The cell contents are:
    1282   *
    1283   *   - 0:   invalid because the interface property doesn't exist (invalid flags)
    1284   *   - 'v': valid
    1285   *   - 'i': invalid because the implementation flags are invalid
    1286   *   - 'f': invalid because of the removal of functionality
    1287   *   - 'r': invalid because of the addition of restrictions (ie: construct-only)
    1288   *
    1289   * We also ensure that removal of functionality is reported before
    1290   * addition of restrictions, since this is a more basic problem.
    1291   */
    1292  static gint valid_impl_flags[16][16] = {
    1293                   /* ''   r    w    rw   c    rc   wc   rwc  C    rC   wC   rwC  cC   rcC  wcC  rwcC */
    1294      /* '*-' */    { 0, },
    1295      /* '*-r' */   { 'i', 'v', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'i', 'i' },
    1296      /* '*-w' */   { 'i', 'f', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'r', 'r', 'i', 'i', 'i', 'i' },
    1297      /* '*-rw' */  { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'r', 'i', 'i', 'i', 'i' },
    1298      /* '*-c */    { 0, },
    1299      /* '*-rc' */  { 0, },
    1300      /* '*-wc' */  { 'i', 'f', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'r', 'r', 'i', 'i', 'i', 'i' },
    1301      /* '*-rwc' */ { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'r', 'i', 'i', 'i', 'i' },
    1302      /* '*-C */    { 0, },
    1303      /* '*-rC' */  { 0, },
    1304      /* '*-wC' */  { 'i', 'f', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'i', 'i' },
    1305      /* '*-rwC' */ { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'i', 'i' },
    1306  };
    1307  
    1308  static guint change_this_flag;
    1309  static guint change_this_type;
    1310  static guint use_this_flag;
    1311  static guint use_this_type;
    1312  
    1313  typedef GObjectClass TestImplementationClass;
    1314  typedef GObject TestImplementation;
    1315  
    1316  static void test_implementation_init (TestImplementation *impl) { }
    1317  static void test_implementation_iface_init (TestInterfaceInterface *iface) { }
    1318  
    1319  static GType test_implementation_get_type (void);
    1320  G_DEFINE_TYPE_WITH_CODE (TestImplementation, test_implementation, G_TYPE_OBJECT,
    1321                           G_IMPLEMENT_INTERFACE (test_interface_get_type (), test_implementation_iface_init))
    1322  
    1323  static void test_implementation_class_init (TestImplementationClass *class)
    1324  {
    1325    const gchar *names[] = { "a", "b", "c" };
    1326    const gchar *perms[] = { NULL, "r",  "w",  "rw",
    1327                             NULL, NULL, "wc", "rwc",
    1328                             NULL, NULL, "wC", "rwC",
    1329                             NULL, NULL, NULL, NULL };
    1330    const GType types[] = { test_object_a_get_type (), test_object_b_get_type (),
    1331                            test_object_c_get_type (), G_TYPE_OBJECT };
    1332    gchar prop_name[10];
    1333    GParamSpec *pspec;
    1334    guint i, j;
    1335  
    1336    class->get_property = GINT_TO_POINTER (1);
    1337    class->set_property = GINT_TO_POINTER (1);
    1338  
    1339    /* Install all of the non-modified properties or else GObject will
    1340     * complain about non-implemented properties.
    1341     */
    1342    for (i = 0; i < 3; i++)
    1343      for (j = 0; j < G_N_ELEMENTS (perms); j++)
    1344        {
    1345          if (i == change_this_type && j == change_this_flag)
    1346            continue;
    1347  
    1348          if (perms[j] != NULL)
    1349            {
    1350              /* override the property without making changes */
    1351              g_snprintf (prop_name, sizeof prop_name, "%s-%s", names[i], perms[j]);
    1352              g_object_class_override_property (class, 1, prop_name);
    1353            }
    1354        }
    1355  
    1356    /* Now try installing our modified property */
    1357    if (perms[change_this_flag] == NULL)
    1358      g_error ("Interface property does not exist");
    1359  
    1360    g_snprintf (prop_name, sizeof prop_name, "%s-%s", names[change_this_type], perms[change_this_flag]);
    1361    pspec = g_param_spec_object (prop_name, prop_name, prop_name, types[use_this_type], use_this_flag);
    1362    g_object_class_install_property (class, 1, pspec);
    1363  }
    1364  
    1365  typedef struct {
    1366    gint change_this_flag;
    1367    gint change_this_type;
    1368    gint use_this_flag;
    1369    gint use_this_type;
    1370  } TestParamImplementData;
    1371  
    1372  static void
    1373  test_param_implement_child (gconstpointer user_data)
    1374  {
    1375    TestParamImplementData *data = (gpointer) user_data;
    1376  
    1377    /* GObject oddity: GObjectClass must be initialised before we can
    1378     * initialise a GTypeInterface.
    1379     */
    1380    g_type_class_ref (G_TYPE_OBJECT);
    1381  
    1382    /* Bring up the interface first. */
    1383    g_type_default_interface_ref (test_interface_get_type ());
    1384  
    1385    /* Copy the flags into the global vars so
    1386     * test_implementation_class_init() will see them.
    1387     */
    1388    change_this_flag = data->change_this_flag;
    1389    change_this_type = data->change_this_type;
    1390    use_this_flag = data->use_this_flag;
    1391    use_this_type = data->use_this_type;
    1392  
    1393    g_type_class_ref (test_implementation_get_type ());
    1394  }
    1395  
    1396  static void
    1397  test_param_implement (void)
    1398  {
    1399    gchar *test_path;
    1400  
    1401    for (change_this_flag = 0; change_this_flag < 16; change_this_flag++)
    1402      for (change_this_type = 0; change_this_type < 3; change_this_type++)
    1403        for (use_this_flag = 0; use_this_flag < 16; use_this_flag++)
    1404          for (use_this_type = 0; use_this_type < 4; use_this_type++)
    1405            {
    1406              if (!g_test_undefined ())
    1407                {
    1408                  /* only test the valid (defined) cases, e.g. under valgrind */
    1409                  if (valid_impl_flags[change_this_flag][use_this_flag] != 'v')
    1410                    continue;
    1411  
    1412                  if (valid_impl_types[change_this_type * 16 + change_this_flag][use_this_type] != 'v')
    1413                    continue;
    1414                }
    1415  
    1416              test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
    1417                                           change_this_flag, change_this_type,
    1418                                           use_this_flag, use_this_type);
    1419              g_test_trap_subprocess (test_path, G_TIME_SPAN_SECOND,
    1420                                      G_TEST_SUBPROCESS_DEFAULT);
    1421              g_free (test_path);
    1422  
    1423              /* We want to ensure that any flags mismatch problems are reported first. */
    1424              switch (valid_impl_flags[change_this_flag][use_this_flag])
    1425                {
    1426                case 0:
    1427                  /* make sure the other table agrees */
    1428                  g_assert_cmpint (valid_impl_types[change_this_type * 16 + change_this_flag][use_this_type], ==, 0);
    1429                  g_test_trap_assert_failed ();
    1430                  g_test_trap_assert_stderr ("*Interface property does not exist*");
    1431                  continue;
    1432  
    1433                case 'i':
    1434                  g_test_trap_assert_failed ();
    1435                  g_test_trap_assert_stderr ("*g_object_class_install_property*");
    1436                  continue;
    1437  
    1438                case 'f':
    1439                  g_test_trap_assert_failed ();
    1440                  g_test_trap_assert_stderr ("*remove functionality*");
    1441                  continue;
    1442  
    1443                case 'r':
    1444                  g_test_trap_assert_failed ();
    1445                  g_test_trap_assert_stderr ("*introduce additional restrictions*");
    1446                  continue;
    1447  
    1448                case 'v':
    1449                  break;
    1450                }
    1451  
    1452              /* Next, we check if there should have been a type error. */
    1453              switch (valid_impl_types[change_this_type * 16 + change_this_flag][use_this_type])
    1454                {
    1455                case 0:
    1456                  /* this should have been caught above */
    1457                  g_assert_not_reached ();
    1458  
    1459                case '=':
    1460                  g_test_trap_assert_failed ();
    1461                  g_test_trap_assert_stderr ("*exactly equal*");
    1462                  continue;
    1463  
    1464                case '<':
    1465                  g_test_trap_assert_failed ();
    1466                  g_test_trap_assert_stderr ("*equal to or more restrictive*");
    1467                  continue;
    1468  
    1469                case '>':
    1470                  g_test_trap_assert_failed ();
    1471                  g_test_trap_assert_stderr ("*equal to or less restrictive*");
    1472                  continue;
    1473  
    1474                case 'v':
    1475                  break;
    1476                }
    1477  
    1478              g_test_trap_assert_passed ();
    1479            }
    1480  }
    1481  
    1482  static void
    1483  test_param_default (void)
    1484  {
    1485    GParamSpec *param;
    1486    const GValue *def;
    1487  
    1488    param = g_param_spec_int ("my-int", "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
    1489    def = g_param_spec_get_default_value (param);
    1490  
    1491    g_assert_true (G_VALUE_HOLDS (def, G_TYPE_INT));
    1492    g_assert_cmpint (g_value_get_int (def), ==, 10);
    1493  
    1494    g_param_spec_unref (param);
    1495  }
    1496  
    1497  static void
    1498  test_param_is_valid_name (void)
    1499  {
    1500    const gchar *valid_names[] =
    1501      {
    1502        "property",
    1503        "i",
    1504        "multiple-segments",
    1505        "segment0-SEGMENT1",
    1506        "using_underscores",
    1507      };
    1508    const gchar *invalid_names[] =
    1509      {
    1510        "",
    1511        "7zip",
    1512        "my_int:hello",
    1513      };
    1514    gsize i;
    1515  
    1516    for (i = 0; i < G_N_ELEMENTS (valid_names); i++)
    1517      g_assert_true (g_param_spec_is_valid_name (valid_names[i]));
    1518  
    1519    for (i = 0; i < G_N_ELEMENTS (invalid_names); i++)
    1520      g_assert_false (g_param_spec_is_valid_name (invalid_names[i]));
    1521  }
    1522  
    1523  static void
    1524  param_int_init (GParamSpec *pspec)
    1525  {
    1526    GParamSpecInt *ispec = (GParamSpecInt *)pspec;
    1527  
    1528    ispec->minimum = 0x7fffffff;
    1529    ispec->maximum = 0x80000000;
    1530    ispec->default_value = 0;
    1531  }
    1532  
    1533  static void
    1534  param_int_set_default (GParamSpec *pspec,
    1535                         GValue     *value)
    1536  {
    1537    value->data[0].v_int = ((GParamSpecInt *)pspec)->default_value;
    1538  }
    1539  
    1540  static gboolean
    1541  param_int_validate (GParamSpec *pspec,
    1542                      GValue     *value)
    1543  {
    1544    GParamSpecInt *ispec = (GParamSpecInt *)pspec;
    1545    int oval = value->data[0].v_int;
    1546  
    1547    value->data[0].v_int = CLAMP (value->data[0].v_int, ispec->minimum, ispec->maximum);
    1548  
    1549    return value->data[0].v_int != oval;
    1550  }
    1551  
    1552  static int
    1553  param_int_values_cmp (GParamSpec   *pspec,
    1554                        const GValue *value1,
    1555                        const GValue *value2)
    1556  {
    1557    if (value1->data[0].v_int < value2->data[0].v_int)
    1558      return -1;
    1559    else
    1560      return value1->data[0].v_int > value2->data[0].v_int;
    1561  }
    1562  
    1563  static GType custom_type;
    1564  
    1565  /* Register a pspec that has a validate vfunc, but not
    1566   * value_is_valid, to test the fallback in g_param_value_is_valid
    1567   */
    1568  static void
    1569  register_custom_pspec (void)
    1570  {
    1571    const GParamSpecTypeInfo pspec_info = {
    1572      sizeof (GParamSpecInt),   /* instance_size */
    1573      16,                       /* n_preallocs */
    1574      param_int_init,           /* instance_init */
    1575      G_TYPE_INT,               /* value_type */
    1576      NULL,                     /* finalize */
    1577      param_int_set_default,    /* value_set_default */
    1578      param_int_validate,       /* value_validate */
    1579      param_int_values_cmp,     /* values_cmp */
    1580    };
    1581  
    1582    custom_type = g_param_type_register_static ("GParamInt2", &pspec_info);
    1583  }
    1584  
    1585  static GParamSpec *
    1586  g_param_spec_custom (const char   *name,
    1587                       int           minimum,
    1588                       int           maximum,
    1589                       int           default_value,
    1590                        GParamFlags  flags)
    1591  {
    1592    GParamSpecInt *ispec;
    1593  
    1594    g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
    1595  
    1596    ispec = g_param_spec_internal (custom_type, name, NULL, NULL, flags);
    1597    if (ispec == NULL)
    1598      return NULL;
    1599  
    1600    ispec->minimum = minimum;
    1601    ispec->maximum = maximum;
    1602    ispec->default_value = default_value;
    1603  
    1604    return G_PARAM_SPEC (ispec);
    1605  }
    1606  
    1607  static void
    1608  test_param_spec_custom (void)
    1609  {
    1610    GParamSpec *pspec;
    1611    GValue value = G_VALUE_INIT;
    1612  
    1613    register_custom_pspec ();
    1614  
    1615    pspec = g_param_spec_custom ("myint", 10, 30, 20, G_PARAM_READWRITE);
    1616  
    1617    g_value_init (&value, G_TYPE_INT);
    1618  
    1619    g_value_set_int (&value, 40);
    1620  
    1621    g_assert_false (g_param_value_is_valid (pspec, &value));
    1622    g_assert_cmpint (g_value_get_int (&value), ==, 40);
    1623  
    1624    g_param_spec_unref (pspec);
    1625  }
    1626  
    1627  static void
    1628  test_param_spec_pool (void)
    1629  {
    1630    GParamSpecPool *pool = g_param_spec_pool_new (FALSE);
    1631    GParamSpec *pspec = g_param_spec_int ("int", NULL, NULL, -1, 100, -1, G_PARAM_READWRITE);
    1632    GParamSpec *check = NULL;
    1633  
    1634    g_param_spec_pool_insert (pool, g_param_spec_ref_sink (pspec), G_TYPE_OBJECT);
    1635    check = g_param_spec_pool_lookup (pool, "int", G_TYPE_OBJECT, FALSE);
    1636    g_assert_true (check->owner_type == G_TYPE_OBJECT);
    1637  
    1638    g_param_spec_pool_remove (pool, pspec);
    1639    g_assert_null (g_param_spec_pool_lookup (pool, "int", G_TYPE_OBJECT, FALSE));
    1640  
    1641    g_param_spec_pool_free (pool);
    1642  }
    1643  
    1644  int
    1645  main (int argc, char *argv[])
    1646  {
    1647    TestParamImplementData data, *test_data;
    1648    gchar *test_path;
    1649  
    1650    g_test_init (&argc, &argv, NULL);
    1651  
    1652    g_test_add_func ("/param/value", test_param_value);
    1653    g_test_add_func ("/param/strings", test_param_strings);
    1654    g_test_add_data_func ("/param/invalid-name/colon", "my_int:hello", test_param_invalid_name);
    1655    g_test_add_data_func ("/param/invalid-name/first-char", "7zip", test_param_invalid_name);
    1656    g_test_add_data_func ("/param/invalid-name/empty", "", test_param_invalid_name);
    1657    g_test_add_func ("/param/qdata", test_param_qdata);
    1658    g_test_add_func ("/param/validate", test_param_validate);
    1659    g_test_add_func ("/param/convert", test_param_convert);
    1660  
    1661    if (g_test_slow ())
    1662      g_test_add_func ("/param/implement", test_param_implement);
    1663  
    1664    for (data.change_this_flag = 0; data.change_this_flag < 16; data.change_this_flag++)
    1665      for (data.change_this_type = 0; data.change_this_type < 3; data.change_this_type++)
    1666        for (data.use_this_flag = 0; data.use_this_flag < 16; data.use_this_flag++)
    1667          for (data.use_this_type = 0; data.use_this_type < 4; data.use_this_type++)
    1668            {
    1669              test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
    1670                                           data.change_this_flag, data.change_this_type,
    1671                                           data.use_this_flag, data.use_this_type);
    1672              test_data = g_memdup2 (&data, sizeof (TestParamImplementData));
    1673              g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free);
    1674              g_free (test_data);
    1675              g_free (test_path);
    1676            }
    1677  
    1678    g_test_add_func ("/value/transform", test_value_transform);
    1679    g_test_add_func ("/param/default", test_param_default);
    1680    g_test_add_func ("/param/is-valid-name", test_param_is_valid_name);
    1681    g_test_add_func ("/paramspec/char", test_param_spec_char);
    1682    g_test_add_func ("/paramspec/uchar", test_param_spec_uchar);
    1683    g_test_add_func ("/paramspec/int", test_param_spec_int);
    1684    g_test_add_func ("/paramspec/uint", test_param_spec_uint);
    1685    g_test_add_func ("/paramspec/long", test_param_spec_long);
    1686    g_test_add_func ("/paramspec/ulong", test_param_spec_ulong);
    1687    g_test_add_func ("/paramspec/int64", test_param_spec_int64);
    1688    g_test_add_func ("/paramspec/uint64", test_param_spec_uint64);
    1689    g_test_add_func ("/paramspec/float", test_param_spec_float);
    1690    g_test_add_func ("/paramspec/double", test_param_spec_double);
    1691    g_test_add_func ("/paramspec/unichar", test_param_spec_unichar);
    1692    g_test_add_func ("/paramspec/param", test_param_spec_param);
    1693    g_test_add_func ("/paramspec/null-param", test_param_spec_null_param);
    1694    g_test_add_func ("/paramspec/string", test_param_spec_string);
    1695    g_test_add_func ("/paramspec/override", test_param_spec_override);
    1696    g_test_add_func ("/paramspec/gtype", test_param_spec_gtype);
    1697    g_test_add_func ("/paramspec/variant", test_param_spec_variant);
    1698    g_test_add_func ("/paramspec/variant/cmp", test_param_spec_variant_cmp);
    1699    g_test_add_func ("/paramspec/custom", test_param_spec_custom);
    1700    g_test_add_func ("/paramspec/pool", test_param_spec_pool);
    1701  
    1702    return g_test_run ();
    1703  }