1#!/usr/local/bin/python3.8 2# -*- coding: ascii -*- 3# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab 4# 5"""Simple test suite using unittest. 6By clach04 (Chris Clark). 7 8Calling: 9 10 python test/testsuite.py 11 12or 13 cd test 14 ./testsuite.py 15 16Could use any unitest compatible test runner (nose, etc.) 17 18Aims to test for regressions. Where possible use stdlib to 19avoid the need to compile C code. 20 21Known to run clean with: 22 * 32bit Linux (python 2.5.2, 2.6) 23 * 32bit Windows XP (python 2.4, 2.5, 2.6.1) 24""" 25 26import sys 27import os 28import ctypes 29import math 30import unittest 31import logging 32from subprocess import Popen, PIPE 33 34test_directory = os.path.abspath(os.path.dirname(__file__)) 35sys.path.append(test_directory) 36sys.path.append(os.path.join(test_directory, os.pardir)) 37 38import ctypesgentest # TODO consider moving test() from ctypesgentest into this module 39 40 41def cleanup_json_src_paths(json): 42 """ 43 JSON stores the path to some source items. These need to be genericized in 44 order for tests to succeed on all machines/user accounts. 45 """ 46 TYPES_W_PATHS = ["CtypesStruct", "CtypesEnum"] 47 for i in json: 48 if "ctype" in i and i["ctype"]["Klass"] in TYPES_W_PATHS: 49 i["ctype"]["src"][0] = "/some-path/temp.h" 50 51 52def compare_json(test_instance, json, json_ans, verbose=False): 53 print_excess = False 54 try: 55 test_instance.assertEqual(len(json), len(json_ans)) 56 except: 57 if verbose: 58 print( 59 "JSONs do not have same length: ", 60 len(json), 61 "generated vs", 62 len(json_ans), 63 "stored", 64 ) 65 print_excess = True 66 else: 67 raise 68 69 # first fix paths that exist inside JSON to avoid user-specific paths: 70 for i, ith_json_ans in zip(json, json_ans): 71 try: 72 test_instance.assertEqual(i, ith_json_ans) 73 except: 74 if verbose: 75 print("\nFailed JSON for: ", i["name"]) 76 print("GENERATED:\n", i, "\nANS:\n", ith_json_ans) 77 raise 78 79 if print_excess: 80 if len(json) > len(json_ans): 81 j, jlen, jlabel = json, len(json_ans), "generated" 82 else: 83 j, jlen, jlabel = json_ans, len(json), "stored" 84 import pprint 85 86 print("Excess JSON content from", jlabel, "content:") 87 pprint.pprint(j[jlen:]) 88 89 90def compute_packed(modulo, fields): 91 packs = [ 92 ( 93 modulo * int(ctypes.sizeof(f) / modulo) 94 + modulo * (1 if (ctypes.sizeof(f) % modulo) else 0) 95 ) 96 for f in fields 97 ] 98 return sum(packs) 99 100 101class StdlibTest(unittest.TestCase): 102 def setUp(self): 103 """NOTE this is called once for each test* method 104 (it is not called once per class). 105 FIXME This is slightly inefficient as it is called *way* more times than it needs to be. 106 """ 107 header_str = "#include <stdlib.h>\n" 108 if sys.platform == "win32": 109 # pick something from %windir%\system32\msvc*dll that include stdlib 110 libraries = ["msvcrt.dll"] 111 libraries = ["msvcrt"] 112 elif sys.platform.startswith("linux"): 113 libraries = ["libc.so.6"] 114 else: 115 libraries = ["libc"] 116 self.module, output = ctypesgentest.test(header_str, libraries=libraries, all_headers=True) 117 118 def tearDown(self): 119 del self.module 120 ctypesgentest.cleanup() 121 122 def test_getenv_returns_string(self): 123 """Issue 8 - Regression for crash with 64 bit and bad strings on 32 bit. 124 See http://code.google.com/p/ctypesgen/issues/detail?id=8 125 Test that we get a valid (non-NULL, non-empty) string back 126 """ 127 module = self.module 128 129 if sys.platform == "win32": 130 # Check a variable that is already set 131 env_var_name = ( 132 "USERNAME" 133 ) # this is always set (as is windir, ProgramFiles, USERPROFILE, etc.) 134 expect_result = os.environ[env_var_name] 135 self.assertTrue(expect_result, "this should not be None or empty") 136 # reason for using an existing OS variable is that unless the 137 # MSVCRT dll imported is the exact same one that Python was 138 # built with you can't share structures, see 139 # http://msdn.microsoft.com/en-us/library/ms235460.aspx 140 # "Potential Errors Passing CRT Objects Across DLL Boundaries" 141 else: 142 env_var_name = "HELLO" 143 os.environ[env_var_name] = "WORLD" # This doesn't work under win32 144 expect_result = "WORLD" 145 146 result = str(module.getenv(env_var_name)) 147 self.assertEqual(expect_result, result) 148 149 def test_getenv_returns_null(self): 150 """Related to issue 8. Test getenv of unset variable. 151 """ 152 module = self.module 153 env_var_name = "NOT SET" 154 expect_result = None 155 try: 156 # ensure variable is not set, ignoring not set errors 157 del os.environ[env_var_name] 158 except KeyError: 159 pass 160 result = module.getenv(env_var_name) 161 self.assertEqual(expect_result, result) 162 163 164class StdBoolTest(unittest.TestCase): 165 "Test correct parsing and generation of bool type" 166 167 def setUp(self): 168 """NOTE this is called once for each test* method 169 (it is not called once per class). 170 FIXME This is slightly inefficient as it is called *way* more times than it needs to be. 171 """ 172 header_str = """ 173#include <stdbool.h> 174 175struct foo 176{ 177 bool is_bar; 178 int a; 179}; 180""" 181 self.module, _ = ctypesgentest.test(header_str) # , all_headers=True) 182 183 def tearDown(self): 184 del self.module 185 ctypesgentest.cleanup() 186 187 def test_stdbool_type(self): 188 """Test is bool is correctly parsed""" 189 module = self.module 190 struct_foo = module.struct_foo 191 self.assertEqual(struct_foo._fields_, [("is_bar", ctypes.c_bool), ("a", ctypes.c_int)]) 192 193 194class SimpleMacrosTest(unittest.TestCase): 195 """Based on simple_macros.py 196 """ 197 198 def setUp(self): 199 """NOTE this is called once for each test* method 200 (it is not called once per class). 201 FIXME This is slightly inefficient as it is called *way* more times than it needs to be. 202 """ 203 header_str = """ 204#define A 1 205#define B(x,y) x+y 206#define C(a,b,c) a?b:c 207#define funny(x) "funny" #x 208#define multipler_macro(x,y) x*y 209#define minus_macro(x,y) x-y 210#define divide_macro(x,y) x/y 211#define mod_macro(x,y) x%y 212#define subcall_macro_simple(x) (A) 213#define subcall_macro_simple_plus(x) (A) + (x) 214#define subcall_macro_minus(x,y) minus_macro(x,y) 215#define subcall_macro_minus_plus(x,y,z) (minus_macro(x,y)) + (z) 216""" 217 libraries = None 218 self.module, output = ctypesgentest.test(header_str) 219 self.json, output = ctypesgentest.test(header_str, output_language="json") 220 221 def _json(self, name): 222 for i in self.json: 223 if i["name"] == name: 224 return i 225 raise KeyError("Could not find JSON entry") 226 227 def tearDown(self): 228 del self.module, self.json 229 ctypesgentest.cleanup() 230 231 def test_macro_constant_int(self): 232 """Tests from simple_macros.py 233 """ 234 module, json = self.module, self._json 235 236 self.assertEqual(module.A, 1) 237 self.assertEqual(json("A"), {"name": "A", "type": "macro", "value": "1"}) 238 239 def test_macro_addition_json(self): 240 json = self._json 241 242 self.assertEqual( 243 json("B"), 244 {"args": ["x", "y"], "body": "(x + y)", "name": "B", "type": "macro_function"}, 245 ) 246 247 def test_macro_addition(self): 248 """Tests from simple_macros.py 249 """ 250 module = self.module 251 252 self.assertEqual(module.B(2, 2), 4) 253 254 def test_macro_ternary_json(self): 255 """Tests from simple_macros.py 256 """ 257 json = self._json 258 259 self.assertEqual( 260 json("C"), 261 { 262 "args": ["a", "b", "c"], 263 "body": "a and b or c", 264 "name": "C", 265 "type": "macro_function", 266 }, 267 ) 268 269 def test_macro_ternary_true(self): 270 """Tests from simple_macros.py 271 """ 272 module = self.module 273 274 self.assertEqual(module.C(True, 1, 2), 1) 275 276 def test_macro_ternary_false(self): 277 """Tests from simple_macros.py 278 """ 279 module = self.module 280 281 self.assertEqual(module.C(False, 1, 2), 2) 282 283 def test_macro_ternary_true_complex(self): 284 """Test ?: with true, using values that can not be confused between True and 1 285 """ 286 module = self.module 287 288 self.assertEqual(module.C(True, 99, 100), 99) 289 290 def test_macro_ternary_false_complex(self): 291 """Test ?: with false, using values that can not be confused between True and 1 292 """ 293 module = self.module 294 295 self.assertEqual(module.C(False, 99, 100), 100) 296 297 def test_macro_string_compose(self): 298 """Tests from simple_macros.py 299 """ 300 module = self.module 301 302 self.assertEqual(module.funny("bunny"), "funnybunny") 303 304 def test_macro_string_compose_json(self): 305 """Tests from simple_macros.py 306 """ 307 json = self._json 308 309 self.assertEqual( 310 json("funny"), 311 {"args": ["x"], "body": "('funny' + x)", "name": "funny", "type": "macro_function"}, 312 ) 313 314 def test_macro_math_multipler(self): 315 module = self.module 316 317 x, y = 2, 5 318 self.assertEqual(module.multipler_macro(x, y), x * y) 319 320 def test_macro_math_multiplier_json(self): 321 json = self._json 322 323 self.assertEqual( 324 json("multipler_macro"), 325 { 326 "args": ["x", "y"], 327 "body": "(x * y)", 328 "name": "multipler_macro", 329 "type": "macro_function", 330 }, 331 ) 332 333 def test_macro_math_minus(self): 334 module = self.module 335 336 x, y = 2, 5 337 self.assertEqual(module.minus_macro(x, y), x - y) 338 339 def test_macro_math_minus_json(self): 340 json = self._json 341 342 self.assertEqual( 343 json("minus_macro"), 344 { 345 "args": ["x", "y"], 346 "body": "(x - y)", 347 "name": "minus_macro", 348 "type": "macro_function", 349 }, 350 ) 351 352 def test_macro_math_divide(self): 353 module = self.module 354 355 x, y = 2, 5 356 self.assertEqual(module.divide_macro(x, y), x / y) 357 358 def test_macro_math_divide_json(self): 359 json = self._json 360 361 self.assertEqual( 362 json("divide_macro"), 363 { 364 "args": ["x", "y"], 365 "body": "(x / y)", 366 "name": "divide_macro", 367 "type": "macro_function", 368 }, 369 ) 370 371 def test_macro_math_mod(self): 372 module = self.module 373 374 x, y = 2, 5 375 self.assertEqual(module.mod_macro(x, y), x % y) 376 377 def test_macro_math_mod_json(self): 378 json = self._json 379 380 self.assertEqual( 381 json("mod_macro"), 382 {"args": ["x", "y"], "body": "(x % y)", "name": "mod_macro", "type": "macro_function"}, 383 ) 384 385 def test_macro_subcall_simple(self): 386 """Test use of a constant valued macro within a macro""" 387 module = self.module 388 389 self.assertEqual(module.subcall_macro_simple(2), 1) 390 391 def test_macro_subcall_simple_json(self): 392 json = self._json 393 394 self.assertEqual( 395 json("subcall_macro_simple"), 396 {"args": ["x"], "body": "A", "name": "subcall_macro_simple", "type": "macro_function"}, 397 ) 398 399 def test_macro_subcall_simple_plus(self): 400 """Test math with constant valued macro within a macro""" 401 module = self.module 402 403 self.assertEqual(module.subcall_macro_simple_plus(2), 1 + 2) 404 405 def test_macro_subcall_simple_plus_json(self): 406 json = self._json 407 408 self.assertEqual( 409 json("subcall_macro_simple_plus"), 410 { 411 "args": ["x"], 412 "body": "(A + x)", 413 "name": "subcall_macro_simple_plus", 414 "type": "macro_function", 415 }, 416 ) 417 418 def test_macro_subcall_minus(self): 419 """Test use of macro function within a macro""" 420 module = self.module 421 422 x, y = 2, 5 423 self.assertEqual(module.subcall_macro_minus(x, y), x - y) 424 425 def test_macro_subcall_minus_json(self): 426 json = self._json 427 428 self.assertEqual( 429 json("subcall_macro_minus"), 430 { 431 "args": ["x", "y"], 432 "body": "(minus_macro (x, y))", 433 "name": "subcall_macro_minus", 434 "type": "macro_function", 435 }, 436 ) 437 438 def test_macro_subcall_minus_plus(self): 439 """Test math with a macro function within a macro""" 440 module = self.module 441 442 x, y, z = 2, 5, 1 443 self.assertEqual(module.subcall_macro_minus_plus(x, y, z), (x - y) + z) 444 445 def test_macro_subcall_minus_plus_json(self): 446 json = self._json 447 448 self.assertEqual( 449 json("subcall_macro_minus_plus"), 450 { 451 "args": ["x", "y", "z"], 452 "body": "((minus_macro (x, y)) + z)", 453 "name": "subcall_macro_minus_plus", 454 "type": "macro_function", 455 }, 456 ) 457 458 459class StructuresTest(unittest.TestCase): 460 """Based on structures.py 461 """ 462 463 def setUp(self): 464 """NOTE this is called once for each test* method 465 (it is not called once per class). 466 FIXME This is slightly inefficient as it is called *way* more times than it needs to be. 467 468 NOTE: Very possibly, if you change this header string, you need to change the line 469 numbers in the JSON output test result below (in 470 test_struct_json). 471 """ 472 header_str = """ 473 474struct foo 475{ 476 int a; 477 char b; 478 int c; 479 int d : 15; 480 int : 17; 481}; 482 483struct __attribute__((packed)) packed_foo 484{ 485 int a; 486 char b; 487 int c; 488 int d : 15; 489 int : 17; 490}; 491 492typedef struct 493{ 494 int a; 495 char b; 496 int c; 497 int d : 15; 498 int : 17; 499} foo_t; 500 501typedef struct __attribute__((packed)) 502{ 503 int a; 504 char b; 505 int c; 506 int d : 15; 507 int : 17; 508} packed_foo_t; 509 510#pragma pack(push, 4) 511typedef struct 512{ 513 int a; 514 char b; 515 int c; 516 int d : 15; 517 int : 17; 518} pragma_packed_foo_t; 519#pragma pack(pop) 520 521#pragma pack(push, thing1, 2) 522#pragma pack(push, thing2, 4) 523#pragma pack(pop) 524#pragma pack(push, thing3, 8) 525#pragma pack(push, thing4, 16) 526#pragma pack(pop, thing3) 527struct pragma_packed_foo2 528{ 529 int a; 530 char b; 531 int c; 532 int d : 15; 533 int : 17; 534}; 535#pragma pack(pop, thing1) 536 537struct foo3 538{ 539 int a; 540 char b; 541 int c; 542 int d : 15; 543 int : 17; 544}; 545 546typedef int Int; 547 548typedef struct { 549 int Int; 550} id_struct_t; 551""" 552 libraries = None 553 self.module, output = ctypesgentest.test(header_str) 554 self.json, output = ctypesgentest.test(header_str, output_language="json") 555 cleanup_json_src_paths(self.json) 556 557 def tearDown(self): 558 del self.module 559 ctypesgentest.cleanup() 560 561 def test_struct_json(self): 562 json_ans = [ 563 { 564 "attrib": {}, 565 "fields": [ 566 { 567 "ctype": { 568 "Klass": "CtypesSimple", 569 "errors": [], 570 "longs": 0, 571 "name": "int", 572 "signed": True, 573 }, 574 "name": "a", 575 }, 576 { 577 "ctype": { 578 "Klass": "CtypesSimple", 579 "errors": [], 580 "longs": 0, 581 "name": "char", 582 "signed": True, 583 }, 584 "name": "b", 585 }, 586 { 587 "ctype": { 588 "Klass": "CtypesSimple", 589 "errors": [], 590 "longs": 0, 591 "name": "int", 592 "signed": True, 593 }, 594 "name": "c", 595 }, 596 { 597 "bitfield": "15", 598 "ctype": { 599 "Klass": "CtypesBitfield", 600 "base": { 601 "Klass": "CtypesSimple", 602 "errors": [], 603 "longs": 0, 604 "name": "int", 605 "signed": True, 606 }, 607 "bitfield": { 608 "Klass": "ConstantExpressionNode", 609 "errors": [], 610 "value": 15, 611 }, 612 "errors": [], 613 }, 614 "name": "d", 615 }, 616 { 617 "bitfield": "17", 618 "ctype": { 619 "Klass": "CtypesBitfield", 620 "base": { 621 "Klass": "CtypesSimple", 622 "errors": [], 623 "longs": 0, 624 "name": "int", 625 "signed": True, 626 }, 627 "bitfield": { 628 "Klass": "ConstantExpressionNode", 629 "errors": [], 630 "value": 17, 631 }, 632 "errors": [], 633 }, 634 "name": None, 635 }, 636 ], 637 "name": "foo", 638 "type": "struct", 639 }, 640 { 641 "attrib": {"packed": True}, 642 "fields": [ 643 { 644 "ctype": { 645 "Klass": "CtypesSimple", 646 "errors": [], 647 "longs": 0, 648 "name": "int", 649 "signed": True, 650 }, 651 "name": "a", 652 }, 653 { 654 "ctype": { 655 "Klass": "CtypesSimple", 656 "errors": [], 657 "longs": 0, 658 "name": "char", 659 "signed": True, 660 }, 661 "name": "b", 662 }, 663 { 664 "ctype": { 665 "Klass": "CtypesSimple", 666 "errors": [], 667 "longs": 0, 668 "name": "int", 669 "signed": True, 670 }, 671 "name": "c", 672 }, 673 { 674 "bitfield": "15", 675 "ctype": { 676 "Klass": "CtypesBitfield", 677 "base": { 678 "Klass": "CtypesSimple", 679 "errors": [], 680 "longs": 0, 681 "name": "int", 682 "signed": True, 683 }, 684 "bitfield": { 685 "Klass": "ConstantExpressionNode", 686 "errors": [], 687 "value": 15, 688 }, 689 "errors": [], 690 }, 691 "name": "d", 692 }, 693 { 694 "bitfield": "17", 695 "ctype": { 696 "Klass": "CtypesBitfield", 697 "base": { 698 "Klass": "CtypesSimple", 699 "errors": [], 700 "longs": 0, 701 "name": "int", 702 "signed": True, 703 }, 704 "bitfield": { 705 "Klass": "ConstantExpressionNode", 706 "errors": [], 707 "value": 17, 708 }, 709 "errors": [], 710 }, 711 "name": None, 712 }, 713 ], 714 "name": "packed_foo", 715 "type": "struct", 716 }, 717 { 718 "attrib": {}, 719 "fields": [ 720 { 721 "ctype": { 722 "Klass": "CtypesSimple", 723 "errors": [], 724 "longs": 0, 725 "name": "int", 726 "signed": True, 727 }, 728 "name": "a", 729 }, 730 { 731 "ctype": { 732 "Klass": "CtypesSimple", 733 "errors": [], 734 "longs": 0, 735 "name": "char", 736 "signed": True, 737 }, 738 "name": "b", 739 }, 740 { 741 "ctype": { 742 "Klass": "CtypesSimple", 743 "errors": [], 744 "longs": 0, 745 "name": "int", 746 "signed": True, 747 }, 748 "name": "c", 749 }, 750 { 751 "bitfield": "15", 752 "ctype": { 753 "Klass": "CtypesBitfield", 754 "base": { 755 "Klass": "CtypesSimple", 756 "errors": [], 757 "longs": 0, 758 "name": "int", 759 "signed": True, 760 }, 761 "bitfield": { 762 "Klass": "ConstantExpressionNode", 763 "errors": [], 764 "value": 15, 765 }, 766 "errors": [], 767 }, 768 "name": "d", 769 }, 770 { 771 "bitfield": "17", 772 "ctype": { 773 "Klass": "CtypesBitfield", 774 "base": { 775 "Klass": "CtypesSimple", 776 "errors": [], 777 "longs": 0, 778 "name": "int", 779 "signed": True, 780 }, 781 "bitfield": { 782 "Klass": "ConstantExpressionNode", 783 "errors": [], 784 "value": 17, 785 }, 786 "errors": [], 787 }, 788 "name": None, 789 }, 790 ], 791 "name": "anon_5", 792 "type": "struct", 793 }, 794 { 795 "ctype": { 796 "Klass": "CtypesStruct", 797 "anonymous": True, 798 "errors": [], 799 "members": [ 800 [ 801 "a", 802 { 803 "Klass": "CtypesSimple", 804 "errors": [], 805 "longs": 0, 806 "name": "int", 807 "signed": True, 808 }, 809 ], 810 [ 811 "b", 812 { 813 "Klass": "CtypesSimple", 814 "errors": [], 815 "longs": 0, 816 "name": "char", 817 "signed": True, 818 }, 819 ], 820 [ 821 "c", 822 { 823 "Klass": "CtypesSimple", 824 "errors": [], 825 "longs": 0, 826 "name": "int", 827 "signed": True, 828 }, 829 ], 830 [ 831 "d", 832 { 833 "Klass": "CtypesBitfield", 834 "base": { 835 "Klass": "CtypesSimple", 836 "errors": [], 837 "longs": 0, 838 "name": "int", 839 "signed": True, 840 }, 841 "bitfield": { 842 "Klass": "ConstantExpressionNode", 843 "errors": [], 844 "value": 15, 845 }, 846 "errors": [], 847 }, 848 ], 849 [ 850 None, 851 { 852 "Klass": "CtypesBitfield", 853 "base": { 854 "Klass": "CtypesSimple", 855 "errors": [], 856 "longs": 0, 857 "name": "int", 858 "signed": True, 859 }, 860 "bitfield": { 861 "Klass": "ConstantExpressionNode", 862 "errors": [], 863 "value": 17, 864 }, 865 "errors": [], 866 }, 867 ], 868 ], 869 "opaque": False, 870 "attrib": {}, 871 "src": ["/some-path/temp.h", 21], 872 "tag": "anon_5", 873 "variety": "struct", 874 }, 875 "name": "foo_t", 876 "type": "typedef", 877 }, 878 { 879 "attrib": {"packed": True}, 880 "fields": [ 881 { 882 "ctype": { 883 "Klass": "CtypesSimple", 884 "errors": [], 885 "longs": 0, 886 "name": "int", 887 "signed": True, 888 }, 889 "name": "a", 890 }, 891 { 892 "ctype": { 893 "Klass": "CtypesSimple", 894 "errors": [], 895 "longs": 0, 896 "name": "char", 897 "signed": True, 898 }, 899 "name": "b", 900 }, 901 { 902 "ctype": { 903 "Klass": "CtypesSimple", 904 "errors": [], 905 "longs": 0, 906 "name": "int", 907 "signed": True, 908 }, 909 "name": "c", 910 }, 911 { 912 "bitfield": "15", 913 "ctype": { 914 "Klass": "CtypesBitfield", 915 "base": { 916 "Klass": "CtypesSimple", 917 "errors": [], 918 "longs": 0, 919 "name": "int", 920 "signed": True, 921 }, 922 "bitfield": { 923 "Klass": "ConstantExpressionNode", 924 "errors": [], 925 "value": 15, 926 }, 927 "errors": [], 928 }, 929 "name": "d", 930 }, 931 { 932 "bitfield": "17", 933 "ctype": { 934 "Klass": "CtypesBitfield", 935 "base": { 936 "Klass": "CtypesSimple", 937 "errors": [], 938 "longs": 0, 939 "name": "int", 940 "signed": True, 941 }, 942 "bitfield": { 943 "Klass": "ConstantExpressionNode", 944 "errors": [], 945 "value": 17, 946 }, 947 "errors": [], 948 }, 949 "name": None, 950 }, 951 ], 952 "name": "anon_6", 953 "type": "struct", 954 }, 955 { 956 "ctype": { 957 "Klass": "CtypesStruct", 958 "anonymous": True, 959 "errors": [], 960 "members": [ 961 [ 962 "a", 963 { 964 "Klass": "CtypesSimple", 965 "errors": [], 966 "longs": 0, 967 "name": "int", 968 "signed": True, 969 }, 970 ], 971 [ 972 "b", 973 { 974 "Klass": "CtypesSimple", 975 "errors": [], 976 "longs": 0, 977 "name": "char", 978 "signed": True, 979 }, 980 ], 981 [ 982 "c", 983 { 984 "Klass": "CtypesSimple", 985 "errors": [], 986 "longs": 0, 987 "name": "int", 988 "signed": True, 989 }, 990 ], 991 [ 992 "d", 993 { 994 "Klass": "CtypesBitfield", 995 "base": { 996 "Klass": "CtypesSimple", 997 "errors": [], 998 "longs": 0, 999 "name": "int", 1000 "signed": True, 1001 }, 1002 "bitfield": { 1003 "Klass": "ConstantExpressionNode", 1004 "errors": [], 1005 "value": 15, 1006 }, 1007 "errors": [], 1008 }, 1009 ], 1010 [ 1011 None, 1012 { 1013 "Klass": "CtypesBitfield", 1014 "base": { 1015 "Klass": "CtypesSimple", 1016 "errors": [], 1017 "longs": 0, 1018 "name": "int", 1019 "signed": True, 1020 }, 1021 "bitfield": { 1022 "Klass": "ConstantExpressionNode", 1023 "errors": [], 1024 "value": 17, 1025 }, 1026 "errors": [], 1027 }, 1028 ], 1029 ], 1030 "opaque": False, 1031 "attrib": {"packed": True}, 1032 "src": ["/some-path/temp.h", 30], 1033 "tag": "anon_6", 1034 "variety": "struct", 1035 }, 1036 "name": "packed_foo_t", 1037 "type": "typedef", 1038 }, 1039 { 1040 "attrib": {"packed": True, "aligned": [4]}, 1041 "fields": [ 1042 { 1043 "ctype": { 1044 "Klass": "CtypesSimple", 1045 "errors": [], 1046 "longs": 0, 1047 "name": "int", 1048 "signed": True, 1049 }, 1050 "name": "a", 1051 }, 1052 { 1053 "ctype": { 1054 "Klass": "CtypesSimple", 1055 "errors": [], 1056 "longs": 0, 1057 "name": "char", 1058 "signed": True, 1059 }, 1060 "name": "b", 1061 }, 1062 { 1063 "ctype": { 1064 "Klass": "CtypesSimple", 1065 "errors": [], 1066 "longs": 0, 1067 "name": "int", 1068 "signed": True, 1069 }, 1070 "name": "c", 1071 }, 1072 { 1073 "bitfield": "15", 1074 "ctype": { 1075 "Klass": "CtypesBitfield", 1076 "base": { 1077 "Klass": "CtypesSimple", 1078 "errors": [], 1079 "longs": 0, 1080 "name": "int", 1081 "signed": True, 1082 }, 1083 "bitfield": { 1084 "Klass": "ConstantExpressionNode", 1085 "errors": [], 1086 "value": 15, 1087 }, 1088 "errors": [], 1089 }, 1090 "name": "d", 1091 }, 1092 { 1093 "bitfield": "17", 1094 "ctype": { 1095 "Klass": "CtypesBitfield", 1096 "base": { 1097 "Klass": "CtypesSimple", 1098 "errors": [], 1099 "longs": 0, 1100 "name": "int", 1101 "signed": True, 1102 }, 1103 "bitfield": { 1104 "Klass": "ConstantExpressionNode", 1105 "errors": [], 1106 "value": 17, 1107 }, 1108 "errors": [], 1109 }, 1110 "name": None, 1111 }, 1112 ], 1113 "name": "anon_7", 1114 "type": "struct", 1115 }, 1116 { 1117 "ctype": { 1118 "Klass": "CtypesStruct", 1119 "anonymous": True, 1120 "errors": [], 1121 "members": [ 1122 [ 1123 "a", 1124 { 1125 "Klass": "CtypesSimple", 1126 "errors": [], 1127 "longs": 0, 1128 "name": "int", 1129 "signed": True, 1130 }, 1131 ], 1132 [ 1133 "b", 1134 { 1135 "Klass": "CtypesSimple", 1136 "errors": [], 1137 "longs": 0, 1138 "name": "char", 1139 "signed": True, 1140 }, 1141 ], 1142 [ 1143 "c", 1144 { 1145 "Klass": "CtypesSimple", 1146 "errors": [], 1147 "longs": 0, 1148 "name": "int", 1149 "signed": True, 1150 }, 1151 ], 1152 [ 1153 "d", 1154 { 1155 "Klass": "CtypesBitfield", 1156 "base": { 1157 "Klass": "CtypesSimple", 1158 "errors": [], 1159 "longs": 0, 1160 "name": "int", 1161 "signed": True, 1162 }, 1163 "bitfield": { 1164 "Klass": "ConstantExpressionNode", 1165 "errors": [], 1166 "value": 15, 1167 }, 1168 "errors": [], 1169 }, 1170 ], 1171 [ 1172 None, 1173 { 1174 "Klass": "CtypesBitfield", 1175 "base": { 1176 "Klass": "CtypesSimple", 1177 "errors": [], 1178 "longs": 0, 1179 "name": "int", 1180 "signed": True, 1181 }, 1182 "bitfield": { 1183 "Klass": "ConstantExpressionNode", 1184 "errors": [], 1185 "value": 17, 1186 }, 1187 "errors": [], 1188 }, 1189 ], 1190 ], 1191 "opaque": False, 1192 "attrib": {"packed": True, "aligned": [4]}, 1193 "src": ["/some-path/temp.h", 40], 1194 "tag": "anon_7", 1195 "variety": "struct", 1196 }, 1197 "name": "pragma_packed_foo_t", 1198 "type": "typedef", 1199 }, 1200 { 1201 "attrib": {"packed": True, "aligned": [2]}, 1202 "fields": [ 1203 { 1204 "ctype": { 1205 "Klass": "CtypesSimple", 1206 "errors": [], 1207 "longs": 0, 1208 "name": "int", 1209 "signed": True, 1210 }, 1211 "name": "a", 1212 }, 1213 { 1214 "ctype": { 1215 "Klass": "CtypesSimple", 1216 "errors": [], 1217 "longs": 0, 1218 "name": "char", 1219 "signed": True, 1220 }, 1221 "name": "b", 1222 }, 1223 { 1224 "ctype": { 1225 "Klass": "CtypesSimple", 1226 "errors": [], 1227 "longs": 0, 1228 "name": "int", 1229 "signed": True, 1230 }, 1231 "name": "c", 1232 }, 1233 { 1234 "bitfield": "15", 1235 "ctype": { 1236 "Klass": "CtypesBitfield", 1237 "base": { 1238 "Klass": "CtypesSimple", 1239 "errors": [], 1240 "longs": 0, 1241 "name": "int", 1242 "signed": True, 1243 }, 1244 "bitfield": { 1245 "Klass": "ConstantExpressionNode", 1246 "errors": [], 1247 "value": 15, 1248 }, 1249 "errors": [], 1250 }, 1251 "name": "d", 1252 }, 1253 { 1254 "bitfield": "17", 1255 "ctype": { 1256 "Klass": "CtypesBitfield", 1257 "base": { 1258 "Klass": "CtypesSimple", 1259 "errors": [], 1260 "longs": 0, 1261 "name": "int", 1262 "signed": True, 1263 }, 1264 "bitfield": { 1265 "Klass": "ConstantExpressionNode", 1266 "errors": [], 1267 "value": 17, 1268 }, 1269 "errors": [], 1270 }, 1271 "name": None, 1272 }, 1273 ], 1274 "name": "pragma_packed_foo2", 1275 "type": "struct", 1276 }, 1277 { 1278 "attrib": {}, 1279 "fields": [ 1280 { 1281 "ctype": { 1282 "Klass": "CtypesSimple", 1283 "errors": [], 1284 "longs": 0, 1285 "name": "int", 1286 "signed": True, 1287 }, 1288 "name": "a", 1289 }, 1290 { 1291 "ctype": { 1292 "Klass": "CtypesSimple", 1293 "errors": [], 1294 "longs": 0, 1295 "name": "char", 1296 "signed": True, 1297 }, 1298 "name": "b", 1299 }, 1300 { 1301 "ctype": { 1302 "Klass": "CtypesSimple", 1303 "errors": [], 1304 "longs": 0, 1305 "name": "int", 1306 "signed": True, 1307 }, 1308 "name": "c", 1309 }, 1310 { 1311 "bitfield": "15", 1312 "ctype": { 1313 "Klass": "CtypesBitfield", 1314 "base": { 1315 "Klass": "CtypesSimple", 1316 "errors": [], 1317 "longs": 0, 1318 "name": "int", 1319 "signed": True, 1320 }, 1321 "bitfield": { 1322 "Klass": "ConstantExpressionNode", 1323 "errors": [], 1324 "value": 15, 1325 }, 1326 "errors": [], 1327 }, 1328 "name": "d", 1329 }, 1330 { 1331 "bitfield": "17", 1332 "ctype": { 1333 "Klass": "CtypesBitfield", 1334 "base": { 1335 "Klass": "CtypesSimple", 1336 "errors": [], 1337 "longs": 0, 1338 "name": "int", 1339 "signed": True, 1340 }, 1341 "bitfield": { 1342 "Klass": "ConstantExpressionNode", 1343 "errors": [], 1344 "value": 17, 1345 }, 1346 "errors": [], 1347 }, 1348 "name": None, 1349 }, 1350 ], 1351 "name": "foo3", 1352 "type": "struct", 1353 }, 1354 { 1355 "ctype": { 1356 "Klass": "CtypesSimple", 1357 "errors": [], 1358 "longs": 0, 1359 "name": "int", 1360 "signed": True, 1361 }, 1362 "name": "Int", 1363 "type": "typedef", 1364 }, 1365 { 1366 "attrib": {}, 1367 "fields": [ 1368 { 1369 "ctype": { 1370 "Klass": "CtypesSimple", 1371 "errors": [], 1372 "longs": 0, 1373 "name": "int", 1374 "signed": True, 1375 }, 1376 "name": "Int", 1377 } 1378 ], 1379 "name": "anon_8", 1380 "type": "struct", 1381 }, 1382 { 1383 "ctype": { 1384 "Klass": "CtypesStruct", 1385 "anonymous": True, 1386 "errors": [], 1387 "members": [ 1388 [ 1389 "Int", 1390 { 1391 "Klass": "CtypesSimple", 1392 "errors": [], 1393 "longs": 0, 1394 "name": "int", 1395 "signed": True, 1396 }, 1397 ] 1398 ], 1399 "opaque": False, 1400 "attrib": {}, 1401 "src": ["/some-path/temp.h", 77], 1402 "tag": "anon_8", 1403 "variety": "struct", 1404 }, 1405 "name": "id_struct_t", 1406 "type": "typedef", 1407 }, 1408 { 1409 "ctype": { 1410 "Klass": "CtypesStruct", 1411 "anonymous": False, 1412 "errors": [], 1413 "members": [ 1414 [ 1415 "a", 1416 { 1417 "Klass": "CtypesSimple", 1418 "errors": [], 1419 "longs": 0, 1420 "name": "int", 1421 "signed": True, 1422 }, 1423 ], 1424 [ 1425 "b", 1426 { 1427 "Klass": "CtypesSimple", 1428 "errors": [], 1429 "longs": 0, 1430 "name": "char", 1431 "signed": True, 1432 }, 1433 ], 1434 [ 1435 "c", 1436 { 1437 "Klass": "CtypesSimple", 1438 "errors": [], 1439 "longs": 0, 1440 "name": "int", 1441 "signed": True, 1442 }, 1443 ], 1444 [ 1445 "d", 1446 { 1447 "Klass": "CtypesBitfield", 1448 "base": { 1449 "Klass": "CtypesSimple", 1450 "errors": [], 1451 "longs": 0, 1452 "name": "int", 1453 "signed": True, 1454 }, 1455 "bitfield": { 1456 "Klass": "ConstantExpressionNode", 1457 "errors": [], 1458 "value": 15, 1459 }, 1460 "errors": [], 1461 }, 1462 ], 1463 [ 1464 None, 1465 { 1466 "Klass": "CtypesBitfield", 1467 "base": { 1468 "Klass": "CtypesSimple", 1469 "errors": [], 1470 "longs": 0, 1471 "name": "int", 1472 "signed": True, 1473 }, 1474 "bitfield": { 1475 "Klass": "ConstantExpressionNode", 1476 "errors": [], 1477 "value": 17, 1478 }, 1479 "errors": [], 1480 }, 1481 ], 1482 ], 1483 "opaque": False, 1484 "attrib": {}, 1485 "src": ["/some-path/temp.h", 3], 1486 "tag": "foo", 1487 "variety": "struct", 1488 }, 1489 "name": "foo", 1490 "type": "typedef", 1491 }, 1492 { 1493 "ctype": { 1494 "Klass": "CtypesStruct", 1495 "anonymous": False, 1496 "errors": [], 1497 "members": [ 1498 [ 1499 "a", 1500 { 1501 "Klass": "CtypesSimple", 1502 "errors": [], 1503 "longs": 0, 1504 "name": "int", 1505 "signed": True, 1506 }, 1507 ], 1508 [ 1509 "b", 1510 { 1511 "Klass": "CtypesSimple", 1512 "errors": [], 1513 "longs": 0, 1514 "name": "char", 1515 "signed": True, 1516 }, 1517 ], 1518 [ 1519 "c", 1520 { 1521 "Klass": "CtypesSimple", 1522 "errors": [], 1523 "longs": 0, 1524 "name": "int", 1525 "signed": True, 1526 }, 1527 ], 1528 [ 1529 "d", 1530 { 1531 "Klass": "CtypesBitfield", 1532 "base": { 1533 "Klass": "CtypesSimple", 1534 "errors": [], 1535 "longs": 0, 1536 "name": "int", 1537 "signed": True, 1538 }, 1539 "bitfield": { 1540 "Klass": "ConstantExpressionNode", 1541 "errors": [], 1542 "value": 15, 1543 }, 1544 "errors": [], 1545 }, 1546 ], 1547 [ 1548 None, 1549 { 1550 "Klass": "CtypesBitfield", 1551 "base": { 1552 "Klass": "CtypesSimple", 1553 "errors": [], 1554 "longs": 0, 1555 "name": "int", 1556 "signed": True, 1557 }, 1558 "bitfield": { 1559 "Klass": "ConstantExpressionNode", 1560 "errors": [], 1561 "value": 17, 1562 }, 1563 "errors": [], 1564 }, 1565 ], 1566 ], 1567 "opaque": False, 1568 "attrib": {"packed": True}, 1569 "src": ["/some-path/temp.h", 12], 1570 "tag": "packed_foo", 1571 "variety": "struct", 1572 }, 1573 "name": "packed_foo", 1574 "type": "typedef", 1575 }, 1576 { 1577 "ctype": { 1578 "Klass": "CtypesStruct", 1579 "anonymous": False, 1580 "attrib": {"aligned": [2], "packed": True}, 1581 "errors": [], 1582 "members": [ 1583 [ 1584 "a", 1585 { 1586 "Klass": "CtypesSimple", 1587 "errors": [], 1588 "longs": 0, 1589 "name": "int", 1590 "signed": True, 1591 }, 1592 ], 1593 [ 1594 "b", 1595 { 1596 "Klass": "CtypesSimple", 1597 "errors": [], 1598 "longs": 0, 1599 "name": "char", 1600 "signed": True, 1601 }, 1602 ], 1603 [ 1604 "c", 1605 { 1606 "Klass": "CtypesSimple", 1607 "errors": [], 1608 "longs": 0, 1609 "name": "int", 1610 "signed": True, 1611 }, 1612 ], 1613 [ 1614 "d", 1615 { 1616 "Klass": "CtypesBitfield", 1617 "base": { 1618 "Klass": "CtypesSimple", 1619 "errors": [], 1620 "longs": 0, 1621 "name": "int", 1622 "signed": True, 1623 }, 1624 "bitfield": { 1625 "Klass": "ConstantExpressionNode", 1626 "errors": [], 1627 "value": 15, 1628 }, 1629 "errors": [], 1630 }, 1631 ], 1632 [ 1633 None, 1634 { 1635 "Klass": "CtypesBitfield", 1636 "base": { 1637 "Klass": "CtypesSimple", 1638 "errors": [], 1639 "longs": 0, 1640 "name": "int", 1641 "signed": True, 1642 }, 1643 "bitfield": { 1644 "Klass": "ConstantExpressionNode", 1645 "errors": [], 1646 "value": 17, 1647 }, 1648 "errors": [], 1649 }, 1650 ], 1651 ], 1652 "opaque": False, 1653 "src": ["/some-path/temp.h", 56], 1654 "tag": "pragma_packed_foo2", 1655 "variety": "struct", 1656 }, 1657 "name": "pragma_packed_foo2", 1658 "type": "typedef", 1659 }, 1660 { 1661 "ctype": { 1662 "Klass": "CtypesStruct", 1663 "anonymous": False, 1664 "attrib": {}, 1665 "errors": [], 1666 "members": [ 1667 [ 1668 "a", 1669 { 1670 "Klass": "CtypesSimple", 1671 "errors": [], 1672 "longs": 0, 1673 "name": "int", 1674 "signed": True, 1675 }, 1676 ], 1677 [ 1678 "b", 1679 { 1680 "Klass": "CtypesSimple", 1681 "errors": [], 1682 "longs": 0, 1683 "name": "char", 1684 "signed": True, 1685 }, 1686 ], 1687 [ 1688 "c", 1689 { 1690 "Klass": "CtypesSimple", 1691 "errors": [], 1692 "longs": 0, 1693 "name": "int", 1694 "signed": True, 1695 }, 1696 ], 1697 [ 1698 "d", 1699 { 1700 "Klass": "CtypesBitfield", 1701 "base": { 1702 "Klass": "CtypesSimple", 1703 "errors": [], 1704 "longs": 0, 1705 "name": "int", 1706 "signed": True, 1707 }, 1708 "bitfield": { 1709 "Klass": "ConstantExpressionNode", 1710 "errors": [], 1711 "value": 15, 1712 }, 1713 "errors": [], 1714 }, 1715 ], 1716 [ 1717 None, 1718 { 1719 "Klass": "CtypesBitfield", 1720 "base": { 1721 "Klass": "CtypesSimple", 1722 "errors": [], 1723 "longs": 0, 1724 "name": "int", 1725 "signed": True, 1726 }, 1727 "bitfield": { 1728 "Klass": "ConstantExpressionNode", 1729 "errors": [], 1730 "value": 17, 1731 }, 1732 "errors": [], 1733 }, 1734 ], 1735 ], 1736 "opaque": False, 1737 "src": ["/some-path/temp.h", 66], 1738 "tag": "foo3", 1739 "variety": "struct", 1740 }, 1741 "name": "foo3", 1742 "type": "typedef", 1743 }, 1744 ] 1745 1746 compare_json(self, self.json, json_ans, True) 1747 1748 def test_fields(self): 1749 """Test whether fields are built correctly. 1750 """ 1751 struct_foo = self.module.struct_foo 1752 self.assertEqual( 1753 struct_foo._fields_, 1754 [ 1755 ("a", ctypes.c_int), 1756 ("b", ctypes.c_char), 1757 ("c", ctypes.c_int), 1758 ("d", ctypes.c_int, 15), 1759 ("unnamed_1", ctypes.c_int, 17), 1760 ], 1761 ) 1762 1763 def test_pack(self): 1764 """Test whether gcc __attribute__((packed)) is interpreted correctly. 1765 """ 1766 unpacked_size = compute_packed(4, [ctypes.c_int] * 3 + [ctypes.c_char]) 1767 packed_size = compute_packed(1, [ctypes.c_int] * 3 + [ctypes.c_char]) 1768 1769 struct_foo = self.module.struct_foo 1770 struct_packed_foo = self.module.struct_packed_foo 1771 foo_t = self.module.foo_t 1772 packed_foo_t = self.module.packed_foo_t 1773 self.assertEqual(getattr(struct_foo, "_pack_", 0), 0) 1774 self.assertEqual(getattr(struct_packed_foo, "_pack_", 0), 1) 1775 self.assertEqual(getattr(foo_t, "_pack_", 0), 0) 1776 self.assertEqual(getattr(packed_foo_t, "_pack_", -1), 1) 1777 self.assertEqual(ctypes.sizeof(struct_foo), unpacked_size) 1778 self.assertEqual(ctypes.sizeof(foo_t), unpacked_size) 1779 self.assertEqual(ctypes.sizeof(struct_packed_foo), packed_size) 1780 self.assertEqual(ctypes.sizeof(packed_foo_t), packed_size) 1781 1782 def test_pragma_pack(self): 1783 """Test whether #pragma pack(...) is interpreted correctly. 1784 """ 1785 packed4_size = compute_packed(4, [ctypes.c_int] * 3 + [ctypes.c_char]) 1786 packed2_size = compute_packed(2, [ctypes.c_int] * 3 + [ctypes.c_char]) 1787 unpacked_size = compute_packed(4, [ctypes.c_int] * 3 + [ctypes.c_char]) 1788 1789 pragma_packed_foo_t = self.module.pragma_packed_foo_t 1790 struct_pragma_packed_foo2 = self.module.struct_pragma_packed_foo2 1791 struct_foo3 = self.module.struct_foo3 1792 1793 self.assertEqual(getattr(pragma_packed_foo_t, "_pack_", 0), 4) 1794 self.assertEqual(getattr(struct_pragma_packed_foo2, "_pack_", 0), 2) 1795 self.assertEqual(getattr(struct_foo3, "_pack_", 0), 0) 1796 1797 self.assertEqual(ctypes.sizeof(pragma_packed_foo_t), packed4_size) 1798 self.assertEqual(ctypes.sizeof(struct_pragma_packed_foo2), packed2_size) 1799 self.assertEqual(ctypes.sizeof(struct_foo3), unpacked_size) 1800 1801 def test_typedef_vs_field_id(self): 1802 """Test whether local field identifier names can override external 1803 typedef names. 1804 """ 1805 Int = self.module.Int 1806 id_struct_t = self.module.id_struct_t 1807 self.assertEqual(Int, ctypes.c_int) 1808 self.assertEqual(id_struct_t._fields_, [("Int", ctypes.c_int)]) 1809 1810 1811class MathTest(unittest.TestCase): 1812 """Based on math_functions.py""" 1813 1814 def setUp(self): 1815 """NOTE this is called once for each test* method 1816 (it is not called once per class). 1817 FIXME This is slightly inefficient as it is called *way* more times than it needs to be. 1818 """ 1819 header_str = """ 1820#include <math.h> 1821#define sin_plus_y(x,y) (sin(x) + (y)) 1822""" 1823 if sys.platform == "win32": 1824 # pick something from %windir%\system32\msvc*dll that include stdlib 1825 libraries = ["msvcrt.dll"] 1826 libraries = ["msvcrt"] 1827 elif sys.platform.startswith("linux"): 1828 libraries = ["libm.so.6"] 1829 else: 1830 libraries = ["libc"] 1831 self.module, output = ctypesgentest.test(header_str, libraries=libraries, all_headers=True) 1832 1833 def tearDown(self): 1834 del self.module 1835 ctypesgentest.cleanup() 1836 1837 def test_sin(self): 1838 """Based on math_functions.py""" 1839 module = self.module 1840 1841 self.assertEqual(module.sin(2), math.sin(2)) 1842 1843 def test_sqrt(self): 1844 """Based on math_functions.py""" 1845 module = self.module 1846 1847 self.assertEqual(module.sqrt(4), 2) 1848 1849 def local_test(): 1850 module.sin("foobar") 1851 1852 self.assertRaises(ctypes.ArgumentError, local_test) 1853 1854 def test_bad_args_string_not_number(self): 1855 """Based on math_functions.py""" 1856 module = self.module 1857 1858 def local_test(): 1859 module.sin("foobar") 1860 1861 self.assertRaises(ctypes.ArgumentError, local_test) 1862 1863 def test_subcall_sin(self): 1864 """Test math with sin(x) in a macro""" 1865 module = self.module 1866 1867 self.assertEqual(module.sin_plus_y(2, 1), math.sin(2) + 1) 1868 1869 1870class EnumTest(unittest.TestCase): 1871 def setUp(self): 1872 """NOTE this is called once for each test* method 1873 (it is not called once per class). 1874 FIXME This is slightly inefficient as it is called *way* more times than it needs to be. 1875 """ 1876 header_str = """ 1877 typedef enum { 1878 TEST_1 = 0, 1879 TEST_2 1880 } test_status_t; 1881 """ 1882 libraries = None 1883 self.module, output = ctypesgentest.test(header_str) 1884 self.json, output = ctypesgentest.test(header_str, output_language="json") 1885 cleanup_json_src_paths(self.json) 1886 1887 def tearDown(self): 1888 del self.module, self.json 1889 ctypesgentest.cleanup() 1890 1891 def test_enum(self): 1892 self.assertEqual(self.module.TEST_1, 0) 1893 self.assertEqual(self.module.TEST_2, 1) 1894 1895 def test_enum_json(self): 1896 json_ans = [ 1897 { 1898 "fields": [ 1899 { 1900 "ctype": {"Klass": "ConstantExpressionNode", "errors": [], "value": 0}, 1901 "name": "TEST_1", 1902 }, 1903 { 1904 "ctype": { 1905 "Klass": "BinaryExpressionNode", 1906 "can_be_ctype": [False, False], 1907 "errors": [], 1908 "format": "(%s + %s)", 1909 "left": { 1910 "Klass": "IdentifierExpressionNode", 1911 "errors": [], 1912 "name": "TEST_1", 1913 }, 1914 "name": "addition", 1915 "right": {"Klass": "ConstantExpressionNode", "errors": [], "value": 1}, 1916 }, 1917 "name": "TEST_2", 1918 }, 1919 ], 1920 "name": "anon_2", 1921 "type": "enum", 1922 }, 1923 {"name": "TEST_1", "type": "constant", "value": "0"}, 1924 {"name": "TEST_2", "type": "constant", "value": "(TEST_1 + 1)"}, 1925 { 1926 "ctype": { 1927 "Klass": "CtypesEnum", 1928 "anonymous": True, 1929 "enumerators": [ 1930 ["TEST_1", {"Klass": "ConstantExpressionNode", "errors": [], "value": 0}], 1931 [ 1932 "TEST_2", 1933 { 1934 "Klass": "BinaryExpressionNode", 1935 "can_be_ctype": [False, False], 1936 "errors": [], 1937 "format": "(%s + %s)", 1938 "left": { 1939 "Klass": "IdentifierExpressionNode", 1940 "errors": [], 1941 "name": "TEST_1", 1942 }, 1943 "name": "addition", 1944 "right": { 1945 "Klass": "ConstantExpressionNode", 1946 "errors": [], 1947 "value": 1, 1948 }, 1949 }, 1950 ], 1951 ], 1952 "errors": [], 1953 "opaque": False, 1954 "src": ["/some-path/temp.h", 2], 1955 "tag": "anon_2", 1956 }, 1957 "name": "test_status_t", 1958 "type": "typedef", 1959 }, 1960 ] 1961 1962 compare_json(self, self.json, json_ans) 1963 1964 1965class PrototypeTest(unittest.TestCase): 1966 def setUp(self): 1967 """NOTE this is called once for each test* method 1968 (it is not called once per class). 1969 FIXME This is slightly inefficient as it is called *way* more times than it needs to be. 1970 """ 1971 header_str = """ 1972 int bar2(int a); 1973 int bar(int); 1974 void foo(void); 1975 void foo2(void) __attribute__((stdcall)); 1976 void * __attribute__((stdcall)) foo3(void); 1977 void * __attribute__((stdcall)) * foo4(void); 1978 void foo5(void) __attribute__((__stdcall__)); 1979 """ 1980 libraries = None 1981 self.json, output = ctypesgentest.test(header_str, output_language="json") 1982 cleanup_json_src_paths(self.json) 1983 1984 def tearDown(self): 1985 del self.json 1986 ctypesgentest.cleanup() 1987 1988 def test_function_prototypes_json(self): 1989 json_ans = [ 1990 { 1991 "args": [ 1992 { 1993 "Klass": "CtypesSimple", 1994 "errors": [], 1995 "identifier": "a", 1996 "longs": 0, 1997 "name": "int", 1998 "signed": True, 1999 } 2000 ], 2001 "attrib": {}, 2002 "name": "bar2", 2003 "return": { 2004 "Klass": "CtypesSimple", 2005 "errors": [], 2006 "longs": 0, 2007 "name": "int", 2008 "signed": True, 2009 }, 2010 "type": "function", 2011 "variadic": False, 2012 }, 2013 { 2014 "args": [ 2015 { 2016 "Klass": "CtypesSimple", 2017 "errors": [], 2018 "identifier": "", 2019 "longs": 0, 2020 "name": "int", 2021 "signed": True, 2022 } 2023 ], 2024 "attrib": {}, 2025 "name": "bar", 2026 "return": { 2027 "Klass": "CtypesSimple", 2028 "errors": [], 2029 "longs": 0, 2030 "name": "int", 2031 "signed": True, 2032 }, 2033 "type": "function", 2034 "variadic": False, 2035 }, 2036 { 2037 "args": [], 2038 "attrib": {}, 2039 "name": "foo", 2040 "return": { 2041 "Klass": "CtypesSimple", 2042 "errors": [], 2043 "longs": 0, 2044 "name": "void", 2045 "signed": True, 2046 }, 2047 "type": "function", 2048 "variadic": False, 2049 }, 2050 { 2051 "args": [], 2052 "attrib": {"stdcall": True}, 2053 "name": "foo2", 2054 "return": { 2055 "Klass": "CtypesSimple", 2056 "errors": [], 2057 "longs": 0, 2058 "name": "void", 2059 "signed": True, 2060 }, 2061 "type": "function", 2062 "variadic": False, 2063 }, 2064 { 2065 "args": [], 2066 "attrib": {"stdcall": True}, 2067 "name": "foo3", 2068 "return": { 2069 "Klass": "CtypesPointer", 2070 "destination": {"Klass": "CtypesSpecial", "errors": [], "name": "c_ubyte"}, 2071 "errors": [], 2072 "qualifiers": [], 2073 }, 2074 "type": "function", 2075 "variadic": False, 2076 }, 2077 { 2078 "args": [], 2079 "attrib": {"stdcall": True}, 2080 "name": "foo4", 2081 "return": { 2082 "Klass": "CtypesPointer", 2083 "destination": { 2084 "Klass": "CtypesPointer", 2085 "destination": { 2086 # this return type seems like it really ought to be 2087 # the same as for foo3 2088 "Klass": "CtypesSimple", 2089 "errors": [], 2090 "longs": 0, 2091 "name": "void", 2092 "signed": True, 2093 }, 2094 "errors": [], 2095 "qualifiers": [], 2096 }, 2097 "errors": [], 2098 "qualifiers": [], 2099 }, 2100 "type": "function", 2101 "variadic": False, 2102 }, 2103 { 2104 "args": [], 2105 "attrib": {"stdcall": True}, 2106 "name": "foo5", 2107 "return": { 2108 "Klass": "CtypesSimple", 2109 "errors": [], 2110 "longs": 0, 2111 "name": "void", 2112 "signed": True, 2113 }, 2114 "type": "function", 2115 "variadic": False, 2116 }, 2117 ] 2118 2119 compare_json(self, self.json, json_ans, True) 2120 2121 2122class LongDoubleTest(unittest.TestCase): 2123 "Test correct parsing and generation of 'long double' type" 2124 2125 def setUp(self): 2126 """NOTE this is called once for each test* method 2127 (it is not called once per class). 2128 FIXME This is slightly inefficient as it is called *way* more times than it needs to be. 2129 """ 2130 header_str = """ 2131 struct foo 2132 { 2133 long double is_bar; 2134 int a; 2135 }; 2136 """ 2137 self.module, _ = ctypesgentest.test(header_str) # , all_headers=True) 2138 2139 def tearDown(self): 2140 del self.module 2141 ctypesgentest.cleanup() 2142 2143 def test_longdouble_type(self): 2144 """Test is long double is correctly parsed""" 2145 module = self.module 2146 struct_foo = module.struct_foo 2147 self.assertEqual( 2148 struct_foo._fields_, [("is_bar", ctypes.c_longdouble), ("a", ctypes.c_int)] 2149 ) 2150 2151 2152class MainTest(unittest.TestCase): 2153 script = os.path.join(test_directory, os.pardir, os.pardir, "run.py") 2154 2155 """Test primary entry point used for ctypesgen when called as executable: 2156 ctypesgen.main.main() 2157 2158 This test does not directly execute the script that is autogenerated by 2159 setup.py, but does instead test the entry point as used by that script by 2160 executing `run.py`. `run.py` is a local work-alike (as compared to the 2161 setuptools-autogenerated script) that is only meant to be run in its *in* 2162 the root of source code tree. 2163 """ 2164 2165 @staticmethod 2166 def _exec(args): 2167 p = Popen([MainTest.script] + args, stdout=PIPE, stderr=PIPE) 2168 o, e = p.communicate() 2169 return o, e, p.returncode 2170 2171 def test_version(self): 2172 """Test version string returned by script interface""" 2173 o, e, c = self._exec(["--version"]) 2174 self.assertEqual(c, 0) 2175 self.assertEqual(o.decode().strip(), ctypesgentest.ctypesgen.VERSION) 2176 self.assertEqual(e.decode(), "") 2177 2178 def test_help(self): 2179 """Test that script at least generates a help""" 2180 o, e, c = self._exec(["--help"]) 2181 self.assertEqual(c, 0) 2182 self.assertEqual( 2183 o.decode().splitlines()[0], "Usage: run.py [options] /path/to/header.h ..." 2184 ) 2185 self.assertGreater(len(o), 3000) # its long, so it must be the generated help 2186 self.assertEqual(e.decode(), "") 2187 2188 def test_invalid_option(self): 2189 """Test that script at least generates a help""" 2190 o, e, c = self._exec(["--oh-what-a-goose-i-am"]) 2191 self.assertEqual(c, 2) 2192 self.assertEqual(o.decode(), "") 2193 self.assertEqual( 2194 e.decode().splitlines()[0], "Usage: run.py [options] /path/to/header.h ..." 2195 ) 2196 self.assertIn("run.py: error: no such option: --oh-what-a-goose-i-am", e.decode()) 2197 2198 2199class UncheckedTest(unittest.TestCase): 2200 """Fixing a bug in 1.0.0 - basic type returns of function pointers get treated as pointers""" 2201 2202 def setUp(self): 2203 """NOTE this is called once for each test* method 2204 (it is not called once per class). 2205 FIXME This is slightly inefficient as it is called *way* more times than it needs to be. 2206 """ 2207 header_str = """ 2208 typedef int (*some_type_of_answer)(void*); 2209 """ 2210 self.module, self.output = ctypesgentest.test(header_str, all_headers=False) 2211 2212 def test_unchecked_prototype(self): 2213 """Test is function type marked UNCHECKED (function pointer returning int) is handled correctly""" 2214 module = self.module 2215 A = module.some_type_of_answer() 2216 self.assertEqual(A.restype, ctypes.c_int) 2217 self.assertEqual(A.argtypes, (ctypes.c_void_p,)) 2218 2219 def tearDown(self): 2220 del self.module 2221 ctypesgentest.cleanup() 2222 2223 2224def main(argv=None): 2225 if argv is None: 2226 argv = sys.argv 2227 2228 ctypesgentest.ctypesgen.messages.log.setLevel(logging.CRITICAL) # do not log anything 2229 unittest.main() 2230 2231 return 0 2232 2233 2234if __name__ == "__main__": 2235 sys.exit(main()) 2236