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