| #!/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" | |
| env["G_DEBUG"] = "fatal-warnings" | |
| 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()) |