LCOV - code coverage report
Current view: top level - glib/glib/tests - gvariant.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 2705 2731 99.0 %
Date: 2024-03-26 05:16:46 Functions: 114 118 96.6 %
Branches: 727 827 87.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright © 2010 Codethink Limited
       3                 :            :  * Copyright © 2020 William Manley
       4                 :            :  * Copyright © 2022 Endless OS Foundation, LLC
       5                 :            :  *
       6                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       7                 :            :  *
       8                 :            :  * This library is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU Lesser General Public
      10                 :            :  * License as published by the Free Software Foundation; either
      11                 :            :  * version 2.1 of the License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * See the included COPYING file for more information.
      14                 :            :  *
      15                 :            :  * Author: Ryan Lortie <desrt@desrt.ca>
      16                 :            :  */
      17                 :            : 
      18                 :            : #include "config.h"
      19                 :            : 
      20                 :            : #include <glib/gvariant-internal.h>
      21                 :            : #include <string.h>
      22                 :            : #include <stdlib.h>
      23                 :            : #include <glib.h>
      24                 :            : 
      25                 :            : #define BASIC "bynqiuxthdsog?"
      26                 :            : #define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
      27                 :            : 
      28                 :            : #define INVALIDS "cefjklpwz&@^$"
      29                 :            : #define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
      30                 :            : 
      31                 :            : /* see comment in gvariant-serialiser.c about this madness.
      32                 :            :  *
      33                 :            :  * we use this to get testing of non-strictly-aligned GVariant instances
      34                 :            :  * on machines that can tolerate it.  it is necessary to support this
      35                 :            :  * because some systems have malloc() that returns non-8-aligned
      36                 :            :  * pointers.  it is necessary to have special support in the tests
      37                 :            :  * because on most machines malloc() is 8-aligned.
      38                 :            :  */
      39                 :            : #define ALIGN_BITS (sizeof (struct { char a; union {                       \
      40                 :            :                       guint64 x; void *y; gdouble z; } b; }) - 9)
      41                 :            : 
      42                 :            : static gboolean
      43                 :   19941117 : randomly (gdouble prob)
      44                 :            : {
      45                 :   19941117 :   return g_test_rand_double_range (0, 1) < prob;
      46                 :            : }
      47                 :            : 
      48                 :            : /* corecursion */
      49                 :            : static GVariantType *
      50                 :            : append_tuple_type_string (GString *, GString *, gboolean, gint);
      51                 :            : 
      52                 :            : /* append a random GVariantType to a GString
      53                 :            :  * append a description of the type to another GString
      54                 :            :  * return what the type is
      55                 :            :  */
      56                 :            : static GVariantType *
      57                 :     301700 : append_type_string (GString  *string,
      58                 :            :                     GString  *description,
      59                 :            :                     gboolean  definite,
      60                 :            :                     gint      depth)
      61                 :            : {
      62   [ +  +  +  + ]:     301700 :   if (!depth-- || randomly (0.3))
      63                 :            :     {
      64                 :     193894 :       gchar b = BASIC[g_test_rand_int_range (0, N_BASIC - definite)];
      65         [ +  - ]:     193894 :       g_string_append_c (string, b);
      66         [ +  - ]:     193894 :       g_string_append_c (description, b);
      67                 :            : 
      68   [ +  +  +  +  :     193894 :       switch (b)
          +  +  +  +  +  
          +  +  +  +  +  
                      - ]
      69                 :            :         {
      70                 :      14649 :         case 'b':
      71                 :      14649 :           return g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
      72                 :      14418 :         case 'y':
      73                 :      14418 :           return g_variant_type_copy (G_VARIANT_TYPE_BYTE);
      74                 :      14465 :         case 'n':
      75                 :      14465 :           return g_variant_type_copy (G_VARIANT_TYPE_INT16);
      76                 :      14729 :         case 'q':
      77                 :      14729 :           return g_variant_type_copy (G_VARIANT_TYPE_UINT16);
      78                 :      14597 :         case 'i':
      79                 :      14597 :           return g_variant_type_copy (G_VARIANT_TYPE_INT32);
      80                 :      14591 :         case 'u':
      81                 :      14591 :           return g_variant_type_copy (G_VARIANT_TYPE_UINT32);
      82                 :      14561 :         case 'x':
      83                 :      14561 :           return g_variant_type_copy (G_VARIANT_TYPE_INT64);
      84                 :      14473 :         case 't':
      85                 :      14473 :           return g_variant_type_copy (G_VARIANT_TYPE_UINT64);
      86                 :      14453 :         case 'h':
      87                 :      14453 :           return g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
      88                 :      14640 :         case 'd':
      89                 :      14640 :           return g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
      90                 :      14518 :         case 's':
      91                 :      14518 :           return g_variant_type_copy (G_VARIANT_TYPE_STRING);
      92                 :      14659 :         case 'o':
      93                 :      14659 :           return g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
      94                 :      14647 :         case 'g':
      95                 :      14647 :           return g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
      96                 :       4494 :         case '?':
      97                 :       4494 :           return g_variant_type_copy (G_VARIANT_TYPE_BASIC);
      98                 :          0 :         default:
      99                 :            :           g_assert_not_reached ();
     100                 :            :         }
     101                 :            :     }
     102                 :            :   else
     103                 :            :     {
     104                 :            :       GVariantType *result;
     105                 :            : 
     106   [ +  +  +  +  :     107806 :       switch (g_test_rand_int_range (0, definite ? 5 : 7))
          +  +  +  +  +  
                      - ]
     107                 :            :         {
     108         [ +  - ]:      18790 :         case 0:
     109                 :            :           {
     110                 :            :             GVariantType *element;
     111                 :            : 
     112                 :            :             g_string_append_c (string, 'a');
     113         [ +  - ]:      18790 :             g_string_append (description, "a of ");
     114                 :      18790 :             element = append_type_string (string, description,
     115                 :            :                                           definite, depth);
     116                 :      18790 :             result = g_variant_type_new_array (element);
     117                 :      18790 :             g_variant_type_free (element);
     118                 :            :           }
     119                 :            : 
     120                 :      18790 :           g_assert_true (g_variant_type_is_array (result));
     121                 :      18790 :           break;
     122                 :            : 
     123         [ +  - ]:      19026 :         case 1:
     124                 :            :           {
     125                 :            :             GVariantType *element;
     126                 :            : 
     127                 :            :             g_string_append_c (string, 'm');
     128         [ +  - ]:      19026 :             g_string_append (description, "m of ");
     129                 :      19026 :             element = append_type_string (string, description,
     130                 :            :                                           definite, depth);
     131                 :      19026 :             result = g_variant_type_new_maybe (element);
     132                 :      19026 :             g_variant_type_free (element);
     133                 :            :           }
     134                 :            : 
     135                 :      19026 :           g_assert_true (g_variant_type_is_maybe (result));
     136                 :      19026 :           break;
     137                 :            : 
     138                 :      18655 :         case 2:
     139                 :      18655 :           result = append_tuple_type_string (string, description,
     140                 :            :                                              definite, depth);
     141                 :            : 
     142                 :      18655 :           g_assert_true (g_variant_type_is_tuple (result));
     143                 :      18655 :           break;
     144                 :            : 
     145         [ +  - ]:      18579 :         case 3:
     146                 :            :           {
     147                 :            :             GVariantType *key, *value;
     148                 :            : 
     149                 :            :             g_string_append_c (string, '{');
     150         [ +  - ]:      18579 :             g_string_append (description, "e of [");
     151                 :      18579 :             key = append_type_string (string, description, definite, 0);
     152         [ +  - ]:      18579 :             g_string_append (description, ", ");
     153                 :      18579 :             value = append_type_string (string, description, definite, depth);
     154                 :            :             g_string_append_c (description, ']');
     155                 :            :             g_string_append_c (string, '}');
     156                 :      18579 :             result = g_variant_type_new_dict_entry (key, value);
     157                 :      18579 :             g_variant_type_free (key);
     158                 :      18579 :             g_variant_type_free (value);
     159                 :            :           }
     160                 :            : 
     161                 :      18579 :           g_assert_true (g_variant_type_is_dict_entry (result));
     162                 :      18579 :           break;
     163                 :            : 
     164         [ +  - ]:      18842 :         case 4:
     165                 :            :           g_string_append_c (string, 'v');
     166                 :            :           g_string_append_c (description, 'V');
     167                 :      18842 :           result = g_variant_type_copy (G_VARIANT_TYPE_VARIANT);
     168                 :      18842 :           g_assert_true (g_variant_type_equal (result, G_VARIANT_TYPE_VARIANT));
     169                 :      18842 :           break;
     170                 :            : 
     171         [ +  - ]:       7080 :         case 5:
     172                 :            :           g_string_append_c (string, '*');
     173                 :            :           g_string_append_c (description, 'S');
     174                 :       7080 :           result = g_variant_type_copy (G_VARIANT_TYPE_ANY);
     175                 :       7080 :           g_assert_true (g_variant_type_equal (result, G_VARIANT_TYPE_ANY));
     176                 :       7080 :           break;
     177                 :            : 
     178         [ +  - ]:       6834 :         case 6:
     179                 :            :           g_string_append_c (string, 'r');
     180                 :            :           g_string_append_c (description, 'R');
     181                 :       6834 :           result = g_variant_type_copy (G_VARIANT_TYPE_TUPLE);
     182                 :       6834 :           g_assert_true (g_variant_type_is_tuple (result));
     183                 :       6834 :           break;
     184                 :            : 
     185                 :          0 :         default:
     186                 :            :           g_assert_not_reached ();
     187                 :            :         }
     188                 :            : 
     189                 :     107806 :       return result;
     190                 :            :     }
     191                 :            : }
     192                 :            : 
     193                 :            : static GVariantType *
     194         [ +  - ]:      19694 : append_tuple_type_string (GString  *string,
     195                 :            :                           GString  *description,
     196                 :            :                           gboolean  definite,
     197                 :            :                           gint      depth)
     198                 :            : {
     199                 :            :   GVariantType *result, *other_result;
     200                 :            :   GVariantType **types;
     201                 :            :   gsize i, size;
     202                 :            : 
     203                 :            :   g_string_append_c (string, '(');
     204         [ +  - ]:      19694 :   g_string_append (description, "t of [");
     205                 :            : 
     206                 :      19694 :   size = g_test_rand_int_range (0, 20);
     207                 :      19694 :   types = g_new (GVariantType *, size + 1);
     208                 :            : 
     209         [ +  + ]:     208058 :   for (i = 0; i < size; i++)
     210                 :            :     {
     211                 :     188364 :       types[i] = append_type_string (string, description, definite, depth);
     212                 :            : 
     213         [ +  + ]:     188364 :       if (i < size - 1)
     214         [ +  - ]:     339202 :         g_string_append (description, ", ");
     215                 :            :     }
     216                 :            : 
     217         [ +  - ]:      19694 :   types[i] = NULL;
     218                 :            : 
     219                 :            :   g_string_append_c (description, ']');
     220                 :            :   g_string_append_c (string, ')');
     221                 :            : 
     222                 :      19694 :   result = g_variant_type_new_tuple ((gpointer) types, size);
     223                 :      19694 :   other_result = g_variant_type_new_tuple ((gpointer) types, -1);
     224                 :      19694 :   g_assert_true (g_variant_type_equal (result, other_result));
     225                 :      19694 :   g_variant_type_free (other_result);
     226         [ +  + ]:     208058 :   for (i = 0; i < size; i++)
     227                 :     188364 :     g_variant_type_free (types[i]);
     228                 :      19694 :   g_free (types);
     229                 :            : 
     230                 :      19694 :   return result;
     231                 :            : }
     232                 :            : 
     233                 :            : /* given a valid type string, make it invalid */
     234                 :            : static gchar *
     235                 :       2000 : invalid_mutation (const gchar *type_string)
     236                 :            : {
     237                 :            :   gboolean have_parens, have_braces;
     238                 :            : 
     239                 :            :   /* it's valid, so '(' implies ')' and same for '{' and '}' */
     240                 :       2000 :   have_parens = strchr (type_string, '(') != NULL;
     241                 :       2000 :   have_braces = strchr (type_string, '{') != NULL;
     242                 :            : 
     243   [ +  +  +  +  :       2000 :   if (have_parens && have_braces && randomly (0.3))
                   +  + ]
     244                 :            :     {
     245                 :            :       /* swap a paren and a brace */
     246                 :            :       gchar *pp, *bp;
     247                 :            :       gint np, nb;
     248                 :            :       gchar p, b;
     249                 :            :       gchar *new;
     250                 :            : 
     251                 :         63 :       new = g_strdup (type_string);
     252                 :            : 
     253         [ +  + ]:         63 :       if (randomly (0.5))
     254                 :         40 :         p = '(', b = '{';
     255                 :            :       else
     256                 :         23 :         p = ')', b = '}';
     257                 :            : 
     258                 :         63 :       np = nb = 0;
     259                 :         63 :       pp = bp = new - 1;
     260                 :            : 
     261                 :            :       /* count number of parens/braces */
     262         [ +  + ]:        679 :       while ((pp = strchr (pp + 1, p))) np++;
     263         [ +  + ]:        587 :       while ((bp = strchr (bp + 1, b))) nb++;
     264                 :            : 
     265                 :            :       /* randomly pick one of each */
     266                 :         63 :       np = g_test_rand_int_range (0, np) + 1;
     267                 :         63 :       nb = g_test_rand_int_range (0, nb) + 1;
     268                 :            : 
     269                 :            :       /* find it */
     270                 :         63 :       pp = bp = new - 1;
     271         [ +  + ]:        395 :       while (np--) pp = strchr (pp + 1, p);
     272         [ +  + ]:        371 :       while (nb--) bp = strchr (bp + 1, b);
     273                 :            : 
     274                 :            :       /* swap */
     275                 :         63 :       g_assert_true (*bp == b && *pp == p);
     276                 :         63 :       *bp = p;
     277                 :         63 :       *pp = b;
     278                 :            : 
     279                 :         63 :       return new;
     280                 :            :     }
     281                 :            : 
     282   [ +  +  +  +  :       1937 :   if ((have_parens || have_braces) && randomly (0.3))
                   +  + ]
     283                 :            :     {
     284                 :            :       /* drop a paren/brace */
     285                 :            :       gchar *new;
     286                 :            :       gchar *pp;
     287                 :            :       gint np;
     288                 :            :       gchar p;
     289                 :            : 
     290         [ +  + ]:        116 :       if (have_parens)
     291         [ +  + ]:         53 :         if (randomly (0.5)) p = '('; else p = ')';
     292                 :            :       else
     293         [ +  + ]:         63 :         if (randomly (0.5)) p = '{'; else p = '}';
     294                 :            : 
     295                 :        116 :       new = g_strdup (type_string);
     296                 :            : 
     297                 :        116 :       np = 0;
     298                 :        116 :       pp = new - 1;
     299         [ +  + ]:        687 :       while ((pp = strchr (pp + 1, p))) np++;
     300                 :        116 :       np = g_test_rand_int_range (0, np) + 1;
     301                 :        116 :       pp = new - 1;
     302         [ +  + ]:        410 :       while (np--) pp = strchr (pp + 1, p);
     303                 :        116 :       g_assert_cmpint (*pp, ==, p);
     304                 :            : 
     305         [ +  + ]:       4865 :       while (*pp)
     306                 :            :         {
     307                 :       4749 :           *pp = *(pp + 1);
     308                 :       4749 :           pp++;
     309                 :            :         }
     310                 :            : 
     311                 :        116 :       return new;
     312                 :            :     }
     313                 :            : 
     314                 :            :   /* else, perform a random mutation at a random point */
     315                 :            :   {
     316                 :            :     gint length, n;
     317                 :            :     gchar *new;
     318                 :            :     gchar p;
     319                 :            : 
     320         [ +  + ]:       1821 :     if (randomly (0.3))
     321                 :            :       {
     322                 :            :         /* insert a paren/brace */
     323         [ +  + ]:        502 :         if (randomly (0.5))
     324         [ +  + ]:        254 :           if (randomly (0.5)) p = '('; else p = ')';
     325                 :            :         else
     326         [ +  + ]:        248 :           if (randomly (0.5)) p = '{'; else p = '}';
     327                 :            :       }
     328         [ +  + ]:       1319 :     else if (randomly (0.5))
     329                 :            :       {
     330                 :            :         /* insert junk */
     331                 :        694 :         p = INVALIDS[g_test_rand_int_range (0, N_INVALIDS)];
     332                 :            :       }
     333                 :            :     else
     334                 :            :       {
     335                 :            :         /* truncate */
     336                 :        625 :         p = '\0';
     337                 :            :       }
     338                 :            : 
     339                 :            : 
     340                 :       1821 :     length = strlen (type_string);
     341                 :       1821 :     new = g_malloc (length + 2);
     342                 :       1821 :     n = g_test_rand_int_range (0, length);
     343                 :       1821 :     memcpy (new, type_string, n);
     344                 :       1821 :     new[n] = p;
     345                 :       1821 :     memcpy (new + n + 1, type_string + n, length - n);
     346                 :       1821 :     new[length + 1] = '\0';
     347                 :            : 
     348                 :       1821 :     return new;
     349                 :            :   }
     350                 :            : }
     351                 :            : 
     352                 :            : /* describe a type using the same language as is generated
     353                 :            :  * while generating the type with append_type_string
     354                 :            :  */
     355                 :            : static gchar *
     356                 :      43394 : describe_type (const GVariantType *type)
     357                 :            : {
     358                 :            :   gchar *result;
     359                 :            : 
     360         [ +  + ]:      43394 :   if (g_variant_type_is_container (type))
     361                 :            :     {
     362                 :      16476 :       g_assert_false (g_variant_type_is_basic (type));
     363                 :            : 
     364         [ +  + ]:      16476 :       if (g_variant_type_is_array (type))
     365                 :            :         {
     366                 :       2728 :           gchar *subtype = describe_type (g_variant_type_element (type));
     367                 :       2728 :           result = g_strdup_printf ("a of %s", subtype);
     368                 :       2728 :           g_free (subtype);
     369                 :            :         }
     370         [ +  + ]:      13748 :       else if (g_variant_type_is_maybe (type))
     371                 :            :         {
     372                 :       2877 :           gchar *subtype = describe_type (g_variant_type_element (type));
     373                 :       2877 :           result = g_strdup_printf ("m of %s", subtype);
     374                 :       2877 :           g_free (subtype);
     375                 :            :         }
     376         [ +  + ]:      10871 :       else if (g_variant_type_is_tuple (type))
     377                 :            :         {
     378         [ +  + ]:       5356 :           if (!g_variant_type_equal (type, G_VARIANT_TYPE_TUPLE))
     379                 :            :             {
     380                 :            :               const GVariantType *sub;
     381                 :            :               GString *string;
     382                 :            :               gsize i, length;
     383                 :            : 
     384                 :       2614 :               string = g_string_new ("t of [");
     385                 :            : 
     386                 :       2614 :               length = g_variant_type_n_items (type);
     387                 :       2614 :               sub = g_variant_type_first (type);
     388         [ +  + ]:      27519 :               for (i = 0; i < length; i++)
     389                 :            :                 {
     390                 :      24905 :                   gchar *subtype = describe_type (sub);
     391                 :            :                   g_string_append (string, subtype);
     392                 :      24905 :                   g_free (subtype);
     393                 :            : 
     394         [ +  + ]:      24905 :                   if ((sub = g_variant_type_next (sub)))
     395         [ +  - ]:      44858 :                     g_string_append (string, ", ");
     396                 :            :                 }
     397                 :       2614 :               g_assert_null (sub);
     398                 :            :               g_string_append_c (string, ']');
     399                 :            : 
     400                 :       2614 :               result = g_string_free (string, FALSE);
     401                 :            :             }
     402                 :            :           else
     403                 :       2742 :             result = g_strdup ("R");
     404                 :            :         }
     405         [ +  + ]:       5515 :       else if (g_variant_type_is_dict_entry (type))
     406                 :            :         {
     407                 :            :           gchar *key, *value, *key2, *value2;
     408                 :            : 
     409                 :       2721 :           key = describe_type (g_variant_type_key (type));
     410                 :       2721 :           value = describe_type (g_variant_type_value (type));
     411                 :       2721 :           key2 = describe_type (g_variant_type_first (type));
     412                 :       2721 :           value2 = describe_type (
     413                 :            :             g_variant_type_next (g_variant_type_first (type)));
     414                 :       2721 :           g_assert_null (g_variant_type_next (g_variant_type_next (
     415                 :            :             g_variant_type_first (type))));
     416                 :       2721 :           g_assert_cmpstr (key, ==, key2);
     417                 :       2721 :           g_assert_cmpstr (value, ==, value2);
     418                 :       2721 :           result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
     419                 :       2721 :           g_free (key2);
     420                 :       2721 :           g_free (value2);
     421                 :       2721 :           g_free (key);
     422                 :       2721 :           g_free (value);
     423                 :            :         }
     424         [ +  - ]:       2794 :       else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
     425                 :            :         {
     426                 :       2794 :           result = g_strdup ("V");
     427                 :            :         }
     428                 :            :       else
     429                 :            :         g_assert_not_reached ();
     430                 :            :     }
     431                 :            :   else
     432                 :            :     {
     433         [ +  + ]:      26918 :       if (g_variant_type_is_definite (type))
     434                 :            :         {
     435                 :      22326 :           g_assert_true (g_variant_type_is_basic (type));
     436                 :            : 
     437         [ +  + ]:      22326 :           if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
     438                 :       1632 :             result = g_strdup ("b");
     439         [ +  + ]:      20694 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
     440                 :       1633 :             result = g_strdup ("y");
     441         [ +  + ]:      19061 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
     442                 :       1730 :             result = g_strdup ("n");
     443         [ +  + ]:      17331 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
     444                 :       1761 :             result = g_strdup ("q");
     445         [ +  + ]:      15570 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
     446                 :       1713 :             result = g_strdup ("i");
     447         [ +  + ]:      13857 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
     448                 :       1818 :             result = g_strdup ("u");
     449         [ +  + ]:      12039 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
     450                 :       1749 :             result = g_strdup ("x");
     451         [ +  + ]:      10290 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
     452                 :       1671 :             result = g_strdup ("t");
     453         [ +  + ]:       8619 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
     454                 :       1714 :             result = g_strdup ("h");
     455         [ +  + ]:       6905 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
     456                 :       1647 :             result = g_strdup ("d");
     457         [ +  + ]:       5258 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
     458                 :       1730 :             result = g_strdup ("s");
     459         [ +  + ]:       3528 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
     460                 :       1676 :             result = g_strdup ("o");
     461         [ +  - ]:       1852 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
     462                 :       1852 :             result = g_strdup ("g");
     463                 :            :           else
     464                 :            :             g_assert_not_reached ();
     465                 :            :         }
     466                 :            :       else
     467                 :            :         {
     468         [ +  + ]:       4592 :           if (g_variant_type_equal (type, G_VARIANT_TYPE_ANY))
     469                 :            :             {
     470                 :       2867 :               result = g_strdup ("S");
     471                 :            :             }
     472         [ +  - ]:       1725 :           else if (g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
     473                 :            :             {
     474                 :       1725 :               result = g_strdup ("?");
     475                 :            :             }
     476                 :            :           else
     477                 :            :             g_assert_not_reached ();
     478                 :            :         }
     479                 :            :     }
     480                 :            : 
     481                 :      43394 :   return result;
     482                 :            : }
     483                 :            : 
     484                 :            : /* given a type string, replace one of the indefinite type characters in
     485                 :            :  * it with a matching type (possibly the same type).
     486                 :            :  */
     487                 :            : static gchar *
     488                 :       2657 : generate_subtype (const gchar *type_string)
     489                 :            : {
     490                 :            :   GVariantType *replacement;
     491                 :            :   GString *result, *junk;
     492                 :            :   gint l;
     493                 :       2657 :   gsize length, n = 0;
     494                 :            : 
     495                 :       2657 :   result = g_string_new (NULL);
     496                 :       2657 :   junk = g_string_new (NULL);
     497                 :            : 
     498                 :            :   /* count the number of indefinite type characters */
     499         [ +  + ]:     277397 :   for (length = 0; type_string[length]; length++)
     500                 :     809717 :     n += type_string[length] == 'r' ||
     501   [ +  +  +  + ]:     525589 :          type_string[length] == '?' ||
     502         [ +  + ]:     250849 :          type_string[length] == '*';
     503                 :            :   /* length now is strlen (type_string) */
     504                 :            : 
     505                 :            :   /* pick one at random to replace */
     506                 :       2657 :   n = g_test_rand_int_range (0, n) + 1;
     507                 :            : 
     508                 :            :   /* find it */
     509                 :       2657 :   l = -1;
     510         [ +  + ]:      23903 :   while (n--) l += strcspn (type_string + l + 1, "r?*") + 1;
     511                 :       2657 :   g_assert_true (type_string[l] == 'r' ||
     512                 :            :                  type_string[l] == '?' ||
     513                 :            :                  type_string[l] == '*');
     514                 :            : 
     515                 :            :   /* store up to that point in a GString */
     516         [ -  + ]:       2657 :   g_string_append_len (result, type_string, l);
     517                 :            : 
     518                 :            :   /* then store the replacement in the GString */
     519         [ +  + ]:       2657 :   if (type_string[l] == 'r')
     520                 :       1039 :     replacement = append_tuple_type_string (result, junk, FALSE, 3);
     521                 :            : 
     522         [ +  + ]:       1618 :   else if (type_string[l] == '?')
     523                 :        550 :     replacement = append_type_string (result, junk, FALSE, 0);
     524                 :            : 
     525         [ +  - ]:       1068 :   else if (type_string[l] == '*')
     526                 :       1068 :     replacement = append_type_string (result, junk, FALSE, 3);
     527                 :            : 
     528                 :            :   else
     529                 :            :     g_assert_not_reached ();
     530                 :            : 
     531                 :            :   /* ensure the replacement has the proper type */
     532                 :       2657 :   g_assert_true (g_variant_type_is_subtype_of (replacement,
     533                 :            :                                                (gpointer) &type_string[l]));
     534                 :            : 
     535                 :            :   /* store the rest from the original type string */
     536         [ -  + ]:       2657 :   g_string_append (result, type_string + l + 1);
     537                 :            : 
     538                 :       2657 :   g_variant_type_free (replacement);
     539                 :       2657 :   g_string_free (junk, TRUE);
     540                 :            : 
     541                 :       2657 :   return g_string_free (result, FALSE);
     542                 :            : }
     543                 :            : 
     544                 :            : struct typestack
     545                 :            : {
     546                 :            :   const GVariantType *type;
     547                 :            :   struct typestack *parent;
     548                 :            : };
     549                 :            : 
     550                 :            : /* given an indefinite type string, replace one of the indefinite
     551                 :            :  * characters in it with a matching type and ensure that the result is a
     552                 :            :  * subtype of the original.  repeat.
     553                 :            :  */
     554                 :            : static void
     555                 :       2657 : subtype_check (const gchar      *type_string,
     556                 :            :                struct typestack *parent_ts)
     557                 :            : {
     558                 :            :   struct typestack ts, *node;
     559                 :            :   gchar *subtype;
     560                 :       2657 :   gint depth = 0;
     561                 :            : 
     562                 :       2657 :   subtype = generate_subtype (type_string);
     563                 :            : 
     564                 :       2657 :   ts.type = G_VARIANT_TYPE (subtype);
     565                 :       2657 :   ts.parent = parent_ts;
     566                 :            : 
     567         [ +  + ]:      11371 :   for (node = &ts; node; node = node->parent)
     568                 :            :     {
     569                 :            :       /* this type should be a subtype of each parent type */
     570                 :       8714 :       g_assert_true (g_variant_type_is_subtype_of (ts.type, node->type));
     571                 :            : 
     572                 :            :       /* it should only be a supertype when it is exactly equal */
     573                 :       8714 :       g_assert_true (g_variant_type_is_subtype_of (node->type, ts.type) ==
     574                 :            :                      g_variant_type_equal (ts.type, node->type));
     575                 :            : 
     576                 :       8714 :       depth++;
     577                 :            :     }
     578                 :            : 
     579   [ +  +  +  + ]:       2657 :   if (!g_variant_type_is_definite (ts.type) && depth < 5)
     580                 :            :     {
     581                 :            :       /* the type is still indefinite and we haven't repeated too many
     582                 :            :        * times.  go once more.
     583                 :            :        */
     584                 :            : 
     585                 :       1748 :       subtype_check (subtype, &ts);
     586                 :            :     }
     587                 :            : 
     588                 :       2657 :   g_free (subtype);
     589                 :       2657 : }
     590                 :            : 
     591                 :            : static void
     592                 :          1 : test_gvarianttype (void)
     593                 :            : {
     594                 :            :   gsize i;
     595                 :            : 
     596         [ +  + ]:       2001 :   for (i = 0; i < 2000; i++)
     597                 :            :     {
     598                 :            :       GString *type_string, *description;
     599                 :            :       GVariantType *type, *other_type;
     600                 :            :       const GVariantType *ctype;
     601                 :            :       gchar *invalid;
     602                 :            :       gchar *desc;
     603                 :            : 
     604                 :       2000 :       type_string = g_string_new (NULL);
     605                 :       2000 :       description = g_string_new (NULL);
     606                 :            : 
     607                 :            :       /* generate a random type, its type string and a description
     608                 :            :        *
     609                 :            :        * exercises type constructor functions and g_variant_type_copy()
     610                 :            :        */
     611                 :       2000 :       type = append_type_string (type_string, description, FALSE, 6);
     612                 :            : 
     613                 :            :       /* convert the type string to a type and ensure that it is equal
     614                 :            :        * to the one produced with the type constructor routines
     615                 :            :        */
     616                 :       2000 :       ctype = G_VARIANT_TYPE (type_string->str);
     617                 :       2000 :       g_assert_true (g_variant_type_equal (ctype, type));
     618                 :       2000 :       g_assert_cmpuint (g_variant_type_hash (ctype), ==, g_variant_type_hash (type));
     619                 :       2000 :       g_assert_true (g_variant_type_is_subtype_of (ctype, type));
     620                 :       2000 :       g_assert_true (g_variant_type_is_subtype_of (type, ctype));
     621                 :            : 
     622                 :            :       /* check if the type is indefinite */
     623         [ +  + ]:       2000 :       if (!g_variant_type_is_definite (type))
     624                 :            :         {
     625                 :        909 :           struct typestack ts = { type, NULL };
     626                 :            : 
     627                 :            :           /* if it is indefinite, then replace one of the indefinite
     628                 :            :            * characters with a matching type and ensure that the result
     629                 :            :            * is a subtype of the original type.  repeat.
     630                 :            :            */
     631                 :        909 :           subtype_check (type_string->str, &ts);
     632                 :            :         }
     633                 :            :       else
     634                 :            :         /* ensure that no indefinite characters appear */
     635                 :       1091 :         g_assert_cmpint (strcspn (type_string->str, "r?*"), ==, type_string->len);
     636                 :            : 
     637                 :            : 
     638                 :            :       /* describe the type.
     639                 :            :        *
     640                 :            :        * exercises the type iterator interface
     641                 :            :        */
     642                 :       2000 :       desc = describe_type (type);
     643                 :            : 
     644                 :            :       /* make sure the description matches */
     645                 :       2000 :       g_assert_cmpstr (desc, ==, description->str);
     646                 :       2000 :       g_free (desc);
     647                 :            : 
     648                 :            :       /* make an invalid mutation to the type and make sure the type
     649                 :            :        * validation routines catch it */
     650                 :       2000 :       invalid = invalid_mutation (type_string->str);
     651                 :       2000 :       g_assert_true (g_variant_type_string_is_valid (type_string->str));
     652                 :       2000 :       g_assert_false (g_variant_type_string_is_valid (invalid));
     653                 :       2000 :       g_free (invalid);
     654                 :            : 
     655                 :            :       /* concatenate another type to the type string and ensure that
     656                 :            :        * the result is recognised as being invalid
     657                 :            :        */
     658                 :       2000 :       other_type = append_type_string (type_string, description, FALSE, 2);
     659                 :            : 
     660                 :       2000 :       g_string_free (description, TRUE);
     661                 :       2000 :       g_string_free (type_string, TRUE);
     662                 :       2000 :       g_variant_type_free (other_type);
     663                 :       2000 :       g_variant_type_free (type);
     664                 :            :     }
     665                 :          1 : }
     666                 :            : 
     667                 :            : /* Test that scanning a deeply recursive type string doesn’t exhaust our
     668                 :            :  * stack space (which it would if the type string scanner was recursive). */
     669                 :            : static void
     670                 :          1 : test_gvarianttype_string_scan_recursion_tuple (void)
     671                 :            : {
     672                 :          1 :   gchar *type_string = NULL;
     673                 :          1 :   gsize type_string_len = 1000001;  /* not including nul terminator */
     674                 :            :   gsize i;
     675                 :            : 
     676                 :            :   /* Build a long type string of ‘((…u…))’. */
     677                 :          1 :   type_string = g_new0 (gchar, type_string_len + 1);
     678         [ +  + ]:    1000002 :   for (i = 0; i < type_string_len; i++)
     679                 :            :     {
     680         [ +  + ]:    1000001 :       if (i < type_string_len / 2)
     681                 :     500000 :         type_string[i] = '(';
     682         [ +  + ]:     500001 :       else if (i == type_string_len / 2)
     683                 :          1 :         type_string[i] = 'u';
     684                 :            :       else
     685                 :     500000 :         type_string[i] = ')';
     686                 :            :     }
     687                 :            : 
     688                 :            :   /* Goes (way) over allowed recursion limit. */
     689                 :          1 :   g_assert_false (g_variant_type_string_is_valid (type_string));
     690                 :            : 
     691                 :          1 :   g_free (type_string);
     692                 :          1 : }
     693                 :            : 
     694                 :            : /* Same as above, except with an array rather than a tuple. */
     695                 :            : static void
     696                 :          1 : test_gvarianttype_string_scan_recursion_array (void)
     697                 :            : {
     698                 :          1 :   gchar *type_string = NULL;
     699                 :          1 :   gsize type_string_len = 1000001;  /* not including nul terminator */
     700                 :            :   gsize i;
     701                 :            : 
     702                 :            :   /* Build a long type string of ‘aaa…aau’. */
     703                 :          1 :   type_string = g_new0 (gchar, type_string_len + 1);
     704         [ +  + ]:    1000002 :   for (i = 0; i < type_string_len; i++)
     705                 :            :     {
     706         [ +  + ]:    1000001 :       if (i < type_string_len - 1)
     707                 :    1000000 :         type_string[i] = 'a';
     708                 :            :       else
     709                 :          1 :         type_string[i] = 'u';
     710                 :            :     }
     711                 :            : 
     712                 :            :   /* Goes (way) over allowed recursion limit. */
     713                 :          1 :   g_assert_false (g_variant_type_string_is_valid (type_string));
     714                 :            : 
     715                 :          1 :   g_free (type_string);
     716                 :          1 : }
     717                 :            : 
     718                 :            : #define ALIGNED(x, y)   (((x + (y - 1)) / y) * y)
     719                 :            : 
     720                 :            : /* do our own calculation of the fixed_size and alignment of a type
     721                 :            :  * using a simple algorithm to make sure the "fancy" one in the
     722                 :            :  * implementation is correct.
     723                 :            :  */
     724                 :            : static void
     725                 :    1108584 : calculate_type_info (const GVariantType *type,
     726                 :            :                      gsize              *fixed_size,
     727                 :            :                      guint              *alignment)
     728                 :            : {
     729   [ +  +  +  + ]:    2137863 :   if (g_variant_type_is_array (type) ||
     730                 :    1029279 :       g_variant_type_is_maybe (type))
     731                 :            :     {
     732                 :     159817 :       calculate_type_info (g_variant_type_element (type), NULL, alignment);
     733                 :            : 
     734         [ +  + ]:     159817 :       if (fixed_size)
     735                 :     135282 :         *fixed_size = 0;
     736                 :            :     }
     737   [ +  +  +  + ]:    1817972 :   else if (g_variant_type_is_tuple (type) ||
     738                 :     869205 :            g_variant_type_is_dict_entry (type))
     739                 :            :     {
     740         [ +  + ]:     158586 :       if (g_variant_type_n_items (type))
     741                 :            :         {
     742                 :            :           const GVariantType *sub;
     743                 :            :           gboolean variable;
     744                 :            :           gsize size;
     745                 :            :           guint al;
     746                 :            : 
     747                 :     154975 :           variable = FALSE;
     748                 :     154975 :           size = 0;
     749                 :     154975 :           al = 0;
     750                 :            : 
     751                 :     154975 :           sub = g_variant_type_first (type);
     752                 :            :           do
     753                 :            :             {
     754                 :            :               gsize this_fs;
     755                 :            :               guint this_al;
     756                 :            : 
     757                 :     920927 :               calculate_type_info (sub, &this_fs, &this_al);
     758                 :            : 
     759                 :     920927 :               al = MAX (al, this_al);
     760                 :            : 
     761         [ +  + ]:     920927 :               if (!this_fs)
     762                 :            :                 {
     763                 :     424756 :                   variable = TRUE;
     764                 :     424756 :                   size = 0;
     765                 :            :                 }
     766                 :            : 
     767         [ +  + ]:     920927 :               if (!variable)
     768                 :            :                 {
     769                 :     205953 :                   size = ALIGNED (size, this_al);
     770                 :     205953 :                   size += this_fs;
     771                 :            :                 }
     772                 :            :             }
     773         [ +  + ]:     920927 :           while ((sub = g_variant_type_next (sub)));
     774                 :            : 
     775                 :     154975 :           size = ALIGNED (size, al);
     776                 :            : 
     777         [ +  - ]:     154975 :           if (alignment)
     778                 :     154975 :             *alignment = al;
     779                 :            : 
     780         [ +  + ]:     154975 :           if (fixed_size)
     781                 :     131432 :             *fixed_size = size;
     782                 :            :         }
     783                 :            :       else
     784                 :            :         {
     785         [ +  + ]:       3611 :           if (fixed_size)
     786                 :       3015 :             *fixed_size = 1;
     787                 :            : 
     788         [ +  - ]:       3611 :           if (alignment)
     789                 :       3611 :             *alignment = 1;
     790                 :            :         }
     791                 :            :     }
     792                 :            :   else
     793                 :            :     {
     794                 :            :       gint fs, al;
     795                 :            : 
     796   [ +  +  +  + ]:    1524731 :       if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN) ||
     797                 :     734550 :           g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
     798                 :            :         {
     799                 :     108741 :           al = fs = 1;
     800                 :            :         }
     801                 :            : 
     802   [ +  +  +  + ]:    1309220 :       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16) ||
     803                 :     627780 :                g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
     804                 :            :         {
     805                 :     108052 :           al = fs = 2;
     806                 :            :         }
     807                 :            : 
     808   [ +  +  +  + ]:    1091094 :       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32) ||
     809         [ +  + ]:     980561 :                g_variant_type_equal (type, G_VARIANT_TYPE_UINT32) ||
     810                 :     462855 :                g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
     811                 :            :         {
     812                 :     164451 :           al = fs = 4;
     813                 :            :         }
     814                 :            : 
     815   [ +  +  +  + ]:     763237 :       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64) ||
     816         [ +  + ]:     654012 :                g_variant_type_equal (type, G_VARIANT_TYPE_UINT64) ||
     817                 :     299712 :                g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
     818                 :            :         {
     819                 :     164503 :           al = fs = 8;
     820                 :            :         }
     821   [ +  +  +  + ]:     433784 :       else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING) ||
     822         [ +  + ]:     323818 :                g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH) ||
     823                 :     134468 :                g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
     824                 :            :         {
     825                 :     164707 :           al = 1;
     826                 :     164707 :           fs = 0;
     827                 :            :         }
     828         [ +  - ]:      79727 :       else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
     829                 :            :         {
     830                 :      79727 :           al = 8;
     831                 :      79727 :           fs = 0;
     832                 :            :         }
     833                 :            :       else
     834                 :            :         g_assert_not_reached ();
     835                 :            : 
     836         [ +  + ]:     790181 :       if (fixed_size)
     837                 :     679038 :         *fixed_size = fs;
     838                 :            : 
     839         [ +  - ]:     790181 :       if (alignment)
     840                 :     790181 :         *alignment = al;
     841                 :            :     }
     842                 :    1108584 : }
     843                 :            : 
     844                 :            : /* same as the describe_type() function above, but iterates over
     845                 :            :  * typeinfo instead of types.
     846                 :            :  */
     847                 :            : static gchar *
     848                 :     143258 : describe_info (GVariantTypeInfo *info)
     849                 :            : {
     850                 :            :   gchar *result;
     851                 :            : 
     852   [ +  +  +  +  :     143258 :   switch (g_variant_type_info_get_type_char (info))
                   +  + ]
     853                 :            :     {
     854                 :      10572 :     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
     855                 :            :       {
     856                 :            :         gchar *element;
     857                 :            : 
     858                 :      10572 :         element = describe_info (g_variant_type_info_element (info));
     859                 :      10572 :         result = g_strdup_printf ("m of %s", element);
     860                 :      10572 :         g_free (element);
     861                 :            :       }
     862                 :      10572 :       break;
     863                 :            : 
     864                 :      10335 :     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
     865                 :            :       {
     866                 :            :         gchar *element;
     867                 :            : 
     868                 :      10335 :         element = describe_info (g_variant_type_info_element (info));
     869                 :      10335 :         result = g_strdup_printf ("a of %s", element);
     870                 :      10335 :         g_free (element);
     871                 :            :       }
     872                 :      10335 :       break;
     873                 :            : 
     874                 :      10400 :     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
     875                 :            :       {
     876                 :      10400 :         const gchar *sep = "";
     877                 :            :         GString *string;
     878                 :            :         gsize i, length;
     879                 :            : 
     880                 :      10400 :         string = g_string_new ("t of [");
     881                 :      10400 :         length = g_variant_type_info_n_members (info);
     882                 :            : 
     883         [ +  + ]:     110107 :         for (i = 0; i < length; i++)
     884                 :            :           {
     885                 :            :             const GVariantMemberInfo *minfo;
     886                 :            :             gchar *subtype;
     887                 :            : 
     888                 :            :             g_string_append (string, sep);
     889                 :      99707 :             sep = ", ";
     890                 :            : 
     891                 :      99707 :             minfo = g_variant_type_info_member_info (info, i);
     892                 :      99707 :             subtype = describe_info (minfo->type_info);
     893                 :            :             g_string_append (string, subtype);
     894                 :      99707 :             g_free (subtype);
     895                 :            :           }
     896                 :            : 
     897                 :            :         g_string_append_c (string, ']');
     898                 :            : 
     899                 :      10400 :         result = g_string_free (string, FALSE);
     900                 :            :       }
     901                 :      10400 :       break;
     902                 :            : 
     903                 :      10322 :     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
     904                 :            :       {
     905                 :            :         const GVariantMemberInfo *keyinfo, *valueinfo;
     906                 :            :         gchar *key, *value;
     907                 :            : 
     908                 :      10322 :         g_assert_cmpint (g_variant_type_info_n_members (info), ==, 2);
     909                 :      10322 :         keyinfo = g_variant_type_info_member_info (info, 0);
     910                 :      10322 :         valueinfo = g_variant_type_info_member_info (info, 1);
     911                 :      10322 :         key = describe_info (keyinfo->type_info);
     912                 :      10322 :         value = describe_info (valueinfo->type_info);
     913                 :      10322 :         result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
     914                 :      10322 :         g_free (key);
     915                 :      10322 :         g_free (value);
     916                 :            :       }
     917                 :      10322 :       break;
     918                 :            : 
     919                 :      10423 :     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
     920                 :      10423 :       result = g_strdup ("V");
     921                 :      10423 :       break;
     922                 :            : 
     923                 :      91206 :     default:
     924                 :      91206 :       result = g_strdup (g_variant_type_info_get_type_string (info));
     925                 :      91206 :       g_assert_cmpint (strlen (result), ==, 1);
     926                 :      91206 :       break;
     927                 :            :     }
     928                 :            : 
     929                 :     143258 :   return result;
     930                 :            : }
     931                 :            : 
     932                 :            : /* check that the O(1) method of calculating offsets meshes with the
     933                 :            :  * results of simple iteration.
     934                 :            :  */
     935                 :            : static void
     936                 :        542 : check_offsets (GVariantTypeInfo   *info,
     937                 :            :                const GVariantType *type)
     938                 :            : {
     939                 :            :   gsize flavour, length;
     940                 :            : 
     941                 :        542 :   length = g_variant_type_info_n_members (info);
     942                 :        542 :   g_assert_cmpuint (length, ==, g_variant_type_n_items (type));
     943                 :            : 
     944                 :            :   /* the 'flavour' is the low order bits of the ending point of
     945                 :            :    * variable-size items in the tuple.  this lets us test that the type
     946                 :            :    * info is correct for various starting alignments.
     947                 :            :    */
     948         [ +  + ]:       4878 :   for (flavour = 0; flavour < 8; flavour++)
     949                 :            :     {
     950                 :            :       const GVariantType *subtype;
     951                 :            :       gsize last_offset_index;
     952                 :            :       gsize last_offset;
     953                 :            :       gsize position;
     954                 :            :       gsize i;
     955                 :            : 
     956                 :       4336 :       subtype = g_variant_type_first (type);
     957                 :       4336 :       last_offset_index = -1;
     958                 :       4336 :       last_offset = 0;
     959                 :       4336 :       position = 0;
     960                 :            : 
     961                 :            :       /* go through the tuple, keeping track of our position */
     962         [ +  + ]:      29592 :       for (i = 0; i < length; i++)
     963                 :            :         {
     964                 :            :           gsize fixed_size;
     965                 :            :           guint alignment;
     966                 :            : 
     967                 :      25256 :           calculate_type_info (subtype, &fixed_size, &alignment);
     968                 :            : 
     969                 :      25256 :           position = ALIGNED (position, alignment);
     970                 :            : 
     971                 :            :           /* compare our current aligned position (ie: the start of this
     972                 :            :            * item) to the start offset that would be calculated if we
     973                 :            :            * used the type info
     974                 :            :            */
     975                 :            :           {
     976                 :            :             const GVariantMemberInfo *member;
     977                 :            :             gsize start;
     978                 :            : 
     979                 :      25256 :             member = g_variant_type_info_member_info (info, i);
     980                 :      25256 :             g_assert_cmpint (member->i, ==, last_offset_index);
     981                 :            : 
     982                 :            :             /* do the calculation using the typeinfo */
     983                 :      25256 :             start = last_offset;
     984                 :      25256 :             start += member->a;
     985                 :      25256 :             start &= member->b;
     986                 :      25256 :             start |= member->c;
     987                 :            : 
     988                 :            :             /* did we reach the same spot? */
     989                 :      25256 :             g_assert_cmpint (start, ==, position);
     990                 :            :           }
     991                 :            : 
     992         [ +  + ]:      25256 :           if (fixed_size)
     993                 :            :             {
     994                 :            :               /* fixed size.  add that size. */
     995                 :       7848 :               position += fixed_size;
     996                 :            :             }
     997                 :            :           else
     998                 :            :             {
     999                 :            :               /* variable size.  do the flavouring. */
    1000         [ +  + ]:      73260 :               while ((position & 0x7) != flavour)
    1001                 :      55852 :                 position++;
    1002                 :            : 
    1003                 :            :               /* and store the offset, just like it would be in the
    1004                 :            :                * serialized data.
    1005                 :            :                */
    1006                 :      17408 :               last_offset = position;
    1007                 :      17408 :               last_offset_index++;
    1008                 :            :             }
    1009                 :            : 
    1010                 :            :           /* next type */
    1011                 :      25256 :           subtype = g_variant_type_next (subtype);
    1012                 :            :         }
    1013                 :            : 
    1014                 :            :       /* make sure we used up exactly all the types */
    1015                 :       4336 :       g_assert_null (subtype);
    1016                 :            :     }
    1017                 :        542 : }
    1018                 :            : 
    1019                 :            : static void
    1020                 :          1 : test_gvarianttypeinfo (void)
    1021                 :            : {
    1022                 :            :   gsize i;
    1023                 :            : 
    1024         [ +  + ]:       2001 :   for (i = 0; i < 2000; i++)
    1025                 :            :     {
    1026                 :            :       GString *type_string, *description;
    1027                 :            :       gsize fixed_size1, fixed_size2;
    1028                 :            :       guint alignment1, alignment2;
    1029                 :            :       GVariantTypeInfo *info;
    1030                 :            :       GVariantType *type;
    1031                 :            :       gchar *desc;
    1032                 :            : 
    1033                 :       2000 :       type_string = g_string_new (NULL);
    1034                 :       2000 :       description = g_string_new (NULL);
    1035                 :            : 
    1036                 :            :       /* random type */
    1037                 :       2000 :       type = append_type_string (type_string, description, TRUE, 6);
    1038                 :            : 
    1039                 :            :       /* create a typeinfo for it */
    1040                 :       2000 :       info = g_variant_type_info_get (type);
    1041                 :            : 
    1042                 :            :       /* make sure the typeinfo has the right type string */
    1043                 :       2000 :       g_assert_cmpstr (g_variant_type_info_get_type_string (info), ==,
    1044                 :            :                        type_string->str);
    1045                 :            : 
    1046                 :            :       /* calculate the alignment and fixed size, compare to the
    1047                 :            :        * typeinfo's calculations
    1048                 :            :        */
    1049                 :       2000 :       calculate_type_info (type, &fixed_size1, &alignment1);
    1050                 :       2000 :       g_variant_type_info_query (info, &alignment2, &fixed_size2);
    1051                 :       2000 :       g_assert_cmpint (fixed_size1, ==, fixed_size2);
    1052                 :       2000 :       g_assert_cmpint (alignment1, ==, alignment2 + 1);
    1053                 :            : 
    1054                 :            :       /* test the iteration functions over typeinfo structures by
    1055                 :            :        * "describing" the typeinfo and verifying equality.
    1056                 :            :        */
    1057                 :       2000 :       desc = describe_info (info);
    1058                 :       2000 :       g_assert_cmpstr (desc, ==, description->str);
    1059                 :            : 
    1060                 :            :       /* do extra checks for containers */
    1061   [ +  +  +  + ]:       3709 :       if (g_variant_type_is_array (type) ||
    1062                 :       1709 :           g_variant_type_is_maybe (type))
    1063                 :        584 :         {
    1064                 :            :           const GVariantType *element;
    1065                 :            :           gsize efs1, efs2;
    1066                 :            :           guint ea1, ea2;
    1067                 :            : 
    1068                 :        584 :           element = g_variant_type_element (type);
    1069                 :        584 :           calculate_type_info (element, &efs1, &ea1);
    1070                 :        584 :           g_variant_type_info_query_element (info, &ea2, &efs2);
    1071                 :        584 :           g_assert_cmpint (efs1, ==, efs2);
    1072                 :        584 :           g_assert_cmpint (ea1, ==, ea2 + 1);
    1073                 :            : 
    1074                 :        584 :           g_assert_cmpint (ea1, ==, alignment1);
    1075                 :        584 :           g_assert_cmpint (0, ==, fixed_size1);
    1076                 :            :         }
    1077   [ +  +  +  + ]:       2556 :       else if (g_variant_type_is_tuple (type) ||
    1078                 :       1140 :                g_variant_type_is_dict_entry (type))
    1079                 :            :         {
    1080                 :            :           /* make sure the "magic constants" are working */
    1081                 :        542 :           check_offsets (info, type);
    1082                 :            :         }
    1083                 :            : 
    1084                 :       2000 :       g_string_free (type_string, TRUE);
    1085                 :       2000 :       g_string_free (description, TRUE);
    1086                 :       2000 :       g_variant_type_info_unref (info);
    1087                 :       2000 :       g_variant_type_free (type);
    1088                 :       2000 :       g_free (desc);
    1089                 :            :     }
    1090                 :            : 
    1091                 :          1 :   g_variant_type_info_assert_no_infos ();
    1092                 :          1 : }
    1093                 :            : 
    1094                 :            : #define MAX_FIXED_MULTIPLIER    256
    1095                 :            : #define MAX_INSTANCE_SIZE       1024
    1096                 :            : #define MAX_ARRAY_CHILDREN      128
    1097                 :            : #define MAX_TUPLE_CHILDREN      128
    1098                 :            : 
    1099                 :            : /* this function generates a random type such that all characteristics
    1100                 :            :  * that are "interesting" to the serializer are tested.
    1101                 :            :  *
    1102                 :            :  * this basically means:
    1103                 :            :  *   - test different alignments
    1104                 :            :  *   - test variable sized items and fixed sized items
    1105                 :            :  *   - test different fixed sizes
    1106                 :            :  */
    1107                 :            : static gchar *
    1108                 :       6743 : random_type_string (void)
    1109                 :            : {
    1110                 :       6743 :   const guchar base_types[] = "ynix";
    1111                 :            :   guchar base_type;
    1112                 :            : 
    1113                 :       6743 :   base_type = base_types[g_test_rand_int_range (0, 4)];
    1114                 :            : 
    1115         [ +  + ]:       6743 :   if (g_test_rand_bit ())
    1116                 :            :     /* construct a fixed-sized type */
    1117                 :            :     {
    1118                 :            :       char type_string[MAX_FIXED_MULTIPLIER];
    1119                 :            :       guint multiplier;
    1120                 :       3371 :       gsize i = 0;
    1121                 :            : 
    1122                 :       3371 :       multiplier = g_test_rand_int_range (1, sizeof type_string - 1);
    1123                 :            : 
    1124                 :       3371 :       type_string[i++] = '(';
    1125         [ +  + ]:     432259 :       while (multiplier--)
    1126                 :     428888 :         type_string[i++] = base_type;
    1127                 :       3371 :       type_string[i++] = ')';
    1128                 :            : 
    1129                 :       3371 :       return g_strndup (type_string, i);
    1130                 :            :     }
    1131                 :            :   else
    1132                 :            :     /* construct a variable-sized type */
    1133                 :            :     {
    1134                 :       3372 :       char type_string[2] = { 'a', base_type };
    1135                 :            : 
    1136                 :       3372 :       return g_strndup (type_string, 2);
    1137                 :            :     }
    1138                 :            : }
    1139                 :            : 
    1140                 :            : typedef struct
    1141                 :            : {
    1142                 :            :   GVariantTypeInfo *type_info;
    1143                 :            :   guint alignment;
    1144                 :            :   gsize size;
    1145                 :            :   gboolean is_fixed_sized;
    1146                 :            : 
    1147                 :            :   guint32 seed;
    1148                 :            : 
    1149                 :            : #define INSTANCE_MAGIC    1287582829
    1150                 :            :   guint magic;
    1151                 :            : } RandomInstance;
    1152                 :            : 
    1153                 :            : static RandomInstance *
    1154                 :      13500 : random_instance (GVariantTypeInfo *type_info)
    1155                 :            : {
    1156                 :            :   RandomInstance *instance;
    1157                 :            : 
    1158                 :      13500 :   instance = g_slice_new (RandomInstance);
    1159                 :            : 
    1160         [ +  + ]:      13500 :   if (type_info == NULL)
    1161                 :            :     {
    1162                 :       6643 :       gchar *str = random_type_string ();
    1163                 :       6643 :       instance->type_info = g_variant_type_info_get (G_VARIANT_TYPE (str));
    1164                 :       6643 :       g_free (str);
    1165                 :            :     }
    1166                 :            :   else
    1167                 :       6857 :     instance->type_info = g_variant_type_info_ref (type_info);
    1168                 :            : 
    1169                 :      13500 :   instance->seed = g_test_rand_int ();
    1170                 :            : 
    1171                 :      13500 :   g_variant_type_info_query (instance->type_info,
    1172                 :            :                              &instance->alignment,
    1173                 :            :                              &instance->size);
    1174                 :            : 
    1175                 :      13500 :   instance->is_fixed_sized = instance->size != 0;
    1176                 :            : 
    1177         [ +  + ]:      13500 :   if (!instance->is_fixed_sized)
    1178                 :       6625 :     instance->size = g_test_rand_int_range (0, MAX_INSTANCE_SIZE);
    1179                 :            : 
    1180                 :      13500 :   instance->magic = INSTANCE_MAGIC;
    1181                 :            : 
    1182                 :      13500 :   return instance;
    1183                 :            : }
    1184                 :            : 
    1185                 :            : static void
    1186                 :      13500 : random_instance_free (RandomInstance *instance)
    1187                 :            : {
    1188                 :      13500 :   g_variant_type_info_unref (instance->type_info);
    1189                 :      13500 :   g_slice_free (RandomInstance, instance);
    1190                 :      13500 : }
    1191                 :            : 
    1192                 :            : static void
    1193                 :      12400 : append_instance_size (RandomInstance *instance,
    1194                 :            :                       gsize          *offset)
    1195                 :            : {
    1196                 :      12400 :   *offset += (-*offset) & instance->alignment;
    1197                 :      12400 :   *offset += instance->size;
    1198                 :      12400 : }
    1199                 :            : 
    1200                 :            : static void
    1201                 :      51601 : random_instance_write (RandomInstance *instance,
    1202                 :            :                        guchar         *buffer)
    1203                 :            : {
    1204                 :            :   GRand *rand;
    1205                 :            :   gsize i;
    1206                 :            : 
    1207                 :      51601 :   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
    1208                 :            : 
    1209                 :      51601 :   rand = g_rand_new_with_seed (instance->seed);
    1210         [ +  + ]:   21240900 :   for (i = 0; i < instance->size; i++)
    1211                 :   21189299 :     buffer[i] = g_rand_int (rand);
    1212                 :      51601 :   g_rand_free (rand);
    1213                 :      51601 : }
    1214                 :            : 
    1215                 :            : static void
    1216                 :      13500 : append_instance_data (RandomInstance  *instance,
    1217                 :            :                       guchar         **buffer)
    1218                 :            : {
    1219         [ +  + ]:      23026 :   while (((gsize) *buffer) & instance->alignment)
    1220                 :       9526 :     *(*buffer)++ = '\0';
    1221                 :            : 
    1222                 :      13500 :   random_instance_write (instance, *buffer);
    1223                 :      13500 :   *buffer += instance->size;
    1224                 :      13500 : }
    1225                 :            : 
    1226                 :            : static gboolean
    1227                 :      37987 : random_instance_assert (RandomInstance *instance,
    1228                 :            :                         guchar         *buffer,
    1229                 :            :                         gsize           size)
    1230                 :            : {
    1231                 :            :   GRand *rand;
    1232                 :            :   gsize i;
    1233                 :            : 
    1234                 :      37987 :   g_assert_true (size == 0 || buffer != NULL);
    1235                 :      37987 :   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
    1236                 :      37987 :   g_assert_cmpint (size, ==, instance->size);
    1237                 :            : 
    1238                 :      37987 :   rand = g_rand_new_with_seed (instance->seed);
    1239         [ +  + ]:   14520675 :   for (i = 0; i < instance->size; i++)
    1240                 :            :     {
    1241                 :   14482688 :       guchar byte = g_rand_int (rand);
    1242                 :            : 
    1243                 :   14482688 :       g_assert_cmpuint (buffer[i], ==, byte);
    1244                 :            :     }
    1245                 :      37987 :   g_rand_free (rand);
    1246                 :            : 
    1247                 :      37987 :   return i == instance->size;
    1248                 :            : }
    1249                 :            : 
    1250                 :            : static gboolean
    1251                 :        100 : random_instance_check (RandomInstance *instance,
    1252                 :            :                        guchar         *buffer,
    1253                 :            :                        gsize           size)
    1254                 :            : {
    1255                 :            :   GRand *rand;
    1256                 :            :   gsize i;
    1257                 :            : 
    1258                 :        100 :   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
    1259                 :            : 
    1260         [ -  + ]:        100 :   if (size != instance->size)
    1261                 :          0 :     return FALSE;
    1262                 :            : 
    1263                 :        100 :   rand = g_rand_new_with_seed (instance->seed);
    1264         [ +  + ]:      48198 :   for (i = 0; i < instance->size; i++)
    1265         [ -  + ]:      48098 :     if (buffer[i] != (guchar) g_rand_int (rand))
    1266                 :          0 :       break;
    1267                 :        100 :   g_rand_free (rand);
    1268                 :            : 
    1269                 :        100 :   return i == instance->size;
    1270                 :            : }
    1271                 :            : 
    1272                 :            : static void
    1273                 :      44783 : random_instance_filler (GVariantSerialised *serialised,
    1274                 :            :                         gpointer            data)
    1275                 :            : {
    1276                 :      44783 :   RandomInstance *instance = data;
    1277                 :            : 
    1278                 :      44783 :   g_assert_cmpuint (instance->magic, ==, INSTANCE_MAGIC);
    1279                 :            : 
    1280         [ +  + ]:      44783 :   if (serialised->type_info == NULL)
    1281                 :      28848 :     serialised->type_info = instance->type_info;
    1282                 :            : 
    1283         [ +  + ]:      44783 :   if (serialised->size == 0)
    1284                 :      24990 :     serialised->size = instance->size;
    1285                 :            : 
    1286                 :      44783 :   serialised->depth = 0;
    1287                 :      44783 :   serialised->ordered_offsets_up_to = 0;
    1288                 :      44783 :   serialised->checked_offsets_up_to = 0;
    1289                 :            : 
    1290                 :      44783 :   g_assert_true (serialised->type_info == instance->type_info);
    1291                 :      44783 :   g_assert_cmpuint (serialised->size, ==, instance->size);
    1292                 :            : 
    1293         [ +  + ]:      44783 :   if (serialised->data)
    1294                 :      38101 :     random_instance_write (instance, serialised->data);
    1295                 :      44783 : }
    1296                 :            : 
    1297                 :            : static gsize
    1298                 :        151 : calculate_offset_size (gsize body_size,
    1299                 :            :                        gsize n_offsets)
    1300                 :            : {
    1301         [ +  + ]:        151 :   if (body_size == 0)
    1302                 :          1 :     return 0;
    1303                 :            : 
    1304         [ +  + ]:        150 :   if (body_size + n_offsets <= G_MAXUINT8)
    1305                 :          2 :     return 1;
    1306                 :            : 
    1307         [ +  + ]:        148 :   if (body_size + 2 * n_offsets <= G_MAXUINT16)
    1308                 :        143 :     return 2;
    1309                 :            : 
    1310         [ +  - ]:          5 :   if (body_size + 4 * n_offsets <= G_MAXUINT32)
    1311                 :          5 :     return 4;
    1312                 :            : 
    1313                 :            :   /* the test case won't generate anything bigger */
    1314                 :            :   g_assert_not_reached ();
    1315                 :            : }
    1316                 :            : 
    1317                 :            : static gpointer
    1318                 :       4483 : flavoured_malloc (gsize size, gsize flavour)
    1319                 :            : {
    1320                 :       4483 :   g_assert_cmpuint (flavour, <, 8);
    1321                 :            : 
    1322         [ +  + ]:       4483 :   if (size == 0)
    1323                 :          8 :     return NULL;
    1324                 :            : 
    1325                 :       4475 :   return ((gchar *) g_malloc (size + flavour)) + flavour;
    1326                 :            : }
    1327                 :            : 
    1328                 :            : static void
    1329                 :       4483 : flavoured_free (gpointer data,
    1330                 :            :                 gsize flavour)
    1331                 :            : {
    1332         [ +  + ]:       4483 :   if (!data)
    1333                 :          8 :     return;
    1334                 :       4475 :   g_free (((gchar *) data) - flavour);
    1335                 :            : }
    1336                 :            : 
    1337                 :            : static gpointer
    1338                 :       1300 : align_malloc (gsize size)
    1339                 :            : {
    1340                 :       1300 :   gpointer mem = NULL;
    1341                 :            : 
    1342                 :            : #ifdef HAVE_POSIX_MEMALIGN
    1343                 :            :   /* posix_memalign() requires the alignment to be a multiple of
    1344                 :            :    * sizeof(void*), and a power of 2.
    1345                 :            :    * Calling it with size==0 leads to implementation-defined behaviour, so avoid
    1346                 :            :    * that and guarantee to return NULL. */
    1347         [ +  + ]:       1300 :   if (size != 0 &&
    1348         [ -  + ]:       1299 :       posix_memalign (&mem, MAX (sizeof (void *), 8), size))
    1349                 :          0 :     g_error ("posix_memalign failed");
    1350                 :            : #else
    1351                 :            :   /* NOTE: there may be platforms that lack posix_memalign() and also
    1352                 :            :    * have malloc() that returns non-8-aligned.  if so, we need to try
    1353                 :            :    * harder here.
    1354                 :            :    */
    1355                 :            :   mem = (size > 0) ? malloc (size) : NULL;
    1356                 :            : #endif
    1357                 :            : 
    1358                 :       1300 :   return mem;
    1359                 :            : }
    1360                 :            : 
    1361                 :            : static void
    1362                 :       1300 : align_free (gpointer mem)
    1363                 :            : {
    1364                 :       1300 :   free (mem);
    1365                 :       1300 : }
    1366                 :            : 
    1367                 :            : static void
    1368                 :       6857 : append_offset (guchar **offset_ptr,
    1369                 :            :                gsize    offset,
    1370                 :            :                guint    offset_size)
    1371                 :            : {
    1372                 :            :   union
    1373                 :            :   {
    1374                 :            :     guchar bytes[sizeof (gsize)];
    1375                 :            :     gsize integer;
    1376                 :            :   } tmpvalue;
    1377                 :            : 
    1378                 :       6857 :   tmpvalue.integer = GSIZE_TO_LE (offset);
    1379                 :       6857 :   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
    1380                 :       6857 :   *offset_ptr += offset_size;
    1381                 :       6857 : }
    1382                 :            : 
    1383                 :            : static void
    1384                 :       2733 : prepend_offset (guchar **offset_ptr,
    1385                 :            :                 gsize    offset,
    1386                 :            :                 guint    offset_size)
    1387                 :            : {
    1388                 :            :   union
    1389                 :            :   {
    1390                 :            :     guchar bytes[sizeof (gsize)];
    1391                 :            :     gsize integer;
    1392                 :            :   } tmpvalue;
    1393                 :            : 
    1394                 :       2733 :   *offset_ptr -= offset_size;
    1395                 :       2733 :   tmpvalue.integer = GSIZE_TO_LE (offset);
    1396                 :       2733 :   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
    1397                 :       2733 : }
    1398                 :            : 
    1399                 :            : static void
    1400                 :       1000 : test_maybe (void)
    1401                 :            : {
    1402                 :            :   GVariantTypeInfo *type_info;
    1403                 :            :   RandomInstance *instance;
    1404                 :            :   gsize needed_size;
    1405                 :            :   guchar *data;
    1406                 :            : 
    1407                 :       1000 :   instance = random_instance (NULL);
    1408                 :            : 
    1409                 :            :   {
    1410                 :            :     const gchar *element;
    1411                 :            :     gchar *tmp;
    1412                 :            : 
    1413                 :       1000 :     element = g_variant_type_info_get_type_string (instance->type_info);
    1414                 :       1000 :     tmp = g_strdup_printf ("m%s", element);
    1415                 :       1000 :     type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
    1416                 :       1000 :     g_free (tmp);
    1417                 :            :   }
    1418                 :            : 
    1419                 :       1000 :   needed_size = g_variant_serialiser_needed_size (type_info,
    1420                 :            :                                                   random_instance_filler,
    1421                 :            :                                                   NULL, 0);
    1422                 :       1000 :   g_assert_cmpint (needed_size, ==, 0);
    1423                 :            : 
    1424                 :       1000 :   needed_size = g_variant_serialiser_needed_size (type_info,
    1425                 :            :                                                   random_instance_filler,
    1426                 :            :                                                   (gpointer *) &instance, 1);
    1427                 :            : 
    1428         [ +  + ]:       1000 :   if (instance->is_fixed_sized)
    1429                 :        504 :     g_assert_cmpint (needed_size, ==, instance->size);
    1430                 :            :   else
    1431                 :        496 :     g_assert_cmpint (needed_size, ==, instance->size + 1);
    1432                 :            : 
    1433                 :            :   {
    1434                 :            :     guchar *ptr;
    1435                 :            : 
    1436                 :       1000 :     ptr = data = align_malloc (needed_size);
    1437                 :       1000 :     append_instance_data (instance, &ptr);
    1438                 :            : 
    1439         [ +  + ]:       1000 :     if (!instance->is_fixed_sized)
    1440                 :        496 :       *ptr++ = '\0';
    1441                 :            : 
    1442                 :       1000 :     g_assert_cmpint (ptr - data, ==, needed_size);
    1443                 :            :   }
    1444                 :            : 
    1445                 :            :   {
    1446                 :            :     guint alignment;
    1447                 :            :     gsize flavour;
    1448                 :            : 
    1449                 :       1000 :     alignment = (instance->alignment & ALIGN_BITS) + 1;
    1450                 :            : 
    1451         [ +  + ]:       4859 :     for (flavour = 0; flavour < 8; flavour += alignment)
    1452                 :            :       {
    1453                 :       3859 :         GVariantSerialised serialised = { 0, };
    1454                 :            :         GVariantSerialised child;
    1455                 :            : 
    1456                 :       3859 :         serialised.type_info = type_info;
    1457                 :       3859 :         serialised.data = flavoured_malloc (needed_size, flavour);
    1458                 :       3859 :         serialised.size = needed_size;
    1459                 :       3859 :         serialised.depth = 0;
    1460                 :       3859 :         serialised.ordered_offsets_up_to = 0;
    1461                 :       3859 :         serialised.checked_offsets_up_to = 0;
    1462                 :            : 
    1463                 :       3859 :         g_variant_serialiser_serialise (serialised,
    1464                 :            :                                         random_instance_filler,
    1465                 :            :                                         (gpointer *) &instance, 1);
    1466                 :            : 
    1467                 :       3859 :         child = g_variant_serialised_get_child (serialised, 0);
    1468                 :       3859 :         g_assert_true (child.type_info == instance->type_info);
    1469         [ +  + ]:       3859 :         if (child.data != NULL)  /* could be NULL if element is non-normal */
    1470                 :       3858 :           random_instance_assert (instance, child.data, child.size);
    1471                 :       3859 :         g_variant_type_info_unref (child.type_info);
    1472                 :            : 
    1473                 :       3859 :         flavoured_free (serialised.data, flavour);
    1474                 :            :       }
    1475                 :            :   }
    1476                 :            : 
    1477                 :       1000 :   g_variant_type_info_unref (type_info);
    1478                 :       1000 :   random_instance_free (instance);
    1479                 :       1000 :   align_free (data);
    1480                 :       1000 : }
    1481                 :            : 
    1482                 :            : static void
    1483                 :          1 : test_maybes (void)
    1484                 :            : {
    1485                 :            :   gsize i;
    1486                 :            : 
    1487         [ +  + ]:       1001 :   for (i = 0; i < 1000; i++)
    1488                 :       1000 :     test_maybe ();
    1489                 :            : 
    1490                 :          1 :   g_variant_type_info_assert_no_infos ();
    1491                 :          1 : }
    1492                 :            : 
    1493                 :            : static void
    1494                 :        100 : test_array (void)
    1495                 :            : {
    1496                 :            :   GVariantTypeInfo *element_info;
    1497                 :            :   GVariantTypeInfo *array_info;
    1498                 :            :   RandomInstance **instances;
    1499                 :            :   gsize needed_size;
    1500                 :            :   gsize offset_size;
    1501                 :            :   guint n_children;
    1502                 :            :   guchar *data;
    1503                 :            : 
    1504                 :            :   {
    1505                 :            :     gchar *element_type, *array_type;
    1506                 :            : 
    1507                 :        100 :     element_type = random_type_string ();
    1508                 :        100 :     array_type = g_strdup_printf ("a%s", element_type);
    1509                 :            : 
    1510                 :        100 :     element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
    1511                 :        100 :     array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
    1512                 :        100 :     g_assert_true (g_variant_type_info_element (array_info) == element_info);
    1513                 :            : 
    1514                 :        100 :     g_free (element_type);
    1515                 :        100 :     g_free (array_type);
    1516                 :            :   }
    1517                 :            : 
    1518                 :            :   {
    1519                 :            :     gsize i;
    1520                 :            : 
    1521                 :        100 :     n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
    1522                 :        100 :     instances = g_new (RandomInstance *, n_children);
    1523         [ +  + ]:       6957 :     for (i = 0; i < n_children; i++)
    1524                 :       6857 :       instances[i] = random_instance (element_info);
    1525                 :            :   }
    1526                 :            : 
    1527                 :        100 :   needed_size = g_variant_serialiser_needed_size (array_info,
    1528                 :            :                                                   random_instance_filler,
    1529                 :            :                                                   (gpointer *) instances,
    1530                 :            :                                                   n_children);
    1531                 :            : 
    1532                 :            :   {
    1533                 :            :     gsize element_fixed_size;
    1534                 :        100 :     gsize body_size = 0;
    1535                 :            :     gsize i;
    1536                 :            : 
    1537         [ +  + ]:       6957 :     for (i = 0; i < n_children; i++)
    1538                 :       6857 :       append_instance_size (instances[i], &body_size);
    1539                 :            : 
    1540                 :        100 :     g_variant_type_info_query (element_info, NULL, &element_fixed_size);
    1541                 :            : 
    1542         [ +  + ]:        100 :     if (!element_fixed_size)
    1543                 :            :       {
    1544                 :         51 :         offset_size = calculate_offset_size (body_size, n_children);
    1545                 :            : 
    1546         [ +  + ]:         51 :         if (offset_size == 0)
    1547                 :          1 :           offset_size = 1;
    1548                 :            :       }
    1549                 :            :     else
    1550                 :         49 :       offset_size = 0;
    1551                 :            : 
    1552                 :        100 :     g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
    1553                 :            :   }
    1554                 :            : 
    1555                 :            :   {
    1556                 :            :     guchar *offset_ptr, *body_ptr;
    1557                 :            :     gsize i;
    1558                 :            : 
    1559                 :        100 :     body_ptr = data = align_malloc (needed_size);
    1560                 :        100 :     offset_ptr = body_ptr + needed_size - offset_size * n_children;
    1561                 :            : 
    1562         [ +  + ]:       6957 :     for (i = 0; i < n_children; i++)
    1563                 :            :       {
    1564                 :       6857 :         append_instance_data (instances[i], &body_ptr);
    1565                 :       6857 :         append_offset (&offset_ptr, body_ptr - data, offset_size);
    1566                 :            :       }
    1567                 :            : 
    1568                 :        100 :     g_assert_true (body_ptr == data + needed_size - offset_size * n_children);
    1569                 :        100 :     g_assert_true (offset_ptr == data + needed_size);
    1570                 :            :   }
    1571                 :            : 
    1572                 :            :   {
    1573                 :            :     guint alignment;
    1574                 :            :     gsize flavour;
    1575                 :            :     gsize i;
    1576                 :            : 
    1577                 :        100 :     g_variant_type_info_query (array_info, &alignment, NULL);
    1578                 :        100 :     alignment = (alignment & ALIGN_BITS) + 1;
    1579                 :            : 
    1580         [ +  + ]:        513 :     for (flavour = 0; flavour < 8; flavour += alignment)
    1581                 :            :       {
    1582                 :        413 :         GVariantSerialised serialised = { 0, };
    1583                 :            : 
    1584                 :        413 :         serialised.type_info = array_info;
    1585                 :        413 :         serialised.data = flavoured_malloc (needed_size, flavour);
    1586                 :        413 :         serialised.size = needed_size;
    1587                 :        413 :         serialised.depth = 0;
    1588                 :        413 :         serialised.ordered_offsets_up_to = 0;
    1589                 :        413 :         serialised.checked_offsets_up_to = 0;
    1590                 :            : 
    1591                 :        413 :         g_variant_serialiser_serialise (serialised, random_instance_filler,
    1592                 :            :                                         (gpointer *) instances, n_children);
    1593                 :            : 
    1594         [ +  + ]:        413 :         if (serialised.size)
    1595                 :        405 :           g_assert_cmpint (memcmp (serialised.data, data, serialised.size), ==, 0);
    1596                 :            : 
    1597                 :        413 :         g_assert_cmpuint (g_variant_serialised_n_children (serialised), ==, n_children);
    1598                 :            : 
    1599         [ +  + ]:      29008 :         for (i = 0; i < n_children; i++)
    1600                 :            :           {
    1601                 :            :             GVariantSerialised child;
    1602                 :            : 
    1603                 :      28595 :             child = g_variant_serialised_get_child (serialised, i);
    1604                 :      28595 :             g_assert_true (child.type_info == instances[i]->type_info);
    1605         [ +  + ]:      28595 :             if (child.data != NULL)  /* could be NULL if element is non-normal */
    1606                 :      28586 :               random_instance_assert (instances[i], child.data, child.size);
    1607                 :      28595 :             g_variant_type_info_unref (child.type_info);
    1608                 :            :           }
    1609                 :            : 
    1610                 :        413 :         flavoured_free (serialised.data, flavour);
    1611                 :            :       }
    1612                 :            :   }
    1613                 :            : 
    1614                 :            :   {
    1615                 :            :     gsize i;
    1616                 :            : 
    1617         [ +  + ]:       6957 :     for (i = 0; i < n_children; i++)
    1618                 :       6857 :       random_instance_free (instances[i]);
    1619                 :        100 :     g_free (instances);
    1620                 :            :   }
    1621                 :            : 
    1622                 :        100 :   g_variant_type_info_unref (element_info);
    1623                 :        100 :   g_variant_type_info_unref (array_info);
    1624                 :        100 :   align_free (data);
    1625                 :        100 : }
    1626                 :            : 
    1627                 :            : static void
    1628                 :          1 : test_arrays (void)
    1629                 :            : {
    1630                 :            :   gsize i;
    1631                 :            : 
    1632         [ +  + ]:        101 :   for (i = 0; i < 100; i++)
    1633                 :        100 :     test_array ();
    1634                 :            : 
    1635                 :          1 :   g_variant_type_info_assert_no_infos ();
    1636                 :          1 : }
    1637                 :            : 
    1638                 :            : static void
    1639                 :        100 : test_tuple (void)
    1640                 :            : {
    1641                 :            :   GVariantTypeInfo *type_info;
    1642                 :            :   RandomInstance **instances;
    1643                 :            :   gboolean fixed_size;
    1644                 :            :   gsize needed_size;
    1645                 :            :   gsize offset_size;
    1646                 :            :   guint n_children;
    1647                 :            :   guint alignment;
    1648                 :            :   guchar *data;
    1649                 :            : 
    1650                 :        100 :   n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
    1651                 :        100 :   instances = g_new (RandomInstance *, n_children);
    1652                 :            : 
    1653                 :            :   {
    1654                 :            :     GString *type_string;
    1655                 :            :     gsize i;
    1656                 :            : 
    1657                 :        100 :     fixed_size = TRUE;
    1658                 :        100 :     alignment = 0;
    1659                 :            : 
    1660                 :        100 :     type_string = g_string_new ("(");
    1661         [ +  + ]:       5643 :     for (i = 0; i < n_children; i++)
    1662                 :            :       {
    1663                 :            :         const gchar *str;
    1664                 :            : 
    1665                 :       5543 :         instances[i] = random_instance (NULL);
    1666                 :            : 
    1667                 :       5543 :         alignment |= instances[i]->alignment;
    1668         [ +  + ]:       5543 :         if (!instances[i]->is_fixed_sized)
    1669                 :       2782 :           fixed_size = FALSE;
    1670                 :            : 
    1671                 :       5543 :         str = g_variant_type_info_get_type_string (instances[i]->type_info);
    1672                 :            :         g_string_append (type_string, str);
    1673                 :            :       }
    1674                 :            :     g_string_append_c (type_string, ')');
    1675                 :            : 
    1676                 :        100 :     type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
    1677                 :        100 :     g_string_free (type_string, TRUE);
    1678                 :            :   }
    1679                 :            : 
    1680                 :        100 :   needed_size = g_variant_serialiser_needed_size (type_info,
    1681                 :            :                                                   random_instance_filler,
    1682                 :            :                                                   (gpointer *) instances,
    1683                 :            :                                                   n_children);
    1684                 :            :   {
    1685                 :        100 :     gsize body_size = 0;
    1686                 :        100 :     gsize offsets = 0;
    1687                 :            :     gsize i;
    1688                 :            : 
    1689         [ +  + ]:       5643 :     for (i = 0; i < n_children; i++)
    1690                 :            :       {
    1691                 :       5543 :         append_instance_size (instances[i], &body_size);
    1692                 :            : 
    1693   [ +  +  +  + ]:       5543 :         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
    1694                 :       2733 :           offsets++;
    1695                 :            :       }
    1696                 :            : 
    1697         [ +  + ]:        100 :     if (fixed_size)
    1698                 :            :       {
    1699                 :          3 :         body_size += (-body_size) & alignment;
    1700                 :            : 
    1701                 :          3 :         g_assert_true ((body_size == 0) == (n_children == 0));
    1702         [ +  + ]:          3 :         if (n_children == 0)
    1703                 :          1 :           body_size = 1;
    1704                 :            :       }
    1705                 :            : 
    1706                 :        100 :     offset_size = calculate_offset_size (body_size, offsets);
    1707                 :        100 :     g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
    1708                 :            :   }
    1709                 :            : 
    1710                 :            :   {
    1711                 :            :     guchar *body_ptr;
    1712                 :            :     guchar *ofs_ptr;
    1713                 :            :     gsize i;
    1714                 :            : 
    1715                 :        100 :     body_ptr = data = align_malloc (needed_size);
    1716                 :        100 :     ofs_ptr = body_ptr + needed_size;
    1717                 :            : 
    1718         [ +  + ]:       5643 :     for (i = 0; i < n_children; i++)
    1719                 :            :       {
    1720                 :       5543 :         append_instance_data (instances[i], &body_ptr);
    1721                 :            : 
    1722   [ +  +  +  + ]:       5543 :         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
    1723                 :       2733 :           prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
    1724                 :            :       }
    1725                 :            : 
    1726         [ +  + ]:        100 :     if (fixed_size)
    1727                 :            :       {
    1728         [ -  + ]:          3 :         while (((gsize) body_ptr) & alignment)
    1729                 :          0 :           *body_ptr++ = '\0';
    1730                 :            : 
    1731                 :          3 :         g_assert_true ((body_ptr == data) == (n_children == 0));
    1732         [ +  + ]:          3 :         if (n_children == 0)
    1733                 :          1 :           *body_ptr++ = '\0';
    1734                 :            : 
    1735                 :            :       }
    1736                 :            : 
    1737                 :            : 
    1738                 :        100 :     g_assert_true (body_ptr == ofs_ptr);
    1739                 :            :   }
    1740                 :            : 
    1741                 :            :   {
    1742                 :            :     gsize flavour;
    1743                 :            :     gsize i;
    1744                 :            : 
    1745                 :        100 :     alignment = (alignment & ALIGN_BITS) + 1;
    1746                 :            : 
    1747         [ +  + ]:        211 :     for (flavour = 0; flavour < 8; flavour += alignment)
    1748                 :            :       {
    1749                 :        111 :         GVariantSerialised serialised = { 0, };
    1750                 :            : 
    1751                 :        111 :         serialised.type_info = type_info;
    1752                 :        111 :         serialised.data = flavoured_malloc (needed_size, flavour);
    1753                 :        111 :         serialised.size = needed_size;
    1754                 :        111 :         serialised.depth = 0;
    1755                 :        111 :         serialised.ordered_offsets_up_to = 0;
    1756                 :        111 :         serialised.checked_offsets_up_to = 0;
    1757                 :            : 
    1758                 :        111 :         g_variant_serialiser_serialise (serialised, random_instance_filler,
    1759                 :            :                                         (gpointer *) instances, n_children);
    1760                 :            : 
    1761         [ +  - ]:        111 :         if (serialised.size)
    1762                 :        111 :           g_assert_cmpint (memcmp (serialised.data, data, serialised.size), ==, 0);
    1763                 :            : 
    1764                 :        111 :         g_assert_cmpuint (g_variant_serialised_n_children (serialised), ==, n_children);
    1765                 :            : 
    1766         [ +  + ]:       5658 :         for (i = 0; i < n_children; i++)
    1767                 :            :           {
    1768                 :            :             GVariantSerialised child;
    1769                 :            : 
    1770                 :       5547 :             child = g_variant_serialised_get_child (serialised, i);
    1771                 :       5547 :             g_assert_true (child.type_info == instances[i]->type_info);
    1772         [ +  + ]:       5547 :             if (child.data != NULL)  /* could be NULL if element is non-normal */
    1773                 :       5543 :               random_instance_assert (instances[i], child.data, child.size);
    1774                 :       5547 :             g_variant_type_info_unref (child.type_info);
    1775                 :            :           }
    1776                 :            : 
    1777                 :        111 :         flavoured_free (serialised.data, flavour);
    1778                 :            :       }
    1779                 :            :   }
    1780                 :            : 
    1781                 :            :   {
    1782                 :            :     gsize i;
    1783                 :            : 
    1784         [ +  + ]:       5643 :     for (i = 0; i < n_children; i++)
    1785                 :       5543 :       random_instance_free (instances[i]);
    1786                 :        100 :     g_free (instances);
    1787                 :            :   }
    1788                 :            : 
    1789                 :        100 :   g_variant_type_info_unref (type_info);
    1790                 :        100 :   align_free (data);
    1791                 :        100 : }
    1792                 :            : 
    1793                 :            : static void
    1794                 :          1 : test_tuples (void)
    1795                 :            : {
    1796                 :            :   gsize i;
    1797                 :            : 
    1798         [ +  + ]:        101 :   for (i = 0; i < 100; i++)
    1799                 :        100 :     test_tuple ();
    1800                 :            : 
    1801                 :          1 :   g_variant_type_info_assert_no_infos ();
    1802                 :          1 : }
    1803                 :            : 
    1804                 :            : static void
    1805                 :        100 : test_variant (void)
    1806                 :            : {
    1807                 :            :   GVariantTypeInfo *type_info;
    1808                 :            :   RandomInstance *instance;
    1809                 :            :   const gchar *type_string;
    1810                 :            :   gsize needed_size;
    1811                 :            :   guchar *data;
    1812                 :            :   gsize len;
    1813                 :            : 
    1814                 :        100 :   type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
    1815                 :        100 :   instance = random_instance (NULL);
    1816                 :            : 
    1817                 :        100 :   type_string = g_variant_type_info_get_type_string (instance->type_info);
    1818                 :        100 :   len = strlen (type_string);
    1819                 :            : 
    1820                 :        100 :   needed_size = g_variant_serialiser_needed_size (type_info,
    1821                 :            :                                                   random_instance_filler,
    1822                 :            :                                                   (gpointer *) &instance, 1);
    1823                 :            : 
    1824                 :        100 :   g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
    1825                 :            : 
    1826                 :            :   {
    1827                 :            :     guchar *ptr;
    1828                 :            : 
    1829                 :        100 :     ptr = data = align_malloc (needed_size);
    1830                 :        100 :     append_instance_data (instance, &ptr);
    1831                 :        100 :     *ptr++ = '\0';
    1832                 :        100 :     memcpy (ptr, type_string, len);
    1833                 :        100 :     ptr += len;
    1834                 :            : 
    1835                 :        100 :     g_assert_true (data + needed_size == ptr);
    1836                 :            :   }
    1837                 :            : 
    1838                 :            :   {
    1839                 :            :     gsize alignment;
    1840                 :            :     gsize flavour;
    1841                 :            : 
    1842                 :            :     /* variants are always 8-aligned */
    1843                 :        100 :     alignment = ALIGN_BITS + 1;
    1844                 :            : 
    1845         [ +  + ]:        200 :     for (flavour = 0; flavour < 8; flavour += alignment)
    1846                 :            :       {
    1847                 :        100 :         GVariantSerialised serialised = { 0, };
    1848                 :            :         GVariantSerialised child;
    1849                 :            : 
    1850                 :        100 :         serialised.type_info = type_info;
    1851                 :        100 :         serialised.data = flavoured_malloc (needed_size, flavour);
    1852                 :        100 :         serialised.size = needed_size;
    1853                 :        100 :         serialised.depth = 0;
    1854                 :        100 :         serialised.ordered_offsets_up_to = 0;
    1855                 :        100 :         serialised.checked_offsets_up_to = 0;
    1856                 :            : 
    1857                 :        100 :         g_variant_serialiser_serialise (serialised, random_instance_filler,
    1858                 :            :                                         (gpointer *) &instance, 1);
    1859                 :            : 
    1860         [ +  - ]:        100 :         if (serialised.size)
    1861                 :        100 :           g_assert_cmpint (memcmp (serialised.data, data, serialised.size), ==, 0);
    1862                 :            : 
    1863                 :        100 :         g_assert_cmpuint (g_variant_serialised_n_children (serialised), ==, 1);
    1864                 :            : 
    1865                 :        100 :         child = g_variant_serialised_get_child (serialised, 0);
    1866                 :        100 :         g_assert_true (child.type_info == instance->type_info);
    1867                 :        100 :         random_instance_check (instance, child.data, child.size);
    1868                 :            : 
    1869                 :        100 :         g_variant_type_info_unref (child.type_info);
    1870                 :        100 :         flavoured_free (serialised.data, flavour);
    1871                 :            :       }
    1872                 :            :   }
    1873                 :            : 
    1874                 :        100 :   g_variant_type_info_unref (type_info);
    1875                 :        100 :   random_instance_free (instance);
    1876                 :        100 :   align_free (data);
    1877                 :        100 : }
    1878                 :            : 
    1879                 :            : static void
    1880                 :          1 : test_variants (void)
    1881                 :            : {
    1882                 :            :   gsize i;
    1883                 :            : 
    1884         [ +  + ]:        101 :   for (i = 0; i < 100; i++)
    1885                 :        100 :     test_variant ();
    1886                 :            : 
    1887                 :          1 :   g_variant_type_info_assert_no_infos ();
    1888                 :          1 : }
    1889                 :            : 
    1890                 :            : static void
    1891                 :          1 : test_strings (void)
    1892                 :            : {
    1893                 :            :   struct {
    1894                 :            :     guint flags;
    1895                 :            :     guint size;
    1896                 :            :     gconstpointer data;
    1897                 :          1 :   } test_cases[] = {
    1898                 :            : #define is_nval           0
    1899                 :            : #define is_string         1
    1900                 :            : #define is_objpath        is_string | 2
    1901                 :            : #define is_sig            is_string | 4
    1902                 :            :     { is_sig,       1, "" },
    1903                 :            :     { is_nval,      0, NULL },
    1904                 :            :     { is_nval,     13, "hello\xffworld!" },
    1905                 :            :     { is_string,   13, "hello world!" },
    1906                 :            :     { is_nval,     13, "hello world\0" },
    1907                 :            :     { is_nval,     13, "hello\0world!" },
    1908                 :            :     { is_nval,     12, "hello world!" },
    1909                 :            :     { is_nval,     13, "hello world!\xff" },
    1910                 :            : 
    1911                 :            :     { is_objpath,   2, "/" },
    1912                 :            :     { is_objpath,   3, "/a" },
    1913                 :            :     { is_string,    3, "//" },
    1914                 :            :     { is_objpath,  11, "/some/path" },
    1915                 :            :     { is_string,   12, "/some/path/" },
    1916                 :            :     { is_nval,     11, "/some\0path" },
    1917                 :            :     { is_string,   11, "/some\\path" },
    1918                 :            :     { is_string,   12, "/some//path" },
    1919                 :            :     { is_string,   12, "/some-/path" },
    1920                 :            : 
    1921                 :            :     { is_sig,       2, "i" },
    1922                 :            :     { is_sig,       2, "s" },
    1923                 :            :     { is_sig,       5, "(si)" },
    1924                 :            :     { is_string,    4, "(si" },
    1925                 :            :     { is_string,    2, "*" },
    1926                 :            :     { is_sig,       3, "ai" },
    1927                 :            :     { is_string,    3, "mi" },
    1928                 :            :     { is_string,    2, "r" },
    1929                 :            :     { is_sig,      15, "(yyy{sv}ssiai)" },
    1930                 :            :     { is_string,   16, "(yyy{yv}ssiai))" },
    1931                 :            :     { is_string,   15, "(yyy{vv}ssiai)" },
    1932                 :            :     { is_string,   15, "(yyy{sv)ssiai}" }
    1933                 :            :   };
    1934                 :            :   gsize i;
    1935                 :            : 
    1936         [ +  + ]:         30 :   for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
    1937                 :            :     {
    1938                 :            :       guint flags;
    1939                 :            : 
    1940                 :         58 :       flags = g_variant_serialiser_is_string (test_cases[i].data,
    1941                 :         29 :                                               test_cases[i].size)
    1942                 :         29 :         ? 1 : 0;
    1943                 :            : 
    1944                 :         58 :       flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
    1945                 :         29 :                                                     test_cases[i].size)
    1946         [ +  + ]:         29 :         ? 2 : 0;
    1947                 :            : 
    1948                 :         58 :       flags |= g_variant_serialiser_is_signature (test_cases[i].data,
    1949                 :         29 :                                                   test_cases[i].size)
    1950         [ +  + ]:         29 :         ? 4 : 0;
    1951                 :            : 
    1952                 :         29 :       g_assert_cmpuint (flags, ==, test_cases[i].flags);
    1953                 :            :     }
    1954                 :          1 : }
    1955                 :            : 
    1956                 :            : typedef struct _TreeInstance TreeInstance;
    1957                 :            : struct _TreeInstance
    1958                 :            : {
    1959                 :            :   GVariantTypeInfo *info;
    1960                 :            : 
    1961                 :            :   TreeInstance **children;
    1962                 :            :   gsize n_children;
    1963                 :            : 
    1964                 :            :   union {
    1965                 :            :     guint64 integer;
    1966                 :            :     gdouble floating;
    1967                 :            :     gchar string[200];
    1968                 :            :   } data;
    1969                 :            :   gsize data_size;
    1970                 :            : };
    1971                 :            : 
    1972                 :            : static GVariantType *
    1973                 :      30744 : make_random_definite_type (int depth)
    1974                 :            : {
    1975                 :            :   GString *description;
    1976                 :            :   GString *type_string;
    1977                 :            :   GVariantType *type;
    1978                 :            : 
    1979                 :      30744 :   description = g_string_new (NULL);
    1980                 :      30744 :   type_string = g_string_new (NULL);
    1981                 :      30744 :   type = append_type_string (type_string, description, TRUE, depth);
    1982                 :      30744 :   g_string_free (description, TRUE);
    1983                 :      30744 :   g_string_free (type_string, TRUE);
    1984                 :            : 
    1985                 :      30744 :   return type;
    1986                 :            : }
    1987                 :            : 
    1988                 :            : static void
    1989                 :    1001071 : make_random_string (gchar              *string,
    1990                 :            :                     gsize               size,
    1991                 :            :                     const GVariantType *type)
    1992                 :            : {
    1993                 :            :   gsize i;
    1994                 :            : 
    1995                 :            :   /* create strings that are valid signature strings */
    1996                 :            : #define good_chars "bynqiuxthdsog"
    1997                 :            : 
    1998         [ +  + ]:  104710584 :   for (i = 0; i < size - 1; i++)
    1999                 :  103709513 :     string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
    2000                 :    1001071 :   string[i] = '\0';
    2001                 :            : 
    2002                 :            :   /* in case we need an object path, prefix a '/' */
    2003         [ +  + ]:    1001071 :   if (*g_variant_type_peek_string (type) == 'o')
    2004                 :     392803 :     string[0] = '/';
    2005                 :            : 
    2006                 :            : #undef good_chars
    2007                 :    1001071 : }
    2008                 :            : 
    2009                 :            : static TreeInstance *
    2010                 :    2562126 : tree_instance_new (const GVariantType *type,
    2011                 :            :                    int                 depth)
    2012                 :            : {
    2013                 :    2562126 :   const GVariantType *child_type = NULL;
    2014                 :    2562126 :   GVariantType *mytype = NULL;
    2015                 :            :   TreeInstance *instance;
    2016                 :            :   gboolean is_tuple_type;
    2017                 :            : 
    2018         [ +  + ]:    2562126 :   if (type == NULL)
    2019                 :      30744 :     type = mytype = make_random_definite_type (depth);
    2020                 :            : 
    2021                 :    2562126 :   instance = g_slice_new (TreeInstance);
    2022                 :    2562126 :   instance->info = g_variant_type_info_get (type);
    2023                 :    2562126 :   instance->children = NULL;
    2024                 :    2562126 :   instance->n_children = 0;
    2025                 :    2562126 :   instance->data_size = 0;
    2026                 :            : 
    2027                 :    2562126 :   is_tuple_type = FALSE;
    2028                 :            : 
    2029   [ +  +  +  +  :    2562126 :   switch (*g_variant_type_peek_string (type))
          +  +  +  +  +  
                +  +  - ]
    2030                 :            :     {
    2031                 :      18175 :     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
    2032                 :      18175 :       instance->n_children = g_test_rand_int_range (0, 2);
    2033                 :      18175 :       child_type = g_variant_type_element (type);
    2034                 :      18175 :       break;
    2035                 :            : 
    2036                 :      35350 :     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
    2037                 :      35350 :       instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
    2038                 :      35350 :       child_type = g_variant_type_element (type);
    2039                 :      35350 :       break;
    2040                 :            : 
    2041                 :      40003 :     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
    2042                 :            :     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
    2043                 :      40003 :       instance->n_children = g_variant_type_n_items (type);
    2044                 :      40003 :       child_type = g_variant_type_first (type);
    2045                 :      40003 :       is_tuple_type = TRUE;
    2046                 :      40003 :       break;
    2047                 :            : 
    2048                 :      24718 :     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
    2049                 :      24718 :       instance->n_children = 1;
    2050                 :      24718 :       child_type = NULL;
    2051                 :      24718 :       break;
    2052                 :            : 
    2053                 :      53726 :     case 'b':
    2054                 :      53726 :       instance->data.integer = g_test_rand_int_range (0, 2);
    2055                 :      53726 :       instance->data_size = 1;
    2056                 :      53726 :       break;
    2057                 :            : 
    2058                 :      61213 :     case 'y':
    2059                 :      61213 :       instance->data.integer = g_test_rand_int ();
    2060                 :      61213 :       instance->data_size = 1;
    2061                 :      61213 :       break;
    2062                 :            : 
    2063                 :     109619 :     case 'n': case 'q':
    2064                 :     109619 :       instance->data.integer = g_test_rand_int ();
    2065                 :     109619 :       instance->data_size = 2;
    2066                 :     109619 :       break;
    2067                 :            : 
    2068                 :     580262 :     case 'i': case 'u': case 'h':
    2069                 :     580262 :       instance->data.integer = g_test_rand_int ();
    2070                 :     580262 :       instance->data_size = 4;
    2071                 :     580262 :       break;
    2072                 :            : 
    2073                 :     114032 :     case 'x': case 't':
    2074                 :     114032 :       instance->data.integer = g_test_rand_int ();
    2075                 :     114032 :       instance->data.integer <<= 32;
    2076                 :     114032 :       instance->data.integer |= (guint32) g_test_rand_int ();
    2077                 :     114032 :       instance->data_size = 8;
    2078                 :     114032 :       break;
    2079                 :            : 
    2080                 :     523957 :     case 'd':
    2081                 :     523957 :       instance->data.floating = g_test_rand_double ();
    2082                 :     523957 :       instance->data_size = 8;
    2083                 :     523957 :       break;
    2084                 :            : 
    2085                 :    1001071 :     case 's': case 'o': case 'g':
    2086                 :    1001071 :       instance->data_size = g_test_rand_int_range (10, 200);
    2087                 :    1001071 :       make_random_string (instance->data.string, instance->data_size, type);
    2088                 :    1001071 :       break;
    2089                 :            :     }
    2090                 :            : 
    2091         [ +  + ]:    2562126 :   if (instance->data_size == 0)
    2092                 :            :     /* no data -> it is a container */
    2093                 :            :     {
    2094                 :            :       gsize i;
    2095                 :            : 
    2096                 :     118246 :       instance->children = g_new (TreeInstance *, instance->n_children);
    2097                 :            : 
    2098         [ +  + ]:    2674346 :       for (i = 0; i < instance->n_children; i++)
    2099                 :            :         {
    2100                 :    2556100 :           instance->children[i] = tree_instance_new (child_type, depth - 1);
    2101                 :            : 
    2102         [ +  + ]:    2556100 :           if (is_tuple_type)
    2103                 :     271903 :             child_type = g_variant_type_next (child_type);
    2104                 :            :         }
    2105                 :            : 
    2106                 :     118246 :       g_assert_true (!is_tuple_type || child_type == NULL);
    2107                 :            :     }
    2108                 :            : 
    2109                 :    2562126 :   g_variant_type_free (mytype);
    2110                 :            : 
    2111                 :    2562126 :   return instance;
    2112                 :            : }
    2113                 :            : 
    2114                 :            : static void
    2115                 :    2562126 : tree_instance_free (TreeInstance *instance)
    2116                 :            : {
    2117                 :            :   gsize i;
    2118                 :            : 
    2119                 :    2562126 :   g_variant_type_info_unref (instance->info);
    2120         [ +  + ]:    5118226 :   for (i = 0; i < instance->n_children; i++)
    2121                 :    2556100 :     tree_instance_free (instance->children[i]);
    2122                 :    2562126 :   g_free (instance->children);
    2123                 :    2562126 :   g_slice_free (TreeInstance, instance);
    2124                 :    2562126 : }
    2125                 :            : 
    2126                 :            : static gboolean i_am_writing_byteswapped;
    2127                 :            : 
    2128                 :            : static void
    2129                 :    7022468 : tree_filler (GVariantSerialised *serialised,
    2130                 :            :              gpointer            data)
    2131                 :            : {
    2132                 :    7022468 :   TreeInstance *instance = data;
    2133                 :            : 
    2134         [ +  + ]:    7022468 :   if (serialised->type_info == NULL)
    2135                 :    5770425 :     serialised->type_info = instance->info;
    2136                 :            : 
    2137                 :    7022468 :   serialised->depth = 0;
    2138                 :            : 
    2139         [ +  + ]:    7022468 :   if (instance->data_size == 0)
    2140                 :            :     /* is a container */
    2141                 :            :     {
    2142         [ +  + ]:     362307 :       if (serialised->size == 0)
    2143                 :     347748 :         serialised->size =
    2144                 :     347748 :           g_variant_serialiser_needed_size (instance->info, tree_filler,
    2145                 :     347748 :                                             (gpointer *) instance->children,
    2146                 :            :                                             instance->n_children);
    2147                 :            : 
    2148         [ +  + ]:     362307 :       if (serialised->data)
    2149                 :     135962 :         g_variant_serialiser_serialise (*serialised, tree_filler,
    2150                 :     135962 :                                         (gpointer *) instance->children,
    2151                 :            :                                         instance->n_children);
    2152                 :            :     }
    2153                 :            :   else
    2154                 :            :     /* it is a leaf */
    2155                 :            :     {
    2156         [ +  + ]:    6660161 :       if (serialised->size == 0)
    2157                 :    5413154 :         serialised->size = instance->data_size;
    2158                 :            : 
    2159         [ +  + ]:    6660161 :       if (serialised->data)
    2160                 :            :         {
    2161   [ +  +  +  +  :    2808623 :           switch (instance->data_size)
                      + ]
    2162                 :            :             {
    2163                 :     171420 :             case 1:
    2164                 :     171420 :               *serialised->data = instance->data.integer;
    2165                 :     171420 :               break;
    2166                 :            : 
    2167                 :     118759 :             case 2:
    2168                 :            :               {
    2169                 :     118759 :                 guint16 value = instance->data.integer;
    2170                 :            : 
    2171         [ +  + ]:     118759 :                 if (i_am_writing_byteswapped)
    2172                 :      25662 :                   value = GUINT16_SWAP_LE_BE (value);
    2173                 :            : 
    2174                 :     118759 :                 *(guint16 *) serialised->data = value;
    2175                 :            :               }
    2176                 :     118759 :               break;
    2177                 :            : 
    2178                 :     591063 :             case 4:
    2179                 :            :               {
    2180                 :     591063 :                 guint32 value = instance->data.integer;
    2181                 :            : 
    2182         [ +  + ]:     591063 :                 if (i_am_writing_byteswapped)
    2183                 :      24664 :                   value = GUINT32_SWAP_LE_BE (value);
    2184                 :            : 
    2185                 :     591063 :                 *(guint32 *) serialised->data = value;
    2186                 :            :               }
    2187                 :     591063 :               break;
    2188                 :            : 
    2189                 :     651254 :             case 8:
    2190                 :            :               {
    2191                 :     651254 :                 guint64 value = instance->data.integer;
    2192                 :            : 
    2193         [ +  + ]:     651254 :                 if (i_am_writing_byteswapped)
    2194                 :      38060 :                   value = GUINT64_SWAP_LE_BE (value);
    2195                 :            : 
    2196                 :     651254 :                 *(guint64 *) serialised->data = value;
    2197                 :            :               }
    2198                 :     651254 :               break;
    2199                 :            : 
    2200                 :    1276127 :             default:
    2201                 :    1276127 :               memcpy (serialised->data,
    2202                 :    1276127 :                       instance->data.string,
    2203                 :            :                       instance->data_size);
    2204                 :    1276127 :               break;
    2205                 :            :             }
    2206                 :            :         }
    2207                 :            :     }
    2208                 :    7022468 : }
    2209                 :            : 
    2210                 :            : static gboolean
    2211                 :    1495132 : check_tree (TreeInstance       *instance,
    2212                 :            :             GVariantSerialised  serialised)
    2213                 :            : {
    2214         [ +  + ]:    1495132 :   if (instance->info != serialised.type_info)
    2215                 :        115 :     return FALSE;
    2216                 :            : 
    2217         [ +  + ]:    1495017 :   if (instance->data_size == 0)
    2218                 :            :     /* is a container */
    2219                 :            :     {
    2220                 :            :       gsize i;
    2221                 :            : 
    2222                 :      80135 :       if (g_variant_serialised_n_children (serialised) !=
    2223         [ +  + ]:      80135 :           instance->n_children)
    2224                 :         50 :         return FALSE;
    2225                 :            : 
    2226         [ +  + ]:    1572234 :       for (i = 0; i < instance->n_children; i++)
    2227                 :            :         {
    2228                 :            :           GVariantSerialised child;
    2229                 :    1493190 :           gpointer data = NULL;
    2230                 :            :           gboolean ok;
    2231                 :            : 
    2232                 :    1493190 :           child = g_variant_serialised_get_child (serialised, i);
    2233   [ +  +  +  + ]:    1493190 :           if (child.size && child.data == NULL)
    2234                 :        119 :             child.data = data = g_malloc0 (child.size);
    2235                 :    1493190 :           ok = check_tree (instance->children[i], child);
    2236                 :    1493190 :           g_variant_type_info_unref (child.type_info);
    2237                 :    1493190 :           g_free (data);
    2238                 :            : 
    2239         [ +  + ]:    1493190 :           if (!ok)
    2240                 :       1041 :             return FALSE;
    2241                 :            :         }
    2242                 :            : 
    2243                 :      79044 :       return TRUE;
    2244                 :            :     }
    2245                 :            :   else
    2246                 :            :     /* it is a leaf */
    2247                 :            :     {
    2248   [ +  +  +  +  :    1414882 :       switch (instance->data_size)
                      + ]
    2249                 :            :         {
    2250                 :      70202 :         case 1:
    2251                 :      70202 :           g_assert_cmpuint (serialised.size, ==, 1);
    2252                 :      70202 :           return *(guint8 *) serialised.data ==
    2253                 :      70202 :                   (guint8) instance->data.integer;
    2254                 :            : 
    2255                 :      80860 :         case 2:
    2256                 :      80860 :           g_assert_cmpuint (serialised.size, ==, 2);
    2257                 :      80860 :           return *(guint16 *) serialised.data ==
    2258                 :      80860 :                   (guint16) instance->data.integer;
    2259                 :            : 
    2260                 :     554618 :         case 4:
    2261                 :     554618 :           g_assert_cmpuint (serialised.size, ==, 4);
    2262                 :     554618 :           return *(guint32 *) serialised.data ==
    2263                 :     554618 :                   (guint32) instance->data.integer;
    2264                 :            : 
    2265                 :     594480 :         case 8:
    2266                 :     594480 :           g_assert_cmpuint (serialised.size, ==, 8);
    2267                 :     594480 :           return *(guint64 *) serialised.data ==
    2268                 :     594480 :                   (guint64) instance->data.integer;
    2269                 :            : 
    2270                 :     114722 :         default:
    2271         [ +  + ]:     114722 :           if (serialised.size != instance->data_size)
    2272                 :         15 :             return FALSE;
    2273                 :            : 
    2274                 :     114707 :           return memcmp (serialised.data,
    2275                 :     114707 :                          instance->data.string,
    2276                 :     114707 :                          instance->data_size) == 0;
    2277                 :            :         }
    2278                 :            :     }
    2279                 :            : }
    2280                 :            : 
    2281                 :            : static void
    2282                 :       1600 : serialise_tree (TreeInstance       *tree,
    2283                 :            :                 GVariantSerialised *serialised)
    2284                 :            : {
    2285                 :       1600 :   GVariantSerialised empty = {0, };
    2286                 :            : 
    2287                 :       1600 :   *serialised = empty;
    2288                 :       1600 :   tree_filler (serialised, tree);
    2289                 :       1600 :   serialised->data = g_malloc (serialised->size);
    2290                 :       1600 :   tree_filler (serialised, tree);
    2291                 :       1600 : }
    2292                 :            : 
    2293                 :            : static void
    2294                 :        200 : test_byteswap (void)
    2295                 :            : {
    2296                 :        200 :   GVariantSerialised one = { 0, }, two = { 0, }, three = { 0, };
    2297                 :            :   TreeInstance *tree;
    2298                 :        200 :   GVariant *one_variant = NULL;
    2299                 :        200 :   GVariant *two_variant = NULL;
    2300                 :        200 :   GVariant *two_byteswapped = NULL;
    2301                 :        200 :   GVariant *three_variant = NULL;
    2302                 :        200 :   GVariant *three_byteswapped = NULL;
    2303                 :        200 :   guint8 *three_data_copy = NULL;
    2304                 :        200 :   gsize three_size_copy = 0;
    2305                 :            : 
    2306                 :            :   /* Write a tree out twice, once normally and once byteswapped. */
    2307                 :        200 :   tree = tree_instance_new (NULL, 3);
    2308                 :        200 :   serialise_tree (tree, &one);
    2309                 :            : 
    2310                 :        200 :   one_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (one.type_info)),
    2311                 :        200 :                                          one.data, one.size, FALSE, NULL, NULL);
    2312                 :            : 
    2313                 :        200 :   i_am_writing_byteswapped = TRUE;
    2314                 :        200 :   serialise_tree (tree, &two);
    2315                 :        200 :   serialise_tree (tree, &three);
    2316                 :        200 :   i_am_writing_byteswapped = FALSE;
    2317                 :            : 
    2318                 :            :   /* Swap the first byteswapped one back using the function we want to test. */
    2319                 :        200 :   two_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (two.type_info)),
    2320                 :        200 :                                          two.data, two.size, FALSE, NULL, NULL);
    2321                 :        200 :   two_byteswapped = g_variant_byteswap (two_variant);
    2322                 :            : 
    2323                 :            :   /* Make the second byteswapped one non-normal (hopefully), and then byteswap
    2324                 :            :    * it back using the function we want to test in its non-normal mode.
    2325                 :            :    * This might not work because it’s not necessarily possible to make an
    2326                 :            :    * arbitrary random variant non-normal. Adding a single zero byte to the end
    2327                 :            :    * often makes something non-normal but still readable. */
    2328                 :        200 :   three_size_copy = three.size + 1;
    2329                 :        200 :   three_data_copy = g_malloc (three_size_copy);
    2330                 :        200 :   memcpy (three_data_copy, three.data, three.size);
    2331                 :        200 :   three_data_copy[three.size] = '\0';
    2332                 :            : 
    2333                 :        200 :   three_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (three.type_info)),
    2334                 :            :                                            three_data_copy, three_size_copy, FALSE, NULL, NULL);
    2335                 :        200 :   three_byteswapped = g_variant_byteswap (three_variant);
    2336                 :            : 
    2337                 :            :   /* Check they’re the same. We can always compare @one_variant and
    2338                 :            :    * @two_byteswapped. We can only compare @two_byteswapped and
    2339                 :            :    * @three_byteswapped if @two_variant and @three_variant are equal: in that
    2340                 :            :    * case, the corruption to @three_variant was enough to make it non-normal but
    2341                 :            :    * not enough to change its value. */
    2342                 :        200 :   g_assert_cmpvariant (one_variant, two_byteswapped);
    2343                 :            : 
    2344         [ +  + ]:        200 :   if (g_variant_equal (two_variant, three_variant))
    2345                 :          8 :     g_assert_cmpvariant (two_byteswapped, three_byteswapped);
    2346                 :            : 
    2347                 :        200 :   g_variant_unref (three_byteswapped);
    2348                 :        200 :   g_variant_unref (three_variant);
    2349                 :        200 :   g_variant_unref (two_byteswapped);
    2350                 :        200 :   g_variant_unref (two_variant);
    2351                 :        200 :   g_variant_unref (one_variant);
    2352                 :        200 :   tree_instance_free (tree);
    2353                 :        200 :   g_free (one.data);
    2354                 :        200 :   g_free (two.data);
    2355                 :        200 :   g_free (three.data);
    2356                 :        200 :   g_free (three_data_copy);
    2357                 :        200 : }
    2358                 :            : 
    2359                 :            : static void
    2360                 :          1 : test_byteswaps (void)
    2361                 :            : {
    2362                 :            :   int i;
    2363                 :            : 
    2364         [ +  + ]:        201 :   for (i = 0; i < 200; i++)
    2365                 :        200 :     test_byteswap ();
    2366                 :            : 
    2367                 :          1 :   g_variant_type_info_assert_no_infos ();
    2368                 :          1 : }
    2369                 :            : 
    2370                 :            : static void
    2371                 :          1 : test_serialiser_children (void)
    2372                 :            : {
    2373                 :            :   GBytes *data1, *data2;
    2374                 :            :   GVariant *child1, *child2;
    2375                 :          1 :   GVariantType *mv_type = g_variant_type_new_maybe (G_VARIANT_TYPE_VARIANT);
    2376                 :            :   GVariant *variant, *child;
    2377                 :            : 
    2378                 :          1 :   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1865");
    2379                 :          1 :   g_test_summary ("Test that getting a child variant before and after "
    2380                 :            :                   "serialisation of the parent works");
    2381                 :            : 
    2382                 :            :   /* Construct a variable sized array containing a child which serializes to a
    2383                 :            :    * zero-length bytestring. */
    2384                 :          1 :   child = g_variant_new_maybe (G_VARIANT_TYPE_VARIANT, NULL);
    2385                 :          1 :   variant = g_variant_new_array (mv_type, &child, 1);
    2386                 :            : 
    2387                 :            :   /* Get the child before serializing. */
    2388                 :          1 :   child1 = g_variant_get_child_value (variant, 0);
    2389                 :          1 :   data1 = g_variant_get_data_as_bytes (child1);
    2390                 :            : 
    2391                 :            :   /* Serialize the parent variant. */
    2392                 :          1 :   g_variant_get_data (variant);
    2393                 :            : 
    2394                 :            :   /* Get the child again after serializing — this uses a different code path. */
    2395                 :          1 :   child2 = g_variant_get_child_value (variant, 0);
    2396                 :          1 :   data2 = g_variant_get_data_as_bytes (child2);
    2397                 :            : 
    2398                 :            :   /* Check things are equal. */
    2399                 :          1 :   g_assert_cmpvariant (child1, child2);
    2400                 :          1 :   g_assert_true (g_bytes_equal (data1, data2));
    2401                 :            : 
    2402                 :          1 :   g_variant_unref (child2);
    2403                 :          1 :   g_variant_unref (child1);
    2404                 :          1 :   g_variant_unref (variant);
    2405                 :          1 :   g_bytes_unref (data2);
    2406                 :          1 :   g_bytes_unref (data1);
    2407                 :          1 :   g_variant_type_free (mv_type);
    2408                 :          1 : }
    2409                 :            : 
    2410                 :            : static void
    2411                 :       1000 : test_fuzz (gdouble *fuzziness)
    2412                 :            : {
    2413                 :       1000 :   GVariantSerialised serialised = { 0, };
    2414                 :            :   TreeInstance *tree;
    2415                 :            : 
    2416                 :            :   /* make an instance */
    2417                 :       1000 :   tree = tree_instance_new (NULL, 3);
    2418                 :            : 
    2419                 :            :   /* serialize it */
    2420                 :       1000 :   serialise_tree (tree, &serialised);
    2421                 :            : 
    2422                 :       1000 :   g_assert_true (g_variant_serialised_is_normal (serialised));
    2423                 :       1000 :   g_assert_true (check_tree (tree, serialised));
    2424                 :            : 
    2425         [ +  + ]:       1000 :   if (serialised.size)
    2426                 :            :     {
    2427                 :        942 :       gboolean fuzzed = FALSE;
    2428                 :            :       gboolean a, b;
    2429                 :            : 
    2430         [ +  + ]:       6608 :       while (!fuzzed)
    2431                 :            :         {
    2432                 :            :           gsize i;
    2433                 :            : 
    2434         [ +  + ]:   19777603 :           for (i = 0; i < serialised.size; i++)
    2435         [ +  + ]:   19771937 :             if (randomly (*fuzziness))
    2436                 :            :               {
    2437                 :    2371411 :                 serialised.data[i] += g_test_rand_int_range (1, 256);
    2438                 :    2371411 :                 fuzzed = TRUE;
    2439                 :            :               }
    2440                 :            :         }
    2441                 :            : 
    2442                 :            :       /* at least one byte in the serialized data has changed.
    2443                 :            :        *
    2444                 :            :        * this means that at least one of the following is true:
    2445                 :            :        *
    2446                 :            :        *    - the serialized data now represents a different value:
    2447                 :            :        *        check_tree() will return FALSE
    2448                 :            :        *
    2449                 :            :        *    - the serialized data is in non-normal form:
    2450                 :            :        *        g_variant_serialiser_is_normal() will return FALSE
    2451                 :            :        *
    2452                 :            :        * we always do both checks to increase exposure of the serializer
    2453                 :            :        * to corrupt data.
    2454                 :            :        */
    2455                 :        942 :       a = g_variant_serialised_is_normal (serialised);
    2456                 :        942 :       b = check_tree (tree, serialised);
    2457                 :            : 
    2458                 :        942 :       g_assert_true (!a || !b);
    2459                 :            :     }
    2460                 :            : 
    2461                 :       1000 :   tree_instance_free (tree);
    2462                 :       1000 :   g_free (serialised.data);
    2463                 :       1000 : }
    2464                 :            : 
    2465                 :            : 
    2466                 :            : static void
    2467                 :          5 : test_fuzzes (gpointer data)
    2468                 :            : {
    2469                 :            :   gdouble fuzziness;
    2470                 :            :   int i;
    2471                 :            : 
    2472                 :          5 :   fuzziness = GPOINTER_TO_INT (data) / 100.;
    2473                 :            : 
    2474         [ +  + ]:       1005 :   for (i = 0; i < 200; i++)
    2475                 :       1000 :     test_fuzz (&fuzziness);
    2476                 :            : 
    2477                 :          5 :   g_variant_type_info_assert_no_infos ();
    2478                 :          5 : }
    2479                 :            : 
    2480                 :            : static GVariant *
    2481                 :     616543 : tree_instance_get_gvariant (TreeInstance *tree)
    2482                 :            : {
    2483                 :            :   const GVariantType *type;
    2484                 :            :   GVariant *result;
    2485                 :            : 
    2486                 :     616543 :   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
    2487                 :            : 
    2488   [ +  +  +  +  :     616543 :   switch (g_variant_type_info_get_type_char (tree->info))
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  +  
                      - ]
    2489                 :            :     {
    2490                 :       1371 :     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
    2491                 :            :       {
    2492                 :            :         const GVariantType *child_type;
    2493                 :            :         GVariant *child;
    2494                 :            : 
    2495         [ +  + ]:       1371 :         if (tree->n_children)
    2496                 :        678 :           child = tree_instance_get_gvariant (tree->children[0]);
    2497                 :            :         else
    2498                 :        693 :           child = NULL;
    2499                 :            : 
    2500                 :       1371 :         child_type = g_variant_type_element (type);
    2501                 :            : 
    2502   [ +  +  +  + ]:       1371 :         if (child != NULL && randomly (0.5))
    2503                 :        331 :           child_type = NULL;
    2504                 :            : 
    2505                 :       1371 :         result = g_variant_new_maybe (child_type, child);
    2506                 :            :       }
    2507                 :       1371 :       break;
    2508                 :            : 
    2509                 :       8792 :     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
    2510                 :            :       {
    2511                 :            :         const GVariantType *child_type;
    2512                 :            :         GVariant **children;
    2513                 :            :         gsize i;
    2514                 :            : 
    2515                 :       8792 :         children = g_new (GVariant *, tree->n_children);
    2516         [ +  + ]:     569843 :         for (i = 0; i < tree->n_children; i++)
    2517                 :     561051 :           children[i] = tree_instance_get_gvariant (tree->children[i]);
    2518                 :            : 
    2519                 :       8792 :         child_type = g_variant_type_element (type);
    2520                 :            : 
    2521   [ +  +  +  + ]:       8792 :         if (i > 0 && randomly (0.5))
    2522                 :       4355 :           child_type = NULL;
    2523                 :            : 
    2524                 :       8792 :         result = g_variant_new_array (child_type, children, tree->n_children);
    2525                 :       8792 :         g_free (children);
    2526                 :            :       }
    2527                 :       8792 :       break;
    2528                 :            : 
    2529                 :       1097 :     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
    2530                 :            :       {
    2531                 :            :         GVariant **children;
    2532                 :            :         gsize i;
    2533                 :            : 
    2534                 :       1097 :         children = g_new (GVariant *, tree->n_children);
    2535         [ +  + ]:      10714 :         for (i = 0; i < tree->n_children; i++)
    2536                 :       9617 :           children[i] = tree_instance_get_gvariant (tree->children[i]);
    2537                 :            : 
    2538                 :       1097 :         result = g_variant_new_tuple (children, tree->n_children);
    2539                 :       1097 :         g_free (children);
    2540                 :            :       }
    2541                 :       1097 :       break;
    2542                 :            : 
    2543                 :       1025 :     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
    2544                 :            :       {
    2545                 :            :         GVariant *key, *val;
    2546                 :            : 
    2547                 :       1025 :         g_assert_cmpuint (tree->n_children, ==, 2);
    2548                 :            : 
    2549                 :       1025 :         key = tree_instance_get_gvariant (tree->children[0]);
    2550                 :       1025 :         val = tree_instance_get_gvariant (tree->children[1]);
    2551                 :            : 
    2552                 :       1025 :         result = g_variant_new_dict_entry (key, val);
    2553                 :            :       }
    2554                 :       1025 :       break;
    2555                 :            : 
    2556                 :       8223 :     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
    2557                 :            :       {
    2558                 :            :         GVariant *value;
    2559                 :            : 
    2560                 :       8223 :         g_assert_cmpuint (tree->n_children, ==, 1);
    2561                 :            : 
    2562                 :       8223 :         value = tree_instance_get_gvariant (tree->children[0]);
    2563                 :       8223 :         result = g_variant_new_variant (value);
    2564                 :            :       }
    2565                 :       8223 :       break;
    2566                 :            : 
    2567                 :       6756 :     case 'b':
    2568                 :       6756 :       result = g_variant_new_boolean (tree->data.integer > 0);
    2569                 :       6756 :       break;
    2570                 :            : 
    2571                 :      13576 :     case 'y':
    2572                 :      13576 :       result = g_variant_new_byte (tree->data.integer);
    2573                 :      13576 :       break;
    2574                 :            : 
    2575                 :      12154 :     case 'n':
    2576                 :      12154 :       result = g_variant_new_int16 (tree->data.integer);
    2577                 :      12154 :       break;
    2578                 :            : 
    2579                 :       6606 :     case 'q':
    2580                 :       6606 :       result = g_variant_new_uint16 (tree->data.integer);
    2581                 :       6606 :       break;
    2582                 :            : 
    2583                 :      10511 :     case 'i':
    2584                 :      10511 :       result = g_variant_new_int32 (tree->data.integer);
    2585                 :      10511 :       break;
    2586                 :            : 
    2587                 :      11046 :     case 'u':
    2588                 :      11046 :       result = g_variant_new_uint32 (tree->data.integer);
    2589                 :      11046 :       break;
    2590                 :            : 
    2591                 :       7320 :     case 'x':
    2592                 :       7320 :       result = g_variant_new_int64 (tree->data.integer);
    2593                 :       7320 :       break;
    2594                 :            : 
    2595                 :      11910 :     case 't':
    2596                 :      11910 :       result = g_variant_new_uint64 (tree->data.integer);
    2597                 :      11910 :       break;
    2598                 :            : 
    2599                 :       3507 :     case 'h':
    2600                 :       3507 :       result = g_variant_new_handle (tree->data.integer);
    2601                 :       3507 :       break;
    2602                 :            : 
    2603                 :       9322 :     case 'd':
    2604                 :       9322 :       result = g_variant_new_double (tree->data.floating);
    2605                 :       9322 :       break;
    2606                 :            : 
    2607                 :     484743 :     case 's':
    2608                 :     484743 :       result = g_variant_new_string (tree->data.string);
    2609                 :     484743 :       break;
    2610                 :            : 
    2611                 :       9027 :     case 'o':
    2612                 :       9027 :       result = g_variant_new_object_path (tree->data.string);
    2613                 :       9027 :       break;
    2614                 :            : 
    2615                 :       9557 :     case 'g':
    2616                 :       9557 :       result = g_variant_new_signature (tree->data.string);
    2617                 :       9557 :       break;
    2618                 :            : 
    2619                 :          0 :     default:
    2620                 :            :       g_assert_not_reached ();
    2621                 :            :     }
    2622                 :            : 
    2623                 :     616543 :   return result;
    2624                 :            : }
    2625                 :            : 
    2626                 :            : static gboolean
    2627                 :     109606 : tree_instance_check_gvariant (TreeInstance *tree,
    2628                 :            :                               GVariant     *value)
    2629                 :            : {
    2630                 :            :   const GVariantType *type;
    2631                 :            : 
    2632                 :     109606 :   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
    2633                 :     109606 :   g_assert_true (g_variant_is_of_type (value, type));
    2634                 :            : 
    2635   [ +  +  +  +  :     109606 :   switch (g_variant_type_info_get_type_char (tree->info))
          +  +  +  +  +  
          +  +  +  +  +  
                      - ]
    2636                 :            :     {
    2637                 :       1204 :     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
    2638                 :            :       {
    2639                 :            :         GVariant *child;
    2640                 :            :         gboolean equal;
    2641                 :            : 
    2642                 :       1204 :         child = g_variant_get_maybe (value);
    2643                 :            : 
    2644   [ +  +  +  - ]:       1204 :         if (child != NULL && tree->n_children == 1)
    2645                 :        620 :           equal = tree_instance_check_gvariant (tree->children[0], child);
    2646   [ +  -  +  - ]:        584 :         else if (child == NULL && tree->n_children == 0)
    2647                 :        584 :           equal = TRUE;
    2648                 :            :         else
    2649                 :          0 :           equal = FALSE;
    2650                 :            : 
    2651         [ +  + ]:       1204 :         if (child != NULL)
    2652                 :        620 :           g_variant_unref (child);
    2653                 :            : 
    2654                 :       1204 :         return equal;
    2655                 :            :       }
    2656                 :            :       break;
    2657                 :            : 
    2658                 :       2576 :     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
    2659                 :            :     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
    2660                 :            :     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
    2661                 :            :       {
    2662                 :            :         gsize i;
    2663                 :            : 
    2664         [ -  + ]:       2576 :         if (g_variant_n_children (value) != tree->n_children)
    2665                 :          0 :           return FALSE;
    2666                 :            : 
    2667         [ +  + ]:      65798 :         for (i = 0; i < tree->n_children; i++)
    2668                 :            :           {
    2669                 :            :             GVariant *child;
    2670                 :            :             gboolean equal;
    2671                 :            : 
    2672                 :      63222 :             child = g_variant_get_child_value (value, i);
    2673                 :      63222 :             equal = tree_instance_check_gvariant (tree->children[i], child);
    2674                 :      63222 :             g_variant_unref (child);
    2675                 :            : 
    2676         [ -  + ]:      63222 :             if (!equal)
    2677                 :          0 :               return FALSE;
    2678                 :            :           }
    2679                 :            : 
    2680                 :       2576 :         return TRUE;
    2681                 :            :       }
    2682                 :            :       break;
    2683                 :            : 
    2684                 :      15466 :     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
    2685                 :            :       {
    2686                 :            :         const gchar *str1, *str2;
    2687                 :            :         GVariant *child;
    2688                 :            :         gboolean equal;
    2689                 :            : 
    2690                 :      15466 :         child = g_variant_get_variant (value);
    2691                 :      15466 :         str1 = g_variant_get_type_string (child);
    2692                 :      15466 :         str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
    2693                 :            :         /* GVariant only keeps one copy of type strings around */
    2694   [ +  -  +  - ]:      30932 :         equal = str1 == str2 &&
    2695                 :      15466 :                 tree_instance_check_gvariant (tree->children[0], child);
    2696                 :            : 
    2697                 :      15466 :         g_variant_unref (child);
    2698                 :            : 
    2699                 :      15466 :         return equal;
    2700                 :            :       }
    2701                 :            :       break;
    2702                 :            : 
    2703                 :       7952 :     case 'b':
    2704                 :       7952 :       return g_variant_get_boolean (value) == (gboolean) tree->data.integer;
    2705                 :            : 
    2706                 :      18941 :     case 'y':
    2707                 :      18941 :       return g_variant_get_byte (value) == (guchar) tree->data.integer;
    2708                 :            : 
    2709                 :       2898 :     case 'n':
    2710                 :       2898 :       return g_variant_get_int16 (value) == (gint16) tree->data.integer;
    2711                 :            : 
    2712                 :       3830 :     case 'q':
    2713                 :       3830 :       return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
    2714                 :            : 
    2715                 :      14466 :     case 'i':
    2716                 :      14466 :       return g_variant_get_int32 (value) == (gint32) tree->data.integer;
    2717                 :            : 
    2718                 :      15042 :     case 'u':
    2719                 :      15042 :       return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
    2720                 :            : 
    2721                 :       5314 :     case 'x':
    2722                 :       5314 :       return g_variant_get_int64 (value) == (gint64) tree->data.integer;
    2723                 :            : 
    2724                 :       2729 :     case 't':
    2725                 :       2729 :       return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
    2726                 :            : 
    2727                 :       4101 :     case 'h':
    2728                 :       4101 :       return g_variant_get_handle (value) == (gint32) tree->data.integer;
    2729                 :            : 
    2730                 :       3250 :     case 'd':
    2731                 :            :       {
    2732                 :       3250 :         gdouble floating = g_variant_get_double (value);
    2733                 :            : 
    2734                 :       3250 :         return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
    2735                 :            :       }
    2736                 :            : 
    2737                 :      11837 :     case 's':
    2738                 :            :     case 'o':
    2739                 :            :     case 'g':
    2740                 :      23674 :       return strcmp (g_variant_get_string (value, NULL),
    2741                 :      11837 :                      tree->data.string) == 0;
    2742                 :            : 
    2743                 :          0 :     default:
    2744                 :            :       g_assert_not_reached ();
    2745                 :            :     }
    2746                 :            : }
    2747                 :            : 
    2748                 :            : static void
    2749                 :      39721 : tree_instance_build_gvariant (TreeInstance    *tree,
    2750                 :            :                               GVariantBuilder *builder,
    2751                 :            :                               gboolean         guess_ok)
    2752                 :            : {
    2753                 :            :   const GVariantType *type;
    2754                 :            : 
    2755                 :      39721 :   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
    2756                 :            : 
    2757         [ +  + ]:      39721 :   if (g_variant_type_is_container (type))
    2758                 :            :     {
    2759                 :            :       gsize i;
    2760                 :            : 
    2761                 :            :       /* force GVariantBuilder to guess the type half the time */
    2762   [ +  +  +  + ]:       9623 :       if (guess_ok && randomly (0.5))
    2763                 :            :         {
    2764   [ +  +  +  + ]:        402 :           if (g_variant_type_is_array (type) && tree->n_children)
    2765                 :         45 :             type = G_VARIANT_TYPE_ARRAY;
    2766                 :            : 
    2767   [ +  +  +  + ]:        402 :           if (g_variant_type_is_maybe (type) && tree->n_children)
    2768                 :         77 :             type = G_VARIANT_TYPE_MAYBE;
    2769                 :            : 
    2770         [ +  + ]:        402 :           if (g_variant_type_is_tuple (type))
    2771                 :        104 :             type = G_VARIANT_TYPE_TUPLE;
    2772                 :            : 
    2773         [ +  + ]:        402 :           if (g_variant_type_is_dict_entry (type))
    2774                 :         51 :             type = G_VARIANT_TYPE_DICT_ENTRY;
    2775                 :            :         }
    2776                 :            :       else
    2777                 :       9221 :         guess_ok = FALSE;
    2778                 :            : 
    2779                 :       9623 :       g_variant_builder_open (builder, type);
    2780                 :            : 
    2781         [ +  + ]:      49277 :       for (i = 0; i < tree->n_children; i++)
    2782                 :      39654 :         tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
    2783                 :            : 
    2784                 :       9623 :       g_variant_builder_close (builder);
    2785                 :            :     }
    2786                 :            :   else
    2787                 :      30098 :     g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
    2788                 :      39721 : }
    2789                 :            : 
    2790                 :            : 
    2791                 :            : static gboolean
    2792                 :      39721 : tree_instance_check_iter (TreeInstance *tree,
    2793                 :            :                           GVariantIter *iter)
    2794                 :            : {
    2795                 :            :   GVariant *value;
    2796                 :            : 
    2797                 :      39721 :   value = g_variant_iter_next_value (iter);
    2798                 :            : 
    2799         [ +  + ]:      39721 :   if (g_variant_is_container (value))
    2800                 :            :     {
    2801                 :            :       gsize i;
    2802                 :            : 
    2803                 :       9623 :       iter = g_variant_iter_new (value);
    2804                 :       9623 :       g_variant_unref (value);
    2805                 :            : 
    2806         [ -  + ]:       9623 :       if (g_variant_iter_n_children (iter) != tree->n_children)
    2807                 :            :         {
    2808                 :          0 :           g_variant_iter_free (iter);
    2809                 :          0 :           return FALSE;
    2810                 :            :         }
    2811                 :            : 
    2812         [ +  + ]:      49277 :       for (i = 0; i < tree->n_children; i++)
    2813         [ -  + ]:      39654 :         if (!tree_instance_check_iter (tree->children[i], iter))
    2814                 :            :           {
    2815                 :          0 :             g_variant_iter_free (iter);
    2816                 :          0 :             return FALSE;
    2817                 :            :           }
    2818                 :            : 
    2819                 :       9623 :       g_assert_null (g_variant_iter_next_value (iter));
    2820                 :       9623 :       g_variant_iter_free (iter);
    2821                 :            : 
    2822                 :       9623 :       return TRUE;
    2823                 :            :     }
    2824                 :            : 
    2825                 :            :   else
    2826                 :            :     {
    2827                 :            :       gboolean equal;
    2828                 :            : 
    2829                 :      30098 :       equal = tree_instance_check_gvariant (tree, value);
    2830                 :      30098 :       g_variant_unref (value);
    2831                 :            : 
    2832                 :      30098 :       return equal;
    2833                 :            :     }
    2834                 :            : }
    2835                 :            : 
    2836                 :            : static void
    2837                 :        100 : test_container (void)
    2838                 :            : {
    2839                 :            :   TreeInstance *tree;
    2840                 :            :   GVariant *value;
    2841                 :            :   gchar *s1, *s2;
    2842                 :            : 
    2843                 :        100 :   tree = tree_instance_new (NULL, 3);
    2844                 :        100 :   value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
    2845                 :            : 
    2846                 :        100 :   s1 = g_variant_print (value, TRUE);
    2847                 :        100 :   g_assert_true (tree_instance_check_gvariant (tree, value));
    2848                 :            : 
    2849                 :        100 :   g_variant_get_data (value);
    2850                 :            : 
    2851                 :        100 :   s2 = g_variant_print (value, TRUE);
    2852                 :        100 :   g_assert_true (tree_instance_check_gvariant (tree, value));
    2853                 :            : 
    2854                 :        100 :   g_assert_cmpstr (s1, ==, s2);
    2855                 :            : 
    2856         [ +  + ]:        100 :   if (g_variant_is_container (value))
    2857                 :            :     {
    2858                 :            :       GVariantBuilder builder;
    2859                 :            :       GVariantIter iter;
    2860                 :            :       GVariant *built;
    2861                 :            :       GVariant *val;
    2862                 :            :       gchar *s3;
    2863                 :            : 
    2864                 :         67 :       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
    2865                 :         67 :       tree_instance_build_gvariant (tree, &builder, TRUE);
    2866                 :         67 :       built = g_variant_builder_end (&builder);
    2867                 :         67 :       g_variant_ref_sink (built);
    2868                 :         67 :       g_variant_get_data (built);
    2869                 :         67 :       val = g_variant_get_variant (built);
    2870                 :            : 
    2871                 :         67 :       s3 = g_variant_print (val, TRUE);
    2872                 :         67 :       g_assert_cmpstr (s1, ==, s3);
    2873                 :            : 
    2874                 :         67 :       g_variant_iter_init (&iter, built);
    2875                 :         67 :       g_assert_true (tree_instance_check_iter (tree, &iter));
    2876                 :         67 :       g_assert_null (g_variant_iter_next_value (&iter));
    2877                 :            : 
    2878                 :         67 :       g_variant_unref (built);
    2879                 :         67 :       g_variant_unref (val);
    2880                 :         67 :       g_free (s3);
    2881                 :            :     }
    2882                 :            : 
    2883                 :        100 :   tree_instance_free (tree);
    2884                 :        100 :   g_variant_unref (value);
    2885                 :        100 :   g_free (s2);
    2886                 :        100 :   g_free (s1);
    2887                 :        100 : }
    2888                 :            : 
    2889                 :            : static void
    2890                 :          1 : test_string (void)
    2891                 :            : {
    2892                 :            :   /* Test some different methods of creating strings */
    2893                 :            :   GVariant *v;
    2894                 :            : 
    2895                 :          1 :   v = g_variant_new_string ("foo");
    2896                 :          1 :   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
    2897                 :          1 :   g_variant_unref (v);
    2898                 :            : 
    2899                 :            : 
    2900                 :          1 :   v = g_variant_new_take_string (g_strdup ("foo"));
    2901                 :          1 :   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
    2902                 :          1 :   g_variant_unref (v);
    2903                 :            : 
    2904                 :          1 :   v = g_variant_new_printf ("%s %d", "foo", 123);
    2905                 :          1 :   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo 123");
    2906                 :          1 :   g_variant_unref (v);
    2907                 :          1 : }
    2908                 :            : 
    2909                 :            : static void
    2910                 :          1 : test_utf8 (void)
    2911                 :            : {
    2912                 :          1 :   const gchar invalid[] = "hello\xffworld";
    2913                 :            :   GVariant *value;
    2914                 :            : 
    2915                 :            :   /* ensure that the test data is not valid utf8... */
    2916                 :          1 :   g_assert_false (g_utf8_validate (invalid, -1, NULL));
    2917                 :            : 
    2918                 :            :   /* load the data untrusted */
    2919                 :          1 :   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
    2920                 :            :                                    invalid, sizeof invalid,
    2921                 :            :                                    FALSE, NULL, NULL);
    2922                 :            : 
    2923                 :            :   /* ensure that the problem is caught and we get valid UTF-8 */
    2924                 :          1 :   g_assert_true (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
    2925                 :          1 :   g_variant_unref (value);
    2926                 :            : 
    2927                 :            : 
    2928                 :            :   /* now load it trusted */
    2929                 :          1 :   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
    2930                 :            :                                    invalid, sizeof invalid,
    2931                 :            :                                    TRUE, NULL, NULL);
    2932                 :            : 
    2933                 :            :   /* ensure we get the invalid data (ie: make sure that time wasn't
    2934                 :            :    * wasted on validating data that was marked as trusted)
    2935                 :            :    */
    2936                 :          1 :   g_assert_true (g_variant_get_string (value, NULL) == invalid);
    2937                 :          1 :   g_variant_unref (value);
    2938                 :          1 : }
    2939                 :            : 
    2940                 :            : static void
    2941                 :          1 : test_containers (void)
    2942                 :            : {
    2943                 :            :   gsize i;
    2944                 :            : 
    2945         [ +  + ]:        101 :   for (i = 0; i < 100; i++)
    2946                 :            :     {
    2947                 :        100 :       test_container ();
    2948                 :            :     }
    2949                 :            : 
    2950                 :          1 :   g_variant_type_info_assert_no_infos ();
    2951                 :          1 : }
    2952                 :            : 
    2953                 :            : static void
    2954                 :          1 : test_format_strings (void)
    2955                 :            : {
    2956                 :            :   GVariantType *type;
    2957                 :            :   const gchar *end;
    2958                 :            : 
    2959                 :          1 :   g_assert_true (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
    2960                 :          1 :   g_assert_true (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
    2961                 :          1 :   g_assert_true (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
    2962                 :          1 :   g_assert_true (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
    2963                 :          1 :   g_assert_true (g_variant_format_string_scan ("(^as)", NULL, &end) &&
    2964                 :            :                  *end == '\0');
    2965                 :          1 :   g_assert_false (g_variant_format_string_scan ("(^s)", NULL, &end));
    2966                 :          1 :   g_assert_false (g_variant_format_string_scan ("(^a)", NULL, &end));
    2967                 :          1 :   g_assert_false (g_variant_format_string_scan ("(z)", NULL, &end));
    2968                 :          1 :   g_assert_false (g_variant_format_string_scan ("az", NULL, &end));
    2969                 :          1 :   g_assert_false (g_variant_format_string_scan ("{**}", NULL, &end));
    2970                 :          1 :   g_assert_false (g_variant_format_string_scan ("{@**}", NULL, &end));
    2971                 :          1 :   g_assert_true (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
    2972                 :            :                  *end == '\0');
    2973                 :          1 :   g_assert_true (g_variant_format_string_scan ("{yv}", NULL, &end) &&
    2974                 :            :                  *end == '\0');
    2975                 :          1 :   g_assert_false (g_variant_format_string_scan ("{&?v}", NULL, &end));
    2976                 :          1 :   g_assert_true (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
    2977                 :            :                  *end == '\0');
    2978                 :          1 :   g_assert_false (g_variant_format_string_scan ("{&@sv}", NULL, &end));
    2979                 :          1 :   g_assert_false (g_variant_format_string_scan ("{@&sv}", NULL, &end));
    2980                 :          1 :   g_assert_true (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
    2981                 :            :                  *end == '\0');
    2982                 :          1 :   g_assert_false (g_variant_format_string_scan ("{vv}", NULL, &end));
    2983                 :          1 :   g_assert_false (g_variant_format_string_scan ("{y}", NULL, &end));
    2984                 :          1 :   g_assert_false (g_variant_format_string_scan ("{yyy}", NULL, &end));
    2985                 :          1 :   g_assert_false (g_variant_format_string_scan ("{ya}", NULL, &end));
    2986                 :          1 :   g_assert_true (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
    2987                 :          1 :   g_assert_false (g_variant_format_string_scan ("&as", NULL, &end));
    2988                 :          1 :   g_assert_false (g_variant_format_string_scan ("@z", NULL, &end));
    2989                 :          1 :   g_assert_false (g_variant_format_string_scan ("az", NULL, &end));
    2990                 :          1 :   g_assert_false (g_variant_format_string_scan ("a&s", NULL, &end));
    2991                 :            : 
    2992                 :          1 :   type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
    2993                 :          1 :   g_assert_true (type && *end == '\0');
    2994                 :          1 :   g_assert_true (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
    2995                 :          1 :   g_variant_type_free (type);
    2996                 :            : 
    2997                 :          1 :   type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
    2998                 :          1 :   g_assert_null (type);
    2999                 :          1 : }
    3000                 :            : 
    3001                 :            : static void
    3002                 :          4 : do_failed_test (const char *test,
    3003                 :            :                 const gchar *pattern)
    3004                 :            : {
    3005                 :          4 :   g_test_trap_subprocess (test, 1000000, G_TEST_SUBPROCESS_DEFAULT);
    3006                 :          4 :   g_test_trap_assert_failed ();
    3007                 :          4 :   g_test_trap_assert_stderr (pattern);
    3008                 :          4 : }
    3009                 :            : 
    3010                 :            : static void
    3011                 :          1 : test_invalid_varargs (void)
    3012                 :            : {
    3013                 :            :   GVariant *value;
    3014                 :            :   const gchar *end;
    3015                 :            : 
    3016         [ -  + ]:          1 :   if (!g_test_undefined ())
    3017                 :          0 :     return;
    3018                 :            : 
    3019                 :          1 :   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    3020                 :            :                          "*GVariant format string*");
    3021                 :          1 :   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    3022                 :            :                          "*valid_format_string*");
    3023                 :          1 :   value = g_variant_new ("z");
    3024                 :          1 :   g_test_assert_expected_messages ();
    3025                 :          1 :   g_assert_null (value);
    3026                 :            : 
    3027                 :          1 :   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    3028                 :            :                          "*valid GVariant format string as a prefix*");
    3029                 :          1 :   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    3030                 :            :                          "*valid_format_string*");
    3031                 :          1 :   value = g_variant_new_va ("z", &end, NULL);
    3032                 :          1 :   g_test_assert_expected_messages ();
    3033                 :          1 :   g_assert_null (value);
    3034                 :            : 
    3035                 :          1 :   value = g_variant_new ("y", 'a');
    3036                 :          1 :   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    3037                 :            :                          "*type of 'q' but * has a type of 'y'*");
    3038                 :          1 :   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    3039                 :            :                          "*valid_format_string*");
    3040                 :          1 :   g_variant_get (value, "q");
    3041                 :          1 :   g_test_assert_expected_messages ();
    3042                 :          1 :   g_variant_unref (value);
    3043                 :            : }
    3044                 :            : 
    3045                 :            : static void
    3046                 :          7 : check_and_free (GVariant    *value,
    3047                 :            :                 const gchar *str)
    3048                 :            : {
    3049                 :          7 :   gchar *valstr = g_variant_print (value, FALSE);
    3050                 :          7 :   g_assert_cmpstr (str, ==, valstr);
    3051                 :          7 :   g_variant_unref (value);
    3052                 :          7 :   g_free (valstr);
    3053                 :          7 : }
    3054                 :            : 
    3055                 :            : static void
    3056                 :          0 : test_varargs_empty_array (void)
    3057                 :            : {
    3058                 :          0 :   g_variant_new ("(a{s*})", NULL);
    3059                 :            : 
    3060                 :            :   g_assert_not_reached ();
    3061                 :            : }
    3062                 :            : 
    3063                 :            : static void
    3064                 :          1 : test_varargs (void)
    3065                 :            : {
    3066                 :            :   {
    3067                 :            :     GVariantBuilder array;
    3068                 :            : 
    3069                 :          1 :     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
    3070                 :          1 :     g_variant_builder_add_parsed (&array, "{'size', <(%i, %i)> }", 800, 600);
    3071                 :          1 :     g_variant_builder_add (&array, "{sv}", "title",
    3072                 :            :                            g_variant_new_string ("Test case"));
    3073                 :          1 :     g_variant_builder_add_value (&array,
    3074                 :            :       g_variant_new_dict_entry (g_variant_new_string ("temperature"),
    3075                 :            :                                 g_variant_new_variant (
    3076                 :            :                                   g_variant_new_double (37.5))));
    3077                 :          1 :     check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
    3078                 :            :                                    NULL, FALSE, NULL, &array, 7777, 8888),
    3079                 :            :                     "(nothing, nothing, {'size': <(800, 600)>, "
    3080                 :            :                                         "'title': <'Test case'>, "
    3081                 :            :                                         "'temperature': <37.5>}, "
    3082                 :            :                      "7777, 8888)");
    3083                 :            : 
    3084                 :          1 :     check_and_free (g_variant_new ("(imimimmimmimmi)",
    3085                 :            :                                    123,
    3086                 :            :                                    FALSE, 321,
    3087                 :            :                                    TRUE, 123,
    3088                 :            :                                    FALSE, TRUE, 321,
    3089                 :            :                                    TRUE, FALSE, 321,
    3090                 :            :                                    TRUE, TRUE, 123),
    3091                 :            :                     "(123, nothing, 123, nothing, just nothing, 123)");
    3092                 :            : 
    3093                 :          1 :     check_and_free (g_variant_new ("(ybnixd)",
    3094                 :            :                                    'a', 1, 22, 33, (guint64) 44, 5.5),
    3095                 :            :                     "(0x61, true, 22, 33, 44, 5.5)");
    3096                 :            : 
    3097                 :          1 :     check_and_free (g_variant_new ("(@y?*rv)",
    3098                 :            :                                    g_variant_new ("y", 'a'),
    3099                 :            :                                    g_variant_new ("y", 'b'),
    3100                 :            :                                    g_variant_new ("y", 'c'),
    3101                 :            :                                    g_variant_new ("(y)", 'd'),
    3102                 :            :                                    g_variant_new ("y", 'e')),
    3103                 :            :                     "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
    3104                 :            :   }
    3105                 :            : 
    3106                 :            :   {
    3107                 :            :     GVariantBuilder array;
    3108                 :            :     GVariantIter iter;
    3109                 :            :     GVariant *value;
    3110                 :            :     gchar *number;
    3111                 :            :     gboolean just;
    3112                 :            :     guint i;
    3113                 :            :     gint val;
    3114                 :            : 
    3115                 :          1 :     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
    3116         [ +  + ]:        101 :     for (i = 0; i < 100; i++)
    3117                 :            :       {
    3118                 :        100 :         number = g_strdup_printf ("%u", i);
    3119                 :        100 :         g_variant_builder_add (&array, "s", number);
    3120                 :        100 :         g_free (number);
    3121                 :            :       }
    3122                 :            : 
    3123                 :          1 :     value = g_variant_builder_end (&array);
    3124                 :          1 :     g_variant_iter_init (&iter, value);
    3125                 :            : 
    3126                 :          1 :     i = 0;
    3127         [ +  + ]:        101 :     while (g_variant_iter_loop (&iter, "s", &number))
    3128                 :            :       {
    3129                 :        100 :         gchar *check = g_strdup_printf ("%u", i++);
    3130                 :        100 :         g_assert_cmpstr (number, ==, check);
    3131                 :        100 :         g_free (check);
    3132                 :            :       }
    3133                 :          1 :     g_assert_null (number);
    3134                 :          1 :     g_assert_cmpuint (i, ==, 100);
    3135                 :            : 
    3136                 :          1 :     g_variant_unref (value);
    3137                 :            : 
    3138                 :          1 :     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
    3139         [ +  + ]:        101 :     for (i = 0; i < 100; i++)
    3140                 :        100 :       g_variant_builder_add (&array, "mi", i % 2 == 0, i);
    3141                 :          1 :     value = g_variant_builder_end (&array);
    3142                 :            : 
    3143                 :          1 :     i = 0;
    3144                 :          1 :     g_variant_iter_init (&iter, value);
    3145         [ +  + ]:        101 :     while (g_variant_iter_loop (&iter, "mi", NULL, &val))
    3146                 :        100 :       g_assert_true (val == (gint) i++ || val == 0);
    3147                 :          1 :     g_assert_cmpuint (i, ==, 100);
    3148                 :            : 
    3149                 :          1 :     i = 0;
    3150                 :          1 :     g_variant_iter_init (&iter, value);
    3151         [ +  + ]:        101 :     while (g_variant_iter_loop (&iter, "mi", &just, &val))
    3152                 :            :       {
    3153                 :        100 :         gint this = i++;
    3154                 :            : 
    3155         [ +  + ]:        100 :         if (this % 2 == 0)
    3156                 :            :           {
    3157                 :         50 :             g_assert_true (just);
    3158                 :         50 :             g_assert_cmpint (val, ==, this);
    3159                 :            :           }
    3160                 :            :         else
    3161                 :            :           {
    3162                 :         50 :             g_assert_false (just);
    3163                 :         50 :             g_assert_cmpint (val, ==, 0);
    3164                 :            :           }
    3165                 :            :       }
    3166                 :          1 :     g_assert_cmpuint (i, ==, 100);
    3167                 :            : 
    3168                 :          1 :     g_variant_unref (value);
    3169                 :            :   }
    3170                 :            : 
    3171                 :            :   {
    3172                 :          1 :     const gchar *strvector[] = {"/hello", "/world", NULL};
    3173                 :          1 :     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
    3174                 :            :     GVariantBuilder builder;
    3175                 :            :     GVariantIter *array;
    3176                 :            :     GVariantIter tuple;
    3177                 :            :     const gchar **strv;
    3178                 :            :     gchar **my_strv;
    3179                 :            :     GVariant *value;
    3180                 :            :     gchar *str;
    3181                 :            :     gsize i;
    3182                 :            : 
    3183                 :          1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
    3184                 :          1 :     g_variant_builder_add (&builder, "s", test_strs[0]);
    3185                 :          1 :     g_variant_builder_add (&builder, "s", test_strs[1]);
    3186                 :          1 :     g_variant_builder_add (&builder, "s", test_strs[2]);
    3187                 :          1 :     value = g_variant_new ("(as^as^a&s)", &builder, strvector, strvector);
    3188                 :          1 :     g_variant_iter_init (&tuple, value);
    3189                 :          1 :     g_variant_iter_next (&tuple, "as", &array);
    3190                 :            : 
    3191                 :          1 :     i = 0;
    3192         [ +  + ]:          4 :     while (g_variant_iter_loop (array, "s", &str))
    3193                 :          3 :       g_assert_cmpstr (str, ==, test_strs[i++]);
    3194                 :          1 :     g_assert_cmpuint (i, ==, 3);
    3195                 :            : 
    3196                 :          1 :     g_variant_iter_free (array);
    3197                 :            : 
    3198                 :            :     /* start over */
    3199                 :          1 :     g_variant_iter_init (&tuple, value);
    3200                 :          1 :     g_variant_iter_next (&tuple, "as", &array);
    3201                 :            : 
    3202                 :          1 :     i = 0;
    3203         [ +  + ]:          4 :     while (g_variant_iter_loop (array, "&s", &str))
    3204                 :          3 :       g_assert_cmpstr (str, ==, test_strs[i++]);
    3205                 :          1 :     g_assert_cmpuint (i, ==, 3);
    3206                 :            : 
    3207                 :          1 :     g_variant_iter_free (array);
    3208                 :            : 
    3209                 :          1 :     g_variant_iter_next (&tuple, "^a&s", &strv);
    3210                 :          1 :     g_variant_iter_next (&tuple, "^as", &my_strv);
    3211                 :            : 
    3212                 :          3 :     g_assert_cmpstrv (strv, strvector);
    3213                 :          3 :     g_assert_cmpstrv (my_strv, strvector);
    3214                 :            : 
    3215                 :          1 :     g_variant_unref (value);
    3216                 :          1 :     g_strfreev (my_strv);
    3217                 :          1 :     g_free (strv);
    3218                 :            :   }
    3219                 :            : 
    3220                 :            :   {
    3221                 :          1 :     const gchar *strvector[] = {"/hello", "/world", NULL};
    3222                 :          1 :     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
    3223                 :            :     GVariantBuilder builder;
    3224                 :            :     GVariantIter *array;
    3225                 :            :     GVariantIter tuple;
    3226                 :            :     const gchar **strv;
    3227                 :            :     gchar **my_strv;
    3228                 :            :     GVariant *value;
    3229                 :            :     gchar *str;
    3230                 :            :     gsize i;
    3231                 :            : 
    3232                 :          1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aaay"));
    3233                 :          1 :     g_variant_builder_add (&builder, "^aay", strvector);
    3234                 :          1 :     g_variant_builder_add (&builder, "^aay", strvector);
    3235                 :          1 :     g_variant_builder_add (&builder, "^aay", strvector);
    3236                 :          1 :     value = g_variant_new ("aaay", &builder);
    3237                 :          1 :     array = g_variant_iter_new (value);
    3238                 :          1 :     i = 0;
    3239         [ +  + ]:          4 :     while (g_variant_iter_loop (array, "^aay", &my_strv))
    3240                 :          3 :       i++;
    3241                 :          1 :     g_assert_cmpuint (i, ==, 3);
    3242                 :            : 
    3243                 :            :     /* start over */
    3244                 :          1 :     g_variant_iter_init (array, value);
    3245                 :          1 :     i = 0;
    3246         [ +  + ]:          4 :     while (g_variant_iter_loop (array, "^a&ay", &strv))
    3247                 :          3 :       i++;
    3248                 :          1 :     g_assert_cmpuint (i, ==, 3);
    3249                 :          1 :     g_variant_unref (value);
    3250                 :          1 :     g_variant_iter_free (array);
    3251                 :            : 
    3252                 :            :     /* next test */
    3253                 :          1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
    3254                 :          1 :     g_variant_builder_add (&builder, "^ay", test_strs[0]);
    3255                 :          1 :     g_variant_builder_add (&builder, "^ay", test_strs[1]);
    3256                 :          1 :     g_variant_builder_add (&builder, "^ay", test_strs[2]);
    3257                 :          1 :     value = g_variant_new ("(aay^aay^a&ay)", &builder, strvector, strvector);
    3258                 :          1 :     g_variant_iter_init (&tuple, value);
    3259                 :          1 :     g_variant_iter_next (&tuple, "aay", &array);
    3260                 :            : 
    3261                 :          1 :     i = 0;
    3262         [ +  + ]:          4 :     while (g_variant_iter_loop (array, "^ay", &str))
    3263                 :          3 :       g_assert_cmpstr (str, ==, test_strs[i++]);
    3264                 :          1 :     g_assert_cmpuint (i, ==, 3);
    3265                 :            : 
    3266                 :          1 :     g_variant_iter_free (array);
    3267                 :            : 
    3268                 :            :     /* start over */
    3269                 :          1 :     g_variant_iter_init (&tuple, value);
    3270                 :          1 :     g_variant_iter_next (&tuple, "aay", &array);
    3271                 :            : 
    3272                 :          1 :     i = 0;
    3273         [ +  + ]:          4 :     while (g_variant_iter_loop (array, "^&ay", &str))
    3274                 :          3 :       g_assert_cmpstr (str, ==, test_strs[i++]);
    3275                 :          1 :     g_assert_cmpuint (i, ==, 3);
    3276                 :            : 
    3277                 :          1 :     g_variant_iter_free (array);
    3278                 :            : 
    3279                 :          1 :     g_variant_iter_next (&tuple, "^a&ay", &strv);
    3280                 :          1 :     g_variant_iter_next (&tuple, "^aay", &my_strv);
    3281                 :            : 
    3282                 :          3 :     g_assert_cmpstrv (strv, strvector);
    3283                 :          3 :     g_assert_cmpstrv (my_strv, strvector);
    3284                 :            : 
    3285                 :          1 :     g_variant_unref (value);
    3286                 :          1 :     g_strfreev (my_strv);
    3287                 :          1 :     g_free (strv);
    3288                 :            :   }
    3289                 :            : 
    3290                 :            :   {
    3291                 :          1 :     const gchar *strvector[] = {"/hello", "/world", NULL};
    3292                 :          1 :     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
    3293                 :            :     GVariantBuilder builder;
    3294                 :            :     GVariantIter *array;
    3295                 :            :     GVariantIter tuple;
    3296                 :            :     const gchar **strv;
    3297                 :            :     gchar **my_strv;
    3298                 :            :     GVariant *value;
    3299                 :            :     gchar *str;
    3300                 :            :     gsize i;
    3301                 :            : 
    3302                 :          1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
    3303                 :          1 :     g_variant_builder_add (&builder, "o", test_strs[0]);
    3304                 :          1 :     g_variant_builder_add (&builder, "o", test_strs[1]);
    3305                 :          1 :     g_variant_builder_add (&builder, "o", test_strs[2]);
    3306                 :          1 :     value = g_variant_new ("(ao^ao^a&o)", &builder, strvector, strvector);
    3307                 :          1 :     g_variant_iter_init (&tuple, value);
    3308                 :          1 :     g_variant_iter_next (&tuple, "ao", &array);
    3309                 :            : 
    3310                 :          1 :     i = 0;
    3311         [ +  + ]:          4 :     while (g_variant_iter_loop (array, "o", &str))
    3312                 :          3 :       g_assert_cmpstr (str, ==, test_strs[i++]);
    3313                 :          1 :     g_assert_cmpuint (i, ==, 3);
    3314                 :            : 
    3315                 :          1 :     g_variant_iter_free (array);
    3316                 :            : 
    3317                 :            :     /* start over */
    3318                 :          1 :     g_variant_iter_init (&tuple, value);
    3319                 :          1 :     g_variant_iter_next (&tuple, "ao", &array);
    3320                 :            : 
    3321                 :          1 :     i = 0;
    3322         [ +  + ]:          4 :     while (g_variant_iter_loop (array, "&o", &str))
    3323                 :          3 :       g_assert_cmpstr (str, ==, test_strs[i++]);
    3324                 :          1 :     g_assert_cmpuint (i, ==, 3);
    3325                 :            : 
    3326                 :          1 :     g_variant_iter_free (array);
    3327                 :            : 
    3328                 :          1 :     g_variant_iter_next (&tuple, "^a&o", &strv);
    3329                 :          1 :     g_variant_iter_next (&tuple, "^ao", &my_strv);
    3330                 :            : 
    3331                 :          3 :     g_assert_cmpstrv (strv, strvector);
    3332                 :          3 :     g_assert_cmpstrv (my_strv, strvector);
    3333                 :            : 
    3334                 :          1 :     g_variant_unref (value);
    3335                 :          1 :     g_strfreev (my_strv);
    3336                 :          1 :     g_free (strv);
    3337                 :            :   }
    3338                 :            : 
    3339                 :            :   {
    3340                 :          1 :     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
    3341                 :            :     GVariantBuilder builder;
    3342                 :            :     GVariantIter iter;
    3343                 :            :     GVariantIter *i2;
    3344                 :            :     GVariantIter *i3;
    3345                 :            :     GVariant *value;
    3346                 :            :     GVariant *sub;
    3347                 :            :     gchar **strv;
    3348                 :            :     gsize i;
    3349                 :            : 
    3350                 :          1 :     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aas"));
    3351                 :          1 :     g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
    3352         [ +  + ]:          7 :     for (i = 0; i < 6; i++)
    3353         [ +  + ]:          6 :       if (i & 1)
    3354                 :          3 :         g_variant_builder_add (&builder, "s", strvector[i]);
    3355                 :            :       else
    3356                 :          3 :         g_variant_builder_add (&builder, "&s", strvector[i]);
    3357                 :          1 :     g_variant_builder_close (&builder);
    3358                 :          1 :     g_variant_builder_add (&builder, "^as", strvector);
    3359                 :          1 :     g_variant_builder_add (&builder, "^as", strvector);
    3360                 :          1 :     value = g_variant_new ("aas", &builder);
    3361                 :            : 
    3362                 :          1 :     g_variant_iter_init (&iter, value);
    3363         [ +  + ]:          4 :     while (g_variant_iter_loop (&iter, "^as", &strv))
    3364         [ +  + ]:         21 :       for (i = 0; i < 6; i++)
    3365                 :         18 :         g_assert_cmpstr (strv[i], ==, strvector[i]);
    3366                 :            : 
    3367                 :          1 :     g_variant_iter_init (&iter, value);
    3368         [ +  + ]:          4 :     while (g_variant_iter_loop (&iter, "^a&s", &strv))
    3369         [ +  + ]:         21 :       for (i = 0; i < 6; i++)
    3370                 :         18 :         g_assert_cmpstr (strv[i], ==, strvector[i]);
    3371                 :            : 
    3372                 :          1 :     g_variant_iter_init (&iter, value);
    3373         [ +  + ]:          4 :     while (g_variant_iter_loop (&iter, "as", &i2))
    3374                 :            :       {
    3375                 :            :         gchar *str;
    3376                 :            : 
    3377                 :          3 :         i = 0;
    3378         [ +  + ]:         21 :         while (g_variant_iter_loop (i2, "s", &str))
    3379                 :         18 :           g_assert_cmpstr (str, ==, strvector[i++]);
    3380                 :          3 :         g_assert_cmpuint (i, ==, 6);
    3381                 :            :       }
    3382                 :            : 
    3383                 :          1 :     g_variant_iter_init (&iter, value);
    3384                 :          1 :     i3 = g_variant_iter_copy (&iter);
    3385         [ +  + ]:          4 :     while (g_variant_iter_loop (&iter, "@as", &sub))
    3386                 :            :       {
    3387                 :          3 :         gchar *str = g_variant_print (sub, TRUE);
    3388                 :          3 :         g_assert_cmpstr (str, ==,
    3389                 :            :                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
    3390                 :          3 :         g_free (str);
    3391                 :            :       }
    3392                 :            : 
    3393                 :          1 :     g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
    3394                 :            :                            "*NULL has already been returned*");
    3395                 :          1 :     g_variant_iter_next_value (&iter);
    3396                 :          1 :     g_test_assert_expected_messages ();
    3397                 :            : 
    3398         [ +  + ]:          4 :     while (g_variant_iter_loop (i3, "*", &sub))
    3399                 :            :       {
    3400                 :          3 :         gchar *str = g_variant_print (sub, TRUE);
    3401                 :          3 :         g_assert_cmpstr (str, ==,
    3402                 :            :                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
    3403                 :          3 :         g_free (str);
    3404                 :            :       }
    3405                 :            : 
    3406                 :          1 :     g_variant_iter_free (i3);
    3407                 :            : 
    3408         [ +  + ]:          4 :     for (i = 0; i < g_variant_n_children (value); i++)
    3409                 :            :       {
    3410                 :            :         gsize j;
    3411                 :            : 
    3412                 :          3 :         g_variant_get_child (value, i, "*", &sub);
    3413                 :            : 
    3414         [ +  + ]:         21 :         for (j = 0; j < g_variant_n_children (sub); j++)
    3415                 :            :           {
    3416                 :         18 :             const gchar *str = NULL;
    3417                 :            :             GVariant *cval;
    3418                 :            : 
    3419                 :         18 :             g_variant_get_child (sub, j, "&s", &str);
    3420                 :         18 :             g_assert_cmpstr (str, ==, strvector[j]);
    3421                 :            : 
    3422                 :         18 :             cval = g_variant_get_child_value (sub, j);
    3423                 :         18 :             g_variant_get (cval, "&s", &str);
    3424                 :         18 :             g_assert_cmpstr (str, ==, strvector[j]);
    3425                 :         18 :             g_variant_unref (cval);
    3426                 :            :           }
    3427                 :            : 
    3428                 :          3 :         g_variant_unref (sub);
    3429                 :            :       }
    3430                 :            : 
    3431                 :          1 :     g_variant_unref (value);
    3432                 :            :   }
    3433                 :            : 
    3434                 :            :   {
    3435                 :            :     gboolean justs[10];
    3436                 :            :     GVariant *value;
    3437                 :            : 
    3438                 :            :     GVariant *vval;
    3439                 :            :     guchar byteval;
    3440                 :            :     gboolean bval;
    3441                 :            :     gint16 i16val;
    3442                 :            :     guint16 u16val;
    3443                 :            :     gint32 i32val;
    3444                 :            :     guint32 u32val;
    3445                 :            :     gint64 i64val;
    3446                 :            :     guint64 u64val;
    3447                 :            :     gdouble dval;
    3448                 :            :     gint32 hval;
    3449                 :            : 
    3450                 :            :     /* test all 'nothing' */
    3451                 :          1 :     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
    3452                 :            :                            FALSE, 'a',
    3453                 :            :                            FALSE, TRUE,
    3454                 :            :                            FALSE, (gint16) 123,
    3455                 :            :                            FALSE, (guint16) 123,
    3456                 :            :                            FALSE, (gint32) 123,
    3457                 :            :                            FALSE, (guint32) 123,
    3458                 :            :                            FALSE, (gint64) 123,
    3459                 :            :                            FALSE, (guint64) 123,
    3460                 :            :                            FALSE, (gint32) -1,
    3461                 :            :                            FALSE, (gdouble) 37.5,
    3462                 :            :                            NULL);
    3463                 :            : 
    3464                 :            :     /* both NULL */
    3465                 :          1 :     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
    3466                 :            :                    NULL, NULL,
    3467                 :            :                    NULL, NULL,
    3468                 :            :                    NULL, NULL,
    3469                 :            :                    NULL, NULL,
    3470                 :            :                    NULL, NULL,
    3471                 :            :                    NULL, NULL,
    3472                 :            :                    NULL, NULL,
    3473                 :            :                    NULL, NULL,
    3474                 :            :                    NULL, NULL,
    3475                 :            :                    NULL, NULL,
    3476                 :            :                    NULL);
    3477                 :            : 
    3478                 :            :     /* NULL values */
    3479                 :          1 :     memset (justs, 1, sizeof justs);
    3480                 :          1 :     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
    3481                 :            :                    &justs[0], NULL,
    3482                 :            :                    &justs[1], NULL,
    3483                 :            :                    &justs[2], NULL,
    3484                 :            :                    &justs[3], NULL,
    3485                 :            :                    &justs[4], NULL,
    3486                 :            :                    &justs[5], NULL,
    3487                 :            :                    &justs[6], NULL,
    3488                 :            :                    &justs[7], NULL,
    3489                 :            :                    &justs[8], NULL,
    3490                 :            :                    &justs[9], NULL,
    3491                 :            :                    NULL);
    3492                 :          1 :     g_assert_true (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
    3493                 :            :                      justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
    3494                 :            : 
    3495                 :            :     /* both non-NULL */
    3496                 :          1 :     memset (justs, 1, sizeof justs);
    3497                 :          1 :     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
    3498                 :          1 :     vval = (void *) 1;
    3499                 :          1 :     bval = TRUE;
    3500                 :          1 :     dval = 88.88;
    3501                 :          1 :     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
    3502                 :            :                    &justs[0], &byteval,
    3503                 :            :                    &justs[1], &bval,
    3504                 :            :                    &justs[2], &i16val,
    3505                 :            :                    &justs[3], &u16val,
    3506                 :            :                    &justs[4], &i32val,
    3507                 :            :                    &justs[5], &u32val,
    3508                 :            :                    &justs[6], &i64val,
    3509                 :            :                    &justs[7], &u64val,
    3510                 :            :                    &justs[8], &hval,
    3511                 :            :                    &justs[9], &dval,
    3512                 :            :                    &vval);
    3513                 :          1 :     g_assert_true (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
    3514                 :            :                      justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
    3515                 :          1 :     g_assert_true (byteval == '\0' && bval == FALSE);
    3516                 :          1 :     g_assert_true (i16val == 0 && u16val == 0 && i32val == 0 &&
    3517                 :            :                    u32val == 0 && i64val == 0 && u64val == 0 &&
    3518                 :            :                    hval == 0 && dval == 0.0);
    3519                 :          1 :     g_assert_null (vval);
    3520                 :            : 
    3521                 :            :     /* NULL justs */
    3522                 :          1 :     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
    3523                 :          1 :     vval = (void *) 1;
    3524                 :          1 :     bval = TRUE;
    3525                 :          1 :     dval = 88.88;
    3526                 :          1 :     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
    3527                 :            :                    NULL, &byteval,
    3528                 :            :                    NULL, &bval,
    3529                 :            :                    NULL, &i16val,
    3530                 :            :                    NULL, &u16val,
    3531                 :            :                    NULL, &i32val,
    3532                 :            :                    NULL, &u32val,
    3533                 :            :                    NULL, &i64val,
    3534                 :            :                    NULL, &u64val,
    3535                 :            :                    NULL, &hval,
    3536                 :            :                    NULL, &dval,
    3537                 :            :                    &vval);
    3538                 :          1 :     g_assert_true (byteval == '\0' && bval == FALSE);
    3539                 :          1 :     g_assert_true (i16val == 0 && u16val == 0 && i32val == 0 &&
    3540                 :            :                    u32val == 0 && i64val == 0 && u64val == 0 &&
    3541                 :            :                    hval == 0 && dval == 0.0);
    3542                 :          1 :     g_assert_null (vval);
    3543                 :            : 
    3544                 :          1 :     g_variant_unref (value);
    3545                 :            : 
    3546                 :            : 
    3547                 :            :     /* test all 'just' */
    3548                 :          1 :     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
    3549                 :            :                            TRUE, 'a',
    3550                 :            :                            TRUE, TRUE,
    3551                 :            :                            TRUE, (gint16) 123,
    3552                 :            :                            TRUE, (guint16) 123,
    3553                 :            :                            TRUE, (gint32) 123,
    3554                 :            :                            TRUE, (guint32) 123,
    3555                 :            :                            TRUE, (gint64) 123,
    3556                 :            :                            TRUE, (guint64) 123,
    3557                 :            :                            TRUE, (gint32) -1,
    3558                 :            :                            TRUE, (gdouble) 37.5,
    3559                 :            :                            g_variant_new ("()"));
    3560                 :            : 
    3561                 :            :     /* both NULL */
    3562                 :          1 :     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
    3563                 :            :                    NULL, NULL,
    3564                 :            :                    NULL, NULL,
    3565                 :            :                    NULL, NULL,
    3566                 :            :                    NULL, NULL,
    3567                 :            :                    NULL, NULL,
    3568                 :            :                    NULL, NULL,
    3569                 :            :                    NULL, NULL,
    3570                 :            :                    NULL, NULL,
    3571                 :            :                    NULL, NULL,
    3572                 :            :                    NULL, NULL,
    3573                 :            :                    NULL);
    3574                 :            : 
    3575                 :            :     /* NULL values */
    3576                 :          1 :     memset (justs, 0, sizeof justs);
    3577                 :          1 :     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
    3578                 :            :                    &justs[0], NULL,
    3579                 :            :                    &justs[1], NULL,
    3580                 :            :                    &justs[2], NULL,
    3581                 :            :                    &justs[3], NULL,
    3582                 :            :                    &justs[4], NULL,
    3583                 :            :                    &justs[5], NULL,
    3584                 :            :                    &justs[6], NULL,
    3585                 :            :                    &justs[7], NULL,
    3586                 :            :                    &justs[8], NULL,
    3587                 :            :                    &justs[9], NULL,
    3588                 :            :                    NULL);
    3589                 :          1 :     g_assert_true (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
    3590                 :            :                    justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
    3591                 :            : 
    3592                 :            :     /* both non-NULL */
    3593                 :          1 :     memset (justs, 0, sizeof justs);
    3594                 :          1 :     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
    3595                 :          1 :     vval = (void *) 1;
    3596                 :          1 :     bval = FALSE;
    3597                 :          1 :     dval = 88.88;
    3598                 :          1 :     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
    3599                 :            :                    &justs[0], &byteval,
    3600                 :            :                    &justs[1], &bval,
    3601                 :            :                    &justs[2], &i16val,
    3602                 :            :                    &justs[3], &u16val,
    3603                 :            :                    &justs[4], &i32val,
    3604                 :            :                    &justs[5], &u32val,
    3605                 :            :                    &justs[6], &i64val,
    3606                 :            :                    &justs[7], &u64val,
    3607                 :            :                    &justs[8], &hval,
    3608                 :            :                    &justs[9], &dval,
    3609                 :            :                    &vval);
    3610                 :          1 :     g_assert_true (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
    3611                 :            :                    justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
    3612                 :          1 :     g_assert_true (byteval == 'a' && bval == TRUE);
    3613                 :          1 :     g_assert_true (i16val == 123 && u16val == 123 && i32val == 123 &&
    3614                 :            :                    u32val == 123 && i64val == 123 && u64val == 123 &&
    3615                 :            :                    hval == -1 && dval == 37.5);
    3616                 :          1 :     g_assert_true (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
    3617                 :          1 :     g_variant_unref (vval);
    3618                 :            : 
    3619                 :            :     /* NULL justs */
    3620                 :          1 :     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
    3621                 :          1 :     vval = (void *) 1;
    3622                 :          1 :     bval = TRUE;
    3623                 :          1 :     dval = 88.88;
    3624                 :          1 :     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
    3625                 :            :                    NULL, &byteval,
    3626                 :            :                    NULL, &bval,
    3627                 :            :                    NULL, &i16val,
    3628                 :            :                    NULL, &u16val,
    3629                 :            :                    NULL, &i32val,
    3630                 :            :                    NULL, &u32val,
    3631                 :            :                    NULL, &i64val,
    3632                 :            :                    NULL, &u64val,
    3633                 :            :                    NULL, &hval,
    3634                 :            :                    NULL, &dval,
    3635                 :            :                    &vval);
    3636                 :          1 :     g_assert_true (byteval == 'a' && bval == TRUE);
    3637                 :          1 :     g_assert_true (i16val == 123 && u16val == 123 && i32val == 123 &&
    3638                 :            :                    u32val == 123 && i64val == 123 && u64val == 123 &&
    3639                 :            :                    hval == -1 && dval == 37.5);
    3640                 :          1 :     g_assert_true (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
    3641                 :          1 :     g_variant_unref (vval);
    3642                 :            : 
    3643                 :          1 :     g_variant_unref (value);
    3644                 :            :   }
    3645                 :            : 
    3646                 :            :   {
    3647                 :            :     GVariant *value;
    3648                 :            :     gchar *str;
    3649                 :            : 
    3650                 :          1 :     value = g_variant_new ("(masas)", NULL, NULL);
    3651                 :          1 :     g_variant_ref_sink (value);
    3652                 :            : 
    3653                 :          1 :     str = g_variant_print (value, TRUE);
    3654                 :          1 :     g_assert_cmpstr (str, ==, "(@mas nothing, @as [])");
    3655                 :          1 :     g_variant_unref (value);
    3656                 :          1 :     g_free (str);
    3657                 :            : 
    3658                 :          1 :     do_failed_test ("/gvariant/varargs/subprocess/empty-array",
    3659                 :            :                     "*which type of empty array*");
    3660                 :            :   }
    3661                 :            : 
    3662                 :          1 :   g_variant_type_info_assert_no_infos ();
    3663                 :          1 : }
    3664                 :            : 
    3665                 :            : static void
    3666                 :          2 : hash_get (GVariant    *value,
    3667                 :            :           const gchar *format,
    3668                 :            :           ...)
    3669                 :            : {
    3670                 :          2 :   const gchar *endptr = NULL;
    3671                 :            :   gboolean hash;
    3672                 :            :   va_list ap;
    3673                 :            : 
    3674   [ +  -  -  +  :          2 :   hash = g_str_has_suffix (format, "#");
                   +  - ]
    3675                 :            : 
    3676                 :          2 :   va_start (ap, format);
    3677         [ +  + ]:          2 :   g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
    3678                 :          2 :   va_end (ap);
    3679                 :            : 
    3680         [ +  + ]:          2 :   if (hash)
    3681                 :          1 :     g_assert_cmpint (*endptr, ==, '#');
    3682                 :          2 : }
    3683                 :            : 
    3684                 :            : static GVariant *
    3685                 :          2 : hash_new (const gchar *format,
    3686                 :            :           ...)
    3687                 :            : {
    3688                 :          2 :   const gchar *endptr = NULL;
    3689                 :            :   GVariant *value;
    3690                 :            :   gboolean hash;
    3691                 :            :   va_list ap;
    3692                 :            : 
    3693   [ +  -  -  +  :          2 :   hash = g_str_has_suffix (format, "#");
                   +  - ]
    3694                 :            : 
    3695                 :          2 :   va_start (ap, format);
    3696         [ +  + ]:          2 :   value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
    3697                 :          2 :   va_end (ap);
    3698                 :            : 
    3699         [ +  + ]:          2 :   if (hash)
    3700                 :          1 :     g_assert_cmpint (*endptr, ==, '#');
    3701                 :            : 
    3702                 :          2 :   return value;
    3703                 :            : }
    3704                 :            : 
    3705                 :            : static void
    3706                 :          1 : test_valist (void)
    3707                 :            : {
    3708                 :            :   GVariant *value;
    3709                 :            :   gint32 x;
    3710                 :            : 
    3711                 :          1 :   x = 0;
    3712                 :          1 :   value = hash_new ("i", 234);
    3713                 :          1 :   hash_get (value, "i", &x);
    3714                 :          1 :   g_assert_cmpint (x, ==, 234);
    3715                 :          1 :   g_variant_unref (value);
    3716                 :            : 
    3717                 :          1 :   x = 0;
    3718                 :          1 :   value = hash_new ("i#", 234);
    3719                 :          1 :   hash_get (value, "i#", &x);
    3720                 :          1 :   g_assert_cmpint (x, ==, 234);
    3721                 :          1 :   g_variant_unref (value);
    3722                 :            : 
    3723                 :          1 :   g_variant_type_info_assert_no_infos ();
    3724                 :          1 : }
    3725                 :            : 
    3726                 :            : static void
    3727                 :          1 : test_builder_memory (void)
    3728                 :            : {
    3729                 :            :   GVariantBuilder *hb;
    3730                 :            :   GVariantBuilder sb;
    3731                 :            : 
    3732                 :          1 :   hb = g_variant_builder_new  (G_VARIANT_TYPE_ARRAY);
    3733                 :          1 :   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
    3734                 :          1 :   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
    3735                 :          1 :   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
    3736                 :          1 :   g_variant_builder_add (hb, "s", "some value");
    3737                 :          1 :   g_variant_builder_ref (hb);
    3738                 :          1 :   g_variant_builder_unref (hb);
    3739                 :          1 :   g_variant_builder_unref (hb);
    3740                 :            : 
    3741                 :          1 :   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
    3742                 :          1 :   g_variant_builder_unref (hb);
    3743                 :            : 
    3744                 :          1 :   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
    3745                 :          1 :   g_variant_builder_clear (hb);
    3746                 :          1 :   g_variant_builder_unref (hb);
    3747                 :            : 
    3748                 :          1 :   g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
    3749                 :          1 :   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
    3750                 :          1 :   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
    3751                 :          1 :   g_variant_builder_add (&sb, "s", "some value");
    3752                 :          1 :   g_variant_builder_clear (&sb);
    3753                 :            : 
    3754                 :          1 :   g_variant_type_info_assert_no_infos ();
    3755                 :          1 : }
    3756                 :            : 
    3757                 :            : static void
    3758                 :          1 : test_hashing (void)
    3759                 :            : {
    3760                 :            :   GVariant *items[4096];
    3761                 :            :   GHashTable *table;
    3762                 :            :   gsize i;
    3763                 :            : 
    3764                 :          1 :   table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
    3765                 :            :                                  (GDestroyNotify ) g_variant_unref,
    3766                 :            :                                  NULL);
    3767                 :            : 
    3768         [ +  + ]:       4097 :   for (i = 0; i < G_N_ELEMENTS (items); i++)
    3769                 :            :     {
    3770                 :            :       TreeInstance *tree;
    3771                 :            :       gsize j;
    3772                 :            : 
    3773                 :       4626 :  again:
    3774                 :       4626 :       tree = tree_instance_new (NULL, 0);
    3775                 :       4626 :       items[i] = tree_instance_get_gvariant (tree);
    3776                 :       4626 :       tree_instance_free (tree);
    3777                 :            : 
    3778         [ +  + ]:    8562970 :       for (j = 0; j < i; j++)
    3779         [ +  + ]:    8558874 :         if (g_variant_equal (items[i], items[j]))
    3780                 :            :           {
    3781                 :        530 :             g_variant_unref (items[i]);
    3782                 :        530 :             goto again;
    3783                 :            :           }
    3784                 :            : 
    3785                 :       4096 :       g_hash_table_insert (table,
    3786                 :       4096 :                            g_variant_ref_sink (items[i]),
    3787                 :            :                            GINT_TO_POINTER (i));
    3788                 :            :     }
    3789                 :            : 
    3790         [ +  + ]:       4097 :   for (i = 0; i < G_N_ELEMENTS (items); i++)
    3791                 :            :     {
    3792                 :            :       gpointer result;
    3793                 :            : 
    3794                 :       4096 :       result = g_hash_table_lookup (table, items[i]);
    3795                 :       4096 :       g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
    3796                 :            :     }
    3797                 :            : 
    3798                 :          1 :   g_hash_table_unref (table);
    3799                 :            : 
    3800                 :          1 :   g_variant_type_info_assert_no_infos ();
    3801                 :          1 : }
    3802                 :            : 
    3803                 :            : static void
    3804                 :          1 : test_gv_byteswap (void)
    3805                 :            : {
    3806                 :            : #if G_BYTE_ORDER == G_LITTLE_ENDIAN
    3807                 :            : # define native16(x)  x, 0
    3808                 :            : # define swapped16(x) 0, x
    3809                 :            : #else
    3810                 :            : # define native16(x)  0, x
    3811                 :            : # define swapped16(x) x, 0
    3812                 :            : #endif
    3813                 :            :   /* all kinds of crazy randomised testing already performed on the
    3814                 :            :    * byteswapper in the /gvariant/serializer/byteswap test and all kinds
    3815                 :            :    * of crazy randomised testing performed against the serializer
    3816                 :            :    * normalisation functions in the /gvariant/serializer/fuzz/ tests.
    3817                 :            :    *
    3818                 :            :    * just test a few simple cases here to make sure they each work
    3819                 :            :    */
    3820                 :          1 :   guchar validbytes[] = { 'a', '\0', swapped16(66), 2,
    3821                 :            :                           0,
    3822                 :            :                           'b', '\0', swapped16(77), 2,
    3823                 :            :                           5, 11 };
    3824                 :          1 :   guchar corruptbytes[] = { 'a', '\0', swapped16(66), 2,
    3825                 :            :                             0,
    3826                 :            :                             'b', '\0', swapped16(77), 2,
    3827                 :            :                             6, 11 };
    3828                 :            :   guint valid_data[4], corrupt_data[4];
    3829                 :            :   GVariant *value, *swapped;
    3830                 :            :   gchar *string, *string2;
    3831                 :            : 
    3832                 :          1 :   memcpy (valid_data, validbytes, sizeof validbytes);
    3833                 :          1 :   memcpy (corrupt_data, corruptbytes, sizeof corruptbytes);
    3834                 :            : 
    3835                 :            :   /* trusted */
    3836                 :          1 :   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
    3837                 :            :                                    valid_data, sizeof validbytes, TRUE,
    3838                 :            :                                    NULL, NULL);
    3839                 :          1 :   swapped = g_variant_byteswap (value);
    3840                 :          1 :   g_variant_unref (value);
    3841                 :          1 :   g_assert_cmpuint (g_variant_get_size (swapped), ==, 13);
    3842                 :          1 :   string = g_variant_print (swapped, FALSE);
    3843                 :          1 :   g_variant_unref (swapped);
    3844                 :          1 :   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
    3845                 :          1 :   g_free (string);
    3846                 :            : 
    3847                 :            :   /* untrusted but valid */
    3848                 :          1 :   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
    3849                 :            :                                    valid_data, sizeof validbytes, FALSE,
    3850                 :            :                                    NULL, NULL);
    3851                 :          1 :   swapped = g_variant_byteswap (value);
    3852                 :          1 :   g_variant_unref (value);
    3853                 :          1 :   g_assert_cmpuint (g_variant_get_size (swapped), ==, 13);
    3854                 :          1 :   string = g_variant_print (swapped, FALSE);
    3855                 :          1 :   g_variant_unref (swapped);
    3856                 :          1 :   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
    3857                 :          1 :   g_free (string);
    3858                 :            : 
    3859                 :            :   /* untrusted, invalid */
    3860                 :          1 :   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
    3861                 :            :                                    corrupt_data, sizeof corruptbytes, FALSE,
    3862                 :            :                                    NULL, NULL);
    3863                 :          1 :   string = g_variant_print (value, FALSE);
    3864                 :          1 :   swapped = g_variant_byteswap (value);
    3865                 :          1 :   g_variant_unref (value);
    3866                 :          1 :   g_assert_cmpuint (g_variant_get_size (swapped), ==, 13);
    3867                 :          1 :   value = g_variant_byteswap (swapped);
    3868                 :          1 :   g_variant_unref (swapped);
    3869                 :          1 :   string2 = g_variant_print (value, FALSE);
    3870                 :          1 :   g_assert_cmpuint (g_variant_get_size (value), ==, 13);
    3871                 :          1 :   g_variant_unref (value);
    3872                 :          1 :   g_assert_cmpstr (string, ==, string2);
    3873                 :          1 :   g_free (string2);
    3874                 :          1 :   g_free (string);
    3875                 :          1 : }
    3876                 :            : 
    3877                 :            : static void
    3878                 :          1 : test_gv_byteswap_non_normal_non_aligned (void)
    3879                 :            : {
    3880                 :          1 :   const guint8 data[] = { 0x02 };
    3881                 :          1 :   GVariant *v = NULL;
    3882                 :          1 :   GVariant *v_byteswapped = NULL;
    3883                 :            : 
    3884                 :          1 :   g_test_summary ("Test that calling g_variant_byteswap() on a variant which "
    3885                 :            :                   "is in non-normal form and doesn’t need byteswapping returns "
    3886                 :            :                   "the same variant in normal form.");
    3887                 :            : 
    3888                 :          1 :   v = g_variant_new_from_data (G_VARIANT_TYPE_BOOLEAN, data, sizeof (data), FALSE, NULL, NULL);
    3889                 :          1 :   g_assert_false (g_variant_is_normal_form (v));
    3890                 :            : 
    3891                 :          1 :   v_byteswapped = g_variant_byteswap (v);
    3892                 :          1 :   g_assert_true (g_variant_is_normal_form (v_byteswapped));
    3893                 :            : 
    3894                 :          1 :   g_assert_cmpvariant (v, v_byteswapped);
    3895                 :            : 
    3896                 :          1 :   g_variant_unref (v);
    3897                 :          1 :   g_variant_unref (v_byteswapped);
    3898                 :          1 : }
    3899                 :            : 
    3900                 :            : static void
    3901                 :        100 : test_parser (void)
    3902                 :            : {
    3903                 :            :   TreeInstance *tree;
    3904                 :            :   GVariant *parsed;
    3905                 :            :   GVariant *value;
    3906                 :            :   gchar *pt, *p;
    3907                 :            :   gchar *res;
    3908                 :            : 
    3909                 :        100 :   tree = tree_instance_new (NULL, 3);
    3910                 :        100 :   value = tree_instance_get_gvariant (tree);
    3911                 :        100 :   tree_instance_free (tree);
    3912                 :            : 
    3913                 :        100 :   pt = g_variant_print (value, TRUE);
    3914                 :        100 :   p = g_variant_print (value, FALSE);
    3915                 :            : 
    3916                 :        100 :   parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
    3917                 :        100 :   res = g_variant_print (parsed, FALSE);
    3918                 :        100 :   g_assert_cmpstr (p, ==, res);
    3919                 :        100 :   g_variant_unref (parsed);
    3920                 :        100 :   g_free (res);
    3921                 :            : 
    3922                 :        100 :   parsed = g_variant_parse (g_variant_get_type (value), p,
    3923                 :            :                             NULL, NULL, NULL);
    3924                 :        100 :   res = g_variant_print (parsed, TRUE);
    3925                 :        100 :   g_assert_cmpstr (pt, ==, res);
    3926                 :        100 :   g_variant_unref (parsed);
    3927                 :        100 :   g_free (res);
    3928                 :            : 
    3929                 :        100 :   g_variant_unref (value);
    3930                 :        100 :   g_free (pt);
    3931                 :        100 :   g_free (p);
    3932                 :        100 : }
    3933                 :            : 
    3934                 :            : static void
    3935                 :          1 : test_parses (void)
    3936                 :            : {
    3937                 :            :   gsize i;
    3938                 :            : 
    3939         [ +  + ]:        101 :   for (i = 0; i < 100; i++)
    3940                 :            :     {
    3941                 :        100 :       test_parser ();
    3942                 :            :     }
    3943                 :            : 
    3944                 :            :   /* mini test */
    3945                 :            :   {
    3946                 :          1 :     GError *error = NULL;
    3947                 :            :     gchar str[128];
    3948                 :            :     GVariant *val;
    3949                 :            :     gchar *p, *p2;
    3950                 :            : 
    3951         [ +  + ]:        128 :     for (i = 0; i < 127; i++)
    3952                 :        127 :       str[i] = i + 1;
    3953                 :          1 :     str[i] = 0;
    3954                 :            : 
    3955                 :          1 :     val = g_variant_new_string (str);
    3956                 :          1 :     p = g_variant_print (val, FALSE);
    3957                 :          1 :     g_variant_unref (val);
    3958                 :            : 
    3959                 :          1 :     val = g_variant_parse (NULL, p, NULL, NULL, &error);
    3960                 :          1 :     p2 = g_variant_print (val, FALSE);
    3961                 :            : 
    3962                 :          1 :     g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
    3963                 :          1 :     g_assert_cmpstr (p, ==, p2);
    3964                 :            : 
    3965                 :          1 :     g_variant_unref (val);
    3966                 :          1 :     g_free (p2);
    3967                 :          1 :     g_free (p);
    3968                 :            :   }
    3969                 :            : 
    3970                 :            :   /* another mini test */
    3971                 :            :   {
    3972                 :            :     const gchar *end;
    3973                 :            :     GVariant *value;
    3974                 :            : 
    3975                 :          1 :     value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
    3976                 :          1 :     g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
    3977                 :            :     /* make sure endptr returning works */
    3978                 :          1 :     g_assert_cmpstr (end, ==, " 2 3");
    3979                 :          1 :     g_variant_unref (value);
    3980                 :            :   }
    3981                 :            : 
    3982                 :            :   /* unicode mini test */
    3983                 :            :   {
    3984                 :            :     /* ał𝄞 */
    3985                 :          1 :     const gchar orig[] = "a\xc5\x82\xf0\x9d\x84\x9e \t\n";
    3986                 :            :     GVariant *value;
    3987                 :            :     gchar *printed;
    3988                 :            : 
    3989                 :          1 :     value = g_variant_new_string (orig);
    3990                 :          1 :     printed = g_variant_print (value, FALSE);
    3991                 :          1 :     g_variant_unref (value);
    3992                 :            : 
    3993                 :          1 :     g_assert_cmpstr (printed, ==, "'a\xc5\x82\xf0\x9d\x84\x9e \\t\\n'");
    3994                 :          1 :     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
    3995                 :          1 :     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
    3996                 :          1 :     g_variant_unref (value);
    3997                 :          1 :     g_free (printed);
    3998                 :            :   }
    3999                 :            : 
    4000                 :            :   /* escapes */
    4001                 :            :   {
    4002                 :          1 :     const gchar orig[] = " \342\200\254 \360\220\210\240 \a \b \f \n \r \t \v ";
    4003                 :            :     GVariant *value;
    4004                 :            :     gchar *printed;
    4005                 :            : 
    4006                 :          1 :     value = g_variant_new_string (orig);
    4007                 :          1 :     printed = g_variant_print (value, FALSE);
    4008                 :          1 :     g_variant_unref (value);
    4009                 :            : 
    4010                 :          1 :     g_assert_cmpstr (printed, ==, "' \\u202c \\U00010220 \\a \\b \\f \\n \\r \\t \\v '");
    4011                 :          1 :     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
    4012                 :          1 :     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
    4013                 :          1 :     g_variant_unref (value);
    4014                 :          1 :     g_free (printed);
    4015                 :            :   }
    4016                 :            : 
    4017                 :            :   /* pattern coalese of `MN` and `*` is `MN` */
    4018                 :            :   {
    4019                 :          1 :     GVariant *value = NULL;
    4020                 :          1 :     GError *error = NULL;
    4021                 :            : 
    4022                 :          1 :     value = g_variant_parse (NULL, "[[0], [], [nothing]]", NULL, NULL, &error);
    4023                 :          1 :     g_assert_no_error (error);
    4024                 :          1 :     g_assert_cmpstr (g_variant_get_type_string (value), ==, "aami");
    4025                 :          1 :     g_variant_unref (value);
    4026                 :            :   }
    4027                 :            : 
    4028                 :            : #ifndef _MSC_VER
    4029                 :            :   /* inf/nan strings are C99 features which Visual C++ does not support */
    4030                 :            :   /* inf/nan mini test */
    4031                 :            :   {
    4032                 :          1 :     const gchar *tests[] = { "inf", "-inf", "nan" };
    4033                 :            :     GVariant *value;
    4034                 :            :     gchar *printed;
    4035                 :            :     gchar *printed_down;
    4036                 :            :     gsize i;
    4037                 :            : 
    4038         [ +  + ]:          4 :     for (i = 0; i < G_N_ELEMENTS (tests); i++)
    4039                 :            :       {
    4040                 :          3 :         GError *error = NULL;
    4041                 :          3 :         value = g_variant_parse (NULL, tests[i], NULL, NULL, &error);
    4042                 :          3 :         printed = g_variant_print (value, FALSE);
    4043                 :            :         /* Canonicalize to lowercase; https://bugzilla.gnome.org/show_bug.cgi?id=704585 */
    4044                 :          3 :         printed_down = g_ascii_strdown (printed, -1);
    4045                 :          3 :         g_assert_true (g_str_has_prefix (printed_down, tests[i]));
    4046                 :          3 :         g_free (printed);
    4047                 :          3 :         g_free (printed_down);
    4048                 :          3 :         g_variant_unref (value);
    4049                 :            :       }
    4050                 :            :   }
    4051                 :            : #endif
    4052                 :            : 
    4053                 :          1 :   g_variant_type_info_assert_no_infos ();
    4054                 :          1 : }
    4055                 :            : 
    4056                 :            : static void
    4057                 :          1 : test_parse_failures (void)
    4058                 :            : {
    4059                 :          1 :   const gchar *test[] = {
    4060                 :            :     "[1, 2,",                   "6:",              "expected value",
    4061                 :            :     "",                         "0:",              "expected value",
    4062                 :            :     "(1, 2,",                   "6:",              "expected value",
    4063                 :            :     "<1",                       "2:",              "expected '>'",
    4064                 :            :     "[]",                       "0-2:",            "unable to infer",
    4065                 :            :     "(,",                       "1:",              "expected value",
    4066                 :            :     "[4,'']",                   "1-2,3-5:",        "common type",
    4067                 :            :     "[4, '', 5]",               "1-2,4-6:",        "common type",
    4068                 :            :     "['', 4, 5]",               "1-3,5-6:",        "common type",
    4069                 :            :     "[4, 5, '']",               "1-2,7-9:",        "common type",
    4070                 :            :     "[[4], [], ['']]",          "1-4,10-14:",      "common type",
    4071                 :            :     "[[], [4], ['']]",          "5-8,10-14:",      "common type",
    4072                 :            :     "just",                     "4:",              "expected value",
    4073                 :            :     "nothing",                  "0-7:",            "unable to infer",
    4074                 :            :     "just [4, '']",             "6-7,9-11:",       "common type",
    4075                 :            :     "[[4,'']]",                 "2-3,4-6:",        "common type",
    4076                 :            :     "([4,''],)",                "2-3,4-6:",        "common type",
    4077                 :            :     "(4)",                      "2:",              "','",
    4078                 :            :     "{}",                       "0-2:",            "unable to infer",
    4079                 :            :     "{[1,2],[3,4]}",            "0-13:",           "basic types",
    4080                 :            :     "{[1,2]:[3,4]}",            "0-13:",           "basic types",
    4081                 :            :     "justt",                    "0-5:",            "unknown keyword",
    4082                 :            :     "nothng",                   "0-6:",            "unknown keyword",
    4083                 :            :     "uint33",                   "0-6:",            "unknown keyword",
    4084                 :            :     "@mi just ''",              "9-11:",           "can not parse as",
    4085                 :            :     "@ai ['']",                 "5-7:",            "can not parse as",
    4086                 :            :     "@(i) ('',)",               "6-8:",            "can not parse as",
    4087                 :            :     "[[], 5]",                  "1-3,5-6:",        "common type",
    4088                 :            :     "[[5], 5]",                 "1-4,6-7:",        "common type",
    4089                 :            :     "5 5",                      "2:",              "expected end of input",
    4090                 :            :     "[5, [5, '']]",             "5-6,8-10:",       "common type",
    4091                 :            :     "@i just 5",                "3-9:",            "can not parse as",
    4092                 :            :     "@i nothing",               "3-10:",           "can not parse as",
    4093                 :            :     "@i []",                    "3-5:",            "can not parse as",
    4094                 :            :     "@i ()",                    "3-5:",            "can not parse as",
    4095                 :            :     "@ai (4,)",                 "4-8:",            "can not parse as",
    4096                 :            :     "@(i) []",                  "5-7:",            "can not parse as",
    4097                 :            :     "(5 5)",                    "3:",              "expected ','",
    4098                 :            :     "[5 5]",                    "3:",              "expected ',' or ']'",
    4099                 :            :     "(5, 5 5)",                 "6:",              "expected ',' or ')'",
    4100                 :            :     "[5, 5 5]",                 "6:",              "expected ',' or ']'",
    4101                 :            :     "<@i []>",                  "4-6:",            "can not parse as",
    4102                 :            :     "<[5 5]>",                  "4:",              "expected ',' or ']'",
    4103                 :            :     "{[4,''],5}",               "2-3,4-6:",        "common type",
    4104                 :            :     "{5,[4,'']}",               "4-5,6-8:",        "common type",
    4105                 :            :     "@i {1,2}",                 "3-8:",            "can not parse as",
    4106                 :            :     "{@i '', 5}",               "4-6:",            "can not parse as",
    4107                 :            :     "{5, @i ''}",               "7-9:",            "can not parse as",
    4108                 :            :     "@ai {}",                   "4-6:",            "can not parse as",
    4109                 :            :     "{@i '': 5}",               "4-6:",            "can not parse as",
    4110                 :            :     "{5: @i ''}",               "7-9:",            "can not parse as",
    4111                 :            :     "{<4,5}",                   "3:",              "expected '>'",
    4112                 :            :     "{4,<5}",                   "5:",              "expected '>'",
    4113                 :            :     "{4,5,6}",                  "4:",              "expected '}'",
    4114                 :            :     "{5 5}",                    "3:",              "expected ':' or ','",
    4115                 :            :     "{4: 5: 6}",                "5:",              "expected ',' or '}'",
    4116                 :            :     "{4:5,<6:7}",               "7:",              "expected '>'",
    4117                 :            :     "{4:5,6:<7}",               "9:",              "expected '>'",
    4118                 :            :     "{4:5,6 7}",                "7:",              "expected ':'",
    4119                 :            :     "@o 'foo'",                 "3-8:",            "object path",
    4120                 :            :     "@g 'zzz'",                 "3-8:",            "signature",
    4121                 :            :     "@i true",                  "3-7:",            "can not parse as",
    4122                 :            :     "@z 4",                     "0-2:",            "invalid type",
    4123                 :            :     "@a* []",                   "0-3:",            "definite",
    4124                 :            :     "@ai [3 3]",                "7:",              "expected ',' or ']'",
    4125                 :            :     "18446744073709551616",     "0-20:",           "too big for any type",
    4126                 :            :     "-18446744073709551616",    "0-21:",           "too big for any type",
    4127                 :            :     "byte 256",                 "5-8:",            "out of range for type",
    4128                 :            :     "byte -1",                  "5-7:",            "out of range for type",
    4129                 :            :     "int16 32768",              "6-11:",           "out of range for type",
    4130                 :            :     "int16 -32769",             "6-12:",           "out of range for type",
    4131                 :            :     "uint16 -1",                "7-9:",            "out of range for type",
    4132                 :            :     "uint16 65536",             "7-12:",           "out of range for type",
    4133                 :            :     "2147483648",               "0-10:",           "out of range for type",
    4134                 :            :     "-2147483649",              "0-11:",           "out of range for type",
    4135                 :            :     "uint32 -1",                "7-9:",            "out of range for type",
    4136                 :            :     "uint32 4294967296",        "7-17:",           "out of range for type",
    4137                 :            :     "@x 9223372036854775808",   "3-22:",           "out of range for type",
    4138                 :            :     "@x -9223372036854775809",  "3-23:",           "out of range for type",
    4139                 :            :     "@t -1",                    "3-5:",            "out of range for type",
    4140                 :            :     "@t 18446744073709551616",  "3-23:",           "too big for any type",
    4141                 :            :     "handle 2147483648",        "7-17:",           "out of range for type",
    4142                 :            :     "handle -2147483649",       "7-18:",           "out of range for type",
    4143                 :            :     "1.798e308",                "0-9:",            "too big for any type",
    4144                 :            :     "37.5a488",                 "4-5:",            "invalid character",
    4145                 :            :     "0x7ffgf",                  "5-6:",            "invalid character",
    4146                 :            :     "07758",                    "4-5:",            "invalid character",
    4147                 :            :     "123a5",                    "3-4:",            "invalid character",
    4148                 :            :     "@ai 123",                  "4-7:",            "can not parse as",
    4149                 :            :     "'\"\\'",                   "0-4:",            "unterminated string",
    4150                 :            :     "'\"\\'\\",                 "0-5:",            "unterminated string",
    4151                 :            :     "boolean 4",                "8-9:",            "can not parse as",
    4152                 :            :     "int32 true",               "6-10:",           "can not parse as",
    4153                 :            :     "[double 5, int32 5]",      "1-9,11-18:",      "common type",
    4154                 :            :     "string 4",                 "7-8:",            "can not parse as",
    4155                 :            :     "\x0a",                     "1:",              "expected value",
    4156                 :            :     "((",                       "2:",              "expected value",
    4157                 :            :     "(b",                       "1:",              "expected value",
    4158                 :            :     "b'",                       "0-2:",            "unterminated string constant",
    4159                 :            :     "b\"",                      "0-2:",            "unterminated string constant",
    4160                 :            :     "b'a",                      "0-3:",            "unterminated string constant",
    4161                 :            :     "b\"a",                     "0-3:",            "unterminated string constant",
    4162                 :            :     "b'\\",                     "0-3:",            "unterminated string constant",
    4163                 :            :     "b\"\\",                    "0-3:",            "unterminated string constant",
    4164                 :            :     "b'\\'",                    "0-4:",            "unterminated string constant",
    4165                 :            :     "b\"\\\"",                  "0-4:",            "unterminated string constant",
    4166                 :            :     "b'\\'a",                   "0-5:",            "unterminated string constant",
    4167                 :            :     "b\"\\\"a",                 "0-5:",            "unterminated string constant",
    4168                 :            :     "'\\u-ff4'",                "3:",              "invalid 4-character unicode escape",
    4169                 :            :     "'\\u+ff4'",                "3:",              "invalid 4-character unicode escape",
    4170                 :            :     "'\\u'",                    "3:",              "invalid 4-character unicode escape",
    4171                 :            :     "'\\u0'",                   "3-4:",            "invalid 4-character unicode escape",
    4172                 :            :     "'\\uHELLO'",               "3:",              "invalid 4-character unicode escape",
    4173                 :            :     "'\\u ff4'",                "3:",              "invalid 4-character unicode escape",
    4174                 :            :     "'\\u012'",                 "3-6:",            "invalid 4-character unicode escape",
    4175                 :            :     "'\\u0xff4'",               "3-4:",            "invalid 4-character unicode escape",
    4176                 :            :     "'\\U-ff4'",                "3:",              "invalid 8-character unicode escape",
    4177                 :            :     "'\\U+ff4'",                "3:",              "invalid 8-character unicode escape",
    4178                 :            :     "'\\U'",                    "3:",              "invalid 8-character unicode escape",
    4179                 :            :     "'\\U0'",                   "3-4:",            "invalid 8-character unicode escape",
    4180                 :            :     "'\\UHELLO'",               "3:",              "invalid 8-character unicode escape",
    4181                 :            :     "'\\U ff4'",                "3:",              "invalid 8-character unicode escape",
    4182                 :            :     "'\\U0123456'",             "3-10:",           "invalid 8-character unicode escape",
    4183                 :            :     "'\\U0xff4'",               "3-4:",            "invalid 8-character unicode escape",
    4184                 :            :   };
    4185                 :            :   guint i;
    4186                 :            : 
    4187         [ +  + ]:        125 :   for (i = 0; i < G_N_ELEMENTS (test); i += 3)
    4188                 :            :     {
    4189                 :        124 :       GError *error1 = NULL, *error2 = NULL;
    4190                 :            :       GVariant *value;
    4191                 :            : 
    4192                 :            :       /* Copy the test string and drop its nul terminator, then use the @limit
    4193                 :            :        * parameter of g_variant_parse() to set the length. This allows valgrind
    4194                 :            :        * to catch 1-byte heap buffer overflows. */
    4195         [ +  + ]:        124 :       gsize test_len = MAX (strlen (test[i]), 1);
    4196                 :        124 :       gchar *test_blob = g_malloc0 (test_len);  /* no nul terminator */
    4197                 :            : 
    4198                 :        124 :       memcpy (test_blob, test[i], test_len);
    4199                 :        124 :       value = g_variant_parse (NULL, test_blob, test_blob + test_len, NULL, &error1);
    4200                 :        124 :       g_assert_null (value);
    4201                 :            : 
    4202                 :        124 :       g_free (test_blob);
    4203                 :            : 
    4204         [ -  + ]:        124 :       if (!strstr (error1->message, test[i+2]))
    4205                 :          0 :         g_error ("test %u: Can't find '%s' in '%s'", i / 3,
    4206                 :            :                  test[i+2], error1->message);
    4207                 :            : 
    4208         [ -  + ]:        124 :       if (!g_str_has_prefix (error1->message, test[i+1]))
    4209                 :          0 :         g_error ("test %u: Expected location '%s' in '%s'", i / 3,
    4210                 :            :                  test[i+1], error1->message);
    4211                 :            : 
    4212                 :            :       /* Test again with the nul terminator this time. The behaviour should be
    4213                 :            :        * the same. */
    4214                 :        124 :       value = g_variant_parse (NULL, test[i], NULL, NULL, &error2);
    4215                 :        124 :       g_assert_null (value);
    4216                 :            : 
    4217                 :        124 :       g_assert_cmpint (error1->domain, ==, error2->domain);
    4218                 :        124 :       g_assert_cmpint (error1->code, ==, error2->code);
    4219                 :        124 :       g_assert_cmpstr (error1->message, ==, error2->message);
    4220                 :            : 
    4221                 :        124 :       g_clear_error (&error1);
    4222                 :        124 :       g_clear_error (&error2);
    4223                 :            :     }
    4224                 :          1 : }
    4225                 :            : 
    4226                 :            : /* Test that parsing GVariant text format integers works at the boundaries of
    4227                 :            :  * those integer types. We’re especially interested in the handling of the most
    4228                 :            :  * negative numbers, since those can’t be represented in sign + absolute value
    4229                 :            :  * form. */
    4230                 :            : static void
    4231                 :          1 : test_parser_integer_bounds (void)
    4232                 :            : {
    4233                 :          1 :   GVariant *value = NULL;
    4234                 :          1 :   GError *local_error = NULL;
    4235                 :            : 
    4236                 :            : #define test_bound(TYPE, type, text, expected_value) \
    4237                 :            :   value = g_variant_parse (G_VARIANT_TYPE_##TYPE, text, NULL, NULL, &local_error); \
    4238                 :            :   g_assert_no_error (local_error); \
    4239                 :            :   g_assert_nonnull (value); \
    4240                 :            :   g_assert_true (g_variant_is_of_type (value, G_VARIANT_TYPE_##TYPE)); \
    4241                 :            :   g_assert_cmpint (g_variant_get_##type (value), ==, expected_value); \
    4242                 :            :   g_variant_unref (value)
    4243                 :            : 
    4244   [ -  +  -  +  :          1 :   test_bound (BYTE, byte, "0", 0);
             -  +  -  + ]
    4245   [ -  +  -  +  :          1 :   test_bound (BYTE, byte, "255", G_MAXUINT8);
             -  +  -  + ]
    4246   [ -  +  -  +  :          1 :   test_bound (INT16, int16, "-32768", G_MININT16);
             -  +  -  + ]
    4247   [ -  +  -  +  :          1 :   test_bound (INT16, int16, "32767", G_MAXINT16);
             -  +  -  + ]
    4248   [ -  +  -  +  :          1 :   test_bound (INT32, int32, "-2147483648", G_MININT32);
             -  +  -  + ]
    4249   [ -  +  -  +  :          1 :   test_bound (INT32, int32, "2147483647", G_MAXINT32);
             -  +  -  + ]
    4250   [ -  +  -  +  :          1 :   test_bound (INT64, int64, "-9223372036854775808", G_MININT64);
             -  +  -  + ]
    4251   [ -  +  -  +  :          1 :   test_bound (INT64, int64, "9223372036854775807", G_MAXINT64);
             -  +  -  + ]
    4252   [ -  +  -  +  :          1 :   test_bound (HANDLE, handle, "-2147483648", G_MININT32);
             -  +  -  + ]
    4253   [ -  +  -  +  :          1 :   test_bound (HANDLE, handle, "2147483647", G_MAXINT32);
             -  +  -  + ]
    4254                 :            : 
    4255                 :            : #undef test_bound
    4256                 :          1 : }
    4257                 :            : 
    4258                 :            : /* Test that #GVariants which recurse too deeply are rejected. */
    4259                 :            : static void
    4260                 :          1 : test_parser_recursion (void)
    4261                 :            : {
    4262                 :          1 :   GVariant *value = NULL;
    4263                 :          1 :   GError *local_error = NULL;
    4264                 :          1 :   const guint recursion_depth = G_VARIANT_MAX_RECURSION_DEPTH + 1;
    4265                 :          1 :   gchar *silly_dict = g_malloc0 (recursion_depth * 2 + 1);
    4266                 :            :   gsize i;
    4267                 :            : 
    4268         [ +  + ]:        130 :   for (i = 0; i < recursion_depth; i++)
    4269                 :            :     {
    4270                 :        129 :       silly_dict[i] = '{';
    4271                 :        129 :       silly_dict[recursion_depth * 2 - i - 1] = '}';
    4272                 :            :     }
    4273                 :            : 
    4274                 :          1 :   value = g_variant_parse (NULL, silly_dict, NULL, NULL, &local_error);
    4275                 :          1 :   g_assert_error (local_error, G_VARIANT_PARSE_ERROR, G_VARIANT_PARSE_ERROR_RECURSION);
    4276                 :          1 :   g_assert_null (value);
    4277                 :          1 :   g_error_free (local_error);
    4278                 :          1 :   g_free (silly_dict);
    4279                 :          1 : }
    4280                 :            : 
    4281                 :            : /* Test that #GVariants which recurse too deeply through use of typedecls are
    4282                 :            :  * rejected. This is a sneaky way to multiply the number of objects in a text
    4283                 :            :  * representation of a #GVariant without making the text-form proportionately
    4284                 :            :  * long. It uses a typedecl to nest one of the elements deeply within nested
    4285                 :            :  * maybes, while keeping all the other elements un-nested in the text form. It
    4286                 :            :  * relies on g_variant_parse() not being provided with a concrete type for the
    4287                 :            :  * top-level #GVariant. */
    4288                 :            : static void
    4289                 :          1 : test_parser_recursion_typedecls (void)
    4290                 :            : {
    4291                 :          1 :   GVariant *value = NULL;
    4292                 :          1 :   GError *local_error = NULL;
    4293                 :          1 :   const guint recursion_depth = G_VARIANT_MAX_RECURSION_DEPTH - 1;
    4294                 :          1 :   gchar *silly_type = g_malloc0 (recursion_depth + 2 /* trailing `u` and then nul */);
    4295                 :          1 :   gchar *silly_array = NULL;
    4296                 :            :   gsize i;
    4297                 :            : 
    4298         [ +  + ]:        128 :   for (i = 0; i < recursion_depth; i++)
    4299                 :        127 :     silly_type[i] = 'm';
    4300                 :          1 :   silly_type[recursion_depth] = 'u';
    4301                 :            : 
    4302                 :          1 :   silly_array = g_strdup_printf ("[1,2,3,@%s 0]", silly_type);
    4303                 :            : 
    4304                 :          1 :   value = g_variant_parse (NULL, silly_array, NULL, NULL, &local_error);
    4305                 :          1 :   g_assert_error (local_error, G_VARIANT_PARSE_ERROR, G_VARIANT_PARSE_ERROR_RECURSION);
    4306                 :          1 :   g_assert_null (value);
    4307                 :          1 :   g_error_free (local_error);
    4308                 :          1 :   g_free (silly_array);
    4309                 :          1 :   g_free (silly_type);
    4310                 :          1 : }
    4311                 :            : 
    4312                 :            : static void
    4313                 :          1 : test_parser_recursion_maybes (void)
    4314                 :            : {
    4315                 :          1 :   const gchar *hello = "hello";
    4316                 :            :   struct
    4317                 :            :     {
    4318                 :            :       const gchar *text_form;  /* (not nullable) */
    4319                 :            :       GVariant *expected_variant;  /* (not nullable) (owned) */
    4320                 :            :     }
    4321                 :          9 :   vectors[] =
    4322                 :            :     {
    4323                 :            :       {
    4324                 :            :         /* fixed size base value */
    4325                 :            :         "@mmmu 5",
    4326                 :          1 :         g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_uint32 (5)))))
    4327                 :            :       },
    4328                 :            :       {
    4329                 :            :         /* variable size base value */
    4330                 :            :         "@mmmas ['hello']",
    4331                 :          1 :         g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_strv (&hello, 1)))))
    4332                 :            :       },
    4333                 :            :       {
    4334                 :            :         /* fixed size base value, unset */
    4335                 :            :         "@mmmu just just nothing",
    4336                 :          1 :         g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_maybe (G_VARIANT_TYPE_UINT32, NULL))))
    4337                 :            :       },
    4338                 :            :       {
    4339                 :            :         /* variable size base value, unset */
    4340                 :            :         "@mmmas just just nothing",
    4341                 :          1 :         g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_maybe (G_VARIANT_TYPE_STRING_ARRAY, NULL))))
    4342                 :            :       },
    4343                 :            :       {
    4344                 :            :         /* fixed size base value, unset */
    4345                 :            :         "@mmmu just nothing",
    4346                 :          1 :         g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (G_VARIANT_TYPE ("mu"), NULL)))
    4347                 :            :       },
    4348                 :            :       {
    4349                 :            :         /* variable size base value, unset */
    4350                 :            :         "@mmmas just nothing",
    4351                 :          1 :         g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (G_VARIANT_TYPE ("mas"), NULL)))
    4352                 :            :       },
    4353                 :            :       {
    4354                 :            :         /* fixed size base value, unset */
    4355                 :            :         "@mmmu nothing",
    4356                 :          1 :         g_variant_ref_sink (g_variant_new_maybe (G_VARIANT_TYPE ("mmu"), NULL))
    4357                 :            :       },
    4358                 :            :       {
    4359                 :            :         /* variable size base value, unset */
    4360                 :            :         "@mmmas nothing",
    4361                 :          1 :         g_variant_ref_sink (g_variant_new_maybe (G_VARIANT_TYPE ("mmas"), NULL))
    4362                 :            :       },
    4363                 :            :     };
    4364                 :            :   gsize i;
    4365                 :            : 
    4366                 :          1 :   g_test_summary ("Test that nested maybes are handled correctly when parsing text-form variants");
    4367                 :          1 :   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2782");
    4368                 :            : 
    4369         [ +  + ]:          9 :   for (i = 0; i < G_N_ELEMENTS (vectors); i++)
    4370                 :            :     {
    4371                 :          8 :       GVariant *value = NULL;
    4372                 :          8 :       GError *local_error = NULL;
    4373                 :            : 
    4374                 :          8 :       g_test_message ("Text form %" G_GSIZE_FORMAT ": %s", i, vectors[i].text_form);
    4375                 :            : 
    4376                 :          8 :       value = g_variant_parse (NULL, vectors[i].text_form, NULL, NULL, &local_error);
    4377                 :          8 :       g_assert_no_error (local_error);
    4378                 :          8 :       g_assert_nonnull (value);
    4379                 :            : 
    4380                 :          8 :       g_assert_cmpvariant (value, vectors[i].expected_variant);
    4381                 :            : 
    4382                 :          8 :       g_variant_unref (value);
    4383                 :            : 
    4384                 :          8 :       g_clear_pointer (&vectors[i].expected_variant, g_variant_unref);
    4385                 :            :     }
    4386                 :          1 : }
    4387                 :            : 
    4388                 :            : static void
    4389                 :          0 : test_parse_bad_format_char (void)
    4390                 :            : {
    4391                 :          0 :   g_variant_new_parsed ("%z");
    4392                 :            : 
    4393                 :            :   g_assert_not_reached ();
    4394                 :            : }
    4395                 :            : 
    4396                 :            : static void
    4397                 :          0 : test_parse_bad_format_string (void)
    4398                 :            : {
    4399                 :          0 :   g_variant_new_parsed ("uint32 %i", 2);
    4400                 :            : 
    4401                 :            :   g_assert_not_reached ();
    4402                 :            : }
    4403                 :            : 
    4404                 :            : static void
    4405                 :          0 : test_parse_bad_args (void)
    4406                 :            : {
    4407                 :          0 :   g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
    4408                 :            : 
    4409                 :            :   g_assert_not_reached ();
    4410                 :            : }
    4411                 :            : 
    4412                 :            : static void
    4413                 :          1 : test_parse_positional (void)
    4414                 :            : {
    4415                 :            :   GVariant *value;
    4416                 :          1 :   check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
    4417                 :            :                                         " ('three', %i)]", "two", 3),
    4418                 :            :                   "[('one', 1), ('two', 2), ('three', 3)]");
    4419                 :          1 :   value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
    4420                 :            :                                 " ('three', %u)]", "two", 3);
    4421                 :          1 :   g_assert_true (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
    4422                 :          1 :   check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
    4423                 :          1 :   check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
    4424                 :            : 
    4425         [ +  - ]:          1 :   if (g_test_undefined ())
    4426                 :            :     {
    4427                 :          1 :       do_failed_test ("/gvariant/parse/subprocess/bad-format-char",
    4428                 :            :                       "*GVariant format string*");
    4429                 :            : 
    4430                 :          1 :       do_failed_test ("/gvariant/parse/subprocess/bad-format-string",
    4431                 :            :                       "*can not parse as*");
    4432                 :            : 
    4433                 :          1 :       do_failed_test ("/gvariant/parse/subprocess/bad-args",
    4434                 :            :                       "*expected GVariant of type 'i'*");
    4435                 :            :     }
    4436                 :          1 : }
    4437                 :            : 
    4438                 :            : static void
    4439                 :          1 : test_floating (void)
    4440                 :            : {
    4441                 :            :   GVariant *value;
    4442                 :            : 
    4443                 :          1 :   value = g_variant_new_int32 (42);
    4444                 :          1 :   g_assert_true (g_variant_is_floating (value));
    4445                 :          1 :   g_variant_ref_sink (value);
    4446                 :          1 :   g_assert_true (!g_variant_is_floating (value));
    4447                 :          1 :   g_variant_unref (value);
    4448                 :          1 : }
    4449                 :            : 
    4450                 :            : static void
    4451                 :          1 : test_bytestring (void)
    4452                 :            : {
    4453                 :          1 :   const gchar *test_string = "foo,bar,baz,quux,\xffoooo";
    4454                 :            :   GVariant *value;
    4455                 :            :   gchar **strv;
    4456                 :            :   gchar *str;
    4457                 :            :   const gchar *const_str;
    4458                 :            :   GVariant *untrusted_empty;
    4459                 :            : 
    4460                 :          1 :   strv = g_strsplit (test_string, ",", 0);
    4461                 :            : 
    4462                 :          1 :   value = g_variant_new_bytestring_array ((const gchar **) strv, -1);
    4463                 :          1 :   g_assert_true (g_variant_is_floating (value));
    4464                 :          1 :   g_strfreev (strv);
    4465                 :            : 
    4466                 :          1 :   str = g_variant_print (value, FALSE);
    4467                 :          1 :   g_variant_unref (value);
    4468                 :            : 
    4469                 :          1 :   value = g_variant_parse (NULL, str, NULL, NULL, NULL);
    4470                 :          1 :   g_free (str);
    4471                 :            : 
    4472                 :          1 :   strv = g_variant_dup_bytestring_array (value, NULL);
    4473                 :          1 :   g_variant_unref (value);
    4474                 :            : 
    4475                 :          1 :   str = g_strjoinv (",", strv);
    4476                 :          1 :   g_strfreev (strv);
    4477                 :            : 
    4478                 :          1 :   g_assert_cmpstr (str, ==, test_string);
    4479                 :          1 :   g_free (str);
    4480                 :            : 
    4481                 :          1 :   strv = g_strsplit (test_string, ",", 0);
    4482                 :          1 :   value = g_variant_new ("(^aay^a&ay^ay^&ay)",
    4483                 :            :                          strv, strv, strv[0], strv[0]);
    4484                 :          1 :   g_strfreev (strv);
    4485                 :            : 
    4486                 :          1 :   g_variant_get_child (value, 0, "^a&ay", &strv);
    4487                 :          1 :   str = g_strjoinv (",", strv);
    4488                 :          1 :   g_free (strv);
    4489                 :          1 :   g_assert_cmpstr (str, ==, test_string);
    4490                 :          1 :   g_free (str);
    4491                 :            : 
    4492                 :          1 :   g_variant_get_child (value, 0, "^aay", &strv);
    4493                 :          1 :   str = g_strjoinv (",", strv);
    4494                 :          1 :   g_strfreev (strv);
    4495                 :          1 :   g_assert_cmpstr (str, ==, test_string);
    4496                 :          1 :   g_free (str);
    4497                 :            : 
    4498                 :          1 :   g_variant_get_child (value, 1, "^a&ay", &strv);
    4499                 :          1 :   str = g_strjoinv (",", strv);
    4500                 :          1 :   g_free (strv);
    4501                 :          1 :   g_assert_cmpstr (str, ==, test_string);
    4502                 :          1 :   g_free (str);
    4503                 :            : 
    4504                 :          1 :   g_variant_get_child (value, 1, "^aay", &strv);
    4505                 :          1 :   str = g_strjoinv (",", strv);
    4506                 :          1 :   g_strfreev (strv);
    4507                 :          1 :   g_assert_cmpstr (str, ==, test_string);
    4508                 :          1 :   g_free (str);
    4509                 :            : 
    4510                 :          1 :   g_variant_get_child (value, 2, "^ay", &str);
    4511                 :          1 :   g_assert_cmpstr (str, ==, "foo");
    4512                 :          1 :   g_free (str);
    4513                 :            : 
    4514                 :          1 :   g_variant_get_child (value, 2, "^&ay", &str);
    4515                 :          1 :   g_assert_cmpstr (str, ==, "foo");
    4516                 :            : 
    4517                 :          1 :   g_variant_get_child (value, 3, "^ay", &str);
    4518                 :          1 :   g_assert_cmpstr (str, ==, "foo");
    4519                 :          1 :   g_free (str);
    4520                 :            : 
    4521                 :          1 :   g_variant_get_child (value, 3, "^&ay", &str);
    4522                 :          1 :   g_assert_cmpstr (str, ==, "foo");
    4523                 :          1 :   g_variant_unref (value);
    4524                 :            : 
    4525                 :          1 :   untrusted_empty = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL);
    4526                 :          1 :   value = g_variant_get_normal_form (untrusted_empty);
    4527                 :          1 :   const_str = g_variant_get_bytestring (value);
    4528                 :            :   (void) const_str;
    4529                 :          1 :   g_variant_unref (value);
    4530                 :          1 :   g_variant_unref (untrusted_empty);
    4531                 :          1 : }
    4532                 :            : 
    4533                 :            : static void
    4534                 :          1 : test_lookup_value (void)
    4535                 :            : {
    4536                 :            :   struct {
    4537                 :            :     const gchar *dict, *key, *value;
    4538                 :          1 :   } cases[] = {
    4539                 :            :     { "@a{ss} {'x':  'y'}",   "x",  "'y'" },
    4540                 :            :     { "@a{ss} {'x':  'y'}",   "y",  NULL  },
    4541                 :            :     { "@a{os} {'/x': 'y'}",   "/x", "'y'" },
    4542                 :            :     { "@a{os} {'/x': 'y'}",   "/y", NULL  },
    4543                 :            :     { "@a{sv} {'x':  <'y'>}", "x",  "'y'" },
    4544                 :            :     { "@a{sv} {'x':  <5>}",   "x",  "5"   },
    4545                 :            :     { "@a{sv} {'x':  <'y'>}", "y",  NULL  }
    4546                 :            :   };
    4547                 :            :   gsize i;
    4548                 :            : 
    4549         [ +  + ]:          8 :   for (i = 0; i < G_N_ELEMENTS (cases); i++)
    4550                 :            :     {
    4551                 :            :       GVariant *dictionary;
    4552                 :            :       GVariant *value;
    4553                 :            :       gchar *p;
    4554                 :            :       
    4555                 :          7 :       dictionary = g_variant_parse (NULL, cases[i].dict, NULL, NULL, NULL);
    4556                 :          7 :       value = g_variant_lookup_value (dictionary, cases[i].key, NULL);
    4557                 :          7 :       g_variant_unref (dictionary);
    4558                 :            : 
    4559   [ +  +  +  - ]:          7 :       if (value == NULL && cases[i].value == NULL)
    4560                 :          3 :         continue;
    4561                 :            : 
    4562                 :          4 :       g_assert_true (value && cases[i].value);
    4563                 :          4 :       p = g_variant_print (value, FALSE);
    4564                 :          4 :       g_assert_cmpstr (cases[i].value, ==, p);
    4565                 :          4 :       g_variant_unref (value);
    4566                 :          4 :       g_free (p);
    4567                 :            :     }
    4568                 :          1 : }
    4569                 :            : 
    4570                 :            : static void
    4571                 :          1 : test_lookup (void)
    4572                 :            : {
    4573                 :            :   const gchar *str;
    4574                 :            :   GVariant *dict;
    4575                 :            :   gboolean ok;
    4576                 :            :   gint num;
    4577                 :            : 
    4578                 :          1 :   dict = g_variant_parse (NULL,
    4579                 :            :                           "{'a': <5>, 'b': <'c'>}",
    4580                 :            :                           NULL, NULL, NULL);
    4581                 :            : 
    4582                 :          1 :   ok = g_variant_lookup (dict, "a", "i", &num);
    4583                 :          1 :   g_assert_true (ok);
    4584                 :          1 :   g_assert_cmpint (num, ==, 5);
    4585                 :            : 
    4586                 :          1 :   ok = g_variant_lookup (dict, "a", "&s", &str);
    4587                 :          1 :   g_assert_false (ok);
    4588                 :            : 
    4589                 :          1 :   ok = g_variant_lookup (dict, "q", "&s", &str);
    4590                 :          1 :   g_assert_false (ok);
    4591                 :            : 
    4592                 :          1 :   ok = g_variant_lookup (dict, "b", "i", &num);
    4593                 :          1 :   g_assert_false (ok);
    4594                 :            : 
    4595                 :          1 :   ok = g_variant_lookup (dict, "b", "&s", &str);
    4596                 :          1 :   g_assert_true (ok);
    4597                 :          1 :   g_assert_cmpstr (str, ==, "c");
    4598                 :            : 
    4599                 :          1 :   ok = g_variant_lookup (dict, "q", "&s", &str);
    4600                 :          1 :   g_assert_false (ok);
    4601                 :            : 
    4602                 :          1 :   g_variant_unref (dict);
    4603                 :          1 : }
    4604                 :            : 
    4605                 :            : static GVariant *
    4606                 :         26 : untrusted (GVariant *a)
    4607                 :            : {
    4608                 :            :   GVariant *b;
    4609                 :            :   const GVariantType *type;
    4610                 :            :   GBytes *bytes;
    4611                 :            : 
    4612                 :         26 :   type = g_variant_get_type (a);
    4613                 :         26 :   bytes = g_variant_get_data_as_bytes (a);
    4614                 :         26 :   b = g_variant_new_from_bytes (type, bytes, FALSE);
    4615                 :         26 :   g_bytes_unref (bytes);
    4616                 :         26 :   g_variant_unref (a);
    4617                 :            : 
    4618                 :         26 :   return b;
    4619                 :            : }
    4620                 :            : 
    4621                 :            : static void
    4622                 :          1 : test_compare (void)
    4623                 :            : {
    4624                 :            :   GVariant *a;
    4625                 :            :   GVariant *b;
    4626                 :            : 
    4627                 :          1 :   a = untrusted (g_variant_new_byte (5));
    4628                 :          1 :   b = g_variant_new_byte (6);
    4629                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4630                 :          1 :   g_variant_unref (a);
    4631                 :          1 :   g_variant_unref (b);
    4632                 :          1 :   a = untrusted (g_variant_new_int16 (G_MININT16));
    4633                 :          1 :   b = g_variant_new_int16 (G_MAXINT16);
    4634                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4635                 :          1 :   g_variant_unref (a);
    4636                 :          1 :   g_variant_unref (b);
    4637                 :          1 :   a = untrusted (g_variant_new_uint16 (0));
    4638                 :          1 :   b = g_variant_new_uint16 (G_MAXUINT16);
    4639                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4640                 :          1 :   g_variant_unref (a);
    4641                 :          1 :   g_variant_unref (b);
    4642                 :          1 :   a = untrusted (g_variant_new_int32 (G_MININT32));
    4643                 :          1 :   b = g_variant_new_int32 (G_MAXINT32);
    4644                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4645                 :          1 :   g_variant_unref (a);
    4646                 :          1 :   g_variant_unref (b);
    4647                 :          1 :   a = untrusted (g_variant_new_uint32 (0));
    4648                 :          1 :   b = g_variant_new_uint32 (G_MAXUINT32);
    4649                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4650                 :          1 :   g_variant_unref (a);
    4651                 :          1 :   g_variant_unref (b);
    4652                 :          1 :   a = untrusted (g_variant_new_int64 (G_MININT64));
    4653                 :          1 :   b = g_variant_new_int64 (G_MAXINT64);
    4654                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4655                 :          1 :   g_variant_unref (a);
    4656                 :          1 :   g_variant_unref (b);
    4657                 :          1 :   a = untrusted (g_variant_new_uint64 (0));
    4658                 :          1 :   b = g_variant_new_uint64 (G_MAXUINT64);
    4659                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4660                 :          1 :   g_variant_unref (a);
    4661                 :          1 :   g_variant_unref (b);
    4662                 :          1 :   a = untrusted (g_variant_new_double (G_MINDOUBLE));
    4663                 :          1 :   b = g_variant_new_double (G_MAXDOUBLE);
    4664                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4665                 :          1 :   g_variant_unref (a);
    4666                 :          1 :   g_variant_unref (b);
    4667                 :          1 :   a = untrusted (g_variant_new_string ("abc"));
    4668                 :          1 :   b = g_variant_new_string ("abd");
    4669                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4670                 :          1 :   g_variant_unref (a);
    4671                 :          1 :   g_variant_unref (b);
    4672                 :          1 :   a = untrusted (g_variant_new_object_path ("/abc"));
    4673                 :          1 :   b = g_variant_new_object_path ("/abd");
    4674                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4675                 :          1 :   g_variant_unref (a);
    4676                 :          1 :   g_variant_unref (b);
    4677                 :          1 :   a = untrusted (g_variant_new_signature ("g"));
    4678                 :          1 :   b = g_variant_new_signature ("o");
    4679                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4680                 :          1 :   g_variant_unref (a);
    4681                 :          1 :   g_variant_unref (b);
    4682                 :          1 :   a = untrusted (g_variant_new_boolean (FALSE));
    4683                 :          1 :   b = g_variant_new_boolean (TRUE);
    4684                 :          1 :   g_assert_cmpint (g_variant_compare (a, b), <, 0);
    4685                 :          1 :   g_variant_unref (a);
    4686                 :          1 :   g_variant_unref (b);
    4687                 :          1 : }
    4688                 :            : 
    4689                 :            : static void
    4690                 :          1 : test_equal (void)
    4691                 :            : {
    4692                 :            :   GVariant *a;
    4693                 :            :   GVariant *b;
    4694                 :            : 
    4695                 :          1 :   a = untrusted (g_variant_new_byte (5));
    4696                 :          1 :   b = g_variant_get_normal_form (a);
    4697                 :          1 :   g_assert_cmpvariant (a, b);
    4698                 :          1 :   g_variant_unref (a);
    4699                 :          1 :   g_variant_unref (b);
    4700                 :          1 :   a = untrusted (g_variant_new_int16 (G_MININT16));
    4701                 :          1 :   b = g_variant_get_normal_form (a);
    4702                 :          1 :   g_assert_cmpvariant (a, b);
    4703                 :          1 :   g_variant_unref (a);
    4704                 :          1 :   g_variant_unref (b);
    4705                 :          1 :   a = untrusted (g_variant_new_uint16 (0));
    4706                 :          1 :   b = g_variant_get_normal_form (a);
    4707                 :          1 :   g_assert_cmpvariant (a, b);
    4708                 :          1 :   g_variant_unref (a);
    4709                 :          1 :   g_variant_unref (b);
    4710                 :          1 :   a = untrusted (g_variant_new_int32 (G_MININT32));
    4711                 :          1 :   b = g_variant_get_normal_form (a);
    4712                 :          1 :   g_assert_cmpvariant (a, b);
    4713                 :          1 :   g_variant_unref (a);
    4714                 :          1 :   g_variant_unref (b);
    4715                 :          1 :   a = untrusted (g_variant_new_uint32 (0));
    4716                 :          1 :   b = g_variant_get_normal_form (a);
    4717                 :          1 :   g_assert_cmpvariant (a, b);
    4718                 :          1 :   g_variant_unref (a);
    4719                 :          1 :   g_variant_unref (b);
    4720                 :          1 :   a = untrusted (g_variant_new_int64 (G_MININT64));
    4721                 :          1 :   b = g_variant_get_normal_form (a);
    4722                 :          1 :   g_assert_cmpvariant (a, b);
    4723                 :          1 :   g_variant_unref (a);
    4724                 :          1 :   g_variant_unref (b);
    4725                 :          1 :   a = untrusted (g_variant_new_uint64 (0));
    4726                 :          1 :   b = g_variant_get_normal_form (a);
    4727                 :          1 :   g_assert_cmpvariant (a, b);
    4728                 :          1 :   g_variant_unref (a);
    4729                 :          1 :   g_variant_unref (b);
    4730                 :          1 :   a = untrusted (g_variant_new_double (G_MINDOUBLE));
    4731                 :          1 :   b = g_variant_get_normal_form (a);
    4732                 :          1 :   g_assert_cmpvariant (a, b);
    4733                 :          1 :   g_variant_unref (a);
    4734                 :          1 :   g_variant_unref (b);
    4735                 :          1 :   a = untrusted (g_variant_new_string ("abc"));
    4736                 :          1 :   g_assert_cmpvariant (a, a);
    4737                 :          1 :   b = g_variant_get_normal_form (a);
    4738                 :          1 :   g_assert_cmpvariant (a, b);
    4739                 :          1 :   g_variant_unref (a);
    4740                 :          1 :   g_variant_unref (b);
    4741                 :          1 :   a = untrusted (g_variant_new_object_path ("/abc"));
    4742                 :          1 :   g_assert_cmpvariant (a, a);
    4743                 :          1 :   b = g_variant_get_normal_form (a);
    4744                 :          1 :   a = untrusted (a);
    4745                 :          1 :   g_assert_cmpvariant (a, b);
    4746                 :          1 :   g_variant_unref (a);
    4747                 :          1 :   g_variant_unref (b);
    4748                 :          1 :   a = untrusted (g_variant_new_signature ("g"));
    4749                 :          1 :   g_assert_cmpvariant (a, a);
    4750                 :          1 :   b = g_variant_get_normal_form (a);
    4751                 :          1 :   a = untrusted (a);
    4752                 :          1 :   g_assert_cmpvariant (a, b);
    4753                 :          1 :   g_variant_unref (a);
    4754                 :          1 :   g_variant_unref (b);
    4755                 :          1 :   a = untrusted (g_variant_new_boolean (FALSE));
    4756                 :          1 :   b = g_variant_get_normal_form (a);
    4757                 :          1 :   g_assert_cmpvariant (a, b);
    4758                 :          1 :   g_variant_unref (a);
    4759                 :          1 :   g_variant_unref (b);
    4760                 :          1 : }
    4761                 :            : 
    4762                 :            : static void
    4763                 :          1 : test_fixed_array (void)
    4764                 :            : {
    4765                 :            :   GVariant *a;
    4766                 :            :   gint32 values[5];
    4767                 :            :   const gint32 *elts;
    4768                 :            :   gsize n_elts;
    4769                 :            :   gsize i;
    4770                 :            : 
    4771                 :          1 :   n_elts = 0;
    4772                 :          1 :   a = g_variant_new_parsed ("[1,2,3,4,5]");
    4773                 :          1 :   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
    4774                 :          1 :   g_assert_cmpuint (n_elts, ==, 5);
    4775         [ +  + ]:          6 :   for (i = 0; i < 5; i++)
    4776                 :          5 :     g_assert_cmpint (elts[i], ==, i + 1);
    4777                 :          1 :   g_variant_unref (a);
    4778                 :            : 
    4779                 :          1 :   n_elts = 0;
    4780         [ +  + ]:          6 :   for (i = 0; i < 5; i++)
    4781                 :          5 :     values[i] = i + 1;
    4782                 :          1 :   a = g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, values,
    4783                 :            :                                  G_N_ELEMENTS (values), sizeof (values[0]));
    4784                 :          1 :   g_assert_cmpstr (g_variant_get_type_string (a), ==, "ai");
    4785                 :          1 :   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
    4786                 :          1 :   g_assert_cmpuint (n_elts, ==, 5);
    4787         [ +  + ]:          6 :   for (i = 0; i < 5; i++)
    4788                 :          5 :     g_assert_cmpint (elts[i], ==, i + 1);
    4789                 :          1 :   g_variant_unref (a);
    4790                 :          1 : }
    4791                 :            : 
    4792                 :            : static void
    4793                 :          1 : test_check_format_string (void)
    4794                 :            : {
    4795                 :            :   GVariant *value;
    4796                 :            : 
    4797                 :          1 :   value = g_variant_new ("(sas)", "foo", NULL);
    4798                 :          1 :   g_variant_ref_sink (value);
    4799                 :            : 
    4800                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s*)", TRUE));
    4801                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s*)", FALSE));
    4802                 :          1 :   g_assert_false (g_variant_check_format_string (value, "(u*)", TRUE));
    4803                 :          1 :   g_assert_false (g_variant_check_format_string (value, "(u*)", FALSE));
    4804                 :            : 
    4805                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(&s*)", FALSE));
    4806                 :          1 :   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
    4807                 :          1 :   g_assert_false (g_variant_check_format_string (value, "(&s*)", TRUE));
    4808                 :          1 :   g_test_assert_expected_messages ();
    4809                 :            : 
    4810                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s^as)", TRUE));
    4811                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s^as)", FALSE));
    4812                 :            : 
    4813                 :          1 :   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
    4814                 :          1 :   g_assert_false (g_variant_check_format_string (value, "(s^a&s)", TRUE));
    4815                 :          1 :   g_test_assert_expected_messages ();
    4816                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s^a&s)", FALSE));
    4817                 :            : 
    4818                 :          1 :   g_variant_unref (value);
    4819                 :            : 
    4820                 :            :   /* Do it again with a type that will let us put a '&' after a '^' */
    4821                 :          1 :   value = g_variant_new ("(say)", "foo", NULL);
    4822                 :          1 :   g_variant_ref_sink (value);
    4823                 :            : 
    4824                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s*)", TRUE));
    4825                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s*)", FALSE));
    4826                 :          1 :   g_assert_false (g_variant_check_format_string (value, "(u*)", TRUE));
    4827                 :          1 :   g_assert_false (g_variant_check_format_string (value, "(u*)", FALSE));
    4828                 :            : 
    4829                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(&s*)", FALSE));
    4830                 :          1 :   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
    4831                 :          1 :   g_assert_false (g_variant_check_format_string (value, "(&s*)", TRUE));
    4832                 :          1 :   g_test_assert_expected_messages ();
    4833                 :            : 
    4834                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s^ay)", TRUE));
    4835                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s^ay)", FALSE));
    4836                 :            : 
    4837                 :          1 :   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
    4838                 :          1 :   g_assert_false (g_variant_check_format_string (value, "(s^&ay)", TRUE));
    4839                 :          1 :   g_test_assert_expected_messages ();
    4840                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(s^&ay)", FALSE));
    4841                 :            : 
    4842                 :          1 :   g_assert_true (g_variant_check_format_string (value, "r", FALSE));
    4843                 :          1 :   g_assert_true (g_variant_check_format_string (value, "(?a?)", FALSE));
    4844                 :            : 
    4845                 :          1 :   g_variant_unref (value);
    4846                 :          1 : }
    4847                 :            : 
    4848                 :            : static void
    4849                 :         13 : verify_gvariant_checksum (const gchar  *sha256,
    4850                 :            :                           GVariant     *v)
    4851                 :            :              
    4852                 :            : {
    4853                 :            :   gchar *checksum;
    4854                 :         26 :   checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA256,
    4855                 :         13 :                                           g_variant_get_data (v),
    4856                 :            :                                           g_variant_get_size (v));
    4857                 :         13 :   g_assert_cmpstr (sha256, ==, checksum);
    4858                 :         13 :   g_free (checksum);
    4859                 :         13 : }
    4860                 :            : 
    4861                 :            : static void
    4862                 :         13 : verify_gvariant_checksum_va (const gchar *sha256,
    4863                 :            :                              const gchar *fmt,
    4864                 :            :                              ...)
    4865                 :            : {
    4866                 :            :   va_list args;
    4867                 :            :   GVariant *v;
    4868                 :            : 
    4869                 :         13 :   va_start (args, fmt);
    4870                 :            : 
    4871                 :         13 :   v = g_variant_new_va (fmt, NULL, &args);
    4872                 :         13 :   g_variant_ref_sink (v);
    4873                 :            : #if G_BYTE_ORDER == G_BIG_ENDIAN
    4874                 :            :   {
    4875                 :            :     GVariant *byteswapped = g_variant_byteswap (v);
    4876                 :            :     g_variant_unref (v);
    4877                 :            :     v = byteswapped;
    4878                 :            :   }
    4879                 :            : #endif
    4880                 :            : 
    4881                 :         13 :   va_end (args);
    4882                 :            : 
    4883                 :         13 :   verify_gvariant_checksum (sha256, v);
    4884                 :            : 
    4885                 :         13 :   g_variant_unref (v);
    4886                 :         13 : }
    4887                 :            : 
    4888                 :            : static void
    4889                 :          1 : test_checksum_basic (void)
    4890                 :            : {
    4891                 :          1 :   verify_gvariant_checksum_va ("e8a4b2ee7ede79a3afb332b5b6cc3d952a65fd8cffb897f5d18016577c33d7cc",
    4892                 :            :                                "u", 42);
    4893                 :          1 :   verify_gvariant_checksum_va ("c53e363c33b00cfce298229ee83856b8a98c2e6126cab13f65899f62473b0df5",
    4894                 :            :                                "s", "moocow");
    4895                 :          1 :   verify_gvariant_checksum_va ("2b4c342f5433ebe591a1da77e013d1b72475562d48578dca8b84bac6651c3cb9",
    4896                 :            :                                "y", 9);
    4897                 :          1 :   verify_gvariant_checksum_va ("12a3ae445661ce5dee78d0650d33362dec29c4f82af05e7e57fb595bbbacf0ca",
    4898                 :            :                                "t", G_MAXUINT64);
    4899                 :          1 :   verify_gvariant_checksum_va ("e25a59b24440eb6c833aa79c93b9840e6eab6966add0dacf31df7e9e7000f5b3",
    4900                 :            :                                "d", 3.14159);
    4901                 :          1 :   verify_gvariant_checksum_va ("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a",
    4902                 :            :                                "b", TRUE);
    4903                 :          1 :   verify_gvariant_checksum_va ("ca2fd00fa001190744c15c317643ab092e7048ce086a243e2be9437c898de1bb",
    4904                 :            :                                "q", G_MAXUINT16);
    4905                 :          1 : }
    4906                 :            : 
    4907                 :            : static void
    4908                 :          1 : test_checksum_nested (void)
    4909                 :            : {
    4910                 :            :   static const char* const strv[] = {"foo", "bar", "baz", NULL};
    4911                 :            : 
    4912                 :          1 :   verify_gvariant_checksum_va ("31fbc92f08fddaca716188fe4b5d44ae122fc6306fd3c6925af53cfa47ea596d",
    4913                 :            :                                "(uu)", 41, 43);
    4914                 :          1 :   verify_gvariant_checksum_va ("01759d683cead856d1d386d59af0578841698a424a265345ad5413122f220de8",
    4915                 :            :                                "(su)", "moocow", 79);
    4916                 :          1 :   verify_gvariant_checksum_va ("52b3ae95f19b3e642ea1d01185aea14a09004c1d1712672644427403a8a0afe6",
    4917                 :            :                                "(qyst)", G_MAXUINT16, 9, "moocow", G_MAXUINT64);
    4918                 :          1 :   verify_gvariant_checksum_va ("6fc6f4524161c3ae0d316812d7088e3fcd372023edaea2d7821093be40ae1060",
    4919                 :            :                                "(@ay)", g_variant_new_bytestring ("\xFF\xFF\xFF"));
    4920                 :          1 :   verify_gvariant_checksum_va ("572aca386e1a983dd23bb6eb6e3dfa72eef9ca7c7744581aa800e18d7d9d0b0b",
    4921                 :            :                                "(^as)", strv);
    4922                 :          1 :   verify_gvariant_checksum_va ("4bddf6174c791bb44fc6a4106573031690064df34b741033a0122ed8dc05bcf3",
    4923                 :            :                                "(yvu)", 254, g_variant_new ("(^as)", strv), 42);
    4924                 :          1 : }
    4925                 :            : 
    4926                 :            : static void
    4927                 :          1 : test_gbytes (void)
    4928                 :            : {
    4929                 :            :   GVariant *a;
    4930                 :            :   GVariant *tuple;
    4931                 :            :   GBytes *bytes;
    4932                 :            :   GBytes *bytes2;
    4933                 :          1 :   const guint8 values[5] = { 1, 2, 3, 4, 5 };
    4934                 :            :   const guint8 *elts;
    4935                 :            :   gsize n_elts;
    4936                 :            :   gsize i;
    4937                 :            : 
    4938                 :          1 :   bytes = g_bytes_new (&values, 5);
    4939                 :          1 :   a = g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING, bytes, TRUE);
    4940                 :          1 :   g_bytes_unref (bytes);
    4941                 :          1 :   n_elts = 0;
    4942                 :          1 :   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (guint8));
    4943                 :          1 :   g_assert_cmpuint (n_elts, ==, 5);
    4944         [ +  + ]:          6 :   for (i = 0; i < 5; i++)
    4945                 :          5 :     g_assert_cmpuint (elts[i], ==, i + 1);
    4946                 :            : 
    4947                 :          1 :   bytes2 = g_variant_get_data_as_bytes (a);
    4948                 :          1 :   g_variant_unref (a);
    4949                 :            : 
    4950                 :          1 :   bytes = g_bytes_new (&values, 5);
    4951                 :          1 :   g_assert_true (g_bytes_equal (bytes, bytes2));
    4952                 :          1 :   g_bytes_unref (bytes);
    4953                 :          1 :   g_bytes_unref (bytes2);
    4954                 :            : 
    4955                 :          1 :   tuple = g_variant_new_parsed ("['foo', 'bar']");
    4956                 :          1 :   bytes = g_variant_get_data_as_bytes (tuple); /* force serialization */
    4957                 :          1 :   a = g_variant_get_child_value (tuple, 1);
    4958                 :          1 :   bytes2 = g_variant_get_data_as_bytes (a);
    4959                 :          1 :   g_assert_false (g_bytes_equal (bytes, bytes2));
    4960                 :            : 
    4961                 :          1 :   g_bytes_unref (bytes);
    4962                 :          1 :   g_bytes_unref (bytes2);
    4963                 :          1 :   g_variant_unref (a);
    4964                 :          1 :   g_variant_unref (tuple);
    4965                 :            : 
    4966                 :          1 :   bytes = g_bytes_new (NULL, 0);
    4967                 :          1 :   a = g_variant_new_from_bytes (G_VARIANT_TYPE ("as"), bytes, TRUE);
    4968                 :          1 :   g_bytes_unref (bytes);
    4969                 :          1 :   g_assert_cmpuint (g_variant_n_children (a), ==, 0);
    4970                 :          1 :   g_variant_unref (a);
    4971                 :          1 : }
    4972                 :            : 
    4973                 :            : typedef struct {
    4974                 :            :   const GVariantType *type;
    4975                 :            :   const gchar *in;
    4976                 :            :   const gchar *out;
    4977                 :            : } ContextTest;
    4978                 :            : 
    4979                 :            : static void
    4980                 :          1 : test_print_context (void)
    4981                 :            : {
    4982                 :          1 :   ContextTest tests[] = {
    4983                 :            :     { NULL, "(1, 2, 3, 'abc", "          ^^^^" },
    4984                 :            :     { NULL, "[1, 2, 3, 'str']", " ^        ^^^^^" },
    4985                 :            :     { G_VARIANT_TYPE_UINT16, "{ 'abc':'def' }", "  ^^^^^^^^^^^^^^^" },
    4986                 :            :     { NULL, "<5", "    ^" },
    4987                 :            :     { NULL, "'ab\\ux'", "       ^ " },
    4988                 :            :     { NULL, "'ab\\U00efx'", "       ^^^^  " }
    4989                 :            :   };
    4990                 :            :   GVariant *v;
    4991                 :            :   gchar *s;
    4992                 :            :   gsize i;
    4993                 :          1 :   GError *error = NULL;
    4994                 :            : 
    4995         [ +  + ]:          7 :   for (i = 0; i < G_N_ELEMENTS (tests); i++)
    4996                 :            :     {
    4997                 :          6 :       v = g_variant_parse (tests[i].type, tests[i].in, NULL, NULL, &error);
    4998                 :          6 :       g_assert_null (v);
    4999                 :          6 :       s = g_variant_parse_error_print_context (error, tests[i].in);
    5000                 :          6 :       g_assert_nonnull (strstr (s, tests[i].out));
    5001                 :          6 :       g_free (s);
    5002                 :          6 :       g_clear_error (&error);
    5003                 :            :     }
    5004                 :          1 : }
    5005                 :            : 
    5006                 :            : static void
    5007                 :          1 : test_error_quark (void)
    5008                 :            : {
    5009                 :            : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
    5010                 :          1 :   g_assert_cmpuint (g_variant_parser_get_error_quark (), ==, g_variant_parse_error_quark ());
    5011                 :            : G_GNUC_END_IGNORE_DEPRECATIONS
    5012                 :          1 : }
    5013                 :            : 
    5014                 :            : static void
    5015                 :          1 : test_stack_builder_init (void)
    5016                 :            : {
    5017                 :          1 :   GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_BYTESTRING);
    5018                 :            :   GVariant *variant;
    5019                 :            : 
    5020                 :          1 :   g_variant_builder_add_value (&builder, g_variant_new_byte ('g'));
    5021                 :          1 :   g_variant_builder_add_value (&builder, g_variant_new_byte ('l'));
    5022                 :          1 :   g_variant_builder_add_value (&builder, g_variant_new_byte ('i'));
    5023                 :          1 :   g_variant_builder_add_value (&builder, g_variant_new_byte ('b'));
    5024                 :          1 :   g_variant_builder_add_value (&builder, g_variant_new_byte ('\0'));
    5025                 :            : 
    5026                 :          1 :   variant = g_variant_ref_sink (g_variant_builder_end (&builder));
    5027                 :          1 :   g_assert_nonnull (variant);
    5028                 :          1 :   g_assert_true (g_variant_type_equal (g_variant_get_type (variant),
    5029                 :            :                                        G_VARIANT_TYPE_BYTESTRING));
    5030                 :          1 :   g_assert_cmpuint (g_variant_n_children (variant), ==, 5);
    5031                 :          1 :   g_assert_cmpstr (g_variant_get_bytestring (variant), ==, "glib");
    5032                 :          1 :   g_variant_unref (variant);
    5033                 :          1 : }
    5034                 :            : 
    5035                 :            : static GVariant *
    5036                 :          1 : get_asv (void)
    5037                 :            : {
    5038                 :          1 :   GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
    5039                 :            : 
    5040                 :          1 :   g_variant_builder_add (&builder, "{s@v}", "foo", g_variant_new_variant (g_variant_new_string ("FOO")));
    5041                 :          1 :   g_variant_builder_add (&builder, "{s@v}", "bar", g_variant_new_variant (g_variant_new_string ("BAR")));
    5042                 :            : 
    5043                 :          1 :   return g_variant_ref_sink (g_variant_builder_end (&builder));
    5044                 :            : }
    5045                 :            : 
    5046                 :            : static void
    5047                 :          1 : test_stack_dict_init (void)
    5048                 :            : {
    5049                 :          1 :   GVariant *asv = get_asv ();
    5050                 :          1 :   GVariantDict dict = G_VARIANT_DICT_INIT (asv);
    5051                 :            :   GVariant *variant;
    5052                 :            :   GVariantIter iter;
    5053                 :            :   gchar *key;
    5054                 :            :   GVariant *value;
    5055                 :            :   const gchar *str_value;
    5056                 :            : 
    5057                 :          1 :   g_assert_true (g_variant_dict_lookup (&dict, "foo", "&s", &str_value, NULL));
    5058                 :          1 :   g_assert_cmpstr (str_value, ==, "FOO");
    5059                 :          1 :   g_assert_true (g_variant_dict_lookup (&dict, "bar", "&s", &str_value, NULL));
    5060                 :          1 :   g_assert_cmpstr (str_value, ==, "BAR");
    5061                 :            : 
    5062                 :          1 :   g_variant_dict_insert_value (&dict, "baz", g_variant_new_string ("BAZ"));
    5063                 :          1 :   g_variant_dict_insert_value (&dict, "quux", g_variant_new_string ("QUUX"));
    5064                 :            : 
    5065                 :          1 :   g_assert_true (g_variant_dict_lookup (&dict, "baz", "&s", &str_value, NULL));
    5066                 :          1 :   g_assert_cmpstr (str_value, ==, "BAZ");
    5067                 :          1 :   g_assert_true (g_variant_dict_lookup (&dict, "quux", "&s", &str_value, NULL));
    5068                 :          1 :   g_assert_cmpstr (str_value, ==, "QUUX");
    5069                 :            : 
    5070                 :          1 :   variant = g_variant_ref_sink (g_variant_dict_end (&dict));
    5071                 :          1 :   g_assert_nonnull (variant);
    5072                 :          1 :   g_assert_true (g_variant_type_equal (g_variant_get_type (variant),
    5073                 :            :                                        G_VARIANT_TYPE_VARDICT));
    5074                 :          1 :   g_assert_cmpuint (g_variant_n_children (variant), ==, 4);
    5075                 :            : 
    5076                 :          1 :   g_variant_iter_init (&iter, variant);
    5077         [ +  + ]:          5 :   while (g_variant_iter_next (&iter, "{sv}", &key, &value))
    5078                 :            :     {
    5079                 :          4 :       gchar *strup = g_ascii_strup (key, -1);
    5080                 :            : 
    5081                 :          4 :       g_assert_cmpstr (strup, ==, g_variant_get_string (value, NULL));
    5082                 :          4 :       g_free (key);
    5083                 :          4 :       g_free (strup);
    5084                 :          4 :       g_variant_unref (value);
    5085                 :            :     }
    5086                 :            : 
    5087                 :          1 :   g_variant_unref (asv);
    5088                 :          1 :   g_variant_unref (variant);
    5089                 :          1 : }
    5090                 :            : 
    5091                 :            : /* Test checking arbitrary binary data for normal form. This time, it’s a tuple
    5092                 :            :  * with invalid element ends. */
    5093                 :            : static void
    5094                 :          1 : test_normal_checking_tuples (void)
    5095                 :            : {
    5096                 :          1 :   const guint8 data[] = {
    5097                 :            :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
    5098                 :            :     'a', '(', 'a', 'o', 'a', 'o', 'a', 'a', 'o', 'a', 'a', 'o', ')'
    5099                 :            :   };
    5100                 :          1 :   gsize size = sizeof (data);
    5101                 :          1 :   GVariant *variant = NULL;
    5102                 :          1 :   GVariant *normal_variant = NULL;
    5103                 :            : 
    5104                 :          1 :   variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
    5105                 :            :                                      FALSE, NULL, NULL);
    5106                 :          1 :   g_assert_nonnull (variant);
    5107                 :            : 
    5108                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5109                 :          1 :   g_assert_nonnull (normal_variant);
    5110                 :            : 
    5111                 :          1 :   g_variant_unref (normal_variant);
    5112                 :          1 :   g_variant_unref (variant);
    5113                 :          1 : }
    5114                 :            : 
    5115                 :            : /* Check that deeply nested variants are not considered in normal form when
    5116                 :            :  * deserialized from untrusted data.*/
    5117                 :            : static void
    5118                 :          1 : test_recursion_limits_variant_in_variant (void)
    5119                 :            : {
    5120                 :          1 :   GVariant *wrapper_variant = NULL;
    5121                 :            :   gsize i;
    5122                 :          1 :   GBytes *bytes = NULL;
    5123                 :          1 :   GVariant *deserialised_variant = NULL;
    5124                 :            : 
    5125                 :            :   /* Construct a hierarchy of variants, containing a single string. This is just
    5126                 :            :    * below the maximum recursion level, as a series of nested variant types. */
    5127                 :          1 :   wrapper_variant = g_variant_new_string ("hello");
    5128                 :            : 
    5129         [ +  + ]:        128 :   for (i = 0; i < G_VARIANT_MAX_RECURSION_DEPTH - 1; i++)
    5130                 :        127 :     wrapper_variant = g_variant_new_variant (g_steal_pointer (&wrapper_variant));
    5131                 :            : 
    5132                 :            :   /* Serialize and deserialize it as untrusted data, to force normalisation. */
    5133                 :          1 :   bytes = g_variant_get_data_as_bytes (wrapper_variant);
    5134                 :          1 :   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
    5135                 :            :                                                    bytes, FALSE);
    5136                 :          1 :   g_assert_nonnull (deserialised_variant);
    5137                 :          1 :   g_assert_true (g_variant_is_normal_form (deserialised_variant));
    5138                 :            : 
    5139                 :          1 :   g_bytes_unref (bytes);
    5140                 :          1 :   g_variant_unref (deserialised_variant);
    5141                 :            : 
    5142                 :            :   /* Wrap it once more. Normalisation should now fail. */
    5143                 :          1 :   wrapper_variant = g_variant_new_variant (g_steal_pointer (&wrapper_variant));
    5144                 :            : 
    5145                 :          1 :   bytes = g_variant_get_data_as_bytes (wrapper_variant);
    5146                 :          1 :   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
    5147                 :            :                                                    bytes, FALSE);
    5148                 :          1 :   g_assert_nonnull (deserialised_variant);
    5149                 :          1 :   g_assert_false (g_variant_is_normal_form (deserialised_variant));
    5150                 :            : 
    5151                 :          1 :   g_variant_unref (deserialised_variant);
    5152                 :            : 
    5153                 :            :   /* Deserialize it again, but trusted this time. This should succeed. */
    5154                 :          1 :   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
    5155                 :            :                                                    bytes, TRUE);
    5156                 :          1 :   g_assert_nonnull (deserialised_variant);
    5157                 :          1 :   g_assert_true (g_variant_is_normal_form (deserialised_variant));
    5158                 :            : 
    5159                 :          1 :   g_bytes_unref (bytes);
    5160                 :          1 :   g_variant_unref (deserialised_variant);
    5161                 :          1 :   g_variant_unref (wrapper_variant);
    5162                 :          1 : }
    5163                 :            : 
    5164                 :            : /* Check that deeply nested arrays are not considered in normal form when
    5165                 :            :  * deserialized from untrusted data after being wrapped in a variant. This is
    5166                 :            :  * worth testing, because neither the deeply nested array, nor the variant,
    5167                 :            :  * have a static #GVariantType which is too deep — only when nested together do
    5168                 :            :  * they become too deep. */
    5169                 :            : static void
    5170                 :          1 : test_recursion_limits_array_in_variant (void)
    5171                 :            : {
    5172                 :          1 :   GVariant *child_variant = NULL;
    5173                 :          1 :   GVariant *wrapper_variant = NULL;
    5174                 :            :   gsize i;
    5175                 :          1 :   GBytes *bytes = NULL;
    5176                 :          1 :   GVariant *deserialised_variant = NULL;
    5177                 :            : 
    5178                 :            :   /* Construct a hierarchy of arrays, containing a single string. This is just
    5179                 :            :    * below the maximum recursion level, all in a single definite type. */
    5180                 :          1 :   child_variant = g_variant_new_string ("hello");
    5181                 :            : 
    5182         [ +  + ]:        128 :   for (i = 0; i < G_VARIANT_MAX_RECURSION_DEPTH - 1; i++)
    5183                 :        127 :     child_variant = g_variant_new_array (NULL, &child_variant, 1);
    5184                 :            : 
    5185                 :            :   /* Serialize and deserialize it as untrusted data, to force normalisation. */
    5186                 :          1 :   bytes = g_variant_get_data_as_bytes (child_variant);
    5187                 :          1 :   deserialised_variant = g_variant_new_from_bytes (g_variant_get_type (child_variant),
    5188                 :            :                                                    bytes, FALSE);
    5189                 :          1 :   g_assert_nonnull (deserialised_variant);
    5190                 :          1 :   g_assert_true (g_variant_is_normal_form (deserialised_variant));
    5191                 :            : 
    5192                 :          1 :   g_bytes_unref (bytes);
    5193                 :          1 :   g_variant_unref (deserialised_variant);
    5194                 :            : 
    5195                 :            :   /* Wrap it in a variant. Normalisation should now fail. */
    5196                 :          1 :   wrapper_variant = g_variant_new_variant (g_steal_pointer (&child_variant));
    5197                 :            : 
    5198                 :          1 :   bytes = g_variant_get_data_as_bytes (wrapper_variant);
    5199                 :          1 :   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
    5200                 :            :                                                    bytes, FALSE);
    5201                 :          1 :   g_assert_nonnull (deserialised_variant);
    5202                 :          1 :   g_assert_false (g_variant_is_normal_form (deserialised_variant));
    5203                 :            : 
    5204                 :          1 :   g_variant_unref (deserialised_variant);
    5205                 :            : 
    5206                 :            :   /* Deserialize it again, but trusted this time. This should succeed. */
    5207                 :          1 :   deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
    5208                 :            :                                                    bytes, TRUE);
    5209                 :          1 :   g_assert_nonnull (deserialised_variant);
    5210                 :          1 :   g_assert_true (g_variant_is_normal_form (deserialised_variant));
    5211                 :            : 
    5212                 :          1 :   g_bytes_unref (bytes);
    5213                 :          1 :   g_variant_unref (deserialised_variant);
    5214                 :          1 :   g_variant_unref (wrapper_variant);
    5215                 :          1 : }
    5216                 :            : 
    5217                 :            : /* Test that a nested array with invalid values in its offset table (which point
    5218                 :            :  * from the inner to the outer array) is normalised successfully without
    5219                 :            :  * looping infinitely. */
    5220                 :            : static void
    5221                 :          1 : test_normal_checking_array_offsets_overlapped (void)
    5222                 :            : {
    5223                 :          1 :   const guint8 data[] = {
    5224                 :            :     0x01, 0x00,
    5225                 :            :   };
    5226                 :          1 :   gsize size = sizeof (data);
    5227                 :          1 :   GVariant *variant = NULL;
    5228                 :          1 :   GVariant *normal_variant = NULL;
    5229                 :          1 :   GVariant *expected_variant = NULL;
    5230                 :            : 
    5231                 :          1 :   variant = g_variant_new_from_data (G_VARIANT_TYPE ("aay"), data, size,
    5232                 :            :                                      FALSE, NULL, NULL);
    5233                 :          1 :   g_assert_nonnull (variant);
    5234                 :            : 
    5235                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5236                 :          1 :   g_assert_nonnull (normal_variant);
    5237                 :            : 
    5238                 :          1 :   expected_variant = g_variant_new_parsed ("[@ay [], []]");
    5239                 :          1 :   g_assert_cmpvariant (normal_variant, expected_variant);
    5240                 :            : 
    5241                 :          1 :   g_assert_cmpmem (g_variant_get_data (normal_variant), g_variant_get_size (normal_variant),
    5242                 :            :                    g_variant_get_data (expected_variant), g_variant_get_size (expected_variant));
    5243                 :            : 
    5244                 :          1 :   g_variant_unref (expected_variant);
    5245                 :          1 :   g_variant_unref (normal_variant);
    5246                 :          1 :   g_variant_unref (variant);
    5247                 :          1 : }
    5248                 :            : 
    5249                 :            : /* Test that an array with invalidly large values in its offset table is
    5250                 :            :  * normalised successfully without looping infinitely. */
    5251                 :            : static void
    5252                 :          1 : test_normal_checking_array_offsets (void)
    5253                 :            : {
    5254                 :          1 :   const guint8 data[] = {
    5255                 :            :     0x07, 0xe5, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
    5256                 :            :     'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'g',
    5257                 :            :   };
    5258                 :          1 :   gsize size = sizeof (data);
    5259                 :          1 :   GVariant *variant = NULL;
    5260                 :          1 :   GVariant *normal_variant = NULL;
    5261                 :            : 
    5262                 :          1 :   variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
    5263                 :            :                                      FALSE, NULL, NULL);
    5264                 :          1 :   g_assert_nonnull (variant);
    5265                 :            : 
    5266                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5267                 :          1 :   g_assert_nonnull (normal_variant);
    5268                 :            : 
    5269                 :          1 :   g_variant_unref (normal_variant);
    5270                 :          1 :   g_variant_unref (variant);
    5271                 :          1 : }
    5272                 :            : 
    5273                 :            : /* This is a regression test that we can't have non-normal values that take up
    5274                 :            :  * significantly more space than the normal equivalent, by specifying the
    5275                 :            :  * offset table entries so that array elements overlap.
    5276                 :            :  *
    5277                 :            :  * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_832242 */
    5278                 :            : static void
    5279                 :          1 : test_normal_checking_array_offsets2 (void)
    5280                 :            : {
    5281                 :          1 :   const guint8 data[] = {
    5282                 :            :     'h', 'i', '\0',
    5283                 :            :     0x03, 0x00, 0x03,
    5284                 :            :     0x06, 0x00, 0x06,
    5285                 :            :     0x09, 0x00, 0x09,
    5286                 :            :     0x0c, 0x00, 0x0c,
    5287                 :            :     0x0f, 0x00, 0x0f,
    5288                 :            :     0x12, 0x00, 0x12,
    5289                 :            :     0x15, 0x00, 0x15,
    5290                 :            :   };
    5291                 :          1 :   gsize size = sizeof (data);
    5292                 :          1 :   const GVariantType *aaaaaaas = G_VARIANT_TYPE ("aaaaaaas");
    5293                 :          1 :   GVariant *variant = NULL;
    5294                 :          1 :   GVariant *normal_variant = NULL;
    5295                 :          1 :   GVariant *expected = NULL;
    5296                 :            : 
    5297                 :          1 :   variant = g_variant_new_from_data (aaaaaaas, data, size, FALSE, NULL, NULL);
    5298                 :          1 :   g_assert_nonnull (variant);
    5299                 :            : 
    5300                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5301                 :          1 :   g_assert_nonnull (normal_variant);
    5302                 :          1 :   g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 2);
    5303                 :            : 
    5304                 :          1 :   expected = g_variant_new_parsed (
    5305                 :            :       "[[[[[[['hi', '', ''], [], []], [], []], [], []], [], []], [], []], [], []]");
    5306                 :          1 :   g_assert_cmpvariant (expected, variant);
    5307                 :          1 :   g_assert_cmpvariant (expected, normal_variant);
    5308                 :            : 
    5309                 :          1 :   g_variant_unref (expected);
    5310                 :          1 :   g_variant_unref (normal_variant);
    5311                 :          1 :   g_variant_unref (variant);
    5312                 :          1 : }
    5313                 :            : 
    5314                 :            : /* Test that an otherwise-valid serialised GVariant is considered non-normal if
    5315                 :            :  * its offset table entries are too wide.
    5316                 :            :  *
    5317                 :            :  * See §2.3.6 (Framing Offsets) of the GVariant specification. */
    5318                 :            : static void
    5319                 :          1 : test_normal_checking_array_offsets_minimal_sized (void)
    5320                 :            : {
    5321                 :            :   GVariantBuilder builder;
    5322                 :            :   gsize i;
    5323                 :          1 :   GVariant *aay_constructed = NULL;
    5324                 :          1 :   const guint8 *data = NULL;
    5325                 :          1 :   guint8 *data_owned = NULL;
    5326                 :          1 :   GVariant *aay_deserialised = NULL;
    5327                 :          1 :   GVariant *aay_normalised = NULL;
    5328                 :            : 
    5329                 :            :   /* Construct an array of type aay, consisting of 128 elements which are each
    5330                 :            :    * an empty array, i.e. `[[] * 128]`. This is chosen because the inner
    5331                 :            :    * elements are variable sized (making the outer array variable sized, so it
    5332                 :            :    * must have an offset table), but they are also zero-sized when serialised.
    5333                 :            :    * So the serialised representation of @aay_constructed consists entirely of
    5334                 :            :    * its offset table, which is entirely zeroes.
    5335                 :            :    *
    5336                 :            :    * The array is chosen to be 128 elements long because that means offset
    5337                 :            :    * table entries which are 1 byte long. If the elements in the array were
    5338                 :            :    * non-zero-sized (to the extent that the overall array is ≥256 bytes long),
    5339                 :            :    * the offset table entries would end up being 2 bytes long. */
    5340                 :          1 :   g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
    5341                 :            : 
    5342         [ +  + ]:        129 :   for (i = 0; i < 128; i++)
    5343                 :        128 :     g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
    5344                 :            : 
    5345                 :          1 :   aay_constructed = g_variant_builder_end (&builder);
    5346                 :            : 
    5347                 :            :   /* Verify that the constructed array is in normal form, and its serialised
    5348                 :            :    * form is `b'\0' * 128`. */
    5349                 :          1 :   g_assert_true (g_variant_is_normal_form (aay_constructed));
    5350                 :          1 :   g_assert_cmpuint (g_variant_n_children (aay_constructed), ==, 128);
    5351                 :          1 :   g_assert_cmpuint (g_variant_get_size (aay_constructed), ==, 128);
    5352                 :            : 
    5353                 :          1 :   data = g_variant_get_data (aay_constructed);
    5354         [ +  + ]:        129 :   for (i = 0; i < g_variant_get_size (aay_constructed); i++)
    5355                 :        128 :     g_assert_cmpuint (data[i], ==, 0);
    5356                 :            : 
    5357                 :            :   /* Construct a serialised `aay` GVariant which is `b'\0' * 256`. This has to
    5358                 :            :    * be a non-normal form of `[[] * 128]`, with 2-byte-long offset table
    5359                 :            :    * entries, because each offset table entry has to be able to reference all of
    5360                 :            :    * the byte boundaries in the container. All the entries in the offset table
    5361                 :            :    * are zero, so all the elements of the array are zero-sized. */
    5362                 :          1 :   data = data_owned = g_malloc0 (256);
    5363                 :          1 :   aay_deserialised = g_variant_new_from_data (G_VARIANT_TYPE ("aay"),
    5364                 :            :                                               data,
    5365                 :            :                                               256,
    5366                 :            :                                               FALSE,
    5367                 :            :                                               g_free,
    5368                 :            :                                               g_steal_pointer (&data_owned));
    5369                 :            : 
    5370                 :          1 :   g_assert_false (g_variant_is_normal_form (aay_deserialised));
    5371                 :          1 :   g_assert_cmpuint (g_variant_n_children (aay_deserialised), ==, 128);
    5372                 :          1 :   g_assert_cmpuint (g_variant_get_size (aay_deserialised), ==, 256);
    5373                 :            : 
    5374                 :          1 :   data = g_variant_get_data (aay_deserialised);
    5375         [ +  + ]:        257 :   for (i = 0; i < g_variant_get_size (aay_deserialised); i++)
    5376                 :        256 :     g_assert_cmpuint (data[i], ==, 0);
    5377                 :            : 
    5378                 :            :   /* Get its normal form. That should change the serialised size. */
    5379                 :          1 :   aay_normalised = g_variant_get_normal_form (aay_deserialised);
    5380                 :            : 
    5381                 :          1 :   g_assert_true (g_variant_is_normal_form (aay_normalised));
    5382                 :          1 :   g_assert_cmpuint (g_variant_n_children (aay_normalised), ==, 128);
    5383                 :          1 :   g_assert_cmpuint (g_variant_get_size (aay_normalised), ==, 128);
    5384                 :            : 
    5385                 :          1 :   data = g_variant_get_data (aay_normalised);
    5386         [ +  + ]:        129 :   for (i = 0; i < g_variant_get_size (aay_normalised); i++)
    5387                 :        128 :     g_assert_cmpuint (data[i], ==, 0);
    5388                 :            : 
    5389                 :          1 :   g_variant_unref (aay_normalised);
    5390                 :          1 :   g_variant_unref (aay_deserialised);
    5391                 :          1 :   g_variant_unref (aay_constructed);
    5392                 :          1 : }
    5393                 :            : 
    5394                 :            : /* Test that a tuple with invalidly large values in its offset table is
    5395                 :            :  * normalised successfully without looping infinitely. */
    5396                 :            : static void
    5397                 :          1 : test_normal_checking_tuple_offsets (void)
    5398                 :            : {
    5399                 :          1 :   const guint8 data[] = {
    5400                 :            :     0x07, 0xe5, 0x00, 0x07, 0x00, 0x07,
    5401                 :            :     '(', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', ')',
    5402                 :            :   };
    5403                 :          1 :   gsize size = sizeof (data);
    5404                 :          1 :   GVariant *variant = NULL;
    5405                 :          1 :   GVariant *normal_variant = NULL;
    5406                 :            : 
    5407                 :          1 :   variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
    5408                 :            :                                      FALSE, NULL, NULL);
    5409                 :          1 :   g_assert_nonnull (variant);
    5410                 :            : 
    5411                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5412                 :          1 :   g_assert_nonnull (normal_variant);
    5413                 :            : 
    5414                 :          1 :   g_variant_unref (normal_variant);
    5415                 :          1 :   g_variant_unref (variant);
    5416                 :          1 : }
    5417                 :            : 
    5418                 :            : /* This is a regression test that we can't have non-normal values that take up
    5419                 :            :  * significantly more space than the normal equivalent, by specifying the
    5420                 :            :  * offset table entries so that tuple elements overlap.
    5421                 :            :  *
    5422                 :            :  * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838503 and
    5423                 :            :  * https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838513 */
    5424                 :            : static void
    5425                 :          1 : test_normal_checking_tuple_offsets2 (void)
    5426                 :            : {
    5427                 :          1 :   const GVariantType *data_type = G_VARIANT_TYPE ("(yyaiyyaiyy)");
    5428                 :          1 :   const guint8 data[] = {
    5429                 :            :     0x12, 0x34, 0x56, 0x78, 0x01,
    5430                 :            :     /*
    5431                 :            :          ^───────────────────┘
    5432                 :            : 
    5433                 :            :     ^^^^^^^^^^                   1st yy
    5434                 :            :           ^^^^^^^^^^             2nd yy
    5435                 :            :                 ^^^^^^^^^^       3rd yy
    5436                 :            :                             ^^^^ Framing offsets
    5437                 :            :      */
    5438                 :            : 
    5439                 :            :   /* If this variant was encoded normally, it would be something like this:
    5440                 :            :    * 0x12, 0x34,  pad,  pad, [array bytes], 0x56, 0x78,  pad,  pad, [array bytes], 0x9A, 0xBC, 0xXX
    5441                 :            :    *                                      ^─────────────────────────────────────────────────────┘
    5442                 :            :    *
    5443                 :            :    * ^^^^^^^^^^                                                                                     1st yy
    5444                 :            :    *                                        ^^^^^^^^^^                                              2nd yy
    5445                 :            :    *                                                                               ^^^^^^^^^^       3rd yy
    5446                 :            :    *                                                                                           ^^^^ Framing offsets
    5447                 :            :    */
    5448                 :            :   };
    5449                 :          1 :   gsize size = sizeof (data);
    5450                 :          1 :   GVariant *variant = NULL;
    5451                 :          1 :   GVariant *normal_variant = NULL;
    5452                 :          1 :   GVariant *expected = NULL;
    5453                 :            : 
    5454                 :          1 :   variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
    5455                 :          1 :   g_assert_nonnull (variant);
    5456                 :            : 
    5457                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5458                 :          1 :   g_assert_nonnull (normal_variant);
    5459                 :          1 :   g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
    5460                 :            : 
    5461                 :          1 :   expected = g_variant_new_parsed (
    5462                 :            :       "@(yyaiyyaiyy) (0x12, 0x34, [], 0x00, 0x00, [], 0x00, 0x00)");
    5463                 :          1 :   g_assert_cmpvariant (expected, variant);
    5464                 :          1 :   g_assert_cmpvariant (expected, normal_variant);
    5465                 :            : 
    5466                 :          1 :   g_variant_unref (expected);
    5467                 :          1 :   g_variant_unref (normal_variant);
    5468                 :          1 :   g_variant_unref (variant);
    5469                 :          1 : }
    5470                 :            : 
    5471                 :            : /* This is a regression test that overlapping entries in the offset table are
    5472                 :            :  * decoded consistently, even though they’re non-normal.
    5473                 :            :  *
    5474                 :            :  * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
    5475                 :            : static void
    5476                 :          1 : test_normal_checking_tuple_offsets3 (void)
    5477                 :            : {
    5478                 :            :   /* The expected decoding of this non-normal byte stream is complex. See
    5479                 :            :    * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
    5480                 :            :    * specification.
    5481                 :            :    *
    5482                 :            :    * The rule “Child Values Overlapping Framing Offsets” from the specification
    5483                 :            :    * says that the first `ay` must be decoded as `[0x01]` even though it
    5484                 :            :    * overlaps the first byte of the offset table. However, since commit
    5485                 :            :    * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
    5486                 :            :    * this as it’s exploitable. So the first `ay` must be given a default value.
    5487                 :            :    *
    5488                 :            :    * The second and third `ay`s must be given default values because of rule
    5489                 :            :    * “End Boundary Precedes Start Boundary”.
    5490                 :            :    *
    5491                 :            :    * The `i` must be given a default value because of rule “Start or End
    5492                 :            :    * Boundary of a Child Falls Outside the Container”.
    5493                 :            :    */
    5494                 :          1 :   const GVariantType *data_type = G_VARIANT_TYPE ("(ayayiay)");
    5495                 :          1 :   const guint8 data[] = {
    5496                 :            :     0x01, 0x00, 0x02,
    5497                 :            :     /*
    5498                 :            :                ^──┘
    5499                 :            : 
    5500                 :            :     ^^^^^^^^^^                   1st ay, bytes 0-2 (but given a default value anyway, see above)
    5501                 :            :                                  2nd ay, bytes 2-0
    5502                 :            :                                      i,  bytes 0-4
    5503                 :            :                                  3rd ay, bytes 4-1
    5504                 :            :           ^^^^^^^^^^ Framing offsets
    5505                 :            :      */
    5506                 :            :   };
    5507                 :          1 :   gsize size = sizeof (data);
    5508                 :          1 :   GVariant *variant = NULL;
    5509                 :          1 :   GVariant *normal_variant = NULL;
    5510                 :          1 :   GVariant *expected = NULL;
    5511                 :            : 
    5512                 :          1 :   variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
    5513                 :          1 :   g_assert_nonnull (variant);
    5514                 :            : 
    5515                 :          1 :   g_assert_false (g_variant_is_normal_form (variant));
    5516                 :            : 
    5517                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5518                 :          1 :   g_assert_nonnull (normal_variant);
    5519                 :          1 :   g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
    5520                 :            : 
    5521                 :          1 :   expected = g_variant_new_parsed ("@(ayayiay) ([], [], 0, [])");
    5522                 :          1 :   g_assert_cmpvariant (expected, variant);
    5523                 :          1 :   g_assert_cmpvariant (expected, normal_variant);
    5524                 :            : 
    5525                 :          1 :   g_variant_unref (expected);
    5526                 :          1 :   g_variant_unref (normal_variant);
    5527                 :          1 :   g_variant_unref (variant);
    5528                 :          1 : }
    5529                 :            : 
    5530                 :            : /* This is a regression test that overlapping entries in the offset table are
    5531                 :            :  * decoded consistently, even though they’re non-normal.
    5532                 :            :  *
    5533                 :            :  * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
    5534                 :            : static void
    5535                 :          1 : test_normal_checking_tuple_offsets4 (void)
    5536                 :            : {
    5537                 :            :   /* The expected decoding of this non-normal byte stream is complex. See
    5538                 :            :    * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
    5539                 :            :    * specification.
    5540                 :            :    *
    5541                 :            :    * The rule “Child Values Overlapping Framing Offsets” from the specification
    5542                 :            :    * says that the first `ay` must be decoded as `[0x01]` even though it
    5543                 :            :    * overlaps the first byte of the offset table. However, since commit
    5544                 :            :    * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
    5545                 :            :    * this as it’s exploitable. So the first `ay` must be given a default value.
    5546                 :            :    *
    5547                 :            :    * The second `ay` must be given a default value because of rule “End Boundary
    5548                 :            :    * Precedes Start Boundary”.
    5549                 :            :    *
    5550                 :            :    * The third `ay` must be given a default value because its framing offsets
    5551                 :            :    * overlap that of the first `ay`.
    5552                 :            :    */
    5553                 :          1 :   const GVariantType *data_type = G_VARIANT_TYPE ("(ayayay)");
    5554                 :          1 :   const guint8 data[] = {
    5555                 :            :     0x01, 0x00, 0x02,
    5556                 :            :     /*
    5557                 :            :                ^──┘
    5558                 :            : 
    5559                 :            :     ^^^^^^^^^^                   1st ay, bytes 0-2 (but given a default value anyway, see above)
    5560                 :            :                                  2nd ay, bytes 2-0
    5561                 :            :                                  3rd ay, bytes 0-1
    5562                 :            :           ^^^^^^^^^^ Framing offsets
    5563                 :            :      */
    5564                 :            :   };
    5565                 :          1 :   gsize size = sizeof (data);
    5566                 :          1 :   GVariant *variant = NULL;
    5567                 :          1 :   GVariant *normal_variant = NULL;
    5568                 :          1 :   GVariant *expected = NULL;
    5569                 :            : 
    5570                 :          1 :   variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
    5571                 :          1 :   g_assert_nonnull (variant);
    5572                 :            : 
    5573                 :          1 :   g_assert_false (g_variant_is_normal_form (variant));
    5574                 :            : 
    5575                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5576                 :          1 :   g_assert_nonnull (normal_variant);
    5577                 :          1 :   g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
    5578                 :            : 
    5579                 :          1 :   expected = g_variant_new_parsed ("@(ayayay) ([], [], [])");
    5580                 :          1 :   g_assert_cmpvariant (expected, variant);
    5581                 :          1 :   g_assert_cmpvariant (expected, normal_variant);
    5582                 :            : 
    5583                 :          1 :   g_variant_unref (expected);
    5584                 :          1 :   g_variant_unref (normal_variant);
    5585                 :          1 :   g_variant_unref (variant);
    5586                 :          1 : }
    5587                 :            : 
    5588                 :            : /* This is a regression test that dereferencing the first element in the offset
    5589                 :            :  * table doesn’t dereference memory before the start of the GVariant. The first
    5590                 :            :  * element in the offset table gives the offset of the final member in the
    5591                 :            :  * tuple (the offset table is stored in reverse), and the position of this final
    5592                 :            :  * member is needed to check that none of the tuple members overlap with the
    5593                 :            :  * offset table
    5594                 :            :  *
    5595                 :            :  * See https://gitlab.gnome.org/GNOME/glib/-/issues/2840 */
    5596                 :            : static void
    5597                 :          1 : test_normal_checking_tuple_offsets5 (void)
    5598                 :            : {
    5599                 :            :   /* A tuple of type (sss) in normal form would have an offset table with two
    5600                 :            :    * entries:
    5601                 :            :    *  - The first entry (lowest index in the table) gives the offset of the
    5602                 :            :    *    third `s` in the tuple, as the offset table is reversed compared to the
    5603                 :            :    *    tuple members.
    5604                 :            :    *  - The second entry (highest index in the table) gives the offset of the
    5605                 :            :    *    second `s` in the tuple.
    5606                 :            :    *  - The offset of the first `s` in the tuple is always 0.
    5607                 :            :    *
    5608                 :            :    * See §2.5.4 (Structures) of the GVariant specification for details, noting
    5609                 :            :    * that the table is only layed out this way because all three members of the
    5610                 :            :    * tuple have non-fixed sizes.
    5611                 :            :    *
    5612                 :            :    * It’s not clear whether the 0xaa data of this variant is part of the strings
    5613                 :            :    * in the tuple, or part of the offset table. It doesn’t really matter. This
    5614                 :            :    * is a regression test to check that the code to validate the offset table
    5615                 :            :    * doesn’t unconditionally try to access the first entry in the offset table
    5616                 :            :    * by subtracting the table size from the end of the GVariant data.
    5617                 :            :    *
    5618                 :            :    * In this non-normal case, that would result in an address off the start of
    5619                 :            :    * the GVariant data, and an out-of-bounds read, because the GVariant is one
    5620                 :            :    * byte long, but the offset table is calculated as two bytes long (with 1B
    5621                 :            :    * sized entries) from the tuple’s type.
    5622                 :            :    */
    5623                 :          1 :   const GVariantType *data_type = G_VARIANT_TYPE ("(sss)");
    5624                 :          1 :   const guint8 data[] = { 0xaa };
    5625                 :          1 :   gsize size = sizeof (data);
    5626                 :          1 :   GVariant *variant = NULL;
    5627                 :          1 :   GVariant *normal_variant = NULL;
    5628                 :          1 :   GVariant *expected = NULL;
    5629                 :            : 
    5630                 :          1 :   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2840");
    5631                 :            : 
    5632                 :          1 :   variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
    5633                 :          1 :   g_assert_nonnull (variant);
    5634                 :            : 
    5635                 :          1 :   g_assert_false (g_variant_is_normal_form (variant));
    5636                 :            : 
    5637                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5638                 :          1 :   g_assert_nonnull (normal_variant);
    5639                 :            : 
    5640                 :          1 :   expected = g_variant_new_parsed ("('', '', '')");
    5641                 :          1 :   g_assert_cmpvariant (expected, variant);
    5642                 :          1 :   g_assert_cmpvariant (expected, normal_variant);
    5643                 :            : 
    5644                 :          1 :   g_variant_unref (expected);
    5645                 :          1 :   g_variant_unref (normal_variant);
    5646                 :          1 :   g_variant_unref (variant);
    5647                 :          1 : }
    5648                 :            : 
    5649                 :            : /* Test that an otherwise-valid serialised GVariant is considered non-normal if
    5650                 :            :  * its offset table entries are too wide.
    5651                 :            :  *
    5652                 :            :  * See §2.3.6 (Framing Offsets) of the GVariant specification. */
    5653                 :            : static void
    5654                 :          1 : test_normal_checking_tuple_offsets_minimal_sized (void)
    5655                 :            : {
    5656                 :          1 :   GString *type_string = NULL;
    5657                 :            :   GVariantBuilder builder;
    5658                 :            :   gsize i;
    5659                 :          1 :   GVariant *ray_constructed = NULL;
    5660                 :          1 :   const guint8 *data = NULL;
    5661                 :          1 :   guint8 *data_owned = NULL;
    5662                 :          1 :   GVariant *ray_deserialised = NULL;
    5663                 :          1 :   GVariant *ray_normalised = NULL;
    5664                 :            : 
    5665                 :            :   /* Construct a tuple of type (ay…ay), consisting of 129 members which are each
    5666                 :            :    * an empty array, i.e. `([] * 129)`. This is chosen because the inner
    5667                 :            :    * members are variable sized, so the outer tuple must have an offset table,
    5668                 :            :    * but they are also zero-sized when serialised. So the serialised
    5669                 :            :    * representation of @ray_constructed consists entirely of its offset table,
    5670                 :            :    * which is entirely zeroes.
    5671                 :            :    *
    5672                 :            :    * The tuple is chosen to be 129 members long because that means it has 128
    5673                 :            :    * offset table entries which are 1 byte long each. If the members in the
    5674                 :            :    * tuple were non-zero-sized (to the extent that the overall tuple is ≥256
    5675                 :            :    * bytes long), the offset table entries would end up being 2 bytes long.
    5676                 :            :    *
    5677                 :            :    * 129 members are used unlike 128 array elements in
    5678                 :            :    * test_normal_checking_array_offsets_minimal_sized(), because the last member
    5679                 :            :    * in a tuple never needs an offset table entry. */
    5680                 :          1 :   type_string = g_string_new ("");
    5681                 :            :   g_string_append_c (type_string, '(');
    5682         [ +  + ]:        130 :   for (i = 0; i < 129; i++)
    5683         [ +  - ]:        258 :     g_string_append (type_string, "ay");
    5684                 :            :   g_string_append_c (type_string, ')');
    5685                 :            : 
    5686                 :          1 :   g_variant_builder_init (&builder, G_VARIANT_TYPE (type_string->str));
    5687                 :            : 
    5688         [ +  + ]:        130 :   for (i = 0; i < 129; i++)
    5689                 :        129 :     g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
    5690                 :            : 
    5691                 :          1 :   ray_constructed = g_variant_builder_end (&builder);
    5692                 :            : 
    5693                 :            :   /* Verify that the constructed tuple is in normal form, and its serialised
    5694                 :            :    * form is `b'\0' * 128`. */
    5695                 :          1 :   g_assert_true (g_variant_is_normal_form (ray_constructed));
    5696                 :          1 :   g_assert_cmpuint (g_variant_n_children (ray_constructed), ==, 129);
    5697                 :          1 :   g_assert_cmpuint (g_variant_get_size (ray_constructed), ==, 128);
    5698                 :            : 
    5699                 :          1 :   data = g_variant_get_data (ray_constructed);
    5700         [ +  + ]:        129 :   for (i = 0; i < g_variant_get_size (ray_constructed); i++)
    5701                 :        128 :     g_assert_cmpuint (data[i], ==, 0);
    5702                 :            : 
    5703                 :            :   /* Construct a serialised `(ay…ay)` GVariant which is `b'\0' * 256`. This has
    5704                 :            :    * to be a non-normal form of `([] * 129)`, with 2-byte-long offset table
    5705                 :            :    * entries, because each offset table entry has to be able to reference all of
    5706                 :            :    * the byte boundaries in the container. All the entries in the offset table
    5707                 :            :    * are zero, so all the members of the tuple are zero-sized. */
    5708                 :          1 :   data = data_owned = g_malloc0 (256);
    5709                 :          1 :   ray_deserialised = g_variant_new_from_data (G_VARIANT_TYPE (type_string->str),
    5710                 :            :                                               data,
    5711                 :            :                                               256,
    5712                 :            :                                               FALSE,
    5713                 :            :                                               g_free,
    5714                 :            :                                               g_steal_pointer (&data_owned));
    5715                 :            : 
    5716                 :          1 :   g_assert_false (g_variant_is_normal_form (ray_deserialised));
    5717                 :          1 :   g_assert_cmpuint (g_variant_n_children (ray_deserialised), ==, 129);
    5718                 :          1 :   g_assert_cmpuint (g_variant_get_size (ray_deserialised), ==, 256);
    5719                 :            : 
    5720                 :          1 :   data = g_variant_get_data (ray_deserialised);
    5721         [ +  + ]:        257 :   for (i = 0; i < g_variant_get_size (ray_deserialised); i++)
    5722                 :        256 :     g_assert_cmpuint (data[i], ==, 0);
    5723                 :            : 
    5724                 :            :   /* Get its normal form. That should change the serialised size. */
    5725                 :          1 :   ray_normalised = g_variant_get_normal_form (ray_deserialised);
    5726                 :            : 
    5727                 :          1 :   g_assert_true (g_variant_is_normal_form (ray_normalised));
    5728                 :          1 :   g_assert_cmpuint (g_variant_n_children (ray_normalised), ==, 129);
    5729                 :          1 :   g_assert_cmpuint (g_variant_get_size (ray_normalised), ==, 128);
    5730                 :            : 
    5731                 :          1 :   data = g_variant_get_data (ray_normalised);
    5732         [ +  + ]:        129 :   for (i = 0; i < g_variant_get_size (ray_normalised); i++)
    5733                 :        128 :     g_assert_cmpuint (data[i], ==, 0);
    5734                 :            : 
    5735                 :          1 :   g_variant_unref (ray_normalised);
    5736                 :          1 :   g_variant_unref (ray_deserialised);
    5737                 :          1 :   g_variant_unref (ray_constructed);
    5738                 :          1 :   g_string_free (type_string, TRUE);
    5739                 :          1 : }
    5740                 :            : 
    5741                 :            : /* Test that an empty object path is normalised successfully to the base object
    5742                 :            :  * path, ‘/’. */
    5743                 :            : static void
    5744                 :          1 : test_normal_checking_empty_object_path (void)
    5745                 :            : {
    5746                 :          1 :   const guint8 data[] = {
    5747                 :            :     0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
    5748                 :            :     '(', 'h', '(', 'a', 'i', 'a', 'b', 'i', 'o', ')', ')',
    5749                 :            :   };
    5750                 :          1 :   gsize size = sizeof (data);
    5751                 :          1 :   GVariant *variant = NULL;
    5752                 :          1 :   GVariant *normal_variant = NULL;
    5753                 :            : 
    5754                 :          1 :   variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
    5755                 :            :                                      FALSE, NULL, NULL);
    5756                 :          1 :   g_assert_nonnull (variant);
    5757                 :            : 
    5758                 :          1 :   normal_variant = g_variant_get_normal_form (variant);
    5759                 :          1 :   g_assert_nonnull (normal_variant);
    5760                 :            : 
    5761                 :          1 :   g_variant_unref (normal_variant);
    5762                 :          1 :   g_variant_unref (variant);
    5763                 :          1 : }
    5764                 :            : 
    5765                 :            : /* Test that constructing a #GVariant from data which is not correctly aligned
    5766                 :            :  * for the variant type is OK, by loading a variant from data at various offsets
    5767                 :            :  * which are aligned and unaligned. When unaligned, a slow construction path
    5768                 :            :  * should be taken. */
    5769                 :            : static void
    5770                 :          1 : test_unaligned_construction (void)
    5771                 :            : {
    5772                 :          1 :   const guint8 data[] = {
    5773                 :            :     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    5774                 :            :     0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    5775                 :            :   };
    5776                 :          1 :   GVariant *variant = NULL;
    5777                 :          1 :   GVariant *normal_variant = NULL;
    5778                 :            :   gsize i, offset;
    5779                 :            :   const struct {
    5780                 :            :     const GVariantType *type;
    5781                 :            :     gsize size;
    5782                 :            :     gsize max_offset;
    5783                 :          1 :   } vectors[] = {
    5784                 :            :     { G_VARIANT_TYPE_UINT64, sizeof (guint64), sizeof (guint64) },
    5785                 :            :     { G_VARIANT_TYPE_UINT32, sizeof (guint32), sizeof (guint32) },
    5786                 :            :     { G_VARIANT_TYPE_UINT16, sizeof (guint16), sizeof (guint16) },
    5787                 :            :     { G_VARIANT_TYPE_BYTE, sizeof (guint8), 3 },
    5788                 :            :   };
    5789                 :            : 
    5790                 :            :   G_STATIC_ASSERT (sizeof (guint64) * 2 <= sizeof (data));
    5791                 :            : 
    5792         [ +  + ]:          5 :   for (i = 0; i < G_N_ELEMENTS (vectors); i++)
    5793                 :            :     {
    5794         [ +  + ]:         21 :       for (offset = 0; offset < vectors[i].max_offset; offset++)
    5795                 :            :         {
    5796                 :         17 :           variant = g_variant_new_from_data (vectors[i].type, data + offset,
    5797                 :         17 :                                              vectors[i].size,
    5798                 :            :                                              FALSE, NULL, NULL);
    5799                 :         17 :           g_assert_nonnull (variant);
    5800                 :            : 
    5801                 :         17 :           normal_variant = g_variant_get_normal_form (variant);
    5802                 :         17 :           g_assert_nonnull (normal_variant);
    5803                 :            : 
    5804                 :         17 :           g_variant_unref (normal_variant);
    5805                 :         17 :           g_variant_unref (variant);
    5806                 :            :         }
    5807                 :            :     }
    5808                 :          1 : }
    5809                 :            : 
    5810                 :            : int
    5811                 :          1 : main (int argc, char **argv)
    5812                 :            : {
    5813                 :            :   guint i;
    5814                 :            : 
    5815                 :          1 :   g_test_init (&argc, &argv, NULL);
    5816                 :            : 
    5817                 :          1 :   g_test_add_func ("/gvariant/type", test_gvarianttype);
    5818                 :          1 :   g_test_add_func ("/gvariant/type/string-scan/recursion/tuple",
    5819                 :            :                    test_gvarianttype_string_scan_recursion_tuple);
    5820                 :          1 :   g_test_add_func ("/gvariant/type/string-scan/recursion/array",
    5821                 :            :                    test_gvarianttype_string_scan_recursion_array);
    5822                 :          1 :   g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
    5823                 :          1 :   g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
    5824                 :          1 :   g_test_add_func ("/gvariant/serialiser/array", test_arrays);
    5825                 :          1 :   g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
    5826                 :          1 :   g_test_add_func ("/gvariant/serialiser/variant", test_variants);
    5827                 :          1 :   g_test_add_func ("/gvariant/serialiser/strings", test_strings);
    5828                 :          1 :   g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
    5829                 :          1 :   g_test_add_func ("/gvariant/serialiser/children", test_serialiser_children);
    5830                 :            : 
    5831         [ +  + ]:          6 :   for (i = 1; i <= 20; i += 4)
    5832                 :            :     {
    5833                 :            :       char *testname;
    5834                 :            : 
    5835                 :          5 :       testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%u%%", i);
    5836                 :          5 :       g_test_add_data_func (testname, GINT_TO_POINTER (i),
    5837                 :            :                             (gpointer) test_fuzzes);
    5838                 :          5 :       g_free (testname);
    5839                 :            :     }
    5840                 :            : 
    5841                 :          1 :   g_test_add_func ("/gvariant/string", test_string);
    5842                 :          1 :   g_test_add_func ("/gvariant/utf8", test_utf8);
    5843                 :          1 :   g_test_add_func ("/gvariant/containers", test_containers);
    5844                 :          1 :   g_test_add_func ("/gvariant/format-strings", test_format_strings);
    5845                 :          1 :   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
    5846                 :          1 :   g_test_add_func ("/gvariant/varargs", test_varargs);
    5847                 :          1 :   g_test_add_func ("/gvariant/varargs/subprocess/empty-array", test_varargs_empty_array);
    5848                 :          1 :   g_test_add_func ("/gvariant/valist", test_valist);
    5849                 :          1 :   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
    5850                 :          1 :   g_test_add_func ("/gvariant/hashing", test_hashing);
    5851                 :          1 :   g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
    5852                 :          1 :   g_test_add_func ("/gvariant/byteswap/non-normal-non-aligned", test_gv_byteswap_non_normal_non_aligned);
    5853                 :          1 :   g_test_add_func ("/gvariant/parser", test_parses);
    5854                 :          1 :   g_test_add_func ("/gvariant/parser/integer-bounds", test_parser_integer_bounds);
    5855                 :          1 :   g_test_add_func ("/gvariant/parser/recursion", test_parser_recursion);
    5856                 :          1 :   g_test_add_func ("/gvariant/parser/recursion/typedecls", test_parser_recursion_typedecls);
    5857                 :          1 :   g_test_add_func ("/gvariant/parser/recursion/maybes", test_parser_recursion_maybes);
    5858                 :          1 :   g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
    5859                 :          1 :   g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
    5860                 :          1 :   g_test_add_func ("/gvariant/parse/subprocess/bad-format-char", test_parse_bad_format_char);
    5861                 :          1 :   g_test_add_func ("/gvariant/parse/subprocess/bad-format-string", test_parse_bad_format_string);
    5862                 :          1 :   g_test_add_func ("/gvariant/parse/subprocess/bad-args", test_parse_bad_args);
    5863                 :          1 :   g_test_add_func ("/gvariant/floating", test_floating);
    5864                 :          1 :   g_test_add_func ("/gvariant/bytestring", test_bytestring);
    5865                 :          1 :   g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
    5866                 :          1 :   g_test_add_func ("/gvariant/lookup", test_lookup);
    5867                 :          1 :   g_test_add_func ("/gvariant/compare", test_compare);
    5868                 :          1 :   g_test_add_func ("/gvariant/equal", test_equal);
    5869                 :          1 :   g_test_add_func ("/gvariant/fixed-array", test_fixed_array);
    5870                 :          1 :   g_test_add_func ("/gvariant/check-format-string", test_check_format_string);
    5871                 :            : 
    5872                 :          1 :   g_test_add_func ("/gvariant/checksum-basic", test_checksum_basic);
    5873                 :          1 :   g_test_add_func ("/gvariant/checksum-nested", test_checksum_nested);
    5874                 :            : 
    5875                 :          1 :   g_test_add_func ("/gvariant/gbytes", test_gbytes);
    5876                 :          1 :   g_test_add_func ("/gvariant/print-context", test_print_context);
    5877                 :          1 :   g_test_add_func ("/gvariant/error-quark", test_error_quark);
    5878                 :            : 
    5879                 :          1 :   g_test_add_func ("/gvariant/stack-builder-init", test_stack_builder_init);
    5880                 :          1 :   g_test_add_func ("/gvariant/stack-dict-init", test_stack_dict_init);
    5881                 :            : 
    5882                 :          1 :   g_test_add_func ("/gvariant/normal-checking/tuples",
    5883                 :            :                    test_normal_checking_tuples);
    5884                 :          1 :   g_test_add_func ("/gvariant/normal-checking/array-offsets/overlapped",
    5885                 :            :                    test_normal_checking_array_offsets_overlapped);
    5886                 :          1 :   g_test_add_func ("/gvariant/normal-checking/array-offsets",
    5887                 :            :                    test_normal_checking_array_offsets);
    5888                 :          1 :   g_test_add_func ("/gvariant/normal-checking/array-offsets2",
    5889                 :            :                    test_normal_checking_array_offsets2);
    5890                 :          1 :   g_test_add_func ("/gvariant/normal-checking/array-offsets/minimal-sized",
    5891                 :            :                    test_normal_checking_array_offsets_minimal_sized);
    5892                 :          1 :   g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
    5893                 :            :                    test_normal_checking_tuple_offsets);
    5894                 :          1 :   g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
    5895                 :            :                    test_normal_checking_tuple_offsets2);
    5896                 :          1 :   g_test_add_func ("/gvariant/normal-checking/tuple-offsets3",
    5897                 :            :                    test_normal_checking_tuple_offsets3);
    5898                 :          1 :   g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
    5899                 :            :                    test_normal_checking_tuple_offsets4);
    5900                 :          1 :   g_test_add_func ("/gvariant/normal-checking/tuple-offsets5",
    5901                 :            :                    test_normal_checking_tuple_offsets5);
    5902                 :          1 :   g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
    5903                 :            :                    test_normal_checking_tuple_offsets_minimal_sized);
    5904                 :          1 :   g_test_add_func ("/gvariant/normal-checking/empty-object-path",
    5905                 :            :                    test_normal_checking_empty_object_path);
    5906                 :            : 
    5907                 :          1 :   g_test_add_func ("/gvariant/recursion-limits/variant-in-variant",
    5908                 :            :                    test_recursion_limits_variant_in_variant);
    5909                 :          1 :   g_test_add_func ("/gvariant/recursion-limits/array-in-variant",
    5910                 :            :                    test_recursion_limits_array_in_variant);
    5911                 :            : 
    5912                 :          1 :   g_test_add_func ("/gvariant/unaligned-construction",
    5913                 :            :                    test_unaligned_construction);
    5914                 :            : 
    5915                 :          1 :   return g_test_run ();
    5916                 :            : }

Generated by: LCOV version 1.14