Repository: rust-lang/rust
File: library/alloc/src/collections/btree/map/tests.rs (Rust)

Code before:
    map2.check();
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_merge_drop_leak() {
    let a = CrashTestDummy::new(0);
    let b = CrashTestDummy::new(1);
    let c = CrashTestDummy::new(2);
    let mut left = BTreeMap::new();
    let mut right = BTreeMap::new();
    left.insert(a.spawn(Panic::Never), ());
    left.insert(b.spawn(Panic::Never), ());
    left.insert(c.spawn(Panic::Never), ());
    right.insert(b.spawn(Panic::InDrop), ()); // first duplicate key, dropped during append
    right.insert(c.spawn(Panic::Never), ());

    catch_unwind(move || left.merge(right, |_, _, _| ())).unwrap_err();
    assert_eq!(a.dropped(), 1);
    assert_eq!(b.dropped(), 2);
    assert_eq!(c.dropped(), 2);
}

#[test]
fn test_merge_ord_chaos() {
    let mut map1 = BTreeMap::new();
    map1.insert(Cyclic3::A, ());
    map1.insert(Cyclic3::B, ());
    let mut map2 = BTreeMap::new();
    map2.insert(Cyclic3::A, ());
    map2.insert(Cyclic3::B, ());
    map2.insert(Cyclic3::C, ()); // lands first, before A
    map2.insert(Cyclic3::B, ()); // lands first, before C
    map1.check();
    map2.check(); // keys are not unique but still strictly ascending
    assert_eq!(map1.len(), 2);
    assert_eq!(map2.len(), 4);
    map1.merge(map2, |_, _, _| ());
    assert_eq!(map1.len(), 5);
    map1.check();
}

fn rand_data(len: usize) -> Vec<(u32, u32)> {
    let mut rng = DeterministicRng::new();
    Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
}

#[test]
fn test_split_off_empty_right() {
    let mut data = rand_data(173);


Review comment (bug):
you also need a test that panics in the `conflict` function and has values that are `CrashTestDummy::spawn()` instead of `()`, that way you can ensure the values are dropped correctly

Code after:
    map1.check();
    map2.check(); // keys are not unique but still strictly ascending
    assert_eq!(map1.len(), 2);
    assert_eq!(map2.len(), 4);
    map1.append(&mut map2);
    assert_eq!(map1.len(), 5);
    assert_eq!(map2.len(), 0);
    map1.check();
    map2.check();
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_merge_drop_leak() {
    let a = CrashTestDummy::new(0);
    let b = CrashTestDummy::new(1);
    let c = CrashTestDummy::new(2);
    let mut left = BTreeMap::new();
    let mut right = BTreeMap::new();
    left.insert(a.spawn(Panic::Never), ());
    left.insert(b.spawn(Panic::Never), ());
    left.insert(c.spawn(Panic::Never), ());
    right.insert(b.spawn(Panic::InDrop), ()); // first duplicate key, dropped during merge
    right.insert(c.spawn(Panic::Never), ());

    catch_unwind(move || left.merge(right, |_, _, _| ())).unwrap_err();
    assert_eq!(a.dropped(), 1); // this should not be dropped
    assert_eq!(b.dropped(), 2); // key is dropped on panic
    assert_eq!(c.dropped(), 2); // key is dropped on panic
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_merge_conflict_drop_leak() {
    let a = CrashTestDummy::new(0);
    let a_val_left = CrashTestDummy::new(0);

    let b = CrashTestDummy::new(1);
    let b_val_left = CrashTestDummy::new(1);
    let b_val_right = CrashTestDummy::new(1);

    let c = CrashTestDummy::new(2);
    let c_val_left = CrashTestDummy::new(2);
    let c_val_right = CrashTestDummy::new(2);

    let mut left = BTreeMap::new();
    let mut right = BTreeMap::new();

    left.insert(a.spawn(Panic::Never), a_val_left.spawn(Panic::Never));
    left.insert(b.spawn(Panic::Never), b_val_left.spawn(Panic::Never));
    left.insert(c.spawn(Panic::Never), c_val_left.spawn(Panic::Never));