gather_all_code_from_crates/
build_effective_config_from_cli.rs

1crate::ix!();
2
3/// Attempts to load global configuration and merge it with CLI arguments to produce an EffectiveConfig.
4/// Returns `Result<EffectiveConfig, AppError>` if successful, or `AppError` if something goes wrong.
5pub fn build_effective_config_from_cli() -> Result<EffectiveConfig, AppError> {
6    let cli = Cli::from_args();
7
8    // Try to load global config, fallback to defaults if needed
9    let global_cfg = match load_global_config() {
10        Ok(cfg) => cfg,
11        Err(_e) => {
12            // If config load fails, use defaults
13            GlobalConfigBuilder::default()
14                .build()
15                .map_err(|_| AppError::Config { reason: ErrorReason::Config })?
16        }
17    };
18
19    // Merge CLI and global config into EffectiveConfig
20    EffectiveConfig::from_cli_and_global(&cli, &global_cfg)
21}
22
23#[cfg(test)]
24mod build_effective_config_from_cli_tests {
25    use super::*;
26    use std::env;
27
28    #[test]
29    fn test_effective_config_with_mocked_cli_and_global() {
30        // Prepare a mock global config
31        let global_cfg = GlobalConfigBuilder::default()
32            .default_include_tests(true)
33            .default_omit_bodies(false)
34            .build().unwrap();
35
36        // Prepare a mock CLI. Since Cli::from_args() is used at runtime,
37        // For testing, we can directly build a Cli instance using the builder if available.
38        let cli = CliBuilder::default()
39            .crates(vec![])
40            .include_tests(false)
41            .omit_private(true)
42            .omit_bodies(false)
43            .excluded_files(vec!["some_file.rs".to_string()])
44            .build()
45            .unwrap();
46
47        // Merge them
48        let eff = EffectiveConfig::from_cli_and_global(&cli, &global_cfg).unwrap();
49
50        // Assert conditions
51        // include_tests = true from global OR cli (global=true, cli=false => true)
52        assert_eq!(*eff.criteria().include_tests(), true);
53        // omit_private = true from cli
54        assert_eq!(*eff.criteria().omit_private(), true);
55        // omit_bodies = global=false, cli=false => false OR false => false
56        assert_eq!(*eff.criteria().omit_bodies(), false);
57        // Excluded files from cli are present
58        assert!(eff.criteria().excluded_files().contains(&"some_file.rs".to_string()));
59    }
60
61    #[test]
62    fn test_build_effective_config_from_cli_with_no_global_config() {
63        // Temporarily remove HOME env var to force global config load to fail
64        let original_home = std::env::var_os("HOME");
65        std::env::remove_var("HOME");
66
67        // Simulate CLI arguments using `from_iter`
68        let args = vec!["myprog", "--include-tests", "--omit-private"];
69        let cli = Cli::from_iter(args);
70
71        // Simulate global config load failure and fallback to default
72        let global_cfg = match GlobalConfigBuilder::default().build() {
73            Ok(cfg) => cfg,
74            Err(_) => panic!("Failed to build default global config"),
75        };
76
77        // Now call the logic for building the effective config
78        let result = EffectiveConfig::from_cli_and_global(&cli, &global_cfg);
79        assert!(result.is_ok());
80        let eff = result.unwrap();
81
82        // From CLI: include_tests=true, omit_private=true
83        assert_eq!(*eff.criteria().include_tests(), true);
84        assert_eq!(*eff.criteria().omit_private(), true);
85
86        // Restore HOME if it was set
87        if let Some(h) = original_home {
88            std::env::set_var("HOME", h);
89        }
90    }
91}