Add unit tests for ElementMap::remap
This commit is contained in:
+140
@@ -142,6 +142,7 @@ impl<E: Copy, T: Clone> IndexMut<E> for ElementMap<E, T> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[test]
|
||||
fn initial_values_are_default() {
|
||||
@@ -238,4 +239,143 @@ mod tests {
|
||||
"slot added by grow should hold the mapped default"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remap() {
|
||||
let mut source = ElementMap::new('-', |e| e, 3);
|
||||
source[0] = 'a';
|
||||
source[1] = 'b';
|
||||
source[2] = 'c';
|
||||
let mut mapping = ElementMap::new(usize::MAX, |e| e, 3);
|
||||
mapping[0] = 2;
|
||||
mapping[1] = 0;
|
||||
mapping[2] = 1;
|
||||
let template = ElementMap::new((), |f| f, 3);
|
||||
let result = source.remap(&mapping, &template);
|
||||
assert_eq!(result[0], 'b', "unexpected value at slot 0");
|
||||
assert_eq!(result[1], 'c', "unexpected value at slot 1");
|
||||
assert_eq!(result[2], 'a', "unexpected value at slot 2");
|
||||
assert_eq!(
|
||||
result.default, '-',
|
||||
"default should be taken from the source map"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remap_skips_default() {
|
||||
let mut source = ElementMap::new(0, |e| e, 3);
|
||||
source[0] = 1;
|
||||
source[1] = 2;
|
||||
source[2] = 3;
|
||||
// Slot 1 stays unmapped, which would be out of bounds for the template if it was used.
|
||||
let mut mapping = ElementMap::new(usize::MAX, |e| e, 3);
|
||||
mapping[0] = 1;
|
||||
mapping[2] = 0;
|
||||
let template = ElementMap::new((), |f| f, 2);
|
||||
let result = source.remap(&mapping, &template);
|
||||
assert_eq!(result[0], 3, "unexpected value at slot 0");
|
||||
assert_eq!(result[1], 1, "unexpected value at slot 1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remap_unmapped_slots() {
|
||||
let mut source = ElementMap::new(9, |e| e, 2);
|
||||
source[0] = 1;
|
||||
source[1] = 2;
|
||||
let mut mapping = ElementMap::new(usize::MAX, |e| e, 2);
|
||||
mapping[0] = 0;
|
||||
mapping[1] = 2;
|
||||
let template = ElementMap::new((), |f| f, 4);
|
||||
let result = source.remap(&mapping, &template);
|
||||
assert_eq!(
|
||||
result.data,
|
||||
vec![1, 9, 2, 9],
|
||||
"should have the template's length, with unmapped slots holding the source's default"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remap_index_function() {
|
||||
let mut source = ElementMap::<usize, i32>::new(0, |e| e, 3);
|
||||
source[0] = 10;
|
||||
source[1] = 20;
|
||||
source[2] = 30;
|
||||
let mut mapping = ElementMap::<usize, u32>::new(u32::MAX, |e| e, 3);
|
||||
mapping[0] = 0;
|
||||
mapping[1] = 1;
|
||||
mapping[2] = 2;
|
||||
// Reverses the order of the slots.
|
||||
let template = ElementMap::<u32, ()>::new((), |f| 2 - f as usize, 3);
|
||||
let result = source.remap(&mapping, &template);
|
||||
assert_eq!(
|
||||
result.data,
|
||||
vec![30, 20, 10],
|
||||
"values should be written at the slots given by the template's index function"
|
||||
);
|
||||
assert_eq!(
|
||||
(result.to_index)(0),
|
||||
2,
|
||||
"index function should be taken from the template"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remap_shorter_source() {
|
||||
let mut source = ElementMap::new(9, |e| e, 2);
|
||||
source[0] = 5;
|
||||
source[1] = 6;
|
||||
let mut mapping = ElementMap::new(usize::MAX, |e| e, 4);
|
||||
for i in 0..4 {
|
||||
mapping[i] = i;
|
||||
}
|
||||
let template = ElementMap::new((), |f| f, 4);
|
||||
let result = source.remap(&mapping, &template);
|
||||
assert_eq!(result.data, vec![5, 6, 9, 9], "unexpected data");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remap_longer_source() {
|
||||
let mut source = ElementMap::new(0, |e| e, 4);
|
||||
for i in 0..4 {
|
||||
source[i] = i + 1;
|
||||
}
|
||||
let mut mapping = ElementMap::new(usize::MAX, |e| e, 2);
|
||||
mapping[0] = 1;
|
||||
mapping[1] = 0;
|
||||
let template = ElementMap::new((), |f| f, 2);
|
||||
let result = source.remap(&mapping, &template);
|
||||
assert_eq!(result.data, vec![2, 1], "unexpected data");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remap_empty() {
|
||||
let source = ElementMap::new(0, |e| e, 0);
|
||||
let mapping = ElementMap::new(usize::MAX, |e| e, 0);
|
||||
let template = ElementMap::new((), |f| f, 0);
|
||||
let result = source.remap(&mapping, &template);
|
||||
assert_eq!(result.data, Vec::<i32>::new(), "should be empty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remap_clones_values() {
|
||||
let value = Rc::new(1);
|
||||
let mut source = ElementMap::new(Rc::new(0), |e| e, 1);
|
||||
source[0] = Rc::clone(&value);
|
||||
let mut mapping = ElementMap::new(usize::MAX, |e| e, 1);
|
||||
mapping[0] = 0;
|
||||
let template = ElementMap::new((), |f| f, 1);
|
||||
let _result = source.remap(&mapping, &template);
|
||||
// The local variable, the source slot and the result slot each hold one reference.
|
||||
assert_eq!(
|
||||
Rc::strong_count(&value),
|
||||
3,
|
||||
"result should hold its own clone of the value"
|
||||
);
|
||||
drop(source);
|
||||
assert_eq!(
|
||||
Rc::strong_count(&value),
|
||||
2,
|
||||
"result should keep the value alive on its own"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user