use assert_cmd::Command;
use predicates::prelude::*;
use std::io::Write;
#[test]
fn batch_run_empty_stdin_succeeds() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("")
.assert()
.success()
.stderr(predicate::str::contains("0 succeeded, 0 failed"));
}
#[test]
fn batch_run_no_summary_suppresses_summary() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--no-summary", "-"])
.write_stdin("")
.assert()
.success()
.stderr(predicate::str::contains("batch-run:").not());
}
#[test]
fn batch_run_json_tracing_emits_json_summary() {
let assert = Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--json-tracing", "-"])
.write_stdin("")
.assert()
.success();
let stderr = String::from_utf8(assert.get_output().stderr.clone()).unwrap();
let summary_line = stderr
.lines()
.find(|l| l.contains("\"summary\":\"batch-run\""))
.unwrap_or_else(|| panic!("no JSON summary line in stderr: {stderr}"));
let v: serde_json::Value = serde_json::from_str(summary_line).unwrap();
assert_eq!(v["summary"], "batch-run");
assert_eq!(v["succeeded"], 0);
assert_eq!(v["failed"], 0);
assert_eq!(v["skipped"], 0);
assert!(v["elapsed_seconds"].is_number());
}
#[test]
fn batch_run_json_tracing_with_no_summary_emits_nothing() {
let assert = Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--json-tracing", "--no-summary", "-"])
.write_stdin("")
.assert()
.success();
let stderr = String::from_utf8(assert.get_output().stderr.clone()).unwrap();
assert!(
!stderr.contains("\"summary\":\"batch-run\""),
"JSON summary should be suppressed; stderr={stderr}"
);
assert!(
!stderr.contains("batch-run:"),
"human summary should be suppressed; stderr={stderr}"
);
}
#[test]
fn batch_run_rejects_nested_batch_run_line() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("batch-run -\n")
.assert()
.failure()
.stderr(predicate::str::contains("nested batch-run"));
}
#[test]
fn batch_run_rejects_per_line_tracing_flag() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("head-bucket --aws-sdk-tracing s3://b\n")
.assert()
.failure()
.stderr(predicate::str::contains("tracing flags are not allowed"));
}
#[test]
fn batch_run_rejects_stdio_cp_target() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("cp s3://bucket/key -\n")
.assert()
.failure()
.stderr(predicate::str::contains("stdin/stdout"));
}
#[test]
fn batch_run_parses_blank_and_comment_lines() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("\n# this is a comment\n \n# another\n")
.assert()
.success()
.stderr(predicate::str::contains("0 succeeded, 0 failed"));
}
#[test]
fn batch_run_parse_error_includes_line_number() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("# ok\ncp \"unterminated\n")
.assert()
.failure()
.stderr(predicate::str::contains("line 2"));
}
#[test]
fn batch_run_help_works() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--help"])
.assert()
.success()
.stdout(predicate::str::contains("--parallel"))
.stdout(predicate::str::contains("--streaming"))
.stdout(predicate::str::contains("--continue-on-error"))
.stdout(predicate::str::contains("--max-errors"))
.stdout(predicate::str::contains("--check-format"));
}
#[test]
fn top_level_help_lists_batch_run() {
Command::cargo_bin("s7cmd")
.unwrap()
.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains("batch-run"));
}
#[test]
fn batch_run_streaming_empty_stdin_succeeds() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "-"])
.write_stdin("")
.assert()
.success()
.stderr(predicate::str::contains("0 succeeded, 0 failed"));
}
#[test]
fn batch_run_streaming_rejects_per_line_tracing_flag() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "-"])
.write_stdin("head-bucket --aws-sdk-tracing s3://b\n")
.assert()
.failure()
.stderr(predicate::str::contains("tracing flags are not allowed"));
}
#[test]
fn batch_run_streaming_parses_blank_and_comment_lines() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "-"])
.write_stdin("\n# comment\n \n")
.assert()
.success()
.stderr(predicate::str::contains("0 succeeded, 0 failed"));
}
#[test]
fn batch_run_invalid_sync_config_counts_as_per_line_failure() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"sync /tmp/nonexistent-src /tmp/nonexistent-dst\n",
"create-bucket --dry-run s3://b3\n",
))
.assert()
.failure()
.stderr(predicate::str::contains("line 2"))
.stderr(predicate::str::contains(
"1 succeeded, 1 failed, 0 warnings, 1 skipped",
));
}
const MAX_LINE_LEN: usize = 16 * 1024;
#[test]
fn batch_run_accepts_line_at_16kib_cap() {
let mut input = String::with_capacity(MAX_LINE_LEN + 1);
input.push('#');
input.extend(std::iter::repeat_n('x', MAX_LINE_LEN - 1));
input.push('\n');
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin(input)
.assert()
.success()
.stderr(predicate::str::contains("0 succeeded, 0 failed"));
}
#[test]
fn batch_run_rejects_line_over_16kib_cap_read_all() {
let mut input = String::with_capacity(MAX_LINE_LEN + 3);
input.push('#');
input.extend(std::iter::repeat_n('x', MAX_LINE_LEN));
input.push('\n');
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin(input)
.assert()
.failure()
.stderr(predicate::str::contains("line 1"))
.stderr(predicate::str::contains("exceeds"));
}
#[test]
fn batch_run_rejects_line_over_16kib_cap_streaming() {
let mut input = String::with_capacity(MAX_LINE_LEN + 3);
input.push('#');
input.extend(std::iter::repeat_n('x', MAX_LINE_LEN));
input.push('\n');
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "-"])
.write_stdin(input)
.assert()
.failure()
.stderr(predicate::str::contains("line 1"))
.stderr(predicate::str::contains("exceeds"));
}
#[test]
fn batch_run_invalid_ls_config_does_not_kill_process() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--continue-on-error", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"ls --recursive\n",
"create-bucket --dry-run s3://b3\n",
))
.assert()
.failure()
.stderr(predicate::str::contains("2 succeeded, 1 failed"));
}
#[test]
fn batch_run_requires_script_positional() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run"])
.assert()
.failure()
.stderr(predicate::str::contains("required"));
}
#[test]
fn batch_run_missing_file_errors() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "/nonexistent/s7cmd-batch-run-script.txt"])
.assert()
.failure()
.stderr(predicate::str::contains(
"/nonexistent/s7cmd-batch-run-script.txt",
));
}
#[test]
fn batch_run_reads_from_file_in_read_all_mode() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("script.txt");
let mut f = std::fs::File::create(&path).unwrap();
writeln!(f, "# comment").unwrap();
writeln!(f, "create-bucket --dry-run s3://b1").unwrap();
writeln!(f, "create-bucket --dry-run s3://b2").unwrap();
drop(f);
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", path.to_str().unwrap()])
.assert()
.success()
.stderr(predicate::str::contains("2 succeeded, 0 failed"));
}
#[test]
fn batch_run_reads_from_file_in_streaming_mode() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("script.txt");
let mut f = std::fs::File::create(&path).unwrap();
writeln!(f, "create-bucket --dry-run s3://b1").unwrap();
writeln!(f, "create-bucket --dry-run s3://b2").unwrap();
drop(f);
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", path.to_str().unwrap()])
.assert()
.success()
.stderr(predicate::str::contains("2 succeeded, 0 failed"));
}
#[test]
fn batch_run_check_format_reports_ok_for_valid_script() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("script.txt");
let mut f = std::fs::File::create(&path).unwrap();
writeln!(f, "# this is a comment").unwrap();
writeln!(f, "head-bucket s3://b1").unwrap();
writeln!(f, "create-bucket --dry-run s3://b2").unwrap();
drop(f);
let path_str = path.to_str().unwrap();
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", path_str])
.assert()
.success()
.stderr(predicate::str::contains(format!("format OK ({path_str}).")))
.stderr(predicate::str::contains("[dry-run]").not())
.stderr(predicate::str::contains("ok, ").not());
}
#[test]
fn batch_run_check_format_reports_ok_for_stdin_uses_stdin_label() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", "-"])
.write_stdin("head-bucket s3://b1\n")
.assert()
.success()
.stderr(predicate::str::contains("format OK (stdin)."))
.stderr(predicate::str::contains("format OK (-)").not());
}
#[test]
fn batch_run_check_format_error_includes_source_path() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("hosts.txt");
let mut f = std::fs::File::create(&path).unwrap();
writeln!(f, "# the loopback address").unwrap();
writeln!(f, "127.0.0.1\tlocalhost").unwrap();
drop(f);
let path_str = path.to_str().unwrap();
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", path_str])
.assert()
.failure()
.stderr(predicate::str::contains(format!(
"{path_str}: line 2: parse error: unrecognized subcommand '127.0.0.1':"
)))
.stderr(predicate::str::contains("Usage:").not())
.stderr(predicate::str::contains("For more information").not())
.stderr(predicate::str::contains("parse error: error:").not());
}
#[test]
fn batch_run_check_format_error_uses_stdin_label_for_dash() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", "-"])
.write_stdin("127.0.0.1\tlocalhost\n")
.assert()
.failure()
.stderr(predicate::str::contains(
"stdin: line 1: parse error: unrecognized subcommand '127.0.0.1':",
));
}
#[test]
fn batch_run_check_format_stops_at_first_error() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("script.txt");
let mut f = std::fs::File::create(&path).unwrap();
writeln!(f, "head-bucket s3://b1").unwrap(); writeln!(f, "batch-run -").unwrap(); writeln!(f, "cp s3://b/k -").unwrap(); writeln!(f, "another-bad-line").unwrap(); drop(f);
let path_str = path.to_str().unwrap();
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", path_str])
.assert()
.failure()
.stderr(predicate::str::contains(format!("{path_str}: line 2:")))
.stderr(predicate::str::contains("nested batch-run"))
.stderr(predicate::str::contains("line 3:").not())
.stderr(predicate::str::contains("line 4:").not())
.stderr(predicate::str::contains("stdin/stdout").not())
.stderr(predicate::str::contains("format OK").not());
}
#[test]
fn batch_run_check_format_reads_from_stdin() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", "-"])
.write_stdin("head-bucket s3://b1\nbatch-run -\n")
.assert()
.failure()
.stderr(predicate::str::contains("stdin: line 2:"))
.stderr(predicate::str::contains("nested batch-run"))
.stderr(predicate::str::contains("format OK").not());
}
#[test]
fn batch_run_check_format_error_drains_unread_stdin() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("hosts.txt");
std::fs::write(&path, "127.0.0.1\tlocalhost\n").unwrap();
let payload: String =
std::iter::repeat_n("create-bucket --dry-run s3://x\n", 32 * 1024).collect();
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", path.to_str().unwrap()])
.write_stdin(payload)
.assert()
.failure()
.stderr(predicate::str::contains(
"parse error: unrecognized subcommand '127.0.0.1'",
));
}
#[test]
fn batch_run_check_format_missing_file_drains_unread_stdin() {
let payload: String =
std::iter::repeat_n("create-bucket --dry-run s3://x\n", 32 * 1024).collect();
Command::cargo_bin("s7cmd")
.unwrap()
.args([
"batch-run",
"--check-format",
"/nonexistent/s7cmd-drain-test.txt",
])
.write_stdin(payload)
.assert()
.failure()
.stderr(predicate::str::contains(
"/nonexistent/s7cmd-drain-test.txt",
));
}
#[test]
fn batch_run_check_format_missing_file_errors() {
Command::cargo_bin("s7cmd")
.unwrap()
.args([
"batch-run",
"--check-format",
"/nonexistent/s7cmd-check-format.txt",
])
.assert()
.failure()
.stderr(predicate::str::contains(
"/nonexistent/s7cmd-check-format.txt",
));
}
#[test]
fn batch_run_max_errors_two_stops_after_second_failure() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--max-errors", "2", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"ls --recursive\n",
"create-bucket --dry-run s3://b2\n",
"ls --recursive\n",
"create-bucket --dry-run s3://b3\n",
))
.assert()
.failure()
.stderr(predicate::str::contains(
"2 succeeded, 2 failed, 0 warnings, 1 skipped",
));
}
#[test]
fn batch_run_max_errors_conflicts_with_continue_on_error() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--continue-on-error", "--max-errors", "3", "-"])
.assert()
.failure()
.stderr(predicate::str::contains("cannot be used with"));
}
#[test]
fn batch_run_max_errors_zero_rejected() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--max-errors", "0", "-"])
.assert()
.failure()
.stderr(predicate::str::contains("invalid value"));
}
#[test]
fn batch_run_max_errors_covers_clap_parse_failures() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--max-errors", "3", "-"])
.write_stdin(concat!(
"cp --server-side-copy2 s3://b/a s3://b/backup/\n",
"cp --server-side-copy2 s3://b/b s3://b/backup/\n",
"cp --server-side-copy2 s3://b/c s3://b/backup/\n",
"cp --server-side-copy2 s3://b/d s3://b/backup/\n",
"cp --server-side-copy2 s3://b/e s3://b/backup/\n",
))
.assert()
.failure()
.stderr(predicate::str::contains(
"0 succeeded, 3 failed, 0 warnings, 2 skipped",
))
.stderr(predicate::str::contains("server-side-copy2"));
}
#[test]
fn batch_run_default_is_fail_fast() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"ls --recursive\n",
"create-bucket --dry-run s3://b2\n",
))
.assert()
.failure()
.stderr(predicate::str::contains(
"1 succeeded, 1 failed, 0 warnings, 1 skipped",
));
}
#[test]
fn batch_run_logs_per_line_start_and_end_at_info() {
Command::cargo_bin("s7cmd")
.unwrap()
.env_remove("RUST_LOG")
.args(["batch-run", "-v", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"create-bucket --dry-run s3://b2\n",
))
.assert()
.success()
.stderr(predicate::str::contains(
"line 1: start: create-bucket --dry-run s3://b1",
))
.stderr(predicate::str::contains(
"line 1: success: create-bucket --dry-run s3://b1",
))
.stderr(predicate::str::contains(
"line 2: start: create-bucket --dry-run s3://b2",
))
.stderr(predicate::str::contains(
"line 2: success: create-bucket --dry-run s3://b2",
));
}
#[test]
fn batch_run_logs_per_line_failure_outcome_with_exit_code() {
Command::cargo_bin("s7cmd")
.unwrap()
.env_remove("RUST_LOG")
.args(["batch-run", "-v", "--continue-on-error", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"ls --recursive\n",
))
.assert()
.failure()
.stderr(predicate::str::contains("line 1: success: create-bucket"))
.stderr(predicate::str::contains("line 2: start: ls --recursive"))
.stderr(predicate::str::contains(
"line 2: failure (exit 2): ls --recursive",
));
}
#[test]
fn batch_run_per_line_logs_silent_at_default_verbosity() {
Command::cargo_bin("s7cmd")
.unwrap()
.env_remove("RUST_LOG")
.args(["batch-run", "-"])
.write_stdin("create-bucket --dry-run s3://b1\n")
.assert()
.success()
.stderr(predicate::str::contains("line 1: start").not())
.stderr(predicate::str::contains("line 1: success").not())
.stderr(predicate::str::contains("1 succeeded, 0 failed"));
}
#[test]
fn batch_run_failure_log_visible_at_default_verbosity() {
Command::cargo_bin("s7cmd")
.unwrap()
.env_remove("RUST_LOG")
.args(["batch-run", "--continue-on-error", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"ls --recursive\n",
))
.assert()
.failure()
.stderr(predicate::str::contains("line 2: start").not())
.stderr(predicate::str::contains("line 1: success").not())
.stderr(predicate::str::contains(
"line 2: failure (exit 2): ls --recursive",
));
}
#[test]
fn batch_run_continue_on_warning_listed_in_help() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--help"])
.assert()
.success()
.stdout(predicate::str::contains("--continue-on-warning"));
}
#[test]
fn batch_run_continue_on_warning_conflicts_with_continue_on_error() {
Command::cargo_bin("s7cmd")
.unwrap()
.args([
"batch-run",
"--continue-on-error",
"--continue-on-warning",
"-",
])
.assert()
.failure()
.stderr(predicate::str::contains("cannot be used with"));
}
#[test]
fn batch_run_continue_on_warning_combines_with_max_errors() {
Command::cargo_bin("s7cmd")
.unwrap()
.args([
"batch-run",
"--continue-on-warning",
"--max-errors",
"3",
"-",
])
.write_stdin("")
.assert()
.success()
.stderr(predicate::str::contains("0 succeeded, 0 failed"));
}
#[test]
fn batch_run_parallel_two_workers_succeeds() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--parallel", "2", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"create-bucket --dry-run s3://b2\n",
"create-bucket --dry-run s3://b3\n",
"create-bucket --dry-run s3://b4\n",
))
.assert()
.success()
.stderr(predicate::str::contains("4 succeeded, 0 failed"));
}
#[test]
fn batch_run_streaming_parallel_two_workers_succeeds() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "--parallel", "2", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"create-bucket --dry-run s3://b2\n",
"create-bucket --dry-run s3://b3\n",
))
.assert()
.success()
.stderr(predicate::str::contains("3 succeeded, 0 failed"));
}
#[test]
fn batch_run_rejects_stdio_mv_target() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("mv s3://bucket/key -\n")
.assert()
.failure()
.stderr(predicate::str::contains("stdin/stdout"));
}
#[test]
fn batch_run_rejects_stdio_mv_source() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("mv - s3://bucket/key\n")
.assert()
.failure()
.stderr(predicate::str::contains("stdin/stdout"));
}
#[test]
fn batch_run_rejects_line_over_16kib_cap_file_read_all() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("script.txt");
let mut content = String::with_capacity(MAX_LINE_LEN + 3);
content.push('#');
content.extend(std::iter::repeat_n('x', MAX_LINE_LEN));
content.push('\n');
std::fs::write(&path, content).unwrap();
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", path.to_str().unwrap()])
.assert()
.failure()
.stderr(predicate::str::contains("line 1"))
.stderr(predicate::str::contains("exceeds"));
}
#[test]
fn batch_run_streaming_missing_file_errors() {
Command::cargo_bin("s7cmd")
.unwrap()
.args([
"batch-run",
"--streaming",
"/nonexistent/s7cmd-streaming-missing.txt",
])
.assert()
.failure()
.stderr(predicate::str::contains(
"/nonexistent/s7cmd-streaming-missing.txt",
));
}
#[test]
fn batch_run_streaming_parse_error_includes_line_number() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "-"])
.write_stdin("# blank ok\ncp \"unterminated\n")
.assert()
.failure()
.stderr(predicate::str::contains("line 2"))
.stderr(predicate::str::contains("parse error"));
}
#[test]
fn batch_run_streaming_clap_parse_error_includes_line_number() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "-"])
.write_stdin("no-such-command\n")
.assert()
.failure()
.stderr(predicate::str::contains("line 1"))
.stderr(predicate::str::contains("parse error"));
}
#[test]
fn batch_run_streaming_empty_command_errors() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "-"])
.write_stdin("--auto-complete-shell bash\n")
.assert()
.failure()
.stderr(predicate::str::contains("line 1"))
.stderr(predicate::str::contains("empty command"));
}
#[test]
fn batch_run_check_format_rejects_empty_command() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", "-"])
.write_stdin("--auto-complete-shell bash\n")
.assert()
.failure()
.stderr(predicate::str::contains("empty command"));
}
#[test]
fn batch_run_check_format_rejects_tokenize_error() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", "-"])
.write_stdin("cp \"unterminated\n")
.assert()
.failure()
.stderr(predicate::str::contains("parse error"))
.stderr(predicate::str::contains("line 1"));
}
#[test]
fn batch_run_read_all_empty_command_errors() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("--auto-complete-shell bash\n")
.assert()
.failure()
.stderr(predicate::str::contains("empty command"))
.stderr(predicate::str::contains("line 1"));
}
#[test]
fn batch_run_per_line_auto_complete_shell_does_not_panic() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "-"])
.write_stdin("cp --auto-complete-shell fish\n")
.assert()
.failure()
.stderr(predicate::str::contains("line 1"))
.stderr(predicate::str::contains("parse error"))
.stderr(predicate::str::contains("panicked").not());
}
#[test]
fn batch_run_streaming_per_line_auto_complete_shell_does_not_panic() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "-"])
.write_stdin("cp --auto-complete-shell fish\n")
.assert()
.failure()
.stderr(predicate::str::contains("line 1"))
.stderr(predicate::str::contains("parse error"))
.stderr(predicate::str::contains("panicked").not());
}
#[test]
fn batch_run_check_format_per_line_auto_complete_shell_does_not_panic() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--check-format", "-"])
.write_stdin("cp --auto-complete-shell fish\n")
.assert()
.failure()
.stderr(predicate::str::contains("line 1"))
.stderr(predicate::str::contains("parse error"))
.stderr(predicate::str::contains("panicked").not());
}
#[test]
fn batch_run_streaming_continue_on_error_runs_all_lines() {
Command::cargo_bin("s7cmd")
.unwrap()
.args(["batch-run", "--streaming", "--continue-on-error", "-"])
.write_stdin(concat!(
"create-bucket --dry-run s3://b1\n",
"ls --recursive\n",
"create-bucket --dry-run s3://b2\n",
))
.assert()
.failure()
.stderr(predicate::str::contains("2 succeeded, 1 failed"));
}