1#[cfg(test)]
4extern crate self as cf_integration;
5
6use std::{io::Write, process::ExitCode};
7
8use clap::Parser;
9
10mod app;
11mod cli;
12mod conformance;
13mod error;
14mod infrastructure;
15mod mcp;
16mod output;
17mod performance;
18mod runtime;
19
20use app::resolve_action;
21use cli::Cli;
22use error::AppFailure;
23use infrastructure::config::{AppConfig, ConfigBootstrap, Environment};
24use infrastructure::process::SystemProcessRunner;
25pub(crate) use output::{Activity, OutputStyle, TestStatus};
26use runtime::RuntimeContext;
27
28pub async fn run() -> ExitCode {
30 let arguments = std::env::args_os().collect::<Vec<_>>();
31 if conformance::client::is_internal_client_invocation(&arguments) {
32 return match conformance::client::run_internal_client(&arguments).await {
33 Ok(()) => ExitCode::SUCCESS,
34 Err(error) => {
35 eprintln!(
36 "{}: {}",
37 conformance::client::CLIENT_DRIVER_FAILURE_PREFIX,
38 OutputStyle::stderr().failure(&format!("{error:#}"))
39 );
40 ExitCode::FAILURE
41 }
42 };
43 }
44 let cli = Cli::parse_from(arguments);
45 let environment: Environment = std::env::vars_os().collect();
46 let cwd = match std::env::current_dir() {
47 Ok(path) => path,
48 Err(error) => {
49 eprintln!(
50 "{}",
51 OutputStyle::stderr()
52 .failure(&format!("failed to determine current directory: {error}"))
53 );
54 return ExitCode::FAILURE;
55 }
56 };
57 let bootstrap = match ConfigBootstrap::load(&environment, &cwd) {
58 Ok(loaded) => loaded,
59 Err(error) => {
60 eprintln!("{}", OutputStyle::stderr().failure(&format!("{error:#}")));
61 return ExitCode::FAILURE;
62 }
63 };
64 for warning in bootstrap.warnings() {
65 eprintln!(
66 "{}",
67 OutputStyle::stderr().warning(&format!("warning: {warning}"))
68 );
69 }
70
71 let effective_environment = bootstrap
72 .environment()
73 .iter()
74 .map(|(key, value)| (key.clone(), value.value.clone()))
75 .collect::<Environment>();
76 let action = match resolve_action(cli, &effective_environment) {
77 Ok(action) => action,
78 Err(error) => return report_failure(AppFailure::from(error)),
79 };
80 let requirements = action.config_requirements();
81 eprintln!("{}", OutputStyle::stderr().info(&action.startup_summary()));
82 let activity = action
83 .uses_global_activity()
84 .then(|| Activity::spinner(action.description()));
85 let config = match AppConfig::load(bootstrap, requirements) {
86 Ok(config) => config,
87 Err(error) => {
88 if let Some(activity) = activity {
89 activity.finish(false);
90 }
91 return report_failure(AppFailure::from(error));
92 }
93 };
94 let runtime = RuntimeContext::new(config, SystemProcessRunner);
95 let result = runtime.execute(action).await;
96 if let Some(activity) = activity {
97 activity.finish(result.is_ok());
98 }
99 match result {
100 Ok(()) => ExitCode::SUCCESS,
101 Err(error) => report_failure(error),
102 }
103}
104
105fn report_failure(error: AppFailure) -> ExitCode {
106 let _ = std::io::stdout().flush();
109 if !error.is_reported() {
110 eprintln!("{}", OutputStyle::stderr().failure(&error.to_string()));
111 }
112 exit_code(error.exit_code())
113}
114
115fn exit_code(code: i32) -> ExitCode {
116 u8::try_from(code)
117 .map(ExitCode::from)
118 .unwrap_or(ExitCode::FAILURE)
119}
120
121#[cfg(test)]
122#[path = "app_tests.rs"]
123mod app_tests;
124#[cfg(test)]
125#[path = "cli_public_tests.rs"]
126mod cli_public_tests;
127#[cfg(test)]
128#[path = "conformance/fixture_tests.rs"]
129mod conformance_fixture_tests;
130#[cfg(test)]
131#[path = "conformance/results_tests.rs"]
132mod conformance_tests;
133#[cfg(test)]
134#[path = "infrastructure/checkout_integration_tests.rs"]
135mod infrastructure_checkout_tests;
136#[cfg(test)]
137#[path = "infrastructure/compose_integration_tests.rs"]
138mod infrastructure_compose_tests;
139#[cfg(test)]
140#[path = "infrastructure/config_integration_tests.rs"]
141mod infrastructure_config_tests;
142#[cfg(test)]
143#[path = "infrastructure/process_integration_tests.rs"]
144mod infrastructure_process_tests;
145#[cfg(test)]
146#[path = "infrastructure/stack_integration_tests.rs"]
147mod infrastructure_stack_tests;
148#[cfg(test)]
149#[path = "mcp/auth_proxy_integration_tests.rs"]
150mod mcp_auth_proxy_tests;
151#[cfg(test)]
152#[path = "mcp/backend_identity_integration_tests.rs"]
153mod mcp_backend_identity_tests;
154#[cfg(test)]
155#[path = "mcp/gateway_integration_tests.rs"]
156mod mcp_gateway_tests;
157#[cfg(test)]
158#[path = "mcp/protocol_integration_tests.rs"]
159mod mcp_protocol_tests;
160#[cfg(test)]
161#[path = "performance/locust_integration_tests.rs"]
162mod performance_locust_tests;
163#[cfg(test)]
164#[path = "performance/python_adapter_tests.rs"]
165mod performance_python_adapter_tests;