use super::*;
fn e(k: &str, v: &str) -> DedupEntry<String, String> {
DedupEntry::new(k.to_string(), v.to_string())
}
#[test]
fn distinct_keys_pass_through() {
let s0 = vec![e("a", "1"), e("c", "3")];
let s1 = vec![e("b", "2"), e("d", "4")];
let merged: Vec<_> = DedupMergeIterator::new([s0.into_iter(), s1.into_iter()]).collect();
assert_eq!(
merged,
vec![e("a", "1"), e("b", "2"), e("c", "3"), e("d", "4")]
);
}
#[test]
fn duplicate_key_picks_latest_source() {
let s0 = vec![e("k", "old")];
let s1 = vec![e("k", "new")];
let merged: Vec<_> = DedupMergeIterator::new([s0.into_iter(), s1.into_iter()]).collect();
assert_eq!(merged, vec![e("k", "new")]);
}
#[test]
fn three_way_duplicate_picks_highest_source() {
let s0 = vec![e("k", "v0")];
let s1 = vec![e("k", "v1")];
let s2 = vec![e("k", "v2")];
let merged: Vec<_> =
DedupMergeIterator::new([s0.into_iter(), s1.into_iter(), s2.into_iter()]).collect();
assert_eq!(merged, vec![e("k", "v2")]);
}
#[test]
fn empty_sources_yield_empty() {
let s0: Vec<DedupEntry<String, String>> = vec![];
let s1: Vec<DedupEntry<String, String>> = vec![];
let merged: Vec<_> = DedupMergeIterator::new([s0.into_iter(), s1.into_iter()]).collect();
assert!(merged.is_empty());
}
#[test]
fn interleaved_with_some_duplicates() {
let s0 = vec![e("a", "a0"), e("b", "b0"), e("c", "c0")];
let s1 = vec![e("b", "b1"), e("d", "d1")];
let merged: Vec<_> = DedupMergeIterator::new([s0.into_iter(), s1.into_iter()]).collect();
assert_eq!(
merged,
vec![e("a", "a0"), e("b", "b1"), e("c", "c0"), e("d", "d1")]
);
}
#[test]
fn dedup_preserves_count_with_unique_keys() {
let s0: Vec<_> = (0..100i32).map(|i| DedupEntry::new(i * 2, i)).collect();
let s1: Vec<_> = (0..100i32).map(|i| DedupEntry::new(i * 2 + 1, i)).collect();
let merged: Vec<_> = DedupMergeIterator::new([s0.into_iter(), s1.into_iter()]).collect();
assert_eq!(merged.len(), 200);
for w in merged.windows(2) {
assert!(w[0].key < w[1].key);
}
}
#[test]
fn heap_item_eq_and_ord_direct() {
let a = HeapItem {
key: 5i32,
source: 0,
value: "a",
};
let b = HeapItem {
key: 5i32,
source: 0,
value: "different-value",
};
let c = HeapItem {
key: 5i32,
source: 1,
value: "a",
};
let d = HeapItem {
key: 9i32,
source: 0,
value: "a",
};
assert!(a == b);
assert!(a != c);
assert!(a != d);
assert_eq!(a.cmp(&d), std::cmp::Ordering::Less);
assert_eq!(a.cmp(&c), std::cmp::Ordering::Greater);
assert_eq!(a.partial_cmp(&b), Some(std::cmp::Ordering::Equal));
}
#[test]
fn long_interleaved_streams_with_repeated_advances() {
let s0: Vec<_> = (0..30i32).map(|i| DedupEntry::new(i, i * 10)).collect();
let s1: Vec<_> = (0..30i32).map(|i| DedupEntry::new(i, i * 100)).collect();
let s2: Vec<_> = (10..40i32).map(|i| DedupEntry::new(i, i)).collect();
let merged: Vec<_> =
DedupMergeIterator::new([s0.into_iter(), s1.into_iter(), s2.into_iter()]).collect();
assert_eq!(merged.len(), 40);
for w in merged.windows(2) {
assert!(w[0].key < w[1].key);
}
assert_eq!(merged[0], DedupEntry::new(0, 0));
assert_eq!(merged[20], DedupEntry::new(20, 20));
}
#[test]
fn all_duplicates_collapses_to_one_per_key() {
let mk = |tag: &str| {
(0..5i32)
.map(move |k| DedupEntry::new(k, format!("{tag}-{k}")))
.collect::<Vec<_>>()
};
let merged: Vec<_> = DedupMergeIterator::new([
mk("a").into_iter(),
mk("b").into_iter(),
mk("c").into_iter(),
])
.collect();
assert_eq!(
merged,
(0..5i32)
.map(|k| DedupEntry::new(k, format!("c-{k}")))
.collect::<Vec<_>>()
);
}