|
| 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