fastiron_stats/
command_line.rs

1//! Module used for I/O handling
2//!
3//! This module holds all the code defining the CLI, i.e. the entire I/O system of
4//! the program.
5
6use clap::{Args, Parser};
7
8/// fastiron-stats, a profiling companion for Fastiron
9#[derive(Debug, Parser)]
10#[command(author, version, about, arg_required_else_help(true))]
11pub struct Cli {
12    /// name of the two timers report files to compare - old report first, new report second
13    #[arg(short = 'T', long = "timers-comparison", num_args(2))]
14    pub comparison: Option<Vec<String>>,
15
16    /// name of the tallies file to analyze
17    #[arg(short = 'E', long = "event-correlation", num_args(1))]
18    pub correlation: Option<String>,
19
20    /// root path of timer files for weak scaling data
21    #[arg(
22        short = 'W',
23        long = "weak-scaling",
24        num_args(1),
25        requires_all(vec!["t_init", "t_iter", "t_factor"])
26    )]
27    pub weak_scaling_root: Option<String>,
28
29    /// root path of timer files for strong scaling data
30    #[arg(
31        short = 'S',
32        long = "strong-scaling",
33        num_args(1),
34        requires_all(vec!["t_init", "t_iter", "t_factor"])
35    )]
36    pub strong_scaling_root: Option<String>,
37
38    #[command(flatten)]
39    pub scaling_params: ScalingParams,
40
41    /// if present, plot the results of all computed metrics
42    #[arg(short = 'p', long = "plot", num_args(0))]
43    pub plot: bool,
44}
45
46/// Structure used to hold all scaling parameters.
47#[derive(Args, Debug)]
48pub struct ScalingParams {
49    /// starting number of threads for scaling data
50    #[arg(short = 't', long = "thread_init_n", num_args(1))]
51    pub t_init: Option<usize>,
52
53    /// starting number of threads for scaling data
54    #[arg(short = 'i', long = "thread_iter_n", num_args(1))]
55    pub t_iter: Option<usize>,
56
57    /// starting number of threads for scaling data
58    #[arg(short = 'f', long = "thread_step_factor", num_args(1))]
59    pub t_factor: Option<usize>,
60}
61
62//=============
63// Unit tests
64//=============
65
66#[cfg(test)]
67mod tests {
68    #[test]
69    fn verify_cli_parsing() {
70        use super::*;
71        let cmd_line = "./fastiron-stats -E file_path1 -T oldfile newfile --strong-scaling file_path2/rootname_t -t 1 -i 9 -f 2";
72        let cli = Cli::parse_from(cmd_line.split(' '));
73        assert!(cli.weak_scaling_root.is_none());
74        assert_eq!(cli.correlation.unwrap(), "file_path1");
75        assert_eq!(
76            cli.comparison.unwrap(),
77            vec!["oldfile".to_string(), "newfile".to_string()]
78        );
79        assert_eq!(cli.strong_scaling_root.unwrap(), "file_path2/rootname_t");
80        assert_eq!(cli.scaling_params.t_init.unwrap(), 1);
81        assert_eq!(cli.scaling_params.t_iter.unwrap(), 9);
82        assert_eq!(cli.scaling_params.t_factor.unwrap(), 2);
83    }
84
85    #[test]
86    fn missing_scaling_param() {
87        use super::*;
88        let cmd_line = "./fastiron-stats --strong-scaling file_path2/rootname_t -t 1 -f 2";
89        let cli = Cli::try_parse_from(cmd_line.split(' '));
90        assert!(cli.is_err());
91        assert_eq!(
92            cli.unwrap_err().kind(),
93            clap::error::ErrorKind::MissingRequiredArgument
94        );
95    }
96}