| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  | import unittest | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from test.support import import_helper | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  | # Skip this test if the _testcapi, _testlimitedcapi or _testinternalcapi | 
					
						
							|  |  |  | # modules aren't available. | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  | _testcapi = import_helper.import_module('_testcapi') | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  | _testlimitedcapi = import_helper.import_module('_testlimitedcapi') | 
					
						
							| 
									
										
										
										
											2023-10-10 19:00:05 +03:00
										 |  |  | _testinternalcapi = import_helper.import_module('_testinternalcapi') | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | class set_subclass(set): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class frozenset_subclass(frozenset): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-10 19:00:05 +03:00
										 |  |  | class BaseSetTests: | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |     def assertImmutable(self, action, *args): | 
					
						
							|  |  |  |         self.assertRaises(SystemError, action, frozenset(), *args) | 
					
						
							|  |  |  |         self.assertRaises(SystemError, action, frozenset({1}), *args) | 
					
						
							|  |  |  |         self.assertRaises(SystemError, action, frozenset_subclass(), *args) | 
					
						
							|  |  |  |         self.assertRaises(SystemError, action, frozenset_subclass({1}), *args) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-10 19:00:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TestSetCAPI(BaseSetTests, unittest.TestCase): | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |     def test_set_check(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         check = _testlimitedcapi.set_check | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         self.assertTrue(check(set())) | 
					
						
							|  |  |  |         self.assertTrue(check({1, 2})) | 
					
						
							|  |  |  |         self.assertFalse(check(frozenset())) | 
					
						
							|  |  |  |         self.assertTrue(check(set_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(frozenset_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(object())) | 
					
						
							|  |  |  |         # CRASHES: check(NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_set_check_exact(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         check = _testlimitedcapi.set_checkexact | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         self.assertTrue(check(set())) | 
					
						
							|  |  |  |         self.assertTrue(check({1, 2})) | 
					
						
							|  |  |  |         self.assertFalse(check(frozenset())) | 
					
						
							|  |  |  |         self.assertFalse(check(set_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(frozenset_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(object())) | 
					
						
							|  |  |  |         # CRASHES: check(NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_frozenset_check(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         check = _testlimitedcapi.frozenset_check | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         self.assertFalse(check(set())) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset())) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset({1, 2}))) | 
					
						
							|  |  |  |         self.assertFalse(check(set_subclass())) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(object())) | 
					
						
							|  |  |  |         # CRASHES: check(NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_frozenset_check_exact(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         check = _testlimitedcapi.frozenset_checkexact | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         self.assertFalse(check(set())) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset())) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset({1, 2}))) | 
					
						
							|  |  |  |         self.assertFalse(check(set_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(frozenset_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(object())) | 
					
						
							|  |  |  |         # CRASHES: check(NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_anyset_check(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         check = _testlimitedcapi.anyset_check | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         self.assertTrue(check(set())) | 
					
						
							|  |  |  |         self.assertTrue(check({1, 2})) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset())) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset({1, 2}))) | 
					
						
							|  |  |  |         self.assertTrue(check(set_subclass())) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(object())) | 
					
						
							|  |  |  |         # CRASHES: check(NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_anyset_check_exact(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         check = _testlimitedcapi.anyset_checkexact | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         self.assertTrue(check(set())) | 
					
						
							|  |  |  |         self.assertTrue(check({1, 2})) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset())) | 
					
						
							|  |  |  |         self.assertTrue(check(frozenset({1, 2}))) | 
					
						
							|  |  |  |         self.assertFalse(check(set_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(frozenset_subclass())) | 
					
						
							|  |  |  |         self.assertFalse(check(object())) | 
					
						
							|  |  |  |         # CRASHES: check(NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_set_new(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         set_new = _testlimitedcapi.set_new | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         self.assertEqual(set_new().__class__, set) | 
					
						
							|  |  |  |         self.assertEqual(set_new(), set()) | 
					
						
							|  |  |  |         self.assertEqual(set_new((1, 1, 2)), {1, 2}) | 
					
						
							|  |  |  |         self.assertEqual(set_new([1, 1, 2]), {1, 2}) | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, 'object is not iterable'): | 
					
						
							|  |  |  |             set_new(object()) | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, 'object is not iterable'): | 
					
						
							|  |  |  |             set_new(1) | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "unhashable type: 'dict'"): | 
					
						
							|  |  |  |             set_new((1, {})) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_frozenset_new(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         frozenset_new = _testlimitedcapi.frozenset_new | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         self.assertEqual(frozenset_new().__class__, frozenset) | 
					
						
							|  |  |  |         self.assertEqual(frozenset_new(), frozenset()) | 
					
						
							|  |  |  |         self.assertEqual(frozenset_new((1, 1, 2)), frozenset({1, 2})) | 
					
						
							|  |  |  |         self.assertEqual(frozenset_new([1, 1, 2]), frozenset({1, 2})) | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, 'object is not iterable'): | 
					
						
							|  |  |  |             frozenset_new(object()) | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, 'object is not iterable'): | 
					
						
							|  |  |  |             frozenset_new(1) | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "unhashable type: 'dict'"): | 
					
						
							|  |  |  |             frozenset_new((1, {})) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_set_size(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         get_size = _testlimitedcapi.set_size | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         self.assertEqual(get_size(set()), 0) | 
					
						
							|  |  |  |         self.assertEqual(get_size(frozenset()), 0) | 
					
						
							|  |  |  |         self.assertEqual(get_size({1, 1, 2}), 2) | 
					
						
							|  |  |  |         self.assertEqual(get_size(frozenset({1, 1, 2})), 2) | 
					
						
							|  |  |  |         self.assertEqual(get_size(set_subclass((1, 2, 3))), 3) | 
					
						
							|  |  |  |         self.assertEqual(get_size(frozenset_subclass((1, 2, 3))), 3) | 
					
						
							|  |  |  |         with self.assertRaises(SystemError): | 
					
						
							|  |  |  |             get_size(object()) | 
					
						
							|  |  |  |         # CRASHES: get_size(NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_set_get_size(self): | 
					
						
							|  |  |  |         get_size = _testcapi.set_get_size | 
					
						
							|  |  |  |         self.assertEqual(get_size(set()), 0) | 
					
						
							|  |  |  |         self.assertEqual(get_size(frozenset()), 0) | 
					
						
							|  |  |  |         self.assertEqual(get_size({1, 1, 2}), 2) | 
					
						
							|  |  |  |         self.assertEqual(get_size(frozenset({1, 1, 2})), 2) | 
					
						
							|  |  |  |         self.assertEqual(get_size(set_subclass((1, 2, 3))), 3) | 
					
						
							|  |  |  |         self.assertEqual(get_size(frozenset_subclass((1, 2, 3))), 3) | 
					
						
							|  |  |  |         # CRASHES: get_size(NULL) | 
					
						
							|  |  |  |         # CRASHES: get_size(object()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_set_contains(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         contains = _testlimitedcapi.set_contains | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         for cls in (set, frozenset, set_subclass, frozenset_subclass): | 
					
						
							|  |  |  |             with self.subTest(cls=cls): | 
					
						
							|  |  |  |                 instance = cls((1, 2)) | 
					
						
							|  |  |  |                 self.assertTrue(contains(instance, 1)) | 
					
						
							|  |  |  |                 self.assertFalse(contains(instance, 'missing')) | 
					
						
							|  |  |  |                 with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"): | 
					
						
							|  |  |  |                     contains(instance, []) | 
					
						
							|  |  |  |         # CRASHES: contains(instance, NULL) | 
					
						
							|  |  |  |         # CRASHES: contains(NULL, object()) | 
					
						
							|  |  |  |         # CRASHES: contains(NULL, NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_add(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         add = _testlimitedcapi.set_add | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         for cls in (set, set_subclass): | 
					
						
							|  |  |  |             with self.subTest(cls=cls): | 
					
						
							|  |  |  |                 instance = cls((1, 2)) | 
					
						
							|  |  |  |                 self.assertEqual(add(instance, 1), 0) | 
					
						
							|  |  |  |                 self.assertEqual(instance, {1, 2}) | 
					
						
							|  |  |  |                 self.assertEqual(add(instance, 3), 0) | 
					
						
							|  |  |  |                 self.assertEqual(instance, {1, 2, 3}) | 
					
						
							|  |  |  |                 with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"): | 
					
						
							|  |  |  |                     add(instance, []) | 
					
						
							|  |  |  |         with self.assertRaises(SystemError): | 
					
						
							|  |  |  |             add(object(), 1) | 
					
						
							|  |  |  |         self.assertImmutable(add, 1) | 
					
						
							|  |  |  |         # CRASHES: add(NULL, object()) | 
					
						
							|  |  |  |         # CRASHES: add(instance, NULL) | 
					
						
							|  |  |  |         # CRASHES: add(NULL, NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_discard(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         discard = _testlimitedcapi.set_discard | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         for cls in (set, set_subclass): | 
					
						
							|  |  |  |             with self.subTest(cls=cls): | 
					
						
							|  |  |  |                 instance = cls((1, 2)) | 
					
						
							|  |  |  |                 self.assertEqual(discard(instance, 3), 0) | 
					
						
							|  |  |  |                 self.assertEqual(instance, {1, 2}) | 
					
						
							|  |  |  |                 self.assertEqual(discard(instance, 1), 1) | 
					
						
							|  |  |  |                 self.assertEqual(instance, {2}) | 
					
						
							|  |  |  |                 self.assertEqual(discard(instance, 2), 1) | 
					
						
							|  |  |  |                 self.assertEqual(instance, set()) | 
					
						
							|  |  |  |                 self.assertEqual(discard(instance, 2), 0) | 
					
						
							|  |  |  |                 self.assertEqual(instance, set()) | 
					
						
							|  |  |  |                 with self.assertRaisesRegex(TypeError, "unhashable type: 'list'"): | 
					
						
							|  |  |  |                     discard(instance, []) | 
					
						
							|  |  |  |         with self.assertRaises(SystemError): | 
					
						
							|  |  |  |             discard(object(), 1) | 
					
						
							|  |  |  |         self.assertImmutable(discard, 1) | 
					
						
							|  |  |  |         # CRASHES: discard(NULL, object()) | 
					
						
							|  |  |  |         # CRASHES: discard(instance, NULL) | 
					
						
							|  |  |  |         # CRASHES: discard(NULL, NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_pop(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         pop = _testlimitedcapi.set_pop | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         orig = (1, 2) | 
					
						
							|  |  |  |         for cls in (set, set_subclass): | 
					
						
							|  |  |  |             with self.subTest(cls=cls): | 
					
						
							|  |  |  |                 instance = cls(orig) | 
					
						
							|  |  |  |                 self.assertIn(pop(instance), orig) | 
					
						
							|  |  |  |                 self.assertEqual(len(instance), 1) | 
					
						
							|  |  |  |                 self.assertIn(pop(instance), orig) | 
					
						
							|  |  |  |                 self.assertEqual(len(instance), 0) | 
					
						
							|  |  |  |                 with self.assertRaises(KeyError): | 
					
						
							|  |  |  |                     pop(instance) | 
					
						
							|  |  |  |         with self.assertRaises(SystemError): | 
					
						
							|  |  |  |             pop(object()) | 
					
						
							|  |  |  |         self.assertImmutable(pop) | 
					
						
							|  |  |  |         # CRASHES: pop(NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_clear(self): | 
					
						
							| 
									
										
										
										
											2024-03-18 22:03:55 +01:00
										 |  |  |         clear = _testlimitedcapi.set_clear | 
					
						
							| 
									
										
										
										
											2023-10-09 11:57:48 +03:00
										 |  |  |         for cls in (set, set_subclass): | 
					
						
							|  |  |  |             with self.subTest(cls=cls): | 
					
						
							|  |  |  |                 instance = cls((1, 2)) | 
					
						
							|  |  |  |                 self.assertEqual(clear(instance), 0) | 
					
						
							|  |  |  |                 self.assertEqual(instance, set()) | 
					
						
							|  |  |  |                 self.assertEqual(clear(instance), 0) | 
					
						
							|  |  |  |                 self.assertEqual(instance, set()) | 
					
						
							|  |  |  |         with self.assertRaises(SystemError): | 
					
						
							|  |  |  |             clear(object()) | 
					
						
							|  |  |  |         self.assertImmutable(clear) | 
					
						
							|  |  |  |         # CRASHES: clear(NULL) | 
					
						
							| 
									
										
										
										
											2023-10-10 19:00:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestInternalCAPI(BaseSetTests, unittest.TestCase): | 
					
						
							|  |  |  |     def test_set_update(self): | 
					
						
							|  |  |  |         update = _testinternalcapi.set_update | 
					
						
							|  |  |  |         for cls in (set, set_subclass): | 
					
						
							|  |  |  |             for it in ('ab', ('a', 'b'), ['a', 'b'], | 
					
						
							|  |  |  |                        set('ab'), set_subclass('ab'), | 
					
						
							|  |  |  |                        frozenset('ab'), frozenset_subclass('ab')): | 
					
						
							|  |  |  |                 with self.subTest(cls=cls, it=it): | 
					
						
							|  |  |  |                     instance = cls() | 
					
						
							|  |  |  |                     self.assertEqual(update(instance, it), 0) | 
					
						
							|  |  |  |                     self.assertEqual(instance, {'a', 'b'}) | 
					
						
							|  |  |  |                     instance = cls(it) | 
					
						
							|  |  |  |                     self.assertEqual(update(instance, it), 0) | 
					
						
							|  |  |  |                     self.assertEqual(instance, {'a', 'b'}) | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, 'object is not iterable'): | 
					
						
							|  |  |  |                 update(cls(), 1) | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, "unhashable type: 'dict'"): | 
					
						
							|  |  |  |                 update(cls(), [{}]) | 
					
						
							|  |  |  |         with self.assertRaises(SystemError): | 
					
						
							|  |  |  |             update(object(), 'ab') | 
					
						
							|  |  |  |         self.assertImmutable(update, 'ab') | 
					
						
							|  |  |  |         # CRASHES: update(NULL, object()) | 
					
						
							|  |  |  |         # CRASHES: update(instance, NULL) | 
					
						
							|  |  |  |         # CRASHES: update(NULL, NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_set_next_entry(self): | 
					
						
							|  |  |  |         set_next = _testinternalcapi.set_next_entry | 
					
						
							|  |  |  |         for cls in (set, set_subclass, frozenset, frozenset_subclass): | 
					
						
							|  |  |  |             with self.subTest(cls=cls): | 
					
						
							|  |  |  |                 instance = cls('abc') | 
					
						
							|  |  |  |                 pos = 0 | 
					
						
							|  |  |  |                 items = [] | 
					
						
							|  |  |  |                 while True: | 
					
						
							|  |  |  |                     res = set_next(instance, pos) | 
					
						
							|  |  |  |                     if res is None: | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                     rc, pos, hash_, item = res | 
					
						
							|  |  |  |                     items.append(item) | 
					
						
							|  |  |  |                     self.assertEqual(rc, 1) | 
					
						
							|  |  |  |                     self.assertIn(item, instance) | 
					
						
							|  |  |  |                     self.assertEqual(hash(item), hash_) | 
					
						
							|  |  |  |                 self.assertEqual(items, list(instance)) | 
					
						
							|  |  |  |         with self.assertRaises(SystemError): | 
					
						
							|  |  |  |             set_next(object(), 0) | 
					
						
							|  |  |  |         # CRASHES: set_next(NULL, 0) |