Wrote unit tests for functionality within lib.rs (#45)
This commit is contained in:
417
src/lib.rs
417
src/lib.rs
@@ -50,6 +50,7 @@ pub struct StateGroupEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Helper struct for parsing the `level_sizes` argument.
|
/// Helper struct for parsing the `level_sizes` argument.
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
struct LevelSizes(Vec<usize>);
|
struct LevelSizes(Vec<usize>);
|
||||||
|
|
||||||
impl FromStr for LevelSizes {
|
impl FromStr for LevelSizes {
|
||||||
@@ -72,7 +73,7 @@ impl FromStr for LevelSizes {
|
|||||||
/// Contains configuration information for this run of the compressor
|
/// Contains configuration information for this run of the compressor
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
// the url for the postgres database
|
// the url for the postgres database
|
||||||
// this should be of the form postgres://user:pass@domain/database
|
// this should be of the form postgresql://user:pass@domain/database
|
||||||
db_url: String,
|
db_url: String,
|
||||||
// The file where the transactions are written that would carry out
|
// The file where the transactions are written that would carry out
|
||||||
// the compression that get's calculated
|
// the compression that get's calculated
|
||||||
@@ -473,7 +474,7 @@ fn check_that_maps_match(
|
|||||||
println!("State Group: {}", sg);
|
println!("State Group: {}", sg);
|
||||||
println!("Expected: {:#?}", expected);
|
println!("Expected: {:#?}", expected);
|
||||||
println!("actual: {:#?}", actual);
|
println!("actual: {:#?}", actual);
|
||||||
Err(format!("State for group {} do not match", sg))
|
Err(format!("States for group {} do not match", sg))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -487,6 +488,10 @@ fn check_that_maps_match(
|
|||||||
|
|
||||||
/// Gets the full state for a given group from the map (of deltas)
|
/// Gets the full state for a given group from the map (of deltas)
|
||||||
fn collapse_state_maps(map: &BTreeMap<i64, StateGroupEntry>, state_group: i64) -> StateMap<Atom> {
|
fn collapse_state_maps(map: &BTreeMap<i64, StateGroupEntry>, state_group: i64) -> StateMap<Atom> {
|
||||||
|
if !map.contains_key(&state_group) {
|
||||||
|
panic!("Missing {}", state_group);
|
||||||
|
}
|
||||||
|
|
||||||
let mut entry = &map[&state_group];
|
let mut entry = &map[&state_group];
|
||||||
let mut state_map = StateMap::new();
|
let mut state_map = StateMap::new();
|
||||||
|
|
||||||
@@ -619,3 +624,411 @@ fn synapse_compress_state(_py: Python, m: &PyModule) -> PyResult<()> {
|
|||||||
m.add_function(wrap_pyfunction!(run_compression, m)?)?;
|
m.add_function(wrap_pyfunction!(run_compression, m)?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TESTS START HERE
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod level_sizes_tests {
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use crate::LevelSizes;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_str_produces_correct_sizes() {
|
||||||
|
let input_string = "100,50,25";
|
||||||
|
|
||||||
|
let levels = LevelSizes::from_str(input_string).unwrap();
|
||||||
|
|
||||||
|
let mut levels_iter = levels.0.iter();
|
||||||
|
|
||||||
|
assert_eq!(levels_iter.next().unwrap(), &100);
|
||||||
|
assert_eq!(levels_iter.next().unwrap(), &50);
|
||||||
|
assert_eq!(levels_iter.next().unwrap(), &25);
|
||||||
|
assert_eq!(levels_iter.next(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_str_produces_err_if_not_list_of_numbers() {
|
||||||
|
let input_string = "100-sheep-25";
|
||||||
|
|
||||||
|
let result = LevelSizes::from_str(input_string);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod lib_tests {
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use state_map::StateMap;
|
||||||
|
use string_cache::DefaultAtom as Atom;
|
||||||
|
|
||||||
|
use crate::{check_that_maps_match, collapse_state_maps, StateGroupEntry};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn collapse_state_maps_works_for_non_snapshot() {
|
||||||
|
let mut initial: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
let mut prev = None;
|
||||||
|
|
||||||
|
// This starts with the following structure
|
||||||
|
//
|
||||||
|
// 0-1-2-3-4-5-6-7-8-9-10-11-12-13
|
||||||
|
//
|
||||||
|
// Each group i has state:
|
||||||
|
// ('node','is', i)
|
||||||
|
// ('group', j, 'seen') where j is less than i
|
||||||
|
for i in 0i64..=13i64 {
|
||||||
|
let mut entry = StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: prev,
|
||||||
|
state_map: StateMap::new(),
|
||||||
|
};
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("group", &i.to_string(), "seen".into());
|
||||||
|
entry.state_map.insert("node", "is", i.to_string().into());
|
||||||
|
|
||||||
|
initial.insert(i, entry);
|
||||||
|
|
||||||
|
prev = Some(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
let result_state = collapse_state_maps(&initial, 3);
|
||||||
|
|
||||||
|
let mut expected_state: StateMap<Atom> = StateMap::new();
|
||||||
|
expected_state.insert("node", "is", "3".into());
|
||||||
|
expected_state.insert("group", "0", "seen".into());
|
||||||
|
expected_state.insert("group", "1", "seen".into());
|
||||||
|
expected_state.insert("group", "2", "seen".into());
|
||||||
|
expected_state.insert("group", "3", "seen".into());
|
||||||
|
|
||||||
|
assert_eq!(result_state, expected_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn collapse_state_maps_works_for_snapshot() {
|
||||||
|
let mut initial: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
let mut prev = None;
|
||||||
|
|
||||||
|
// This starts with the following structure
|
||||||
|
//
|
||||||
|
// 0-1-2-3-4-5-6-7-8-9-10-11-12-13
|
||||||
|
//
|
||||||
|
// Each group i has state:
|
||||||
|
// ('node','is', i)
|
||||||
|
// ('group', j, 'seen') where j is less than i
|
||||||
|
for i in 0i64..=13i64 {
|
||||||
|
let mut entry = StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: prev,
|
||||||
|
state_map: StateMap::new(),
|
||||||
|
};
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("group", &i.to_string(), "seen".into());
|
||||||
|
entry.state_map.insert("node", "is", i.to_string().into());
|
||||||
|
|
||||||
|
initial.insert(i, entry);
|
||||||
|
|
||||||
|
prev = Some(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
let result_state = collapse_state_maps(&initial, 0);
|
||||||
|
|
||||||
|
let mut expected_state: StateMap<Atom> = StateMap::new();
|
||||||
|
expected_state.insert("node", "is", "0".into());
|
||||||
|
expected_state.insert("group", "0", "seen".into());
|
||||||
|
|
||||||
|
assert_eq!(result_state, expected_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Missing")]
|
||||||
|
fn collapse_state_maps_panics_if_pred_not_in_map() {
|
||||||
|
let mut initial: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
let mut prev = Some(14); // note will not be in map
|
||||||
|
|
||||||
|
// This starts with the following structure
|
||||||
|
//
|
||||||
|
// N.B. Group 14 will only exist as the predecessor of 0
|
||||||
|
// There is no group 14 in the map
|
||||||
|
//
|
||||||
|
// (14)-0-1-2-3-4-5-6-7-8-9-10-11-12-13
|
||||||
|
//
|
||||||
|
// Each group i has state:
|
||||||
|
// ('node','is', i)
|
||||||
|
// ('group', j, 'seen') where j is less than i
|
||||||
|
for i in 0i64..=13i64 {
|
||||||
|
let mut entry = StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: prev,
|
||||||
|
state_map: StateMap::new(),
|
||||||
|
};
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("group", &i.to_string(), "seen".into());
|
||||||
|
entry.state_map.insert("node", "is", i.to_string().into());
|
||||||
|
|
||||||
|
initial.insert(i, entry);
|
||||||
|
|
||||||
|
prev = Some(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse_state_maps(&initial, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_that_maps_match_returns_if_both_empty() {
|
||||||
|
check_that_maps_match(&BTreeMap::new(), &BTreeMap::new());
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Missing")]
|
||||||
|
fn check_that_maps_match_panics_if_just_new_map_is_empty() {
|
||||||
|
let mut old_map: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
let mut prev = None; // note will not be in map
|
||||||
|
|
||||||
|
// This starts with the following structure
|
||||||
|
//
|
||||||
|
// 0-1-2-3-4-5-6-7-8-9-10-11-12-13
|
||||||
|
//
|
||||||
|
// Each group i has state:
|
||||||
|
// ('node','is', i)
|
||||||
|
// ('group', j, 'seen') where j is less than i
|
||||||
|
for i in 0i64..=13i64 {
|
||||||
|
let mut entry = StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: prev,
|
||||||
|
state_map: StateMap::new(),
|
||||||
|
};
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("group", &i.to_string(), "seen".into());
|
||||||
|
entry.state_map.insert("node", "is", i.to_string().into());
|
||||||
|
|
||||||
|
old_map.insert(i, entry);
|
||||||
|
|
||||||
|
prev = Some(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
check_that_maps_match(&old_map, &BTreeMap::new());
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_that_maps_match_returns_if_just_old_map_is_empty() {
|
||||||
|
// note that this IS the desired behaviour as only want to ensure that
|
||||||
|
// all groups that existed BEFORE compression, will still collapse to the same
|
||||||
|
// states (i.e. no visible changes to rest of synapse
|
||||||
|
|
||||||
|
let mut new_map: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
let mut prev = None; // note will not be in map
|
||||||
|
|
||||||
|
// This starts with the following structure
|
||||||
|
//
|
||||||
|
// 0-1-2-3-4-5-6-7-8-9-10-11-12-13
|
||||||
|
//
|
||||||
|
// Each group i has state:
|
||||||
|
// ('node','is', i)
|
||||||
|
// ('group', j, 'seen') where j is less than i
|
||||||
|
for i in 0i64..=13i64 {
|
||||||
|
let mut entry = StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: prev,
|
||||||
|
state_map: StateMap::new(),
|
||||||
|
};
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("group", &i.to_string(), "seen".into());
|
||||||
|
entry.state_map.insert("node", "is", i.to_string().into());
|
||||||
|
|
||||||
|
new_map.insert(i, entry);
|
||||||
|
|
||||||
|
prev = Some(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
check_that_maps_match(&BTreeMap::new(), &new_map);
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_that_maps_match_returns_if_no_changes() {
|
||||||
|
let mut old_map: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
let mut prev = None; // note will not be in map
|
||||||
|
|
||||||
|
// This starts with the following structure
|
||||||
|
//
|
||||||
|
// 0-1-2-3-4-5-6-7-8-9-10-11-12-13
|
||||||
|
//
|
||||||
|
// Each group i has state:
|
||||||
|
// ('node','is', i)
|
||||||
|
// ('group', j, 'seen') where j is less than i
|
||||||
|
for i in 0i64..=13i64 {
|
||||||
|
let mut entry = StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: prev,
|
||||||
|
state_map: StateMap::new(),
|
||||||
|
};
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("group", &i.to_string(), "seen".into());
|
||||||
|
entry.state_map.insert("node", "is", i.to_string().into());
|
||||||
|
|
||||||
|
old_map.insert(i, entry);
|
||||||
|
|
||||||
|
prev = Some(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
check_that_maps_match(&BTreeMap::new(), &old_map.clone());
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "States for group")]
|
||||||
|
fn check_that_maps_match_panics_if_same_preds_but_different_deltas() {
|
||||||
|
let mut old_map: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
let mut prev = None; // note will not be in map
|
||||||
|
|
||||||
|
// This starts with the following structure
|
||||||
|
//
|
||||||
|
// 0-1-2-3-4-5-6-7-8-9-10-11-12-13
|
||||||
|
//
|
||||||
|
// Each group i has state:
|
||||||
|
// ('node','is', i)
|
||||||
|
// ('group', j, 'seen') where j is less than i
|
||||||
|
for i in 0i64..=13i64 {
|
||||||
|
let mut entry = StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: prev,
|
||||||
|
state_map: StateMap::new(),
|
||||||
|
};
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("group", &i.to_string(), "seen".into());
|
||||||
|
entry.state_map.insert("node", "is", i.to_string().into());
|
||||||
|
|
||||||
|
old_map.insert(i, entry);
|
||||||
|
|
||||||
|
prev = Some(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// new_map will have the same structure but the (node, is) values will be
|
||||||
|
// different
|
||||||
|
let mut new_map: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
let mut prev = None; // note will not be in map
|
||||||
|
|
||||||
|
// This starts with the following structure
|
||||||
|
//
|
||||||
|
// 0-1-2-3-4-5-6-7-8-9-10-11-12-13
|
||||||
|
//
|
||||||
|
// Each group i has state:
|
||||||
|
// ('node','is', i+1) <- NOTE DIFFERENCE
|
||||||
|
// ('group', j, 'seen') where j is less than i
|
||||||
|
for i in 0i64..=13i64 {
|
||||||
|
let mut entry = StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: prev,
|
||||||
|
state_map: StateMap::new(),
|
||||||
|
};
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("group", &i.to_string(), "seen".into());
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("node", "is", (i + 1).to_string().into());
|
||||||
|
|
||||||
|
new_map.insert(i, entry);
|
||||||
|
|
||||||
|
prev = Some(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
check_that_maps_match(&old_map, &new_map);
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_that_maps_match_returns_if_same_states_but_different_structure() {
|
||||||
|
let mut old_map: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
let mut prev = None; // note will not be in map
|
||||||
|
|
||||||
|
// This starts with the following structure
|
||||||
|
//
|
||||||
|
// 0-1-2-3-4-5-6
|
||||||
|
//
|
||||||
|
// Each group i has state:
|
||||||
|
// ('node','is', i)
|
||||||
|
// ('group', j, 'seen') where j is less than i
|
||||||
|
for i in 0i64..=6i64 {
|
||||||
|
let mut entry = StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: prev,
|
||||||
|
state_map: StateMap::new(),
|
||||||
|
};
|
||||||
|
entry
|
||||||
|
.state_map
|
||||||
|
.insert("group", &i.to_string(), "seen".into());
|
||||||
|
entry.state_map.insert("node", "is", i.to_string().into());
|
||||||
|
|
||||||
|
old_map.insert(i, entry);
|
||||||
|
|
||||||
|
prev = Some(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a structure that could be produced by the compressor
|
||||||
|
// and should pass the maps_match test:
|
||||||
|
//
|
||||||
|
// 0 3\
|
||||||
|
// 1 4 6
|
||||||
|
// 2 5
|
||||||
|
//
|
||||||
|
// State contents should be the same as before
|
||||||
|
let mut new_map: BTreeMap<i64, StateGroupEntry> = BTreeMap::new();
|
||||||
|
|
||||||
|
// 0-1-2 is left the same
|
||||||
|
new_map.insert(0, old_map.get(&0).unwrap().clone());
|
||||||
|
new_map.insert(1, old_map.get(&1).unwrap().clone());
|
||||||
|
new_map.insert(2, old_map.get(&2).unwrap().clone());
|
||||||
|
|
||||||
|
// 3 is now a snapshot
|
||||||
|
let mut entry_3: StateMap<Atom> = StateMap::new();
|
||||||
|
entry_3.insert("node", "is", "3".into());
|
||||||
|
entry_3.insert("group", "0", "seen".into());
|
||||||
|
entry_3.insert("group", "1", "seen".into());
|
||||||
|
entry_3.insert("group", "2", "seen".into());
|
||||||
|
entry_3.insert("group", "3", "seen".into());
|
||||||
|
new_map.insert(
|
||||||
|
3,
|
||||||
|
StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: None,
|
||||||
|
state_map: entry_3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4 and 5 are also left the same
|
||||||
|
new_map.insert(4, old_map.get(&4).unwrap().clone());
|
||||||
|
new_map.insert(5, old_map.get(&5).unwrap().clone());
|
||||||
|
|
||||||
|
// 6 is a "partial" snapshot now
|
||||||
|
let mut entry_6: StateMap<Atom> = StateMap::new();
|
||||||
|
entry_6.insert("node", "is", "6".into());
|
||||||
|
entry_6.insert("group", "4", "seen".into());
|
||||||
|
entry_6.insert("group", "5", "seen".into());
|
||||||
|
entry_6.insert("group", "6", "seen".into());
|
||||||
|
new_map.insert(
|
||||||
|
6,
|
||||||
|
StateGroupEntry {
|
||||||
|
in_range: true,
|
||||||
|
prev_state_group: Some(3),
|
||||||
|
state_map: entry_6,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
check_that_maps_match(&old_map, &new_map);
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: tests for correct SQL code produced by output_sql
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user