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