|
1 | 1 | import platform
|
| 2 | +from platform import architecture as _architecture |
| 3 | +import struct |
2 | 4 | import sys
|
3 | 5 | import unittest
|
4 | 6 | from test.test_ctypes import need_symbol
|
|
7 | 9 | c_uint8, c_uint16, c_uint32,
|
8 | 10 | c_short, c_ushort, c_int, c_uint,
|
9 | 11 | c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double)
|
| 12 | +from ctypes.util import find_library |
10 | 13 | from struct import calcsize
|
11 | 14 | import _ctypes_test
|
12 | 15 | from collections import namedtuple
|
@@ -189,7 +192,6 @@ class X(Structure):
|
189 | 192 | self.assertEqual(sizeof(X), 10)
|
190 | 193 | self.assertEqual(X.b.offset, 2)
|
191 | 194 |
|
192 |
| - import struct |
193 | 195 | longlong_size = struct.calcsize("q")
|
194 | 196 | longlong_align = struct.calcsize("bq") - longlong_size
|
195 | 197 |
|
@@ -480,6 +482,66 @@ class X(Structure):
|
480 | 482 | self.assertEqual(s.first, got.first)
|
481 | 483 | self.assertEqual(s.second, got.second)
|
482 | 484 |
|
| 485 | + def _test_issue18060(self, Vector): |
| 486 | + # The call to atan2() should succeed if the |
| 487 | + # class fields were correctly cloned in the |
| 488 | + # subclasses. Otherwise, it will segfault. |
| 489 | + if sys.platform == 'win32': |
| 490 | + libm = CDLL(find_library('msvcrt.dll')) |
| 491 | + else: |
| 492 | + libm = CDLL(find_library('m')) |
| 493 | + |
| 494 | + libm.atan2.argtypes = [Vector] |
| 495 | + libm.atan2.restype = c_double |
| 496 | + |
| 497 | + arg = Vector(y=0.0, x=-1.0) |
| 498 | + self.assertAlmostEqual(libm.atan2(arg), 3.141592653589793) |
| 499 | + |
| 500 | + @unittest.skipIf(_architecture() == ('64bit', 'WindowsPE'), "can't test Windows x64 build") |
| 501 | + @unittest.skipUnless(sys.byteorder == 'little', "can't test on this platform") |
| 502 | + def test_issue18060_a(self): |
| 503 | + # This test case calls |
| 504 | + # PyCStructUnionType_update_stgdict() for each |
| 505 | + # _fields_ assignment, and PyCStgDict_clone() |
| 506 | + # for the Mid and Vector class definitions. |
| 507 | + class Base(Structure): |
| 508 | + _fields_ = [('y', c_double), |
| 509 | + ('x', c_double)] |
| 510 | + class Mid(Base): |
| 511 | + pass |
| 512 | + Mid._fields_ = [] |
| 513 | + class Vector(Mid): pass |
| 514 | + self._test_issue18060(Vector) |
| 515 | + |
| 516 | + @unittest.skipIf(_architecture() == ('64bit', 'WindowsPE'), "can't test Windows x64 build") |
| 517 | + @unittest.skipUnless(sys.byteorder == 'little', "can't test on this platform") |
| 518 | + def test_issue18060_b(self): |
| 519 | + # This test case calls |
| 520 | + # PyCStructUnionType_update_stgdict() for each |
| 521 | + # _fields_ assignment. |
| 522 | + class Base(Structure): |
| 523 | + _fields_ = [('y', c_double), |
| 524 | + ('x', c_double)] |
| 525 | + class Mid(Base): |
| 526 | + _fields_ = [] |
| 527 | + class Vector(Mid): |
| 528 | + _fields_ = [] |
| 529 | + self._test_issue18060(Vector) |
| 530 | + |
| 531 | + @unittest.skipIf(_architecture() == ('64bit', 'WindowsPE'), "can't test Windows x64 build") |
| 532 | + @unittest.skipUnless(sys.byteorder == 'little', "can't test on this platform") |
| 533 | + def test_issue18060_c(self): |
| 534 | + # This test case calls |
| 535 | + # PyCStructUnionType_update_stgdict() for each |
| 536 | + # _fields_ assignment. |
| 537 | + class Base(Structure): |
| 538 | + _fields_ = [('y', c_double)] |
| 539 | + class Mid(Base): |
| 540 | + _fields_ = [] |
| 541 | + class Vector(Mid): |
| 542 | + _fields_ = [('x', c_double)] |
| 543 | + self._test_issue18060(Vector) |
| 544 | + |
483 | 545 | def test_array_in_struct(self):
|
484 | 546 | # See bpo-22273
|
485 | 547 |
|
|
0 commit comments