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