use crate::{BenchError, BenchSpec};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum BrowserRunnerError {
#[error("failed to parse BenchSpec JSON: {0}")]
InvalidSpec(serde_json::Error),
#[error("failed to run benchmark: {0}")]
Benchmark(#[from] BenchError),
#[error("failed to serialize RunnerReport JSON: {0}")]
SerializeReport(serde_json::Error),
}
pub fn run_benchmark_json(spec_json: &str) -> Result<String, BrowserRunnerError> {
let spec =
serde_json::from_str::<BenchSpec>(spec_json).map_err(BrowserRunnerError::InvalidSpec)?;
let report = crate::run_benchmark(spec)?;
serde_json::to_string(&report).map_err(BrowserRunnerError::SerializeReport)
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen::prelude::wasm_bindgen(js_name = runBenchmarkJson)]
pub fn run_benchmark_json_wasm(spec_json: &str) -> Result<String, wasm_bindgen::JsValue> {
run_benchmark_json(spec_json)
.map_err(|error| wasm_bindgen::JsValue::from_str(&error.to_string()))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::timing::{BenchReport, TimingError, run_closure};
fn run_test_benchmark(spec: BenchSpec) -> Result<BenchReport, TimingError> {
run_closure(spec, || {
std::hint::black_box(21_u64.saturating_mul(2));
Ok(())
})
}
inventory::submit! {
crate::registry::BenchFunction {
name: "mobench_sdk::web::tests::browser_json_contract",
runner: run_test_benchmark,
}
}
#[test]
fn returns_runner_report_json() {
let result =
run_benchmark_json(r#"{"name":"browser_json_contract","iterations":2,"warmup":1}"#)
.expect("browser benchmark should run");
let report: crate::RunnerReport =
serde_json::from_str(&result).expect("valid RunnerReport JSON");
assert_eq!(report.spec.name, "browser_json_contract");
assert_eq!(report.samples.len(), 2);
}
#[test]
fn rejects_invalid_spec_json() {
let error = run_benchmark_json("{not json}").expect_err("invalid JSON should fail");
assert!(matches!(error, BrowserRunnerError::InvalidSpec(_)));
assert!(error.to_string().contains("failed to parse BenchSpec JSON"));
}
#[test]
fn reports_unknown_benchmark() {
let error = run_benchmark_json(
r#"{"name":"definitely_missing_browser_benchmark","iterations":1,"warmup":0}"#,
)
.expect_err("unknown function should fail");
assert!(matches!(
error,
BrowserRunnerError::Benchmark(BenchError::UnknownFunction(_, _))
));
}
}