Merge lp:~attente/glib/gicon-upstream into lp:ubuntu/saucy/glib2.0

Proposed by William Hua
Status: Merged
Merge reported by: Sebastien Bacher
Merged at revision: not available
Proposed branch: lp:~attente/glib/gicon-upstream
Merge into: lp:ubuntu/saucy/glib2.0
Diff against target: 27569 lines (+26956/-46)
51 files modified
.pc/applied-patches (+3/-0)
.pc/g-variant-get-data-as-bytes.patch/glib/gvariant-core.c (+1104/-0)
.pc/g-variant-get-data-as-bytes.patch/glib/tests/gvariant.c (+4339/-0)
.pc/g-variant-new-take-string.patch/docs/reference/glib/glib-sections.txt (+3227/-0)
.pc/g-variant-new-take-string.patch/glib/gvariant.c (+5328/-0)
.pc/g-variant-new-take-string.patch/glib/gvariant.h (+395/-0)
.pc/gicon-serialization-support.patch/docs/reference/gio/gio-docs.xml (+306/-0)
.pc/gicon-serialization-support.patch/docs/reference/gio/gio-sections.txt (+4024/-0)
.pc/gicon-serialization-support.patch/gio/Makefile.am (+786/-0)
.pc/gicon-serialization-support.patch/gio/gemblem.c (+359/-0)
.pc/gicon-serialization-support.patch/gio/gemblemedicon.c (+423/-0)
.pc/gicon-serialization-support.patch/gio/gfileicon.c (+340/-0)
.pc/gicon-serialization-support.patch/gio/gicon.c (+449/-0)
.pc/gicon-serialization-support.patch/gio/gicon.h (+96/-0)
.pc/gicon-serialization-support.patch/gio/gio.h (+164/-0)
.pc/gicon-serialization-support.patch/gio/giotypes.h (+473/-0)
.pc/gicon-serialization-support.patch/gio/gmenu.c (+1336/-0)
.pc/gicon-serialization-support.patch/gio/gmenu.h (+177/-0)
.pc/gicon-serialization-support.patch/gio/gmenumodel.h (+276/-0)
.pc/gicon-serialization-support.patch/gio/gthemedicon.c (+522/-0)
.pc/gicon-serialization-support.patch/gio/gvfs.h (+133/-0)
.pc/gicon-serialization-support.patch/gio/tests/g-icon.c (+382/-0)
debian/changelog (+11/-0)
debian/libglib2.0-0.symbols (+7/-0)
debian/patches/g-variant-get-data-as-bytes.patch (+58/-0)
debian/patches/g-variant-new-take-string.patch (+66/-0)
debian/patches/gicon-serialization-support.patch (+1205/-0)
debian/patches/series (+3/-0)
docs/reference/gio/gio-docs.xml (+1/-0)
docs/reference/gio/gio-sections.txt (+19/-1)
docs/reference/glib/glib-sections.txt (+1/-0)
gio/Makefile.am (+2/-0)
gio/gbytesicon.c (+264/-0)
gio/gbytesicon.h (+54/-0)
gio/gemblem.c (+21/-0)
gio/gemblemedicon.c (+49/-0)
gio/gfileicon.c (+9/-0)
gio/gicon.c (+277/-39)
gio/gicon.h (+7/-0)
gio/gio.h (+1/-0)
gio/giotypes.h (+1/-0)
gio/gmenu.c (+41/-0)
gio/gmenu.h (+4/-0)
gio/gmenumodel.h (+15/-0)
gio/gthemedicon.c (+9/-0)
gio/gvfs.h (+2/-1)
gio/tests/g-icon.c (+121/-1)
glib/gvariant-core.c (+14/-1)
glib/gvariant.c (+36/-0)
glib/gvariant.h (+2/-0)
glib/tests/gvariant.c (+14/-3)
To merge this branch: bzr merge lp:~attente/glib/gicon-upstream
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+162430@code.launchpad.net

Commit message

* debian/patches/g-variant-new-take-string.patch:
  - Add upstream's g_variant_new_take_string ().
* debian/patches/g-variant-get-data-as-bytes.patch:
  - Add upstream's GVariant bytes serialization bug fix.
* debian/patches/gicon-serialization-support.patch:
  - Add upstream's improved GIcon serialization support.

Description of the change

Patch GLib with upstream bug fixes to GVariant and changes to GIcon interface.

To post a comment you must log in.
Revision history for this message
Sebastien Bacher (seb128) wrote :

