Skip to content

Commit 2aee416

Browse files
committed
added --silent arg
1 parent 802d8a4 commit 2aee416

2 files changed

Lines changed: 85 additions & 16 deletions

File tree

src/cli.rs

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ pub struct Cli {
2525
#[arg(long)]
2626
pub text: bool,
2727

28+
/// Run silently: suppress all output except errors (for cron usage)
29+
#[arg(long)]
30+
pub silent: bool,
31+
2832
/// Download phase duration
2933
#[arg(long, default_value = "10s")]
3034
pub download_duration: humantime::Duration,
@@ -95,6 +99,18 @@ pub struct Cli {
9599
}
96100

97101
pub async fn run(args: Cli) -> Result<()> {
102+
// Validate that --silent can only be used with --json
103+
if args.silent && !args.json {
104+
return Err(anyhow::anyhow!(
105+
"--silent can only be used with --json. Use --silent --json together."
106+
));
107+
}
108+
109+
// Silent mode takes precedence over other output modes
110+
if args.silent {
111+
return run_test_engine(args, true).await;
112+
}
113+
98114
if !args.json && !args.text {
99115
#[cfg(feature = "tui")]
100116
{
@@ -108,7 +124,7 @@ pub async fn run(args: Cli) -> Result<()> {
108124
}
109125

110126
if args.json {
111-
return run_json(args).await;
127+
return run_test_engine(args, false).await;
112128
}
113129

114130
run_text(args).await
@@ -143,29 +159,63 @@ pub fn build_config(args: &Cli) -> RunConfig {
143159
}
144160
}
145161

146-
async fn run_json(args: Cli) -> Result<()> {
162+
/// Common function to run the test engine and process results.
163+
/// `silent` controls whether to consume events and suppress output.
164+
async fn run_test_engine(args: Cli, silent: bool) -> Result<()> {
147165
let cfg = build_config(&args);
148-
let (evt_tx, _) = mpsc::channel::<TestEvent>(1024);
149-
let (_, ctrl_rx) = mpsc::channel::<EngineControl>(16);
166+
let network_info = crate::network::gather_network_info(&args);
167+
let enriched = if silent {
168+
// In silent mode, spawn task and consume events
169+
let (evt_tx, mut evt_rx) = mpsc::channel::<TestEvent>(2048);
170+
let (_, ctrl_rx) = mpsc::channel::<EngineControl>(16);
150171

151-
let engine = TestEngine::new(cfg);
152-
let result = engine
153-
.run(evt_tx, ctrl_rx)
154-
.await
155-
.context("speed test failed")?;
172+
let engine = TestEngine::new(cfg);
173+
let handle = tokio::spawn(async move { engine.run(evt_tx, ctrl_rx).await });
156174

157-
// Gather network information and enrich result
158-
let network_info = crate::network::gather_network_info(&args);
159-
let enriched = crate::network::enrich_result(&result, &network_info);
175+
// Consume events silently (no output)
176+
while let Some(_ev) = evt_rx.recv().await {
177+
// All events are silently consumed - no output
178+
}
179+
180+
let result = handle
181+
.await
182+
.context("test engine task failed")?
183+
.context("speed test failed")?;
184+
185+
crate::network::enrich_result(&result, &network_info)
186+
} else {
187+
// In JSON mode, directly await the engine (no need to consume events)
188+
let (evt_tx, _) = mpsc::channel::<TestEvent>(1024);
189+
let (_, ctrl_rx) = mpsc::channel::<EngineControl>(16);
160190

191+
let engine = TestEngine::new(cfg);
192+
let result = engine
193+
.run(evt_tx, ctrl_rx)
194+
.await
195+
.context("speed test failed")?;
196+
197+
crate::network::enrich_result(&result, &network_info)
198+
};
199+
200+
// Handle exports (errors will propagate)
161201
handle_exports(&args, &enriched)?;
162202

163-
println!("{}", serde_json::to_string_pretty(&enriched)?);
203+
if !silent {
204+
// Print JSON output in non-silent mode
205+
println!("{}", serde_json::to_string_pretty(&enriched)?);
206+
}
207+
208+
// Save results if auto_save is enabled
164209
if args.auto_save {
165-
if let Ok(p) = crate::storage::save_run(&enriched) {
166-
eprintln!("Saved: {}", p.display());
210+
if silent {
211+
crate::storage::save_run(&enriched).context("failed to save run results")?;
212+
} else {
213+
if let Ok(p) = crate::storage::save_run(&enriched) {
214+
eprintln!("Saved: {}", p.display());
215+
}
167216
}
168217
}
218+
169219
Ok(())
170220
}
171221

src/main.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,24 @@ use clap::Parser;
1414
#[tokio::main]
1515
async fn main() -> Result<()> {
1616
let args = cli::Cli::parse();
17-
cli::run(args).await
17+
let is_silent = args.silent;
18+
let is_non_tui = args.silent || args.json || args.text;
19+
20+
match cli::run(args).await {
21+
Ok(()) => {
22+
// Explicitly exit with code 0 on success, especially for non-TUI modes
23+
if is_non_tui {
24+
std::process::exit(0);
25+
}
26+
Ok(())
27+
}
28+
Err(e) => {
29+
if is_silent {
30+
println!("{}", e);
31+
std::process::exit(1);
32+
} else {
33+
Err(e)
34+
}
35+
}
36+
}
1837
}

0 commit comments

Comments
 (0)