[glib/gvariant] GVariant: add support for file descriptor handles



commit bccce3e8fff965ff6a0740b17c7e358f8c7d9ad2
Author: Ryan Lortie <desrt desrt ca>
Date:   Mon Nov 9 22:47:13 2009 -0500

    GVariant: add support for file descriptor handles

 docs/reference/glib/glib-sections.txt |    2 +
 glib/gvariant-markup.c                |   10 +++++
 glib/gvariant-parser.c                |   29 +++++++++++----
 glib/gvariant-printer.c               |   14 ++++++-
 glib/gvariant-serialiser.c            |    1 +
 glib/gvariant-util.c                  |   49 +++++++++++++++++++++++---
 glib/gvariant-valist.c                |   26 ++++++++++++--
 glib/gvariant.h                       |    2 +
 glib/gvarianttype.c                   |    8 +++--
 glib/gvarianttype.h                   |   14 +++++++-
 glib/gvarianttypeinfo.c               |    1 +
 glib/tests/.gitignore                 |    1 +
 glib/tests/Makefile.am                |    3 ++
 glib/tests/gvariant-handle.c          |   63 +++++++++++++++++++++++++++++++++
 14 files changed, 202 insertions(+), 21 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index b6edbf3..cb52127 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -2798,6 +2798,7 @@ g_variant_new_signature
 g_variant_is_signature
 g_variant_new_variant
 g_variant_new_strv
+g_variant_new_handle
 
 <SUBSECTION>
 g_variant_get_boolean
@@ -2814,6 +2815,7 @@ g_variant_dup_string
 g_variant_get_variant
 g_variant_get_strv
 g_variant_dup_strv
+g_variant_get_handle
 
 <SUBSECTION>
 g_variant_n_children
diff --git a/glib/gvariant-markup.c b/glib/gvariant-markup.c
index a1f7aa0..0d8090a 100644
--- a/glib/gvariant-markup.c
+++ b/glib/gvariant-markup.c
@@ -293,6 +293,11 @@ g_variant_markup_print_string (GVariant *value,
                               g_variant_get_int32 (value));
       break;
 
+    case G_VARIANT_TYPE_CLASS_HANDLE:
+      g_string_append_printf (string, "<handle>%"G_GINT32_FORMAT"</handle>",
+                              g_variant_get_handle (value));
+      break;
+
     case G_VARIANT_TYPE_CLASS_UINT32:
       g_string_append_printf (string, "<uint32>%"G_GUINT32_FORMAT"</uint32>",
                               g_variant_get_uint32 (value));
@@ -410,6 +415,7 @@ type_class_from_keyword (const char *keyword)
     { G_VARIANT_TYPE_CLASS_INT16,            "int16" },
     { G_VARIANT_TYPE_CLASS_UINT16,           "uint16" },
     { G_VARIANT_TYPE_CLASS_INT32,            "int32" },
+    { G_VARIANT_TYPE_CLASS_HANDLE,           "handle" },
     { G_VARIANT_TYPE_CLASS_UINT32,           "uint32" },
     { G_VARIANT_TYPE_CLASS_INT64,            "int64" },
     { G_VARIANT_TYPE_CLASS_UINT64,           "uint64" },
@@ -628,6 +634,10 @@ g_variant_markup_parser_end_element (GMarkupParseContext  *context,
           value = g_variant_new_int32 (g_ascii_strtoll (string, &end, 0));
           break;
 
+        case G_VARIANT_TYPE_CLASS_HANDLE:
+          value = g_variant_new_handle (g_ascii_strtoll (string, &end, 0));
+          break;
+
         case G_VARIANT_TYPE_CLASS_UINT32:
           value = g_variant_new_uint32 (g_ascii_strtoull (string, &end, 0));
           break;
diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
index f4a0331..5927108 100644
--- a/glib/gvariant-parser.c
+++ b/glib/gvariant-parser.c
@@ -238,7 +238,7 @@ type_from_constraints (Constraints constraints)
       if (constraints & (CONSTRAINT_IS_NUMBER | CONSTRAINT_IS_BOOLEAN))
         return 0;
 
-      return 's';
+      return G_VARIANT_TYPE_CLASS_STRING;
     }
 
   if (constraints & CONSTRAINT_IS_BOOLEAN)