thanks, setting as "merged" since we got the new glib

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.pc/applied-patches'
2--- .pc/applied-patches 2013-04-10 11:43:24 +0000
3+++ .pc/applied-patches 2013-05-03 17:57:29 +0000
4@@ -13,3 +13,6 @@
5 17_check_abis_mips_symbols.patch
6 61_glib-compile-binaries-path.patch
7 90_gio-modules-multiarch-compat.patch
8+g-variant-new-take-string.patch
9+g-variant-get-data-as-bytes.patch
10+gicon-serialization-support.patch
11
12=== added directory '.pc/g-variant-get-data-as-bytes.patch'
13=== added directory '.pc/g-variant-get-data-as-bytes.patch/glib'
14=== added file '.pc/g-variant-get-data-as-bytes.patch/glib/gvariant-core.c'
15--- .pc/g-variant-get-data-as-bytes.patch/glib/gvariant-core.c 1970-01-01 00:00:00 +0000
16+++ .pc/g-variant-get-data-as-bytes.patch/glib/gvariant-core.c 2013-05-03 17:57:29 +0000
17@@ -0,0 +1,1104 @@
18+/*
19+ * Copyright © 2007, 2008 Ryan Lortie
20+ * Copyright © 2010 Codethink Limited
21+ *
22+ * This library is free software; you can redistribute it and/or
23+ * modify it under the terms of the GNU Lesser General Public
24+ * License as published by the Free Software Foundation; either
25+ * version 2 of the License, or (at your option) any later version.
26+ *
27+ * This library is distributed in the hope that it will be useful,
28+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30+ * Lesser General Public License for more details.
31+ *
32+ * You should have received a copy of the GNU Lesser General Public
33+ * License along with this library; if not, write to the
34+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
35+ * Boston, MA 02111-1307, USA.
36+ */
37+
38+#include "config.h"
39+
40+#include <glib/gvariant-core.h>
41+
42+#include <glib/gvariant-serialiser.h>
43+#include <glib/gtestutils.h>
44+#include <glib/gbitlock.h>
45+#include <glib/gatomic.h>
46+#include <glib/gbytes.h>
47+#include <glib/gslice.h>
48+#include <glib/gmem.h>
49+#include <string.h>
50+
51+
52+/*
53+ * This file includes the structure definition for GVariant and a small
54+ * set of functions that are allowed to access the structure directly.
55+ *
56+ * This minimises the amount of code that can possibly touch a GVariant
57+ * structure directly to a few simple fundamental operations. These few
58+ * operations are written to be completely threadsafe with respect to
59+ * all possible outside access. This means that we only need to be
60+ * concerned about thread safety issues in this one small file.
61+ *
62+ * Most GVariant API functions are in gvariant.c.
63+ */
64+
65+/**
66+ * GVariant:
67+ *
68+ * #GVariant is an opaque data structure and can only be accessed
69+ * using the following functions.
70+ *
71+ * Since: 2.24
72+ **/
73+struct _GVariant
74+/* see below for field member documentation */
75+{
76+ GVariantTypeInfo *type_info;
77+ gsize size;
78+
79+ union
80+ {
81+ struct
82+ {
83+ GBytes *bytes;
84+ gconstpointer data;
85+ } serialised;
86+
87+ struct
88+ {
89+ GVariant **children;
90+ gsize n_children;
91+ } tree;
92+ } contents;
93+
94+ gint state;
95+ gint ref_count;
96+};
97+
98+/* struct GVariant:
99+ *
100+ * There are two primary forms of GVariant instances: "serialised form"
101+ * and "tree form".
102+ *
103+ * "serialised form": A serialised GVariant instance stores its value in
104+ * the GVariant serialisation format. All
105+ * basic-typed instances (ie: non-containers) are in
106+ * serialised format, as are some containers.
107+ *
108+ * "tree form": Some containers are in "tree form". In this case,
109+ * instead of containing the serialised data for the
110+ * container, the instance contains an array of pointers to
111+ * the child values of the container (thus forming a tree).
112+ *
113+ * It is possible for an instance to transition from tree form to
114+ * serialised form. This happens, implicitly, if the serialised data is
115+ * requested (eg: via g_variant_get_data()). Serialised form instances
116+ * never transition into tree form.
117+ *
118+ *
119+ * The fields of the structure are documented here:
120+ *
121+ * type_info: this is a reference to a GVariantTypeInfo describing the
122+ * type of the instance. When the instance is freed, this
123+ * reference must be released with g_variant_type_info_unref().
124+ *
125+ * The type_info field never changes during the life of the
126+ * instance, so it can be accessed without a lock.
127+ *
128+ * size: this is the size of the serialised form for the instance, if it
129+ * is known. If the instance is in serialised form then it is, by
130+ * definition, known. If the instance is in tree form then it may
131+ * be unknown (in which case it is -1). It is possible for the
132+ * size to be known when in tree form if, for example, the user
133+ * has called g_variant_get_size() without calling
134+ * g_variant_get_data(). Additionally, even when the user calls
135+ * g_variant_get_data() the size of the data must first be
136+ * determined so that a large enough buffer can be allocated for
137+ * the data.
138+ *
139+ * Once the size is known, it can never become unknown again.
140+ * g_variant_ensure_size() is used to ensure that the size is in
141+ * the known state -- it calculates the size if needed. After
142+ * that, the size field can be accessed without a lock.
143+ *
144+ * contents: a union containing either the information associated with
145+ * holding a value in serialised form or holding a value in
146+ * tree form.
147+ *
148+ * .serialised: Only valid when the instance is in serialised form.
149+ *
150+ * Since an instance can never transition away from
151+ * serialised form, once these fields are set, they will
152+ * never be changed. It is therefore valid to access
153+ * them without holding a lock.
154+ *
155+ * .bytes: the #GBytes that contains the memory pointed to by
156+ * .data, or %NULL if .data is %NULL. In the event that
157+ * the instance was deserialised from another instance,
158+ * then the bytes will be shared by both of them. When
159+ * the instance is freed, this reference must be released
160+ * with g_bytes_unref().
161+ *
162+ * .data: the serialised data (of size 'size') of the instance.
163+ * This pointer should not be freed or modified in any way.
164+ * #GBytes is responsible for memory management.
165+ *
166+ * This pointer may be %NULL in two cases:
167+ *
168+ * - if the serialised size of the instance is 0
169+ *
170+ * - if the instance is of a fixed-sized type and was
171+ * deserialised out of a corrupted container such that
172+ * the container contains too few bytes to point to the
173+ * entire proper fixed-size of this instance. In this
174+ * case, 'size' will still be equal to the proper fixed
175+ * size, but this pointer will be %NULL. This is exactly
176+ * the reason that g_variant_get_data() sometimes returns
177+ * %NULL. For all other calls, the effect should be as
178+ * if .data pointed to the appropriate number of nul
179+ * bytes.
180+ *
181+ * .tree: Only valid when the instance is in tree form.
182+ *
183+ * Note that accesses from other threads could result in
184+ * conversion of the instance from tree form to serialised form
185+ * at any time. For this reason, the instance lock must always
186+ * be held while performing any operations on 'contents.tree'.
187+ *
188+ * .children: the array of the child instances of this instance.
189+ * When the instance is freed (or converted to serialised
190+ * form) then each child must have g_variant_unref()
191+ * called on it and the array must be freed using
192+ * g_free().
193+ *
194+ * .n_children: the number of items in the .children array.
195+ *
196+ * state: a bitfield describing the state of the instance. It is a
197+ * bitwise-or of the following STATE_* constants:
198+ *
199+ * STATE_LOCKED: the instance lock is held. This is the bit used by
200+ * g_bit_lock().
201+ *
202+ * STATE_SERIALISED: the instance is in serialised form. If this
203+ * flag is not set then the instance is in tree
204+ * form.
205+ *
206+ * STATE_TRUSTED: for serialised form instances, this means that the
207+ * serialised data is known to be in normal form (ie:
208+ * not corrupted).
209+ *
210+ * For tree form instances, this means that all of the
211+ * child instances in the contents.tree.children array
212+ * are trusted. This means that if the container is
213+ * serialised then the resulting data will be in
214+ * normal form.
215+ *
216+ * If this flag is unset it does not imply that the
217+ * data is corrupted. It merely means that we're not
218+ * sure that it's valid. See g_variant_is_trusted().
219+ *
220+ * STATE_FLOATING: if this flag is set then the object has a floating
221+ * reference. See g_variant_ref_sink().
222+ *
223+ * ref_count: the reference count of the instance
224+ */
225+#define STATE_LOCKED 1
226+#define STATE_SERIALISED 2
227+#define STATE_TRUSTED 4
228+#define STATE_FLOATING 8
229+
230+/* -- private -- */
231+/* < private >
232+ * g_variant_lock:
233+ * @value: a #GVariant
234+ *
235+ * Locks @value for performing sensitive operations.
236+ */
237+static void
238+g_variant_lock (GVariant *value)
239+{
240+ g_bit_lock (&value->state, 0);
241+}
242+
243+/* < private >
244+ * g_variant_unlock:
245+ * @value: a #GVariant
246+ *
247+ * Unlocks @value after performing sensitive operations.
248+ */
249+static void
250+g_variant_unlock (GVariant *value)
251+{
252+ g_bit_unlock (&value->state, 0);
253+}
254+
255+/* < private >
256+ * g_variant_release_children:
257+ * @value: a #GVariant
258+ *
259+ * Releases the reference held on each child in the 'children' array of
260+ * @value and frees the array itself. @value must be in tree form.
261+ *
262+ * This is done when freeing a tree-form instance or converting it to
263+ * serialised form.
264+ *
265+ * The current thread must hold the lock on @value.
266+ */
267+static void
268+g_variant_release_children (GVariant *value)
269+{
270+ gsize i;
271+
272+ g_assert (value->state & STATE_LOCKED);
273+ g_assert (~value->state & STATE_SERIALISED);
274+
275+ for (i = 0; i < value->contents.tree.n_children; i++)
276+ g_variant_unref (value->contents.tree.children[i]);
277+
278+ g_free (value->contents.tree.children);
279+}
280+
281+/* This begins the main body of the recursive serialiser.
282+ *
283+ * There are 3 functions here that work as a team with the serialiser to
284+ * get things done. g_variant_store() has a trivial role, but as a
285+ * public API function, it has its definition elsewhere.
286+ *
287+ * Note that "serialisation" of an instance does not mean that the
288+ * instance is converted to serialised form -- it means that the
289+ * serialised form of an instance is written to an external buffer.
290+ * g_variant_ensure_serialised() (which is not part of this set of
291+ * functions) is the function that is responsible for converting an
292+ * instance to serialised form.
293+ *
294+ * We are only concerned here with container types since non-container
295+ * instances are always in serialised form. For these instances,
296+ * storing their serialised form merely involves a memcpy().
297+ *
298+ * Serialisation is a two-step process. First, the size of the
299+ * serialised data must be calculated so that an appropriately-sized
300+ * buffer can be allocated. Second, the data is written into the
301+ * buffer.
302+ *
303+ * Determining the size:
304+ * The process of determining the size is triggered by a call to
305+ * g_variant_ensure_size() on a container. This invokes the
306+ * serialiser code to determine the size. The serialiser is passed
307+ * g_variant_fill_gvs() as a callback.
308+ *
309+ * g_variant_fill_gvs() is called by the serialiser on each child of
310+ * the container which, in turn, calls g_variant_ensure_size() on
311+ * itself and fills in the result of its own size calculation.
312+ *
313+ * The serialiser uses the size information from the children to
314+ * calculate the size needed for the entire container.
315+ *
316+ * Writing the data:
317+ * After the buffer has been allocated, g_variant_serialise() is
318+ * called on the container. This invokes the serialiser code to write
319+ * the bytes to the container. The serialiser is, again, passed
320+ * g_variant_fill_gvs() as a callback.
321+ *
322+ * This time, when g_variant_fill_gvs() is called for each child, the
323+ * child is given a pointer to a sub-region of the allocated buffer
324+ * where it should write its data. This is done by calling
325+ * g_variant_store(). In the event that the instance is in serialised
326+ * form this means a memcpy() of the serialised data into the
327+ * allocated buffer. In the event that the instance is in tree form
328+ * this means a recursive call back into g_variant_serialise().
329+ *
330+ *
331+ * The forward declaration here allows corecursion via callback:
332+ */
333+static void g_variant_fill_gvs (GVariantSerialised *, gpointer);
334+
335+/* < private >
336+ * g_variant_ensure_size:
337+ * @value: a #GVariant
338+ *
339+ * Ensures that the ->size field of @value is filled in properly. This
340+ * must be done as a precursor to any serialisation of the value in
341+ * order to know how large of a buffer is needed to store the data.
342+ *
343+ * The current thread must hold the lock on @value.
344+ */
345+static void
346+g_variant_ensure_size (GVariant *value)
347+{
348+ g_assert (value->state & STATE_LOCKED);
349+
350+ if (value->size == (gssize) -1)
351+ {
352+ gpointer *children;
353+ gsize n_children;
354+
355+ children = (gpointer *) value->contents.tree.children;
356+ n_children = value->contents.tree.n_children;
357+ value->size = g_variant_serialiser_needed_size (value->type_info,
358+ g_variant_fill_gvs,
359+ children, n_children);
360+ }
361+}
362+
363+/* < private >
364+ * g_variant_serialise:
365+ * @value: a #GVariant
366+ * @data: an appropriately-sized buffer
367+ *
368+ * Serialises @value into @data. @value must be in tree form.
369+ *
370+ * No change is made to @value.
371+ *
372+ * The current thread must hold the lock on @value.
373+ */
374+static void
375+g_variant_serialise (GVariant *value,
376+ gpointer data)
377+{
378+ GVariantSerialised serialised = { 0, };
379+ gpointer *children;
380+ gsize n_children;
381+
382+ g_assert (~value->state & STATE_SERIALISED);
383+ g_assert (value->state & STATE_LOCKED);
384+
385+ serialised.type_info = value->type_info;
386+ serialised.size = value->size;
387+ serialised.data = data;
388+
389+ children = (gpointer *) value->contents.tree.children;
390+ n_children = value->contents.tree.n_children;
391+
392+ g_variant_serialiser_serialise (serialised, g_variant_fill_gvs,
393+ children, n_children);
394+}
395+
396+/* < private >
397+ * g_variant_fill_gvs:
398+ * @serialised: a pointer to a #GVariantSerialised
399+ * @data: a #GVariant instance
400+ *
401+ * This is the callback that is passed by a tree-form container instance
402+ * to the serialiser. This callback gets called on each child of the
403+ * container. Each child is responsible for performing the following
404+ * actions:
405+ *
406+ * - reporting its type
407+ *
408+ * - reporting its serialised size (requires knowing the size first)
409+ *
410+ * - possibly storing its serialised form into the provided buffer
411+ */
412+static void
413+g_variant_fill_gvs (GVariantSerialised *serialised,
414+ gpointer data)
415+{
416+ GVariant *value = data;
417+
418+ g_variant_lock (value);
419+ g_variant_ensure_size (value);
420+ g_variant_unlock (value);
421+
422+ if (serialised->type_info == NULL)
423+ serialised->type_info = value->type_info;
424+ g_assert (serialised->type_info == value->type_info);
425+
426+ if (serialised->size == 0)
427+ serialised->size = value->size;
428+ g_assert (serialised->size == value->size);
429+
430+ if (serialised->data)
431+ /* g_variant_store() is a public API, so it
432+ * it will reacquire the lock if it needs to.
433+ */
434+ g_variant_store (value, serialised->data);
435+}
436+
437+/* this ends the main body of the recursive serialiser */
438+
439+/* < private >
440+ * g_variant_ensure_serialised:
441+ * @value: a #GVariant
442+ *
443+ * Ensures that @value is in serialised form.
444+ *
445+ * If @value is in tree form then this function ensures that the
446+ * serialised size is known and then allocates a buffer of that size and
447+ * serialises the instance into the buffer. The 'children' array is
448+ * then released and the instance is set to serialised form based on the
449+ * contents of the buffer.
450+ *
451+ * The current thread must hold the lock on @value.
452+ */
453+static void
454+g_variant_ensure_serialised (GVariant *value)
455+{
456+ g_assert (value->state & STATE_LOCKED);
457+
458+ if (~value->state & STATE_SERIALISED)
459+ {
460+ GBytes *bytes;
461+ gpointer data;
462+
463+ g_variant_ensure_size (value);
464+ data = g_malloc (value->size);
465+ g_variant_serialise (value, data);
466+
467+ g_variant_release_children (value);
468+
469+ bytes = g_bytes_new_take (data, value->size);
470+ value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
471+ value->contents.serialised.bytes = bytes;
472+ value->state |= STATE_SERIALISED;
473+ }
474+}
475+
476+/* < private >
477+ * g_variant_alloc:
478+ * @type: the type of the new instance
479+ * @serialised: if the instance will be in serialised form
480+ * @trusted: if the instance will be trusted
481+ *
482+ * Allocates a #GVariant instance and does some common work (such as
483+ * looking up and filling in the type info), setting the state field,
484+ * and setting the ref_count to 1.
485+ *
486+ * Returns: a new #GVariant with a floating reference
487+ */
488+static GVariant *
489+g_variant_alloc (const GVariantType *type,
490+ gboolean serialised,
491+ gboolean trusted)
492+{
493+ GVariant *value;
494+
495+ value = g_slice_new (GVariant);
496+ value->type_info = g_variant_type_info_get (type);
497+ value->state = (serialised ? STATE_SERIALISED : 0) |
498+ (trusted ? STATE_TRUSTED : 0) |
499+ STATE_FLOATING;
500+ value->size = (gssize) -1;
501+ value->ref_count = 1;
502+
503+ return value;
504+}
505+
506+/**
507+ * g_variant_new_from_bytes:
508+ * @type: a #GVariantType
509+ * @bytes: a #GBytes
510+ * @trusted: if the contents of @bytes are trusted
511+ *
512+ * Constructs a new serialised-mode #GVariant instance. This is the
513+ * inner interface for creation of new serialised values that gets
514+ * called from various functions in gvariant.c.
515+ *
516+ * A reference is taken on @bytes.
517+ *
518+ * Returns: a new #GVariant with a floating reference
519+ *
520+ * Since: 2.36
521+ */
522+GVariant *
523+g_variant_new_from_bytes (const GVariantType *type,
524+ GBytes *bytes,
525+ gboolean trusted)
526+{
527+ GVariant *value;
528+ guint alignment;
529+ gsize size;
530+
531+ value = g_variant_alloc (type, TRUE, trusted);
532+
533+ value->contents.serialised.bytes = g_bytes_ref (bytes);
534+
535+ g_variant_type_info_query (value->type_info,
536+ &alignment, &size);
537+
538+ if (size && g_bytes_get_size (bytes) != size)
539+ {
540+ /* Creating a fixed-sized GVariant with a bytes of the wrong
541+ * size.
542+ *
543+ * We should do the equivalent of pulling a fixed-sized child out
544+ * of a brozen container (ie: data is NULL size is equal to the correct
545+ * fixed size).
546+ */
547+ value->contents.serialised.data = NULL;
548+ value->size = size;
549+ }
550+ else
551+ {
552+ value->contents.serialised.data = g_bytes_get_data (bytes, &value->size);
553+ }
554+
555+ return value;
556+}
557+
558+/* -- internal -- */
559+
560+/* < internal >
561+ * g_variant_new_from_children:
562+ * @type: a #GVariantType
563+ * @children: an array of #GVariant pointers. Consumed.
564+ * @n_children: the length of @children
565+ * @trusted: %TRUE if every child in @children in trusted
566+ *
567+ * Constructs a new tree-mode #GVariant instance. This is the inner
568+ * interface for creation of new serialised values that gets called from
569+ * various functions in gvariant.c.
570+ *
571+ * @children is consumed by this function. g_free() will be called on
572+ * it some time later.
573+ *
574+ * Returns: a new #GVariant with a floating reference
575+ */
576+GVariant *
577+g_variant_new_from_children (const GVariantType *type,
578+ GVariant **children,
579+ gsize n_children,
580+ gboolean trusted)
581+{
582+ GVariant *value;
583+
584+ value = g_variant_alloc (type, FALSE, trusted);
585+ value->contents.tree.children = children;
586+ value->contents.tree.n_children = n_children;
587+
588+ return value;
589+}
590+
591+/* < internal >
592+ * g_variant_get_type_info:
593+ * @value: a #GVariant
594+ *
595+ * Returns the #GVariantTypeInfo corresponding to the type of @value. A
596+ * reference is not added, so the return value is only good for the
597+ * duration of the life of @value.
598+ *
599+ * Returns: the #GVariantTypeInfo for @value
600+ */
601+GVariantTypeInfo *
602+g_variant_get_type_info (GVariant *value)
603+{
604+ return value->type_info;
605+}
606+
607+/* < internal >
608+ * g_variant_is_trusted:
609+ * @value: a #GVariant
610+ *
611+ * Determines if @value is trusted by #GVariant to contain only
612+ * fully-valid data. All values constructed solely via #GVariant APIs
613+ * are trusted, but values containing data read in from other sources
614+ * are usually not trusted.
615+ *
616+ * The main advantage of trusted data is that certain checks can be
617+ * skipped. For example, we don't need to check that a string is
618+ * properly nul-terminated or that an object path is actually a
619+ * properly-formatted object path.
620+ *
621+ * Returns: if @value is trusted
622+ */
623+gboolean
624+g_variant_is_trusted (GVariant *value)
625+{
626+ return (value->state & STATE_TRUSTED) != 0;
627+}
628+
629+/* -- public -- */
630+
631+/**
632+ * g_variant_unref:
633+ * @value: a #GVariant
634+ *
635+ * Decreases the reference count of @value. When its reference count
636+ * drops to 0, the memory used by the variant is freed.
637+ *
638+ * Since: 2.24
639+ **/
640+void
641+g_variant_unref (GVariant *value)
642+{
643+ g_return_if_fail (value != NULL);
644+ g_return_if_fail (value->ref_count > 0);
645+
646+ if (g_atomic_int_dec_and_test (&value->ref_count))
647+ {
648+ if G_UNLIKELY (value->state & STATE_LOCKED)
649+ g_critical ("attempting to free a locked GVariant instance. "
650+ "This should never happen.");
651+
652+ value->state |= STATE_LOCKED;
653+
654+ g_variant_type_info_unref (value->type_info);
655+
656+ if (value->state & STATE_SERIALISED)
657+ g_bytes_unref (value->contents.serialised.bytes);
658+ else
659+ g_variant_release_children (value);
660+
661+ memset (value, 0, sizeof (GVariant));
662+ g_slice_free (GVariant, value);
663+ }
664+}
665+
666+/**
667+ * g_variant_ref:
668+ * @value: a #GVariant
669+ *
670+ * Increases the reference count of @value.
671+ *
672+ * Returns: the same @value
673+ *
674+ * Since: 2.24
675+ **/
676+GVariant *
677+g_variant_ref (GVariant *value)
678+{
679+ g_return_val_if_fail (value != NULL, NULL);
680+ g_return_val_if_fail (value->ref_count > 0, NULL);
681+
682+ g_atomic_int_inc (&value->ref_count);
683+
684+ return value;
685+}
686+
687+/**
688+ * g_variant_ref_sink:
689+ * @value: a #GVariant
690+ *
691+ * #GVariant uses a floating reference count system. All functions with
692+ * names starting with <literal>g_variant_new_</literal> return floating
693+ * references.
694+ *
695+ * Calling g_variant_ref_sink() on a #GVariant with a floating reference
696+ * will convert the floating reference into a full reference. Calling
697+ * g_variant_ref_sink() on a non-floating #GVariant results in an
698+ * additional normal reference being added.
699+ *
700+ * In other words, if the @value is floating, then this call "assumes
701+ * ownership" of the floating reference, converting it to a normal
702+ * reference. If the @value is not floating, then this call adds a
703+ * new normal reference increasing the reference count by one.
704+ *
705+ * All calls that result in a #GVariant instance being inserted into a
706+ * container will call g_variant_ref_sink() on the instance. This means
707+ * that if the value was just created (and has only its floating
708+ * reference) then the container will assume sole ownership of the value
709+ * at that point and the caller will not need to unreference it. This
710+ * makes certain common styles of programming much easier while still
711+ * maintaining normal refcounting semantics in situations where values
712+ * are not floating.
713+ *
714+ * Returns: the same @value
715+ *
716+ * Since: 2.24
717+ **/
718+GVariant *
719+g_variant_ref_sink (GVariant *value)
720+{
721+ g_return_val_if_fail (value != NULL, NULL);
722+ g_return_val_if_fail (value->ref_count > 0, NULL);
723+
724+ g_variant_lock (value);
725+
726+ if (~value->state & STATE_FLOATING)
727+ g_variant_ref (value);
728+ else
729+ value->state &= ~STATE_FLOATING;
730+
731+ g_variant_unlock (value);
732+
733+ return value;
734+}
735+
736+/**
737+ * g_variant_take_ref:
738+ * @value: a #GVariant
739+ *
740+ * If @value is floating, sink it. Otherwise, do nothing.
741+ *
742+ * Typically you want to use g_variant_ref_sink() in order to
743+ * automatically do the correct thing with respect to floating or
744+ * non-floating references, but there is one specific scenario where
745+ * this function is helpful.
746+ *
747+ * The situation where this function is helpful is when creating an API
748+ * that allows the user to provide a callback function that returns a
749+ * #GVariant. We certainly want to allow the user the flexibility to
750+ * return a non-floating reference from this callback (for the case
751+ * where the value that is being returned already exists).
752+ *
753+ * At the same time, the style of the #GVariant API makes it likely that
754+ * for newly-created #GVariant instances, the user can be saved some
755+ * typing if they are allowed to return a #GVariant with a floating
756+ * reference.
757+ *
758+ * Using this function on the return value of the user's callback allows
759+ * the user to do whichever is more convenient for them. The caller
760+ * will alway receives exactly one full reference to the value: either
761+ * the one that was returned in the first place, or a floating reference
762+ * that has been converted to a full reference.
763+ *
764+ * This function has an odd interaction when combined with
765+ * g_variant_ref_sink() running at the same time in another thread on
766+ * the same #GVariant instance. If g_variant_ref_sink() runs first then
767+ * the result will be that the floating reference is converted to a hard
768+ * reference. If g_variant_take_ref() runs first then the result will
769+ * be that the floating reference is converted to a hard reference and
770+ * an additional reference on top of that one is added. It is best to
771+ * avoid this situation.
772+ *
773+ * Returns: the same @value
774+ **/
775+GVariant *
776+g_variant_take_ref (GVariant *value)
777+{
778+ g_return_val_if_fail (value != NULL, NULL);
779+ g_return_val_if_fail (value->ref_count > 0, NULL);
780+
781+ g_atomic_int_and (&value->state, ~STATE_FLOATING);
782+
783+ return value;
784+}
785+
786+/**
787+ * g_variant_is_floating:
788+ * @value: a #GVariant
789+ *
790+ * Checks whether @value has a floating reference count.
791+ *
792+ * This function should only ever be used to assert that a given variant
793+ * is or is not floating, or for debug purposes. To acquire a reference
794+ * to a variant that might be floating, always use g_variant_ref_sink()
795+ * or g_variant_take_ref().
796+ *
797+ * See g_variant_ref_sink() for more information about floating reference
798+ * counts.
799+ *
800+ * Returns: whether @value is floating
801+ *
802+ * Since: 2.26
803+ **/
804+gboolean
805+g_variant_is_floating (GVariant *value)
806+{
807+ g_return_val_if_fail (value != NULL, FALSE);
808+
809+ return (value->state & STATE_FLOATING) != 0;
810+}
811+
812+/**
813+ * g_variant_get_size:
814+ * @value: a #GVariant instance
815+ *
816+ * Determines the number of bytes that would be required to store @value
817+ * with g_variant_store().
818+ *
819+ * If @value has a fixed-sized type then this function always returned
820+ * that fixed size.
821+ *
822+ * In the case that @value is already in serialised form or the size has
823+ * already been calculated (ie: this function has been called before)
824+ * then this function is O(1). Otherwise, the size is calculated, an
825+ * operation which is approximately O(n) in the number of values
826+ * involved.
827+ *
828+ * Returns: the serialised size of @value
829+ *
830+ * Since: 2.24
831+ **/
832+gsize
833+g_variant_get_size (GVariant *value)
834+{
835+ g_variant_lock (value);
836+ g_variant_ensure_size (value);
837+ g_variant_unlock (value);
838+
839+ return value->size;
840+}
841+
842+/**
843+ * g_variant_get_data:
844+ * @value: a #GVariant instance
845+ *
846+ * Returns a pointer to the serialised form of a #GVariant instance.
847+ * The returned data may not be in fully-normalised form if read from an
848+ * untrusted source. The returned data must not be freed; it remains
849+ * valid for as long as @value exists.
850+ *
851+ * If @value is a fixed-sized value that was deserialised from a
852+ * corrupted serialised container then %NULL may be returned. In this
853+ * case, the proper thing to do is typically to use the appropriate
854+ * number of nul bytes in place of @value. If @value is not fixed-sized
855+ * then %NULL is never returned.
856+ *
857+ * In the case that @value is already in serialised form, this function
858+ * is O(1). If the value is not already in serialised form,
859+ * serialisation occurs implicitly and is approximately O(n) in the size
860+ * of the result.
861+ *
862+ * To deserialise the data returned by this function, in addition to the
863+ * serialised data, you must know the type of the #GVariant, and (if the
864+ * machine might be different) the endianness of the machine that stored
865+ * it. As a result, file formats or network messages that incorporate
866+ * serialised #GVariant<!---->s must include this information either
867+ * implicitly (for instance "the file always contains a
868+ * %G_VARIANT_TYPE_VARIANT and it is always in little-endian order") or
869+ * explicitly (by storing the type and/or endianness in addition to the
870+ * serialised data).
871+ *
872+ * Returns: (transfer none): the serialised form of @value, or %NULL
873+ *
874+ * Since: 2.24
875+ **/
876+gconstpointer
877+g_variant_get_data (GVariant *value)
878+{
879+ g_variant_lock (value);
880+ g_variant_ensure_serialised (value);
881+ g_variant_unlock (value);
882+
883+ return value->contents.serialised.data;
884+}
885+
886+/**
887+ * g_variant_get_data_as_bytes:
888+ * @value: a #GVariant
889+ *
890+ * Returns a pointer to the serialised form of a #GVariant instance.
891+ * The semantics of this function are exactly the same as
892+ * g_variant_get_data(), except that the returned #GBytes holds
893+ * a reference to the variant data.
894+ *
895+ * Returns: (transfer full): A new #GBytes representing the variant data
896+ *
897+ * Since: 2.36
898+ */
899+GBytes *
900+g_variant_get_data_as_bytes (GVariant *value)
901+{
902+ g_variant_lock (value);
903+ g_variant_ensure_serialised (value);
904+ g_variant_unlock (value);
905+
906+ return g_bytes_ref (value->contents.serialised.bytes);
907+}
908+
909+
910+/**
911+ * g_variant_n_children:
912+ * @value: a container #GVariant
913+ *
914+ * Determines the number of children in a container #GVariant instance.
915+ * This includes variants, maybes, arrays, tuples and dictionary
916+ * entries. It is an error to call this function on any other type of
917+ * #GVariant.
918+ *
919+ * For variants, the return value is always 1. For values with maybe
920+ * types, it is always zero or one. For arrays, it is the length of the
921+ * array. For tuples it is the number of tuple items (which depends
922+ * only on the type). For dictionary entries, it is always 2
923+ *
924+ * This function is O(1).
925+ *
926+ * Returns: the number of children in the container
927+ *
928+ * Since: 2.24
929+ **/
930+gsize
931+g_variant_n_children (GVariant *value)
932+{
933+ gsize n_children;
934+
935+ g_variant_lock (value);
936+
937+ if (value->state & STATE_SERIALISED)
938+ {
939+ GVariantSerialised serialised = {
940+ value->type_info,
941+ (gpointer) value->contents.serialised.data,
942+ value->size
943+ };
944+
945+ n_children = g_variant_serialised_n_children (serialised);
946+ }
947+ else
948+ n_children = value->contents.tree.n_children;
949+
950+ g_variant_unlock (value);
951+
952+ return n_children;
953+}
954+
955+/**
956+ * g_variant_get_child_value:
957+ * @value: a container #GVariant
958+ * @index_: the index of the child to fetch
959+ *
960+ * Reads a child item out of a container #GVariant instance. This
961+ * includes variants, maybes, arrays, tuples and dictionary
962+ * entries. It is an error to call this function on any other type of
963+ * #GVariant.
964+ *
965+ * It is an error if @index_ is greater than the number of child items
966+ * in the container. See g_variant_n_children().
967+ *
968+ * The returned value is never floating. You should free it with
969+ * g_variant_unref() when you're done with it.
970+ *
971+ * This function is O(1).
972+ *
973+ * Returns: (transfer full): the child at the specified index
974+ *
975+ * Since: 2.24
976+ **/
977+GVariant *
978+g_variant_get_child_value (GVariant *value,
979+ gsize index_)
980+{
981+ g_return_val_if_fail (index_ < g_variant_n_children (value), NULL);
982+
983+ if (~g_atomic_int_get (&value->state) & STATE_SERIALISED)
984+ {
985+ g_variant_lock (value);
986+
987+ if (~value->state & STATE_SERIALISED)
988+ {
989+ GVariant *child;
990+
991+ child = g_variant_ref (value->contents.tree.children[index_]);
992+ g_variant_unlock (value);
993+
994+ return child;
995+ }
996+
997+ g_variant_unlock (value);
998+ }
999+
1000+ {
1001+ GVariantSerialised serialised = {
1002+ value->type_info,
1003+ (gpointer) value->contents.serialised.data,
1004+ value->size
1005+ };
1006+ GVariantSerialised s_child;
1007+ GVariant *child;
1008+
1009+ /* get the serialiser to extract the serialised data for the child
1010+ * from the serialised data for the container
1011+ */
1012+ s_child = g_variant_serialised_get_child (serialised, index_);
1013+
1014+ /* create a new serialised instance out of it */
1015+ child = g_slice_new (GVariant);
1016+ child->type_info = s_child.type_info;
1017+ child->state = (value->state & STATE_TRUSTED) |
1018+ STATE_SERIALISED;
1019+ child->size = s_child.size;
1020+ child->ref_count = 1;
1021+ child->contents.serialised.bytes =
1022+ g_bytes_ref (value->contents.serialised.bytes);
1023+ child->contents.serialised.data = s_child.data;
1024+
1025+ return child;
1026+ }
1027+}
1028+
1029+/**
1030+ * g_variant_store:
1031+ * @value: the #GVariant to store
1032+ * @data: the location to store the serialised data at
1033+ *
1034+ * Stores the serialised form of @value at @data. @data should be
1035+ * large enough. See g_variant_get_size().
1036+ *
1037+ * The stored data is in machine native byte order but may not be in
1038+ * fully-normalised form if read from an untrusted source. See
1039+ * g_variant_get_normal_form() for a solution.
1040+ *
1041+ * As with g_variant_get_data(), to be able to deserialise the
1042+ * serialised variant successfully, its type and (if the destination
1043+ * machine might be different) its endianness must also be available.
1044+ *
1045+ * This function is approximately O(n) in the size of @data.
1046+ *
1047+ * Since: 2.24
1048+ **/
1049+void
1050+g_variant_store (GVariant *value,
1051+ gpointer data)
1052+{
1053+ g_variant_lock (value);
1054+
1055+ if (value->state & STATE_SERIALISED)
1056+ {
1057+ if (value->contents.serialised.data != NULL)
1058+ memcpy (data, value->contents.serialised.data, value->size);
1059+ else
1060+ memset (data, 0, value->size);
1061+ }
1062+ else
1063+ g_variant_serialise (value, data);
1064+
1065+ g_variant_unlock (value);
1066+}
1067+
1068+/**
1069+ * g_variant_is_normal_form:
1070+ * @value: a #GVariant instance
1071+ *
1072+ * Checks if @value is in normal form.
1073+ *
1074+ * The main reason to do this is to detect if a given chunk of
1075+ * serialised data is in normal form: load the data into a #GVariant
1076+ * using g_variant_new_from_data() and then use this function to
1077+ * check.
1078+ *
1079+ * If @value is found to be in normal form then it will be marked as
1080+ * being trusted. If the value was already marked as being trusted then
1081+ * this function will immediately return %TRUE.
1082+ *
1083+ * Returns: %TRUE if @value is in normal form
1084+ *
1085+ * Since: 2.24
1086+ **/
1087+gboolean
1088+g_variant_is_normal_form (GVariant *value)
1089+{
1090+ if (value->state & STATE_TRUSTED)
1091+ return TRUE;
1092+
1093+ g_variant_lock (value);
1094+
1095+ if (value->state & STATE_SERIALISED)
1096+ {
1097+ GVariantSerialised serialised = {
1098+ value->type_info,
1099+ (gpointer) value->contents.serialised.data,
1100+ value->size
1101+ };
1102+
1103+ if (g_variant_serialised_is_normal (serialised))
1104+ value->state |= STATE_TRUSTED;
1105+ }
1106+ else
1107+ {
1108+ gboolean normal = TRUE;
1109+ gsize i;
1110+
1111+ for (i = 0; i < value->contents.tree.n_children; i++)
1112+ normal &= g_variant_is_normal_form (value->contents.tree.children[i]);
1113+
1114+ if (normal)
1115+ value->state |= STATE_TRUSTED;
1116+ }
1117+
1118+ g_variant_unlock (value);
1119+
1120+ return (value->state & STATE_TRUSTED) != 0;
1121+}
1122
1123=== added directory '.pc/g-variant-get-data-as-bytes.patch/glib/tests'
1124=== added file '.pc/g-variant-get-data-as-bytes.patch/glib/tests/gvariant.c'
1125--- .pc/g-variant-get-data-as-bytes.patch/glib/tests/gvariant.c 1970-01-01 00:00:00 +0000
1126+++ .pc/g-variant-get-data-as-bytes.patch/glib/tests/gvariant.c 2013-05-03 17:57:29 +0000
1127@@ -0,0 +1,4339 @@
1128+/*
1129+ * Copyright © 2010 Codethink Limited
1130+ *
1131+ * This library is free software; you can redistribute it and/or
1132+ * modify it under the terms of the GNU Lesser General Public
1133+ * License as published by the Free Software Foundation; either
1134+ * version 2 of the licence, or (at your option) any later version.
1135+ *
1136+ * See the included COPYING file for more information.
1137+ *
1138+ * Author: Ryan Lortie <desrt@desrt.ca>
1139+ */
1140+
1141+#include "config.h"
1142+
1143+#include <glib/gvariant-internal.h>
1144+#include <string.h>
1145+#include <stdlib.h>
1146+#include <glib.h>
1147+
1148+#define BASIC "bynqiuxthdsog?"
1149+#define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
1150+
1151+#define INVALIDS "cefjklpwz&@^$"
1152+#define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
1153+
1154+/* see comment in gvariant-serialiser.c about this madness.
1155+ *
1156+ * we use this to get testing of non-strictly-aligned GVariant instances
1157+ * on machines that can tolerate it. it is necessary to support this
1158+ * because some systems have malloc() that returns non-8-aligned
1159+ * pointers. it is necessary to have special support in the tests
1160+ * because on most machines malloc() is 8-aligned.
1161+ */
1162+#define ALIGN_BITS (sizeof (struct { char a; union { \
1163+ guint64 x; void *y; gdouble z; } b; }) - 9)
1164+
1165+static gboolean
1166+randomly (gdouble prob)
1167+{
1168+ return g_test_rand_double_range (0, 1) < prob;
1169+}
1170+
1171+/* corecursion */
1172+static GVariantType *
1173+append_tuple_type_string (GString *, GString *, gboolean, gint);
1174+
1175+/* append a random GVariantType to a GString
1176+ * append a description of the type to another GString
1177+ * return what the type is
1178+ */
1179+static GVariantType *
1180+append_type_string (GString *string,
1181+ GString *description,
1182+ gboolean definite,
1183+ gint depth)
1184+{
1185+ if (!depth-- || randomly (0.3))
1186+ {
1187+ gchar b = BASIC[g_test_rand_int_range (0, N_BASIC - definite)];
1188+ g_string_append_c (string, b);
1189+ g_string_append_c (description, b);
1190+
1191+ switch (b)
1192+ {
1193+ case 'b':
1194+ return g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
1195+ case 'y':
1196+ return g_variant_type_copy (G_VARIANT_TYPE_BYTE);
1197+ case 'n':
1198+ return g_variant_type_copy (G_VARIANT_TYPE_INT16);
1199+ case 'q':
1200+ return g_variant_type_copy (G_VARIANT_TYPE_UINT16);
1201+ case 'i':
1202+ return g_variant_type_copy (G_VARIANT_TYPE_INT32);
1203+ case 'u':
1204+ return g_variant_type_copy (G_VARIANT_TYPE_UINT32);
1205+ case 'x':
1206+ return g_variant_type_copy (G_VARIANT_TYPE_INT64);
1207+ case 't':
1208+ return g_variant_type_copy (G_VARIANT_TYPE_UINT64);
1209+ case 'h':
1210+ return g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
1211+ case 'd':
1212+ return g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
1213+ case 's':
1214+ return g_variant_type_copy (G_VARIANT_TYPE_STRING);
1215+ case 'o':
1216+ return g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
1217+ case 'g':
1218+ return g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
1219+ case '?':
1220+ return g_variant_type_copy (G_VARIANT_TYPE_BASIC);
1221+ default:
1222+ g_assert_not_reached ();
1223+ }
1224+ }
1225+ else
1226+ {
1227+ GVariantType *result;
1228+
1229+ switch (g_test_rand_int_range (0, definite ? 5 : 7))
1230+ {
1231+ case 0:
1232+ {
1233+ GVariantType *element;
1234+
1235+ g_string_append_c (string, 'a');
1236+ g_string_append (description, "a of ");
1237+ element = append_type_string (string, description,
1238+ definite, depth);
1239+ result = g_variant_type_new_array (element);
1240+ g_variant_type_free (element);
1241+ }
1242+
1243+ g_assert (g_variant_type_is_array (result));
1244+ break;
1245+
1246+ case 1:
1247+ {
1248+ GVariantType *element;
1249+
1250+ g_string_append_c (string, 'm');
1251+ g_string_append (description, "m of ");
1252+ element = append_type_string (string, description,
1253+ definite, depth);
1254+ result = g_variant_type_new_maybe (element);
1255+ g_variant_type_free (element);
1256+ }
1257+
1258+ g_assert (g_variant_type_is_maybe (result));
1259+ break;
1260+
1261+ case 2:
1262+ result = append_tuple_type_string (string, description,
1263+ definite, depth);
1264+
1265+ g_assert (g_variant_type_is_tuple (result));
1266+ break;
1267+
1268+ case 3:
1269+ {
1270+ GVariantType *key, *value;
1271+
1272+ g_string_append_c (string, '{');
1273+ g_string_append (description, "e of [");
1274+ key = append_type_string (string, description, definite, 0);
1275+ g_string_append (description, ", ");
1276+ value = append_type_string (string, description, definite, depth);
1277+ g_string_append_c (description, ']');
1278+ g_string_append_c (string, '}');
1279+ result = g_variant_type_new_dict_entry (key, value);
1280+ g_variant_type_free (key);
1281+ g_variant_type_free (value);
1282+ }
1283+
1284+ g_assert (g_variant_type_is_dict_entry (result));
1285+ break;
1286+
1287+ case 4:
1288+ g_string_append_c (string, 'v');
1289+ g_string_append_c (description, 'V');
1290+ result = g_variant_type_copy (G_VARIANT_TYPE_VARIANT);
1291+ g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_VARIANT));
1292+ break;
1293+
1294+ case 5:
1295+ g_string_append_c (string, '*');
1296+ g_string_append_c (description, 'S');
1297+ result = g_variant_type_copy (G_VARIANT_TYPE_ANY);
1298+ g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_ANY));
1299+ break;
1300+
1301+ case 6:
1302+ g_string_append_c (string, 'r');
1303+ g_string_append_c (description, 'R');
1304+ result = g_variant_type_copy (G_VARIANT_TYPE_TUPLE);
1305+ g_assert (g_variant_type_is_tuple (result));
1306+ break;
1307+
1308+ default:
1309+ g_assert_not_reached ();
1310+ }
1311+
1312+ return result;
1313+ }
1314+}
1315+
1316+static GVariantType *
1317+append_tuple_type_string (GString *string,
1318+ GString *description,
1319+ gboolean definite,
1320+ gint depth)
1321+{
1322+ GVariantType *result, *other_result;
1323+ GVariantType **types;
1324+ gint size;
1325+ gint i;
1326+
1327+ g_string_append_c (string, '(');
1328+ g_string_append (description, "t of [");
1329+
1330+ size = g_test_rand_int_range (0, 20);
1331+ types = g_new (GVariantType *, size + 1);
1332+
1333+ for (i = 0; i < size; i++)
1334+ {
1335+ types[i] = append_type_string (string, description, definite, depth);
1336+
1337+ if (i < size - 1)
1338+ g_string_append (description, ", ");
1339+ }
1340+
1341+ types[i] = NULL;
1342+
1343+ g_string_append_c (description, ']');
1344+ g_string_append_c (string, ')');
1345+
1346+ result = g_variant_type_new_tuple ((gpointer) types, size);
1347+ other_result = g_variant_type_new_tuple ((gpointer) types, -1);
1348+ g_assert (g_variant_type_equal (result, other_result));
1349+ g_variant_type_free (other_result);
1350+ for (i = 0; i < size; i++)
1351+ g_variant_type_free (types[i]);
1352+ g_free (types);
1353+
1354+ return result;
1355+}
1356+
1357+/* given a valid type string, make it invalid */
1358+static gchar *
1359+invalid_mutation (const gchar *type_string)
1360+{
1361+ gboolean have_parens, have_braces;
1362+
1363+ /* it's valid, so '(' implies ')' and same for '{' and '}' */
1364+ have_parens = strchr (type_string, '(') != NULL;
1365+ have_braces = strchr (type_string, '{') != NULL;
1366+
1367+ if (have_parens && have_braces && randomly (0.3))
1368+ {
1369+ /* swap a paren and a brace */
1370+ gchar *pp, *bp;
1371+ gint np, nb;
1372+ gchar p, b;
1373+ gchar *new;
1374+
1375+ new = g_strdup (type_string);
1376+
1377+ if (randomly (0.5))
1378+ p = '(', b = '{';
1379+ else
1380+ p = ')', b = '}';
1381+
1382+ np = nb = 0;
1383+ pp = bp = new - 1;
1384+
1385+ /* count number of parens/braces */
1386+ while ((pp = strchr (pp + 1, p))) np++;
1387+ while ((bp = strchr (bp + 1, b))) nb++;
1388+
1389+ /* randomly pick one of each */
1390+ np = g_test_rand_int_range (0, np) + 1;
1391+ nb = g_test_rand_int_range (0, nb) + 1;
1392+
1393+ /* find it */
1394+ pp = bp = new - 1;
1395+ while (np--) pp = strchr (pp + 1, p);
1396+ while (nb--) bp = strchr (bp + 1, b);
1397+
1398+ /* swap */
1399+ g_assert (*bp == b && *pp == p);
1400+ *bp = p;
1401+ *pp = b;
1402+
1403+ return new;
1404+ }
1405+
1406+ if ((have_parens || have_braces) && randomly (0.3))
1407+ {
1408+ /* drop a paren/brace */
1409+ gchar *new;
1410+ gchar *pp;
1411+ gint np;
1412+ gchar p;
1413+
1414+ if (have_parens)
1415+ if (randomly (0.5)) p = '('; else p = ')';
1416+ else
1417+ if (randomly (0.5)) p = '{'; else p = '}';
1418+
1419+ new = g_strdup (type_string);
1420+
1421+ np = 0;
1422+ pp = new - 1;
1423+ while ((pp = strchr (pp + 1, p))) np++;
1424+ np = g_test_rand_int_range (0, np) + 1;
1425+ pp = new - 1;
1426+ while (np--) pp = strchr (pp + 1, p);
1427+ g_assert (*pp == p);
1428+
1429+ while (*pp)
1430+ {
1431+ *pp = *(pp + 1);
1432+ pp++;
1433+ }
1434+
1435+ return new;
1436+ }
1437+
1438+ /* else, perform a random mutation at a random point */
1439+ {
1440+ gint length, n;
1441+ gchar *new;
1442+ gchar p;
1443+
1444+ if (randomly (0.3))
1445+ {
1446+ /* insert a paren/brace */
1447+ if (randomly (0.5))
1448+ if (randomly (0.5)) p = '('; else p = ')';
1449+ else
1450+ if (randomly (0.5)) p = '{'; else p = '}';
1451+ }
1452+ else if (randomly (0.5))
1453+ {
1454+ /* insert junk */
1455+ p = INVALIDS[g_test_rand_int_range (0, N_INVALIDS)];
1456+ }
1457+ else
1458+ {
1459+ /* truncate */
1460+ p = '\0';
1461+ }
1462+
1463+
1464+ length = strlen (type_string);
1465+ new = g_malloc (length + 2);
1466+ n = g_test_rand_int_range (0, length);
1467+ memcpy (new, type_string, n);
1468+ new[n] = p;
1469+ memcpy (new + n + 1, type_string + n, length - n);
1470+ new[length + 1] = '\0';
1471+
1472+ return new;
1473+ }
1474+}
1475+
1476+/* describe a type using the same language as is generated
1477+ * while generating the type with append_type_string
1478+ */
1479+static gchar *
1480+describe_type (const GVariantType *type)
1481+{
1482+ gchar *result;
1483+
1484+ if (g_variant_type_is_container (type))
1485+ {
1486+ g_assert (!g_variant_type_is_basic (type));
1487+
1488+ if (g_variant_type_is_array (type))
1489+ {
1490+ gchar *subtype = describe_type (g_variant_type_element (type));
1491+ result = g_strdup_printf ("a of %s", subtype);
1492+ g_free (subtype);
1493+ }
1494+ else if (g_variant_type_is_maybe (type))
1495+ {
1496+ gchar *subtype = describe_type (g_variant_type_element (type));
1497+ result = g_strdup_printf ("m of %s", subtype);
1498+ g_free (subtype);
1499+ }
1500+ else if (g_variant_type_is_tuple (type))
1501+ {
1502+ if (!g_variant_type_equal (type, G_VARIANT_TYPE_TUPLE))
1503+ {
1504+ const GVariantType *sub;
1505+ GString *string;
1506+ gint length;
1507+ gint i;
1508+
1509+ string = g_string_new ("t of [");
1510+
1511+ length = g_variant_type_n_items (type);
1512+ sub = g_variant_type_first (type);
1513+ for (i = 0; i < length; i++)
1514+ {
1515+ gchar *subtype = describe_type (sub);
1516+ g_string_append (string, subtype);
1517+ g_free (subtype);
1518+
1519+ if ((sub = g_variant_type_next (sub)))
1520+ g_string_append (string, ", ");
1521+ }
1522+ g_assert (sub == NULL);
1523+ g_string_append_c (string, ']');
1524+
1525+ result = g_string_free (string, FALSE);
1526+ }
1527+ else
1528+ result = g_strdup ("R");
1529+ }
1530+ else if (g_variant_type_is_dict_entry (type))
1531+ {
1532+ gchar *key, *value, *key2, *value2;
1533+
1534+ key = describe_type (g_variant_type_key (type));
1535+ value = describe_type (g_variant_type_value (type));
1536+ key2 = describe_type (g_variant_type_first (type));
1537+ value2 = describe_type (
1538+ g_variant_type_next (g_variant_type_first (type)));
1539+ g_assert (g_variant_type_next (g_variant_type_next (
1540+ g_variant_type_first (type))) == NULL);
1541+ g_assert_cmpstr (key, ==, key2);
1542+ g_assert_cmpstr (value, ==, value2);
1543+ result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
1544+ g_free (key2);
1545+ g_free (value2);
1546+ g_free (key);
1547+ g_free (value);
1548+ }
1549+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
1550+ {
1551+ result = g_strdup ("V");
1552+ }
1553+ else
1554+ g_assert_not_reached ();
1555+ }
1556+ else
1557+ {
1558+ if (g_variant_type_is_definite (type))
1559+ {
1560+ g_assert (g_variant_type_is_basic (type));
1561+
1562+ if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1563+ result = g_strdup ("b");
1564+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1565+ result = g_strdup ("y");
1566+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
1567+ result = g_strdup ("n");
1568+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
1569+ result = g_strdup ("q");
1570+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
1571+ result = g_strdup ("i");
1572+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
1573+ result = g_strdup ("u");
1574+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
1575+ result = g_strdup ("x");
1576+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
1577+ result = g_strdup ("t");
1578+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
1579+ result = g_strdup ("h");
1580+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1581+ result = g_strdup ("d");
1582+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1583+ result = g_strdup ("s");
1584+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1585+ result = g_strdup ("o");
1586+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1587+ result = g_strdup ("g");
1588+ else
1589+ g_assert_not_reached ();
1590+ }
1591+ else
1592+ {
1593+ if (g_variant_type_equal (type, G_VARIANT_TYPE_ANY))
1594+ {
1595+ result = g_strdup ("S");
1596+ }
1597+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
1598+ {
1599+ result = g_strdup ("?");
1600+ }
1601+ else
1602+ g_assert_not_reached ();
1603+ }
1604+ }
1605+
1606+ return result;
1607+}
1608+
1609+/* given a type string, replace one of the indefinite type characters in
1610+ * it with a matching type (possibly the same type).
1611+ */
1612+static gchar *
1613+generate_subtype (const gchar *type_string)
1614+{
1615+ GVariantType *replacement;
1616+ GString *result, *junk;
1617+ gint length, n = 0, l;
1618+
1619+ result = g_string_new (NULL);
1620+ junk = g_string_new (NULL);
1621+
1622+ /* count the number of indefinite type characters */
1623+ for (length = 0; type_string[length]; length++)
1624+ n += type_string[length] == 'r' ||
1625+ type_string[length] == '?' ||
1626+ type_string[length] == '*';
1627+ /* length now is strlen (type_string) */
1628+
1629+ /* pick one at random to replace */
1630+ n = g_test_rand_int_range (0, n) + 1;
1631+
1632+ /* find it */
1633+ l = -1;
1634+ while (n--) l += strcspn (type_string + l + 1, "r?*") + 1;
1635+ g_assert (type_string[l] == 'r' ||
1636+ type_string[l] == '?' ||
1637+ type_string[l] == '*');
1638+
1639+ /* store up to that point in a GString */
1640+ g_string_append_len (result, type_string, l);
1641+
1642+ /* then store the replacement in the GString */
1643+ if (type_string[l] == 'r')
1644+ replacement = append_tuple_type_string (result, junk, FALSE, 3);
1645+
1646+ else if (type_string[l] == '?')
1647+ replacement = append_type_string (result, junk, FALSE, 0);
1648+
1649+ else if (type_string[l] == '*')
1650+ replacement = append_type_string (result, junk, FALSE, 3);
1651+
1652+ else
1653+ g_assert_not_reached ();
1654+
1655+ /* ensure the replacement has the proper type */
1656+ g_assert (g_variant_type_is_subtype_of (replacement,
1657+ (gpointer) &type_string[l]));
1658+
1659+ /* store the rest from the original type string */
1660+ g_string_append (result, type_string + l + 1);
1661+
1662+ g_variant_type_free (replacement);
1663+ g_string_free (junk, TRUE);
1664+
1665+ return g_string_free (result, FALSE);
1666+}
1667+
1668+struct typestack
1669+{
1670+ const GVariantType *type;
1671+ struct typestack *parent;
1672+};
1673+
1674+/* given an indefinite type string, replace one of the indefinite
1675+ * characters in it with a matching type and ensure that the result is a
1676+ * subtype of the original. repeat.
1677+ */
1678+static void
1679+subtype_check (const gchar *type_string,
1680+ struct typestack *parent_ts)
1681+{
1682+ struct typestack ts, *node;
1683+ gchar *subtype;
1684+ gint depth = 0;
1685+
1686+ subtype = generate_subtype (type_string);
1687+
1688+ ts.type = G_VARIANT_TYPE (subtype);
1689+ ts.parent = parent_ts;
1690+
1691+ for (node = &ts; node; node = node->parent)
1692+ {
1693+ /* this type should be a subtype of each parent type */
1694+ g_assert (g_variant_type_is_subtype_of (ts.type, node->type));
1695+
1696+ /* it should only be a supertype when it is exactly equal */
1697+ g_assert (g_variant_type_is_subtype_of (node->type, ts.type) ==
1698+ g_variant_type_equal (ts.type, node->type));
1699+
1700+ depth++;
1701+ }
1702+
1703+ if (!g_variant_type_is_definite (ts.type) && depth < 5)
1704+ {
1705+ /* the type is still indefinite and we haven't repeated too many
1706+ * times. go once more.
1707+ */
1708+
1709+ subtype_check (subtype, &ts);
1710+ }
1711+
1712+ g_free (subtype);
1713+}
1714+
1715+static void
1716+test_gvarianttype (void)
1717+{
1718+ gint i;
1719+
1720+ for (i = 0; i < 2000; i++)
1721+ {
1722+ GString *type_string, *description;
1723+ GVariantType *type, *other_type;
1724+ const GVariantType *ctype;
1725+ gchar *invalid;
1726+ gchar *desc;
1727+
1728+ type_string = g_string_new (NULL);
1729+ description = g_string_new (NULL);
1730+
1731+ /* generate a random type, its type string and a description
1732+ *
1733+ * exercises type constructor functions and g_variant_type_copy()
1734+ */
1735+ type = append_type_string (type_string, description, FALSE, 6);
1736+
1737+ /* convert the type string to a type and ensure that it is equal
1738+ * to the one produced with the type constructor routines
1739+ */
1740+ ctype = G_VARIANT_TYPE (type_string->str);
1741+ g_assert (g_variant_type_equal (ctype, type));
1742+ g_assert (g_variant_type_hash (ctype) == g_variant_type_hash (type));
1743+ g_assert (g_variant_type_is_subtype_of (ctype, type));
1744+ g_assert (g_variant_type_is_subtype_of (type, ctype));
1745+
1746+ /* check if the type is indefinite */
1747+ if (!g_variant_type_is_definite (type))
1748+ {
1749+ struct typestack ts = { type, NULL };
1750+
1751+ /* if it is indefinite, then replace one of the indefinite
1752+ * characters with a matching type and ensure that the result
1753+ * is a subtype of the original type. repeat.
1754+ */
1755+ subtype_check (type_string->str, &ts);
1756+ }
1757+ else
1758+ /* ensure that no indefinite characters appear */
1759+ g_assert (strcspn (type_string->str, "r?*") == type_string->len);
1760+
1761+
1762+ /* describe the type.
1763+ *
1764+ * exercises the type iterator interface
1765+ */
1766+ desc = describe_type (type);
1767+
1768+ /* make sure the description matches */
1769+ g_assert_cmpstr (desc, ==, description->str);
1770+ g_free (desc);
1771+
1772+ /* make an invalid mutation to the type and make sure the type
1773+ * validation routines catch it */
1774+ invalid = invalid_mutation (type_string->str);
1775+ g_assert (g_variant_type_string_is_valid (type_string->str));
1776+ g_assert (!g_variant_type_string_is_valid (invalid));
1777+ g_free (invalid);
1778+
1779+ /* concatenate another type to the type string and ensure that
1780+ * the result is recognised as being invalid
1781+ */
1782+ other_type = append_type_string (type_string, description, FALSE, 2);
1783+
1784+ g_string_free (description, TRUE);
1785+ g_string_free (type_string, TRUE);
1786+ g_variant_type_free (other_type);
1787+ g_variant_type_free (type);
1788+ }
1789+}
1790+
1791+#define ALIGNED(x, y) (((x + (y - 1)) / y) * y)
1792+
1793+/* do our own calculation of the fixed_size and alignment of a type
1794+ * using a simple algorithm to make sure the "fancy" one in the
1795+ * implementation is correct.
1796+ */
1797+static void
1798+calculate_type_info (const GVariantType *type,
1799+ gsize *fixed_size,
1800+ guint *alignment)
1801+{
1802+ if (g_variant_type_is_array (type) ||
1803+ g_variant_type_is_maybe (type))
1804+ {
1805+ calculate_type_info (g_variant_type_element (type), NULL, alignment);
1806+
1807+ if (fixed_size)
1808+ *fixed_size = 0;
1809+ }
1810+ else if (g_variant_type_is_tuple (type) ||
1811+ g_variant_type_is_dict_entry (type))
1812+ {
1813+ if (g_variant_type_n_items (type))
1814+ {
1815+ const GVariantType *sub;
1816+ gboolean variable;
1817+ gsize size;
1818+ guint al;
1819+
1820+ variable = FALSE;
1821+ size = 0;
1822+ al = 0;
1823+
1824+ sub = g_variant_type_first (type);
1825+ do
1826+ {
1827+ gsize this_fs;
1828+ guint this_al;
1829+
1830+ calculate_type_info (sub, &this_fs, &this_al);
1831+
1832+ al = MAX (al, this_al);
1833+
1834+ if (!this_fs)
1835+ {
1836+ variable = TRUE;
1837+ size = 0;
1838+ }
1839+
1840+ if (!variable)
1841+ {
1842+ size = ALIGNED (size, this_al);
1843+ size += this_fs;
1844+ }
1845+ }
1846+ while ((sub = g_variant_type_next (sub)));
1847+
1848+ size = ALIGNED (size, al);
1849+
1850+ if (alignment)
1851+ *alignment = al;
1852+
1853+ if (fixed_size)
1854+ *fixed_size = size;
1855+ }
1856+ else
1857+ {
1858+ if (fixed_size)
1859+ *fixed_size = 1;
1860+
1861+ if (alignment)
1862+ *alignment = 1;
1863+ }
1864+ }
1865+ else
1866+ {
1867+ gint fs, al;
1868+
1869+ if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN) ||
1870+ g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1871+ {
1872+ al = fs = 1;
1873+ }
1874+
1875+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16) ||
1876+ g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
1877+ {
1878+ al = fs = 2;
1879+ }
1880+
1881+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32) ||
1882+ g_variant_type_equal (type, G_VARIANT_TYPE_UINT32) ||
1883+ g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
1884+ {
1885+ al = fs = 4;
1886+ }
1887+
1888+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64) ||
1889+ g_variant_type_equal (type, G_VARIANT_TYPE_UINT64) ||
1890+ g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1891+ {
1892+ al = fs = 8;
1893+ }
1894+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING) ||
1895+ g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH) ||
1896+ g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1897+ {
1898+ al = 1;
1899+ fs = 0;
1900+ }
1901+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
1902+ {
1903+ al = 8;
1904+ fs = 0;
1905+ }
1906+ else
1907+ g_assert_not_reached ();
1908+
1909+ if (fixed_size)
1910+ *fixed_size = fs;
1911+
1912+ if (alignment)
1913+ *alignment = al;
1914+ }
1915+}
1916+
1917+/* same as the describe_type() function above, but iterates over
1918+ * typeinfo instead of types.
1919+ */
1920+static gchar *
1921+describe_info (GVariantTypeInfo *info)
1922+{
1923+ gchar *result;
1924+
1925+ switch (g_variant_type_info_get_type_char (info))
1926+ {
1927+ case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1928+ {
1929+ gchar *element;
1930+
1931+ element = describe_info (g_variant_type_info_element (info));
1932+ result = g_strdup_printf ("m of %s", element);
1933+ g_free (element);
1934+ }
1935+ break;
1936+
1937+ case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1938+ {
1939+ gchar *element;
1940+
1941+ element = describe_info (g_variant_type_info_element (info));
1942+ result = g_strdup_printf ("a of %s", element);
1943+ g_free (element);
1944+ }
1945+ break;
1946+
1947+ case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1948+ {
1949+ const gchar *sep = "";
1950+ GString *string;
1951+ gint length;
1952+ gint i;
1953+
1954+ string = g_string_new ("t of [");
1955+ length = g_variant_type_info_n_members (info);
1956+
1957+ for (i = 0; i < length; i++)
1958+ {
1959+ const GVariantMemberInfo *minfo;
1960+ gchar *subtype;
1961+
1962+ g_string_append (string, sep);
1963+ sep = ", ";
1964+
1965+ minfo = g_variant_type_info_member_info (info, i);
1966+ subtype = describe_info (minfo->type_info);
1967+ g_string_append (string, subtype);
1968+ g_free (subtype);
1969+ }
1970+
1971+ g_string_append_c (string, ']');
1972+
1973+ result = g_string_free (string, FALSE);
1974+ }
1975+ break;
1976+
1977+ case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1978+ {
1979+ const GVariantMemberInfo *keyinfo, *valueinfo;
1980+ gchar *key, *value;
1981+
1982+ g_assert_cmpint (g_variant_type_info_n_members (info), ==, 2);
1983+ keyinfo = g_variant_type_info_member_info (info, 0);
1984+ valueinfo = g_variant_type_info_member_info (info, 1);
1985+ key = describe_info (keyinfo->type_info);
1986+ value = describe_info (valueinfo->type_info);
1987+ result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
1988+ g_free (key);
1989+ g_free (value);
1990+ }
1991+ break;
1992+
1993+ case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1994+ result = g_strdup ("V");
1995+ break;
1996+
1997+ default:
1998+ result = g_strdup (g_variant_type_info_get_type_string (info));
1999+ g_assert_cmpint (strlen (result), ==, 1);
2000+ break;
2001+ }
2002+
2003+ return result;
2004+}
2005+
2006+/* check that the O(1) method of calculating offsets meshes with the
2007+ * results of simple iteration.
2008+ */
2009+static void
2010+check_offsets (GVariantTypeInfo *info,
2011+ const GVariantType *type)
2012+{
2013+ gint flavour;
2014+ gint length;
2015+
2016+ length = g_variant_type_info_n_members (info);
2017+ g_assert_cmpint (length, ==, g_variant_type_n_items (type));
2018+
2019+ /* the 'flavour' is the low order bits of the ending point of
2020+ * variable-size items in the tuple. this lets us test that the type
2021+ * info is correct for various starting alignments.
2022+ */
2023+ for (flavour = 0; flavour < 8; flavour++)
2024+ {
2025+ const GVariantType *subtype;
2026+ gsize last_offset_index;
2027+ gsize last_offset;
2028+ gsize position;
2029+ gint i;
2030+
2031+ subtype = g_variant_type_first (type);
2032+ last_offset_index = -1;
2033+ last_offset = 0;
2034+ position = 0;
2035+
2036+ /* go through the tuple, keeping track of our position */
2037+ for (i = 0; i < length; i++)
2038+ {
2039+ gsize fixed_size;
2040+ guint alignment;
2041+
2042+ calculate_type_info (subtype, &fixed_size, &alignment);
2043+
2044+ position = ALIGNED (position, alignment);
2045+
2046+ /* compare our current aligned position (ie: the start of this
2047+ * item) to the start offset that would be calculated if we
2048+ * used the type info
2049+ */
2050+ {
2051+ const GVariantMemberInfo *member;
2052+ gsize start;
2053+
2054+ member = g_variant_type_info_member_info (info, i);
2055+ g_assert_cmpint (member->i, ==, last_offset_index);
2056+
2057+ /* do the calculation using the typeinfo */
2058+ start = last_offset;
2059+ start += member->a;
2060+ start &= member->b;
2061+ start |= member->c;
2062+
2063+ /* did we reach the same spot? */
2064+ g_assert_cmpint (start, ==, position);
2065+ }
2066+
2067+ if (fixed_size)
2068+ {
2069+ /* fixed size. add that size. */
2070+ position += fixed_size;
2071+ }
2072+ else
2073+ {
2074+ /* variable size. do the flavouring. */
2075+ while ((position & 0x7) != flavour)
2076+ position++;
2077+
2078+ /* and store the offset, just like it would be in the
2079+ * serialised data.
2080+ */
2081+ last_offset = position;
2082+ last_offset_index++;
2083+ }
2084+
2085+ /* next type */
2086+ subtype = g_variant_type_next (subtype);
2087+ }
2088+
2089+ /* make sure we used up exactly all the types */
2090+ g_assert (subtype == NULL);
2091+ }
2092+}
2093+
2094+static void
2095+test_gvarianttypeinfo (void)
2096+{
2097+ gint i;
2098+
2099+ for (i = 0; i < 2000; i++)
2100+ {
2101+ GString *type_string, *description;
2102+ gsize fixed_size1, fixed_size2;
2103+ guint alignment1, alignment2;
2104+ GVariantTypeInfo *info;
2105+ GVariantType *type;
2106+ gchar *desc;
2107+
2108+ type_string = g_string_new (NULL);
2109+ description = g_string_new (NULL);
2110+
2111+ /* random type */
2112+ type = append_type_string (type_string, description, TRUE, 6);
2113+
2114+ /* create a typeinfo for it */
2115+ info = g_variant_type_info_get (type);
2116+
2117+ /* make sure the typeinfo has the right type string */
2118+ g_assert_cmpstr (g_variant_type_info_get_type_string (info), ==,
2119+ type_string->str);
2120+
2121+ /* calculate the alignment and fixed size, compare to the
2122+ * typeinfo's calculations
2123+ */
2124+ calculate_type_info (type, &fixed_size1, &alignment1);
2125+ g_variant_type_info_query (info, &alignment2, &fixed_size2);
2126+ g_assert_cmpint (fixed_size1, ==, fixed_size2);
2127+ g_assert_cmpint (alignment1, ==, alignment2 + 1);
2128+
2129+ /* test the iteration functions over typeinfo structures by
2130+ * "describing" the typeinfo and verifying equality.
2131+ */
2132+ desc = describe_info (info);
2133+ g_assert_cmpstr (desc, ==, description->str);
2134+
2135+ /* do extra checks for containers */
2136+ if (g_variant_type_is_array (type) ||
2137+ g_variant_type_is_maybe (type))
2138+ {
2139+ const GVariantType *element;
2140+ gsize efs1, efs2;
2141+ guint ea1, ea2;
2142+
2143+ element = g_variant_type_element (type);
2144+ calculate_type_info (element, &efs1, &ea1);
2145+ g_variant_type_info_query_element (info, &ea2, &efs2);
2146+ g_assert_cmpint (efs1, ==, efs2);
2147+ g_assert_cmpint (ea1, ==, ea2 + 1);
2148+
2149+ g_assert_cmpint (ea1, ==, alignment1);
2150+ g_assert_cmpint (0, ==, fixed_size1);
2151+ }
2152+ else if (g_variant_type_is_tuple (type) ||
2153+ g_variant_type_is_dict_entry (type))
2154+ {
2155+ /* make sure the "magic constants" are working */
2156+ check_offsets (info, type);
2157+ }
2158+
2159+ g_string_free (type_string, TRUE);
2160+ g_string_free (description, TRUE);
2161+ g_variant_type_info_unref (info);
2162+ g_variant_type_free (type);
2163+ g_free (desc);
2164+ }
2165+
2166+ g_variant_type_info_assert_no_infos ();
2167+}
2168+
2169+#define MAX_FIXED_MULTIPLIER 256
2170+#define MAX_INSTANCE_SIZE 1024
2171+#define MAX_ARRAY_CHILDREN 128
2172+#define MAX_TUPLE_CHILDREN 128
2173+
2174+/* this function generates a random type such that all characteristics
2175+ * that are "interesting" to the serialiser are tested.
2176+ *
2177+ * this basically means:
2178+ * - test different alignments
2179+ * - test variable sized items and fixed sized items
2180+ * - test different fixed sizes
2181+ */
2182+static gchar *
2183+random_type_string (void)
2184+{
2185+ const guchar base_types[] = "ynix";
2186+ guchar base_type;
2187+
2188+ base_type = base_types[g_test_rand_int_range (0, 4)];
2189+
2190+ if (g_test_rand_bit ())
2191+ /* construct a fixed-sized type */
2192+ {
2193+ char type_string[MAX_FIXED_MULTIPLIER];
2194+ guint multiplier;
2195+ guint i = 0;
2196+
2197+ multiplier = g_test_rand_int_range (1, sizeof type_string - 1);
2198+
2199+ type_string[i++] = '(';
2200+ while (multiplier--)
2201+ type_string[i++] = base_type;
2202+ type_string[i++] = ')';
2203+
2204+ return g_strndup (type_string, i);
2205+ }
2206+ else
2207+ /* construct a variable-sized type */
2208+ {
2209+ char type_string[2] = { 'a', base_type };
2210+
2211+ return g_strndup (type_string, 2);
2212+ }
2213+}
2214+
2215+typedef struct
2216+{
2217+ GVariantTypeInfo *type_info;
2218+ guint alignment;
2219+ gsize size;
2220+ gboolean is_fixed_sized;
2221+
2222+ guint32 seed;
2223+
2224+#define INSTANCE_MAGIC 1287582829
2225+ guint magic;
2226+} RandomInstance;
2227+
2228+static RandomInstance *
2229+random_instance (GVariantTypeInfo *type_info)
2230+{
2231+ RandomInstance *instance;
2232+
2233+ instance = g_slice_new (RandomInstance);
2234+
2235+ if (type_info == NULL)
2236+ {
2237+ gchar *str = random_type_string ();
2238+ instance->type_info = g_variant_type_info_get (G_VARIANT_TYPE (str));
2239+ g_free (str);
2240+ }
2241+ else
2242+ instance->type_info = g_variant_type_info_ref (type_info);
2243+
2244+ instance->seed = g_test_rand_int ();
2245+
2246+ g_variant_type_info_query (instance->type_info,
2247+ &instance->alignment,
2248+ &instance->size);
2249+
2250+ instance->is_fixed_sized = instance->size != 0;
2251+
2252+ if (!instance->is_fixed_sized)
2253+ instance->size = g_test_rand_int_range (0, MAX_INSTANCE_SIZE);
2254+
2255+ instance->magic = INSTANCE_MAGIC;
2256+
2257+ return instance;
2258+}
2259+
2260+static void
2261+random_instance_free (RandomInstance *instance)
2262+{
2263+ g_variant_type_info_unref (instance->type_info);
2264+ g_slice_free (RandomInstance, instance);
2265+}
2266+
2267+static void
2268+append_instance_size (RandomInstance *instance,
2269+ gsize *offset)
2270+{
2271+ *offset += (-*offset) & instance->alignment;
2272+ *offset += instance->size;
2273+}
2274+
2275+static void
2276+random_instance_write (RandomInstance *instance,
2277+ guchar *buffer)
2278+{
2279+ GRand *rand;
2280+ gint i;
2281+
2282+ g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
2283+
2284+ rand = g_rand_new_with_seed (instance->seed);
2285+ for (i = 0; i < instance->size; i++)
2286+ buffer[i] = g_rand_int (rand);
2287+ g_rand_free (rand);
2288+}
2289+
2290+static void
2291+append_instance_data (RandomInstance *instance,
2292+ guchar **buffer)
2293+{
2294+ while (((gsize) *buffer) & instance->alignment)
2295+ *(*buffer)++ = '\0';
2296+
2297+ random_instance_write (instance, *buffer);
2298+ *buffer += instance->size;
2299+}
2300+
2301+static gboolean
2302+random_instance_assert (RandomInstance *instance,
2303+ guchar *buffer,
2304+ gsize size)
2305+{
2306+ GRand *rand;
2307+ gint i;
2308+
2309+ g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
2310+ g_assert_cmpint (size, ==, instance->size);
2311+
2312+ rand = g_rand_new_with_seed (instance->seed);
2313+ for (i = 0; i < instance->size; i++)
2314+ {
2315+ guchar byte = g_rand_int (rand);
2316+
2317+ g_assert (buffer[i] == byte);
2318+ }
2319+ g_rand_free (rand);
2320+
2321+ return i == instance->size;
2322+}
2323+
2324+static gboolean
2325+random_instance_check (RandomInstance *instance,
2326+ guchar *buffer,
2327+ gsize size)
2328+{
2329+ GRand *rand;
2330+ gint i;
2331+
2332+ g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
2333+
2334+ if (size != instance->size)
2335+ return FALSE;
2336+
2337+ rand = g_rand_new_with_seed (instance->seed);
2338+ for (i = 0; i < instance->size; i++)
2339+ if (buffer[i] != (guchar) g_rand_int (rand))
2340+ break;
2341+ g_rand_free (rand);
2342+
2343+ return i == instance->size;
2344+}
2345+
2346+static void
2347+random_instance_filler (GVariantSerialised *serialised,
2348+ gpointer data)
2349+{
2350+ RandomInstance *instance = data;
2351+
2352+ g_assert (instance->magic == INSTANCE_MAGIC);
2353+
2354+ if (serialised->type_info == NULL)
2355+ serialised->type_info = instance->type_info;
2356+
2357+ if (serialised->size == 0)
2358+ serialised->size = instance->size;
2359+
2360+ g_assert (serialised->type_info == instance->type_info);
2361+ g_assert (serialised->size == instance->size);
2362+
2363+ if (serialised->data)
2364+ random_instance_write (instance, serialised->data);
2365+}
2366+
2367+static gsize
2368+calculate_offset_size (gsize body_size,
2369+ gsize n_offsets)
2370+{
2371+ if (body_size == 0)
2372+ return 0;
2373+
2374+ if (body_size + n_offsets <= G_MAXUINT8)
2375+ return 1;
2376+
2377+ if (body_size + 2 * n_offsets <= G_MAXUINT16)
2378+ return 2;
2379+
2380+ if (body_size + 4 * n_offsets <= G_MAXUINT32)
2381+ return 4;
2382+
2383+ /* the test case won't generate anything bigger */
2384+ g_assert_not_reached ();
2385+}
2386+
2387+static gpointer
2388+flavoured_malloc (gsize size, gsize flavour)
2389+{
2390+ g_assert (flavour < 8);
2391+
2392+ if (size == 0)
2393+ return NULL;
2394+
2395+ return ((gchar *) g_malloc (size + flavour)) + flavour;
2396+}
2397+
2398+static void
2399+flavoured_free (gpointer data,
2400+ gsize flavour)
2401+{
2402+ if (!data)
2403+ return;
2404+ g_free (((gchar *) data) - flavour);
2405+}
2406+
2407+static gpointer
2408+align_malloc (gsize size)
2409+{
2410+ gpointer mem;
2411+
2412+#ifdef HAVE_POSIX_MEMALIGN
2413+ if (posix_memalign (&mem, 8, size))
2414+ g_error ("posix_memalign failed");
2415+#else
2416+ /* NOTE: there may be platforms that lack posix_memalign() and also
2417+ * have malloc() that returns non-8-aligned. if so, we need to try
2418+ * harder here.
2419+ */
2420+ mem = malloc (size);
2421+#endif
2422+
2423+ return mem;
2424+}
2425+
2426+static void
2427+align_free (gpointer mem)
2428+{
2429+ free (mem);
2430+}
2431+
2432+static void
2433+append_offset (guchar **offset_ptr,
2434+ gsize offset,
2435+ guint offset_size)
2436+{
2437+ union
2438+ {
2439+ guchar bytes[sizeof (gsize)];
2440+ gsize integer;
2441+ } tmpvalue;
2442+
2443+ tmpvalue.integer = GSIZE_TO_LE (offset);
2444+ memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
2445+ *offset_ptr += offset_size;
2446+}
2447+
2448+static void
2449+prepend_offset (guchar **offset_ptr,
2450+ gsize offset,
2451+ guint offset_size)
2452+{
2453+ union
2454+ {
2455+ guchar bytes[sizeof (gsize)];
2456+ gsize integer;
2457+ } tmpvalue;
2458+
2459+ *offset_ptr -= offset_size;
2460+ tmpvalue.integer = GSIZE_TO_LE (offset);
2461+ memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
2462+}
2463+
2464+static void
2465+test_maybe (void)
2466+{
2467+ GVariantTypeInfo *type_info;
2468+ RandomInstance *instance;
2469+ gsize needed_size;
2470+ guchar *data;
2471+
2472+ instance = random_instance (NULL);
2473+
2474+ {
2475+ const gchar *element;
2476+ gchar *tmp;
2477+
2478+ element = g_variant_type_info_get_type_string (instance->type_info);
2479+ tmp = g_strdup_printf ("m%s", element);
2480+ type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
2481+ g_free (tmp);
2482+ }
2483+
2484+ needed_size = g_variant_serialiser_needed_size (type_info,
2485+ random_instance_filler,
2486+ NULL, 0);
2487+ g_assert_cmpint (needed_size, ==, 0);
2488+
2489+ needed_size = g_variant_serialiser_needed_size (type_info,
2490+ random_instance_filler,
2491+ (gpointer *) &instance, 1);
2492+
2493+ if (instance->is_fixed_sized)
2494+ g_assert_cmpint (needed_size, ==, instance->size);
2495+ else
2496+ g_assert_cmpint (needed_size, ==, instance->size + 1);
2497+
2498+ {
2499+ guchar *ptr;
2500+
2501+ ptr = data = align_malloc (needed_size);
2502+ append_instance_data (instance, &ptr);
2503+
2504+ if (!instance->is_fixed_sized)
2505+ *ptr++ = '\0';
2506+
2507+ g_assert_cmpint (ptr - data, ==, needed_size);
2508+ }
2509+
2510+ {
2511+ guint alignment;
2512+ guint flavour;
2513+
2514+ alignment = (instance->alignment & ALIGN_BITS) + 1;
2515+
2516+ for (flavour = 0; flavour < 8; flavour += alignment)
2517+ {
2518+ GVariantSerialised serialised;
2519+ GVariantSerialised child;
2520+
2521+ serialised.type_info = type_info;
2522+ serialised.data = flavoured_malloc (needed_size, flavour);
2523+ serialised.size = needed_size;
2524+
2525+ g_variant_serialiser_serialise (serialised,
2526+ random_instance_filler,
2527+ (gpointer *) &instance, 1);
2528+ child = g_variant_serialised_get_child (serialised, 0);
2529+ g_assert (child.type_info == instance->type_info);
2530+ random_instance_assert (instance, child.data, child.size);
2531+ g_variant_type_info_unref (child.type_info);
2532+ flavoured_free (serialised.data, flavour);
2533+ }
2534+ }
2535+
2536+ g_variant_type_info_unref (type_info);
2537+ random_instance_free (instance);
2538+ align_free (data);
2539+}
2540+
2541+static void
2542+test_maybes (void)
2543+{
2544+ guint i;
2545+
2546+ for (i = 0; i < 1000; i++)
2547+ test_maybe ();
2548+
2549+ g_variant_type_info_assert_no_infos ();
2550+}
2551+
2552+static void
2553+test_array (void)
2554+{
2555+ GVariantTypeInfo *element_info;
2556+ GVariantTypeInfo *array_info;
2557+ RandomInstance **instances;
2558+ gsize needed_size;
2559+ gsize offset_size;
2560+ guint n_children;
2561+ guchar *data;
2562+
2563+ {
2564+ gchar *element_type, *array_type;
2565+
2566+ element_type = random_type_string ();
2567+ array_type = g_strdup_printf ("a%s", element_type);
2568+
2569+ element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
2570+ array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
2571+ g_assert (g_variant_type_info_element (array_info) == element_info);
2572+
2573+ g_free (element_type);
2574+ g_free (array_type);
2575+ }
2576+
2577+ {
2578+ guint i;
2579+
2580+ n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
2581+ instances = g_new (RandomInstance *, n_children);
2582+ for (i = 0; i < n_children; i++)
2583+ instances[i] = random_instance (element_info);
2584+ }
2585+
2586+ needed_size = g_variant_serialiser_needed_size (array_info,
2587+ random_instance_filler,
2588+ (gpointer *) instances,
2589+ n_children);
2590+
2591+ {
2592+ gsize element_fixed_size;
2593+ gsize body_size = 0;
2594+ guint i;
2595+
2596+ for (i = 0; i < n_children; i++)
2597+ append_instance_size (instances[i], &body_size);
2598+
2599+ g_variant_type_info_query (element_info, NULL, &element_fixed_size);
2600+
2601+ if (!element_fixed_size)
2602+ {
2603+ offset_size = calculate_offset_size (body_size, n_children);
2604+
2605+ if (offset_size == 0)
2606+ offset_size = 1;
2607+ }
2608+ else
2609+ offset_size = 0;
2610+
2611+ g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
2612+ }
2613+
2614+ {
2615+ guchar *offset_ptr, *body_ptr;
2616+ guint i;
2617+
2618+ body_ptr = data = align_malloc (needed_size);
2619+ offset_ptr = body_ptr + needed_size - offset_size * n_children;
2620+
2621+ for (i = 0; i < n_children; i++)
2622+ {
2623+ append_instance_data (instances[i], &body_ptr);
2624+ append_offset (&offset_ptr, body_ptr - data, offset_size);
2625+ }
2626+
2627+ g_assert (body_ptr == data + needed_size - offset_size * n_children);
2628+ g_assert (offset_ptr == data + needed_size);
2629+ }
2630+
2631+ {
2632+ guint alignment;
2633+ gsize flavour;
2634+ guint i;
2635+
2636+ g_variant_type_info_query (array_info, &alignment, NULL);
2637+ alignment = (alignment & ALIGN_BITS) + 1;
2638+
2639+ for (flavour = 0; flavour < 8; flavour += alignment)
2640+ {
2641+ GVariantSerialised serialised;
2642+
2643+ serialised.type_info = array_info;
2644+ serialised.data = flavoured_malloc (needed_size, flavour);
2645+ serialised.size = needed_size;
2646+
2647+ g_variant_serialiser_serialise (serialised, random_instance_filler,
2648+ (gpointer *) instances, n_children);
2649+
2650+ g_assert (memcmp (serialised.data, data, serialised.size) == 0);
2651+ g_assert (g_variant_serialised_n_children (serialised) == n_children);
2652+
2653+ for (i = 0; i < n_children; i++)
2654+ {
2655+ GVariantSerialised child;
2656+
2657+ child = g_variant_serialised_get_child (serialised, i);
2658+ g_assert (child.type_info == instances[i]->type_info);
2659+ random_instance_assert (instances[i], child.data, child.size);
2660+ g_variant_type_info_unref (child.type_info);
2661+ }
2662+
2663+ flavoured_free (serialised.data, flavour);
2664+ }
2665+ }
2666+
2667+ {
2668+ guint i;
2669+
2670+ for (i = 0; i < n_children; i++)
2671+ random_instance_free (instances[i]);
2672+ g_free (instances);
2673+ }
2674+
2675+ g_variant_type_info_unref (element_info);
2676+ g_variant_type_info_unref (array_info);
2677+ align_free (data);
2678+}
2679+
2680+static void
2681+test_arrays (void)
2682+{
2683+ guint i;
2684+
2685+ for (i = 0; i < 100; i++)
2686+ test_array ();
2687+
2688+ g_variant_type_info_assert_no_infos ();
2689+}
2690+
2691+static void
2692+test_tuple (void)
2693+{
2694+ GVariantTypeInfo *type_info;
2695+ RandomInstance **instances;
2696+ gboolean fixed_size;
2697+ gsize needed_size;
2698+ gsize offset_size;
2699+ guint n_children;
2700+ guint alignment;
2701+ guchar *data;
2702+
2703+ n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
2704+ instances = g_new (RandomInstance *, n_children);
2705+
2706+ {
2707+ GString *type_string;
2708+ guint i;
2709+
2710+ fixed_size = TRUE;
2711+ alignment = 0;
2712+
2713+ type_string = g_string_new ("(");
2714+ for (i = 0; i < n_children; i++)
2715+ {
2716+ const gchar *str;
2717+
2718+ instances[i] = random_instance (NULL);
2719+
2720+ alignment |= instances[i]->alignment;
2721+ if (!instances[i]->is_fixed_sized)
2722+ fixed_size = FALSE;
2723+
2724+ str = g_variant_type_info_get_type_string (instances[i]->type_info);
2725+ g_string_append (type_string, str);
2726+ }
2727+ g_string_append_c (type_string, ')');
2728+
2729+ type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
2730+ g_string_free (type_string, TRUE);
2731+ }
2732+
2733+ needed_size = g_variant_serialiser_needed_size (type_info,
2734+ random_instance_filler,
2735+ (gpointer *) instances,
2736+ n_children);
2737+ {
2738+ gsize body_size = 0;
2739+ gsize offsets = 0;
2740+ guint i;
2741+
2742+ for (i = 0; i < n_children; i++)
2743+ {
2744+ append_instance_size (instances[i], &body_size);
2745+
2746+ if (i != n_children - 1 && !instances[i]->is_fixed_sized)
2747+ offsets++;
2748+ }
2749+
2750+ if (fixed_size)
2751+ {
2752+ body_size += (-body_size) & alignment;
2753+
2754+ g_assert ((body_size == 0) == (n_children == 0));
2755+ if (n_children == 0)
2756+ body_size = 1;
2757+ }
2758+
2759+ offset_size = calculate_offset_size (body_size, offsets);
2760+ g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
2761+ }
2762+
2763+ {
2764+ guchar *body_ptr;
2765+ guchar *ofs_ptr;
2766+ guint i;
2767+
2768+ body_ptr = data = align_malloc (needed_size);
2769+ ofs_ptr = body_ptr + needed_size;
2770+
2771+ for (i = 0; i < n_children; i++)
2772+ {
2773+ append_instance_data (instances[i], &body_ptr);
2774+
2775+ if (i != n_children - 1 && !instances[i]->is_fixed_sized)
2776+ prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
2777+ }
2778+
2779+ if (fixed_size)
2780+ {
2781+ while (((gsize) body_ptr) & alignment)
2782+ *body_ptr++ = '\0';
2783+
2784+ g_assert ((body_ptr == data) == (n_children == 0));
2785+ if (n_children == 0)
2786+ *body_ptr++ = '\0';
2787+
2788+ }
2789+
2790+
2791+ g_assert (body_ptr == ofs_ptr);
2792+ }
2793+
2794+ {
2795+ gsize flavour;
2796+ guint i;
2797+
2798+ alignment = (alignment & ALIGN_BITS) + 1;
2799+
2800+ for (flavour = 0; flavour < 8; flavour += alignment)
2801+ {
2802+ GVariantSerialised serialised;
2803+
2804+ serialised.type_info = type_info;
2805+ serialised.data = flavoured_malloc (needed_size, flavour);
2806+ serialised.size = needed_size;
2807+
2808+ g_variant_serialiser_serialise (serialised, random_instance_filler,
2809+ (gpointer *) instances, n_children);
2810+
2811+ g_assert (memcmp (serialised.data, data, serialised.size) == 0);
2812+ g_assert (g_variant_serialised_n_children (serialised) == n_children);
2813+
2814+ for (i = 0; i < n_children; i++)
2815+ {
2816+ GVariantSerialised child;
2817+
2818+ child = g_variant_serialised_get_child (serialised, i);
2819+ g_assert (child.type_info == instances[i]->type_info);
2820+ random_instance_assert (instances[i], child.data, child.size);
2821+ g_variant_type_info_unref (child.type_info);
2822+ }
2823+
2824+ flavoured_free (serialised.data, flavour);
2825+ }
2826+ }
2827+
2828+ {
2829+ guint i;
2830+
2831+ for (i = 0; i < n_children; i++)
2832+ random_instance_free (instances[i]);
2833+ g_free (instances);
2834+ }
2835+
2836+ g_variant_type_info_unref (type_info);
2837+ align_free (data);
2838+}
2839+
2840+static void
2841+test_tuples (void)
2842+{
2843+ guint i;
2844+
2845+ for (i = 0; i < 100; i++)
2846+ test_tuple ();
2847+
2848+ g_variant_type_info_assert_no_infos ();
2849+}
2850+
2851+static void
2852+test_variant (void)
2853+{
2854+ GVariantTypeInfo *type_info;
2855+ RandomInstance *instance;
2856+ const gchar *type_string;
2857+ gsize needed_size;
2858+ guchar *data;
2859+ gsize len;
2860+
2861+ type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
2862+ instance = random_instance (NULL);
2863+
2864+ type_string = g_variant_type_info_get_type_string (instance->type_info);
2865+ len = strlen (type_string);
2866+
2867+ needed_size = g_variant_serialiser_needed_size (type_info,
2868+ random_instance_filler,
2869+ (gpointer *) &instance, 1);
2870+
2871+ g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
2872+
2873+ {
2874+ guchar *ptr;
2875+
2876+ ptr = data = align_malloc (needed_size);
2877+ append_instance_data (instance, &ptr);
2878+ *ptr++ = '\0';
2879+ memcpy (ptr, type_string, len);
2880+ ptr += len;
2881+
2882+ g_assert (data + needed_size == ptr);
2883+ }
2884+
2885+ {
2886+ gsize alignment;
2887+ gsize flavour;
2888+
2889+ /* variants are always 8-aligned */
2890+ alignment = ALIGN_BITS + 1;
2891+
2892+ for (flavour = 0; flavour < 8; flavour += alignment)
2893+ {
2894+ GVariantSerialised serialised;
2895+ GVariantSerialised child;
2896+
2897+ serialised.type_info = type_info;
2898+ serialised.data = flavoured_malloc (needed_size, flavour);
2899+ serialised.size = needed_size;
2900+
2901+ g_variant_serialiser_serialise (serialised, random_instance_filler,
2902+ (gpointer *) &instance, 1);
2903+
2904+ g_assert (memcmp (serialised.data, data, serialised.size) == 0);
2905+ g_assert (g_variant_serialised_n_children (serialised) == 1);
2906+
2907+ child = g_variant_serialised_get_child (serialised, 0);
2908+ g_assert (child.type_info == instance->type_info);
2909+ random_instance_check (instance, child.data, child.size);
2910+
2911+ g_variant_type_info_unref (child.type_info);
2912+ flavoured_free (serialised.data, flavour);
2913+ }
2914+ }
2915+
2916+ g_variant_type_info_unref (type_info);
2917+ random_instance_free (instance);
2918+ align_free (data);
2919+}
2920+
2921+static void
2922+test_variants (void)
2923+{
2924+ guint i;
2925+
2926+ for (i = 0; i < 100; i++)
2927+ test_variant ();
2928+
2929+ g_variant_type_info_assert_no_infos ();
2930+}
2931+
2932+static void
2933+test_strings (void)
2934+{
2935+ struct {
2936+ guint flags;
2937+ guint size;
2938+ gconstpointer data;
2939+ } test_cases[] = {
2940+#define is_nval 0
2941+#define is_string 1
2942+#define is_objpath is_string | 2
2943+#define is_sig is_string | 4
2944+ { is_sig, 1, "" },
2945+ { is_nval, 0, NULL },
2946+ { is_nval, 13, "hello\xffworld!" },
2947+ { is_string, 13, "hello world!" },
2948+ { is_nval, 13, "hello world\0" },
2949+ { is_nval, 13, "hello\0world!" },
2950+ { is_nval, 12, "hello world!" },
2951+ { is_nval, 13, "hello world!\xff" },
2952+
2953+ { is_objpath, 2, "/" },
2954+ { is_objpath, 3, "/a" },
2955+ { is_string, 3, "//" },
2956+ { is_objpath, 11, "/some/path" },
2957+ { is_string, 12, "/some/path/" },
2958+ { is_nval, 11, "/some\0path" },
2959+ { is_string, 11, "/some\\path" },
2960+ { is_string, 12, "/some//path" },
2961+ { is_string, 12, "/some-/path" },
2962+
2963+ { is_sig, 2, "i" },
2964+ { is_sig, 2, "s" },
2965+ { is_sig, 5, "(si)" },
2966+ { is_string, 4, "(si" },
2967+ { is_string, 2, "*" },
2968+ { is_sig, 3, "ai" },
2969+ { is_string, 3, "mi" },
2970+ { is_string, 2, "r" },
2971+ { is_sig, 15, "(yyy{sv}ssiai)" },
2972+ { is_string, 16, "(yyy{yv}ssiai))" },
2973+ { is_string, 15, "(yyy{vv}ssiai)" },
2974+ { is_string, 15, "(yyy{sv)ssiai}" }
2975+ };
2976+ guint i;
2977+
2978+ for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
2979+ {
2980+ guint flags;
2981+
2982+ flags = g_variant_serialiser_is_string (test_cases[i].data,
2983+ test_cases[i].size)
2984+ ? 1 : 0;
2985+
2986+ flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
2987+ test_cases[i].size)
2988+ ? 2 : 0;
2989+
2990+ flags |= g_variant_serialiser_is_signature (test_cases[i].data,
2991+ test_cases[i].size)
2992+ ? 4 : 0;
2993+
2994+ g_assert (flags == test_cases[i].flags);
2995+ }
2996+}
2997+
2998+typedef struct _TreeInstance TreeInstance;
2999+struct _TreeInstance
3000+{
3001+ GVariantTypeInfo *info;
3002+
3003+ TreeInstance **children;
3004+ gsize n_children;
3005+
3006+ union {
3007+ guint64 integer;
3008+ gdouble floating;
3009+ gchar string[32];
3010+ } data;
3011+ gsize data_size;
3012+};
3013+
3014+static GVariantType *
3015+make_random_definite_type (int depth)
3016+{
3017+ GString *description;
3018+ GString *type_string;
3019+ GVariantType *type;
3020+
3021+ description = g_string_new (NULL);
3022+ type_string = g_string_new (NULL);
3023+ type = append_type_string (type_string, description, TRUE, depth);
3024+ g_string_free (description, TRUE);
3025+ g_string_free (type_string, TRUE);
3026+
3027+ return type;
3028+}
3029+
3030+static void
3031+make_random_string (gchar *string,
3032+ gsize size,
3033+ const GVariantType *type)
3034+{
3035+ gint i;
3036+
3037+ /* create strings that are valid signature strings */
3038+#define good_chars "bynqiuxthdsog"
3039+
3040+ for (i = 0; i < size - 1; i++)
3041+ string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
3042+ string[i] = '\0';
3043+
3044+ /* in case we need an object path, prefix a '/' */
3045+ if (*g_variant_type_peek_string (type) == 'o')
3046+ string[0] = '/';
3047+
3048+#undef good_chars
3049+}
3050+
3051+static TreeInstance *
3052+tree_instance_new (const GVariantType *type,
3053+ int depth)
3054+{
3055+ const GVariantType *child_type = NULL;
3056+ GVariantType *mytype = NULL;
3057+ TreeInstance *instance;
3058+ gboolean is_tuple_type;
3059+
3060+ if (type == NULL)
3061+ type = mytype = make_random_definite_type (depth);
3062+
3063+ instance = g_slice_new (TreeInstance);
3064+ instance->info = g_variant_type_info_get (type);
3065+ instance->children = NULL;
3066+ instance->n_children = 0;
3067+ instance->data_size = 0;
3068+
3069+ is_tuple_type = FALSE;
3070+
3071+ switch (*g_variant_type_peek_string (type))
3072+ {
3073+ case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
3074+ instance->n_children = g_test_rand_int_range (0, 2);
3075+ child_type = g_variant_type_element (type);
3076+ break;
3077+
3078+ case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
3079+ instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
3080+ child_type = g_variant_type_element (type);
3081+ break;
3082+
3083+ case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
3084+ case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
3085+ instance->n_children = g_variant_type_n_items (type);
3086+ child_type = g_variant_type_first (type);
3087+ is_tuple_type = TRUE;
3088+ break;
3089+
3090+ case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
3091+ instance->n_children = 1;
3092+ child_type = NULL;
3093+ break;
3094+
3095+ case 'b':
3096+ instance->data.integer = g_test_rand_int_range (0, 2);
3097+ instance->data_size = 1;
3098+ break;
3099+
3100+ case 'y':
3101+ instance->data.integer = g_test_rand_int ();
3102+ instance->data_size = 1;
3103+ break;
3104+
3105+ case 'n': case 'q':
3106+ instance->data.integer = g_test_rand_int ();
3107+ instance->data_size = 2;
3108+ break;
3109+
3110+ case 'i': case 'u': case 'h':
3111+ instance->data.integer = g_test_rand_int ();
3112+ instance->data_size = 4;
3113+ break;
3114+
3115+ case 'x': case 't':
3116+ instance->data.integer = g_test_rand_int ();
3117+ instance->data.integer <<= 32;
3118+ instance->data.integer |= (guint32) g_test_rand_int ();
3119+ instance->data_size = 8;
3120+ break;
3121+
3122+ case 'd':
3123+ instance->data.floating = g_test_rand_double ();
3124+ instance->data_size = 8;
3125+ break;
3126+
3127+ case 's': case 'o': case 'g':
3128+ instance->data_size = g_test_rand_int_range (10, 20);
3129+ make_random_string (instance->data.string, instance->data_size, type);
3130+ break;
3131+ }
3132+
3133+ if (instance->data_size == 0)
3134+ /* no data -> it is a container */
3135+ {
3136+ guint i;
3137+
3138+ instance->children = g_new (TreeInstance *, instance->n_children);
3139+
3140+ for (i = 0; i < instance->n_children; i++)
3141+ {
3142+ instance->children[i] = tree_instance_new (child_type, depth - 1);
3143+
3144+ if (is_tuple_type)
3145+ child_type = g_variant_type_next (child_type);
3146+ }
3147+
3148+ g_assert (!is_tuple_type || child_type == NULL);
3149+ }
3150+
3151+ g_variant_type_free (mytype);
3152+
3153+ return instance;
3154+}
3155+
3156+static void
3157+tree_instance_free (TreeInstance *instance)
3158+{
3159+ gint i;
3160+
3161+ g_variant_type_info_unref (instance->info);
3162+ for (i = 0; i < instance->n_children; i++)
3163+ tree_instance_free (instance->children[i]);
3164+ g_free (instance->children);
3165+ g_slice_free (TreeInstance, instance);
3166+}
3167+
3168+static gboolean i_am_writing_byteswapped;
3169+
3170+static void
3171+tree_filler (GVariantSerialised *serialised,
3172+ gpointer data)
3173+{
3174+ TreeInstance *instance = data;
3175+
3176+ if (serialised->type_info == NULL)
3177+ serialised->type_info = instance->info;
3178+
3179+ if (instance->data_size == 0)
3180+ /* is a container */
3181+ {
3182+ if (serialised->size == 0)
3183+ serialised->size =
3184+ g_variant_serialiser_needed_size (instance->info, tree_filler,
3185+ (gpointer *) instance->children,
3186+ instance->n_children);
3187+
3188+ if (serialised->data)
3189+ g_variant_serialiser_serialise (*serialised, tree_filler,
3190+ (gpointer *) instance->children,
3191+ instance->n_children);
3192+ }
3193+ else
3194+ /* it is a leaf */
3195+ {
3196+ if (serialised->size == 0)
3197+ serialised->size = instance->data_size;
3198+
3199+ if (serialised->data)
3200+ {
3201+ switch (instance->data_size)
3202+ {
3203+ case 1:
3204+ *serialised->data = instance->data.integer;
3205+ break;
3206+
3207+ case 2:
3208+ {
3209+ guint16 value = instance->data.integer;
3210+
3211+ if (i_am_writing_byteswapped)
3212+ value = GUINT16_SWAP_LE_BE (value);
3213+
3214+ *(guint16 *) serialised->data = value;
3215+ }
3216+ break;
3217+
3218+ case 4:
3219+ {
3220+ guint32 value = instance->data.integer;
3221+
3222+ if (i_am_writing_byteswapped)
3223+ value = GUINT32_SWAP_LE_BE (value);
3224+
3225+ *(guint32 *) serialised->data = value;
3226+ }
3227+ break;
3228+
3229+ case 8:
3230+ {
3231+ guint64 value = instance->data.integer;
3232+
3233+ if (i_am_writing_byteswapped)
3234+ value = GUINT64_SWAP_LE_BE (value);
3235+
3236+ *(guint64 *) serialised->data = value;
3237+ }
3238+ break;
3239+
3240+ default:
3241+ memcpy (serialised->data,
3242+ instance->data.string,
3243+ instance->data_size);
3244+ break;
3245+ }
3246+ }
3247+ }
3248+}
3249+
3250+static gboolean
3251+check_tree (TreeInstance *instance,
3252+ GVariantSerialised serialised)
3253+{
3254+ if (instance->info != serialised.type_info)
3255+ return FALSE;
3256+
3257+ if (instance->data_size == 0)
3258+ /* is a container */
3259+ {
3260+ gint i;
3261+
3262+ if (g_variant_serialised_n_children (serialised) !=
3263+ instance->n_children)
3264+ return FALSE;
3265+
3266+ for (i = 0; i < instance->n_children; i++)
3267+ {
3268+ GVariantSerialised child;
3269+ gpointer data = NULL;
3270+ gboolean ok;
3271+
3272+ child = g_variant_serialised_get_child (serialised, i);
3273+ if (child.size && child.data == NULL)
3274+ child.data = data = g_malloc0 (child.size);
3275+ ok = check_tree (instance->children[i], child);
3276+ g_variant_type_info_unref (child.type_info);
3277+ g_free (data);
3278+
3279+ if (!ok)
3280+ return FALSE;
3281+ }
3282+
3283+ return TRUE;
3284+ }
3285+ else
3286+ /* it is a leaf */
3287+ {
3288+ switch (instance->data_size)
3289+ {
3290+ case 1:
3291+ g_assert (serialised.size == 1);
3292+ return *(guint8 *) serialised.data ==
3293+ (guint8) instance->data.integer;
3294+
3295+ case 2:
3296+ g_assert (serialised.size == 2);
3297+ return *(guint16 *) serialised.data ==
3298+ (guint16) instance->data.integer;
3299+
3300+ case 4:
3301+ g_assert (serialised.size == 4);
3302+ return *(guint32 *) serialised.data ==
3303+ (guint32) instance->data.integer;
3304+
3305+ case 8:
3306+ g_assert (serialised.size == 8);
3307+ return *(guint64 *) serialised.data ==
3308+ (guint64) instance->data.integer;
3309+
3310+ default:
3311+ if (serialised.size != instance->data_size)
3312+ return FALSE;
3313+
3314+ return memcmp (serialised.data,
3315+ instance->data.string,
3316+ instance->data_size) == 0;
3317+ }
3318+ }
3319+}
3320+
3321+static void
3322+serialise_tree (TreeInstance *tree,
3323+ GVariantSerialised *serialised)
3324+{
3325+ GVariantSerialised empty = { };
3326+
3327+ *serialised = empty;
3328+ tree_filler (serialised, tree);
3329+ serialised->data = g_malloc (serialised->size);
3330+ tree_filler (serialised, tree);
3331+}
3332+
3333+static void
3334+test_byteswap (void)
3335+{
3336+ GVariantSerialised one, two;
3337+ TreeInstance *tree;
3338+
3339+ tree = tree_instance_new (NULL, 3);
3340+ serialise_tree (tree, &one);
3341+
3342+ i_am_writing_byteswapped = TRUE;
3343+ serialise_tree (tree, &two);
3344+ i_am_writing_byteswapped = FALSE;
3345+
3346+ g_variant_serialised_byteswap (two);
3347+
3348+ g_assert_cmpint (one.size, ==, two.size);
3349+ g_assert (memcmp (one.data, two.data, one.size) == 0);
3350+
3351+ tree_instance_free (tree);
3352+ g_free (one.data);
3353+ g_free (two.data);
3354+}
3355+
3356+static void
3357+test_byteswaps (void)
3358+{
3359+ int i;
3360+
3361+ for (i = 0; i < 200; i++)
3362+ test_byteswap ();
3363+
3364+ g_variant_type_info_assert_no_infos ();
3365+}
3366+
3367+static void
3368+test_fuzz (gdouble *fuzziness)
3369+{
3370+ GVariantSerialised serialised;
3371+ TreeInstance *tree;
3372+
3373+ /* make an instance */
3374+ tree = tree_instance_new (NULL, 3);
3375+
3376+ /* serialise it */
3377+ serialise_tree (tree, &serialised);
3378+
3379+ g_assert (g_variant_serialised_is_normal (serialised));
3380+ g_assert (check_tree (tree, serialised));
3381+
3382+ if (serialised.size)
3383+ {
3384+ gboolean fuzzed = FALSE;
3385+ gboolean a, b;
3386+
3387+ while (!fuzzed)
3388+ {
3389+ gint i;
3390+
3391+ for (i = 0; i < serialised.size; i++)
3392+ if (randomly (*fuzziness))
3393+ {
3394+ serialised.data[i] += g_test_rand_int_range (1, 256);
3395+ fuzzed = TRUE;
3396+ }
3397+ }
3398+
3399+ /* at least one byte in the serialised data has changed.
3400+ *
3401+ * this means that at least one of the following is true:
3402+ *
3403+ * - the serialised data now represents a different value:
3404+ * check_tree() will return FALSE
3405+ *
3406+ * - the serialised data is in non-normal form:
3407+ * g_variant_serialiser_is_normal() will return FALSE
3408+ *
3409+ * we always do both checks to increase exposure of the serialiser
3410+ * to corrupt data.
3411+ */
3412+ a = g_variant_serialised_is_normal (serialised);
3413+ b = check_tree (tree, serialised);
3414+
3415+ g_assert (!a || !b);
3416+ }
3417+
3418+ tree_instance_free (tree);
3419+ g_free (serialised.data);
3420+}
3421+
3422+
3423+static void
3424+test_fuzzes (gpointer data)
3425+{
3426+ gdouble fuzziness;
3427+ int i;
3428+
3429+ fuzziness = GPOINTER_TO_INT (data) / 100.;
3430+
3431+ for (i = 0; i < 200; i++)
3432+ test_fuzz (&fuzziness);
3433+
3434+ g_variant_type_info_assert_no_infos ();
3435+}
3436+
3437+static GVariant *
3438+tree_instance_get_gvariant (TreeInstance *tree)
3439+{
3440+ const GVariantType *type;
3441+ GVariant *result;
3442+
3443+ type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
3444+
3445+ switch (g_variant_type_info_get_type_char (tree->info))
3446+ {
3447+ case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
3448+ {
3449+ const GVariantType *child_type;
3450+ GVariant *child;
3451+
3452+ if (tree->n_children)
3453+ child = tree_instance_get_gvariant (tree->children[0]);
3454+ else
3455+ child = NULL;
3456+
3457+ child_type = g_variant_type_element (type);
3458+
3459+ if (child != NULL && randomly (0.5))
3460+ child_type = NULL;
3461+
3462+ result = g_variant_new_maybe (child_type, child);
3463+ }
3464+ break;
3465+
3466+ case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
3467+ {
3468+ const GVariantType *child_type;
3469+ GVariant **children;
3470+ gint i;
3471+
3472+ children = g_new (GVariant *, tree->n_children);
3473+ for (i = 0; i < tree->n_children; i++)
3474+ children[i] = tree_instance_get_gvariant (tree->children[i]);
3475+
3476+ child_type = g_variant_type_element (type);
3477+
3478+ if (i > 0 && randomly (0.5))
3479+ child_type = NULL;
3480+
3481+ result = g_variant_new_array (child_type, children, tree->n_children);
3482+ g_free (children);
3483+ }
3484+ break;
3485+
3486+ case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
3487+ {
3488+ GVariant **children;
3489+ gint i;
3490+
3491+ children = g_new (GVariant *, tree->n_children);
3492+ for (i = 0; i < tree->n_children; i++)
3493+ children[i] = tree_instance_get_gvariant (tree->children[i]);
3494+
3495+ result = g_variant_new_tuple (children, tree->n_children);
3496+ g_free (children);
3497+ }
3498+ break;
3499+
3500+ case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
3501+ {
3502+ GVariant *key, *val;
3503+
3504+ g_assert (tree->n_children == 2);
3505+
3506+ key = tree_instance_get_gvariant (tree->children[0]);
3507+ val = tree_instance_get_gvariant (tree->children[1]);
3508+
3509+ result = g_variant_new_dict_entry (key, val);
3510+ }
3511+ break;
3512+
3513+ case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
3514+ {
3515+ GVariant *value;
3516+
3517+ g_assert (tree->n_children == 1);
3518+
3519+ value = tree_instance_get_gvariant (tree->children[0]);
3520+ result = g_variant_new_variant (value);
3521+ }
3522+ break;
3523+
3524+ case 'b':
3525+ result = g_variant_new_boolean (tree->data.integer > 0);
3526+ break;
3527+
3528+ case 'y':
3529+ result = g_variant_new_byte (tree->data.integer);
3530+ break;
3531+
3532+ case 'n':
3533+ result = g_variant_new_int16 (tree->data.integer);
3534+ break;
3535+
3536+ case 'q':
3537+ result = g_variant_new_uint16 (tree->data.integer);
3538+ break;
3539+
3540+ case 'i':
3541+ result = g_variant_new_int32 (tree->data.integer);
3542+ break;
3543+
3544+ case 'u':
3545+ result = g_variant_new_uint32 (tree->data.integer);
3546+ break;
3547+
3548+ case 'x':
3549+ result = g_variant_new_int64 (tree->data.integer);
3550+ break;
3551+
3552+ case 't':
3553+ result = g_variant_new_uint64 (tree->data.integer);
3554+ break;
3555+
3556+ case 'h':
3557+ result = g_variant_new_handle (tree->data.integer);
3558+ break;
3559+
3560+ case 'd':
3561+ result = g_variant_new_double (tree->data.floating);
3562+ break;
3563+
3564+ case 's':
3565+ result = g_variant_new_string (tree->data.string);
3566+ break;
3567+
3568+ case 'o':
3569+ result = g_variant_new_object_path (tree->data.string);
3570+ break;
3571+
3572+ case 'g':
3573+ result = g_variant_new_signature (tree->data.string);
3574+ break;
3575+
3576+ default:
3577+ g_assert_not_reached ();
3578+ }
3579+
3580+ return result;
3581+}
3582+
3583+static gboolean
3584+tree_instance_check_gvariant (TreeInstance *tree,
3585+ GVariant *value)
3586+{
3587+ const GVariantType *type;
3588+
3589+ type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
3590+ g_assert (g_variant_is_of_type (value, type));
3591+
3592+ switch (g_variant_type_info_get_type_char (tree->info))
3593+ {
3594+ case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
3595+ {
3596+ GVariant *child;
3597+ gboolean equal;
3598+
3599+ child = g_variant_get_maybe (value);
3600+
3601+ if (child != NULL && tree->n_children == 1)
3602+ equal = tree_instance_check_gvariant (tree->children[0], child);
3603+ else if (child == NULL && tree->n_children == 0)
3604+ equal = TRUE;
3605+ else
3606+ equal = FALSE;
3607+
3608+ if (child != NULL)
3609+ g_variant_unref (child);
3610+
3611+ return equal;
3612+ }
3613+ break;
3614+
3615+ case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
3616+ case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
3617+ case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
3618+ {
3619+ gsize i;
3620+
3621+ if (g_variant_n_children (value) != tree->n_children)
3622+ return FALSE;
3623+
3624+ for (i = 0; i < tree->n_children; i++)
3625+ {
3626+ GVariant *child;
3627+ gboolean equal;
3628+
3629+ child = g_variant_get_child_value (value, i);
3630+ equal = tree_instance_check_gvariant (tree->children[i], child);
3631+ g_variant_unref (child);
3632+
3633+ if (!equal)
3634+ return FALSE;
3635+ }
3636+
3637+ return TRUE;
3638+ }
3639+ break;
3640+
3641+ case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
3642+ {
3643+ const gchar *str1, *str2;
3644+ GVariant *child;
3645+ gboolean equal;
3646+
3647+ child = g_variant_get_variant (value);
3648+ str1 = g_variant_get_type_string (child);
3649+ str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
3650+ /* GVariant only keeps one copy of type strings around */
3651+ equal = str1 == str2 &&
3652+ tree_instance_check_gvariant (tree->children[0], child);
3653+
3654+ g_variant_unref (child);
3655+
3656+ return equal;
3657+ }
3658+ break;
3659+
3660+ case 'b':
3661+ return g_variant_get_boolean (value) == tree->data.integer;
3662+
3663+ case 'y':
3664+ return g_variant_get_byte (value) == (guchar) tree->data.integer;
3665+
3666+ case 'n':
3667+ return g_variant_get_int16 (value) == (gint16) tree->data.integer;
3668+
3669+ case 'q':
3670+ return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
3671+
3672+ case 'i':
3673+ return g_variant_get_int32 (value) == (gint32) tree->data.integer;
3674+
3675+ case 'u':
3676+ return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
3677+
3678+ case 'x':
3679+ return g_variant_get_int64 (value) == (gint64) tree->data.integer;
3680+
3681+ case 't':
3682+ return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
3683+
3684+ case 'h':
3685+ return g_variant_get_handle (value) == (gint32) tree->data.integer;
3686+
3687+ case 'd':
3688+ {
3689+ gdouble floating = g_variant_get_double (value);
3690+
3691+ return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
3692+ }
3693+
3694+ case 's':
3695+ case 'o':
3696+ case 'g':
3697+ return strcmp (g_variant_get_string (value, NULL),
3698+ tree->data.string) == 0;
3699+
3700+ default:
3701+ g_assert_not_reached ();
3702+ }
3703+}
3704+
3705+static void
3706+tree_instance_build_gvariant (TreeInstance *tree,
3707+ GVariantBuilder *builder,
3708+ gboolean guess_ok)
3709+{
3710+ const GVariantType *type;
3711+
3712+ type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
3713+
3714+ if (g_variant_type_is_container (type))
3715+ {
3716+ gsize i;
3717+
3718+ /* force GVariantBuilder to guess the type half the time */
3719+ if (guess_ok && randomly (0.5))
3720+ {
3721+ if (g_variant_type_is_array (type) && tree->n_children)
3722+ type = G_VARIANT_TYPE_ARRAY;
3723+
3724+ if (g_variant_type_is_maybe (type) && tree->n_children)
3725+ type = G_VARIANT_TYPE_MAYBE;
3726+
3727+ if (g_variant_type_is_tuple (type))
3728+ type = G_VARIANT_TYPE_TUPLE;
3729+
3730+ if (g_variant_type_is_dict_entry (type))
3731+ type = G_VARIANT_TYPE_DICT_ENTRY;
3732+ }
3733+ else
3734+ guess_ok = FALSE;
3735+
3736+ g_variant_builder_open (builder, type);
3737+
3738+ for (i = 0; i < tree->n_children; i++)
3739+ tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
3740+
3741+ g_variant_builder_close (builder);
3742+ }
3743+ else
3744+ g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
3745+}
3746+
3747+
3748+static gboolean
3749+tree_instance_check_iter (TreeInstance *tree,
3750+ GVariantIter *iter)
3751+{
3752+ GVariant *value;
3753+
3754+ value = g_variant_iter_next_value (iter);
3755+
3756+ if (g_variant_is_container (value))
3757+ {
3758+ gsize i;
3759+
3760+ iter = g_variant_iter_new (value);
3761+ g_variant_unref (value);
3762+
3763+ if (g_variant_iter_n_children (iter) != tree->n_children)
3764+ {
3765+ g_variant_iter_free (iter);
3766+ return FALSE;
3767+ }
3768+
3769+ for (i = 0; i < tree->n_children; i++)
3770+ if (!tree_instance_check_iter (tree->children[i], iter))
3771+ {
3772+ g_variant_iter_free (iter);
3773+ return FALSE;
3774+ }
3775+
3776+ g_assert (g_variant_iter_next_value (iter) == NULL);
3777+ g_variant_iter_free (iter);
3778+
3779+ return TRUE;
3780+ }
3781+
3782+ else
3783+ {
3784+ gboolean equal;
3785+
3786+ equal = tree_instance_check_gvariant (tree, value);
3787+ g_variant_unref (value);
3788+
3789+ return equal;
3790+ }
3791+}
3792+
3793+static void
3794+test_container (void)
3795+{
3796+ TreeInstance *tree;
3797+ GVariant *value;
3798+ gchar *s1, *s2;
3799+
3800+ tree = tree_instance_new (NULL, 3);
3801+ value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
3802+
3803+ s1 = g_variant_print (value, TRUE);
3804+ g_assert (tree_instance_check_gvariant (tree, value));
3805+
3806+ g_variant_get_data (value);
3807+
3808+ s2 = g_variant_print (value, TRUE);
3809+ g_assert (tree_instance_check_gvariant (tree, value));
3810+
3811+ g_assert_cmpstr (s1, ==, s2);
3812+
3813+ if (g_variant_is_container (value))
3814+ {
3815+ GVariantBuilder builder;
3816+ GVariantIter iter;
3817+ GVariant *built;
3818+ GVariant *val;
3819+ gchar *s3;
3820+
3821+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
3822+ tree_instance_build_gvariant (tree, &builder, TRUE);
3823+ built = g_variant_builder_end (&builder);
3824+ g_variant_ref_sink (built);
3825+ g_variant_get_data (built);
3826+ val = g_variant_get_variant (built);
3827+
3828+ s3 = g_variant_print (val, TRUE);
3829+ g_assert_cmpstr (s1, ==, s3);
3830+
3831+ g_variant_iter_init (&iter, built);
3832+ g_assert (tree_instance_check_iter (tree, &iter));
3833+ g_assert (g_variant_iter_next_value (&iter) == NULL);
3834+
3835+ g_variant_unref (built);
3836+ g_variant_unref (val);
3837+ g_free (s3);
3838+ }
3839+
3840+ tree_instance_free (tree);
3841+ g_variant_unref (value);
3842+ g_free (s2);
3843+ g_free (s1);
3844+}
3845+
3846+static void
3847+test_utf8 (void)
3848+{
3849+ const gchar invalid[] = "hello\xffworld";
3850+ GVariant *value;
3851+
3852+ /* ensure that the test data is not valid utf8... */
3853+ g_assert (!g_utf8_validate (invalid, -1, NULL));
3854+
3855+ /* load the data untrusted */
3856+ value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
3857+ invalid, sizeof invalid,
3858+ FALSE, NULL, NULL);
3859+
3860+ /* ensure that the problem is caught and we get valid UTF-8 */
3861+ g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
3862+ g_variant_unref (value);
3863+
3864+
3865+ /* now load it trusted */
3866+ value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
3867+ invalid, sizeof invalid,
3868+ TRUE, NULL, NULL);
3869+
3870+ /* ensure we get the invalid data (ie: make sure that time wasn't
3871+ * wasted on validating data that was marked as trusted)
3872+ */
3873+ g_assert (g_variant_get_string (value, NULL) == invalid);
3874+ g_variant_unref (value);
3875+}
3876+
3877+static void
3878+test_containers (void)
3879+{
3880+ gint i;
3881+
3882+ for (i = 0; i < 100; i++)
3883+ {
3884+ test_container ();
3885+ }
3886+
3887+ g_variant_type_info_assert_no_infos ();
3888+}
3889+
3890+static void
3891+test_format_strings (void)
3892+{
3893+ GVariantType *type;
3894+ const gchar *end;
3895+
3896+ g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
3897+ g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
3898+ g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
3899+ g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
3900+ g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
3901+ *end == '\0');
3902+ g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
3903+ g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
3904+ g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
3905+ g_assert (!g_variant_format_string_scan ("az", NULL, &end));
3906+ g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
3907+ g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
3908+ g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
3909+ *end == '\0');
3910+ g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
3911+ *end == '\0');
3912+ g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
3913+ g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
3914+ *end == '\0');
3915+ g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
3916+ g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
3917+ g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
3918+ *end == '\0');
3919+ g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
3920+ g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
3921+ g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
3922+ g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
3923+ g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
3924+ g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
3925+ g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
3926+ g_assert (!g_variant_format_string_scan ("az", NULL, &end));
3927+ g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
3928+
3929+ type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
3930+ g_assert (type && *end == '\0');
3931+ g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
3932+ g_variant_type_free (type);
3933+
3934+ type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
3935+ g_assert (type == NULL);
3936+}
3937+
3938+static void
3939+exit_on_abort (int signal)
3940+{
3941+ exit (signal);
3942+}
3943+
3944+static gboolean
3945+do_failed_test (const gchar *pattern)
3946+{
3947+ if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
3948+ {
3949+ signal (SIGABRT, exit_on_abort);
3950+ return TRUE;
3951+ }
3952+
3953+ g_test_trap_assert_failed ();
3954+ g_test_trap_assert_stderr (pattern);
3955+
3956+ return FALSE;
3957+}
3958+
3959+static void
3960+test_invalid_varargs (void)
3961+{
3962+ GVariant *value;
3963+ const gchar *end;
3964+
3965+ if (!g_test_undefined ())
3966+ return;
3967+
3968+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3969+ "*GVariant format string*");
3970+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3971+ "*valid_format_string*");
3972+ value = g_variant_new ("z");
3973+ g_test_assert_expected_messages ();
3974+ g_assert (value == NULL);
3975+
3976+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3977+ "*valid GVariant format string as a prefix*");
3978+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3979+ "*valid_format_string*");
3980+ value = g_variant_new_va ("z", &end, NULL);
3981+ g_test_assert_expected_messages ();
3982+ g_assert (value == NULL);
3983+
3984+ value = g_variant_new ("y", 'a');
3985+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3986+ "*type of `q' but * has a type of `y'*");
3987+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3988+ "*valid_format_string*");
3989+ g_variant_get (value, "q");
3990+ g_test_assert_expected_messages ();
3991+ g_variant_unref (value);
3992+}
3993+
3994+static void
3995+check_and_free (GVariant *value,
3996+ const gchar *str)
3997+{
3998+ gchar *valstr = g_variant_print (value, FALSE);
3999+ g_assert_cmpstr (str, ==, valstr);
4000+ g_variant_unref (value);
4001+ g_free (valstr);
4002+}
4003+
4004+static void
4005+test_varargs (void)
4006+{
4007+ {
4008+ GVariantBuilder array;
4009+
4010+ g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
4011+ g_variant_builder_add_parsed (&array, "{'size', <(%i, %i)> }", 800, 600);
4012+ g_variant_builder_add (&array, "{sv}", "title",
4013+ g_variant_new_string ("Test case"));
4014+ g_variant_builder_add_value (&array,
4015+ g_variant_new_dict_entry (g_variant_new_string ("temperature"),
4016+ g_variant_new_variant (
4017+ g_variant_new_double (37.5))));
4018+ check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
4019+ NULL, FALSE, NULL, &array, 7777, 8888),
4020+ "(nothing, nothing, {'size': <(800, 600)>, "
4021+ "'title': <'Test case'>, "
4022+ "'temperature': <37.5>}, "
4023+ "7777, 8888)");
4024+
4025+ check_and_free (g_variant_new ("(imimimmimmimmi)",
4026+ 123,
4027+ FALSE, 321,
4028+ TRUE, 123,
4029+ FALSE, TRUE, 321,
4030+ TRUE, FALSE, 321,
4031+ TRUE, TRUE, 123),
4032+ "(123, nothing, 123, nothing, just nothing, 123)");
4033+
4034+ check_and_free (g_variant_new ("(ybnixd)",
4035+ 'a', 1, 22, 33, (guint64) 44, 5.5),
4036+ "(0x61, true, 22, 33, 44, 5.5)");
4037+
4038+ check_and_free (g_variant_new ("(@y?*rv)",
4039+ g_variant_new ("y", 'a'),
4040+ g_variant_new ("y", 'b'),
4041+ g_variant_new ("y", 'c'),
4042+ g_variant_new ("(y)", 'd'),
4043+ g_variant_new ("y", 'e')),
4044+ "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
4045+ }
4046+
4047+ {
4048+ GVariantBuilder array;
4049+ GVariantIter iter;
4050+ GVariant *value;
4051+ gchar *number;
4052+ gboolean just;
4053+ gint i, val;
4054+
4055+ g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
4056+ for (i = 0; i < 100; i++)
4057+ {
4058+ number = g_strdup_printf ("%d", i);
4059+ g_variant_builder_add (&array, "s", number);
4060+ g_free (number);
4061+ }
4062+
4063+ value = g_variant_builder_end (&array);
4064+ g_variant_iter_init (&iter, value);
4065+
4066+ i = 0;
4067+ while (g_variant_iter_loop (&iter, "s", &number))
4068+ {
4069+ gchar *check = g_strdup_printf ("%d", i++);
4070+ g_assert_cmpstr (number, ==, check);
4071+ g_free (check);
4072+ }
4073+ g_assert (number == NULL);
4074+ g_assert (i == 100);
4075+
4076+ g_variant_unref (value);
4077+
4078+ g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
4079+ for (i = 0; i < 100; i++)
4080+ g_variant_builder_add (&array, "mi", i % 2 == 0, i);
4081+ value = g_variant_builder_end (&array);
4082+
4083+ i = 0;
4084+ g_variant_iter_init (&iter, value);
4085+ while (g_variant_iter_loop (&iter, "mi", NULL, &val))
4086+ g_assert (val == i++ || val == 0);
4087+ g_assert (i == 100);
4088+
4089+ i = 0;
4090+ g_variant_iter_init (&iter, value);
4091+ while (g_variant_iter_loop (&iter, "mi", &just, &val))
4092+ {
4093+ gint this = i++;
4094+
4095+ if (this % 2 == 0)
4096+ {
4097+ g_assert (just);
4098+ g_assert (val == this);
4099+ }
4100+ else
4101+ {
4102+ g_assert (!just);
4103+ g_assert (val == 0);
4104+ }
4105+ }
4106+ g_assert (i == 100);
4107+
4108+ g_variant_unref (value);
4109+ }
4110+
4111+ {
4112+ const gchar *strvector[] = {"/hello", "/world", NULL};
4113+ const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
4114+ GVariantBuilder builder;
4115+ GVariantIter *array;
4116+ GVariantIter tuple;
4117+ const gchar **strv;
4118+ gchar **my_strv;
4119+ GVariant *value;
4120+ gchar *str;
4121+ gint i;
4122+
4123+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
4124+ g_variant_builder_add (&builder, "s", "/foo");
4125+ g_variant_builder_add (&builder, "s", "/bar");
4126+ g_variant_builder_add (&builder, "s", "/baz");
4127+ value = g_variant_new("(as^as^a&s)", &builder, strvector, strvector);
4128+ g_variant_iter_init (&tuple, value);
4129+ g_variant_iter_next (&tuple, "as", &array);
4130+
4131+ i = 0;
4132+ while (g_variant_iter_loop (array, "s", &str))
4133+ g_assert_cmpstr (str, ==, test_strs[i++]);
4134+ g_assert (i == 3);
4135+
4136+ g_variant_iter_free (array);
4137+
4138+ /* start over */
4139+ g_variant_iter_init (&tuple, value);
4140+ g_variant_iter_next (&tuple, "as", &array);
4141+
4142+ i = 0;
4143+ while (g_variant_iter_loop (array, "&s", &str))
4144+ g_assert_cmpstr (str, ==, test_strs[i++]);
4145+ g_assert (i == 3);
4146+
4147+ g_variant_iter_free (array);
4148+
4149+ g_variant_iter_next (&tuple, "^a&s", &strv);
4150+ g_variant_iter_next (&tuple, "^as", &my_strv);
4151+
4152+ g_assert_cmpstr (strv[0], ==, "/hello");
4153+ g_assert_cmpstr (strv[1], ==, "/world");
4154+ g_assert (strv[2] == NULL);
4155+ g_assert_cmpstr (my_strv[0], ==, "/hello");
4156+ g_assert_cmpstr (my_strv[1], ==, "/world");
4157+ g_assert (my_strv[2] == NULL);
4158+
4159+ g_variant_unref (value);
4160+ g_strfreev (my_strv);
4161+ g_free (strv);
4162+ }
4163+
4164+ {
4165+ const gchar *strvector[] = {"/hello", "/world", NULL};
4166+ const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
4167+ GVariantBuilder builder;
4168+ GVariantIter *array;
4169+ GVariantIter tuple;
4170+ const gchar **strv;
4171+ gchar **my_strv;
4172+ GVariant *value;
4173+ gchar *str;
4174+ gint i;
4175+
4176+ g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
4177+ g_variant_builder_add (&builder, "o", "/foo");
4178+ g_variant_builder_add (&builder, "o", "/bar");
4179+ g_variant_builder_add (&builder, "o", "/baz");
4180+ value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
4181+ g_variant_iter_init (&tuple, value);
4182+ g_variant_iter_next (&tuple, "ao", &array);
4183+
4184+ i = 0;
4185+ while (g_variant_iter_loop (array, "o", &str))
4186+ g_assert_cmpstr (str, ==, test_strs[i++]);
4187+ g_assert (i == 3);
4188+
4189+ g_variant_iter_free (array);
4190+
4191+ /* start over */
4192+ g_variant_iter_init (&tuple, value);
4193+ g_variant_iter_next (&tuple, "ao", &array);
4194+
4195+ i = 0;
4196+ while (g_variant_iter_loop (array, "&o", &str))
4197+ g_assert_cmpstr (str, ==, test_strs[i++]);
4198+ g_assert (i == 3);
4199+
4200+ g_variant_iter_free (array);
4201+
4202+ g_variant_iter_next (&tuple, "^a&o", &strv);
4203+ g_variant_iter_next (&tuple, "^ao", &my_strv);
4204+
4205+ g_assert_cmpstr (strv[0], ==, "/hello");
4206+ g_assert_cmpstr (strv[1], ==, "/world");
4207+ g_assert (strv[2] == NULL);
4208+ g_assert_cmpstr (my_strv[0], ==, "/hello");
4209+ g_assert_cmpstr (my_strv[1], ==, "/world");
4210+ g_assert (my_strv[2] == NULL);
4211+
4212+ g_variant_unref (value);
4213+ g_strfreev (my_strv);
4214+ g_free (strv);
4215+ }
4216+
4217+ {
4218+ const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
4219+ GVariantBuilder builder;
4220+ GVariantIter iter;
4221+ GVariantIter *i2;
4222+ GVariantIter *i3;
4223+ GVariant *value;
4224+ GVariant *sub;
4225+ gchar **strv;
4226+ gint i;
4227+
4228+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aas"));
4229+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
4230+ for (i = 0; i < 6; i++)
4231+ if (i & 1)
4232+ g_variant_builder_add (&builder, "s", strvector[i]);
4233+ else
4234+ g_variant_builder_add (&builder, "&s", strvector[i]);
4235+ g_variant_builder_close (&builder);
4236+ g_variant_builder_add (&builder, "^as", strvector);
4237+ g_variant_builder_add (&builder, "^as", strvector);
4238+ value = g_variant_new ("aas", &builder);
4239+
4240+ g_variant_iter_init (&iter, value);
4241+ while (g_variant_iter_loop (&iter, "^as", &strv))
4242+ for (i = 0; i < 6; i++)
4243+ g_assert_cmpstr (strv[i], ==, strvector[i]);
4244+
4245+ g_variant_iter_init (&iter, value);
4246+ while (g_variant_iter_loop (&iter, "^a&s", &strv))
4247+ for (i = 0; i < 6; i++)
4248+ g_assert_cmpstr (strv[i], ==, strvector[i]);
4249+
4250+ g_variant_iter_init (&iter, value);
4251+ while (g_variant_iter_loop (&iter, "as", &i2))
4252+ {
4253+ gchar *str;
4254+
4255+ i = 0;
4256+ while (g_variant_iter_loop (i2, "s", &str))
4257+ g_assert_cmpstr (str, ==, strvector[i++]);
4258+ g_assert (i == 6);
4259+ }
4260+
4261+ g_variant_iter_init (&iter, value);
4262+ i3 = g_variant_iter_copy (&iter);
4263+ while (g_variant_iter_loop (&iter, "@as", &sub))
4264+ {
4265+ gchar *str = g_variant_print (sub, TRUE);
4266+ g_assert_cmpstr (str, ==,
4267+ "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
4268+ g_free (str);
4269+ }
4270+
4271+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
4272+ "*NULL has already been returned*");
4273+ g_variant_iter_next_value (&iter);
4274+ g_test_assert_expected_messages ();
4275+
4276+ while (g_variant_iter_loop (i3, "*", &sub))
4277+ {
4278+ gchar *str = g_variant_print (sub, TRUE);
4279+ g_assert_cmpstr (str, ==,
4280+ "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
4281+ g_free (str);
4282+ }
4283+
4284+ g_variant_iter_free (i3);
4285+
4286+ for (i = 0; i < g_variant_n_children (value); i++)
4287+ {
4288+ gint j;
4289+
4290+ g_variant_get_child (value, i, "*", &sub);
4291+
4292+ for (j = 0; j < g_variant_n_children (sub); j++)
4293+ {
4294+ const gchar *str = NULL;
4295+ GVariant *cval;
4296+
4297+ g_variant_get_child (sub, j, "&s", &str);
4298+ g_assert_cmpstr (str, ==, strvector[j]);
4299+
4300+ cval = g_variant_get_child_value (sub, j);
4301+ g_variant_get (cval, "&s", &str);
4302+ g_assert_cmpstr (str, ==, strvector[j]);
4303+ g_variant_unref (cval);
4304+ }
4305+
4306+ g_variant_unref (sub);
4307+ }
4308+
4309+ g_variant_unref (value);
4310+ }
4311+
4312+ {
4313+ gboolean justs[10];
4314+ GVariant *value;
4315+
4316+ GVariant *vval;
4317+ guchar byteval;
4318+ gboolean bval;
4319+ gint16 i16val;
4320+ guint16 u16val;
4321+ gint32 i32val;
4322+ guint32 u32val;
4323+ gint64 i64val;
4324+ guint64 u64val;
4325+ gdouble dval;
4326+ gint32 hval;
4327+
4328+ /* test all 'nothing' */
4329+ value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
4330+ FALSE, 'a',
4331+ FALSE, TRUE,
4332+ FALSE, (gint16) 123,
4333+ FALSE, (guint16) 123,
4334+ FALSE, (gint32) 123,
4335+ FALSE, (guint32) 123,
4336+ FALSE, (gint64) 123,
4337+ FALSE, (guint64) 123,
4338+ FALSE, (gint32) -1,
4339+ FALSE, (gdouble) 37.5,
4340+ NULL);
4341+
4342+ /* both NULL */
4343+ g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
4344+ NULL, NULL,
4345+ NULL, NULL,
4346+ NULL, NULL,
4347+ NULL, NULL,
4348+ NULL, NULL,
4349+ NULL, NULL,
4350+ NULL, NULL,
4351+ NULL, NULL,
4352+ NULL, NULL,
4353+ NULL, NULL,
4354+ NULL);
4355+
4356+ /* NULL values */
4357+ memset (justs, 1, sizeof justs);
4358+ g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
4359+ &justs[0], NULL,
4360+ &justs[1], NULL,
4361+ &justs[2], NULL,
4362+ &justs[3], NULL,
4363+ &justs[4], NULL,
4364+ &justs[5], NULL,
4365+ &justs[6], NULL,
4366+ &justs[7], NULL,
4367+ &justs[8], NULL,
4368+ &justs[9], NULL,
4369+ NULL);
4370+ g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
4371+ justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
4372+
4373+ /* both non-NULL */
4374+ memset (justs, 1, sizeof justs);
4375+ byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
4376+ vval = (void *) 1;
4377+ bval = TRUE;
4378+ dval = 88.88;
4379+ g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
4380+ &justs[0], &byteval,
4381+ &justs[1], &bval,
4382+ &justs[2], &i16val,
4383+ &justs[3], &u16val,
4384+ &justs[4], &i32val,
4385+ &justs[5], &u32val,
4386+ &justs[6], &i64val,
4387+ &justs[7], &u64val,
4388+ &justs[8], &hval,
4389+ &justs[9], &dval,
4390+ &vval);
4391+ g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
4392+ justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
4393+ g_assert (byteval == '\0' && bval == FALSE);
4394+ g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
4395+ u32val == 0 && i64val == 0 && u64val == 0 &&
4396+ hval == 0 && dval == 0.0);
4397+ g_assert (vval == NULL);
4398+
4399+ /* NULL justs */
4400+ byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
4401+ vval = (void *) 1;
4402+ bval = TRUE;
4403+ dval = 88.88;
4404+ g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
4405+ NULL, &byteval,
4406+ NULL, &bval,
4407+ NULL, &i16val,
4408+ NULL, &u16val,
4409+ NULL, &i32val,
4410+ NULL, &u32val,
4411+ NULL, &i64val,
4412+ NULL, &u64val,
4413+ NULL, &hval,
4414+ NULL, &dval,
4415+ &vval);
4416+ g_assert (byteval == '\0' && bval == FALSE);
4417+ g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
4418+ u32val == 0 && i64val == 0 && u64val == 0 &&
4419+ hval == 0 && dval == 0.0);
4420+ g_assert (vval == NULL);
4421+
4422+ g_variant_unref (value);
4423+
4424+
4425+ /* test all 'just' */
4426+ value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
4427+ TRUE, 'a',
4428+ TRUE, TRUE,
4429+ TRUE, (gint16) 123,
4430+ TRUE, (guint16) 123,
4431+ TRUE, (gint32) 123,
4432+ TRUE, (guint32) 123,
4433+ TRUE, (gint64) 123,
4434+ TRUE, (guint64) 123,
4435+ TRUE, (gint32) -1,
4436+ TRUE, (gdouble) 37.5,
4437+ g_variant_new ("()"));
4438+
4439+ /* both NULL */
4440+ g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
4441+ NULL, NULL,
4442+ NULL, NULL,
4443+ NULL, NULL,
4444+ NULL, NULL,
4445+ NULL, NULL,
4446+ NULL, NULL,
4447+ NULL, NULL,
4448+ NULL, NULL,
4449+ NULL, NULL,
4450+ NULL, NULL,
4451+ NULL);
4452+
4453+ /* NULL values */
4454+ memset (justs, 0, sizeof justs);
4455+ g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
4456+ &justs[0], NULL,
4457+ &justs[1], NULL,
4458+ &justs[2], NULL,
4459+ &justs[3], NULL,
4460+ &justs[4], NULL,
4461+ &justs[5], NULL,
4462+ &justs[6], NULL,
4463+ &justs[7], NULL,
4464+ &justs[8], NULL,
4465+ &justs[9], NULL,
4466+ NULL);
4467+ g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
4468+ justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
4469+
4470+ /* both non-NULL */
4471+ memset (justs, 0, sizeof justs);
4472+ byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
4473+ vval = (void *) 1;
4474+ bval = FALSE;
4475+ dval = 88.88;
4476+ g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
4477+ &justs[0], &byteval,
4478+ &justs[1], &bval,
4479+ &justs[2], &i16val,
4480+ &justs[3], &u16val,
4481+ &justs[4], &i32val,
4482+ &justs[5], &u32val,
4483+ &justs[6], &i64val,
4484+ &justs[7], &u64val,
4485+ &justs[8], &hval,
4486+ &justs[9], &dval,
4487+ &vval);
4488+ g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
4489+ justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
4490+ g_assert (byteval == 'a' && bval == TRUE);
4491+ g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
4492+ u32val == 123 && i64val == 123 && u64val == 123 &&
4493+ hval == -1 && dval == 37.5);
4494+ g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
4495+ g_variant_unref (vval);
4496+
4497+ /* NULL justs */
4498+ byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
4499+ vval = (void *) 1;
4500+ bval = TRUE;
4501+ dval = 88.88;
4502+ g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
4503+ NULL, &byteval,
4504+ NULL, &bval,
4505+ NULL, &i16val,
4506+ NULL, &u16val,
4507+ NULL, &i32val,
4508+ NULL, &u32val,
4509+ NULL, &i64val,
4510+ NULL, &u64val,
4511+ NULL, &hval,
4512+ NULL, &dval,
4513+ &vval);
4514+ g_assert (byteval == 'a' && bval == TRUE);
4515+ g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
4516+ u32val == 123 && i64val == 123 && u64val == 123 &&
4517+ hval == -1 && dval == 37.5);
4518+ g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
4519+ g_variant_unref (vval);
4520+
4521+ g_variant_unref (value);
4522+ }
4523+
4524+ {
4525+ GVariant *value;
4526+ gchar *str;
4527+
4528+ value = g_variant_new ("(masas)", NULL, NULL);
4529+ g_variant_ref_sink (value);
4530+
4531+ str = g_variant_print (value, TRUE);
4532+ g_assert_cmpstr (str, ==, "(@mas nothing, @as [])");
4533+ g_variant_unref (value);
4534+ g_free (str);
4535+
4536+ if (do_failed_test ("*which type of empty array*"))
4537+ g_variant_new ("(a{s*})", NULL);
4538+ }
4539+
4540+ g_variant_type_info_assert_no_infos ();
4541+}
4542+
4543+static void
4544+hash_get (GVariant *value,
4545+ const gchar *format,
4546+ ...)
4547+{
4548+ const gchar *endptr = NULL;
4549+ gboolean hash;
4550+ va_list ap;
4551+
4552+ hash = g_str_has_suffix (format, "#");
4553+
4554+ va_start (ap, format);
4555+ g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
4556+ va_end (ap);
4557+
4558+ if (hash)
4559+ g_assert (*endptr == '#');
4560+}
4561+
4562+static GVariant *
4563+hash_new (const gchar *format,
4564+ ...)
4565+{
4566+ const gchar *endptr = NULL;
4567+ GVariant *value;
4568+ gboolean hash;
4569+ va_list ap;
4570+
4571+ hash = g_str_has_suffix (format, "#");
4572+
4573+ va_start (ap, format);
4574+ value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
4575+ va_end (ap);
4576+
4577+ if (hash)
4578+ g_assert (*endptr == '#');
4579+
4580+ return value;
4581+}
4582+
4583+static void
4584+test_valist (void)
4585+{
4586+ GVariant *value;
4587+ gint32 x;
4588+
4589+ x = 0;
4590+ value = hash_new ("i", 234);
4591+ hash_get (value, "i", &x);
4592+ g_assert (x == 234);
4593+ g_variant_unref (value);
4594+
4595+ x = 0;
4596+ value = hash_new ("i#", 234);
4597+ hash_get (value, "i#", &x);
4598+ g_assert (x == 234);
4599+ g_variant_unref (value);
4600+
4601+ g_variant_type_info_assert_no_infos ();
4602+}
4603+
4604+static void
4605+test_builder_memory (void)
4606+{
4607+ GVariantBuilder *hb;
4608+ GVariantBuilder sb;
4609+
4610+ hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
4611+ g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
4612+ g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
4613+ g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
4614+ g_variant_builder_add (hb, "s", "some value");
4615+ g_variant_builder_ref (hb);
4616+ g_variant_builder_unref (hb);
4617+ g_variant_builder_unref (hb);
4618+
4619+ hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
4620+ g_variant_builder_unref (hb);
4621+
4622+ hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
4623+ g_variant_builder_clear (hb);
4624+ g_variant_builder_unref (hb);
4625+
4626+ g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
4627+ g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
4628+ g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
4629+ g_variant_builder_add (&sb, "s", "some value");
4630+ g_variant_builder_clear (&sb);
4631+
4632+ g_variant_type_info_assert_no_infos ();
4633+}
4634+
4635+static void
4636+test_hashing (void)
4637+{
4638+ GVariant *items[4096];
4639+ GHashTable *table;
4640+ gint i;
4641+
4642+ table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
4643+ (GDestroyNotify ) g_variant_unref,
4644+ NULL);
4645+
4646+ for (i = 0; i < G_N_ELEMENTS (items); i++)
4647+ {
4648+ TreeInstance *tree;
4649+ gint j;
4650+
4651+ again:
4652+ tree = tree_instance_new (NULL, 0);
4653+ items[i] = tree_instance_get_gvariant (tree);
4654+ tree_instance_free (tree);
4655+
4656+ for (j = 0; j < i; j++)
4657+ if (g_variant_equal (items[i], items[j]))
4658+ {
4659+ g_variant_unref (items[i]);
4660+ goto again;
4661+ }
4662+
4663+ g_hash_table_insert (table,
4664+ g_variant_ref_sink (items[i]),
4665+ GINT_TO_POINTER (i));
4666+ }
4667+
4668+ for (i = 0; i < G_N_ELEMENTS (items); i++)
4669+ {
4670+ gpointer result;
4671+
4672+ result = g_hash_table_lookup (table, items[i]);
4673+ g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
4674+ }
4675+
4676+ g_hash_table_unref (table);
4677+
4678+ g_variant_type_info_assert_no_infos ();
4679+}
4680+
4681+static void
4682+test_gv_byteswap (void)
4683+{
4684+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
4685+# define native16(x) x, 0
4686+# define swapped16(x) 0, x
4687+#else
4688+# define native16(x) 0, x
4689+# define swapped16(x) x, 0
4690+#endif
4691+ /* all kinds of of crazy randomised testing already performed on the
4692+ * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
4693+ * of crazy randomised testing performed against the serialiser
4694+ * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
4695+ *
4696+ * just test a few simple cases here to make sure they each work
4697+ */
4698+ guchar validbytes[] = { 'a', '\0', swapped16(66), 2,
4699+ 0,
4700+ 'b', '\0', swapped16(77), 2,
4701+ 5, 11 };
4702+ guchar corruptbytes[] = { 'a', '\0', swapped16(66), 2,
4703+ 0,
4704+ 'b', '\0', swapped16(77), 2,
4705+ 6, 11 };
4706+ guint valid_data[4], corrupt_data[4];
4707+ GVariant *value, *swapped;
4708+ gchar *string, *string2;
4709+
4710+ memcpy (valid_data, validbytes, sizeof validbytes);
4711+ memcpy (corrupt_data, corruptbytes, sizeof corruptbytes);
4712+
4713+ /* trusted */
4714+ value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
4715+ valid_data, sizeof validbytes, TRUE,
4716+ NULL, NULL);
4717+ swapped = g_variant_byteswap (value);
4718+ g_variant_unref (value);
4719+ g_assert (g_variant_get_size (swapped) == 13);
4720+ string = g_variant_print (swapped, FALSE);
4721+ g_variant_unref (swapped);
4722+ g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
4723+ g_free (string);
4724+
4725+ /* untrusted but valid */
4726+ value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
4727+ valid_data, sizeof validbytes, FALSE,
4728+ NULL, NULL);
4729+ swapped = g_variant_byteswap (value);
4730+ g_variant_unref (value);
4731+ g_assert (g_variant_get_size (swapped) == 13);
4732+ string = g_variant_print (swapped, FALSE);
4733+ g_variant_unref (swapped);
4734+ g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
4735+ g_free (string);
4736+
4737+ /* untrusted, invalid */
4738+ value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
4739+ corrupt_data, sizeof corruptbytes, FALSE,
4740+ NULL, NULL);
4741+ string = g_variant_print (value, FALSE);
4742+ swapped = g_variant_byteswap (value);
4743+ g_variant_unref (value);
4744+ g_assert (g_variant_get_size (swapped) == 13);
4745+ value = g_variant_byteswap (swapped);
4746+ g_variant_unref (swapped);
4747+ string2 = g_variant_print (value, FALSE);
4748+ g_assert (g_variant_get_size (value) == 13);
4749+ g_variant_unref (value);
4750+ g_assert_cmpstr (string, ==, string2);
4751+ g_free (string2);
4752+ g_free (string);
4753+}
4754+
4755+static void
4756+test_parser (void)
4757+{
4758+ TreeInstance *tree;
4759+ GVariant *parsed;
4760+ GVariant *value;
4761+ gchar *pt, *p;
4762+ gchar *res;
4763+
4764+ tree = tree_instance_new (NULL, 3);
4765+ value = tree_instance_get_gvariant (tree);
4766+ tree_instance_free (tree);
4767+
4768+ pt = g_variant_print (value, TRUE);
4769+ p = g_variant_print (value, FALSE);
4770+
4771+ parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
4772+ res = g_variant_print (parsed, FALSE);
4773+ g_assert_cmpstr (p, ==, res);
4774+ g_variant_unref (parsed);
4775+ g_free (res);
4776+
4777+ parsed = g_variant_parse (g_variant_get_type (value), p,
4778+ NULL, NULL, NULL);
4779+ res = g_variant_print (parsed, TRUE);
4780+ g_assert_cmpstr (pt, ==, res);
4781+ g_variant_unref (parsed);
4782+ g_free (res);
4783+
4784+ g_variant_unref (value);
4785+ g_free (pt);
4786+ g_free (p);
4787+}
4788+
4789+static void
4790+test_parses (void)
4791+{
4792+ gint i;
4793+
4794+ for (i = 0; i < 100; i++)
4795+ {
4796+ test_parser ();
4797+ }
4798+
4799+ /* mini test */
4800+ {
4801+ GError *error = NULL;
4802+ gchar str[128];
4803+ GVariant *val;
4804+ gchar *p, *p2;
4805+
4806+ for (i = 0; i < 127; i++)
4807+ str[i] = i + 1;
4808+ str[i] = 0;
4809+
4810+ val = g_variant_new_string (str);
4811+ p = g_variant_print (val, FALSE);
4812+ g_variant_unref (val);
4813+
4814+ val = g_variant_parse (NULL, p, NULL, NULL, &error);
4815+ p2 = g_variant_print (val, FALSE);
4816+
4817+ g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
4818+ g_assert_cmpstr (p, ==, p2);
4819+
4820+ g_variant_unref (val);
4821+ g_free (p2);
4822+ g_free (p);
4823+ }
4824+
4825+ /* another mini test */
4826+ {
4827+ const gchar *end;
4828+ GVariant *value;
4829+
4830+ value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
4831+ g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
4832+ /* make sure endptr returning works */
4833+ g_assert_cmpstr (end, ==, " 2 3");
4834+ g_variant_unref (value);
4835+ }
4836+
4837+ /* unicode mini test */
4838+ {
4839+ /* ał𝄞 */
4840+ const gchar orig[] = "a\xc5\x82\xf0\x9d\x84\x9e \t\n";
4841+ GVariant *value;
4842+ gchar *printed;
4843+
4844+ value = g_variant_new_string (orig);
4845+ printed = g_variant_print (value, FALSE);
4846+ g_variant_unref (value);
4847+
4848+ g_assert_cmpstr (printed, ==, "'a\xc5\x82\xf0\x9d\x84\x9e \\t\\n'");
4849+ value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
4850+ g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
4851+ g_variant_unref (value);
4852+ g_free (printed);
4853+ }
4854+
4855+ /* inf/nan mini test */
4856+ {
4857+ const gchar *tests[] = { "inf", "-inf", "nan" };
4858+ GVariant *value;
4859+ gchar *printed;
4860+ gint i;
4861+
4862+ for (i = 0; i < G_N_ELEMENTS (tests); i++)
4863+ {
4864+ GError *error = NULL;
4865+ value = g_variant_parse (NULL, tests[i], NULL, NULL, &error);
4866+ printed = g_variant_print (value, FALSE);
4867+ g_assert (g_str_has_prefix (printed, tests[i]));
4868+ g_free (printed);
4869+ g_variant_unref (value);
4870+ }
4871+ }
4872+
4873+ g_variant_type_info_assert_no_infos ();
4874+}
4875+
4876+static void
4877+test_parse_failures (void)
4878+{
4879+ const gchar *test[] = {
4880+ "[1, 2,", "6:", "expected value",
4881+ "", "0:", "expected value",
4882+ "(1, 2,", "6:", "expected value",
4883+ "<1", "2:", "expected `>'",
4884+ "[]", "0-2:", "unable to infer",
4885+ "(,", "1:", "expected value",
4886+ "[4,'']", "1-2,3-5:", "common type",
4887+ "[4, '', 5]", "1-2,4-6:", "common type",
4888+ "['', 4, 5]", "1-3,5-6:", "common type",
4889+ "[4, 5, '']", "1-2,7-9:", "common type",
4890+ "[[4], [], ['']]", "1-4,10-14:", "common type",
4891+ "[[], [4], ['']]", "5-8,10-14:", "common type",
4892+ "just", "4:", "expected value",
4893+ "nothing", "0-7:", "unable to infer",
4894+ "just [4, '']", "6-7,9-11:", "common type",
4895+ "[[4,'']]", "2-3,4-6:", "common type",
4896+ "([4,''],)", "2-3,4-6:", "common type",
4897+ "(4)", "2:", "`,'",
4898+ "{}", "0-2:", "unable to infer",
4899+ "{[1,2],[3,4]}", "0-13:", "basic types",
4900+ "{[1,2]:[3,4]}", "0-13:", "basic types",
4901+ "justt", "0-5:", "unknown keyword",
4902+ "nothng", "0-6:", "unknown keyword",
4903+ "uint33", "0-6:", "unknown keyword",
4904+ "@mi just ''", "9-11:", "can not parse as",
4905+ "@ai ['']", "5-7:", "can not parse as",
4906+ "@(i) ('',)", "6-8:", "can not parse as",
4907+ "[[], 5]", "1-3,5-6:", "common type",
4908+ "[[5], 5]", "1-4,6-7:", "common type",
4909+ "5 5", "2:", "expected end of input",
4910+ "[5, [5, '']]", "5-6,8-10:", "common type",
4911+ "@i just 5", "3-9:", "can not parse as",
4912+ "@i nothing", "3-10:", "can not parse as",
4913+ "@i []", "3-5:", "can not parse as",
4914+ "@i ()", "3-5:", "can not parse as",
4915+ "@ai (4,)", "4-8:", "can not parse as",
4916+ "@(i) []", "5-7:", "can not parse as",
4917+ "(5 5)", "3:", "expected `,'",
4918+ "[5 5]", "3:", "expected `,' or `]'",
4919+ "(5, 5 5)", "6:", "expected `,' or `)'",
4920+ "[5, 5 5]", "6:", "expected `,' or `]'",
4921+ "<@i []>", "4-6:", "can not parse as",
4922+ "<[5 5]>", "4:", "expected `,' or `]'",
4923+ "{[4,''],5}", "2-3,4-6:", "common type",
4924+ "{5,[4,'']}", "4-5,6-8:", "common type",
4925+ "@i {1,2}", "3-8:", "can not parse as",
4926+ "{@i '', 5}", "4-6:", "can not parse as",
4927+ "{5, @i ''}", "7-9:", "can not parse as",
4928+ "@ai {}", "4-6:", "can not parse as",
4929+ "{@i '': 5}", "4-6:", "can not parse as",
4930+ "{5: @i ''}", "7-9:", "can not parse as",
4931+ "{<4,5}", "3:", "expected `>'",
4932+ "{4,<5}", "5:", "expected `>'",
4933+ "{4,5,6}", "4:", "expected `}'",
4934+ "{5 5}", "3:", "expected `:' or `,'",
4935+ "{4: 5: 6}", "5:", "expected `,' or `}'",
4936+ "{4:5,<6:7}", "7:", "expected `>'",
4937+ "{4:5,6:<7}", "9:", "expected `>'",
4938+ "{4:5,6 7}", "7:", "expected `:'",
4939+ "@o 'foo'", "3-8:", "object path",
4940+ "@g 'zzz'", "3-8:", "signature",
4941+ "@i true", "3-7:", "can not parse as",
4942+ "@z 4", "0-2:", "invalid type",
4943+ "@a* []", "0-3:", "definite",
4944+ "@ai [3 3]", "7:", "expected `,' or `]'",
4945+ "18446744073709551616", "0-20:", "too big for any type",
4946+ "-18446744073709551616", "0-21:", "too big for any type",
4947+ "byte 256", "5-8:", "out of range for type",
4948+ "byte -1", "5-7:", "out of range for type",
4949+ "int16 32768", "6-11:", "out of range for type",
4950+ "int16 -32769", "6-12:", "out of range for type",
4951+ "uint16 -1", "7-9:", "out of range for type",
4952+ "uint16 65536", "7-12:", "out of range for type",
4953+ "2147483648", "0-10:", "out of range for type",
4954+ "-2147483649", "0-11:", "out of range for type",
4955+ "uint32 -1", "7-9:", "out of range for type",
4956+ "uint32 4294967296", "7-17:", "out of range for type",
4957+ "@x 9223372036854775808", "3-22:", "out of range for type",
4958+ "@x -9223372036854775809", "3-23:", "out of range for type",
4959+ "@t -1", "3-5:", "out of range for type",
4960+ "@t 18446744073709551616", "3-23:", "too big for any type",
4961+ "handle 2147483648", "7-17:", "out of range for type",
4962+ "handle -2147483649", "7-18:", "out of range for type",
4963+ "1.798e308", "0-9:", "too big for any type",
4964+ "37.5a488", "4-5:", "invalid character",
4965+ "0x7ffgf", "5-6:", "invalid character",
4966+ "07758", "4-5:", "invalid character",
4967+ "123a5", "3-4:", "invalid character",
4968+ "@ai 123", "4-7:", "can not parse as",
4969+ "'\"\\'", "0-4:", "unterminated string",
4970+ "'\"\\'\\", "0-5:", "unterminated string",
4971+ "boolean 4", "8-9:", "can not parse as",
4972+ "int32 true", "6-10:", "can not parse as",
4973+ "[double 5, int32 5]", "1-9,11-18:", "common type",
4974+ "string 4", "7-8:", "can not parse as"
4975+ };
4976+ gint i;
4977+
4978+ for (i = 0; i < G_N_ELEMENTS (test); i += 3)
4979+ {
4980+ GError *error = NULL;
4981+ GVariant *value;
4982+
4983+ value = g_variant_parse (NULL, test[i], NULL, NULL, &error);
4984+ g_assert (value == NULL);
4985+
4986+ if (!strstr (error->message, test[i+2]))
4987+ g_error ("test %d: Can't find `%s' in `%s'", i / 3,
4988+ test[i+2], error->message);
4989+
4990+ if (!g_str_has_prefix (error->message, test[i+1]))
4991+ g_error ("test %d: Expected location `%s' in `%s'", i / 3,
4992+ test[i+1], error->message);
4993+
4994+ g_error_free (error);
4995+ }
4996+}
4997+
4998+static void
4999+test_parse_positional (void)
5000+{
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: