]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-124570: ctypes: Run some Structure tests on Union as well (GH-124976)
authorPetr Viktorin <encukou@gmail.com>
Thu, 10 Oct 2024 14:27:52 +0000 (16:27 +0200)
committerGitHub <noreply@github.com>
Thu, 10 Oct 2024 14:27:52 +0000 (16:27 +0200)
- Move some Structure tests to test_structunion; use a common base
  test class + two subclasses to run them on Union too
- Remove test_union for now as it's redundant

Note: `test_simple_structs` & `test_simple_unions` are in the common
file because they share `formats`.

Lib/test/test_ctypes/test_structunion.py [new file with mode: 0644]
Lib/test/test_ctypes/test_structures.py
Lib/test/test_ctypes/test_unions.py [deleted file]

diff --git a/Lib/test/test_ctypes/test_structunion.py b/Lib/test/test_ctypes/test_structunion.py
new file mode 100644 (file)
index 0000000..973ac3b
--- /dev/null
@@ -0,0 +1,353 @@
+"""Common tests for ctypes.Structure and ctypes.Union"""
+
+import unittest
+from ctypes import (Structure, Union, POINTER, sizeof, alignment,
+                    c_char, c_byte, c_ubyte,
+                    c_short, c_ushort, c_int, c_uint,
+                    c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double)
+from ._support import (_CData, PyCStructType, UnionType,
+                       Py_TPFLAGS_DISALLOW_INSTANTIATION,
+                       Py_TPFLAGS_IMMUTABLETYPE)
+from struct import calcsize
+
+
+class StructUnionTestBase:
+    formats = {"c": c_char,
+               "b": c_byte,
+               "B": c_ubyte,
+               "h": c_short,
+               "H": c_ushort,
+               "i": c_int,
+               "I": c_uint,
+               "l": c_long,
+               "L": c_ulong,
+               "q": c_longlong,
+               "Q": c_ulonglong,
+               "f": c_float,
+               "d": c_double,
+               }
+
+    def test_subclass(self):
+        class X(self.cls):
+            _fields_ = [("a", c_int)]
+
+        class Y(X):
+            _fields_ = [("b", c_int)]
+
+        class Z(X):
+            pass
+
+        self.assertEqual(sizeof(X), sizeof(c_int))
+        self.check_sizeof(Y,
+                          struct_size=sizeof(c_int)*2,
+                          union_size=sizeof(c_int))
+        self.assertEqual(sizeof(Z), sizeof(c_int))
+        self.assertEqual(X._fields_, [("a", c_int)])
+        self.assertEqual(Y._fields_, [("b", c_int)])
+        self.assertEqual(Z._fields_, [("a", c_int)])
+
+    def test_subclass_delayed(self):
+        class X(self.cls):
+            pass
+        self.assertEqual(sizeof(X), 0)
+        X._fields_ = [("a", c_int)]
+
+        class Y(X):
+            pass
+        self.assertEqual(sizeof(Y), sizeof(X))
+        Y._fields_ = [("b", c_int)]
+
+        class Z(X):
+            pass
+
+        self.assertEqual(sizeof(X), sizeof(c_int))
+        self.check_sizeof(Y,
+                          struct_size=sizeof(c_int)*2,
+                          union_size=sizeof(c_int))
+        self.assertEqual(sizeof(Z), sizeof(c_int))
+        self.assertEqual(X._fields_, [("a", c_int)])
+        self.assertEqual(Y._fields_, [("b", c_int)])
+        self.assertEqual(Z._fields_, [("a", c_int)])
+
+    def test_inheritance_hierarchy(self):
+        self.assertEqual(self.cls.mro(), [self.cls, _CData, object])
+        self.assertEqual(type(self.metacls), type)
+
+    def test_type_flags(self):
+        for cls in self.cls, self.metacls:
+            with self.subTest(cls=cls):
+                self.assertTrue(cls.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
+                self.assertFalse(cls.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
+
+    def test_metaclass_details(self):
+        # Abstract classes (whose metaclass __init__ was not called) can't be
+        # instantiated directly
+        NewClass = self.metacls.__new__(self.metacls, 'NewClass',
+                                        (self.cls,), {})
+        for cls in self.cls, NewClass:
+            with self.subTest(cls=cls):
+                with self.assertRaisesRegex(TypeError, "abstract class"):
+                    obj = cls()
+
+        # Cannot call the metaclass __init__ more than once
+        class T(self.cls):
+            _fields_ = [("x", c_char),
+                        ("y", c_char)]
+        with self.assertRaisesRegex(SystemError, "already initialized"):
+            self.metacls.__init__(T, 'ptr', (), {})
+
+    def test_alignment(self):
+        class X(self.cls):
+            _fields_ = [("x", c_char * 3)]
+        self.assertEqual(alignment(X), calcsize("s"))
+        self.assertEqual(sizeof(X), calcsize("3s"))
+
+        class Y(self.cls):
+            _fields_ = [("x", c_char * 3),
+                        ("y", c_int)]
+        self.assertEqual(alignment(Y), alignment(c_int))
+        self.check_sizeof(Y,
+                          struct_size=calcsize("3s i"),
+                          union_size=max(calcsize("3s"), calcsize("i")))
+
+        class SI(self.cls):
+            _fields_ = [("a", X),
+                        ("b", Y)]
+        self.assertEqual(alignment(SI), max(alignment(Y), alignment(X)))
+        self.check_sizeof(SI,
+                          struct_size=calcsize("3s0i 3si 0i"),
+                          union_size=max(calcsize("3s"), calcsize("i")))
+
+        class IS(self.cls):
+            _fields_ = [("b", Y),
+                        ("a", X)]
+
+        self.assertEqual(alignment(SI), max(alignment(X), alignment(Y)))
+        self.check_sizeof(IS,
+                          struct_size=calcsize("3si 3s 0i"),
+                          union_size=max(calcsize("3s"), calcsize("i")))
+
+        class XX(self.cls):
+            _fields_ = [("a", X),
+                        ("b", X)]
+        self.assertEqual(alignment(XX), alignment(X))
+        self.check_sizeof(XX,
+                          struct_size=calcsize("3s 3s 0s"),
+                          union_size=calcsize("3s"))
+
+    def test_empty(self):
+        # I had problems with these
+        #
+        # Although these are pathological cases: Empty Structures!
+        class X(self.cls):
+            _fields_ = []
+
+        # Is this really the correct alignment, or should it be 0?
+        self.assertTrue(alignment(X) == 1)
+        self.assertTrue(sizeof(X) == 0)
+
+        class XX(self.cls):
+            _fields_ = [("a", X),
+                        ("b", X)]
+
+        self.assertEqual(alignment(XX), 1)
+        self.assertEqual(sizeof(XX), 0)
+
+    def test_fields(self):
+        # test the offset and size attributes of Structure/Union fields.
+        class X(self.cls):
+            _fields_ = [("x", c_int),
+                        ("y", c_char)]
+
+        self.assertEqual(X.x.offset, 0)
+        self.assertEqual(X.x.size, sizeof(c_int))
+
+        if self.cls == Structure:
+            self.assertEqual(X.y.offset, sizeof(c_int))
+        else:
+            self.assertEqual(X.y.offset, 0)
+        self.assertEqual(X.y.size, sizeof(c_char))
+
+        # readonly
+        self.assertRaises((TypeError, AttributeError), setattr, X.x, "offset", 92)
+        self.assertRaises((TypeError, AttributeError), setattr, X.x, "size", 92)
+
+        # XXX Should we check nested data types also?
+        # offset is always relative to the class...
+
+    def test_invalid_field_types(self):
+        class POINT(self.cls):
+            pass
+        self.assertRaises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)])
+
+    def test_invalid_name(self):
+        # field name must be string
+        def declare_with_name(name):
+            class S(self.cls):
+                _fields_ = [(name, c_int)]
+
+        self.assertRaises(TypeError, declare_with_name, b"x")
+
+    def test_intarray_fields(self):
+        class SomeInts(self.cls):
+            _fields_ = [("a", c_int * 4)]
+
+        # can use tuple to initialize array (but not list!)
+        self.assertEqual(SomeInts((1, 2)).a[:], [1, 2, 0, 0])
+        self.assertEqual(SomeInts((1, 2)).a[::], [1, 2, 0, 0])
+        self.assertEqual(SomeInts((1, 2)).a[::-1], [0, 0, 2, 1])
+        self.assertEqual(SomeInts((1, 2)).a[::2], [1, 0])
+        self.assertEqual(SomeInts((1, 2)).a[1:5:6], [2])
+        self.assertEqual(SomeInts((1, 2)).a[6:4:-1], [])
+        self.assertEqual(SomeInts((1, 2, 3, 4)).a[:], [1, 2, 3, 4])
+        self.assertEqual(SomeInts((1, 2, 3, 4)).a[::], [1, 2, 3, 4])
+        # too long
+        # XXX Should raise ValueError?, not RuntimeError
+        self.assertRaises(RuntimeError, SomeInts, (1, 2, 3, 4, 5))
+
+    def test_huge_field_name(self):
+        # issue12881: segfault with large structure field names
+        def create_class(length):
+            class S(self.cls):
+                _fields_ = [('x' * length, c_int)]
+
+        for length in [10 ** i for i in range(0, 8)]:
+            try:
+                create_class(length)
+            except MemoryError:
+                # MemoryErrors are OK, we just don't want to segfault
+                pass
+
+    def test_abstract_class(self):
+        class X(self.cls):
+            _abstract_ = "something"
+        with self.assertRaisesRegex(TypeError, r"^abstract class$"):
+            X()
+
+    def test_methods(self):
+        self.assertIn("in_dll", dir(type(self.cls)))
+        self.assertIn("from_address", dir(type(self.cls)))
+        self.assertIn("in_dll", dir(type(self.cls)))
+
+
+class StructureTestCase(unittest.TestCase, StructUnionTestBase):
+    cls = Structure
+    metacls = PyCStructType
+
+    def test_metaclass_name(self):
+        self.assertEqual(self.metacls.__name__, "PyCStructType")
+
+    def check_sizeof(self, cls, *, struct_size, union_size):
+        self.assertEqual(sizeof(cls), struct_size)
+
+    def test_simple_structs(self):
+        for code, tp in self.formats.items():
+            class X(Structure):
+                _fields_ = [("x", c_char),
+                            ("y", tp)]
+            self.assertEqual((sizeof(X), code),
+                                 (calcsize("c%c0%c" % (code, code)), code))
+
+
+class UnionTestCase(unittest.TestCase, StructUnionTestBase):
+    cls = Union
+    metacls = UnionType
+
+    def test_metaclass_name(self):
+        self.assertEqual(self.metacls.__name__, "UnionType")
+
+    def check_sizeof(self, cls, *, struct_size, union_size):
+        self.assertEqual(sizeof(cls), union_size)
+
+    def test_simple_unions(self):
+        for code, tp in self.formats.items():
+            class X(Union):
+                _fields_ = [("x", c_char),
+                            ("y", tp)]
+            self.assertEqual((sizeof(X), code),
+                             (calcsize("%c" % (code)), code))
+
+
+class PointerMemberTestBase:
+    def test(self):
+        # a Structure/Union with a POINTER field
+        class S(self.cls):
+            _fields_ = [("array", POINTER(c_int))]
+
+        s = S()
+        # We can assign arrays of the correct type
+        s.array = (c_int * 3)(1, 2, 3)
+        items = [s.array[i] for i in range(3)]
+        self.assertEqual(items, [1, 2, 3])
+
+        s.array[0] = 42
+
+        items = [s.array[i] for i in range(3)]
+        self.assertEqual(items, [42, 2, 3])
+
+        s.array[0] = 1
+
+        items = [s.array[i] for i in range(3)]
+        self.assertEqual(items, [1, 2, 3])
+
+class PointerMemberTestCase_Struct(unittest.TestCase, PointerMemberTestBase):
+    cls = Structure
+
+    def test_none_to_pointer_fields(self):
+        class S(self.cls):
+            _fields_ = [("x", c_int),
+                        ("p", POINTER(c_int))]
+
+        s = S()
+        s.x = 12345678
+        s.p = None
+        self.assertEqual(s.x, 12345678)
+
+class PointerMemberTestCase_Union(unittest.TestCase, PointerMemberTestBase):
+    cls = Union
+
+    def test_none_to_pointer_fields(self):
+        class S(self.cls):
+            _fields_ = [("x", c_int),
+                        ("p", POINTER(c_int))]
+
+        s = S()
+        s.x = 12345678
+        s.p = None
+        self.assertFalse(s.p)  # NULL pointers are falsy
+
+
+class TestRecursiveBase:
+    def test_contains_itself(self):
+        class Recursive(self.cls):
+            pass
+
+        try:
+            Recursive._fields_ = [("next", Recursive)]
+        except AttributeError as details:
+            self.assertIn("Structure or union cannot contain itself",
+                          str(details))
+        else:
+            self.fail("Structure or union cannot contain itself")
+
+
+    def test_vice_versa(self):
+        class First(self.cls):
+            pass
+        class Second(self.cls):
+            pass
+
+        First._fields_ = [("second", Second)]
+
+        try:
+            Second._fields_ = [("first", First)]
+        except AttributeError as details:
+            self.assertIn("_fields_ is final", str(details))
+        else:
+            self.fail("AttributeError not raised")
+
+class TestRecursiveStructure(unittest.TestCase, TestRecursiveBase):
+    cls = Structure
+
+class TestRecursiveUnion(unittest.TestCase, TestRecursiveBase):
+    cls = Union
index 6cc09c8f2b5b59f2cb99ebeb2d676794d180138d..0ec238e04b74cd3921938b8256defa9c92ac0e84 100644 (file)
+"""Tests for ctypes.Structure
+
+Features common with Union should go in test_structunion.py instead.
+"""
+
 from platform import architecture as _architecture
 import struct
 import sys
 import unittest
