bitbelay_cli/commands/
avalanche.rs

1//! A command for running the avalanche test suite.
2
3use std::hash::BuildHasher;
4use std::num::NonZeroUsize;
5
6use anyhow::anyhow;
7use anyhow::bail;
8use anyhow::Context;
9use bitbelay_providers::Provider;
10use bitbelay_report::Config;
11use bitbelay_suites::r#trait::Suite;
12
13/// Arguments for the avalanche command.
14#[derive(clap::Args, Debug)]
15pub struct Args {
16    /// The number of experiments to perform for the Strict Avalanche Criterion
17    /// test.
18    #[arg(short, long, default_value_t = 1 << 12)]
19    experiments: usize,
20
21    /// The number of iterations per experiment for the Strict Avalanche
22    /// Criterion test.
23    #[arg(short, long, default_value_t = 1 << 12)]
24    iterations_per_experiment: usize,
25
26    /// The maximum deviance that any single bit can have off of 50% bias for
27    /// the test to be considered successful.
28    #[arg(short, long, default_value_t = 0.01)]
29    max_deviance: f64,
30}
31
32/// The main function for the avalanche command.
33pub fn main<H: BuildHasher>(
34    args: Args,
35    build_hasher: H,
36    provider: Box<dyn Provider>,
37) -> anyhow::Result<()> {
38    tracing::info!("Starting avalanche test suite.");
39
40    let experiments = NonZeroUsize::try_from(args.experiments)
41        .map_err(|_| anyhow!("--experiments must be non-zero!"))?;
42
43    let iterations_per_experiment = NonZeroUsize::try_from(args.iterations_per_experiment)
44        .map_err(|_| anyhow!("--iterations per experiment must be non-zero!"))?;
45
46    let max_deviance = if (0.0..=1.0).contains(&args.max_deviance) {
47        args.max_deviance
48    } else {
49        bail!("--max-deviance must be in the range of [0, 1]!")
50    };
51
52    let mut suite = bitbelay_suites::avalanche::suite::Builder::<H, 64>::default()
53        .build_hasher(&build_hasher)?
54        .try_build()?;
55
56    suite
57        .run_strict_avalanche_criterion_test(
58            provider,
59            experiments,
60            iterations_per_experiment,
61            max_deviance,
62        )
63        .with_context(|| "running strict avalanche criterion test")?;
64
65    suite
66        .report()
67        .write_to(&mut std::io::stderr(), &Config::default())?;
68
69    Ok(())
70}