Skip to content

Commit e515f26

Browse files
authored
Rollup merge of rust-lang#81300 - ssomers:btree_cleanup_leak_tests, r=Mark-Simulacrum
BTree: share panicky test code & test panic during clear, clone Bases almost all tests of panic on the same, richer definition, and extends it to cloning to test panic during clone. r? ``@Mark-Simulacrum``
2 parents d2b38d6 + 3e1d602 commit e515f26

File tree

7 files changed

+337
-217
lines changed

7 files changed

+337
-217
lines changed

library/alloc/src/collections/btree/map/tests.rs

+154-131
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
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;
24
use super::Entry::{Occupied, Vacant};
35
use super::*;
46
use crate::boxed::Box;
@@ -15,9 +17,6 @@ use std::ops::RangeBounds;
1517
use std::panic::{catch_unwind, AssertUnwindSafe};
1618
use 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.
2322
const 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]
14431454
fn 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]
14881528
fn test_clone_from() {
14891529
let mut map1 = BTreeMap::new();
@@ -1901,29 +1941,21 @@ create_append_test!(test_append_1700, 1700);
19011941

19021942
#[test]
19031943
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);
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]
20522084
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);
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]
20782107
fn 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

Comments
 (0)