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 ;
2
4
use super :: Entry :: { Occupied , Vacant } ;
3
5
use super :: * ;
4
6
use crate :: boxed:: Box ;
@@ -15,9 +17,6 @@ use std::ops::RangeBounds;
15
17
use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
16
18
use std:: sync:: atomic:: { AtomicUsize , Ordering :: SeqCst } ;
17
19
18
- mod ord_chaos;
19
- use ord_chaos:: { Cyclic3 , Governed , Governor } ;
20
-
21
20
// Capacity of a tree with a single level,
22
21
// i.e., a tree who's root is a leaf node at height 0.
23
22
const NODE_CAPACITY : usize = node:: CAPACITY ;
@@ -1136,103 +1135,78 @@ mod test_drain_filter {
1136
1135
1137
1136
#[ test]
1138
1137
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 ) , ( ) ) ;
1153
1145
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 ( ) ;
1161
1147
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 ) ;
1164
1154
}
1165
1155
1166
1156
#[ test]
1167
1157
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 ) ;
1194
1175
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 ) ;
1197
1178
map. check ( ) ;
1198
1179
}
1199
1180
1200
1181
// Same as above, but attempt to use the iterator again after the panic in the predicate
1201
1182
#[ test]
1202
1183
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 ) , ( ) ) ;
1215
1191
1216
1192
{
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 ) ) ;
1224
1194
catch_unwind ( AssertUnwindSafe ( || while it. next ( ) . is_some ( ) { } ) ) . unwrap_err ( ) ;
1225
1195
// Iterator behaviour after a panic is explicitly unspecified,
1226
1196
// so this is just the current implementation:
1227
1197
let result = catch_unwind ( AssertUnwindSafe ( || it. next ( ) ) ) ;
1228
1198
assert ! ( matches!( result, Ok ( None ) ) ) ;
1229
1199
}
1230
1200
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 ) ;
1233
1207
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 ) ;
1236
1210
map. check ( ) ;
1237
1211
}
1238
1212
}
@@ -1439,6 +1413,43 @@ fn test_bad_zst() {
1439
1413
m. check ( ) ;
1440
1414
}
1441
1415
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
+
1442
1453
#[ test]
1443
1454
fn test_clone ( ) {
1444
1455
let mut map = BTreeMap :: new ( ) ;
@@ -1484,6 +1495,35 @@ fn test_clone() {
1484
1495
map. check ( ) ;
1485
1496
}
1486
1497
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
+
1487
1527
#[ test]
1488
1528
fn test_clone_from ( ) {
1489
1529
let mut map1 = BTreeMap :: new ( ) ;
@@ -1901,29 +1941,21 @@ create_append_test!(test_append_1700, 1700);
1901
1941
1902
1942
#[ test]
1903
1943
fn 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 ) ;
1916
1947
let mut left = BTreeMap :: new ( ) ;
1917
1948
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 ) , ( ) ) ;
1923
1954
1924
1955
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 ) ;
1927
1959
}
1928
1960
1929
1961
#[ test]
@@ -2050,51 +2082,42 @@ fn test_split_off_large_random_sorted() {
2050
2082
2051
2083
#[ test]
2052
2084
fn 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 ) ;
2065
2090
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 ) ) ;
2071
2096
2072
2097
catch_unwind ( move || drop ( map. into_iter ( ) ) ) . unwrap_err ( ) ;
2073
2098
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 ) ;
2075
2104
}
2076
2105
2077
2106
#[ test]
2078
2107
fn test_into_iter_drop_leak_height_1 ( ) {
2079
2108
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
-
2092
2109
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 ( ) ;
2096
2117
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
+ }
2098
2121
}
2099
2122
}
2100
2123
0 commit comments