-from ctypes import (CDLL, Structure, Union, POINTER, sizeof, byref, alignment,
+from ctypes import (CDLL, Structure, Union, POINTER, sizeof, byref,
                     c_void_p, c_char, c_wchar, c_byte, c_ubyte,
-                    c_uint8, c_uint16, c_uint32,
-                    c_short, c_ushort, c_int, c_uint,
-                    c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double)
+                    c_uint8, c_uint16, c_uint32, c_int, c_uint,
+                    c_long, c_ulong, c_longlong, c_float, c_double)
 from ctypes.util import find_library
-from struct import calcsize
 from collections import namedtuple
 from test import support
 from test.support import import_helper
 _ctypes_test = import_helper.import_module("_ctypes_test")
-from ._support import (_CData, PyCStructType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
-                       Py_TPFLAGS_IMMUTABLETYPE)
-
-
-class SubclassesTest(unittest.TestCase):
-    def test_subclass(self):
-        class X(Structure):
-            _fields_ = [("a", c_int)]
-
-        class Y(X):
-            _fields_ = [("b", c_int)]
-
-        class Z(X):
-            pass
-
-        self.assertEqual(sizeof(X), sizeof(c_int))
-        self.assertEqual(sizeof(Y), sizeof(c_int)*2)
-        self.assertEqual(sizeof(Z), sizeof(c_int))
-        self.assertEqual(X._fields_, [("a", c_int)])
-        self.assertEqual(Y._fields_, [("b", c_int)])
-        self.assertEqual(Z._fields_, [("a", c_int)])
-
-    def test_subclass_delayed(self):
-        class X(Structure):
-            pass
-        self.assertEqual(sizeof(X), 0)
-        X._fields_ = [("a", c_int)]
-
-        class Y(X):
-            pass
-        self.assertEqual(sizeof(Y), sizeof(X))
-        Y._fields_ = [("b", c_int)]
-
-        class Z(X):
-            pass
-
-        self.assertEqual(sizeof(X), sizeof(c_int))
-        self.assertEqual(sizeof(Y), sizeof(c_int)*2)
-        self.assertEqual(sizeof(Z), sizeof(c_int))
-        self.assertEqual(X._fields_, [("a", c_int)])
-        self.assertEqual(Y._fields_, [("b", c_int)])
-        self.assertEqual(Z._fields_, [("a", c_int)])
 
 
 class StructureTestCase(unittest.TestCase):
