Fix g_autoptr_cleanup_gstring_free( ) argument to avoid of confliting arument name
[platform/upstream/glib.git] / gobject / tests / genmarshal.py
1 #!/usr/bin/python3
2 # -*- coding: utf-8 -*-
3 #
4 # Copyright © 2019 Endless Mobile, Inc.
5 #
6 # SPDX-License-Identifier: LGPL-2.1-or-later
7 #
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 # MA  02110-1301  USA
22
23 """Integration tests for glib-genmarshal utility."""
24
25 import collections
26 import os
27 import shutil
28 import subprocess
29 import sys
30 import tempfile
31 from textwrap import dedent
32 import unittest
33
34 import taptestrunner
35
36
37 # Disable line length warnings as wrapping the C code templates would be hard
38 # flake8: noqa: E501
39
40
41 Result = collections.namedtuple("Result", ("info", "out", "err", "subs"))
42
43
44 class TestGenmarshal(unittest.TestCase):
45     """Integration test for running glib-genmarshal.
46
47     This can be run when installed or uninstalled. When uninstalled, it
48     requires G_TEST_BUILDDIR and G_TEST_SRCDIR to be set.
49
50     The idea with this test harness is to test the glib-genmarshal utility, its
51     handling of command line arguments, its exit statuses, and its handling of
52     various marshaller lists. In future we could split the core glib-genmarshal
53     parsing and generation code out into a library and unit test that, and
54     convert this test to just check command line behaviour.
55     """
56
57     # Track the cwd, we want to back out to that to clean up our tempdir
58     cwd = ""
59
60     def setUp(self):
61         self.timeout_seconds = 10  # seconds per test
62         self.tmpdir = tempfile.TemporaryDirectory()
63         self.cwd = os.getcwd()
64         os.chdir(self.tmpdir.name)
65         print("tmpdir:", self.tmpdir.name)
66         if "G_TEST_BUILDDIR" in os.environ:
67             self.__genmarshal = os.path.join(
68                 os.environ["G_TEST_BUILDDIR"], "..", "glib-genmarshal"
69             )
70         else:
71             self.__genmarshal = shutil.which("glib-genmarshal")
72         print("genmarshal:", self.__genmarshal)
73
74     def tearDown(self):
75         os.chdir(self.cwd)
76         self.tmpdir.cleanup()
77
78     def runGenmarshal(self, *args):
79         argv = [self.__genmarshal]
80
81         # shebang lines are not supported on native
82         # Windows consoles
83         if os.name == "nt":
84             argv.insert(0, sys.executable)
85
86         argv.extend(args)
87         print("Running:", argv)
88
89         env = os.environ.copy()
90         env["LC_ALL"] = "C.UTF-8"
91         print("Environment:", env)
92
93         # We want to ensure consistent line endings...
94         info = subprocess.run(
95             argv,
96             timeout=self.timeout_seconds,
97             stdout=subprocess.PIPE,
98             stderr=subprocess.PIPE,
99             env=env,
100             universal_newlines=True,
101         )
102         info.check_returncode()
103         out = info.stdout.strip()
104         err = info.stderr.strip()
105
106         # Known substitutions for standard boilerplate
107         subs = {
108             "standard_top_comment": "This file is generated by glib-genmarshal, do not modify "
109             "it. This code is licensed under the same license as the "
110             "containing project. Note that it links to GLib, so must "
111             "comply with the LGPL linking clauses.",
112             "standard_top_pragma": dedent(
113                 """
114                 #ifndef __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__
115                 #define __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__
116                 """
117             ).strip(),
118             "standard_bottom_pragma": dedent(
119                 """
120                 #endif /* __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__ */
121                 """
122             ).strip(),
123             "standard_includes": dedent(
124                 """
125                 #include <glib-object.h>
126                 """
127             ).strip(),
128             "standard_marshal_peek_defines": dedent(
129                 """
130                 #ifdef G_ENABLE_DEBUG
131                 #define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
132                 #define g_marshal_value_peek_char(v)     g_value_get_schar (v)
133                 #define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
134                 #define g_marshal_value_peek_int(v)      g_value_get_int (v)
135                 #define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
136                 #define g_marshal_value_peek_long(v)     g_value_get_long (v)
137                 #define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
138                 #define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
139                 #define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
140                 #define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
141                 #define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
142                 #define g_marshal_value_peek_float(v)    g_value_get_float (v)
143                 #define g_marshal_value_peek_double(v)   g_value_get_double (v)
144                 #define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
145                 #define g_marshal_value_peek_param(v)    g_value_get_param (v)
146                 #define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
147                 #define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
148                 #define g_marshal_value_peek_object(v)   g_value_get_object (v)
149                 #define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
150                 #else /* !G_ENABLE_DEBUG */
151                 /* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
152                  *          Do not access GValues directly in your code. Instead, use the
153                  *          g_value_get_*() functions
154                  */
155                 #define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
156                 #define g_marshal_value_peek_char(v)     (v)->data[0].v_int
157                 #define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
158                 #define g_marshal_value_peek_int(v)      (v)->data[0].v_int
159                 #define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
160                 #define g_marshal_value_peek_long(v)     (v)->data[0].v_long
161                 #define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
162                 #define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
163                 #define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
164                 #define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
165                 #define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
166                 #define g_marshal_value_peek_float(v)    (v)->data[0].v_float
167                 #define g_marshal_value_peek_double(v)   (v)->data[0].v_double
168                 #define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
169                 #define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
170                 #define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
171                 #define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
172                 #define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
173                 #define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
174                 #endif /* !G_ENABLE_DEBUG */
175                 """
176             ).strip(),
177         }
178
179         result = Result(info, out, err, subs)
180
181         print("Output:", result.out)
182         return result
183
184     def runGenmarshalWithList(self, list_contents, *args):
185         with tempfile.NamedTemporaryFile(
186             dir=self.tmpdir.name, suffix=".list", delete=False
187         ) as list_file:
188             # Write out the list.
189             list_file.write(list_contents.encode("utf-8"))
190             print(list_file.name + ":", list_contents)
191             list_file.flush()
192
193             header_result = self.runGenmarshal(list_file.name, "--header", *args)
194             body_result = self.runGenmarshal(list_file.name, "--body", *args)
195
196             header_result.subs["list_path"] = list_file.name
197             body_result.subs["list_path"] = list_file.name
198
199             return (header_result, body_result)
200
201     def test_help(self):
202         """Test the --help argument."""
203         result = self.runGenmarshal("--help")
204         self.assertIn("usage: glib-genmarshal", result.out)
205
206     def test_no_args(self):
207         """Test running with no arguments at all."""
208         result = self.runGenmarshal()
209         self.assertEqual("", result.err)
210         self.assertEqual("", result.out)
211
212     def test_empty_list(self):
213         """Test running with an empty list."""
214         (header_result, body_result) = self.runGenmarshalWithList("", "--quiet")
215
216         self.assertEqual("", header_result.err)
217         self.assertEqual("", body_result.err)
218
219         self.assertEqual(
220             dedent(
221                 """
222             /* {standard_top_comment} */
223             {standard_top_pragma}
224
225             {standard_includes}
226
227             G_BEGIN_DECLS
228
229
230             G_END_DECLS
231
232             {standard_bottom_pragma}
233             """
234             )
235             .strip()
236             .format(**header_result.subs),
237             header_result.out.strip(),
238         )
239
240         self.assertEqual(
241             dedent(
242                 """
243             /* {standard_top_comment} */
244             {standard_includes}
245
246             {standard_marshal_peek_defines}
247             """
248             )
249             .strip()
250             .format(**body_result.subs),
251             body_result.out.strip(),
252         )
253
254     def test_void_boolean(self):
255         """Test running with a basic VOID:BOOLEAN list."""
256         (header_result, body_result) = self.runGenmarshalWithList(
257             "VOID:BOOLEAN", "--quiet"
258         )
259
260         self.assertEqual("", header_result.err)
261         self.assertEqual("", body_result.err)
262
263         self.assertEqual(
264             dedent(
265                 """
266             /* {standard_top_comment} */
267             {standard_top_pragma}
268
269             {standard_includes}
270
271             G_BEGIN_DECLS
272
273             /* VOID:BOOLEAN ({list_path}:1) */
274             #define g_cclosure_user_marshal_VOID__BOOLEAN       g_cclosure_marshal_VOID__BOOLEAN
275
276
277             G_END_DECLS
278
279             {standard_bottom_pragma}
280             """
281             )
282             .strip()
283             .format(**header_result.subs),
284             header_result.out.strip(),
285         )
286
287         self.assertEqual(
288             dedent(
289                 """
290             /* {standard_top_comment} */
291             {standard_includes}
292
293             {standard_marshal_peek_defines}
294             """
295             )
296             .strip()
297             .format(**body_result.subs),
298             body_result.out.strip(),
299         )
300
301     def test_void_boolean_int64(self):
302         """Test running with a non-trivial VOID:BOOLEAN,INT64 list."""
303         (header_result, body_result) = self.runGenmarshalWithList(
304             "VOID:BOOLEAN,INT64", "--quiet"
305         )
306
307         self.assertEqual("", header_result.err)
308         self.assertEqual("", body_result.err)
309
310         self.assertEqual(
311             dedent(
312                 """
313             /* {standard_top_comment} */
314             {standard_top_pragma}
315
316             {standard_includes}
317
318             G_BEGIN_DECLS
319
320             /* VOID:BOOLEAN,INT64 ({list_path}:1) */
321             extern
322             void g_cclosure_user_marshal_VOID__BOOLEAN_INT64 (GClosure     *closure,
323                                                               GValue       *return_value,
324                                                               guint         n_param_values,
325                                                               const GValue *param_values,
326                                                               gpointer      invocation_hint,
327                                                               gpointer      marshal_data);
328
329
330             G_END_DECLS
331
332             {standard_bottom_pragma}
333             """
334             )
335             .strip()
336             .format(**header_result.subs),
337             header_result.out.strip(),
338         )
339
340         self.assertEqual(
341             dedent(
342                 """
343             /* {standard_top_comment} */
344             {standard_includes}
345
346             {standard_marshal_peek_defines}
347
348             /* VOID:BOOLEAN,INT64 ({list_path}:1) */
349             void
350             g_cclosure_user_marshal_VOID__BOOLEAN_INT64 (GClosure     *closure,
351                                                          GValue       *return_value G_GNUC_UNUSED,
352                                                          guint         n_param_values,
353                                                          const GValue *param_values,
354                                                          gpointer      invocation_hint G_GNUC_UNUSED,
355                                                          gpointer      marshal_data)
356             {{
357               typedef void (*GMarshalFunc_VOID__BOOLEAN_INT64) (gpointer data1,
358                                                                 gboolean arg1,
359                                                                 gint64 arg2,
360                                                                 gpointer data2);
361               GCClosure *cc = (GCClosure *) closure;
362               gpointer data1, data2;
363               GMarshalFunc_VOID__BOOLEAN_INT64 callback;
364
365               g_return_if_fail (n_param_values == 3);
366
367               if (G_CCLOSURE_SWAP_DATA (closure))
368                 {{
369                   data1 = closure->data;
370                   data2 = g_value_peek_pointer (param_values + 0);
371                 }}
372               else
373                 {{
374                   data1 = g_value_peek_pointer (param_values + 0);
375                   data2 = closure->data;
376                 }}
377               callback = (GMarshalFunc_VOID__BOOLEAN_INT64) (marshal_data ? marshal_data : cc->callback);
378
379               callback (data1,
380                         g_marshal_value_peek_boolean (param_values + 1),
381                         g_marshal_value_peek_int64 (param_values + 2),
382                         data2);
383             }}
384             """
385             )
386             .strip()
387             .format(**body_result.subs),
388             body_result.out.strip(),
389         )
390
391     def test_void_variant_nostdinc_valist_marshaller(self):
392         """Test running with a basic VOID:VARIANT list, but without the
393         standard marshallers, and with valist support enabled. This checks that
394         the valist marshaller for VARIANT correctly sinks floating variants.
395
396         See issue #1793.
397         """
398         (header_result, body_result) = self.runGenmarshalWithList(
399             "VOID:VARIANT", "--quiet", "--nostdinc", "--valist-marshaller"
400         )
401
402         self.assertEqual("", header_result.err)
403         self.assertEqual("", body_result.err)
404
405         self.assertEqual(
406             dedent(
407                 """
408             /* {standard_top_comment} */
409             {standard_top_pragma}
410
411             G_BEGIN_DECLS
412
413             /* VOID:VARIANT ({list_path}:1) */
414             extern
415             void g_cclosure_user_marshal_VOID__VARIANT (GClosure     *closure,
416                                                         GValue       *return_value,
417                                                         guint         n_param_values,
418                                                         const GValue *param_values,
419                                                         gpointer      invocation_hint,
420                                                         gpointer      marshal_data);
421             extern
422             void g_cclosure_user_marshal_VOID__VARIANTv (GClosure *closure,
423                                                          GValue   *return_value,
424                                                          gpointer  instance,
425                                                          va_list   args,
426                                                          gpointer  marshal_data,
427                                                          int       n_params,
428                                                          GType    *param_types);
429
430
431             G_END_DECLS
432
433             {standard_bottom_pragma}
434             """
435             )
436             .strip()
437             .format(**header_result.subs),
438             header_result.out.strip(),
439         )
440
441         self.assertEqual(
442             dedent(
443                 """
444             /* {standard_top_comment} */
445             {standard_marshal_peek_defines}
446
447             /* VOID:VARIANT ({list_path}:1) */
448             void
449             g_cclosure_user_marshal_VOID__VARIANT (GClosure     *closure,
450                                                    GValue       *return_value G_GNUC_UNUSED,
451                                                    guint         n_param_values,
452                                                    const GValue *param_values,
453                                                    gpointer      invocation_hint G_GNUC_UNUSED,
454                                                    gpointer      marshal_data)
455             {{
456               typedef void (*GMarshalFunc_VOID__VARIANT) (gpointer data1,
457                                                           gpointer arg1,
458                                                           gpointer data2);
459               GCClosure *cc = (GCClosure *) closure;
460               gpointer data1, data2;
461               GMarshalFunc_VOID__VARIANT callback;
462
463               g_return_if_fail (n_param_values == 2);
464
465               if (G_CCLOSURE_SWAP_DATA (closure))
466                 {{
467                   data1 = closure->data;
468                   data2 = g_value_peek_pointer (param_values + 0);
469                 }}
470               else
471                 {{
472                   data1 = g_value_peek_pointer (param_values + 0);
473                   data2 = closure->data;
474                 }}
475               callback = (GMarshalFunc_VOID__VARIANT) (marshal_data ? marshal_data : cc->callback);
476
477               callback (data1,
478                         g_marshal_value_peek_variant (param_values + 1),
479                         data2);
480             }}
481
482             void
483             g_cclosure_user_marshal_VOID__VARIANTv (GClosure *closure,
484                                                     GValue   *return_value G_GNUC_UNUSED,
485                                                     gpointer  instance,
486                                                     va_list   args,
487                                                     gpointer  marshal_data,
488                                                     int       n_params,
489                                                     GType    *param_types)
490             {{
491               typedef void (*GMarshalFunc_VOID__VARIANT) (gpointer data1,
492                                                           gpointer arg1,
493                                                           gpointer data2);
494               GCClosure *cc = (GCClosure *) closure;
495               gpointer data1, data2;
496               GMarshalFunc_VOID__VARIANT callback;
497               gpointer arg0;
498               va_list args_copy;
499
500               va_copy (args_copy, args);
501               arg0 = (gpointer) va_arg (args_copy, gpointer);
502               if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
503                 arg0 = g_variant_ref_sink (arg0);
504               va_end (args_copy);
505
506
507               if (G_CCLOSURE_SWAP_DATA (closure))
508                 {{
509                   data1 = closure->data;
510                   data2 = instance;
511                 }}
512               else
513                 {{
514                   data1 = instance;
515                   data2 = closure->data;
516                 }}
517               callback = (GMarshalFunc_VOID__VARIANT) (marshal_data ? marshal_data : cc->callback);
518
519               callback (data1,
520                         arg0,
521                         data2);
522               if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
523                 g_variant_unref (arg0);
524             }}
525             """
526             )
527             .strip()
528             .format(**body_result.subs),
529             body_result.out.strip(),
530         )
531
532     def test_void_string_nostdinc(self):
533         """Test running with a basic VOID:STRING list, but without the
534         standard marshallers, and with valist support enabled. This checks that
535         the valist marshaller for STRING correctly skips a string copy if the
536         argument is static.
537
538         See issue #1792.
539         """
540         (header_result, body_result) = self.runGenmarshalWithList(
541             "VOID:STRING", "--quiet", "--nostdinc", "--valist-marshaller"
542         )
543
544         self.assertEqual("", header_result.err)
545         self.assertEqual("", body_result.err)
546
547         self.assertEqual(
548             dedent(
549                 """
550             /* {standard_top_comment} */
551             {standard_top_pragma}
552
553             G_BEGIN_DECLS
554
555             /* VOID:STRING ({list_path}:1) */
556             extern
557             void g_cclosure_user_marshal_VOID__STRING (GClosure     *closure,
558                                                        GValue       *return_value,
559                                                        guint         n_param_values,
560                                                        const GValue *param_values,
561                                                        gpointer      invocation_hint,
562                                                        gpointer      marshal_data);
563             extern
564             void g_cclosure_user_marshal_VOID__STRINGv (GClosure *closure,
565                                                         GValue   *return_value,
566                                                         gpointer  instance,
567                                                         va_list   args,
568                                                         gpointer  marshal_data,
569                                                         int       n_params,
570                                                         GType    *param_types);
571
572
573             G_END_DECLS
574
575             {standard_bottom_pragma}
576             """
577             )
578             .strip()
579             .format(**header_result.subs),
580             header_result.out.strip(),
581         )
582
583         self.assertEqual(
584             dedent(
585                 """
586             /* {standard_top_comment} */
587             {standard_marshal_peek_defines}
588
589             /* VOID:STRING ({list_path}:1) */
590             void
591             g_cclosure_user_marshal_VOID__STRING (GClosure     *closure,
592                                                   GValue       *return_value G_GNUC_UNUSED,
593                                                   guint         n_param_values,
594                                                   const GValue *param_values,
595                                                   gpointer      invocation_hint G_GNUC_UNUSED,
596                                                   gpointer      marshal_data)
597             {{
598               typedef void (*GMarshalFunc_VOID__STRING) (gpointer data1,
599                                                          gpointer arg1,
600                                                          gpointer data2);
601               GCClosure *cc = (GCClosure *) closure;
602               gpointer data1, data2;
603               GMarshalFunc_VOID__STRING callback;
604
605               g_return_if_fail (n_param_values == 2);
606
607               if (G_CCLOSURE_SWAP_DATA (closure))
608                 {{
609                   data1 = closure->data;
610                   data2 = g_value_peek_pointer (param_values + 0);
611                 }}
612               else
613                 {{
614                   data1 = g_value_peek_pointer (param_values + 0);
615                   data2 = closure->data;
616                 }}
617               callback = (GMarshalFunc_VOID__STRING) (marshal_data ? marshal_data : cc->callback);
618
619               callback (data1,
620                         g_marshal_value_peek_string (param_values + 1),
621                         data2);
622             }}
623
624             void
625             g_cclosure_user_marshal_VOID__STRINGv (GClosure *closure,
626                                                    GValue   *return_value G_GNUC_UNUSED,
627                                                    gpointer  instance,
628                                                    va_list   args,
629                                                    gpointer  marshal_data,
630                                                    int       n_params,
631                                                    GType    *param_types)
632             {{
633               typedef void (*GMarshalFunc_VOID__STRING) (gpointer data1,
634                                                          gpointer arg1,
635                                                          gpointer data2);
636               GCClosure *cc = (GCClosure *) closure;
637               gpointer data1, data2;
638               GMarshalFunc_VOID__STRING callback;
639               gpointer arg0;
640               va_list args_copy;
641
642               va_copy (args_copy, args);
643               arg0 = (gpointer) va_arg (args_copy, gpointer);
644               if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
645                 arg0 = g_strdup (arg0);
646               va_end (args_copy);
647
648
649               if (G_CCLOSURE_SWAP_DATA (closure))
650                 {{
651                   data1 = closure->data;
652                   data2 = instance;
653                 }}
654               else
655                 {{
656                   data1 = instance;
657                   data2 = closure->data;
658                 }}
659               callback = (GMarshalFunc_VOID__STRING) (marshal_data ? marshal_data : cc->callback);
660
661               callback (data1,
662                         arg0,
663                         data2);
664               if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
665                 g_free (arg0);
666             }}
667             """
668             )
669             .strip()
670             .format(**body_result.subs),
671             body_result.out.strip(),
672         )
673
674     def test_void_param_nostdinc(self):
675         """Test running with a basic VOID:PARAM list, but without the
676         standard marshallers, and with valist support enabled. This checks that
677         the valist marshaller for PARAM correctly skips a param copy if the
678         argument is static.
679
680         See issue #1792.
681         """
682         self.maxDiff = None  # TODO
683         (header_result, body_result) = self.runGenmarshalWithList(
684             "VOID:PARAM", "--quiet", "--nostdinc", "--valist-marshaller"
685         )
686
687         self.assertEqual("", header_result.err)
688         self.assertEqual("", body_result.err)
689
690         self.assertEqual(
691             dedent(
692                 """
693             /* {standard_top_comment} */
694             {standard_top_pragma}
695
696             G_BEGIN_DECLS
697
698             /* VOID:PARAM ({list_path}:1) */
699             extern
700             void g_cclosure_user_marshal_VOID__PARAM (GClosure     *closure,
701                                                       GValue       *return_value,
702                                                       guint         n_param_values,
703                                                       const GValue *param_values,
704                                                       gpointer      invocation_hint,
705                                                       gpointer      marshal_data);
706             extern
707             void g_cclosure_user_marshal_VOID__PARAMv (GClosure *closure,
708                                                        GValue   *return_value,
709                                                        gpointer  instance,
710                                                        va_list   args,
711                                                        gpointer  marshal_data,
712                                                        int       n_params,
713                                                        GType    *param_types);
714
715
716             G_END_DECLS
717
718             {standard_bottom_pragma}
719             """
720             )
721             .strip()
722             .format(**header_result.subs),
723             header_result.out.strip(),
724         )
725
726         self.assertEqual(
727             dedent(
728                 """
729             /* {standard_top_comment} */
730             {standard_marshal_peek_defines}
731
732             /* VOID:PARAM ({list_path}:1) */
733             void
734             g_cclosure_user_marshal_VOID__PARAM (GClosure     *closure,
735                                                  GValue       *return_value G_GNUC_UNUSED,
736                                                  guint         n_param_values,
737                                                  const GValue *param_values,
738                                                  gpointer      invocation_hint G_GNUC_UNUSED,
739                                                  gpointer      marshal_data)
740             {{
741               typedef void (*GMarshalFunc_VOID__PARAM) (gpointer data1,
742                                                         gpointer arg1,
743                                                         gpointer data2);
744               GCClosure *cc = (GCClosure *) closure;
745               gpointer data1, data2;
746               GMarshalFunc_VOID__PARAM callback;
747
748               g_return_if_fail (n_param_values == 2);
749
750               if (G_CCLOSURE_SWAP_DATA (closure))
751                 {{
752                   data1 = closure->data;
753                   data2 = g_value_peek_pointer (param_values + 0);
754                 }}
755               else
756                 {{
757                   data1 = g_value_peek_pointer (param_values + 0);
758                   data2 = closure->data;
759                 }}
760               callback = (GMarshalFunc_VOID__PARAM) (marshal_data ? marshal_data : cc->callback);
761
762               callback (data1,
763                         g_marshal_value_peek_param (param_values + 1),
764                         data2);
765             }}
766
767             void
768             g_cclosure_user_marshal_VOID__PARAMv (GClosure *closure,
769                                                   GValue   *return_value G_GNUC_UNUSED,
770                                                   gpointer  instance,
771                                                   va_list   args,
772                                                   gpointer  marshal_data,
773                                                   int       n_params,
774                                                   GType    *param_types)
775             {{
776               typedef void (*GMarshalFunc_VOID__PARAM) (gpointer data1,
777                                                         gpointer arg1,
778                                                         gpointer data2);
779               GCClosure *cc = (GCClosure *) closure;
780               gpointer data1, data2;
781               GMarshalFunc_VOID__PARAM callback;
782               gpointer arg0;
783               va_list args_copy;
784
785               va_copy (args_copy, args);
786               arg0 = (gpointer) va_arg (args_copy, gpointer);
787               if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
788                 arg0 = g_param_spec_ref (arg0);
789               va_end (args_copy);
790
791
792               if (G_CCLOSURE_SWAP_DATA (closure))
793                 {{
794                   data1 = closure->data;
795                   data2 = instance;
796                 }}
797               else
798                 {{
799                   data1 = instance;
800                   data2 = closure->data;
801                 }}
802               callback = (GMarshalFunc_VOID__PARAM) (marshal_data ? marshal_data : cc->callback);
803
804               callback (data1,
805                         arg0,
806                         data2);
807               if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
808                 g_param_spec_unref (arg0);
809             }}
810             """
811             )
812             .strip()
813             .format(**body_result.subs),
814             body_result.out.strip(),
815         )
816
817
818 if __name__ == "__main__":
819     unittest.main(testRunner=taptestrunner.TAPTestRunner())