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