#[test]
fn test_app_tick_updates_demo() {
let mut app = App::new(None);
let initial_tokens = app.pipeline.tokens_generated;
app.tick();
assert_eq!(app.pipeline.tokens_generated, initial_tokens + 1);
}
#[test]
fn test_app_model_name_default() {
let app = App::new(None);
assert_eq!(app.model_name, "qwen2.5-coder-1.5b");
}
#[test]
fn test_app_model_name_custom() {
let app = App::new(Some("custom-model"));
assert_eq!(app.model_name, "custom-model");
}
#[test]
fn test_brick_percent_of_budget_under() {
let mut brick = BrickTiming::new("test", 10.0);
brick.actual_us = 5.0;
assert_eq!(brick.percent_of_budget(), 50);
}
#[test]
fn test_brick_percent_of_budget_at() {
let mut brick = BrickTiming::new("test", 10.0);
brick.actual_us = 10.0;
assert_eq!(brick.percent_of_budget(), 100);
}
#[test]
fn test_brick_percent_of_budget_over() {
let mut brick = BrickTiming::new("test", 10.0);
brick.actual_us = 15.0;
assert_eq!(brick.percent_of_budget(), 150);
}
#[test]
fn test_brick_percent_of_budget_capped_at_200() {
let mut brick = BrickTiming::new("test", 10.0);
brick.actual_us = 30.0; assert_eq!(brick.percent_of_budget(), 200);
}
#[test]
fn test_brick_percent_of_budget_zero_budget() {
let mut brick = BrickTiming::new("test", 0.0);
brick.actual_us = 5.0;
assert_eq!(brick.percent_of_budget(), 100);
}
#[test]
fn test_brick_percent_of_budget_zero_actual() {
let brick = BrickTiming::new("test", 10.0);
assert_eq!(brick.percent_of_budget(), 0);
}
#[test]
fn test_sparkline_data_empty() {
let brick = BrickTiming::new("test", 5.0);
let data = brick.sparkline_data();
assert!(data.is_empty());
}
#[test]
fn test_sparkline_data_single_sample() {
let mut brick = BrickTiming::new("test", 5.0);
brick.add_sample(10.0);
let data = brick.sparkline_data();
assert_eq!(data.len(), 1);
assert_eq!(data[0], 100); }
#[test]
fn test_sparkline_data_overflow_capped() {
let mut brick = BrickTiming::new("test", 5.0);
brick.add_sample(30.0); let data = brick.sparkline_data();
assert_eq!(data[0], 255);
}
#[test]
fn test_sparkline_data_zero_sample() {
let mut brick = BrickTiming::new("test", 5.0);
brick.add_sample(0.0);
let data = brick.sparkline_data();
assert_eq!(data[0], 0);
}
#[test]
fn test_sparkline_data_multiple_samples() {
let mut brick = BrickTiming::new("test", 5.0);
brick.add_sample(1.0);
brick.add_sample(2.0);
brick.add_sample(3.0);
let data = brick.sparkline_data();
assert_eq!(data.len(), 3);
assert_eq!(data[0], 10); assert_eq!(data[1], 20); assert_eq!(data[2], 30); }
#[test]
fn test_add_sample_ring_buffer_overflow() {
let mut brick = BrickTiming::new("test", 5.0);
for i in 0..105 {
brick.add_sample(i as f64);
}
assert_eq!(brick.samples.len(), 100);
assert!((brick.samples[0] - 5.0).abs() < 0.001);
assert!((brick.samples[99] - 104.0).abs() < 0.001);
}
#[test]
fn test_add_sample_updates_moving_average() {
let mut brick = BrickTiming::new("test", 5.0);
brick.add_sample(10.0);
assert!((brick.actual_us - 10.0).abs() < 0.001);
brick.add_sample(20.0);
assert!((brick.actual_us - 15.0).abs() < 0.001); brick.add_sample(30.0);
assert!((brick.actual_us - 20.0).abs() < 0.001); }
#[test]
fn test_brick_status_exact_budget() {
let mut brick = BrickTiming::new("test", 5.0);
brick.actual_us = 5.0; assert_eq!(brick.status(), "✅"); }
#[test]
fn test_brick_status_slightly_over() {
let mut brick = BrickTiming::new("test", 5.0);
brick.actual_us = 5.001;
assert_eq!(brick.status(), "❌");
}
#[test]
fn test_gap_factor_under_budget() {
let mut brick = BrickTiming::new("test", 10.0);
brick.actual_us = 5.0;
assert!((brick.gap_factor() - 0.5).abs() < 0.001);
}
#[test]
fn test_gap_factor_exact_budget() {
let mut brick = BrickTiming::new("test", 10.0);
brick.actual_us = 10.0;
assert!((brick.gap_factor() - 1.0).abs() < 0.001);
}
#[test]
fn test_gap_factor_zero_actual_zero_budget() {
let brick = BrickTiming::new("test", 0.0);
assert!((brick.gap_factor() - 1.0).abs() < 0.001);
}
#[test]
fn test_pipeline_bottleneck_returns_some() {
let mut pipeline = PipelineState::new();
pipeline.bricks[3].actual_us = 100.0; let bottleneck = pipeline.bottleneck();
assert!(bottleneck.is_some());
assert_eq!(
bottleneck.expect("should have bottleneck").name,
"Attention"
);
}
#[test]
fn test_pipeline_bottleneck_all_zero_actual() {
let pipeline = PipelineState::new();
let bottleneck = pipeline.bottleneck();
assert!(bottleneck.is_some()); }
#[test]
fn test_pipeline_bottleneck_all_at_budget() {
let mut pipeline = PipelineState::new();
for brick in &mut pipeline.bricks {
brick.actual_us = brick.budget_us;
}
let bottleneck = pipeline.bottleneck();
assert!(bottleneck.is_some());
}
#[test]
fn test_pipeline_update_demo_sets_current_tok_s() {
let mut pipeline = PipelineState::new();
for _ in 0..10 {
pipeline.update_demo();
}
assert!(pipeline.current_tok_s > 0.0);
}
#[test]
fn test_pipeline_update_demo_total_us_calculated() {
let mut pipeline = PipelineState::new();
pipeline.update_demo();
let expected = pipeline.total_actual() * pipeline.total_layers as f64;
assert!((pipeline.total_us - expected).abs() < 0.001);
}
#[test]
fn test_compute_brick_score_zero_actual() {
assert_eq!(compute_brick_score(0.0, 5.0), 100);
}
#[test]
fn test_compute_brick_score_exactly_120_percent() {
assert_eq!(compute_brick_score(6.0, 5.0), 90);
}
#[test]
fn test_compute_brick_score_just_over_120_percent() {
assert_eq!(compute_brick_score(6.05, 5.0), 79);
}
#[test]
fn test_ci_threshold_both_fail() {
let report = HeadlessReport {
model: "test".to_string(),
timestamp: "now".to_string(),
hardware: HardwareInfo {
gpu: "test".to_string(),
cpu: "test".to_string(),
memory_gb: 32,
},
throughput: ThroughputMetrics {
tokens_per_sec: 100.0, ttft_ms: 1.0,
cv_percent: 3.0,
p50_us: 1.0,
p99_us: 2.0,
},
brick_scores: vec![BrickScore {
name: "test".to_string(),
score: 50, grade: "F".to_string(),
budget_us: 1.0,
actual_us: 2.0,
gap_factor: 2.0,
}],
pmat_scores: PmatScores {
rust_project_score: 92.5,
tdg_score: 95.2,
cuda_tdg_score: 88.0,
brick_score: 50,
grade: "F".to_string(),
},
falsification: FalsificationSummary {
total_points: 120,
passed: 100,
failed: 20,
blocked: 0,
},
status: "FAIL".to_string(),
ci_result: "red".to_string(),
};
let config = CbtopConfig {
ci: true,
throughput_threshold: Some(400.0),
brick_score_threshold: Some(90),
..Default::default()
};
assert!(!check_ci_thresholds(&report, &config));
}
#[test]
fn test_ci_threshold_throughput_passes_brick_fails() {
let report = HeadlessReport {
model: "test".to_string(),
timestamp: "now".to_string(),
hardware: HardwareInfo {
gpu: "test".to_string(),
cpu: "test".to_string(),
memory_gb: 32,
},
throughput: ThroughputMetrics {
tokens_per_sec: 500.0, ttft_ms: 1.0,
cv_percent: 3.0,
p50_us: 1.0,
p99_us: 2.0,
},
brick_scores: vec![BrickScore {
name: "test".to_string(),
score: 50, grade: "F".to_string(),
budget_us: 1.0,
actual_us: 2.0,
gap_factor: 2.0,
}],
pmat_scores: PmatScores {
rust_project_score: 92.5,
tdg_score: 95.2,
cuda_tdg_score: 88.0,
brick_score: 50,
grade: "F".to_string(),
},
falsification: FalsificationSummary {
total_points: 120,
passed: 100,
failed: 20,
blocked: 0,
},
status: "FAIL".to_string(),
ci_result: "red".to_string(),
};
let config = CbtopConfig {
ci: true,
throughput_threshold: Some(400.0),
brick_score_threshold: Some(90),
..Default::default()
};
assert!(!check_ci_thresholds(&report, &config));
}
#[test]
fn test_ci_threshold_multiple_brick_scores_average() {
let report = HeadlessReport {
model: "test".to_string(),
timestamp: "now".to_string(),
hardware: HardwareInfo {
gpu: "test".to_string(),
cpu: "test".to_string(),
memory_gb: 32,
},
throughput: ThroughputMetrics {
tokens_per_sec: 500.0,
ttft_ms: 1.0,
cv_percent: 3.0,
p50_us: 1.0,
p99_us: 2.0,
},
brick_scores: vec![
BrickScore {
name: "brick1".to_string(),
score: 100,
grade: "A".to_string(),
budget_us: 1.0,
actual_us: 0.5,
gap_factor: 0.5,
},
BrickScore {
name: "brick2".to_string(),
score: 80,
grade: "B".to_string(),
budget_us: 1.0,
actual_us: 1.2,
gap_factor: 1.2,
},
],
pmat_scores: PmatScores {
rust_project_score: 92.5,
tdg_score: 95.2,
cuda_tdg_score: 88.0,
brick_score: 90,
grade: "A".to_string(),
},
falsification: FalsificationSummary {
total_points: 120,
passed: 100,
failed: 20,
blocked: 0,
},
status: "PASS".to_string(),
ci_result: "green".to_string(),
};
let config = CbtopConfig {
ci: true,
brick_score_threshold: Some(90),
..Default::default()
};
assert!(check_ci_thresholds(&report, &config));
}