@@ -246,13 +246,13 @@ type_from_constraints (Constraints constraints)
       if (constraints & CONSTRAINT_IS_NUMBER)
         return 0;
 
-      return 'b';
+      return G_VARIANT_TYPE_CLASS_BOOLEAN;
     }
   
   if (constraints & CONSTRAINT_HAS_POINT)
-    return 'd';
+    return G_VARIANT_TYPE_CLASS_DOUBLE;
 
-  return 'i';
+  return G_VARIANT_TYPE_CLASS_INT32;
 }
 
 typedef struct
@@ -321,11 +321,11 @@ pattern_coalesce (Pattern       *dest,
         dest->constraints[i] |= src->constraints[i];
 
       else if (dest->type_string[i] == '?' &&
-               strchr ("bynqiuxtdsog", src->type_string[i]))
+               strchr ("bynqihuxtdsog", src->type_string[i]))
         dest->type_string[i] = src->type_string[i];
 
       else if (src->type_string[i] != '?' ||
-               !strchr ("bynqiuxtdsog", dest->type_string[i]))
+               !strchr ("bynqihuxtdsog", dest->type_string[i]))
         return FALSE;
     }
 
@@ -995,7 +995,7 @@ dictionary_get_pattern (AST                *ast,
       if (other_pattern == NULL)
         break;
 
-      if (!strchr ("bynqiuxtdsog?", other_pattern->type_string[0]))
+      if (!strchr ("bynqihuxtdsog?", other_pattern->type_string[0]))
         {
           ast_set_error (ast, error, "dictionary keys must have basic types");
           pattern_free (other_pattern);
@@ -1509,6 +1509,18 @@ terminal_get_value (AST                *ast,
         return g_variant_new_int32 (value);
       }
 
+    case G_VARIANT_TYPE_CLASS_HANDLE:
+      {
+        gint64 value;
+
+        if (!parse_signed (terminal->token,
+                           G_MININT32, G_MAXINT32,
+                           &value, ast, error))
+          return NULL;
+
+        return g_variant_new_handle (value);
+      }
+
     case G_VARIANT_TYPE_CLASS_UINT32:
       {
         guint64 value;
@@ -1912,6 +1924,9 @@ typedecl_parse (TokenStream *stream,
       else if (token_stream_consume (stream, "int32"))
         type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
 
+      else if (token_stream_consume (stream, "handle"))
+        type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
+
       else if (token_stream_consume (stream, "uint32"))
         type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
 
diff --git a/glib/gvariant-printer.c b/glib/gvariant-printer.c
index 63d6967..90e5fbd 100644
--- a/glib/gvariant-printer.c
+++ b/glib/gvariant-printer.c
@@ -1,6 +1,6 @@
 /*
- * Copyright © 2009, Sam Thursfield
- *
+ * Copyright © 2009 Sam Thursfield
+ * Copyright © 2009 Codethink Limited
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,6 +16,9 @@
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Sam Thursfield
+ *          Ryan Lortie <desrt desrt ca>
  */
 
 #include <math.h>
@@ -241,6 +244,13 @@ g_variant_print_string (GVariant *value,
                               g_variant_get_int32 (value));
       break;
 
+    case G_VARIANT_TYPE_CLASS_HANDLE:
+      if (type_annotate)
+        g_string_append (string, "handle ");
+      g_string_append_printf (string, "%"G_GINT32_FORMAT,
+                              g_variant_get_handle (value));
+      break;
+
     case G_VARIANT_TYPE_CLASS_UINT32:
       if (type_annotate)
         g_string_append (string, "uint32 ");
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
index 82f394b..0f28a01 100644
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -925,6 +925,7 @@ g_variant_serialised_is_normal (GVariantSerialised value)
     case G_VARIANT_TYPE_CLASS_INT16:
     case G_VARIANT_TYPE_CLASS_UINT16:
     case G_VARIANT_TYPE_CLASS_INT32:
+    case G_VARIANT_TYPE_CLASS_HANDLE:
     case G_VARIANT_TYPE_CLASS_UINT32:
     case G_VARIANT_TYPE_CLASS_INT64:
     case G_VARIANT_TYPE_CLASS_UINT64:
diff --git a/glib/gvariant-util.c b/glib/gvariant-util.c
index c963c93..88e5428 100644
--- a/glib/gvariant-util.c
+++ b/glib/gvariant-util.c
@@ -257,7 +257,7 @@ g_variant_new_byte (guint8 byte)
 /**
  * g_variant_new_int16:
  * @int16: a #gint16 value
- * @returns: a new byte #GVariant instance
+ * @returns: a new int16 #GVariant instance
  *
  * Creates a new int16 #GVariant instance.
  **/
@@ -271,7 +271,7 @@ g_variant_new_int16 (gint16 int16)
 /**
  * g_variant_new_uint16:
  * @uint16: a #guint16 value
- * @returns: a new byte #GVariant instance
+ * @returns: a new uint16 #GVariant instance
  *
  * Creates a new uint16 #GVariant instance.
  **/
@@ -285,7 +285,7 @@ g_variant_new_uint16 (guint16 uint16)
 /**
  * g_variant_new_int32:
  * @int32: a #gint32 value
- * @returns: a new byte #GVariant instance
+ * @returns: a new int32 #GVariant instance
  *
  * Creates a new int32 #GVariant instance.
  **/
@@ -297,6 +297,20 @@ g_variant_new_int32 (gint32 int32)
 }
 
 /**
+ * g_variant_new_handle:
+ * @handle: a #gint32 value
+ * @returns: a new handle #GVariant instance
+ *
+ * Creates a new int32 #GVariant instance.
+ **/
+GVariant *
+g_variant_new_handle (gint32 handle)
+{
+  return g_variant_load (G_VARIANT_TYPE_HANDLE,
+                         &handle, 4, G_VARIANT_TRUSTED);
+}
+
+/**
  * g_variant_new_uint32:
  * @uint32: a #guint32 value
  * @returns: a new uint32 #GVariant instance
@@ -313,7 +327,7 @@ g_variant_new_uint32 (guint32 uint32)
 /**
  * g_variant_new_int64:
  * @int64: a #gint64 value
- * @returns: a new byte #GVariant instance
+ * @returns: a new int64 #GVariant instance
  *
  * Creates a new int64 #GVariant instance.
  **/
@@ -478,7 +492,7 @@ g_variant_is_signature (const gchar *string)
   g_return_val_if_fail (string != NULL, FALSE);
 
   /* make sure no non-concrete characters appear */
-  first_invalid = strspn (string, "ybnqiuxtdvmasog(){}");
+  first_invalid = strspn (string, "ybnqihuxtdvmasog(){}");
   if (string[first_invalid])
     return FALSE;
 
@@ -624,6 +638,28 @@ g_variant_get_int32 (GVariant *value)
 }
 
 /**
+ * g_variant_get_handle:
+ * @value: a handle #GVariant instance
+ * @returns: a #gint32
+ *
+ * Returns the 32-bit signed integer value of @value.
+ *
+ * It is an error to call this function with a @value of any type
+ * other than %G_VARIANT_TYPE_HANDLE.
+ **/
+gint32
+g_variant_get_handle (GVariant *value)
+{
+  gint32 int32;
+
+  g_return_val_if_fail (value != NULL, 0);
+  g_assert (g_variant_matches (value, G_VARIANT_TYPE_HANDLE));
+  g_variant_store (value, &int32);
+
+  return int32;
+}
+
+/**
  * g_variant_get_uint32:
  * @value: a uint32 #GVariant instance
  * @returns: a #guint32
@@ -1795,6 +1831,9 @@ g_variant_deep_copy (GVariant *value)
         return new;
       }
 
+    case G_VARIANT_TYPE_CLASS_HANDLE:
+      return g_variant_new_handle (g_variant_get_handle (value));
+
     case G_VARIANT_TYPE_CLASS_MAYBE:
     case G_VARIANT_TYPE_CLASS_ARRAY:
     case G_VARIANT_TYPE_CLASS_TUPLE:
diff --git a/glib/gvariant-valist.c b/glib/gvariant-valist.c
index 0e302ab..747b577 100644
--- a/glib/gvariant-valist.c
+++ b/glib/gvariant-valist.c
@@ -97,7 +97,7 @@ g_variant_format_string_scan (const gchar  *string,
         string++;
 
       if (string == limit || *string == '\0' ||                    /* { */
-          !strchr ("bynqiuxtdsog?", *string++) ||                  /* key */
+          !strchr ("bynqihuxtdsog?", *string++) ||                  /* key */
           !g_variant_format_string_scan (string, limit, &string) ||/* value */
           string == limit || *string++ != '}')                     /* } */
         return FALSE;
@@ -124,7 +124,7 @@ g_variant_format_string_scan (const gchar  *string,
         start++;
 
       while (start != string)
-        if (!strchr ("bynqiuxtd(){}", *start++))
+        if (!strchr ("bynqihuxtd(){}", *start++))
           return FALSE;
 
       break;
@@ -143,7 +143,7 @@ g_variant_format_string_scan (const gchar  *string,
 
     case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
     case 'x': case 't': case 'd': case 's': case 'o': case 'g':
-    case 'v': case '*': case '?': case 'r':
+    case 'v': case '*': case '?': case 'r': case 'h':
       break;
 
     default:
@@ -230,6 +230,10 @@ g_variant_valist_new (const gchar **format_string,
       (*format_string)++;
       return g_variant_new_int32 (va_arg (*app, gint));
 
+    case 'h':
+      (*format_string)++;
+      return g_variant_new_handle (va_arg (*app, gint));
+
     case 'u':
       (*format_string)++;
       return g_variant_new_uint32 (va_arg (*app, guint));
@@ -555,6 +559,22 @@ g_variant_valist_get (GVariant     *value,
         return;
       }
 
+    case 'h':
+      {
+        gint32 *ptr = va_arg (*app, gint32 *);
+        
+        if (ptr)
+          {
+            if (value)
+              *ptr = g_variant_get_handle (value);
+            else
+              *ptr = 0;
+          }
+
+        (*format_string)++;
+        return;
+      }
+
     case 'u':
       {
         guint32 *ptr = va_arg (*app, guint32 *);
diff --git a/glib/gvariant.h b/glib/gvariant.h
index 01f3cca..83ec437 100644
--- a/glib/gvariant.h
+++ b/glib/gvariant.h
@@ -90,6 +90,7 @@ gboolean                        g_variant_is_object_path                (const g
 GVariant *                      g_variant_new_signature                 (const gchar          *string);
 gboolean                        g_variant_is_signature                  (const gchar          *string);
 GVariant *                      g_variant_new_variant                   (GVariant             *value);
+GVariant *                      g_variant_new_handle                    (gint32                handle);
 GVariant *                      g_variant_new_strv                      (const gchar * const  *strv,
                                                                          gint                  length);
 
@@ -112,6 +113,7 @@ const gchar **                  g_variant_get_strv                      (GVarian
 gchar **                        g_variant_dup_strv                      (GVariant             *value,
                                                                          gint                 *length);
 GVariant *                      g_variant_get_variant                   (GVariant             *value);
+gint32                          g_variant_get_handle                    (GVariant             *value);
 gconstpointer                   g_variant_get_fixed                     (GVariant             *value,
                                                                          gsize                 size);
 gconstpointer                   g_variant_get_fixed_array               (GVariant             *value,
diff --git a/glib/gvarianttype.c b/glib/gvarianttype.c
index 4651647..50f33f3 100644
--- a/glib/gvarianttype.c
+++ b/glib/gvarianttype.c
@@ -48,7 +48,7 @@
  *      | 'r' | '{' + base + type + '}' | '(' + types + ')'
  *
  * base = 'b' | 'y' | 'n' | 'q' | 'i' | 'u' | 'x'
- *      | 't' | 'd' | 's' | 'o' | 'g' | '?'
+ *      | 't' | 'd' | 's' | 'o' | 'g' | 'h' | '?'
  *
  * types = '' | type + types
  * </programlisting>
@@ -152,7 +152,7 @@ g_variant_type_string_scan (const gchar  *string,
 
     case '{':
       if (string == limit || *string == '\0' ||                    /* { */
-          !strchr ("bynqiuxtdsog?", *string++) ||                  /* key */
+          !strchr ("bynqihuxtdsog?", *string++) ||                 /* key */
           !g_variant_type_string_scan (string, limit, &string) ||  /* value */
           string == limit || *string++ != '}')                     /* } */
         return FALSE;
@@ -164,7 +164,7 @@ g_variant_type_string_scan (const gchar  *string,
 
     case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
     case 'x': case 't': case 'd': case 's': case 'o': case 'g':
-    case 'v': case 'r': case '*': case '?':
+    case 'v': case 'r': case '*': case '?': case 'h':
       break;
 
     default:
@@ -415,6 +415,7 @@ g_variant_type_is_basic (const GVariantType *type)
     case 'n':
     case 'q':
     case 'i':
+    case 'h':
     case 'u':
     case 't':
     case 'x':
@@ -669,6 +670,7 @@ g_variant_type_class_is_basic (GVariantTypeClass tclass)
     case G_VARIANT_TYPE_CLASS_INT16:
     case G_VARIANT_TYPE_CLASS_UINT16:
     case G_VARIANT_TYPE_CLASS_INT32:
+    case G_VARIANT_TYPE_CLASS_HANDLE:
     case G_VARIANT_TYPE_CLASS_UINT32:
     case G_VARIANT_TYPE_CLASS_INT64:
     case G_VARIANT_TYPE_CLASS_UINT64:
diff --git a/glib/gvarianttype.h b/glib/gvarianttype.h
index dcb0f49..80ed2f8 100644
--- a/glib/gvarianttype.h
+++ b/glib/gvarianttype.h
@@ -41,6 +41,7 @@ typedef struct   OPAQUE_TYPE_GVariantType   GVariantType;
  * @G_VARIANT_TYPE_CLASS_OBJECT_PATH: the class containing the type %G_VARIANT_TYPE_OBJECT_PATH
  * @G_VARIANT_TYPE_CLASS_SIGNATURE: the class containing the type %G_VARIANT_TYPE_SIGNATURE
  * @G_VARIANT_TYPE_CLASS_VARIANT: the class containing the type %G_VARIANT_TYPE_VARIANT
+ * @G_VARIANT_TYPE_CLASS_HANDLE: the class containing the type %G_VARIANT_TYPE_HANDLE
  * @G_VARIANT_TYPE_CLASS_MAYBE: the class containing all maybe types
  * @G_VARIANT_TYPE_CLASS_ARRAY: the class containing all array types
  * @G_VARIANT_TYPE_CLASS_TUPLE: the class containing all tuple types
@@ -82,9 +83,11 @@ typedef enum
 
   G_VARIANT_TYPE_CLASS_VARIANT            = 'v',
 
+  G_VARIANT_TYPE_CLASS_HANDLE             = 'h',
+
   G_VARIANT_TYPE_CLASS_MAYBE              = 'm',
   G_VARIANT_TYPE_CLASS_ARRAY              = 'a',
-  G_VARIANT_TYPE_CLASS_TUPLE             = 'r',
+  G_VARIANT_TYPE_CLASS_TUPLE              = 'r',
   G_VARIANT_TYPE_CLASS_DICT_ENTRY         = 'e',
 
   G_VARIANT_TYPE_CLASS_ALL                = '*',
@@ -203,6 +206,15 @@ typedef enum
 #define G_VARIANT_TYPE_VARIANT              ((const GVariantType *) "v")
 
 /**
+ * G_VARIANT_TYPE_HANDLE:
+ *
+ * The type of a 32bit signed integer value, that by convention, is used
+ * as an index into an array of file descriptors that are sent alongside
+ * a DBus message.
+ **/
+#define G_VARIANT_TYPE_HANDLE               ((const GVariantType *) "h")
+
+/**
  * G_VARIANT_TYPE_UNIT:
  *
  * The empty tuple type.  Has only one instance.  Known also as "triv"
diff --git a/glib/gvarianttypeinfo.c b/glib/gvarianttypeinfo.c
index 344f3d0..c896d32 100644
--- a/glib/gvarianttypeinfo.c
+++ b/glib/gvarianttypeinfo.c
@@ -334,6 +334,7 @@ base_info_new (const GVariantTypeClass class)
 
     case G_VARIANT_TYPE_CLASS_UINT32:
     case G_VARIANT_TYPE_CLASS_INT32:
+    case G_VARIANT_TYPE_CLASS_HANDLE:
       info->alignment = 4 - 1;
       info->fixed_size = 4;
       break;
diff --git a/glib/tests/.gitignore b/glib/tests/.gitignore
index a8e8597..6194648 100644
--- a/glib/tests/.gitignore
+++ b/glib/tests/.gitignore
@@ -13,6 +13,7 @@ tmpsample.xml
 gvariant-big
 gvariant-endian
 gvariant-fuzz
+gvariant-handle
 gvariant-markup
 gvariant-printer-parser
 gvariant-random
diff --git a/glib/tests/Makefile.am b/glib/tests/Makefile.am
index 659337a..f71e3bd 100644
--- a/glib/tests/Makefile.am
+++ b/glib/tests/Makefile.am
@@ -44,6 +44,9 @@ markup_subparser_LDADD    = $(progs_ldadd)
 TEST_PROGS         += array-test
 array_test_LDADD    = $(progs_ldadd)
 
+TEST_PROGS     += gvariant-handle
+gvariant_handle_LDADD    = $(progs_ldadd)
+
 TEST_PROGS     += gvariant-big
 gvariant_big_LDADD    = $(progs_ldadd)
 
diff --git a/glib/tests/gvariant-handle.c b/glib/tests/gvariant-handle.c
new file mode 100644
index 0000000..0a2e223
--- /dev/null
+++ b/glib/tests/gvariant-handle.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2009 Codethink Limited
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include <glib.h>
+
+static void
+test_handles (void)
+{
+  GVariant *handles;
+  const gint32 *hs;
+  gchar *str;
+  gint32 h;
+  gsize n;
+
+  handles = g_variant_new_parsed ("[6, 27, %h , -6, 77, %h , 0, 1]", 72, -1);
+  g_variant_ref_sink (handles);
+  str = g_variant_print (handles, TRUE);
+  g_variant_unref (handles);
+
+  g_assert_cmpstr (str, ==, "[handle 6, 27, 72, -6, 77, -1, 0, 1]");
+  handles = g_variant_new_parsed (str);
+  g_variant_ref_sink (handles);
+  g_free (str);
+
+  g_variant_get_child (handles, 2, "h", &h);
+  g_assert_cmpint (h, ==, 72);
+
+  g_variant_get_child (handles, 3, "h", &h);
+  g_assert_cmpint (h, ==, -6);
+
+  str = g_variant_markup_print (handles, 0, 0, 0);
+  g_assert_cmpstr ("<array><handle>6</handle><handle>27</handle><handle>72</handle><handle>-6</handle><handle>77</handle><handle>-1</handle><handle>0</handle><handle>1</handle></array>", ==, str);
+  g_variant_unref (handles);
+
+  handles = g_variant_markup_parse (str, -1, NULL, NULL);
+  g_free (str);
+
+  hs = g_variant_get_fixed_array (handles, sizeof *hs, &n);
+  g_assert_cmpint (n, ==, 8);
+  g_assert_cmpint (hs[0], ==, 6);
+  g_assert_cmpint (hs[1], ==, 27);
+  g_assert_cmpint (hs[2], ==, 72);
+  g_assert_cmpint (hs[3], ==, -6);
+  g_variant_unref (handles);
+}
+
+int
+main (int argc, char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add_func ("/variant/handles", test_handles);
+
+  return g_test_run ();
+}
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]