mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56:14 +01:00
65016fddd9
Signed-off-by: Simon McVittie <smcv@collabora.com>
820 lines
32 KiB
Python
820 lines
32 KiB
Python
#!/usr/bin/python3
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright © 2019 Endless Mobile, Inc.
|
|
#
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
#
|
|
# This library is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
# License as published by the Free Software Foundation; either
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
#
|
|
# This library is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with this library; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
# MA 02110-1301 USA
|
|
|
|
"""Integration tests for glib-genmarshal utility."""
|
|
|
|
import collections
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from textwrap import dedent
|
|
import unittest
|
|
|
|
import taptestrunner
|
|
|
|
|
|
# Disable line length warnings as wrapping the C code templates would be hard
|
|
# flake8: noqa: E501
|
|
|
|
|
|
Result = collections.namedtuple("Result", ("info", "out", "err", "subs"))
|
|
|
|
|
|
class TestGenmarshal(unittest.TestCase):
|
|
"""Integration test for running glib-genmarshal.
|
|
|
|
This can be run when installed or uninstalled. When uninstalled, it
|
|
requires G_TEST_BUILDDIR and G_TEST_SRCDIR to be set.
|
|
|
|
The idea with this test harness is to test the glib-genmarshal utility, its
|
|
handling of command line arguments, its exit statuses, and its handling of
|
|
various marshaller lists. In future we could split the core glib-genmarshal
|
|
parsing and generation code out into a library and unit test that, and
|
|
convert this test to just check command line behaviour.
|
|
"""
|
|
|
|
# Track the cwd, we want to back out to that to clean up our tempdir
|
|
cwd = ""
|
|
|
|
def setUp(self):
|
|
self.timeout_seconds = 10 # seconds per test
|
|
self.tmpdir = tempfile.TemporaryDirectory()
|
|
self.cwd = os.getcwd()
|
|
os.chdir(self.tmpdir.name)
|
|
print("tmpdir:", self.tmpdir.name)
|
|
if "G_TEST_BUILDDIR" in os.environ:
|
|
self.__genmarshal = os.path.join(
|
|
os.environ["G_TEST_BUILDDIR"], "..", "glib-genmarshal"
|
|
)
|
|
else:
|
|
self.__genmarshal = shutil.which("glib-genmarshal")
|
|
print("genmarshal:", self.__genmarshal)
|
|
|
|
def tearDown(self):
|
|
os.chdir(self.cwd)
|
|
self.tmpdir.cleanup()
|
|
|
|
def runGenmarshal(self, *args):
|
|
argv = [self.__genmarshal]
|
|
|
|
# shebang lines are not supported on native
|
|
# Windows consoles
|
|
if os.name == "nt":
|
|
argv.insert(0, sys.executable)
|
|
|
|
argv.extend(args)
|
|
print("Running:", argv)
|
|
|
|
env = os.environ.copy()
|
|
env["LC_ALL"] = "C.UTF-8"
|
|
print("Environment:", env)
|
|
|
|
# We want to ensure consistent line endings...
|
|
info = subprocess.run(
|
|
argv,
|
|
timeout=self.timeout_seconds,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
env=env,
|
|
universal_newlines=True,
|
|
)
|
|
info.check_returncode()
|
|
out = info.stdout.strip()
|
|
err = info.stderr.strip()
|
|
|
|
# Known substitutions for standard boilerplate
|
|
subs = {
|
|
"standard_top_comment": "This file is generated by glib-genmarshal, do not modify "
|
|
"it. This code is licensed under the same license as the "
|
|
"containing project. Note that it links to GLib, so must "
|
|
"comply with the LGPL linking clauses.",
|
|
"standard_top_pragma": dedent(
|
|
"""
|
|
#ifndef __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__
|
|
#define __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__
|
|
"""
|
|
).strip(),
|
|
"standard_bottom_pragma": dedent(
|
|
"""
|
|
#endif /* __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__ */
|
|
"""
|
|
).strip(),
|
|
"standard_includes": dedent(
|
|
"""
|
|
#include <glib-object.h>
|
|
"""
|
|
).strip(),
|
|
"standard_marshal_peek_defines": dedent(
|
|
"""
|
|
#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 */
|
|
"""
|
|
).strip(),
|
|
}
|
|
|
|
result = Result(info, out, err, subs)
|
|
|
|
print("Output:", result.out)
|
|
return result
|
|
|
|
def runGenmarshalWithList(self, list_contents, *args):
|
|
with tempfile.NamedTemporaryFile(
|
|
dir=self.tmpdir.name, suffix=".list", delete=False
|
|
) as list_file:
|
|
# Write out the list.
|
|
list_file.write(list_contents.encode("utf-8"))
|
|
print(list_file.name + ":", list_contents)
|
|
list_file.flush()
|
|
|
|
header_result = self.runGenmarshal(list_file.name, "--header", *args)
|
|
body_result = self.runGenmarshal(list_file.name, "--body", *args)
|
|
|
|
header_result.subs["list_path"] = list_file.name
|
|
body_result.subs["list_path"] = list_file.name
|
|
|
|
return (header_result, body_result)
|
|
|
|
def test_help(self):
|
|
"""Test the --help argument."""
|
|
result = self.runGenmarshal("--help")
|
|
self.assertIn("usage: glib-genmarshal", result.out)
|
|
|
|
def test_no_args(self):
|
|
"""Test running with no arguments at all."""
|
|
result = self.runGenmarshal()
|
|
self.assertEqual("", result.err)
|
|
self.assertEqual("", result.out)
|
|
|
|
def test_empty_list(self):
|
|
"""Test running with an empty list."""
|
|
(header_result, body_result) = self.runGenmarshalWithList("", "--quiet")
|
|
|
|
self.assertEqual("", header_result.err)
|
|
self.assertEqual("", body_result.err)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_top_pragma}
|
|
|
|
{standard_includes}
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
|
|
G_END_DECLS
|
|
|
|
{standard_bottom_pragma}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**header_result.subs),
|
|
header_result.out.strip(),
|
|
)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_includes}
|
|
|
|
{standard_marshal_peek_defines}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**body_result.subs),
|
|
body_result.out.strip(),
|
|
)
|
|
|
|
def test_void_boolean(self):
|
|
"""Test running with a basic VOID:BOOLEAN list."""
|
|
(header_result, body_result) = self.runGenmarshalWithList(
|
|
"VOID:BOOLEAN", "--quiet"
|
|
)
|
|
|
|
self.assertEqual("", header_result.err)
|
|
self.assertEqual("", body_result.err)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_top_pragma}
|
|
|
|
{standard_includes}
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
/* VOID:BOOLEAN ({list_path}:1) */
|
|
#define g_cclosure_user_marshal_VOID__BOOLEAN g_cclosure_marshal_VOID__BOOLEAN
|
|
|
|
|
|
G_END_DECLS
|
|
|
|
{standard_bottom_pragma}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**header_result.subs),
|
|
header_result.out.strip(),
|
|
)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_includes}
|
|
|
|
{standard_marshal_peek_defines}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**body_result.subs),
|
|
body_result.out.strip(),
|
|
)
|
|
|
|
def test_void_boolean_int64(self):
|
|
"""Test running with a non-trivial VOID:BOOLEAN,INT64 list."""
|
|
(header_result, body_result) = self.runGenmarshalWithList(
|
|
"VOID:BOOLEAN,INT64", "--quiet"
|
|
)
|
|
|
|
self.assertEqual("", header_result.err)
|
|
self.assertEqual("", body_result.err)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_top_pragma}
|
|
|
|
{standard_includes}
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
/* VOID:BOOLEAN,INT64 ({list_path}:1) */
|
|
extern
|
|
void g_cclosure_user_marshal_VOID__BOOLEAN_INT64 (GClosure *closure,
|
|
GValue *return_value,
|
|
guint n_param_values,
|
|
const GValue *param_values,
|
|
gpointer invocation_hint,
|
|
gpointer marshal_data);
|
|
|
|
|
|
G_END_DECLS
|
|
|
|
{standard_bottom_pragma}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**header_result.subs),
|
|
header_result.out.strip(),
|
|
)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_includes}
|
|
|
|
{standard_marshal_peek_defines}
|
|
|
|
/* VOID:BOOLEAN,INT64 ({list_path}:1) */
|
|
void
|
|
g_cclosure_user_marshal_VOID__BOOLEAN_INT64 (GClosure *closure,
|
|
GValue *return_value G_GNUC_UNUSED,
|
|
guint n_param_values,
|
|
const GValue *param_values,
|
|
gpointer invocation_hint G_GNUC_UNUSED,
|
|
gpointer marshal_data)
|
|
{{
|
|
typedef void (*GMarshalFunc_VOID__BOOLEAN_INT64) (gpointer data1,
|
|
gboolean arg1,
|
|
gint64 arg2,
|
|
gpointer data2);
|
|
GCClosure *cc = (GCClosure *) closure;
|
|
gpointer data1, data2;
|
|
GMarshalFunc_VOID__BOOLEAN_INT64 callback;
|
|
|
|
g_return_if_fail (n_param_values == 3);
|
|
|
|
if (G_CCLOSURE_SWAP_DATA (closure))
|
|
{{
|
|
data1 = closure->data;
|
|
data2 = g_value_peek_pointer (param_values + 0);
|
|
}}
|
|
else
|
|
{{
|
|
data1 = g_value_peek_pointer (param_values + 0);
|
|
data2 = closure->data;
|
|
}}
|
|
callback = (GMarshalFunc_VOID__BOOLEAN_INT64) (marshal_data ? marshal_data : cc->callback);
|
|
|
|
callback (data1,
|
|
g_marshal_value_peek_boolean (param_values + 1),
|
|
g_marshal_value_peek_int64 (param_values + 2),
|
|
data2);
|
|
}}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**body_result.subs),
|
|
body_result.out.strip(),
|
|
)
|
|
|
|
def test_void_variant_nostdinc_valist_marshaller(self):
|
|
"""Test running with a basic VOID:VARIANT list, but without the
|
|
standard marshallers, and with valist support enabled. This checks that
|
|
the valist marshaller for VARIANT correctly sinks floating variants.
|
|
|
|
See issue #1793.
|
|
"""
|
|
(header_result, body_result) = self.runGenmarshalWithList(
|
|
"VOID:VARIANT", "--quiet", "--nostdinc", "--valist-marshaller"
|
|
)
|
|
|
|
self.assertEqual("", header_result.err)
|
|
self.assertEqual("", body_result.err)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_top_pragma}
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
/* VOID:VARIANT ({list_path}:1) */
|
|
extern
|
|
void g_cclosure_user_marshal_VOID__VARIANT (GClosure *closure,
|
|
GValue *return_value,
|
|
guint n_param_values,
|
|
const GValue *param_values,
|
|
gpointer invocation_hint,
|
|
gpointer marshal_data);
|
|
extern
|
|
void g_cclosure_user_marshal_VOID__VARIANTv (GClosure *closure,
|
|
GValue *return_value,
|
|
gpointer instance,
|
|
va_list args,
|
|
gpointer marshal_data,
|
|
int n_params,
|
|
GType *param_types);
|
|
|
|
|
|
G_END_DECLS
|
|
|
|
{standard_bottom_pragma}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**header_result.subs),
|
|
header_result.out.strip(),
|
|
)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_marshal_peek_defines}
|
|
|
|
/* VOID:VARIANT ({list_path}:1) */
|
|
void
|
|
g_cclosure_user_marshal_VOID__VARIANT (GClosure *closure,
|
|
GValue *return_value G_GNUC_UNUSED,
|
|
guint n_param_values,
|
|
const GValue *param_values,
|
|
gpointer invocation_hint G_GNUC_UNUSED,
|
|
gpointer marshal_data)
|
|
{{
|
|
typedef void (*GMarshalFunc_VOID__VARIANT) (gpointer data1,
|
|
gpointer arg1,
|
|
gpointer data2);
|
|
GCClosure *cc = (GCClosure *) closure;
|
|
gpointer data1, data2;
|
|
GMarshalFunc_VOID__VARIANT callback;
|
|
|
|
g_return_if_fail (n_param_values == 2);
|
|
|
|
if (G_CCLOSURE_SWAP_DATA (closure))
|
|
{{
|
|
data1 = closure->data;
|
|
data2 = g_value_peek_pointer (param_values + 0);
|
|
}}
|
|
else
|
|
{{
|
|
data1 = g_value_peek_pointer (param_values + 0);
|
|
data2 = closure->data;
|
|
}}
|
|
callback = (GMarshalFunc_VOID__VARIANT) (marshal_data ? marshal_data : cc->callback);
|
|
|
|
callback (data1,
|
|
g_marshal_value_peek_variant (param_values + 1),
|
|
data2);
|
|
}}
|
|
|
|
void
|
|
g_cclosure_user_marshal_VOID__VARIANTv (GClosure *closure,
|
|
GValue *return_value G_GNUC_UNUSED,
|
|
gpointer instance,
|
|
va_list args,
|
|
gpointer marshal_data,
|
|
int n_params,
|
|
GType *param_types)
|
|
{{
|
|
typedef void (*GMarshalFunc_VOID__VARIANT) (gpointer data1,
|
|
gpointer arg1,
|
|
gpointer data2);
|
|
GCClosure *cc = (GCClosure *) closure;
|
|
gpointer data1, data2;
|
|
GMarshalFunc_VOID__VARIANT callback;
|
|
gpointer arg0;
|
|
va_list args_copy;
|
|
|
|
va_copy (args_copy, args);
|
|
arg0 = (gpointer) va_arg (args_copy, gpointer);
|
|
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
|
arg0 = g_variant_ref_sink (arg0);
|
|
va_end (args_copy);
|
|
|
|
|
|
if (G_CCLOSURE_SWAP_DATA (closure))
|
|
{{
|
|
data1 = closure->data;
|
|
data2 = instance;
|
|
}}
|
|
else
|
|
{{
|
|
data1 = instance;
|
|
data2 = closure->data;
|
|
}}
|
|
callback = (GMarshalFunc_VOID__VARIANT) (marshal_data ? marshal_data : cc->callback);
|
|
|
|
callback (data1,
|
|
arg0,
|
|
data2);
|
|
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
|
g_variant_unref (arg0);
|
|
}}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**body_result.subs),
|
|
body_result.out.strip(),
|
|
)
|
|
|
|
def test_void_string_nostdinc(self):
|
|
"""Test running with a basic VOID:STRING list, but without the
|
|
standard marshallers, and with valist support enabled. This checks that
|
|
the valist marshaller for STRING correctly skips a string copy if the
|
|
argument is static.
|
|
|
|
See issue #1792.
|
|
"""
|
|
(header_result, body_result) = self.runGenmarshalWithList(
|
|
"VOID:STRING", "--quiet", "--nostdinc", "--valist-marshaller"
|
|
)
|
|
|
|
self.assertEqual("", header_result.err)
|
|
self.assertEqual("", body_result.err)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_top_pragma}
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
/* VOID:STRING ({list_path}:1) */
|
|
extern
|
|
void g_cclosure_user_marshal_VOID__STRING (GClosure *closure,
|
|
GValue *return_value,
|
|
guint n_param_values,
|
|
const GValue *param_values,
|
|
gpointer invocation_hint,
|
|
gpointer marshal_data);
|
|
extern
|
|
void g_cclosure_user_marshal_VOID__STRINGv (GClosure *closure,
|
|
GValue *return_value,
|
|
gpointer instance,
|
|
va_list args,
|
|
gpointer marshal_data,
|
|
int n_params,
|
|
GType *param_types);
|
|
|
|
|
|
G_END_DECLS
|
|
|
|
{standard_bottom_pragma}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**header_result.subs),
|
|
header_result.out.strip(),
|
|
)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_marshal_peek_defines}
|
|
|
|
/* VOID:STRING ({list_path}:1) */
|
|
void
|
|
g_cclosure_user_marshal_VOID__STRING (GClosure *closure,
|
|
GValue *return_value G_GNUC_UNUSED,
|
|
guint n_param_values,
|
|
const GValue *param_values,
|
|
gpointer invocation_hint G_GNUC_UNUSED,
|
|
gpointer marshal_data)
|
|
{{
|
|
typedef void (*GMarshalFunc_VOID__STRING) (gpointer data1,
|
|
gpointer arg1,
|
|
gpointer data2);
|
|
GCClosure *cc = (GCClosure *) closure;
|
|
gpointer data1, data2;
|
|
GMarshalFunc_VOID__STRING callback;
|
|
|
|
g_return_if_fail (n_param_values == 2);
|
|
|
|
if (G_CCLOSURE_SWAP_DATA (closure))
|
|
{{
|
|
data1 = closure->data;
|
|
data2 = g_value_peek_pointer (param_values + 0);
|
|
}}
|
|
else
|
|
{{
|
|
data1 = g_value_peek_pointer (param_values + 0);
|
|
data2 = closure->data;
|
|
}}
|
|
callback = (GMarshalFunc_VOID__STRING) (marshal_data ? marshal_data : cc->callback);
|
|
|
|
callback (data1,
|
|
g_marshal_value_peek_string (param_values + 1),
|
|
data2);
|
|
}}
|
|
|
|
void
|
|
g_cclosure_user_marshal_VOID__STRINGv (GClosure *closure,
|
|
GValue *return_value G_GNUC_UNUSED,
|
|
gpointer instance,
|
|
va_list args,
|
|
gpointer marshal_data,
|
|
int n_params,
|
|
GType *param_types)
|
|
{{
|
|
typedef void (*GMarshalFunc_VOID__STRING) (gpointer data1,
|
|
gpointer arg1,
|
|
gpointer data2);
|
|
GCClosure *cc = (GCClosure *) closure;
|
|
gpointer data1, data2;
|
|
GMarshalFunc_VOID__STRING callback;
|
|
gpointer arg0;
|
|
va_list args_copy;
|
|
|
|
va_copy (args_copy, args);
|
|
arg0 = (gpointer) va_arg (args_copy, gpointer);
|
|
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
|
arg0 = g_strdup (arg0);
|
|
va_end (args_copy);
|
|
|
|
|
|
if (G_CCLOSURE_SWAP_DATA (closure))
|
|
{{
|
|
data1 = closure->data;
|
|
data2 = instance;
|
|
}}
|
|
else
|
|
{{
|
|
data1 = instance;
|
|
data2 = closure->data;
|
|
}}
|
|
callback = (GMarshalFunc_VOID__STRING) (marshal_data ? marshal_data : cc->callback);
|
|
|
|
callback (data1,
|
|
arg0,
|
|
data2);
|
|
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
|
g_free (arg0);
|
|
}}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**body_result.subs),
|
|
body_result.out.strip(),
|
|
)
|
|
|
|
def test_void_param_nostdinc(self):
|
|
"""Test running with a basic VOID:PARAM list, but without the
|
|
standard marshallers, and with valist support enabled. This checks that
|
|
the valist marshaller for PARAM correctly skips a param copy if the
|
|
argument is static.
|
|
|
|
See issue #1792.
|
|
"""
|
|
self.maxDiff = None # TODO
|
|
(header_result, body_result) = self.runGenmarshalWithList(
|
|
"VOID:PARAM", "--quiet", "--nostdinc", "--valist-marshaller"
|
|
)
|
|
|
|
self.assertEqual("", header_result.err)
|
|
self.assertEqual("", body_result.err)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_top_pragma}
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
/* VOID:PARAM ({list_path}:1) */
|
|
extern
|
|
void g_cclosure_user_marshal_VOID__PARAM (GClosure *closure,
|
|
GValue *return_value,
|
|
guint n_param_values,
|
|
const GValue *param_values,
|
|
gpointer invocation_hint,
|
|
gpointer marshal_data);
|
|
extern
|
|
void g_cclosure_user_marshal_VOID__PARAMv (GClosure *closure,
|
|
GValue *return_value,
|
|
gpointer instance,
|
|
va_list args,
|
|
gpointer marshal_data,
|
|
int n_params,
|
|
GType *param_types);
|
|
|
|
|
|
G_END_DECLS
|
|
|
|
{standard_bottom_pragma}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**header_result.subs),
|
|
header_result.out.strip(),
|
|
)
|
|
|
|
self.assertEqual(
|
|
dedent(
|
|
"""
|
|
/* {standard_top_comment} */
|
|
{standard_marshal_peek_defines}
|
|
|
|
/* VOID:PARAM ({list_path}:1) */
|
|
void
|
|
g_cclosure_user_marshal_VOID__PARAM (GClosure *closure,
|
|
GValue *return_value G_GNUC_UNUSED,
|
|
guint n_param_values,
|
|
const GValue *param_values,
|
|
gpointer invocation_hint G_GNUC_UNUSED,
|
|
gpointer marshal_data)
|
|
{{
|
|
typedef void (*GMarshalFunc_VOID__PARAM) (gpointer data1,
|
|
gpointer arg1,
|
|
gpointer data2);
|
|
GCClosure *cc = (GCClosure *) closure;
|
|
gpointer data1, data2;
|
|
GMarshalFunc_VOID__PARAM callback;
|
|
|
|
g_return_if_fail (n_param_values == 2);
|
|
|
|
if (G_CCLOSURE_SWAP_DATA (closure))
|
|
{{
|
|
data1 = closure->data;
|
|
data2 = g_value_peek_pointer (param_values + 0);
|
|
}}
|
|
else
|
|
{{
|
|
data1 = g_value_peek_pointer (param_values + 0);
|
|
data2 = closure->data;
|
|
}}
|
|
callback = (GMarshalFunc_VOID__PARAM) (marshal_data ? marshal_data : cc->callback);
|
|
|
|
callback (data1,
|
|
g_marshal_value_peek_param (param_values + 1),
|
|
data2);
|
|
}}
|
|
|
|
void
|
|
g_cclosure_user_marshal_VOID__PARAMv (GClosure *closure,
|
|
GValue *return_value G_GNUC_UNUSED,
|
|
gpointer instance,
|
|
va_list args,
|
|
gpointer marshal_data,
|
|
int n_params,
|
|
GType *param_types)
|
|
{{
|
|
typedef void (*GMarshalFunc_VOID__PARAM) (gpointer data1,
|
|
gpointer arg1,
|
|
gpointer data2);
|
|
GCClosure *cc = (GCClosure *) closure;
|
|
gpointer data1, data2;
|
|
GMarshalFunc_VOID__PARAM callback;
|
|
gpointer arg0;
|
|
va_list args_copy;
|
|
|
|
va_copy (args_copy, args);
|
|
arg0 = (gpointer) va_arg (args_copy, gpointer);
|
|
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
|
arg0 = g_param_spec_ref (arg0);
|
|
va_end (args_copy);
|
|
|
|
|
|
if (G_CCLOSURE_SWAP_DATA (closure))
|
|
{{
|
|
data1 = closure->data;
|
|
data2 = instance;
|
|
}}
|
|
else
|
|
{{
|
|
data1 = instance;
|
|
data2 = closure->data;
|
|
}}
|
|
callback = (GMarshalFunc_VOID__PARAM) (marshal_data ? marshal_data : cc->callback);
|
|
|
|
callback (data1,
|
|
arg0,
|
|
data2);
|
|
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
|
g_param_spec_unref (arg0);
|
|
}}
|
|
"""
|
|
)
|
|
.strip()
|
|
.format(**body_result.subs),
|
|
body_result.out.strip(),
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|