Skip to content

Commit b95cebf

Browse files
authored
[3.12] gh-110190: Fix ctypes structs with array on PPCLE64 (GH-112959) (#113170)
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: I31730a3ebe558570ce1d7a3b26db8392f18d1770
1 parent 1dc25ae commit b95cebf

File tree

4 files changed

+209
-207
lines changed

4 files changed

+209
-207
lines changed

Lib/test/test_ctypes/test_structures.py

Lines changed: 84 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double)
1010
from struct import calcsize
1111
import _ctypes_test
12+
from collections import namedtuple
1213
from test import support
1314

1415
# The following definition is meant to be used from time to time to assist
@@ -482,36 +483,53 @@ class X(Structure):
482483
def test_array_in_struct(self):
483484
# See bpo-22273
484485

486+
# Load the shared library
487+
dll = CDLL(_ctypes_test.__file__)
488+
485489
# These should mirror the structures in Modules/_ctypes/_ctypes_test.c
486490
class Test2(Structure):
487491
_fields_ = [
488492
('data', c_ubyte * 16),
489493
]
490494

491-
class Test3(Structure):
495+
class Test3AParent(Structure):
496+
_fields_ = [
497+
('data', c_float * 2),
498+
]
499+
500+
class Test3A(Test3AParent):
501+
_fields_ = [
502+
('more_data', c_float * 2),
503+
]
504+
505+
class Test3B(Structure):
492506
_fields_ = [
493507
('data', c_double * 2),
494508
]
495509

496-
class Test3A(Structure):
510+
class Test3C(Structure):
497511
_fields_ = [
498-
('data', c_float * 2),
512+
("data", c_double * 4)
499513
]
500514

501-
class Test3B(Test3A):
515+
class Test3D(Structure):
502516
_fields_ = [
503-
('more_data', c_float * 2),
517+
("data", c_double * 8)
518+
]
519+
520+
class Test3E(Structure):
521+
_fields_ = [
522+
("data", c_double * 9)
504523
]
505524

506-
# Load the shared library
507-
dll = CDLL(_ctypes_test.__file__)
508525

526+
# Tests for struct Test2
509527
s = Test2()
510528
expected = 0
511529
for i in range(16):
512530
s.data[i] = i
513531
expected += i
514-
func = dll._testfunc_array_in_struct1
532+
func = dll._testfunc_array_in_struct2
515533
func.restype = c_int
516534
func.argtypes = (Test2,)
517535
result = func(s)
@@ -520,29 +538,16 @@ class Test3B(Test3A):
520538
for i in range(16):
521539
self.assertEqual(s.data[i], i)
522540

523-
s = Test3()
524-
s.data[0] = 3.14159
525-
s.data[1] = 2.71828
526-
expected = 3.14159 + 2.71828
527-
func = dll._testfunc_array_in_struct2
528-
func.restype = c_double
529-
func.argtypes = (Test3,)
530-
result = func(s)
531-
self.assertEqual(result, expected)
532-
# check the passed-in struct hasn't changed
533-
self.assertEqual(s.data[0], 3.14159)
534-
self.assertEqual(s.data[1], 2.71828)
535-
536-
s = Test3B()
541+
# Tests for struct Test3A
542+
s = Test3A()
537543
s.data[0] = 3.14159
538544
s.data[1] = 2.71828
539545
s.more_data[0] = -3.0
540546
s.more_data[1] = -2.0
541-
542-
expected = 3.14159 + 2.71828 - 5.0
543-
func = dll._testfunc_array_in_struct2a
547+
expected = 3.14159 + 2.71828 - 3.0 - 2.0
548+
func = dll._testfunc_array_in_struct3A
544549
func.restype = c_double
545-
func.argtypes = (Test3B,)
550+
func.argtypes = (Test3A,)
546551
result = func(s)
547552
self.assertAlmostEqual(result, expected, places=6)
548553
# check the passed-in struct hasn't changed
@@ -551,129 +556,60 @@ class Test3B(Test3A):
551556
self.assertAlmostEqual(s.more_data[0], -3.0, places=6)
552557
self.assertAlmostEqual(s.more_data[1], -2.0, places=6)
553558

554-
@unittest.skipIf(
555-
'ppc64le' in platform.uname().machine,
556-
"gh-110190: currently fails on ppc64le",
557-
)
558-
def test_array_in_struct_registers(self):
559-
dll = CDLL(_ctypes_test.__file__)
560-
561-
class Test3C1(Structure):
562-
_fields_ = [
563-
("data", c_double * 4)
564-
]
565-
566-
class DataType4(Array):
567-
_type_ = c_double
568-
_length_ = 4
569-
570-
class Test3C2(Structure):
571-
_fields_ = [
572-
("data", DataType4)
573-
]
574-
575-
class Test3C3(Structure):
576-
_fields_ = [
577-
("x", c_double),
578-
("y", c_double),
579-
("z", c_double),
580-
("t", c_double)
581-
]
582-
583-
class Test3D1(Structure):
584-
_fields_ = [
585-
("data", c_double * 5)
586-
]
587-
588-
class DataType5(Array):
589-
_type_ = c_double
590-
_length_ = 5
591-
592-
class Test3D2(Structure):
593-
_fields_ = [
594-
("data", DataType5)
595-
]
596-
597-
class Test3D3(Structure):
598-
_fields_ = [
599-
("x", c_double),
600-
("y", c_double),
601-
("z", c_double),
602-
("t", c_double),
603-
("u", c_double)
604-
]
605-
606-
# Tests for struct Test3C
607-
expected = (1.0, 2.0, 3.0, 4.0)
608-
func = dll._testfunc_array_in_struct_set_defaults_3C
609-
func.restype = Test3C1
610-
result = func()
611-
# check the default values have been set properly
612-
self.assertEqual(
613-
(result.data[0],
614-
result.data[1],
615-
result.data[2],
616-
result.data[3]),
617-
expected
559+
# Test3B, Test3C, Test3D, Test3E have the same logic with different
560+
# sizes hence putting them in a loop.
561+
StructCtype = namedtuple(
562+
"StructCtype",
563+
["cls", "cfunc1", "cfunc2", "items"]
618564
)
619-
620-
func = dll._testfunc_array_in_struct_set_defaults_3C
621-
func.restype = Test3C2
622-
result = func()
623-
# check the default values have been set properly
624-
self.assertEqual(
625-
(result.data[0],
626-
result.data[1],
627-
result.data[2],
628-
result.data[3]),
629-
expected
630-
)
631-
632-
func = dll._testfunc_array_in_struct_set_defaults_3C
633-
func.restype = Test3C3
634-
result = func()
635-
# check the default values have been set properly
636-
self.assertEqual((result.x, result.y, result.z, result.t), expected)
637-
638-
# Tests for struct Test3D
639-
expected = (1.0, 2.0, 3.0, 4.0, 5.0)
640-
func = dll._testfunc_array_in_struct_set_defaults_3D
641-
func.restype = Test3D1
642-
result = func()
643-
# check the default values have been set properly
644-
self.assertEqual(
645-
(result.data[0],
646-
result.data[1],
647-
result.data[2],
648-
result.data[3],
649-
result.data[4]),
650-
expected
651-
)
652-
653-
func = dll._testfunc_array_in_struct_set_defaults_3D
654-
func.restype = Test3D2
655-
result = func()
656-
# check the default values have been set properly
657-
self.assertEqual(
658-
(result.data[0],
659-
result.data[1],
660-
result.data[2],
661-
result.data[3],
662-
result.data[4]),
663-
expected
664-
)
665-
666-
func = dll._testfunc_array_in_struct_set_defaults_3D
667-
func.restype = Test3D3
668-
result = func()
669-
# check the default values have been set properly
670-
self.assertEqual(
671-
(result.x,
672-
result.y,
673-
result.z,
674-
result.t,
675-
result.u),
676-
expected)
565+
structs_to_test = [
566+
StructCtype(
567+
Test3B,
568+
dll._testfunc_array_in_struct3B,
569+
dll._testfunc_array_in_struct3B_set_defaults,
570+
2),
571+
StructCtype(
572+
Test3C,
573+
dll._testfunc_array_in_struct3C,
574+
dll._testfunc_array_in_struct3C_set_defaults,
575+
4),
576+
StructCtype(
577+
Test3D,
578+
dll._testfunc_array_in_struct3D,
579+
dll._testfunc_array_in_struct3D_set_defaults,
580+
8),
581+
StructCtype(
582+
Test3E,
583+
dll._testfunc_array_in_struct3E,
584+
dll._testfunc_array_in_struct3E_set_defaults,
585+
9),
586+
]
587+
588+
for sut in structs_to_test:
589+
s = sut.cls()
590+
591+
# Test for cfunc1
592+
expected = 0
593+
for i in range(sut.items):
594+
float_i = float(i)
595+
s.data[i] = float_i
596+
expected += float_i
597+
func = sut.cfunc1
598+
func.restype = c_double
599+
func.argtypes = (sut.cls,)
600+
result = func(s)
601+
self.assertEqual(result, expected)
602+
# check the passed-in struct hasn't changed
603+
for i in range(sut.items):
604+
self.assertEqual(s.data[i], float(i))
605+
606+
# Test for cfunc2
607+
func = sut.cfunc2
608+
func.restype = sut.cls
609+
result = func()
610+
# check if the default values have been set correctly
611+
for i in range(sut.items):
612+
self.assertEqual(result.data[i], float(i+1))
677613

678614
def test_38368(self):
679615
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)