summaryrefslogtreecommitdiff
path: root/src/bin/obnam-benchmark.rs
blob: 76ab620e33a344893e6eb33ef392585fd8139adb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use log::{debug, error, info};
use obnam_benchmark::result::Result;
use obnam_benchmark::specification::Specification;
use obnam_benchmark::state::State;
use std::fs::File;
use std::path::PathBuf;
use std::process::exit;
use structopt::StructOpt;

fn main() {
    pretty_env_logger::init_custom_env("OBNAM_BENCHMARK_LOG");
    info!("obnam-benchmark starts");
    if let Err(err) = real_main() {
        eprintln!("ERROR: {}", err);
        error!("{}", err);
        exit(1);
    }
    info!("obnam-benchmark ends successfully");
}

fn real_main() -> anyhow::Result<()> {
    debug!("parsing command line");
    let opt = Opt::from_args();
    debug!("parsed: {:#?}", opt);

    match opt.cmd {
        Command::Run(x) => x.run()?,
        Command::Spec(x) => x.run()?,
    }

    Ok(())
}

#[derive(Debug, StructOpt)]
struct Opt {
    #[structopt(subcommand)]
    cmd: Command,
}

#[derive(Debug, StructOpt)]
enum Command {
    /// Run benchmarks
    Run(Run),

    /// Dump the specification as JSON
    Spec(Spec),
}

#[derive(Debug, StructOpt)]
struct Run {
    /// Name of the specification file
    #[structopt(parse(from_os_str))]
    spec: PathBuf,

    /// Name of file where the results will be written.
    #[structopt(long, parse(from_os_str))]
    output: PathBuf,
}

impl Run {
    fn run(&self) -> anyhow::Result<()> {
        info!("running benchmarks from {}", self.spec.display());
        let spec = Specification::from_file(&self.spec)?;
        let mut state = State::new()?;
        let mut result = Result::default();
        for step in spec.steps() {
            if let Some(m) = state.execute(&step)? {
                result.push(m);
            }
        }
        debug!("writing results to {}", self.output.display());
        let output = File::create(&self.output)?;
        serde_json::to_writer_pretty(&output, &result)?;
        Ok(())
    }
}

#[derive(Debug, StructOpt)]
struct Spec {
    /// Name of the specification file
    #[structopt(parse(from_os_str))]
    spec: PathBuf,

    /// Name of JSON file to write
    #[structopt(long, parse(from_os_str))]
    output: PathBuf,
}

impl Spec {
    fn run(&self) -> anyhow::Result<()> {
        info!("dumping specification file as JSON");
        debug!("reading specification from {}", self.spec.display());
        let input = File::open(&self.spec)?;
        let spec: Specification = serde_yaml::from_reader(&input)?;

        debug!("writing specification as JSON to {}", self.output.display());
        let output = File::create(&self.output)?;
        serde_json::to_writer(&output, &spec)?;

        Ok(())
    }
}