|
| 1 | +use super::super::testing::crash_test::{CrashTestDummy, Panic}; |
1 | 2 | use super::super::testing::ord_chaos::{Cyclic3, Governed, Governor};
|
2 | 3 | use super::super::testing::rng::DeterministicRng;
|
3 | 4 | use super::Entry::{Occupied, Vacant};
|
@@ -1134,103 +1135,78 @@ mod test_drain_filter {
|
1134 | 1135 |
|
1135 | 1136 | #[test]
|
1136 | 1137 | fn drop_panic_leak() {
|
1137 |
| - static PREDS: AtomicUsize = AtomicUsize::new(0); |
1138 |
| - static DROPS: AtomicUsize = AtomicUsize::new(0); |
1139 |
| - |
1140 |
| - struct D; |
1141 |
| - impl Drop for D { |
1142 |
| - fn drop(&mut self) { |
1143 |
| - if DROPS.fetch_add(1, SeqCst) == 1 { |
1144 |
| - panic!("panic in `drop`"); |
1145 |
| - } |
1146 |
| - } |
1147 |
| - } |
1148 |
| - |
1149 |
| - // Keys are multiples of 4, so that each key is counted by a hexadecimal digit. |
1150 |
| - 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), ()); |
1151 | 1145 |
|
1152 |
| - catch_unwind(move || { |
1153 |
| - drop(map.drain_filter(|i, _| { |
1154 |
| - PREDS.fetch_add(1usize << i, SeqCst); |
1155 |
| - true |
1156 |
| - })) |
1157 |
| - }) |
1158 |
| - .unwrap_err(); |
| 1146 | + catch_unwind(move || drop(map.drain_filter(|dummy, _| dummy.query(true)))).unwrap_err(); |
1159 | 1147 |
|
1160 |
| - assert_eq!(PREDS.load(SeqCst), 0x011); |
1161 |
| - 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); |
1162 | 1154 | }
|
1163 | 1155 |
|
1164 | 1156 | #[test]
|
1165 | 1157 | fn pred_panic_leak() {
|
1166 |
| - static PREDS: AtomicUsize = AtomicUsize::new(0); |
1167 |
| - static DROPS: AtomicUsize = AtomicUsize::new(0); |
1168 |
| - |
1169 |
| - struct D; |
1170 |
| - impl Drop for D { |
1171 |
| - fn drop(&mut self) { |
1172 |
| - DROPS.fetch_add(1, SeqCst); |
1173 |
| - } |
1174 |
| - } |
1175 |
| - |
1176 |
| - // Keys are multiples of 4, so that each key is counted by a hexadecimal digit. |
1177 |
| - let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>(); |
1178 |
| - |
1179 |
| - catch_unwind(AssertUnwindSafe(|| { |
1180 |
| - drop(map.drain_filter(|i, _| { |
1181 |
| - PREDS.fetch_add(1usize << i, SeqCst); |
1182 |
| - match i { |
1183 |
| - 0 => true, |
1184 |
| - _ => panic!(), |
1185 |
| - } |
1186 |
| - })) |
1187 |
| - })) |
1188 |
| - .unwrap_err(); |
1189 |
| - |
1190 |
| - assert_eq!(PREDS.load(SeqCst), 0x011); |
1191 |
| - 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); |
1192 | 1175 | assert_eq!(map.len(), 2);
|
1193 |
| - assert_eq!(map.first_entry().unwrap().key(), &4); |
1194 |
| - 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); |
1195 | 1178 | map.check();
|
1196 | 1179 | }
|
1197 | 1180 |
|
1198 | 1181 | // Same as above, but attempt to use the iterator again after the panic in the predicate
|
1199 | 1182 | #[test]
|
1200 | 1183 | fn pred_panic_reuse() {
|
1201 |
| - static PREDS: AtomicUsize = AtomicUsize::new(0); |
1202 |
| - static DROPS: AtomicUsize = AtomicUsize::new(0); |
1203 |
| - |
1204 |
| - struct D; |
1205 |
| - impl Drop for D { |
1206 |
| - fn drop(&mut self) { |
1207 |
| - DROPS.fetch_add(1, SeqCst); |
1208 |
| - } |
1209 |
| - } |
1210 |
| - |
1211 |
| - // Keys are multiples of 4, so that each key is counted by a hexadecimal digit. |
1212 |
| - 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), ()); |
1213 | 1191 |
|
1214 | 1192 | {
|
1215 |
| - let mut it = map.drain_filter(|i, _| { |
1216 |
| - PREDS.fetch_add(1usize << i, SeqCst); |
1217 |
| - match i { |
1218 |
| - 0 => true, |
1219 |
| - _ => panic!(), |
1220 |
| - } |
1221 |
| - }); |
| 1193 | + let mut it = map.drain_filter(|dummy, _| dummy.query(true)); |
1222 | 1194 | catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
|
1223 | 1195 | // Iterator behaviour after a panic is explicitly unspecified,
|
1224 | 1196 | // so this is just the current implementation:
|
1225 | 1197 | let result = catch_unwind(AssertUnwindSafe(|| it.next()));
|
1226 | 1198 | assert!(matches!(result, Ok(None)));
|
1227 | 1199 | }
|
1228 | 1200 |
|
1229 |
| - assert_eq!(PREDS.load(SeqCst), 0x011); |
1230 |
| - 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); |
1231 | 1207 | assert_eq!(map.len(), 2);
|
1232 |
| - assert_eq!(map.first_entry().unwrap().key(), &4); |
1233 |
| - 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); |
1234 | 1210 | map.check();
|
1235 | 1211 | }
|
1236 | 1212 | }
|
@@ -1437,6 +1413,43 @@ fn test_bad_zst() {
|
1437 | 1413 | m.check();
|
1438 | 1414 | }
|
1439 | 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 | + |
1440 | 1453 | #[test]
|
1441 | 1454 | fn test_clone() {
|
1442 | 1455 | let mut map = BTreeMap::new();
|
@@ -1482,6 +1495,35 @@ fn test_clone() {
|
1482 | 1495 | map.check();
|
1483 | 1496 | }
|
1484 | 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 | + |
1485 | 1527 | #[test]
|
1486 | 1528 | fn test_clone_from() {
|
1487 | 1529 | let mut map1 = BTreeMap::new();
|
@@ -1899,29 +1941,21 @@ create_append_test!(test_append_1700, 1700);
|
1899 | 1941 |
|
1900 | 1942 | #[test]
|
1901 | 1943 | fn test_append_drop_leak() {
|
1902 |
| - static DROPS: AtomicUsize = AtomicUsize::new(0); |
1903 |
| - |
1904 |
| - struct D; |
1905 |
| - |
1906 |
| - impl Drop for D { |
1907 |
| - fn drop(&mut self) { |
1908 |
| - if DROPS.fetch_add(1, SeqCst) == 0 { |
1909 |
| - panic!("panic in `drop`"); |
1910 |
| - } |
1911 |
| - } |
1912 |
| - } |
1913 |
| - |
| 1944 | + let a = CrashTestDummy::new(0); |
| 1945 | + let b = CrashTestDummy::new(1); |
| 1946 | + let c = CrashTestDummy::new(2); |
1914 | 1947 | let mut left = BTreeMap::new();
|
1915 | 1948 | let mut right = BTreeMap::new();
|
1916 |
| - left.insert(0, D); |
1917 |
| - left.insert(1, D); // first to be dropped during append |
1918 |
| - left.insert(2, D); |
1919 |
| - right.insert(1, D); |
1920 |
| - 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), ()); |
1921 | 1954 |
|
1922 | 1955 | catch_unwind(move || left.append(&mut right)).unwrap_err();
|
1923 |
| - |
1924 |
| - 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); |
1925 | 1959 | }
|
1926 | 1960 |
|
1927 | 1961 | #[test]
|
@@ -2048,51 +2082,42 @@ fn test_split_off_large_random_sorted() {
|
2048 | 2082 |
|
2049 | 2083 | #[test]
|
2050 | 2084 | fn test_into_iter_drop_leak_height_0() {
|
2051 |
| - static DROPS: AtomicUsize = AtomicUsize::new(0); |
2052 |
| - |
2053 |
| - struct D; |
2054 |
| - |
2055 |
| - impl Drop for D { |
2056 |
| - fn drop(&mut self) { |
2057 |
| - if DROPS.fetch_add(1, SeqCst) == 3 { |
2058 |
| - panic!("panic in `drop`"); |
2059 |
| - } |
2060 |
| - } |
2061 |
| - } |
2062 |
| - |
| 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); |
2063 | 2090 | let mut map = BTreeMap::new();
|
2064 |
| - map.insert("a", D); |
2065 |
| - map.insert("b", D); |
2066 |
| - map.insert("c", D); |
2067 |
| - map.insert("d", D); |
2068 |
| - 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)); |
2069 | 2096 |
|
2070 | 2097 | catch_unwind(move || drop(map.into_iter())).unwrap_err();
|
2071 | 2098 |
|
2072 |
| - 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); |
2073 | 2104 | }
|
2074 | 2105 |
|
2075 | 2106 | #[test]
|
2076 | 2107 | fn test_into_iter_drop_leak_height_1() {
|
2077 | 2108 | let size = MIN_INSERTS_HEIGHT_1;
|
2078 |
| - static DROPS: AtomicUsize = AtomicUsize::new(0); |
2079 |
| - static PANIC_POINT: AtomicUsize = AtomicUsize::new(0); |
2080 |
| - |
2081 |
| - struct D; |
2082 |
| - impl Drop for D { |
2083 |
| - fn drop(&mut self) { |
2084 |
| - if DROPS.fetch_add(1, SeqCst) == PANIC_POINT.load(SeqCst) { |
2085 |
| - panic!("panic in `drop`"); |
2086 |
| - } |
2087 |
| - } |
2088 |
| - } |
2089 |
| - |
2090 | 2109 | for panic_point in vec![0, 1, size - 2, size - 1] {
|
2091 |
| - DROPS.store(0, SeqCst); |
2092 |
| - PANIC_POINT.store(panic_point, SeqCst); |
2093 |
| - 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(); |
2094 | 2117 | catch_unwind(move || drop(map.into_iter())).unwrap_err();
|
2095 |
| - assert_eq!(DROPS.load(SeqCst), size); |
| 2118 | + for i in 0..size { |
| 2119 | + assert_eq!(dummies[i].dropped(), 2); |
| 2120 | + } |
2096 | 2121 | }
|
2097 | 2122 | }
|
2098 | 2123 |
|
|
0 commit comments