Skip to content

Commit 5da53d3

Browse files
authored
[3.11] gh-110190: Fix ctypes structs with array on PPCLE64 (GH-112959) (#113167)
Fix the same issue of PR #112604 on PPC64LE platform Refactor tests to make easier to add more platfroms if needed. (cherry picked from commit 6644ca4) Change-Id: I1ada30808c0d593a43eca3fa7a628c26bc276310
1 parent 2a4a724 commit 5da53d3

File tree

4 files changed

+209
-207
lines changed

4 files changed

+209
-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
# The following definition is meant to be used from time to time to assist
@@ -545,36 +546,53 @@ class Vector(Mid):
545546
def test_array_in_struct(self):
546547
# See bpo-22273
547548

549+
# Load the shared library
550+
dll = CDLL(_ctypes_test.__file__)
551+
548552
# These should mirror the structures in Modules/_ctypes/_ctypes_test.c
549553
class Test2(Structure):
550554
_fields_ = [
551555
('data', c_ubyte * 16),
552556
]
553557

554-
class Test3(Structure):
558+
class Test3AParent(Structure):
559+
_fields_ = [
560+
('data', c_float * 2),
561+
]
562+
563+
class Test3A(Test3AParent):
564+
_fields_ = [
565+
('more_data', c_float * 2),
566+
]
567+
568+
class Test3B(Structure):
555569
_fields_ = [
556570
('data', c_double * 2),
557571
]
558572

559-
class Test3A(Structure):
573+
class Test3C(Structure):
560574
_fields_ = [
561-
('data', c_float * 2),
575+
("data", c_double * 4)
562576
]
563577

564-
class Test3B(Test3A):
578+
class Test3D(Structure):
565579
_fields_ = [
566-
('more_data', c_float * 2),
580+
("data", c_double * 8)
581+
]
582+
583+
class Test3E(Structure):
584+
_fields_ = [
585+
("data", c_double * 9)
567586
]
568587

569-
# Load the shared library
570-
dll = CDLL(_ctypes_test.__file__)
571588

589+
# Tests for struct Test2
572590
s = Test2()
573591
expected = 0
574592
for i in range(16):
575593
s.data[i] = i
576594
expected += i
577-
func = dll._testfunc_array_in_struct1
595+
func = dll._testfunc_array_in_struct2
578596
func.restype = c_int
579597
func.argtypes = (Test2,)
580598
result = func(s)
@@ -583,29 +601,16 @@ class Test3B(Test3A):
583601
for i in range(16):
584602
self.assertEqual(s.data[i], i)
585603

586-
s = Test3()
587-
s.data[0] = 3.14159
588-
s.data[1] = 2.71828
589-
expected = 3.14159 + 2.71828
590-
func = dll._testfunc_array_in_struct2
591-
func.restype = c_double
592-
func.argtypes = (Test3,)
593-
result = func(s)
594-
self.assertEqual(result, expected)
595-
# check the passed-in struct hasn't changed
596-
self.assertEqual(s.data[0], 3.14159)
597-
self.assertEqual(s.data[1], 2.71828)
598-
599-
s = Test3B()
604+
# Tests for struct Test3A
605+
s = Test3A()
600606
s.data[0] = 3.14159
601607
s.data[1] = 2.71828
602608
s.more_data[0] = -3.0
603609
s.more_data[1] = -2.0
604-
605-
expected = 3.14159 + 2.71828 - 5.0
606-
func = dll._testfunc_array_in_struct2a
610+
expected = 3.14159 + 2.71828 - 3.0 - 2.0
611+
func = dll._testfunc_array_in_struct3A
607612
func.restype = c_double
608-
func.argtypes = (Test3B,)
613+
func.argtypes = (Test3A,)
609614
result = func(s)
610615
self.assertAlmostEqual(result, expected, places=6)
611616
# check the passed-in struct hasn't changed
@@ -614,129 +619,60 @@ class Test3B(Test3A):
614619
self.assertAlmostEqual(s.more_data[0], -3.0, places=6)
615620
self.assertAlmostEqual(s.more_data[1], -2.0, places=6)
616621

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

741677
def test_38368(self):
742678
class U(Union):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix ctypes structs with array on PPC64LE platform by setting ``MAX_STRUCT_SIZE`` to 64 in stgdict. Patch by Diego Russo.

0 commit comments

Comments
 (0)