-    formats = {"c": c_char,
-               "b": c_byte,
-               "B": c_ubyte,
-               "h": c_short,
-               "H": c_ushort,
-               "i": c_int,
-               "I": c_uint,
-               "l": c_long,
-               "L": c_ulong,
-               "q": c_longlong,
-               "Q": c_ulonglong,
-               "f": c_float,
-               "d": c_double,
-               }
-
-    def test_inheritance_hierarchy(self):
-        self.assertEqual(Structure.mro(), [Structure, _CData, object])
-
-        self.assertEqual(PyCStructType.__name__, "PyCStructType")
-        self.assertEqual(type(PyCStructType), type)
-
-
-    def test_type_flags(self):
-        for cls in Structure, PyCStructType:
-            with self.subTest(cls=cls):
-                self.assertTrue(Structure.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
-                self.assertFalse(Structure.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
-
-    def test_metaclass_details(self):
-        # Abstract classes (whose metaclass __init__ was not called) can't be
-        # instantiated directly
-        NewStructure = PyCStructType.__new__(PyCStructType, 'NewStructure',
-                                             (Structure,), {})
-        for cls in Structure, NewStructure:
-            with self.subTest(cls=cls):
-                with self.assertRaisesRegex(TypeError, "abstract class"):
-                    obj = cls()
-
-        # Cannot call the metaclass __init__ more than once
-        class T(Structure):
-            _fields_ = [("x", c_char),
-                        ("y", c_char)]
-        with self.assertRaisesRegex(SystemError, "already initialized"):
-            PyCStructType.__init__(T, 'ptr', (), {})
-
-    def test_simple_structs(self):
-        for code, tp in self.formats.items():
-            class X(Structure):
-                _fields_ = [("x", c_char),
-                            ("y", tp)]
-            self.assertEqual((sizeof(X), code),
-                                 (calcsize("c%c0%c" % (code, code)), code))
-
-    def test_unions(self):
-        for code, tp in self.formats.items():
-            class X(Union):
-                _fields_ = [("x", c_char),
-                            ("y", tp)]
-            self.assertEqual((sizeof(X), code),
-                                 (calcsize("%c" % (code)), code))
-
-    def test_struct_alignment(self):
-        class X(Structure):
-            _fields_ = [("x", c_char * 3)]
-        self.assertEqual(alignment(X), calcsize("s"))
-        self.assertEqual(sizeof(X), calcsize("3s"))
-
-        class Y(Structure):
-            _fields_ = [("x", c_char * 3),
-                        ("y", c_int)]
-        self.assertEqual(alignment(Y), alignment(c_int))
-        self.assertEqual(sizeof(Y), calcsize("3si"))
-
-        class SI(Structure):
-            _fields_ = [("a", X),
-                        ("b", Y)]
-        self.assertEqual(alignment(SI), max(alignment(Y), alignment(X)))
-        self.assertEqual(sizeof(SI), calcsize("3s0i 3si 0i"))
-
-        class IS(Structure):
-            _fields_ = [("b", Y),
-                        ("a", X)]
-
-        self.assertEqual(alignment(SI), max(alignment(X), alignment(Y)))
-        self.assertEqual(sizeof(IS), calcsize("3si 3s 0i"))
-
-        class XX(Structure):
-            _fields_ = [("a", X),
-                        ("b", X)]
-        self.assertEqual(alignment(XX), alignment(X))
-        self.assertEqual(sizeof(XX), calcsize("3s 3s 0s"))
-
-    def test_empty(self):
-        # I had problems with these
-        #
-        # Although these are pathological cases: Empty Structures!
-        class X(Structure):
-            _fields_ = []
-
-        class Y(Union):
-            _fields_ = []
-
-        # Is this really the correct alignment, or should it be 0?
-        self.assertTrue(alignment(X) == alignment(Y) == 1)
-        self.assertTrue(sizeof(X) == sizeof(Y) == 0)
-
-        class XX(Structure):
-            _fields_ = [("a", X),
-                        ("b", X)]
-
-        self.assertEqual(alignment(XX), 1)
-        self.assertEqual(sizeof(XX), 0)
-
-    def test_fields(self):
-        # test the offset and size attributes of Structure/Union fields.
-        class X(Structure):
-            _fields_ = [("x", c_int),
-                        ("y", c_char)]
-
-        self.assertEqual(X.x.offset, 0)
-        self.assertEqual(X.x.size, sizeof(c_int))
-
-        self.assertEqual(X.y.offset, sizeof(c_int))
-        self.assertEqual(X.y.size, sizeof(c_char))
-
-        # readonly
-        self.assertRaises((TypeError, AttributeError), setattr, X.x, "offset", 92)
-        self.assertRaises((TypeError, AttributeError), setattr, X.x, "size", 92)
-
-        class X(Union):
-            _fields_ = [("x", c_int),
-                        ("y", c_char)]
-
-        self.assertEqual(X.x.offset, 0)
-        self.assertEqual(X.x.size, sizeof(c_int))
-
-        self.assertEqual(X.y.offset, 0)
-        self.assertEqual(X.y.size, sizeof(c_char))
-
-        # readonly
-        self.assertRaises((TypeError, AttributeError), setattr, X.x, "offset", 92)
-        self.assertRaises((TypeError, AttributeError), setattr, X.x, "size", 92)
-
-        # XXX Should we check nested data types also?
-        # offset is always relative to the class...
-
     def test_packed(self):
         class X(Structure):
             _fields_ = [("a", c_byte),
@@ -290,36 +105,6 @@ class StructureTestCase(unittest.TestCase):
         pt = POINT(y=2, x=1)
         self.assertEqual((pt.x, pt.y), (1, 2))
 
-    def test_invalid_field_types(self):
-        class POINT(Structure):
-            pass
-        self.assertRaises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)])
-
-    def test_invalid_name(self):
-        # field name must be string
-        def declare_with_name(name):
-            class S(Structure):
-                _fields_ = [(name, c_int)]
-
-        self.assertRaises(TypeError, declare_with_name, b"x")
-
-    def test_intarray_fields(self):
-        class SomeInts(Structure):
-            _fields_ = [("a", c_int * 4)]
-
-        # can use tuple to initialize array (but not list!)
-        self.assertEqual(SomeInts((1, 2)).a[:], [1, 2, 0, 0])
-        self.assertEqual(SomeInts((1, 2)).a[::], [1, 2, 0, 0])
-        self.assertEqual(SomeInts((1, 2)).a[::-1], [0, 0, 2, 1])
-        self.assertEqual(SomeInts((1, 2)).a[::2], [1, 0])
-        self.assertEqual(SomeInts((1, 2)).a[1:5:6], [2])
-        self.assertEqual(SomeInts((1, 2)).a[6:4:-1], [])
-        self.assertEqual(SomeInts((1, 2, 3, 4)).a[:], [1, 2, 3, 4])
-        self.assertEqual(SomeInts((1, 2, 3, 4)).a[::], [1, 2, 3, 4])
-        # too long
-        # XXX Should raise ValueError?, not RuntimeError
-        self.assertRaises(RuntimeError, SomeInts, (1, 2, 3, 4, 5))
-
     def test_nested_initializers(self):
         # test initializing nested structures
         class Phone(Structure):
