Skip to content

Commit 440d869

Browse files
committed
BTreeMap: test panic during clone & share panicky test code
1 parent 5989b5f commit 440d869

File tree

4 files changed

+238
-180
lines changed

4 files changed

+238
-180
lines changed

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

+71-124
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::super::testing::crash_test::{CrashTest, Panic};
12
use super::super::testing::ord_chaos::{Cyclic3, Governed, Governor};
23
use super::super::testing::rng::DeterministicRng;
34
use super::Entry::{Occupied, Vacant};
@@ -1134,103 +1135,60 @@ mod test_drain_filter {
11341135

11351136
#[test]
11361137
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), ());
11481143

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();
11511145

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);
11621148
}
11631149

11641150
#[test]
11651151
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), ());
11781157

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();
11891160

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);
11921163
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);
11951166
map.check();
11961167
}
11971168

11981169
// Same as above, but attempt to use the iterator again after the panic in the predicate
11991170
#[test]
12001171
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), ());
12131177

12141178
{
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));
12221180
catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
12231181
// Iterator behaviour after a panic is explicitly unspecified,
12241182
// so this is just the current implementation:
12251183
let result = catch_unwind(AssertUnwindSafe(|| it.next()));
12261184
assert!(matches!(result, Ok(None)));
12271185
}
12281186

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);
12311189
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);
12341192
map.check();
12351193
}
12361194
}
@@ -1482,6 +1440,25 @@ fn test_clone() {
14821440
map.check();
14831441
}
14841442

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+
14851462
#[test]
14861463
fn test_clone_from() {
14871464
let mut map1 = BTreeMap::new();
@@ -1858,29 +1835,18 @@ create_append_test!(test_append_1700, 1700);
18581835

18591836
#[test]
18601837
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();
18731839
let mut left = BTreeMap::new();
18741840
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), ());
18801846

18811847
catch_unwind(move || left.append(&mut right)).unwrap_err();
18821848

1883-
assert_eq!(DROPS.load(SeqCst), 5);
1849+
assert_eq!(test.dropped(), 0x221);
18841850
}
18851851

18861852
#[test]
@@ -2007,51 +1973,32 @@ fn test_split_off_large_random_sorted() {
20071973

20081974
#[test]
20091975
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();
20221977
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));
20281983

20291984
catch_unwind(move || drop(map.into_iter())).unwrap_err();
20301985

2031-
assert_eq!(DROPS.load(SeqCst), 5);
1986+
assert_eq!(test.dropped(), 0x11111);
20321987
}
20331988

20341989
#[test]
20351990
fn test_into_iter_drop_leak_height_1() {
20361991
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-
20491992
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();
20532000
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);
20552002
}
20562003
}
20572004

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

+19-56
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
use super::super::testing::crash_test::{CrashTest, Panic};
12
use super::super::testing::rng::DeterministicRng;
23
use super::*;
34
use crate::vec::Vec;
45
use std::cmp::Ordering;
56
use std::iter::FromIterator;
67
use std::panic::{catch_unwind, AssertUnwindSafe};
7-
use std::sync::atomic::{AtomicU32, Ordering::SeqCst};
88

99
#[test]
1010
fn test_clone_eq() {
@@ -349,70 +349,33 @@ fn test_drain_filter() {
349349

350350
#[test]
351351
fn test_drain_filter_drop_panic_leak() {
352-
static PREDS: AtomicU32 = AtomicU32::new(0);
353-
static DROPS: AtomicU32 = AtomicU32::new(0);
354-
355-
#[derive(PartialEq, Eq, PartialOrd, Ord)]
356-
struct D(i32);
357-
impl Drop for D {
358-
fn drop(&mut self) {
359-
if DROPS.fetch_add(1, SeqCst) == 1 {
360-
panic!("panic in `drop`");
361-
}
362-
}
363-
}
364-
352+
let test = CrashTest::new();
365353
let mut set = BTreeSet::new();
366-
set.insert(D(0));
367-
set.insert(D(4));
368-
set.insert(D(8));
354+
set.insert(test.dummy(0, Panic::Never));
355+
set.insert(test.dummy(1, Panic::InDrop));
356+
set.insert(test.dummy(2, Panic::Never));
369357

370-
catch_unwind(move || {
371-
drop(set.drain_filter(|d| {
372-
PREDS.fetch_add(1u32 << d.0, SeqCst);
373-
true
374-
}))
375-
})
376-
.ok();
358+
catch_unwind(move || drop(set.drain_filter(|dummy| dummy.query(true)))).ok();
377359

378-
assert_eq!(PREDS.load(SeqCst), 0x011);
379-
assert_eq!(DROPS.load(SeqCst), 3);
360+
assert_eq!(test.queried(), 0x011);
361+
assert_eq!(test.dropped(), 0x111);
380362
}
381363

382364
#[test]
383365
fn test_drain_filter_pred_panic_leak() {
384-
static PREDS: AtomicU32 = AtomicU32::new(0);
385-
static DROPS: AtomicU32 = AtomicU32::new(0);
386-
387-
#[derive(PartialEq, Eq, PartialOrd, Ord)]
388-
struct D(i32);
389-
impl Drop for D {
390-
fn drop(&mut self) {
391-
DROPS.fetch_add(1, SeqCst);
392-
}
393-
}
394-
366+
let test = CrashTest::new();
395367
let mut set = BTreeSet::new();
396-
set.insert(D(0));
397-
set.insert(D(4));
398-
set.insert(D(8));
399-
400-
catch_unwind(AssertUnwindSafe(|| {
401-
drop(set.drain_filter(|d| {
402-
PREDS.fetch_add(1u32 << d.0, SeqCst);
403-
match d.0 {
404-
0 => true,
405-
_ => panic!(),
406-
}
407-
}))
408-
}))
409-
.ok();
410-
411-
assert_eq!(PREDS.load(SeqCst), 0x011);
412-
assert_eq!(DROPS.load(SeqCst), 1);
368+
set.insert(test.dummy(0, Panic::Never));
369+
set.insert(test.dummy(1, Panic::InQuery));
370+
set.insert(test.dummy(2, Panic::InQuery));
371+
372+
catch_unwind(AssertUnwindSafe(|| drop(set.drain_filter(|dummy| dummy.query(true))))).ok();
373+
374+
assert_eq!(test.queried(), 0x011);
375+
assert_eq!(test.dropped(), 0x001);
413376
assert_eq!(set.len(), 2);
414-
assert_eq!(set.first().unwrap().0, 4);
415-
assert_eq!(set.last().unwrap().0, 8);
377+
assert_eq!(set.first().unwrap().id, 1);
378+
assert_eq!(set.last().unwrap().id, 2);
416379
}
417380

418381
#[test]

0 commit comments

Comments
 (0)