@@ -1815,6 +1815,192 @@ def __eq__(self, o):
1815
1815
s = {0 }
1816
1816
s .update (other )
1817
1817
1818
+
1819
+ class TestOperationsMutating :
1820
+ """Regression test for bpo-46615"""
1821
+
1822
+ constructor1 = None
1823
+ constructor2 = None
1824
+
1825
+ def make_sets_of_bad_objects (self ):
1826
+ class Bad :
1827
+ def __eq__ (self , other ):
1828
+ if not enabled :
1829
+ return False
1830
+ if randrange (20 ) == 0 :
1831
+ set1 .clear ()
1832
+ if randrange (20 ) == 0 :
1833
+ set2 .clear ()
1834
+ return bool (randrange (2 ))
1835
+ def __hash__ (self ):
1836
+ return randrange (2 )
1837
+ # Don't behave poorly during construction.
1838
+ enabled = False
1839
+ set1 = self .constructor1 (Bad () for _ in range (randrange (50 )))
1840
+ set2 = self .constructor2 (Bad () for _ in range (randrange (50 )))
1841
+ # Now start behaving poorly
1842
+ enabled = True
1843
+ return set1 , set2
1844
+
1845
+ def check_set_op_does_not_crash (self , function ):
1846
+ for _ in range (100 ):
1847
+ set1 , set2 = self .make_sets_of_bad_objects ()
1848
+ try :
1849
+ function (set1 , set2 )
1850
+ except RuntimeError as e :
1851
+ # Just make sure we don't crash here.
1852
+ self .assertIn ("changed size during iteration" , str (e ))
1853
+
1854
+
1855
+ class TestBinaryOpsMutating (TestOperationsMutating ):
1856
+
1857
+ def test_eq_with_mutation (self ):
1858
+ self .check_set_op_does_not_crash (lambda a , b : a == b )
1859
+
1860
+ def test_ne_with_mutation (self ):
1861
+ self .check_set_op_does_not_crash (lambda a , b : a != b )
1862
+
1863
+ def test_lt_with_mutation (self ):
1864
+ self .check_set_op_does_not_crash (lambda a , b : a < b )
1865
+
1866
+ def test_le_with_mutation (self ):
1867
+ self .check_set_op_does_not_crash (lambda a , b : a <= b )
1868
+
1869
+ def test_gt_with_mutation (self ):
1870
+ self .check_set_op_does_not_crash (lambda a , b : a > b )
1871
+
1872
+ def test_ge_with_mutation (self ):
1873
+ self .check_set_op_does_not_crash (lambda a , b : a >= b )
1874
+
1875
+ def test_and_with_mutation (self ):
1876
+ self .check_set_op_does_not_crash (lambda a , b : a & b )
1877
+
1878
+ def test_or_with_mutation (self ):
1879
+ self .check_set_op_does_not_crash (lambda a , b : a | b )
1880
+
1881
+ def test_sub_with_mutation (self ):
1882
+ self .check_set_op_does_not_crash (lambda a , b : a - b )
1883
+
1884
+ def test_xor_with_mutation (self ):
1885
+ self .check_set_op_does_not_crash (lambda a , b : a ^ b )
1886
+
1887
+ def test_iadd_with_mutation (self ):
1888
+ def f (a , b ):
1889
+ a &= b
1890
+ self .check_set_op_does_not_crash (f )
1891
+
1892
+ def test_ior_with_mutation (self ):
1893
+ def f (a , b ):
1894
+ a |= b
1895
+ self .check_set_op_does_not_crash (f )
1896
+
1897
+ def test_isub_with_mutation (self ):
1898
+ def f (a , b ):
1899
+ a -= b
1900
+ self .check_set_op_does_not_crash (f )
1901
+
1902
+ def test_ixor_with_mutation (self ):
1903
+ def f (a , b ):
1904
+ a ^= b
1905
+ self .check_set_op_does_not_crash (f )
1906
+
1907
+ def test_iteration_with_mutation (self ):
1908
+ def f1 (a , b ):
1909
+ for x in a :
1910
+ pass
1911
+ for y in b :
1912
+ pass
1913
+ def f2 (a , b ):
1914
+ for y in b :
1915
+ pass
1916
+ for x in a :
1917
+ pass
1918
+ def f3 (a , b ):
1919
+ for x , y in zip (a , b ):
1920
+ pass
1921
+ self .check_set_op_does_not_crash (f1 )
1922
+ self .check_set_op_does_not_crash (f2 )
1923
+ self .check_set_op_does_not_crash (f3 )
1924
+
1925
+
1926
+ class TestBinaryOpsMutating_Set_Set (TestBinaryOpsMutating , unittest .TestCase ):
1927
+ constructor1 = set
1928
+ constructor2 = set
1929
+
1930
+ class TestBinaryOpsMutating_Subclass_Subclass (TestBinaryOpsMutating , unittest .TestCase ):
1931
+ constructor1 = SetSubclass
1932
+ constructor2 = SetSubclass
1933
+
1934
+ class TestBinaryOpsMutating_Set_Subclass (TestBinaryOpsMutating , unittest .TestCase ):
1935
+ constructor1 = set
1936
+ constructor2 = SetSubclass
1937
+
1938
+ class TestBinaryOpsMutating_Subclass_Set (TestBinaryOpsMutating , unittest .TestCase ):
1939
+ constructor1 = SetSubclass
1940
+ constructor2 = set
1941
+
1942
+
1943
+ class TestMethodsMutating (TestOperationsMutating ):
1944
+
1945
+ def test_issubset_with_mutation (self ):
1946
+ self .check_set_op_does_not_crash (set .issubset )
1947
+
1948
+ def test_issuperset_with_mutation (self ):
1949
+ self .check_set_op_does_not_crash (set .issuperset )
1950
+
1951
+ def test_intersection_with_mutation (self ):
1952
+ self .check_set_op_does_not_crash (set .intersection )
1953
+
1954
+ def test_union_with_mutation (self ):
1955
+ self .check_set_op_does_not_crash (set .union )
1956
+
1957
+ def test_difference_with_mutation (self ):
1958
+ self .check_set_op_does_not_crash (set .difference )
1959
+
1960
+ def test_symmetric_difference_with_mutation (self ):
1961
+ self .check_set_op_does_not_crash (set .symmetric_difference )
1962
+
1963
+ def test_isdisjoint_with_mutation (self ):
1964
+ self .check_set_op_does_not_crash (set .isdisjoint )
1965
+
1966
+ def test_difference_update_with_mutation (self ):
1967
+ self .check_set_op_does_not_crash (set .difference_update )
1968
+
1969
+ def test_intersection_update_with_mutation (self ):
1970
+ self .check_set_op_does_not_crash (set .intersection_update )
1971
+
1972
+ def test_symmetric_difference_update_with_mutation (self ):
1973
+ self .check_set_op_does_not_crash (set .symmetric_difference_update )
1974
+
1975
+ def test_update_with_mutation (self ):
1976
+ self .check_set_op_does_not_crash (set .update )
1977
+
1978
+
1979
+ class TestMethodsMutating_Set_Set (TestMethodsMutating , unittest .TestCase ):
1980
+ constructor1 = set
1981
+ constructor2 = set
1982
+
1983
+ class TestMethodsMutating_Subclass_Subclass (TestMethodsMutating , unittest .TestCase ):
1984
+ constructor1 = SetSubclass
1985
+ constructor2 = SetSubclass
1986
+
1987
+ class TestMethodsMutating_Set_Subclass (TestMethodsMutating , unittest .TestCase ):
1988
+ constructor1 = set
1989
+ constructor2 = SetSubclass
1990
+
1991
+ class TestMethodsMutating_Subclass_Set (TestMethodsMutating , unittest .TestCase ):
1992
+ constructor1 = SetSubclass
1993
+ constructor2 = set
1994
+
1995
+ class TestMethodsMutating_Set_Dict (TestMethodsMutating , unittest .TestCase ):
1996
+ constructor1 = set
1997
+ constructor2 = dict .fromkeys
1998
+
1999
+ class TestMethodsMutating_Set_List (TestMethodsMutating , unittest .TestCase ):
2000
+ constructor1 = set
2001
+ constructor2 = list
2002
+
2003
+
1818
2004
# Application tests (based on David Eppstein's graph recipes ====================================
1819
2005
1820
2006
def powerset (U ):
0 commit comments