@@ -374,37 +159,12 @@ class StructureTestCase(unittest.TestCase):
         self.assertEqual(msg,
                              "(Phone) TypeError: too many initializers")
 
-    def test_huge_field_name(self):
-        # issue12881: segfault with large structure field names
-        def create_class(length):
-            class S(Structure):
-                _fields_ = [('x' * length, c_int)]
-
-        for length in [10 ** i for i in range(0, 8)]:
-            try:
-                create_class(length)
-            except MemoryError:
-                # MemoryErrors are OK, we just don't want to segfault
-                pass
-
     def get_except(self, func, *args):
         try:
             func(*args)
         except Exception as detail:
             return detail.__class__, str(detail)
 
-    def test_abstract_class(self):
-        class X(Structure):
-            _abstract_ = "something"
-        # try 'X()'
-        cls, msg = self.get_except(eval, "X()", locals())
-        self.assertEqual((cls, msg), (TypeError, "abstract class"))
-
-    def test_methods(self):
-        self.assertIn("in_dll", dir(type(Structure)))
-        self.assertIn("from_address", dir(type(Structure)))
-        self.assertIn("in_dll", dir(type(Structure)))
-
     def test_positional_args(self):
         # see also http://bugs.python.org/issue5042
         class W(Structure):
@@ -507,6 +267,8 @@ class StructureTestCase(unittest.TestCase):
         self.assertEqual(s.second, got.second)
 
     def _test_issue18060(self, Vector):
