Merge branch 'gdbus-marshallers' into 'main'

gdbus-codegen: Generate specific marshallers for each required type

Closes #3028

See merge request GNOME/glib!3491
This commit is contained in:
Philip Withnall 2023-07-02 16:30:21 +00:00
commit 4ef693a457
8 changed files with 989 additions and 36 deletions

View File

@ -1138,7 +1138,7 @@ class InterfaceInfoBodyCodeGenerator:
"const %s * const %s[] =\n" % (element_type, array_name_lower)
)
self.outfile.write("{\n")
for (_, name) in elements:
for _, name in elements:
self.outfile.write(" &%s,\n" % name)
self.outfile.write(" NULL,\n")
self.outfile.write("};\n")
@ -1462,6 +1462,7 @@ class CodeGenerator:
self.glib_min_required = glib_min_required
self.symbol_decoration_define = symbol_decoration_define
self.outfile = outfile
self.marshallers = set()
# ----------------------------------------------------------------------------------------------------
@ -1486,6 +1487,55 @@ class CodeGenerator:
"#ifdef G_OS_UNIX\n" "# include <gio/gunixfdlist.h>\n" "#endif\n" "\n"
)
self.outfile.write(
"""#ifdef G_ENABLE_DEBUG
#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
#define g_marshal_value_peek_char(v) g_value_get_schar (v)
#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
#define g_marshal_value_peek_int(v) g_value_get_int (v)
#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
#define g_marshal_value_peek_long(v) g_value_get_long (v)
#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
#define g_marshal_value_peek_float(v) g_value_get_float (v)
#define g_marshal_value_peek_double(v) g_value_get_double (v)
#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
#define g_marshal_value_peek_param(v) g_value_get_param (v)
#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
#define g_marshal_value_peek_object(v) g_value_get_object (v)
#define g_marshal_value_peek_variant(v) g_value_get_variant (v)
#else /* !G_ENABLE_DEBUG */
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
* Do not access GValues directly in your code. Instead, use the
* g_value_get_*() functions
*/
#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
#define g_marshal_value_peek_char(v) (v)->data[0].v_int
#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
#define g_marshal_value_peek_int(v) (v)->data[0].v_int
#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
#define g_marshal_value_peek_long(v) (v)->data[0].v_long
#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_float(v) (v)->data[0].v_float
#define g_marshal_value_peek_double(v) (v)->data[0].v_double
#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
#endif /* !G_ENABLE_DEBUG */"""
"\n\n"
)
self.outfile.write(
"typedef struct\n"
"{\n"
@ -2136,7 +2186,7 @@ class CodeGenerator:
" G_STRUCT_OFFSET (%sIface, handle_%s),\n"
" g_signal_accumulator_true_handled,\n"
" NULL,\n" # accu_data
" g_cclosure_marshal_generic,\n"
f" {i.name_lower}_method_marshal_{m.name_lower},\n"
" G_TYPE_BOOLEAN,\n"
" %d,\n"
" G_TYPE_DBUS_METHOD_INVOCATION"
@ -2187,7 +2237,7 @@ class CodeGenerator:
" G_STRUCT_OFFSET (%sIface, %s),\n"
" NULL,\n" # accumulator
" NULL,\n" # accu_data
" g_cclosure_marshal_generic,\n"
f" {i.name_lower}_signal_marshal_{s.name_lower},\n"
" G_TYPE_NONE,\n"
" %d"
% (s.name_hyphen, i.camel_name, s.name_lower, len(s.args))
@ -2397,7 +2447,6 @@ class CodeGenerator:
self.outfile.write("}\n")
self.outfile.write("\n")
if p.arg.free_func is not None:
self.outfile.write(
self.docbook_gen.expand(
"/**\n"
@ -2526,6 +2575,159 @@ class CodeGenerator:
# ---------------------------------------------------------------------------------------------------
def generate_marshaller(self, func_name, in_args, ret_arg=None):
self.generate_marshaller_declaration(func_name, uses_ret=ret_arg is not None)
self.outfile.write("{\n")
self.generate_marshaller_body(func_name, in_args, ret_arg)
self.outfile.write("}\n" "\n")
def generate_marshaller_wrapper(self, wrapper_name, wrapped_func):
self.generate_marshaller_declaration(
wrapper_name,
uses_ret=True,
uses_hint=True,
inline=True,
)
self.outfile.write("{\n")
self.outfile.write(
f" {wrapped_func} (closure,\n"
" return_value, n_param_values, param_values, "
"invocation_hint, marshal_data);\n"
)
self.outfile.write("}\n" "\n")
def generate_marshaller_declaration(
self, func_name, uses_ret=False, uses_hint=False, inline=False
):
self.outfile.write(
f"{'inline ' if inline else ''}static void\n"
f"{func_name} (\n"
" GClosure *closure,\n"
f" GValue *return_value{' G_GNUC_UNUSED' if not uses_ret else ''},\n"
" unsigned int n_param_values,\n"
" const GValue *param_values,\n"
f" void *invocation_hint{' G_GNUC_UNUSED' if not uses_hint else ''},\n"
" void *marshal_data)\n"
)
def generate_marshaller_body(self, func_name, in_args=[], ret_arg=None):
marshal_func_type = f"{utils.uscore_to_camel_case(func_name)}Func"
self.outfile.write(
f" typedef {ret_arg.ctype_in if ret_arg else 'void '}(*{marshal_func_type})\n"
" (void *data1,\n"
+ "".join([f" {a.ctype_in}arg_{a.name},\n" for a in in_args])
+ " void *data2);\n"
f" {marshal_func_type} callback;\n"
" GCClosure *cc = (GCClosure*) closure;\n"
f" void *data1, *data2;\n"
)
if ret_arg:
self.outfile.write(
f" {ret_arg.ctype_in}v_return;\n"
"\n"
" g_return_if_fail (return_value != NULL);"
)
self.outfile.write(
"\n"
f" g_return_if_fail (n_param_values == {len(in_args) + 1});\n"
"\n"
" if (G_CCLOSURE_SWAP_DATA (closure))\n"
" {\n"
" data1 = closure->data;\n"
" data2 = g_value_peek_pointer (param_values + 0);\n"
" }\n"
" else\n"
" {\n"
" data1 = g_value_peek_pointer (param_values + 0);\n"
" data2 = closure->data;\n"
" }\n"
"\n"
f" callback = ({marshal_func_type})\n"
" (marshal_data ? marshal_data : cc->callback);\n"
"\n"
)
prefix = ""
if ret_arg:
self.outfile.write(" v_return =\n")
prefix = 2 * " "
self.outfile.write(
f"{prefix} callback (data1,\n"
+ "".join(
[
f"{prefix} {in_args[i].gvalue_get} (param_values + {i+1}),\n"
for i in range(len(in_args))
]
)
+ f"{prefix} data2);\n"
)
if ret_arg:
self.outfile.write(
"\n" f" {ret_arg.gvalue_set} (return_value, v_return);\n"
)
def generic_marshaller_name(self, args=[], ret=None):
name = "_g_dbus_codegen_marshal_"
name += f"{ret.gvalue_type.upper() if ret else 'VOID'}__"
if args:
name += "_".join(f"{a.gvalue_type.upper()}" for a in args)
else:
name += "VOID"
return name
def generic_marshaller_name_for_type(self, t):
assert isinstance(t, (dbustypes.Signal, dbustypes.Method))
if not t.marshaller_ret_arg:
if not t.marshaller_in_args:
return "g_cclosure_marshal_VOID__VOID"
elif (
len(t.marshaller_in_args) == 1
and t.marshaller_in_args[0].gclosure_marshaller
):
return t.marshaller_in_args[0].gclosure_marshaller
return self.generic_marshaller_name(t.marshaller_in_args, t.marshaller_ret_arg)
def generate_generic_marshallers(self, i):
for t in i.signals + i.methods:
marshaller_name = self.generic_marshaller_name_for_type(t)
if marshaller_name.startswith("g_cclosure_"):
self.marshallers.add(marshaller_name)
continue
if marshaller_name in self.marshallers:
continue
self.generate_marshaller(
marshaller_name, t.marshaller_in_args, t.marshaller_ret_arg
)
self.marshallers.add(marshaller_name)
def generate_marshaller_for_type(self, i, t):
assert isinstance(t, (dbustypes.Signal, dbustypes.Method))
kind_uscore = utils.camel_case_to_uscore(t.__class__.__name__.lower())
func_name = f"{i.name_lower}_{kind_uscore}_marshal_{t.name_lower}"
marshaller_name = self.generic_marshaller_name_for_type(t)
assert marshaller_name in self.marshallers
self.generate_marshaller_wrapper(func_name, marshaller_name)
def generate_signal_marshallers(self, i):
for s in i.signals:
self.generate_marshaller_for_type(i, s)
def generate_method_marshallers(self, i):
for m in i.methods:
self.generate_marshaller_for_type(i, m)
# ---------------------------------------------------------------------------------------------------
def generate_method_calls(self, i):
for m in i.methods:
# async begin
@ -5246,10 +5448,14 @@ class CodeGenerator:
def generate(self):
self.generate_body_preamble()
for i in self.ifaces:
self.generate_generic_marshallers(i)
for i in self.ifaces:
self.generate_interface_intro(i)
self.generate_signals_enum_for_interface(i)
self.generate_introspection_for_interface(i)
self.generate_signal_marshallers(i)
self.generate_method_marshallers(i)
self.generate_interface(i)
self.generate_property_accessors(i)
self.generate_signal_emitters(i)

View File

@ -119,7 +119,7 @@ def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
def apply_annotations(iface_list, annotation_list):
# apply annotations given on the command line
for (what, key, value) in annotation_list:
for what, key, value in annotation_list:
pos = what.find("::")
if pos != -1:
# signal

View File

@ -83,7 +83,10 @@ class Arg:
self.format_in = "@" + self.signature
self.format_out = "@" + self.signature
self.gvariant_get = "XXX"
self.gvalue_get = "g_value_get_variant"
self.gvalue_type = "variant"
self.gvalue_get = "g_marshal_value_peek_variant"
self.gvalue_set = "g_value_take_variant"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__VARIANT"
self.array_annotation = ""
if not utils.lookup_annotation(
@ -99,7 +102,10 @@ class Arg:
self.format_in = "b"
self.format_out = "b"
self.gvariant_get = "g_variant_get_boolean"
self.gvalue_get = "g_value_get_boolean"
self.gvalue_type = "boolean"
self.gvalue_get = "g_marshal_value_peek_boolean"
self.gvalue_set = "g_value_set_boolean"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOOLEAN"
elif self.signature == "y":
self.ctype_in_g = "guchar "
self.ctype_in = "guchar "
@ -110,7 +116,10 @@ class Arg:
self.format_in = "y"
self.format_out = "y"
self.gvariant_get = "g_variant_get_byte"
self.gvalue_get = "g_value_get_uchar"
self.gvalue_type = "uchar"
self.gvalue_get = "g_marshal_value_peek_uchar"
self.gvalue_set = "g_value_set_uchar"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__UCHAR"
elif self.signature == "n":
self.ctype_in_g = "gint "
self.ctype_in = "gint16 "
@ -121,7 +130,10 @@ class Arg:
self.format_in = "n"
self.format_out = "n"
self.gvariant_get = "g_variant_get_int16"
self.gvalue_get = "g_value_get_int"
self.gvalue_type = "int"
self.gvalue_get = "g_marshal_value_peek_int"
self.gvalue_set = "g_value_set_int"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__INT"
elif self.signature == "q":
self.ctype_in_g = "guint "
self.ctype_in = "guint16 "
@ -132,7 +144,10 @@ class Arg:
self.format_in = "q"
self.format_out = "q"
self.gvariant_get = "g_variant_get_uint16"
self.gvalue_get = "g_value_get_uint"
self.gvalue_type = "uint"
self.gvalue_get = "g_marshal_value_peek_uint"
self.gvalue_set = "g_value_set_uint"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__UINT"
elif self.signature == "i":
self.ctype_in_g = "gint "
self.ctype_in = "gint "
@ -143,7 +158,10 @@ class Arg:
self.format_in = "i"
self.format_out = "i"
self.gvariant_get = "g_variant_get_int32"
self.gvalue_get = "g_value_get_int"
self.gvalue_type = "int"
self.gvalue_get = "g_marshal_value_peek_int"
self.gvalue_set = "g_value_set_int"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__INT"
elif self.signature == "u":
self.ctype_in_g = "guint "
self.ctype_in = "guint "
@ -154,7 +172,10 @@ class Arg:
self.format_in = "u"
self.format_out = "u"
self.gvariant_get = "g_variant_get_uint32"
self.gvalue_get = "g_value_get_uint"
self.gvalue_type = "uint"
self.gvalue_get = "g_marshal_value_peek_uint"
self.gvalue_set = "g_value_set_uint"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__UINT"
elif self.signature == "x":
self.ctype_in_g = "gint64 "
self.ctype_in = "gint64 "
@ -165,7 +186,10 @@ class Arg:
self.format_in = "x"
self.format_out = "x"
self.gvariant_get = "g_variant_get_int64"
self.gvalue_get = "g_value_get_int64"
self.gvalue_type = "int64"
self.gvalue_get = "g_marshal_value_peek_int64"
self.gvalue_set = "g_value_set_int64"
self.gclosure_marshaller = None
elif self.signature == "t":
self.ctype_in_g = "guint64 "
self.ctype_in = "guint64 "
@ -176,7 +200,10 @@ class Arg:
self.format_in = "t"
self.format_out = "t"
self.gvariant_get = "g_variant_get_uint64"
self.gvalue_get = "g_value_get_uint64"
self.gvalue_type = "uint64"
self.gvalue_get = "g_marshal_value_peek_uint64"
self.gvalue_set = "g_value_set_uint64"
self.gclosure_marshaller = None
elif self.signature == "d":
self.ctype_in_g = "gdouble "
self.ctype_in = "gdouble "
@ -187,7 +214,10 @@ class Arg:
self.format_in = "d"
self.format_out = "d"
self.gvariant_get = "g_variant_get_double"
self.gvalue_get = "g_value_get_double"
self.gvalue_type = "double"
self.gvalue_get = "g_marshal_value_peek_double"
self.gvalue_set = "g_value_set_double"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__DOUBLE"
elif self.signature == "s":
self.ctype_in_g = "const gchar *"
self.ctype_in = "const gchar *"
@ -199,7 +229,10 @@ class Arg:
self.format_in = "s"
self.format_out = "s"
self.gvariant_get = "g_variant_get_string"
self.gvalue_get = "g_value_get_string"
self.gvalue_type = "string"
self.gvalue_get = "g_marshal_value_peek_string"
self.gvalue_set = "g_value_set_string"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
elif self.signature == "o":
self.ctype_in_g = "const gchar *"
self.ctype_in = "const gchar *"
@ -211,7 +244,10 @@ class Arg:
self.format_in = "o"
self.format_out = "o"
self.gvariant_get = "g_variant_get_string"
self.gvalue_get = "g_value_get_string"
self.gvalue_type = "string"
self.gvalue_get = "g_marshal_value_peek_string"
self.gvalue_set = "g_value_set_string"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
elif self.signature == "g":
self.ctype_in_g = "const gchar *"
self.ctype_in = "const gchar *"
@ -223,7 +259,10 @@ class Arg:
self.format_in = "g"
self.format_out = "g"
self.gvariant_get = "g_variant_get_string"
self.gvalue_get = "g_value_get_string"
self.gvalue_type = "string"
self.gvalue_get = "g_marshal_value_peek_string"
self.gvalue_set = "g_value_set_string"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
elif self.signature == "ay":
self.ctype_in_g = "const gchar *"
self.ctype_in = "const gchar *"
@ -235,7 +274,10 @@ class Arg:
self.format_in = "^ay"
self.format_out = "^ay"
self.gvariant_get = "g_variant_get_bytestring"
self.gvalue_get = "g_value_get_string"
self.gvalue_type = "string"
self.gvalue_get = "g_marshal_value_peek_string"
self.gvalue_set = "g_value_set_string"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__STRING"
elif self.signature == "as":
self.ctype_in_g = "const gchar *const *"
self.ctype_in = "const gchar *const *"
@ -247,7 +289,10 @@ class Arg:
self.format_in = "^as"
self.format_out = "^as"
self.gvariant_get = "g_variant_get_strv"
self.gvalue_get = "g_value_get_boxed"
self.gvalue_type = "boxed"
self.gvalue_get = "g_marshal_value_peek_boxed"
self.gvalue_set = "g_value_take_boxed"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOXED"
self.array_annotation = "(array zero-terminated=1)"
elif self.signature == "ao":
self.ctype_in_g = "const gchar *const *"
@ -260,7 +305,10 @@ class Arg:
self.format_in = "^ao"
self.format_out = "^ao"
self.gvariant_get = "g_variant_get_objv"
self.gvalue_get = "g_value_get_boxed"
self.gvalue_type = "boxed"
self.gvalue_get = "g_marshal_value_peek_boxed"
self.gvalue_set = "g_value_take_boxed"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOXED"
self.array_annotation = "(array zero-terminated=1)"
elif self.signature == "aay":
self.ctype_in_g = "const gchar *const *"
@ -273,7 +321,10 @@ class Arg:
self.format_in = "^aay"
self.format_out = "^aay"
self.gvariant_get = "g_variant_get_bytestring_array"
self.gvalue_get = "g_value_get_boxed"
self.gvalue_type = "boxed"
self.gvalue_get = "g_marshal_value_peek_boxed"
self.gvalue_set = "g_value_take_boxed"
self.gclosure_marshaller = "g_cclosure_marshal_VOID__BOXED"
self.array_annotation = "(array zero-terminated=1)"
for a in self.annotations:
@ -336,6 +387,24 @@ class Method:
if utils.lookup_annotation(self.annotations, "org.gtk.GDBus.C.UnixFD"):
self.unix_fd = True
self.marshaller_ret_arg = Arg("return", "b")
self.marshaller_ret_arg.post_process(None, None, None, None, None)
method_invocation_arg = Arg("method_invocation", None)
method_invocation_arg.ctype_in = "GDBusMethodInvocation *"
method_invocation_arg.gvalue_type = "object"
method_invocation_arg.gvalue_get = "g_marshal_value_peek_object"
method_invocation_arg.gclosure_marshaller = None
self.marshaller_in_args = [method_invocation_arg] + self.in_args
if self.unix_fd:
fd_list_arg = Arg("fd_list", None)
fd_list_arg.ctype_in = "GUnixFDList *"
fd_list_arg.gvalue_type = "object"
fd_list_arg.gvalue_get = "g_marshal_value_peek_object"
fd_list_arg.gclosure_marshaller = None
self.marshaller_in_args.insert(0, fd_list_arg)
for a in self.annotations:
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
@ -386,6 +455,9 @@ class Signal:
):
self.deprecated = True
self.marshaller_ret_arg = None
self.marshaller_in_args = self.args
for a in self.annotations:
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)

View File

@ -114,6 +114,10 @@ def camel_case_to_uscore(s):
return ret
def uscore_to_camel_case(s):
return "".join([s[0].upper() + s[1:].lower() if s else "_" for s in s.split("_")])
def is_ugly_case(s):
if s and s.find("_") > 0:
return True

View File

@ -60,6 +60,27 @@ class TestCodegen(unittest.TestCase):
# Track the cwd, we want to back out to that to clean up our tempdir
cwd = ""
ARGUMENTS_TYPES = {
"b": {"value_type": "boolean"},
"y": {"value_type": "uchar"},
"n": {"value_type": "int"},
"q": {"value_type": "uint"},
"i": {"value_type": "int"},
"u": {"value_type": "uint"},
"x": {"value_type": "int64", "lacks_marshaller": True},
"t": {"value_type": "uint64", "lacks_marshaller": True},
"d": {"value_type": "double"},
"s": {"value_type": "string"},
"o": {"value_type": "string"},
"g": {"value_type": "string"},
"h": {"value_type": "variant"},
"ay": {"value_type": "string"},
"as": {"value_type": "boxed"},
"ao": {"value_type": "boxed"},
"aay": {"value_type": "boxed"},
"asv": {"value_type": "variant", "variant_type": "a{sv}"},
}
def setUp(self):
self.timeout_seconds = 6 # seconds per test
self.tmpdir = tempfile.TemporaryDirectory()
@ -126,6 +147,51 @@ class TestCodegen(unittest.TestCase):
"#ifdef G_OS_UNIX\n"
"# include <gio/gunixfdlist.h>\n"
"#endif",
"private_gvalues_getters": """#ifdef G_ENABLE_DEBUG
#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
#define g_marshal_value_peek_char(v) g_value_get_schar (v)
#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
#define g_marshal_value_peek_int(v) g_value_get_int (v)
#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
#define g_marshal_value_peek_long(v) g_value_get_long (v)
#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
#define g_marshal_value_peek_float(v) g_value_get_float (v)
#define g_marshal_value_peek_double(v) g_value_get_double (v)
#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
#define g_marshal_value_peek_param(v) g_value_get_param (v)
#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
#define g_marshal_value_peek_object(v) g_value_get_object (v)
#define g_marshal_value_peek_variant(v) g_value_get_variant (v)
#else /* !G_ENABLE_DEBUG */
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
* Do not access GValues directly in your code. Instead, use the
* g_value_get_*() functions
*/
#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
#define g_marshal_value_peek_char(v) (v)->data[0].v_int
#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
#define g_marshal_value_peek_int(v) (v)->data[0].v_int
#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
#define g_marshal_value_peek_long(v) (v)->data[0].v_long
#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_float(v) (v)->data[0].v_float
#define g_marshal_value_peek_double(v) (v)->data[0].v_double
#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
#endif /* !G_ENABLE_DEBUG */""",
"standard_typedefs_and_helpers": "typedef struct\n"
"{\n"
" GDBusArgInfo parent_struct;\n"
@ -325,6 +391,8 @@ G_END_DECLS
{standard_header_includes}
{private_gvalues_getters}
{standard_typedefs_and_helpers}""".format(
**result.subs
),
@ -665,6 +733,521 @@ G_END_DECLS
self.assertEqual(result.out.strip().count("GDBusCallFlags call_flags,"), 2)
self.assertEqual(result.out.strip().count("gint timeout_msec,"), 2)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_signal_id_simple_signal(self):
"""Test that signals IDs are used to emit signals"""
interface_xml = """
<node>
<interface name="org.project.UsefulInterface">
<signal name="SimpleSignal"/>
</interface>
<interface name="org.project.OtherIface">
<signal name="SimpleSignal"/>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertIs(stripped_out.count("g_signal_emit_by_name ("), 0)
for iface in ["USEFUL_INTERFACE", "OTHER_IFACE"]:
enum_name = f"_ORG_PROJECT_{iface}_SIGNALS"
enum_item = f"_ORG_PROJECT_{iface}_SIMPLE_SIGNAL"
self.assertIs(stripped_out.count(f"{enum_item},"), 1)
self.assertIs(stripped_out.count(f"{enum_name}[{enum_item}] ="), 1)
self.assertIs(
stripped_out.count(
f" g_signal_emit (object, {enum_name}[{enum_item}], 0);"
),
1,
)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_signal_id_multiple_signals_types(self):
"""Test that signals IDs are used to emit signals for all types"""
signal_template = "<signal name='{}'><arg name='{}' type='{}'/></signal>"
generated_signals = [
signal_template.format(
f"SingleArgSignal{t.upper()}", f"an_{t}", props.get("variant_type", t)
)
for t, props in self.ARGUMENTS_TYPES.items()
]
interface_xml = f"""
<node>
<interface name="org.project.SignalingIface">
<signal name="NoArgSignal" />
{''.join(generated_signals)}
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertIs(stripped_out.count("g_signal_emit_by_name ("), 0)
iface = "SIGNALING_IFACE"
for t in self.ARGUMENTS_TYPES.keys():
enum_name = f"_ORG_PROJECT_{iface}_SIGNALS"
enum_item = f"_ORG_PROJECT_{iface}_SINGLE_ARG_SIGNAL_{t.upper()}"
self.assertIs(stripped_out.count(f"{enum_item},"), 1)
self.assertIs(stripped_out.count(f"{enum_name}[{enum_item}] ="), 1)
self.assertIs(
stripped_out.count(
f" g_signal_emit (object, {enum_name}[{enum_item}], 0, arg_an_{t});"
),
1,
)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_signal_id_multiple_signal_args_types(self):
"""Test that signals IDs are used to emit signals for all types"""
generated_args = [
f"<arg name='an_{t}' type='{props.get('variant_type', t)}'/>\n"
for t, props in self.ARGUMENTS_TYPES.items()
]
interface_xml = f"""
<node>
<interface name="org.project.SignalingIface">
<signal name="SignalWithManyArgs">
{''.join(generated_args)}
</signal>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertIs(stripped_out.count("g_signal_emit_by_name ("), 0)
iface = "SIGNALING_IFACE"
enum_name = f"_ORG_PROJECT_{iface}_SIGNALS"
enum_item = f"_ORG_PROJECT_{iface}_SIGNAL_WITH_MANY_ARGS"
self.assertIs(stripped_out.count(f"{enum_item},"), 1)
self.assertIs(stripped_out.count(f"{enum_name}[{enum_item}] ="), 1)
args = ", ".join([f"arg_an_{t}" for t in self.ARGUMENTS_TYPES.keys()])
self.assertIs(
stripped_out.count(
f" g_signal_emit (object, {enum_name}[{enum_item}], 0, {args});"
),
1,
)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_signals_marshaller_simple_signal(self):
"""Test that signals marshaller is generated for simple signal"""
interface_xml = """
<node>
<interface name="org.project.SignalingIface">
<signal name="SimpleSignal"/>
</interface>
<interface name="org.project.OtherSignalingIface">
<signal name="SimpleSignal"/>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertIs(stripped_out.count("g_cclosure_marshal_generic"), 0)
func_name = "org_project_signaling_iface_signal_marshal_simple_signal"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
self.assertIs(stripped_out.count("g_cclosure_marshal_VOID__VOID (closure"), 2)
func_name = "org_project_other_signaling_iface_signal_marshal_simple_signal"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
self.assertIs(stripped_out.count("g_cclosure_marshal_VOID__VOID (closure"), 2)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_signals_marshaller_single_typed_args(self):
"""Test that signals marshaller is generated for each known type"""
for t, props in self.ARGUMENTS_TYPES.items():
camel_type = t[0].upper() + t[1:]
interface_xml = f"""
<node>
<interface name="org.project.SignalingIface">
<signal name="SimpleSignal"/>
<signal name="SingleArgSignal{camel_type}">
<arg name="arg_{t}" type="{props.get("variant_type", t)}"/>
</signal>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertEqual(stripped_out.count("g_cclosure_marshal_generic"), 0)
self.assertIs(
stripped_out.count("g_cclosure_marshal_VOID__VOID (closure"), 1
)
func_name = (
f"org_project_signaling_iface_signal_marshal_single_arg_signal_{t}"
)
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
if props.get("lacks_marshaller", False):
self.assertIs(
stripped_out.count(
f"g_marshal_value_peek_{props['value_type']} (param_values + 1)"
),
1,
)
else:
self.assertIs(
stripped_out.count(
f"g_cclosure_marshal_VOID__{props['value_type'].upper()} (closure"
),
1,
)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_signals_marshallers_multiple_args(self):
"""Test that signals marshallers are generated"""
generated_args = [
f"<arg name='an_{t}' type='{props.get('variant_type', t)}'/>\n"
for t, props in self.ARGUMENTS_TYPES.items()
]
interface_xml = f"""
<node>
<interface name="org.project.SignalingIface">
<signal name="SimpleSignal"/>
<signal name="SignalWithManyArgs">
{''.join(generated_args)}
</signal>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertIs(stripped_out.count("g_cclosure_marshal_generic"), 0)
func_name = f"org_project_signaling_iface_signal_marshal_simple_signal"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
func_name = f"org_project_signaling_iface_signal_marshal_signal_with_many_args"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
# Check access to MultipleArgsSignal arguments
index = 1
for props in self.ARGUMENTS_TYPES.values():
self.assertIs(
stripped_out.count(
f"g_marshal_value_peek_{props['value_type']} (param_values + {index})"
),
1,
)
index += 1
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_methods_marshaller_simple_method(self):
"""Test that methods marshaller is generated for simple method"""
interface_xml = """
<node>
<interface name="org.project.CallableIface">
<method name="SimpleMethod"/>
</interface>
<interface name="org.project.OtherCallableIface">
<method name="SimpleMethod"/>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertIs(stripped_out.count("g_cclosure_marshal_generic"), 0)
func_name = "org_project_callable_iface_method_marshal_simple_method"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
func_name = "org_project_other_callable_iface_method_marshal_simple_method"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
self.assertIs(
stripped_out.count("g_marshal_value_peek_object (param_values + 1)"), 1
)
self.assertIs(
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 1
)
self.assertIs(
stripped_out.count(
"_g_dbus_codegen_marshal_BOOLEAN__OBJECT (\n GClosure"
),
1,
)
self.assertIs(
stripped_out.count("_g_dbus_codegen_marshal_BOOLEAN__OBJECT (closure"), 2
)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_methods_marshaller_single_typed_in_args(self):
"""Test that methods marshallers are generated for each known type"""
for t, props in self.ARGUMENTS_TYPES.items():
camel_type = t[0].upper() + t[1:]
interface_xml = f"""
<node>
<interface name="org.project.UsefulInterface">
<method name="SingleArgMethod{camel_type}">
<arg name="arg_{t}" type="{props.get("variant_type", t)}"/>
</method>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertEqual(stripped_out.count("g_cclosure_marshal_generic"), 0)
func_name = (
f"org_project_useful_interface_method_marshal_single_arg_method_{t}"
)
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
self.assertIs(
stripped_out.count("g_marshal_value_peek_object (param_values + 1)"), 1
)
self.assertIs(
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 1
)
self.assertIs(
stripped_out.count(
f"g_marshal_value_peek_{props['value_type']} (param_values + 2)"
),
1,
)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_methods_marshaller_single_typed_out_args(self):
"""Test that methods marshallers are generated for each known type"""
for t, props in self.ARGUMENTS_TYPES.items():
camel_type = t[0].upper() + t[1:]
interface_xml = f"""
<node>
<interface name="org.project.UsefulInterface">
<method name="SingleArgMethod{camel_type}">
<arg name="arg_{t}" type="{props.get("variant_type", t)}" direction="out"/>
</method>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertEqual(stripped_out.count("g_cclosure_marshal_generic"), 0)
func_name = (
f"org_project_useful_interface_method_marshal_single_arg_method_{t}"
)
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
self.assertIs(
stripped_out.count("g_marshal_value_peek_object (param_values + 1)"), 1
)
self.assertIs(
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 1
)
self.assertIs(stripped_out.count("(param_values + 2)"), 0)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_methods_marshallers_multiple_in_args(self):
"""Test that methods marshallers are generated"""
generated_args = [
f"<arg name='an_{t}' type='{props.get('variant_type', t)}'/>\n"
for t, props in self.ARGUMENTS_TYPES.items()
]
interface_xml = f"""
<node>
<interface name="org.project.CallableIface">
<method name="MethodWithManyArgs">
{''.join(generated_args)}
</method>
<method name="SameMethodWithManyArgs">
{''.join(generated_args)}
</method>
</interface>
<interface name="org.project.OtherCallableIface">
<method name="MethodWithManyArgs">
{''.join(generated_args)}
</method>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertIs(stripped_out.count("g_cclosure_marshal_generic"), 0)
func_name = f"org_project_callable_iface_method_marshal_method_with_many_args"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
# Check access to MultipleArgsMethod arguments
index = 1
self.assertIs(
stripped_out.count(f"g_marshal_value_peek_object (param_values + {index})"),
1,
)
index += 1
for props in self.ARGUMENTS_TYPES.values():
self.assertIs(
stripped_out.count(
f"g_marshal_value_peek_{props['value_type']} (param_values + {index})"
),
1,
)
index += 1
self.assertIs(
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 1
)
func_types = "_".join(
[p["value_type"].upper() for p in self.ARGUMENTS_TYPES.values()]
)
func_name = f"_g_dbus_codegen_marshal_BOOLEAN__OBJECT_{func_types}"
self.assertIs(stripped_out.count(f"{func_name} (\n GClosure"), 1)
self.assertIs(stripped_out.count(f"{func_name} (closure"), 3)
func_name = (
f"org_project_other_callable_iface_method_marshal_method_with_many_args"
)
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_methods_marshallers_multiple_out_args(self):
"""Test that methods marshallers are generated"""
generated_args = [
f"<arg name='an_{t}' type='{props.get('variant_type', t)}' direction='out'/>\n"
for t, props in self.ARGUMENTS_TYPES.items()
]
interface_xml = f"""
<node>
<interface name="org.project.CallableIface">
<method name="MethodWithManyArgs">
{''.join(generated_args)}
</method>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertIs(stripped_out.count("g_cclosure_marshal_generic"), 0)
func_name = f"org_project_callable_iface_method_marshal_method_with_many_args"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
# Check access to MultipleArgsMethod arguments
index = 1
self.assertIs(
stripped_out.count(f"g_marshal_value_peek_object (param_values + {index})"),
1,
)
index += 1
for index in range(index, len(self.ARGUMENTS_TYPES)):
self.assertIs(stripped_out.count(f"(param_values + {index})"), 0)
self.assertIs(
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 1
)
self.assertIs(
stripped_out.count("_g_dbus_codegen_marshal_BOOLEAN__OBJECT (closure"),
1,
)
@unittest.skipIf(on_win32(), "requires /dev/stdout")
def test_generate_methods_marshallers_with_unix_fds(self):
"""Test an interface with `h` arguments"""
interface_xml = """
<node>
<interface name="test.FDPassing">
<method name="HelloFD">
<annotation name="org.gtk.GDBus.C.UnixFD" value="1"/>
<arg name="greeting" direction="in" type="s"/>
<arg name="response" direction="out" type="s"/>
</method>
</interface>
</node>"""
result = self.runCodegenWithInterface(
interface_xml, "--output", "/dev/stdout", "--body"
)
stripped_out = result.out.strip()
self.assertFalse(result.err)
self.assertIs(stripped_out.count("g_cclosure_marshal_generic"), 0)
func_name = f"test_fdpassing_method_marshal_hello_fd"
self.assertIs(stripped_out.count(f"{func_name},"), 1)
self.assertIs(stripped_out.count(f"{func_name} ("), 1)
index = 1
self.assertIs(
stripped_out.count(f"g_marshal_value_peek_object (param_values + {index})"),
1,
)
index += 1
self.assertIs(
stripped_out.count(f"g_marshal_value_peek_object (param_values + {index})"),
1,
)
index += 1
self.assertIs(
stripped_out.count(f"g_marshal_value_peek_string (param_values + {index})"),
1,
)
index += 1
self.assertIs(
stripped_out.count("g_value_set_boolean (return_value, v_return);"), 1
)
def test_generate_valid_docbook(self):
"""Test the basic functionality of the docbook generator."""
xml_contents = """

View File

@ -26,6 +26,7 @@
#include <stdio.h>
#include "gdbus-tests.h"
#include "gstdio.h"
#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64
#include "gdbus-test-codegen-generated-min-required-2-64.h"
@ -410,6 +411,22 @@ on_handle_check_not_authorized_from_object (FooiGenAuthorize *object,
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
static gboolean
on_handle_fdpassing_hello_fd (FooiGenMethodThreads *object,
GDBusMethodInvocation *invocation,
GUnixFDList *fd_list,
const gchar *greeting,
gpointer user_data)
{
g_assert_true (G_IS_UNIX_FD_LIST (fd_list));
g_assert_cmpuint (g_unix_fd_list_get_length (fd_list), ==, 2);
g_assert_cmpstr (greeting, ==, "Hey fd!");
foo_igen_test_fdpassing_complete_hello_fd (FOO_IGEN_TEST_FDPASSING (object),
invocation, fd_list,
"I love to receive fds!");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
@ -430,6 +447,7 @@ static GThread *method_handler_thread = NULL;
static FooiGenBar *exported_bar_object = NULL;
static FooiGenBat *exported_bat_object = NULL;
static FooiGenTestFDPassing *exported_fd_passing_object = NULL;
static FooiGenAuthorize *exported_authorize_object = NULL;
static GDBusObjectSkeleton *authorize_enclosing_object = NULL;
static FooiGenMethodThreads *exported_thread_object_1 = NULL;
@ -443,6 +461,7 @@ unexport_objects (void)
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (exported_authorize_object));
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (exported_thread_object_1));
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (exported_thread_object_2));
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (exported_fd_passing_object));
}
static void
@ -584,6 +603,17 @@ on_bus_acquired (GDBusConnection *connection,
g_assert_cmpint (g_dbus_interface_skeleton_get_flags (G_DBUS_INTERFACE_SKELETON (exported_thread_object_2)), ==, G_DBUS_INTERFACE_SKELETON_FLAGS_NONE);
exported_fd_passing_object = foo_igen_test_fdpassing_skeleton_new ();
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (exported_fd_passing_object),
connection,
"/fdpassing",
&error);
g_assert_no_error (error);
g_signal_connect (exported_fd_passing_object,
"handle-hello-fd",
G_CALLBACK (on_handle_fdpassing_hello_fd),
NULL);
method_handler_thread = g_thread_self ();
}
@ -1125,6 +1155,45 @@ check_bar_proxy (FooiGenBar *proxy,
g_variant_unref (array_of_signatures);
}
static void
check_fdpassing_proxy (FooiGenTestFDPassing *proxy)
{
GError *error = NULL;
GUnixFDList *fd_list = g_unix_fd_list_new ();
GUnixFDList *ret_fd_list = NULL;
char *response = NULL;
int fd;
fd = dup (0);
g_assert_cmpint (g_unix_fd_list_append (fd_list, fd, &error), ==, 0);
g_assert_no_error (error);
g_close (fd, &error);
g_assert_no_error (error);
fd = dup (0);
g_assert_cmpint (g_unix_fd_list_append (fd_list, fd, &error), ==, 1);
g_assert_no_error (error);
g_close (fd, &error);
g_assert_no_error (error);
foo_igen_test_fdpassing_call_hello_fd_sync (proxy, "Hey fd!",
#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64
G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
#endif
fd_list,
&response, &ret_fd_list, NULL,
&error);
g_assert_no_error (error);
g_assert_true (G_IS_UNIX_FD_LIST (ret_fd_list));
g_assert_cmpuint (g_unix_fd_list_get_length (fd_list), ==, 2);
g_assert_cmpstr (response, ==, "I love to receive fds!");
g_clear_pointer (&response, g_free);
g_clear_object (&fd_list);
g_clear_object (&ret_fd_list);
}
/* ---------------------------------------------------------------------------------------------------- */
static void
@ -1309,6 +1378,7 @@ check_proxies_in_thread (gpointer user_data)
GError *error;
FooiGenBar *bar_proxy;
FooiGenBat *bat_proxy;
FooiGenTestFDPassing *fd_passing_proxy;
FooiGenAuthorize *authorize_proxy;
FooiGenMethodThreads *thread_proxy_1;
FooiGenMethodThreads *thread_proxy_2;
@ -1370,6 +1440,16 @@ check_proxies_in_thread (gpointer user_data)
g_object_unref (thread_proxy_1);
g_object_unref (thread_proxy_2);
fd_passing_proxy = foo_igen_test_fdpassing_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
"org.gtk.GDBus.BindingsTool.Test",
"/fdpassing",
NULL, /* GCancellable* */
&error);
g_assert_no_error (error);
check_fdpassing_proxy (fd_passing_proxy);
g_object_unref (fd_passing_proxy);
/* Wait for the proxy signals to all be unsubscribed. */
while (g_main_context_iteration (thread_context, FALSE))
{
@ -2650,53 +2730,53 @@ test_standalone_interface_info (void)
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
handle_hello_fd (FooiGenFDPassing *object,
handle_hello_fd (FooiGenTestFDPassing *object,
GDBusMethodInvocation *invocation,
GUnixFDList *fd_list,
const gchar *arg_greeting)
{
foo_igen_fdpassing_complete_hello_fd (object, invocation, fd_list, arg_greeting);
foo_igen_test_fdpassing_complete_hello_fd (object, invocation, fd_list, arg_greeting);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_64
static gboolean
handle_no_annotation (FooiGenFDPassing *object,
handle_no_annotation (FooiGenTestFDPassing *object,
GDBusMethodInvocation *invocation,
GUnixFDList *fd_list,
GVariant *arg_greeting,
const gchar *arg_greeting_locale)
{
foo_igen_fdpassing_complete_no_annotation (object, invocation, fd_list, arg_greeting, arg_greeting_locale);
foo_igen_test_fdpassing_complete_no_annotation (object, invocation, fd_list, arg_greeting, arg_greeting_locale);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
static gboolean
handle_no_annotation_nested (FooiGenFDPassing *object,
handle_no_annotation_nested (FooiGenTestFDPassing *object,
GDBusMethodInvocation *invocation,
GUnixFDList *fd_list,
GVariant *arg_files)
{
foo_igen_fdpassing_complete_no_annotation_nested (object, invocation, fd_list);
foo_igen_test_fdpassing_complete_no_annotation_nested (object, invocation, fd_list);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
#else
static gboolean
handle_no_annotation (FooiGenFDPassing *object,
handle_no_annotation (FooiGenTestFDPassing *object,
GDBusMethodInvocation *invocation,
GVariant *arg_greeting,
const gchar *arg_greeting_locale)
{
foo_igen_fdpassing_complete_no_annotation (object, invocation, arg_greeting, arg_greeting_locale);
foo_igen_test_fdpassing_complete_no_annotation (object, invocation, arg_greeting, arg_greeting_locale);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
static gboolean
handle_no_annotation_nested (FooiGenFDPassing *object,
handle_no_annotation_nested (FooiGenTestFDPassing *object,
GDBusMethodInvocation *invocation,
GVariant *arg_files)
{
foo_igen_fdpassing_complete_no_annotation_nested (object, invocation);
foo_igen_test_fdpassing_complete_no_annotation_nested (object, invocation);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
#endif
@ -2709,7 +2789,7 @@ handle_no_annotation_nested (FooiGenFDPassing *object,
static void
test_unix_fd_list (void)
{
FooiGenFDPassingIface iface;
FooiGenTestFDPassingIface iface;
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1726");

View File

@ -170,7 +170,11 @@ test_extra_programs = {
python_tests = {
# FIXME: https://gitlab.gnome.org/GNOME/glib/-/issues/2764
'codegen.py' : { 'can_fail' : host_system == 'freebsd' },
'codegen.py' : {
'can_fail' : host_system == 'freebsd',
'suite': ['gdbus-codegen', 'slow'],
'timeout': 90,
},
}
test_env = environment()
@ -458,6 +462,7 @@ if host_machine.system() != 'windows'
'gdbus-test-codegen' : {
'extra_sources' : [extra_sources, gdbus_test_codegen_generated, gdbus_test_codegen_generated_interface_info],
'c_args' : ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_32'],
'suite': ['gdbus-codegen'],
},
'gdbus-threading' : {
'extra_sources' : extra_sources,
@ -476,11 +481,13 @@ if host_machine.system() != 'windows'
'extra_sources' : [extra_sources, gdbus_test_codegen_generated, gdbus_test_codegen_generated_interface_info],
'c_args' : ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_36',
'-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_36'],
'suite': ['gdbus-codegen'],
},
'gdbus-test-codegen-min-required-2-64' : {
'source' : 'gdbus-test-codegen.c',
'extra_sources' : [extra_sources, gdbus_test_codegen_generated_min_required_2_64, gdbus_test_codegen_generated_interface_info],
'c_args' : ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_64'],
'suite': ['gdbus-codegen'],
},
'gapplication' : {
'extra_sources' : extra_sources,
@ -1045,7 +1052,7 @@ endforeach
foreach test_name, extra_args : python_tests
depends = [extra_args.get('depends', [])]
suite = ['gio', 'no-valgrind']
suite = ['gio', 'no-valgrind'] + extra_args.get('suite', [])
if extra_args.get('can_fail', false)
suite += 'failing'
@ -1062,6 +1069,7 @@ foreach test_name, extra_args : python_tests
depends: depends,
args: ['-B', files(test_name)],
env: test_env,
timeout: extra_args.get('timeout'),
suite: suite,
)

View File

@ -475,7 +475,7 @@
</interface>
<unknownTag/>
<interface name="FDPassing">
<interface name="test.FDPassing">
<method name="HelloFD">
<annotation name="org.gtk.GDBus.C.UnixFD" value="1"/>
<arg name="greeting" direction="in" type="s"/>