use super::*;
fn create_test_snapshot(
index: usize,
num_metrics: usize,
values_per_metric: usize,
) -> ProfileSnapshot {
let mut snapshot = ProfileSnapshot::new(index);
snapshot.set_fingerprint(format!("workload_{}", index % 3));
for i in 0..num_metrics {
let mut metric = MetricData::new(format!("metric_{}", i));
for j in 0..values_per_metric {
metric.add(
100.0 + (index * 10 + i + j) as f64 * 0.1,
1000000000 + (index * 1000 + j) as u64,
);
}
snapshot.add_metric(metric);
}
snapshot
}
#[test]
fn test_metric_data() {
let mut metric = MetricData::new("test");
metric.add(1.0, 1000);
metric.add(2.0, 2000);
metric.add(3.0, 3000);
assert_eq!(metric.values.len(), 3);
assert_eq!(metric.timestamps.len(), 3);
assert!(metric.size_bytes() > 0);
}
#[test]
fn test_delta_encoding() {
let mut base = MetricData::new("test");
for i in 0..100 {
base.add(i as f64, i as u64 * 1000);
}
let mut current = MetricData::new("test");
for i in 0..100 {
let val = if i % 10 == 0 {
i as f64 * 2.0
} else {
i as f64
};
current.add(val, i as u64 * 1000);
}
let delta = current.delta_from(&base);
assert!(delta.size_bytes() < current.size_bytes());
let reconstructed = base.apply_delta(&delta);
assert_eq!(reconstructed.values.len(), current.values.len());
}
#[test]
fn test_snapshot_checksum() {
let mut snapshot = create_test_snapshot(0, 5, 100);
snapshot.compute_checksum();
assert!(snapshot.verify_checksum());
if let Some(metric) = snapshot.metrics.get_mut("metric_0") {
metric.values[0] = 999.0;
}
assert!(!snapshot.verify_checksum());
}
#[test]
fn test_delta_snapshot() {
let base = create_test_snapshot(0, 5, 100);
let current = create_test_snapshot(1, 5, 100);
let delta = DeltaSnapshot::from_diff(&base, ¤t);
let reconstructed = delta.apply_to(&base);
assert_eq!(reconstructed.index, current.index);
assert_eq!(reconstructed.metrics.len(), current.metrics.len());
}
#[test]
fn test_incremental_store_append() {
let config = SnapshotConfig::default();
let mut store = IncrementalSnapshotStore::new(config);
let snapshot = create_test_snapshot(0, 5, 100);
let idx = store.append(snapshot).unwrap();
assert_eq!(idx, 0);
assert_eq!(store.count(), 1);
}
#[test]
fn test_incremental_store_get() {
let config = SnapshotConfig::default();
let mut store = IncrementalSnapshotStore::new(config);
let original = create_test_snapshot(0, 5, 100);
store.append(original.clone()).unwrap();
let retrieved = store.get(0).unwrap();
assert_eq!(retrieved.metrics.len(), original.metrics.len());
}
#[test]
fn test_keyframe_interval() {
let config = SnapshotConfig {
keyframe_interval: 5,
..Default::default()
};
let mut store = IncrementalSnapshotStore::new(config);
for i in 0..15 {
store.append(create_test_snapshot(i, 5, 100)).unwrap();
}
assert!(store.keyframes.contains_key(&0));
assert!(store.keyframes.contains_key(&5));
assert!(store.keyframes.contains_key(&10));
assert!(store.deltas.contains_key(&1));
assert!(store.deltas.contains_key(&6));
}
#[test]
fn test_snapshot_query() {
let config = SnapshotConfig::default();
let mut store = IncrementalSnapshotStore::new(config);
for i in 0..10 {
let mut snapshot = create_test_snapshot(i, 5, 100);
snapshot.timestamp_ns = 1000 + i as u64 * 100;
store.append(snapshot).unwrap();
}
let query = SnapshotQuery::new().time_range(1200, 1700).limit(5);
let results = store.query(&query).unwrap();
assert!(results.len() <= 5);
for snapshot in &results {
assert!(snapshot.timestamp_ns >= 1200 && snapshot.timestamp_ns <= 1700);
}
}
#[test]
fn test_query_by_fingerprint() {
let config = SnapshotConfig::default();
let mut store = IncrementalSnapshotStore::new(config);
for i in 0..9 {
store.append(create_test_snapshot(i, 5, 100)).unwrap();
}
let query = SnapshotQuery::new().fingerprint("workload_0");
let results = store.query(&query).unwrap();
for snapshot in &results {
assert_eq!(snapshot.workload_fingerprint, "workload_0");
}
}
#[test]
fn test_compression_ratio() {
let config = SnapshotConfig {
keyframe_interval: 10,
..Default::default()
};
let mut store = IncrementalSnapshotStore::new(config);
for i in 0..50 {
let mut snapshot = ProfileSnapshot::new(i);
snapshot.set_fingerprint(format!("workload_{}", i % 3));
for m in 0..10 {
let mut metric = MetricData::new(format!("metric_{}", m));
for j in 0..100 {
let base_value = 100.0 + (m * 10 + j) as f64;
let value = base_value + (i % 2) as f64 * 0.001;
metric.add(value, 1000000000 + (i * 1000 + j) as u64);
}
snapshot.add_metric(metric);
}
store.append(snapshot).unwrap();
}
let ratio = store.compression_ratio();
assert!(
ratio <= 1.5,
"Compression ratio {} should be reasonable",
ratio
);
}
#[test]
fn test_index_out_of_bounds() {
let config = SnapshotConfig::default();
let mut store = IncrementalSnapshotStore::new(config);
store.append(create_test_snapshot(0, 5, 100)).unwrap();
let result = store.get(999);
assert!(matches!(
result,
Err(SnapshotError::IndexOutOfBounds { .. })
));
}
#[test]
fn test_error_display() {
let err = SnapshotError::ChecksumMismatch {
expected: 12345,
actual: 67890,
};
assert!(err.to_string().contains("12345"));
assert!(err.to_string().contains("67890"));
}
#[test]
fn test_retention_tier_max_age() {
assert!(RetentionTier::Raw.max_age() < RetentionTier::Compressed.max_age());
assert!(RetentionTier::Compressed.max_age() < RetentionTier::Archive.max_age());
}
#[test]
fn test_fkr_051_compression_ratio() {
let config = SnapshotConfig {
keyframe_interval: 10,
..Default::default()
};
let mut store = IncrementalSnapshotStore::new(config);
for i in 0..100 {
let mut snapshot = ProfileSnapshot::new(i);
snapshot.set_fingerprint("test_workload");
snapshot.timestamp_ns = (i * 1000000) as u64;
for m in 0..10 {
let mut metric = MetricData::new(format!("metric_{}", m));
for v in 0..100 {
let value = (m * 100 + v) as f64;
metric.add(value, (i * 1000000 + v) as u64);
}
snapshot.add_metric(metric);
}
store.append(snapshot).unwrap();
}
assert_eq!(store.count(), 100);
let raw_size = store.total_raw_size();
let compressed_size = store.total_compressed_size();
println!(
"Compression: {}/{} bytes ({:.1}% ratio)",
compressed_size,
raw_size,
(compressed_size as f64 / raw_size as f64) * 100.0
);
for i in 0..100 {
let snapshot = store.get(i).unwrap();
assert_eq!(snapshot.index, i);
assert_eq!(snapshot.metrics.len(), 10);
assert_eq!(snapshot.workload_fingerprint, "test_workload");
let metric = snapshot.metrics.get("metric_0").unwrap();
assert_eq!(metric.values.len(), 100);
assert!((metric.values[0] - 0.0).abs() < f64::EPSILON);
}
}