mod server;
pub use server::{run_harness, run_harness_async};
use std::collections::HashMap;
use std::time::Duration;
pub type BenchmarkFn = Box<dyn Fn(u64) -> Duration + Send + Sync>;
pub struct BenchmarkRegistry {
benchmarks: HashMap<String, BenchmarkFn>,
}
impl BenchmarkRegistry {
pub fn new() -> Self {
Self {
benchmarks: HashMap::new(),
}
}
pub fn register<F>(&mut self, name: impl Into<String>, f: F)
where
F: Fn(u64) -> Duration + Send + Sync + 'static,
{
self.benchmarks.insert(name.into(), Box::new(f));
}
pub fn list(&self) -> Vec<String> {
self.benchmarks.keys().cloned().collect()
}
pub fn run(&self, name: &str, iterations: u64) -> Option<Duration> {
self.benchmarks.get(name).map(|f| f(iterations))
}
pub fn contains(&self, name: &str) -> bool {
self.benchmarks.contains_key(name)
}
pub fn len(&self) -> usize {
self.benchmarks.len()
}
pub fn is_empty(&self) -> bool {
self.benchmarks.is_empty()
}
}
impl Default for BenchmarkRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_registry_new() {
let registry = BenchmarkRegistry::new();
assert!(registry.is_empty());
assert_eq!(registry.len(), 0);
}
#[test]
fn test_registry_register_and_list() {
let mut registry = BenchmarkRegistry::new();
registry.register("bench1", |_n| Duration::from_millis(10));
registry.register("bench2", |_n| Duration::from_millis(20));
assert_eq!(registry.len(), 2);
assert!(registry.contains("bench1"));
assert!(registry.contains("bench2"));
assert!(!registry.contains("bench3"));
let names = registry.list();
assert_eq!(names.len(), 2);
assert!(names.contains(&"bench1".to_string()));
assert!(names.contains(&"bench2".to_string()));
}
#[test]
fn test_registry_run_passes_iterations() {
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
let observed = Arc::new(AtomicU64::new(0));
let observed_clone = Arc::clone(&observed);
let mut registry = BenchmarkRegistry::new();
registry.register("iter_echo", move |n| {
observed_clone.store(n, Ordering::SeqCst);
Duration::from_nanos(n * 100)
});
let result = registry.run("iter_echo", 42);
assert_eq!(result, Some(Duration::from_nanos(4200)));
assert_eq!(observed.load(Ordering::SeqCst), 42);
}
#[test]
fn test_registry_run_missing() {
let mut registry = BenchmarkRegistry::new();
registry.register("exists", |_n| Duration::from_millis(5));
assert!(registry.run("missing", 1).is_none());
}
#[test]
fn test_registry_default() {
let registry = BenchmarkRegistry::default();
assert!(registry.is_empty());
}
}