mobench_sdk/registry.rs
1//! Benchmark function registry
2//!
3//! This module provides runtime discovery of benchmark functions that have been
4//! marked with the `#[benchmark]` attribute macro.
5
6use crate::types::BenchError;
7
8/// A registered benchmark function
9///
10/// This struct is submitted to the global registry by the `#[benchmark]` macro.
11/// It contains the function's name and a closure that invokes it.
12pub struct BenchFunction {
13 /// Fully-qualified name of the benchmark function (e.g., "my_crate::my_module::my_bench")
14 pub name: &'static str,
15
16 /// Function that invokes the benchmark
17 ///
18 /// Takes optional arguments and returns a Result.
19 /// Arguments are currently unused but reserved for future parameterization.
20 pub invoke: fn(&[String]) -> Result<(), BenchError>,
21}
22
23// Register the BenchFunction type with inventory
24inventory::collect!(BenchFunction);
25
26/// Discovers all registered benchmark functions
27///
28/// Returns a vector of references to all functions that have been marked with
29/// the `#[benchmark]` attribute in the current binary.
30///
31/// # Example
32///
33/// ```ignore
34/// use mobench_sdk::registry::discover_benchmarks;
35///
36/// let benchmarks = discover_benchmarks();
37/// for bench in benchmarks {
38/// println!("Found benchmark: {}", bench.name);
39/// }
40/// ```
41pub fn discover_benchmarks() -> Vec<&'static BenchFunction> {
42 inventory::iter::<BenchFunction>().collect()
43}
44
45/// Finds a benchmark function by name
46///
47/// Searches the registry for a function with the given name. Supports both
48/// short names (e.g., "fibonacci") and fully-qualified names
49/// (e.g., "my_crate::fibonacci").
50///
51/// # Arguments
52///
53/// * `name` - The name of the benchmark to find
54///
55/// # Returns
56///
57/// * `Some(&BenchFunction)` if found
58/// * `None` if no matching benchmark exists
59///
60/// # Example
61///
62/// ```ignore
63/// use mobench_sdk::registry::find_benchmark;
64///
65/// if let Some(bench) = find_benchmark("fibonacci") {
66/// println!("Found benchmark: {}", bench.name);
67/// } else {
68/// eprintln!("Benchmark not found");
69/// }
70/// ```
71pub fn find_benchmark(name: &str) -> Option<&'static BenchFunction> {
72 inventory::iter::<BenchFunction>().find(|f| {
73 // Match either the full name or just the final component
74 f.name == name || f.name.ends_with(&format!("::{}", name))
75 })
76}
77
78/// Lists all registered benchmark names
79///
80/// Returns a sorted vector of all benchmark function names in the registry.
81///
82/// # Example
83///
84/// ```ignore
85/// use mobench_sdk::registry::list_benchmark_names;
86///
87/// let names = list_benchmark_names();
88/// println!("Available benchmarks:");
89/// for name in names {
90/// println!(" - {}", name);
91/// }
92/// ```
93pub fn list_benchmark_names() -> Vec<&'static str> {
94 let mut names: Vec<&'static str> = inventory::iter::<BenchFunction>().map(|f| f.name).collect();
95 names.sort();
96 names
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_discover_benchmarks() {
105 // Note: This test validates that the discovery function works
106 // The number of benchmarks depends on what's registered in the binary
107 let benchmarks = discover_benchmarks();
108 // Just ensure the function returns successfully
109 let _ = benchmarks;
110 }
111
112 #[test]
113 fn test_find_benchmark_none() {
114 // Should not find a non-existent benchmark
115 let result = find_benchmark("nonexistent_benchmark_function_12345");
116 assert!(result.is_none());
117 }
118
119 #[test]
120 fn test_list_benchmark_names() {
121 // Validates that the function returns successfully
122 let names = list_benchmark_names();
123 let _ = names;
124 }
125}