#![cfg(e2e_test)]
mod common;
use common::{
REGION, TestHelper, create_temp_dir, create_test_file, generate_bucket_name, run, s7cmd_cmd,
};
use std::process::Command;
const TRACING_ENV: &[&str] = &[
"RUST_LOG",
"NO_COLOR",
"CLICOLOR",
"JSON_TRACING",
"TRACING_STDERR",
"AWS_SDK_TRACING",
];
fn scrub_env(cmd: &mut Command) {
for var in TRACING_ENV {
cmd.env_remove(var);
}
}
fn trace_marker_present(s: &str) -> bool {
s.contains(" TRACE ")
|| s.contains(" DEBUG ")
|| s.contains(" INFO ")
|| s.contains(" WARN ")
|| s.contains(" ERROR ")
|| s.contains("config =")
}
#[tokio::test]
async fn sync_tracing_goes_to_stdout_by_default() {
let helper = TestHelper::new().await;
let bucket = generate_bucket_name();
helper.create_bucket(&bucket, REGION).await;
let local_dir = create_temp_dir();
let target = format!("s3://{bucket}/");
let mut cmd = s7cmd_cmd();
cmd.args([
"sync",
"--target-profile",
"s7cmd-e2e-test",
"--target-region",
REGION,
"-vvv",
"--disable-color-tracing",
local_dir.to_str().unwrap(),
&target,
]);
scrub_env(&mut cmd);
let (_code, stdout, stderr) = run(&mut cmd);
assert!(
trace_marker_present(&stdout),
"sync tracing must appear on stdout; stdout={stdout}\nstderr={stderr}"
);
assert!(
!trace_marker_present(&stderr),
"sync tracing must NOT leak to stderr; stderr={stderr}"
);
helper.delete_bucket_with_cascade(&bucket).await;
let _ = std::fs::remove_dir_all(&local_dir);
}
#[tokio::test]
async fn ls_tracing_goes_to_stderr() {
let helper = TestHelper::new().await;
let bucket = generate_bucket_name();
helper.create_bucket(&bucket, REGION).await;
let target = format!("s3://{bucket}/");
let mut cmd = s7cmd_cmd();
cmd.args([
"ls",
"--target-profile",
"s7cmd-e2e-test",
"--target-region",
REGION,
"-vvv",
"--disable-color-tracing",
&target,
]);
scrub_env(&mut cmd);
let (_code, stdout, stderr) = run(&mut cmd);
assert!(
trace_marker_present(&stderr),
"ls tracing must appear on stderr; stdout={stdout}\nstderr={stderr}"
);
assert!(
!trace_marker_present(&stdout),
"ls tracing must NOT leak to stdout; stdout={stdout}"
);
helper.delete_bucket_with_cascade(&bucket).await;
}
#[tokio::test]
async fn clean_tracing_goes_to_stderr() {
let helper = TestHelper::new().await;
let bucket = generate_bucket_name();
helper.create_bucket(&bucket, REGION).await;
let target = format!("s3://{bucket}/");
let mut cmd = s7cmd_cmd();
cmd.args([
"clean",
"--target-profile",
"s7cmd-e2e-test",
"--target-region",
REGION,
"--force",
"-vvv",
"--disable-color-tracing",
&target,
]);
scrub_env(&mut cmd);
let (_code, stdout, stderr) = run(&mut cmd);
assert!(
trace_marker_present(&stderr),
"clean tracing must appear on stderr; stdout={stdout}\nstderr={stderr}"
);
assert!(
!trace_marker_present(&stdout),
"clean tracing must NOT leak to stdout; stdout={stdout}"
);
helper.delete_bucket_with_cascade(&bucket).await;
}
#[tokio::test]
async fn cp_tracing_goes_to_stderr() {
let helper = TestHelper::new().await;
let bucket = generate_bucket_name();
helper.create_bucket(&bucket, REGION).await;
let local_dir = create_temp_dir();
let src = create_test_file(&local_dir, "trace.txt", b"trace body");
let target = format!("s3://{bucket}/trace.txt");
let mut cmd = s7cmd_cmd();
cmd.args([
"cp",
"--target-profile",
"s7cmd-e2e-test",
"--target-region",
REGION,
"-vvv",
"--disable-color-tracing",
src.to_str().unwrap(),
&target,
]);
scrub_env(&mut cmd);
let (_code, stdout, stderr) = run(&mut cmd);
assert!(
trace_marker_present(&stderr),
"cp tracing must appear on stderr; stdout={stdout}\nstderr={stderr}"
);
assert!(
!trace_marker_present(&stdout),
"cp tracing must NOT leak to stdout; stdout={stdout}"
);
helper.delete_bucket_with_cascade(&bucket).await;
let _ = std::fs::remove_dir_all(&local_dir);
}
#[tokio::test]
async fn sync_tracing_stderr_flag_flips_to_stderr() {
let helper = TestHelper::new().await;
let bucket = generate_bucket_name();
helper.create_bucket(&bucket, REGION).await;
let local_dir = create_temp_dir();
let target = format!("s3://{bucket}/");
let mut cmd = s7cmd_cmd();
cmd.args([
"sync",
"--target-profile",
"s7cmd-e2e-test",
"--target-region",
REGION,
"--tracing-stderr",
"-vvv",
"--disable-color-tracing",
local_dir.to_str().unwrap(),
&target,
]);
scrub_env(&mut cmd);
let (_code, stdout, stderr) = run(&mut cmd);
assert!(
trace_marker_present(&stderr),
"sync --tracing-stderr must put tracing on stderr; stdout={stdout}\nstderr={stderr}"
);
assert!(
!trace_marker_present(&stdout),
"sync --tracing-stderr must NOT leak tracing to stdout; stdout={stdout}"
);
helper.delete_bucket_with_cascade(&bucket).await;
let _ = std::fs::remove_dir_all(&local_dir);
}
#[tokio::test]
async fn ls_json_tracing_emits_json() {
let helper = TestHelper::new().await;
let bucket = generate_bucket_name();
helper.create_bucket(&bucket, REGION).await;
let target = format!("s3://{bucket}/");
let mut cmd = s7cmd_cmd();
cmd.args([
"ls",
"--target-profile",
"s7cmd-e2e-test",
"--target-region",
REGION,
"--json-tracing",
"-vvv",
"--disable-color-tracing",
&target,
]);
scrub_env(&mut cmd);
let (_code, _stdout, stderr) = run(&mut cmd);
assert!(
stderr.contains(r#""level":"#),
"expected JSON-tracing 'level' field on stderr; stderr={stderr}"
);
assert!(
stderr.contains(r#""timestamp":"#),
"expected JSON-tracing 'timestamp' field on stderr; stderr={stderr}"
);
helper.delete_bucket_with_cascade(&bucket).await;
}
#[tokio::test]
async fn sync_json_tracing_emits_json() {
let helper = TestHelper::new().await;
let bucket = generate_bucket_name();
helper.create_bucket(&bucket, REGION).await;
let local_dir = create_temp_dir();
let target = format!("s3://{bucket}/");
let mut cmd = s7cmd_cmd();
cmd.args([
"sync",
"--target-profile",
"s7cmd-e2e-test",
"--target-region",
REGION,
"--json-tracing",
"-vvv",
"--disable-color-tracing",
local_dir.to_str().unwrap(),
&target,
]);
scrub_env(&mut cmd);
let (_code, stdout, _stderr) = run(&mut cmd);
assert!(
stdout.contains(r#""level":"#),
"expected JSON-tracing 'level' field on sync stdout; stdout={stdout}"
);
assert!(
stdout.contains(r#""timestamp":"#),
"expected JSON-tracing 'timestamp' field on sync stdout; stdout={stdout}"
);
helper.delete_bucket_with_cascade(&bucket).await;
let _ = std::fs::remove_dir_all(&local_dir);
}