use super::{
logical_memory_to_folded, logical_total_bytes, LogicalMemoryProfile, LogicalMemoryVisitor,
MemoryProfile, Path,
};
use crate::{coeff, linear, quadratic, Linear, Quadratic};
#[test]
fn test_memory_profile_aggregation() {
let mut profile = MemoryProfile::default();
profile.visit_leaf(&Path::from(vec!["root", "child", "leaf"]), 1024);
profile.visit_leaf(&Path::from(vec!["root", "child", "other"]), 2048);
let output = profile.to_string();
assert_eq!(output, "root;child;leaf 1024\nroot;child;other 2048");
assert_eq!(profile.total_bytes(), 3072);
assert_eq!(profile.len(), 2);
}
#[test]
fn test_memory_profile_skip_zero() {
let mut profile = MemoryProfile::default();
profile.visit_leaf(&Path::from(vec!["root", "empty"]), 0);
profile.visit_leaf(&Path::from(vec!["root", "nonempty"]), 100);
let output = profile.to_string();
assert_eq!(output, "root;nonempty 100");
assert_eq!(profile.total_bytes(), 100);
}
#[test]
fn test_memory_profile_same_path_aggregates() {
let mut profile = MemoryProfile::default();
profile.visit_leaf(&Path::from(vec!["root", "leaf"]), 10);
profile.visit_leaf(&Path::from(vec!["root", "leaf"]), 32);
assert_eq!(profile.to_string(), "root;leaf 42");
assert_eq!(profile.total_bytes(), 42);
assert_eq!(profile.len(), 1);
}
#[test]
fn test_memory_profile_entries_iter() {
let mut profile = MemoryProfile::default();
profile.visit_leaf(&Path::from(vec!["a"]), 1);
profile.visit_leaf(&Path::from(vec!["b"]), 2);
let collected: Vec<(Vec<&'static str>, usize)> =
profile.entries().map(|(p, b)| (p.to_vec(), b)).collect();
assert_eq!(collected, vec![(vec!["a"], 1), (vec!["b"], 2),]);
}
#[test]
fn test_linear_memory_profile() {
let expr: Linear =
((coeff!(2.0) * linear!(1)).unwrap() + (coeff!(3.0) * linear!(2)).unwrap()).unwrap();
let expr = (expr + coeff!(5.0)).unwrap();
let folded = logical_memory_to_folded(&expr);
insta::assert_snapshot!(folded, @"PolynomialBase.terms 104");
let total = logical_total_bytes(&expr);
assert!(total > 0);
}
#[test]
fn test_linear_snapshot() {
let expr: Linear =
((coeff!(2.0) * linear!(1)).unwrap() + (coeff!(3.0) * linear!(2)).unwrap()).unwrap();
let expr = (expr + coeff!(5.0)).unwrap();
let folded = logical_memory_to_folded(&expr);
insta::assert_snapshot!(folded, @"PolynomialBase.terms 104");
}
#[test]
fn test_quadratic_memory_profile() {
let expr: Quadratic = ((coeff!(1.0) * quadratic!(1, 2)).unwrap()
+ (coeff!(2.0) * quadratic!(1)).unwrap())
.unwrap();
let expr = (expr + coeff!(1.0)).unwrap();
let folded = logical_memory_to_folded(&expr);
insta::assert_snapshot!(folded, @"PolynomialBase.terms 128");
let total = logical_total_bytes(&expr);
assert!(total > 0);
}
#[test]
fn test_quadratic_snapshot() {
let expr: Quadratic = ((coeff!(1.0) * quadratic!(1, 2)).unwrap()
+ (coeff!(2.0) * quadratic!(1)).unwrap())
.unwrap();
let expr = (expr + coeff!(1.0)).unwrap();
let folded = logical_memory_to_folded(&expr);
insta::assert_snapshot!(folded, @"PolynomialBase.terms 128");
}
#[test]
fn test_large_linear_memory() {
let mut expr = (coeff!(1.0) * linear!(1)).unwrap();
for i in 2..=100 {
expr = (expr + (coeff!(i as f64) * linear!(i)).unwrap()).unwrap();
}
let folded = logical_memory_to_folded(&expr);
println!("Large Linear folded stack:\n{}", folded);
let total = logical_total_bytes(&expr);
println!("Large Linear total bytes: {}", total);
assert!(total > 1000); }
#[test]
fn test_medium_linear_snapshot() {
let mut expr = (coeff!(1.0) * linear!(1)).unwrap();
for i in 2..=10 {
expr = (expr + (coeff!(i as f64) * linear!(i)).unwrap()).unwrap();
}
let folded = logical_memory_to_folded(&expr);
insta::assert_snapshot!(folded, @"PolynomialBase.terms 272");
}
#[test]
fn test_btreemap_with_linear() {
use crate::VariableID;
use std::collections::BTreeMap;
let mut map = BTreeMap::new();
map.insert(VariableID::from(1), (coeff!(2.0) * linear!(1)).unwrap());
map.insert(VariableID::from(2), (coeff!(3.0) * linear!(2)).unwrap());
let folded = logical_memory_to_folded(&map);
insta::assert_snapshot!(folded, @r###"
BTreeMap[key];VariableID.0 16
BTreeMap[stack] 24
PolynomialBase.terms 112
"###);
}
#[test]
fn test_hashmap_with_linear() {
use crate::VariableID;
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert(VariableID::from(1), (coeff!(2.0) * linear!(1)).unwrap());
map.insert(VariableID::from(2), (coeff!(3.0) * linear!(2)).unwrap());
let folded = logical_memory_to_folded(&map);
insta::assert_snapshot!(folded, @r###"
HashMap[key];VariableID.0 16
HashMap[stack] 48
PolynomialBase.terms 112
"###);
}
#[test]
fn test_vec_with_linear() {
let vec = vec![
(coeff!(2.0) * linear!(1)).unwrap(),
(coeff!(3.0) * linear!(2)).unwrap(),
(coeff!(4.0) * linear!(3)).unwrap(),
];
let folded = logical_memory_to_folded(&vec);
insta::assert_snapshot!(folded, @r###"
PolynomialBase.terms 168
Vec[stack] 24
"###);
}
#[test]
fn test_array_snapshot() {
let array = [1_u64, 2, 3];
let folded = logical_memory_to_folded(&array);
insta::assert_snapshot!(folded, @"Array[element] 24");
}
#[test]
fn test_box_snapshot() {
let value = Box::new("hi".to_string());
let folded = logical_memory_to_folded(&value);
insta::assert_snapshot!(folded, @r###"
Box[stack] 8
Box[value] 26
"###);
}
#[test]
fn test_hashset_snapshot() {
use std::collections::HashSet;
#[derive(LogicalMemoryProfile)]
struct HashSetHolder {
set: HashSet<u64>,
}
let folded = logical_memory_to_folded(&HashSetHolder {
set: HashSet::from([1_u64, 2, 3]),
});
insta::assert_snapshot!(folded, @r###"
HashSetHolder.set 24
HashSetHolder.set;HashSet[stack] 48
"###);
}
#[test]
fn test_fnv_hashset_snapshot() {
use fnv::FnvHashSet;
#[derive(LogicalMemoryProfile)]
struct FnvHashSetHolder {
set: FnvHashSet<u64>,
}
let folded = logical_memory_to_folded(&FnvHashSetHolder {
set: FnvHashSet::from_iter([1_u64, 2, 3]),
});
insta::assert_snapshot!(folded, @r###"
FnvHashSetHolder.set 24
FnvHashSetHolder.set;FnvHashSet[stack] 32
"###);
}
#[test]
fn test_vecdeque_snapshot() {
use std::collections::VecDeque;
#[derive(LogicalMemoryProfile)]
struct VecDequeHolder {
deque: VecDeque<u64>,
}
let folded = logical_memory_to_folded(&VecDequeHolder {
deque: VecDeque::from([1_u64, 2, 3]),
});
insta::assert_snapshot!(folded, @r###"
VecDequeHolder.deque 24
VecDequeHolder.deque;VecDeque[stack] 32
"###);
}
#[test]
fn test_bool_char_unit_and_phantom_data_snapshot() {
use std::marker::PhantomData;
#[derive(LogicalMemoryProfile)]
struct MiscStdTypes {
enabled: bool,
marker: char,
unit: (),
phantom: PhantomData<u64>,
}
let value = MiscStdTypes {
enabled: true,
marker: 'x',
unit: (),
phantom: PhantomData,
};
let folded = logical_memory_to_folded(&value);
insta::assert_snapshot!(folded, @r###"
MiscStdTypes.enabled 1
MiscStdTypes.marker 4
"###);
}
#[test]
fn test_tuple_snapshot() {
let tuple = (1_u64, "hi".to_string(), 3_u32);
let folded = logical_memory_to_folded(&tuple);
insta::assert_snapshot!(folded, @r###"
Tuple.0 8
Tuple.1 26
Tuple.2 4
"###);
}
#[test]
fn test_empty_collections() {
use crate::Linear;
use std::collections::BTreeMap;
let empty_map: BTreeMap<u64, Linear> = BTreeMap::new();
let folded = logical_memory_to_folded(&empty_map);
insta::assert_snapshot!(folded, @"BTreeMap[stack] 24");
let empty_vec: Vec<Linear> = Vec::new();
let folded_vec = logical_memory_to_folded(&empty_vec);
insta::assert_snapshot!(folded_vec, @"Vec[stack] 24");
}
#[derive(LogicalMemoryProfile)]
struct DeriveTargetFlat {
alpha: u64,
beta: f64,
gamma: String,
}
#[derive(LogicalMemoryProfile)]
struct DeriveTargetNested {
leaf: u32,
inner: DeriveTargetFlat,
}
#[derive(LogicalMemoryProfile)]
#[allow(dead_code)]
struct DeriveTargetLeaf(u64);
#[derive(LogicalMemoryProfile)]
struct DeriveLeafHolder {
leaf: DeriveTargetLeaf,
}
#[test]
fn test_derive_flat_struct_snapshot() {
let value = DeriveTargetFlat {
alpha: 0,
beta: 0.0,
gamma: "hi".to_string(),
};
let folded = logical_memory_to_folded(&value);
insta::assert_snapshot!(folded, @r###"
DeriveTargetFlat.alpha 8
DeriveTargetFlat.beta 8
DeriveTargetFlat.gamma 26
"###);
}
#[test]
fn test_derive_nested_struct_snapshot() {
let value = DeriveTargetNested {
leaf: 7,
inner: DeriveTargetFlat {
alpha: 0,
beta: 0.0,
gamma: String::new(),
},
};
let folded = logical_memory_to_folded(&value);
insta::assert_snapshot!(folded, @r###"
DeriveTargetNested.inner;DeriveTargetFlat.alpha 8
DeriveTargetNested.inner;DeriveTargetFlat.beta 8
DeriveTargetNested.inner;DeriveTargetFlat.gamma 24
DeriveTargetNested.leaf 4
"###);
}
#[test]
fn test_derive_tuple_struct_snapshot() {
let value = DeriveLeafHolder {
leaf: DeriveTargetLeaf(0),
};
let folded = logical_memory_to_folded(&value);
insta::assert_snapshot!(folded, @"DeriveLeafHolder.leaf;DeriveTargetLeaf.0 8");
}
#[test]
fn test_derive_matches_declarative_macro() {
struct Target {
a: u64,
b: u32,
}
crate::impl_logical_memory_profile! {
Target { a, b }
}
#[derive(LogicalMemoryProfile)]
struct TargetDerived {
a: u64,
b: u32,
}
let declarative = logical_memory_to_folded(&Target { a: 1, b: 2 });
let derived = logical_memory_to_folded(&TargetDerived { a: 1, b: 2 });
let derived_renamed = derived.replace("TargetDerived", "Target");
assert_eq!(declarative, derived_renamed);
}