1- use super :: super :: { node, DeterministicRng } ;
1+ use super :: super :: testing:: crash_test:: { CrashTestDummy , Panic } ;
2+ use super :: super :: testing:: ord_chaos:: { Cyclic3 , Governed , Governor } ;
3+ use super :: super :: testing:: rng:: DeterministicRng ;
24use super :: Entry :: { Occupied , Vacant } ;
35use super :: * ;
46use crate :: boxed:: Box ;
@@ -15,9 +17,6 @@ use std::ops::RangeBounds;
1517use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
1618use std:: sync:: atomic:: { AtomicUsize , Ordering :: SeqCst } ;
1719
18- mod ord_chaos;
19- use ord_chaos:: { Cyclic3 , Governed , Governor } ;
20-
2120// Capacity of a tree with a single level,
2221// i.e., a tree who's root is a leaf node at height 0.
2322const NODE_CAPACITY : usize = node:: CAPACITY ;
@@ -1136,103 +1135,78 @@ mod test_drain_filter {
11361135
11371136 #[ test]
11381137 fn drop_panic_leak ( ) {
1139- static PREDS : AtomicUsize = AtomicUsize :: new ( 0 ) ;
1140- static DROPS : AtomicUsize = AtomicUsize :: new ( 0 ) ;
1141-
1142- struct D ;
1143- impl Drop for D {
1144- fn drop ( & mut self ) {
1145- if DROPS . fetch_add ( 1 , SeqCst ) == 1 {
1146- panic ! ( "panic in `drop`" ) ;
1147- }
1148- }
1149- }
1150-
1151- // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
1152- let mut map = ( 0 ..3 ) . map ( |i| ( i * 4 , D ) ) . collect :: < BTreeMap < _ , _ > > ( ) ;
1138+ let a = CrashTestDummy :: new ( 0 ) ;
1139+ let b = CrashTestDummy :: new ( 1 ) ;
1140+ let c = CrashTestDummy :: new ( 2 ) ;
1141+ let mut map = BTreeMap :: new ( ) ;
1142+ map. insert ( a. spawn ( Panic :: Never ) , ( ) ) ;
1143+ map. insert ( b. spawn ( Panic :: InDrop ) , ( ) ) ;
1144+ map. insert ( c. spawn ( Panic :: Never ) , ( ) ) ;
11531145
1154- catch_unwind ( move || {
1155- drop ( map. drain_filter ( |i, _| {
1156- PREDS . fetch_add ( 1usize << i, SeqCst ) ;
1157- true
1158- } ) )
1159- } )
1160- . unwrap_err ( ) ;
1146+ catch_unwind ( move || drop ( map. drain_filter ( |dummy, _| dummy. query ( true ) ) ) ) . unwrap_err ( ) ;
11611147
1162- assert_eq ! ( PREDS . load( SeqCst ) , 0x011 ) ;
1163- assert_eq ! ( DROPS . load( SeqCst ) , 3 ) ;
1148+ assert_eq ! ( a. queried( ) , 1 ) ;
1149+ assert_eq ! ( b. queried( ) , 1 ) ;
1150+ assert_eq ! ( c. queried( ) , 0 ) ;
1151+ assert_eq ! ( a. dropped( ) , 1 ) ;
1152+ assert_eq ! ( b. dropped( ) , 1 ) ;
1153+ assert_eq ! ( c. dropped( ) , 1 ) ;
11641154 }
11651155
11661156 #[ test]
11671157 fn pred_panic_leak ( ) {
1168- static PREDS : AtomicUsize = AtomicUsize :: new ( 0 ) ;
1169- static DROPS : AtomicUsize = AtomicUsize :: new ( 0 ) ;
1170-
1171- struct D ;
1172- impl Drop for D {
1173- fn drop ( & mut self ) {
1174- DROPS . fetch_add ( 1 , SeqCst ) ;
1175- }
1176- }
1177-
1178- // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
1179- let mut map = ( 0 ..3 ) . map ( |i| ( i * 4 , D ) ) . collect :: < BTreeMap < _ , _ > > ( ) ;
1180-
1181- catch_unwind ( AssertUnwindSafe ( || {
1182- drop ( map. drain_filter ( |i, _| {
1183- PREDS . fetch_add ( 1usize << i, SeqCst ) ;
1184- match i {
1185- 0 => true ,
1186- _ => panic ! ( ) ,
1187- }
1188- } ) )
1189- } ) )
1190- . unwrap_err ( ) ;
1191-
1192- assert_eq ! ( PREDS . load( SeqCst ) , 0x011 ) ;
1193- assert_eq ! ( DROPS . load( SeqCst ) , 1 ) ;
1158+ let a = CrashTestDummy :: new ( 0 ) ;
1159+ let b = CrashTestDummy :: new ( 1 ) ;
1160+ let c = CrashTestDummy :: new ( 2 ) ;
1161+ let mut map = BTreeMap :: new ( ) ;
1162+ map. insert ( a. spawn ( Panic :: Never ) , ( ) ) ;
1163+ map. insert ( b. spawn ( Panic :: InQuery ) , ( ) ) ;
1164+ map. insert ( c. spawn ( Panic :: InQuery ) , ( ) ) ;
1165+
1166+ catch_unwind ( AssertUnwindSafe ( || drop ( map. drain_filter ( |dummy, _| dummy. query ( true ) ) ) ) )
1167+ . unwrap_err ( ) ;
1168+
1169+ assert_eq ! ( a. queried( ) , 1 ) ;
1170+ assert_eq ! ( b. queried( ) , 1 ) ;
1171+ assert_eq ! ( c. queried( ) , 0 ) ;
1172+ assert_eq ! ( a. dropped( ) , 1 ) ;
1173+ assert_eq ! ( b. dropped( ) , 0 ) ;
1174+ assert_eq ! ( c. dropped( ) , 0 ) ;
11941175 assert_eq ! ( map. len( ) , 2 ) ;
1195- assert_eq ! ( map. first_entry( ) . unwrap( ) . key( ) , & 4 ) ;
1196- assert_eq ! ( map. last_entry( ) . unwrap( ) . key( ) , & 8 ) ;
1176+ assert_eq ! ( map. first_entry( ) . unwrap( ) . key( ) . id ( ) , 1 ) ;
1177+ assert_eq ! ( map. last_entry( ) . unwrap( ) . key( ) . id ( ) , 2 ) ;
11971178 map. check ( ) ;
11981179 }
11991180
12001181 // Same as above, but attempt to use the iterator again after the panic in the predicate
12011182 #[ test]
12021183 fn pred_panic_reuse ( ) {
1203- static PREDS : AtomicUsize = AtomicUsize :: new ( 0 ) ;
1204- static DROPS : AtomicUsize = AtomicUsize :: new ( 0 ) ;
1205-
1206- struct D ;
1207- impl Drop for D {
1208- fn drop ( & mut self ) {
1209- DROPS . fetch_add ( 1 , SeqCst ) ;
1210- }
1211- }
1212-
1213- // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
1214- let mut map = ( 0 ..3 ) . map ( |i| ( i * 4 , D ) ) . collect :: < BTreeMap < _ , _ > > ( ) ;
1184+ let a = CrashTestDummy :: new ( 0 ) ;
1185+ let b = CrashTestDummy :: new ( 1 ) ;
1186+ let c = CrashTestDummy :: new ( 2 ) ;
1187+ let mut map = BTreeMap :: new ( ) ;
1188+ map. insert ( a. spawn ( Panic :: Never ) , ( ) ) ;
1189+ map. insert ( b. spawn ( Panic :: InQuery ) , ( ) ) ;
1190+ map. insert ( c. spawn ( Panic :: InQuery ) , ( ) ) ;
12151191
12161192 {
1217- let mut it = map. drain_filter ( |i, _| {
1218- PREDS . fetch_add ( 1usize << i, SeqCst ) ;
1219- match i {
1220- 0 => true ,
1221- _ => panic ! ( ) ,
1222- }
1223- } ) ;
1193+ let mut it = map. drain_filter ( |dummy, _| dummy. query ( true ) ) ;
12241194 catch_unwind ( AssertUnwindSafe ( || while it. next ( ) . is_some ( ) { } ) ) . unwrap_err ( ) ;
12251195 // Iterator behaviour after a panic is explicitly unspecified,
12261196 // so this is just the current implementation:
12271197 let result = catch_unwind ( AssertUnwindSafe ( || it. next ( ) ) ) ;
12281198 assert ! ( matches!( result, Ok ( None ) ) ) ;
12291199 }
12301200
1231- assert_eq ! ( PREDS . load( SeqCst ) , 0x011 ) ;
1232- assert_eq ! ( DROPS . load( SeqCst ) , 1 ) ;
1201+ assert_eq ! ( a. queried( ) , 1 ) ;
1202+ assert_eq ! ( b. queried( ) , 1 ) ;
1203+ assert_eq ! ( c. queried( ) , 0 ) ;
1204+ assert_eq ! ( a. dropped( ) , 1 ) ;
1205+ assert_eq ! ( b. dropped( ) , 0 ) ;
1206+ assert_eq ! ( c. dropped( ) , 0 ) ;
12331207 assert_eq ! ( map. len( ) , 2 ) ;
1234- assert_eq ! ( map. first_entry( ) . unwrap( ) . key( ) , & 4 ) ;
1235- assert_eq ! ( map. last_entry( ) . unwrap( ) . key( ) , & 8 ) ;
1208+ assert_eq ! ( map. first_entry( ) . unwrap( ) . key( ) . id ( ) , 1 ) ;
1209+ assert_eq ! ( map. last_entry( ) . unwrap( ) . key( ) . id ( ) , 2 ) ;
12361210 map. check ( ) ;
12371211 }
12381212}
@@ -1439,6 +1413,43 @@ fn test_bad_zst() {
14391413 m. check ( ) ;
14401414}
14411415
1416+ #[ test]
1417+ fn test_clear ( ) {
1418+ let mut map = BTreeMap :: new ( ) ;
1419+ for & len in & [ MIN_INSERTS_HEIGHT_1 , MIN_INSERTS_HEIGHT_2 , 0 , NODE_CAPACITY ] {
1420+ for i in 0 ..len {
1421+ map. insert ( i, ( ) ) ;
1422+ }
1423+ assert_eq ! ( map. len( ) , len) ;
1424+ map. clear ( ) ;
1425+ map. check ( ) ;
1426+ assert ! ( map. is_empty( ) ) ;
1427+ }
1428+ }
1429+
1430+ #[ test]
1431+ fn test_clear_drop_panic_leak ( ) {
1432+ let a = CrashTestDummy :: new ( 0 ) ;
1433+ let b = CrashTestDummy :: new ( 1 ) ;
1434+ let c = CrashTestDummy :: new ( 2 ) ;
1435+
1436+ let mut map = BTreeMap :: new ( ) ;
1437+ map. insert ( a. spawn ( Panic :: Never ) , ( ) ) ;
1438+ map. insert ( b. spawn ( Panic :: InDrop ) , ( ) ) ;
1439+ map. insert ( c. spawn ( Panic :: Never ) , ( ) ) ;
1440+
1441+ catch_unwind ( AssertUnwindSafe ( || map. clear ( ) ) ) . unwrap_err ( ) ;
1442+ assert_eq ! ( a. dropped( ) , 1 ) ;
1443+ assert_eq ! ( b. dropped( ) , 1 ) ;
1444+ assert_eq ! ( c. dropped( ) , 1 ) ;
1445+ assert_eq ! ( map. len( ) , 0 ) ;
1446+
1447+ drop ( map) ;
1448+ assert_eq ! ( a. dropped( ) , 1 ) ;
1449+ assert_eq ! ( b. dropped( ) , 1 ) ;
1450+ assert_eq ! ( c. dropped( ) , 1 ) ;
1451+ }
1452+
14421453#[ test]
14431454fn test_clone ( ) {
14441455 let mut map = BTreeMap :: new ( ) ;
@@ -1484,6 +1495,35 @@ fn test_clone() {
14841495 map. check ( ) ;
14851496}
14861497
1498+ #[ test]
1499+ fn test_clone_panic_leak ( ) {
1500+ let a = CrashTestDummy :: new ( 0 ) ;
1501+ let b = CrashTestDummy :: new ( 1 ) ;
1502+ let c = CrashTestDummy :: new ( 2 ) ;
1503+
1504+ let mut map = BTreeMap :: new ( ) ;
1505+ map. insert ( a. spawn ( Panic :: Never ) , ( ) ) ;
1506+ map. insert ( b. spawn ( Panic :: InClone ) , ( ) ) ;
1507+ map. insert ( c. spawn ( Panic :: Never ) , ( ) ) ;
1508+
1509+ catch_unwind ( || map. clone ( ) ) . unwrap_err ( ) ;
1510+ assert_eq ! ( a. cloned( ) , 1 ) ;
1511+ assert_eq ! ( b. cloned( ) , 1 ) ;
1512+ assert_eq ! ( c. cloned( ) , 0 ) ;
1513+ assert_eq ! ( a. dropped( ) , 1 ) ;
1514+ assert_eq ! ( b. dropped( ) , 0 ) ;
1515+ assert_eq ! ( c. dropped( ) , 0 ) ;
1516+ assert_eq ! ( map. len( ) , 3 ) ;
1517+
1518+ drop ( map) ;
1519+ assert_eq ! ( a. cloned( ) , 1 ) ;
1520+ assert_eq ! ( b. cloned( ) , 1 ) ;
1521+ assert_eq ! ( c. cloned( ) , 0 ) ;
1522+ assert_eq ! ( a. dropped( ) , 2 ) ;
1523+ assert_eq ! ( b. dropped( ) , 1 ) ;
1524+ assert_eq ! ( c. dropped( ) , 1 ) ;
1525+ }
1526+
14871527#[ test]
14881528fn test_clone_from ( ) {
14891529 let mut map1 = BTreeMap :: new ( ) ;
@@ -1901,29 +1941,21 @@ create_append_test!(test_append_1700, 1700);
19011941
19021942#[ test]
19031943fn test_append_drop_leak ( ) {
1904- static DROPS : AtomicUsize = AtomicUsize :: new ( 0 ) ;
1905-
1906- struct D ;
1907-
1908- impl Drop for D {
1909- fn drop ( & mut self ) {
1910- if DROPS . fetch_add ( 1 , SeqCst ) == 0 {
1911- panic ! ( "panic in `drop`" ) ;
1912- }
1913- }
1914- }
1915-
1944+ let a = CrashTestDummy :: new ( 0 ) ;
1945+ let b = CrashTestDummy :: new ( 1 ) ;
1946+ let c = CrashTestDummy :: new ( 2 ) ;
19161947 let mut left = BTreeMap :: new ( ) ;
19171948 let mut right = BTreeMap :: new ( ) ;
1918- left. insert ( 0 , D ) ;
1919- left. insert ( 1 , D ) ; // first to be dropped during append
1920- left. insert ( 2 , D ) ;
1921- right. insert ( 1 , D ) ;
1922- right. insert ( 2 , D ) ;
1949+ left. insert ( a . spawn ( Panic :: Never ) , ( ) ) ;
1950+ left. insert ( b . spawn ( Panic :: InDrop ) , ( ) ) ; // first duplicate key, dropped during append
1951+ left. insert ( c . spawn ( Panic :: Never ) , ( ) ) ;
1952+ right. insert ( b . spawn ( Panic :: Never ) , ( ) ) ;
1953+ right. insert ( c . spawn ( Panic :: Never ) , ( ) ) ;
19231954
19241955 catch_unwind ( move || left. append ( & mut right) ) . unwrap_err ( ) ;
1925-
1926- assert_eq ! ( DROPS . load( SeqCst ) , 4 ) ; // Rust issue #47949 ate one little piggy
1956+ assert_eq ! ( a. dropped( ) , 1 ) ;
1957+ assert_eq ! ( b. dropped( ) , 1 ) ; // should be 2 were it not for Rust issue #47949
1958+ assert_eq ! ( c. dropped( ) , 2 ) ;
19271959}
19281960
19291961#[ test]
@@ -2050,51 +2082,42 @@ fn test_split_off_large_random_sorted() {
20502082
20512083#[ test]
20522084fn test_into_iter_drop_leak_height_0 ( ) {
2053- static DROPS : AtomicUsize = AtomicUsize :: new ( 0 ) ;
2054-
2055- struct D ;
2056-
2057- impl Drop for D {
2058- fn drop ( & mut self ) {
2059- if DROPS . fetch_add ( 1 , SeqCst ) == 3 {
2060- panic ! ( "panic in `drop`" ) ;
2061- }
2062- }
2063- }
2064-
2085+ let a = CrashTestDummy :: new ( 0 ) ;
2086+ let b = CrashTestDummy :: new ( 1 ) ;
2087+ let c = CrashTestDummy :: new ( 2 ) ;
2088+ let d = CrashTestDummy :: new ( 3 ) ;
2089+ let e = CrashTestDummy :: new ( 4 ) ;
20652090 let mut map = BTreeMap :: new ( ) ;
2066- map. insert ( "a" , D ) ;
2067- map. insert ( "b" , D ) ;
2068- map. insert ( "c" , D ) ;
2069- map. insert ( "d" , D ) ;
2070- map. insert ( "e" , D ) ;
2091+ map. insert ( "a" , a . spawn ( Panic :: Never ) ) ;
2092+ map. insert ( "b" , b . spawn ( Panic :: Never ) ) ;
2093+ map. insert ( "c" , c . spawn ( Panic :: Never ) ) ;
2094+ map. insert ( "d" , d . spawn ( Panic :: InDrop ) ) ;
2095+ map. insert ( "e" , e . spawn ( Panic :: Never ) ) ;
20712096
20722097 catch_unwind ( move || drop ( map. into_iter ( ) ) ) . unwrap_err ( ) ;
20732098
2074- assert_eq ! ( DROPS . load( SeqCst ) , 5 ) ;
2099+ assert_eq ! ( a. dropped( ) , 1 ) ;
2100+ assert_eq ! ( b. dropped( ) , 1 ) ;
2101+ assert_eq ! ( c. dropped( ) , 1 ) ;
2102+ assert_eq ! ( d. dropped( ) , 1 ) ;
2103+ assert_eq ! ( e. dropped( ) , 1 ) ;
20752104}
20762105
20772106#[ test]
20782107fn test_into_iter_drop_leak_height_1 ( ) {
20792108 let size = MIN_INSERTS_HEIGHT_1 ;
2080- static DROPS : AtomicUsize = AtomicUsize :: new ( 0 ) ;
2081- static PANIC_POINT : AtomicUsize = AtomicUsize :: new ( 0 ) ;
2082-
2083- struct D ;
2084- impl Drop for D {
2085- fn drop ( & mut self ) {
2086- if DROPS . fetch_add ( 1 , SeqCst ) == PANIC_POINT . load ( SeqCst ) {
2087- panic ! ( "panic in `drop`" ) ;
2088- }
2089- }
2090- }
2091-
20922109 for panic_point in vec ! [ 0 , 1 , size - 2 , size - 1 ] {
2093- DROPS . store ( 0 , SeqCst ) ;
2094- PANIC_POINT . store ( panic_point, SeqCst ) ;
2095- let map: BTreeMap < _ , _ > = ( 0 ..size) . map ( |i| ( i, D ) ) . collect ( ) ;
2110+ let dummies: Vec < _ > = ( 0 ..size) . map ( |i| CrashTestDummy :: new ( i) ) . collect ( ) ;
2111+ let map: BTreeMap < _ , _ > = ( 0 ..size)
2112+ . map ( |i| {
2113+ let panic = if i == panic_point { Panic :: InDrop } else { Panic :: Never } ;
2114+ ( dummies[ i] . spawn ( Panic :: Never ) , dummies[ i] . spawn ( panic) )
2115+ } )
2116+ . collect ( ) ;
20962117 catch_unwind ( move || drop ( map. into_iter ( ) ) ) . unwrap_err ( ) ;
2097- assert_eq ! ( DROPS . load( SeqCst ) , size) ;
2118+ for i in 0 ..size {
2119+ assert_eq ! ( dummies[ i] . dropped( ) , 2 ) ;
2120+ }
20982121 }
20992122}
21002123
0 commit comments