+        # Regression tests for gh-62260
+
         # The call to atan2() should succeed if the
         # class fields were correctly cloned in the
         # subclasses. Otherwise, it will segfault.
@@ -698,6 +460,7 @@ class StructureTestCase(unittest.TestCase):
                 self.assertEqual(result.data[i], float(i+1))
 
     def test_38368(self):
+        # Regression test for gh-82549
         class U(Union):
             _fields_ = [
                 ('f1', c_uint8 * 16),
@@ -719,9 +482,9 @@ class StructureTestCase(unittest.TestCase):
             self.assertEqual(f2, [0x4567, 0x0123, 0xcdef, 0x89ab,
                                   0x3210, 0x7654, 0xba98, 0xfedc])
 
-    @unittest.skipIf(True, 'Test disabled for now - see bpo-16575/bpo-16576')
+    @unittest.skipIf(True, 'Test disabled for now - see gh-60779/gh-60780')
     def test_union_by_value(self):
-        # See bpo-16575
+        # See gh-60779
 
         # These should mirror the structures in Modules/_ctypes/_ctypes_test.c
 
@@ -800,9 +563,9 @@ class StructureTestCase(unittest.TestCase):
         self.assertEqual(test5.nested.an_int, 0)
         self.assertEqual(test5.another_int, 0)
 
-    @unittest.skipIf(True, 'Test disabled for now - see bpo-16575/bpo-16576')
+    @unittest.skipIf(True, 'Test disabled for now - see gh-60779/gh-60780')
     def test_bitfield_by_value(self):
-        # See bpo-16576
+        # See gh-60780
 
         # These should mirror the structures in Modules/_ctypes/_ctypes_test.c
 
@@ -882,75 +645,5 @@ class StructureTestCase(unittest.TestCase):
                          'a union by value, which is unsupported.')
 
 
