|
| 1 | +use super::super::testing::crash_test::{CrashTest, 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,60 @@ 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 | | - } |
| 1138 | + let test = CrashTest::new(); |
| 1139 | + let mut map = BTreeMap::new(); |
| 1140 | + map.insert(test.dummy(0, Panic::Never), ()); |
| 1141 | + map.insert(test.dummy(1, Panic::InDrop), ()); |
| 1142 | + map.insert(test.dummy(2, Panic::Never), ()); |
1148 | 1143 |
|
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<_, _>>(); |
| 1144 | + catch_unwind(move || drop(map.drain_filter(|dummy, _| dummy.query(true)))).unwrap_err(); |
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(); |
1159 | | - |
1160 | | - assert_eq!(PREDS.load(SeqCst), 0x011); |
1161 | | - assert_eq!(DROPS.load(SeqCst), 3); |
| 1146 | + assert_eq!(test.queried(), 0x011); |
| 1147 | + assert_eq!(test.dropped(), 0x111); |
1162 | 1148 | } |
1163 | 1149 |
|
1164 | 1150 | #[test] |
1165 | 1151 | 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<_, _>>(); |
| 1152 | + let test = CrashTest::new(); |
| 1153 | + let mut map = BTreeMap::new(); |
| 1154 | + map.insert(test.dummy(0, Panic::Never), ()); |
| 1155 | + map.insert(test.dummy(1, Panic::InQuery), ()); |
| 1156 | + map.insert(test.dummy(2, Panic::InQuery), ()); |
1178 | 1157 |
|
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(); |
| 1158 | + catch_unwind(AssertUnwindSafe(|| drop(map.drain_filter(|dummy, _| dummy.query(true))))) |
| 1159 | + .unwrap_err(); |
1189 | 1160 |
|
1190 | | - assert_eq!(PREDS.load(SeqCst), 0x011); |
1191 | | - assert_eq!(DROPS.load(SeqCst), 1); |
| 1161 | + assert_eq!(test.queried(), 0x011); |
| 1162 | + assert_eq!(test.dropped(), 0x001); |
1192 | 1163 | assert_eq!(map.len(), 2); |
1193 | | - assert_eq!(map.first_entry().unwrap().key(), &4); |
1194 | | - assert_eq!(map.last_entry().unwrap().key(), &8); |
| 1164 | + assert_eq!(map.first_entry().unwrap().key().id, 1); |
| 1165 | + assert_eq!(map.last_entry().unwrap().key().id, 2); |
1195 | 1166 | map.check(); |
1196 | 1167 | } |
1197 | 1168 |
|
1198 | 1169 | // Same as above, but attempt to use the iterator again after the panic in the predicate |
1199 | 1170 | #[test] |
1200 | 1171 | 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<_, _>>(); |
| 1172 | + let test = CrashTest::new(); |
| 1173 | + let mut map = BTreeMap::new(); |
| 1174 | + map.insert(test.dummy(0, Panic::Never), ()); |
| 1175 | + map.insert(test.dummy(1, Panic::InQuery), ()); |
| 1176 | + map.insert(test.dummy(2, Panic::InQuery), ()); |
1213 | 1177 |
|
1214 | 1178 | { |
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 | | - }); |
| 1179 | + let mut it = map.drain_filter(|dummy, _| dummy.query(true)); |
1222 | 1180 | catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err(); |
1223 | 1181 | // Iterator behaviour after a panic is explicitly unspecified, |
1224 | 1182 | // so this is just the current implementation: |
1225 | 1183 | let result = catch_unwind(AssertUnwindSafe(|| it.next())); |
1226 | 1184 | assert!(matches!(result, Ok(None))); |
1227 | 1185 | } |
1228 | 1186 |
|
1229 | | - assert_eq!(PREDS.load(SeqCst), 0x011); |
1230 | | - assert_eq!(DROPS.load(SeqCst), 1); |
| 1187 | + assert_eq!(test.queried(), 0x011); |
| 1188 | + assert_eq!(test.dropped(), 0x001); |
1231 | 1189 | assert_eq!(map.len(), 2); |
1232 | | - assert_eq!(map.first_entry().unwrap().key(), &4); |
1233 | | - assert_eq!(map.last_entry().unwrap().key(), &8); |
| 1190 | + assert_eq!(map.first_entry().unwrap().key().id, 1); |
| 1191 | + assert_eq!(map.last_entry().unwrap().key().id, 2); |
1234 | 1192 | map.check(); |
1235 | 1193 | } |
1236 | 1194 | } |
@@ -1482,6 +1440,25 @@ fn test_clone() { |
1482 | 1440 | map.check(); |
1483 | 1441 | } |
1484 | 1442 |
|
| 1443 | +#[test] |
| 1444 | +fn test_clone_panic_leak() { |
| 1445 | + let test = CrashTest::new(); |
| 1446 | + |
| 1447 | + let mut map = BTreeMap::new(); |
| 1448 | + map.insert(test.dummy(0, Panic::Never), ()); |
| 1449 | + map.insert(test.dummy(1, Panic::InClone), ()); |
| 1450 | + map.insert(test.dummy(2, Panic::Never), ()); |
| 1451 | + |
| 1452 | + catch_unwind(|| map.clone()).unwrap_err(); |
| 1453 | + assert_eq!(test.cloned(), 0x011); |
| 1454 | + assert_eq!(test.dropped(), 0x001); |
| 1455 | + assert_eq!(map.len(), 3); |
| 1456 | + |
| 1457 | + drop(map); |
| 1458 | + assert_eq!(test.cloned(), 0x011); |
| 1459 | + assert_eq!(test.dropped(), 0x112); |
| 1460 | +} |
| 1461 | + |
1485 | 1462 | #[test] |
1486 | 1463 | fn test_clone_from() { |
1487 | 1464 | let mut map1 = BTreeMap::new(); |
@@ -1858,29 +1835,18 @@ create_append_test!(test_append_1700, 1700); |
1858 | 1835 |
|
1859 | 1836 | #[test] |
1860 | 1837 | fn test_append_drop_leak() { |
1861 | | - static DROPS: AtomicUsize = AtomicUsize::new(0); |
1862 | | - |
1863 | | - struct D; |
1864 | | - |
1865 | | - impl Drop for D { |
1866 | | - fn drop(&mut self) { |
1867 | | - if DROPS.fetch_add(1, SeqCst) == 0 { |
1868 | | - panic!("panic in `drop`"); |
1869 | | - } |
1870 | | - } |
1871 | | - } |
1872 | | - |
| 1838 | + let test = CrashTest::new(); |
1873 | 1839 | let mut left = BTreeMap::new(); |
1874 | 1840 | let mut right = BTreeMap::new(); |
1875 | | - left.insert(0, D); |
1876 | | - left.insert(1, D); // first to be dropped during append |
1877 | | - left.insert(2, D); |
1878 | | - right.insert(1, D); |
1879 | | - right.insert(2, D); |
| 1841 | + left.insert(test.dummy(0, Panic::Never), ()); |
| 1842 | + left.insert(test.dummy(1, Panic::InDrop), ()); // first duplicate key, dropped during append |
| 1843 | + left.insert(test.dummy(2, Panic::Never), ()); |
| 1844 | + right.insert(test.dummy(1, Panic::Never), ()); |
| 1845 | + right.insert(test.dummy(2, Panic::Never), ()); |
1880 | 1846 |
|
1881 | 1847 | catch_unwind(move || left.append(&mut right)).unwrap_err(); |
1882 | 1848 |
|
1883 | | - assert_eq!(DROPS.load(SeqCst), 5); |
| 1849 | + assert_eq!(test.dropped(), 0x221); |
1884 | 1850 | } |
1885 | 1851 |
|
1886 | 1852 | #[test] |
@@ -2007,51 +1973,32 @@ fn test_split_off_large_random_sorted() { |
2007 | 1973 |
|
2008 | 1974 | #[test] |
2009 | 1975 | fn test_into_iter_drop_leak_height_0() { |
2010 | | - static DROPS: AtomicUsize = AtomicUsize::new(0); |
2011 | | - |
2012 | | - struct D; |
2013 | | - |
2014 | | - impl Drop for D { |
2015 | | - fn drop(&mut self) { |
2016 | | - if DROPS.fetch_add(1, SeqCst) == 3 { |
2017 | | - panic!("panic in `drop`"); |
2018 | | - } |
2019 | | - } |
2020 | | - } |
2021 | | - |
| 1976 | + let test = CrashTest::new(); |
2022 | 1977 | let mut map = BTreeMap::new(); |
2023 | | - map.insert("a", D); |
2024 | | - map.insert("b", D); |
2025 | | - map.insert("c", D); |
2026 | | - map.insert("d", D); |
2027 | | - map.insert("e", D); |
| 1978 | + map.insert("a", test.dummy(0, Panic::Never)); |
| 1979 | + map.insert("b", test.dummy(1, Panic::Never)); |
| 1980 | + map.insert("c", test.dummy(2, Panic::Never)); |
| 1981 | + map.insert("d", test.dummy(3, Panic::InDrop)); |
| 1982 | + map.insert("e", test.dummy(4, Panic::Never)); |
2028 | 1983 |
|
2029 | 1984 | catch_unwind(move || drop(map.into_iter())).unwrap_err(); |
2030 | 1985 |
|
2031 | | - assert_eq!(DROPS.load(SeqCst), 5); |
| 1986 | + assert_eq!(test.dropped(), 0x11111); |
2032 | 1987 | } |
2033 | 1988 |
|
2034 | 1989 | #[test] |
2035 | 1990 | fn test_into_iter_drop_leak_height_1() { |
2036 | 1991 | let size = MIN_INSERTS_HEIGHT_1; |
2037 | | - static DROPS: AtomicUsize = AtomicUsize::new(0); |
2038 | | - static PANIC_POINT: AtomicUsize = AtomicUsize::new(0); |
2039 | | - |
2040 | | - struct D; |
2041 | | - impl Drop for D { |
2042 | | - fn drop(&mut self) { |
2043 | | - if DROPS.fetch_add(1, SeqCst) == PANIC_POINT.load(SeqCst) { |
2044 | | - panic!("panic in `drop`"); |
2045 | | - } |
2046 | | - } |
2047 | | - } |
2048 | | - |
2049 | 1992 | for panic_point in vec![0, 1, size - 2, size - 1] { |
2050 | | - DROPS.store(0, SeqCst); |
2051 | | - PANIC_POINT.store(panic_point, SeqCst); |
2052 | | - let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect(); |
| 1993 | + let test = CrashTest::new_totaling(); |
| 1994 | + let map: BTreeMap<_, _> = (0..size) |
| 1995 | + .map(|i| { |
| 1996 | + let panic = if i == panic_point { Panic::InDrop } else { Panic::Never }; |
| 1997 | + (test.dummy(i, Panic::Never), test.dummy(i, panic)) |
| 1998 | + }) |
| 1999 | + .collect(); |
2053 | 2000 | catch_unwind(move || drop(map.into_iter())).unwrap_err(); |
2054 | | - assert_eq!(DROPS.load(SeqCst), size); |
| 2001 | + assert_eq!(test.dropped(), size as u64 * 2); |
2055 | 2002 | } |
2056 | 2003 | } |
2057 | 2004 |
|
|
0 commit comments