Skip to content

Commit e078493

Browse files
diegorussomgorny
authored andcommitted
[3.11] pythongh-110190: Fix ctypes structs with array on PPCLE64 (pythonGH-112959) (python#113167)
Fix the same issue of PR python#112604 on PPC64LE platform Refactor tests to make easier to add more platfroms if needed. (cherry picked from commit 6644ca4) Change-Id: I1ada30808c0d593a43eca3fa7a628c26bc276310 Signed-off-by: Michał Górny <[email protected]>
1 parent 3d6bab6 commit e078493

File tree

3 files changed

+208
-207
lines changed

3 files changed

+208
-207
lines changed

Lib/ctypes/test/test_structures.py

Lines changed: 84 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from ctypes.util import find_library
1313
from struct import calcsize
1414
import _ctypes_test
15+
from collections import namedtuple
1516
from test import support
1617

1718
class SubclassesTest(unittest.TestCase):
@@ -549,36 +550,53 @@ class Vector(Mid):
549550
def test_array_in_struct(self):
550551
# See bpo-22273
551552

553+
# Load the shared library
554+
dll = CDLL(_ctypes_test.__file__)
555+
552556
# These should mirror the structures in Modules/_ctypes/_ctypes_test.c
553557
class Test2(Structure):
554558
_fields_ = [
555559
('data', c_ubyte * 16),
556560
]
557561

558-
class Test3(Structure):
562+
class Test3AParent(Structure):
563+
_fields_ = [
564+
('data', c_float * 2),
565+
]
566+
567+
class Test3A(Test3AParent):
568+
_fields_ = [
569+
('more_data', c_float * 2),
570+
]
571+
572+
class Test3B(Structure):
559573
_fields_ = [
560574
('data', c_double * 2),
561575
]
562576

563-
class Test3A(Structure):
577+
class Test3C(Structure):
564578
_fields_ = [
565-
('data', c_float * 2),
579+
("data", c_double * 4)
566580
]
567581

568-
class Test3B(Test3A):
582+
class Test3D(Structure):
569583
_fields_ = [
570-
('more_data', c_float * 2),
584+
("data", c_double * 8)
585+
]
586+
587+
class Test3E(Structure):
588+
_fields_ = [
589+
("data", c_double * 9)
571590
]
572591

573-
# Load the shared library
574-
dll = CDLL(_ctypes_test.__file__)
575592

593+
# Tests for struct Test2
576594
s = Test2()
577595
expected = 0
578596
for i in range(16):
579597
s.data[i] = i
580598
expected += i
581-
func = dll._testfunc_array_in_struct1
599+
func = dll._testfunc_array_in_struct2
582600
func.restype = c_int
583601
func.argtypes = (Test2,)
584602
result = func(s)
@@ -587,29 +605,16 @@ class Test3B(Test3A):
587605
for i in range(16):
588606
self.assertEqual(s.data[i], i)
589607

590-
s = Test3()
591-
s.data[0] = 3.14159
592-
s.data[1] = 2.71828
593-
expected = 3.14159 + 2.71828
594-
func = dll._testfunc_array_in_struct2
595-
func.restype = c_double
596-
func.argtypes = (Test3,)
597-
result = func(s)
598-
self.assertEqual(result, expected)
599-
# check the passed-in struct hasn't changed
600-
self.assertEqual(s.data[0], 3.14159)
601-
self.assertEqual(s.data[1], 2.71828)
602-
603-
s = Test3B()
608+
# Tests for struct Test3A
609+
s = Test3A()
604610
s.data[0] = 3.14159
605611
s.data[1] = 2.71828
606612
s.more_data[0] = -3.0
607613
s.more_data[1] = -2.0
608-
609-
expected = 3.14159 + 2.71828 - 5.0
610-
func = dll._testfunc_array_in_struct2a
614+
expected = 3.14159 + 2.71828 - 3.0 - 2.0
615+
func = dll._testfunc_array_in_struct3A
611616
func.restype = c_double
612-
func.argtypes = (Test3B,)
617+
func.argtypes = (Test3A,)
613618
result = func(s)
614619
self.assertAlmostEqual(result, expected, places=6)
615620
# check the passed-in struct hasn't changed
@@ -618,129 +623,60 @@ class Test3B(Test3A):
618623
self.assertAlmostEqual(s.more_data[0], -3.0, places=6)
619624
self.assertAlmostEqual(s.more_data[1], -2.0, places=6)
620625

621-
@unittest.skipIf(
622-
'ppc64le' in platform.uname().machine,
623-
"gh-110190: currently fails on ppc64le",
624-
)
625-
def test_array_in_struct_registers(self):
626-
dll = CDLL(_ctypes_test.__file__)
627-
628-
class Test3C1(Structure):
629-
_fields_ = [
630-
("data", c_double * 4)
631-
]
632-
633-
class DataType4(Array):
634-
_type_ = c_double
635-
_length_ = 4
636-
637-
class Test3C2(Structure):
638-
_fields_ = [
639-
("data", DataType4)
640-
]
641-
642-
class Test3C3(Structure):
643-
_fields_ = [
644-
("x", c_double),
645-
("y", c_double),
646-
("z", c_double),
647-
("t", c_double)
648-
]
649-
650-
class Test3D1(Structure):
651-
_fields_ = [
652-
("data", c_double * 5)
653-
]
654-
655-
class DataType5(Array):
656-
_type_ = c_double
657-
_length_ = 5
658-
659-
class Test3D2(Structure):
660-
_fields_ = [
661-
("data", DataType5)
662-
]
663-
664-
class Test3D3(Structure):
665-
_fields_ = [
666-
("x", c_double),
667-
("y", c_double),
668-
("z", c_double),
669-
("t", c_double),
670-
("u", c_double)
671-
]
672-
673-
# Tests for struct Test3C
674-
expected = (1.0, 2.0, 3.0, 4.0)
675-
func = dll._testfunc_array_in_struct_set_defaults_3C
676-
func.restype = Test3C1
677-
result = func()
678-
# check the default values have been set properly
679-
self.assertEqual(
680-
(result.data[0],
681-
result.data[1],
682-
result.data[2],
683-
result.data[3]),
684-
expected
626+
# Test3B, Test3C, Test3D, Test3E have the same logic with different
627+
# sizes hence putting them in a loop.
628+
StructCtype = namedtuple(
629+
"StructCtype",
630+
["cls", "cfunc1", "cfunc2", "items"]
685631
)
686-
687-
func = dll._testfunc_array_in_struct_set_defaults_3C
688-
func.restype = Test3C2
689-
result = func()
690-
# check the default values have been set properly
691-
self.assertEqual(
692-
(result.data[0],
693-
result.data[1],
694-
result.data[2],
695-
result.data[3]),
696-
expected
697-
)
698-
699-
func = dll._testfunc_array_in_struct_set_defaults_3C
700-
func.restype = Test3C3
701-
result = func()
702-
# check the default values have been set properly
703-
self.assertEqual((result.x, result.y, result.z, result.t), expected)
704-
705-
# Tests for struct Test3D
706-
expected = (1.0, 2.0, 3.0, 4.0, 5.0)
707-
func = dll._testfunc_array_in_struct_set_defaults_3D
708-
func.restype = Test3D1
709-
result = func()
710-
# check the default values have been set properly
711-
self.assertEqual(
712-
(result.data[0],
713-
result.data[1],
714-
result.data[2],
715-
result.data[3],
716-
result.data[4]),
717-
expected
718-
)
719-
720-
func = dll._testfunc_array_in_struct_set_defaults_3D
721-
func.restype = Test3D2
722-
result = func()
723-
# check the default values have been set properly
724-
self.assertEqual(
725-
(result.data[0],
726-
result.data[1],
727-
result.data[2],
728-
result.data[3],
729-
result.data[4]),
730-
expected
731-
)
732-
733-
func = dll._testfunc_array_in_struct_set_defaults_3D
734-
func.restype = Test3D3
735-
result = func()
736-
# check the default values have been set properly
737-
self.assertEqual(
738-
(result.x,
739-
result.y,
740-
result.z,
741-
result.t,
742-
result.u),
743-
expected)
632+
structs_to_test = [
633+
StructCtype(
634+
Test3B,
635+
dll._testfunc_array_in_struct3B,
636+
dll._testfunc_array_in_struct3B_set_defaults,
637+
2),
638+
StructCtype(
639+
Test3C,
640+
dll._testfunc_array_in_struct3C,
641+
dll._testfunc_array_in_struct3C_set_defaults,
642+
4),
643+
StructCtype(
644+
Test3D,
645+
dll._testfunc_array_in_struct3D,
646+
dll._testfunc_array_in_struct3D_set_defaults,
647+
8),
648+
StructCtype(
649+
Test3E,
650+
dll._testfunc_array_in_struct3E,
651+
dll._testfunc_array_in_struct3E_set_defaults,
652+
9),
653+
]
654+
655+
for sut in structs_to_test:
656+
s = sut.cls()
657+
658+
# Test for cfunc1
659+
expected = 0
660+
for i in range(sut.items):
661+
float_i = float(i)
662+
s.data[i] = float_i
663+
expected += float_i
664+
func = sut.cfunc1
665+
func.restype = c_double
666+
func.argtypes = (sut.cls,)
667+
result = func(s)
668+
self.assertEqual(result, expected)
669+
# check the passed-in struct hasn't changed
670+
for i in range(sut.items):
671+
self.assertEqual(s.data[i], float(i))
672+
673+
# Test for cfunc2
674+
func = sut.cfunc2
675+
func.restype = sut.cls
676+
result = func()
677+
# check if the default values have been set correctly
678+
for i in range(sut.items):
679+
self.assertEqual(result.data[i], float(i+1))
744680

745681
def test_38368(self):
746682
class U(Union):

0 commit comments

Comments
 (0)