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

Subscribers

People subscribed via source and target branches

to all changes: