Skip to content

Commit b1df4a6

Browse files
diegorussoaisk
authored andcommitted
pythongh-110190: Fix ctypes structs with array on PPCLE64 (pythonGH-112959)
Fix the same issue of PR python#112604 on PPC64LE platform Refactor tests to make easier to add more platfroms if needed.
1 parent aa326a6 commit b1df4a6

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_short, c_ushort, c_int, c_uint,
1010
c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double)
1111
from struct import calcsize
12+
from collections import namedtuple
1213
from test import support
1314

1415

@@ -474,36 +475,53 @@ class X(Structure):
474475
def test_array_in_struct(self):
475476
# See bpo-22273
476477

478+
# Load the shared library
479+
dll = CDLL(_ctypes_test.__file__)
480+
477481
# These should mirror the structures in Modules/_ctypes/_ctypes_test.c
478482
class Test2(Structure):
479483
_fields_ = [
480484
('data', c_ubyte * 16),
481485
]
482486

483-
class Test3(Structure):
487+
class Test3AParent(Structure):
488+
_fields_ = [
489+
('data', c_float * 2),
490+
]
491+
492+
class Test3A(Test3AParent):
493+
_fields_ = [
494+
('more_data', c_float * 2),
495+
]
496+
497+
class Test3B(Structure):
484498
_fields_ = [
485499
('data', c_double * 2),
486500
]
487501

488-
class Test3A(Structure):
502+
class Test3C(Structure):
489503
_fields_ = [
490-
('data', c_float * 2),
504+
("data", c_double * 4)
491505
]
492506

493-
class Test3B(Test3A):
507+
class Test3D(Structure):
494508
_fields_ = [
495-
('more_data', c_float * 2),
509+
("data", c_double * 8)
510+
]
511+
512+
class Test3E(Structure):
513+
_fields_ = [
514+
("data", c_double * 9)
496515
]
497516

498-
# Load the shared library
499-
dll = CDLL(_ctypes_test.__file__)
500517

518+
# Tests for struct Test2
501519
s = Test2()
502520
expected = 0
503521
for i in range(16):
504522
s.data[i] = i
505523
expected += i
506-
func = dll._testfunc_array_in_struct1
524+
func = dll._testfunc_array_in_struct2
507525
func.restype = c_int
508526
func.argtypes = (Test2,)
509527
result = func(s)
@@ -512,29 +530,16 @@ class Test3B(Test3A):
512530
for i in range(16):
513531
self.assertEqual(s.data[i], i)
514532

515-
s = Test3()
516-
s.data[0] = 3.14159
517-
s.data[1] = 2.71828
518-
expected = 3.14159 + 2.71828
519-
func = dll._testfunc_array_in_struct2
520-
func.restype = c_double
521-
func.argtypes = (Test3,)
522-
result = func(s)
523-
self.assertEqual(result, expected)
524-
# check the passed-in struct hasn't changed
525-
self.assertEqual(s.data[0], 3.14159)
526-
self.assertEqual(s.data[1], 2.71828)
527-
528-
s = Test3B()
533+
# Tests for struct Test3A
534+
s = Test3A()
529535
s.data[0] = 3.14159
530536
s.data[1] = 2.71828
531537
s.more_data[0] = -3.0
532538
s.more_data[1] = -2.0
533-
534-
expected = 3.14159 + 2.71828 - 5.0
535-
func = dll._testfunc_array_in_struct2a
539+
expected = 3.14159 + 2.71828 - 3.0 - 2.0
540+
func = dll._testfunc_array_in_struct3A
536541
func.restype = c_double
537-
func.argtypes = (Test3B,)
542+
func.argtypes = (Test3A,)
538543
result = func(s)
539544
self.assertAlmostEqual(result, expected, places=6)
540545
# check the passed-in struct hasn't changed
@@ -543,129 +548,60 @@ class Test3B(Test3A):
543548
self.assertAlmostEqual(s.more_data[0], -3.0, places=6)
544549
self.assertAlmostEqual(s.more_data[1], -2.0, places=6)
545550

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

670606
def test_38368(self):
671607
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)