-class PointerMemberTestCase(unittest.TestCase):
-
-    def test(self):
-        # a Structure with a POINTER field
-        class S(Structure):
-            _fields_ = [("array", POINTER(c_int))]
-
-        s = S()
-        # We can assign arrays of the correct type
-        s.array = (c_int * 3)(1, 2, 3)
-        items = [s.array[i] for i in range(3)]
-        self.assertEqual(items, [1, 2, 3])
-
-        # The following are bugs, but are included here because the unittests
-        # also describe the current behaviour.
-        #
-        # This fails with SystemError: bad arg to internal function
-        # or with IndexError (with a patch I have)
-
-        s.array[0] = 42
-
-        items = [s.array[i] for i in range(3)]
-        self.assertEqual(items, [42, 2, 3])
-
-        s.array[0] = 1
-
-        items = [s.array[i] for i in range(3)]
-        self.assertEqual(items, [1, 2, 3])
-
-    def test_none_to_pointer_fields(self):
-        class S(Structure):
-            _fields_ = [("x", c_int),
-                        ("p", POINTER(c_int))]
-
-        s = S()
-        s.x = 12345678
-        s.p = None
-        self.assertEqual(s.x, 12345678)
-
-
-class TestRecursiveStructure(unittest.TestCase):
-    def test_contains_itself(self):
-        class Recursive(Structure):
-            pass
-
-        try:
-            Recursive._fields_ = [("next", Recursive)]
-        except AttributeError as details:
-            self.assertIn("Structure or union cannot contain itself",
-                          str(details))
-        else:
-            self.fail("Structure or union cannot contain itself")
-
-
-    def test_vice_versa(self):
-        class First(Structure):
-            pass
-        class Second(Structure):
-            pass
-
-        First._fields_ = [("second", Second)]
-
-        try:
-            Second._fields_ = [("first", First)]
-        except AttributeError as details:
-            self.assertIn("_fields_ is final", str(details))
-        else:
-            self.fail("AttributeError not raised")
-
-
 if __name__ == '__main__':
     unittest.main()
