1""" Tests for the internal type cache in CPython. """
2import unittest
3from test import support
4from test.support import import_helper
5try:
6    from sys import _clear_type_cache
7except ImportError:
8    _clear_type_cache = None
9
10# Skip this test if the _testcapi module isn't available.
11type_get_version = import_helper.import_module('_testcapi').type_get_version
12
13
14@support.cpython_only
15@unittest.skipIf(_clear_type_cache is None, "requires sys._clear_type_cache")
16class TypeCacheTests(unittest.TestCase):
17    def test_tp_version_tag_unique(self):
18        """tp_version_tag should be unique assuming no overflow, even after
19        clearing type cache.
20        """
21        # Check if global version tag has already overflowed.
22        Y = type('Y', (), {})
23        Y.x = 1
24        Y.x  # Force a _PyType_Lookup, populating version tag
25        y_ver = type_get_version(Y)
26        # Overflow, or not enough left to conduct the test.
27        if y_ver == 0 or y_ver > 0xFFFFF000:
28            self.skipTest("Out of type version tags")
29        # Note: try to avoid any method lookups within this loop,
30        # It will affect global version tag.
31        all_version_tags = []
32        append_result = all_version_tags.append
33        assertNotEqual = self.assertNotEqual
34        for _ in range(30):
35            _clear_type_cache()
36            X = type('Y', (), {})
37            X.x = 1
38            X.x
39            tp_version_tag_after = type_get_version(X)
40            assertNotEqual(tp_version_tag_after, 0, msg="Version overflowed")
41            append_result(tp_version_tag_after)
42        self.assertEqual(len(set(all_version_tags)), 30,
43                         msg=f"{all_version_tags} contains non-unique versions")
44
45
46if __name__ == "__main__":
47    support.run_unittest(TypeCacheTests)
48