|
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 ctypes.test 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 test import support |
@@ -483,6 +486,66 @@ class X(Structure): |
483 | 486 | self.assertEqual(s.first, got.first) |
484 | 487 | self.assertEqual(s.second, got.second) |
485 | 488 |
|
| 489 | + def _test_issue18060(self, Vector): |
| 490 | + # The call to atan2() should succeed if the |
| 491 | + # class fields were correctly cloned in the |
| 492 | + # subclasses. Otherwise, it will segfault. |
| 493 | + if sys.platform == 'win32': |
| 494 | + libm = CDLL(find_library('msvcrt.dll')) |
| 495 | + else: |
| 496 | + libm = CDLL(find_library('m')) |
| 497 | + |
| 498 | + libm.atan2.argtypes = [Vector] |
| 499 | + libm.atan2.restype = c_double |
| 500 | + |
| 501 | + arg = Vector(y=0.0, x=-1.0) |
| 502 | + self.assertAlmostEqual(libm.atan2(arg), 3.141592653589793) |
| 503 | + |
| 504 | + @unittest.skipIf(_architecture() == ('64bit', 'WindowsPE'), "can't test Windows x64 build") |
| 505 | + @unittest.skipUnless(sys.byteorder == 'little', "can't test on this platform") |
| 506 | + def test_issue18060_a(self): |
| 507 | + # This test case calls |
| 508 | + # PyCStructUnionType_update_stgdict() for each |
| 509 | + # _fields_ assignment, and PyCStgDict_clone() |
| 510 | + # for the Mid and Vector class definitions. |
| 511 | + class Base(Structure): |
| 512 | + _fields_ = [('y', c_double), |
| 513 | + ('x', c_double)] |
| 514 | + class Mid(Base): |
| 515 | + pass |
| 516 | + Mid._fields_ = [] |
| 517 | + class Vector(Mid): pass |
| 518 | + self._test_issue18060(Vector) |
| 519 | + |
| 520 | + @unittest.skipIf(_architecture() == ('64bit', 'WindowsPE'), "can't test Windows x64 build") |
| 521 | + @unittest.skipUnless(sys.byteorder == 'little', "can't test on this platform") |
| 522 | + def test_issue18060_b(self): |
| 523 | + # This test case calls |
| 524 | + # PyCStructUnionType_update_stgdict() for each |
| 525 | + # _fields_ assignment. |
| 526 | + class Base(Structure): |
| 527 | + _fields_ = [('y', c_double), |
| 528 | + ('x', c_double)] |
| 529 | + class Mid(Base): |
| 530 | + _fields_ = [] |
| 531 | + class Vector(Mid): |
| 532 | + _fields_ = [] |
| 533 | + self._test_issue18060(Vector) |
| 534 | + |
| 535 | + @unittest.skipIf(_architecture() == ('64bit', 'WindowsPE'), "can't test Windows x64 build") |
| 536 | + @unittest.skipUnless(sys.byteorder == 'little', "can't test on this platform") |
| 537 | + def test_issue18060_c(self): |
| 538 | + # This test case calls |
| 539 | + # PyCStructUnionType_update_stgdict() for each |
| 540 | + # _fields_ assignment. |
| 541 | + class Base(Structure): |
| 542 | + _fields_ = [('y', c_double)] |
| 543 | + class Mid(Base): |
| 544 | + _fields_ = [] |
| 545 | + class Vector(Mid): |
| 546 | + _fields_ = [('x', c_double)] |
| 547 | + self._test_issue18060(Vector) |
| 548 | + |
486 | 549 | def test_array_in_struct(self): |
487 | 550 | # See bpo-22273 |
488 | 551 |
|
|
0 commit comments