diff --git a/Lib/test/test_ctypes/test_unions.py b/Lib/test/test_ctypes/test_unions.py
deleted file mode 100644 (file)
index e2dff0f..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-import unittest
-from ctypes import Union, c_char
-from ._support import (_CData, UnionType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
-                       Py_TPFLAGS_IMMUTABLETYPE)
-
-
-class ArrayTestCase(unittest.TestCase):
-    def test_inheritance_hierarchy(self):
-        self.assertEqual(Union.mro(), [Union, _CData, object])
-
-        self.assertEqual(UnionType.__name__, "UnionType")
-        self.assertEqual(type(UnionType), type)
-
-    def test_type_flags(self):
-        for cls in Union, UnionType:
-            with self.subTest(cls=Union):
-                self.assertTrue(Union.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
-                self.assertFalse(Union.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
-
-    def test_metaclass_details(self):
-        # Abstract classes (whose metaclass __init__ was not called) can't be
-        # instantiated directly
-        NewUnion = UnionType.__new__(UnionType, 'NewUnion',
-                                     (Union,), {})
-        for cls in Union, NewUnion:
-            with self.subTest(cls=cls):
-                with self.assertRaisesRegex(TypeError, "abstract class"):
-                    obj = cls()
-
-        # Cannot call the metaclass __init__ more than once
-        class T(Union):
-            _fields_ = [("x", c_char),
-                        ("y", c_char)]
-        with self.assertRaisesRegex(SystemError, "already initialized"):
-            UnionType.__init__(T, 'ptr', (), {})