opcda_bridge_client/
lib.rs1pub mod cli;
2pub mod commands;
3pub mod config;
4pub mod output;
5
6#[cfg(test)]
7mod test_support;
8
9use std::process::ExitCode;
10
11pub async fn run() -> ExitCode {
18 use clap::Parser;
19 run_with_cli(cli::Cli::parse()).await
20}
21
22async fn run_with_cli(cli: cli::Cli) -> ExitCode {
32 let cli_format = output::resolve_from_cli(&cli);
33 match config::load_config(cli.config.as_deref()) {
34 Err(e) => fail(&e, cli_format.unwrap_or(output::OutputFormat::Table)),
35 Ok(config) => {
36 let format = config::resolve_output(cli_format, &config);
37 match cli::run_command(cli, &config, format).await {
38 Ok(()) => ExitCode::SUCCESS,
39 Err(e) => fail(&e, format),
40 }
41 }
42 }
43}
44
45fn fail(err: &anyhow::Error, format: output::OutputFormat) -> ExitCode {
48 eprintln!("{}", output::format_error(err, format));
49 ExitCode::FAILURE
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::cli::{Cli, Commands};
56 use crate::test_support::{MockBridgeService, start_mock_server};
57 use std::path::PathBuf;
58
59 fn base_cli(command: Commands) -> Cli {
60 Cli {
61 host: None,
62 config: None,
63 output: None,
64 json: false,
65 command,
66 }
67 }
68
69 #[tokio::test]
70 async fn test_run_with_cli_success_is_exit_success() {
71 let host = start_mock_server(MockBridgeService::default()).await;
72 let mut cli = base_cli(Commands::Servers);
73 cli.host = Some(host);
74 assert_eq!(run_with_cli(cli).await, ExitCode::SUCCESS);
75 }
76
77 #[tokio::test]
78 async fn test_run_with_cli_command_error_is_exit_failure() {
79 let cli = base_cli(Commands::Browse {
82 server: None,
83 session_id: None,
84 parent_node_key: None,
85 page_token: None,
86 page_size: None,
87 all: false,
88 max_results: None,
89 refresh: false,
90 });
91 assert_eq!(run_with_cli(cli).await, ExitCode::FAILURE);
92 }
93
94 #[tokio::test]
95 async fn test_run_with_cli_config_load_failure_is_exit_failure() {
96 let mut cli = base_cli(Commands::Servers);
99 cli.config = Some(PathBuf::from("/nonexistent/opcda-bridge-client.toml"));
100 assert_eq!(run_with_cli(cli).await, ExitCode::FAILURE);
101 }
102
103 #[tokio::test]
104 async fn test_run_with_cli_config_load_failure_uses_cli_only_format() {
105 let mut cli = base_cli(Commands::Servers);
110 cli.config = Some(PathBuf::from("/nonexistent/opcda-bridge-client.toml"));
111 cli.json = true;
112 assert_eq!(run_with_cli(cli).await, ExitCode::FAILURE);
113 }
114
115 #[test]
116 fn test_fail_returns_exit_failure() {
117 let err = anyhow::anyhow!("boom");
118 assert_eq!(fail(&err, output::OutputFormat::Table), ExitCode::FAILURE);
119 assert_eq!(fail(&err, output::OutputFormat::Json), ExitCode::FAILURE);
120 }
121}