use bashkit::Bash;
async fn run(script: &str) -> bashkit::ExecResult {
let mut bash = Bash::new();
bash.exec(script).await.unwrap()
}
async fn run_with_limits(
script: &str,
max_stdout: usize,
max_stderr: usize,
) -> bashkit::ExecResult {
let limits = bashkit::ExecutionLimits::new()
.max_stdout_bytes(max_stdout)
.max_stderr_bytes(max_stderr);
let mut bash = Bash::builder().limits(limits).build();
bash.exec(script).await.unwrap()
}
#[tokio::test]
async fn no_truncation_by_default() {
let result = run("echo hello").await;
assert_eq!(result.stdout, "hello\n");
assert!(!result.stdout_truncated);
assert!(!result.stderr_truncated);
}
#[tokio::test]
async fn stdout_truncated_when_exceeds_limit() {
let result = run_with_limits("echo hello; echo world", 10, 1_048_576).await;
assert_eq!(result.stdout.len(), 10);
assert!(result.stdout.starts_with("hello\n"));
assert!(result.stdout_truncated);
assert!(!result.stderr_truncated);
}
#[tokio::test]
async fn stdout_not_truncated_when_within_limit() {
let result = run_with_limits("echo hi", 100, 1_048_576).await;
assert_eq!(result.stdout, "hi\n");
assert!(!result.stdout_truncated);
}
#[tokio::test]
async fn stdout_exact_limit_not_truncated() {
let result = run_with_limits("echo hi", 3, 1_048_576).await;
assert_eq!(result.stdout, "hi\n");
assert!(!result.stdout_truncated);
}
#[tokio::test]
async fn stdout_one_byte_over_limit_truncated() {
let result = run_with_limits("echo hi", 2, 1_048_576).await;
assert_eq!(result.stdout.len(), 2);
assert_eq!(result.stdout, "hi");
assert!(result.stdout_truncated);
}
#[tokio::test]
async fn stdout_truncation_preserves_utf8_boundaries() {
let result = run_with_limits("echo é", 1, 1_048_576).await;
assert_eq!(result.stdout, "");
assert!(result.stdout_truncated);
}
#[tokio::test]
async fn stderr_truncated_when_exceeds_limit() {
let result = run_with_limits("echo err1 >&2; echo err2 >&2", 1_048_576, 8).await;
assert!(result.stderr.len() <= 8);
assert!(result.stderr_truncated);
}
#[tokio::test]
async fn stderr_not_truncated_when_within_limit() {
let result = run_with_limits("echo oops >&2", 1_048_576, 100).await;
assert!(!result.stderr_truncated);
}
#[tokio::test]
async fn stderr_truncation_preserves_utf8_boundaries() {
let result = run_with_limits("echo é >&2", 1_048_576, 1).await;
assert_eq!(result.stderr, "");
assert!(result.stderr_truncated);
}
#[tokio::test]
async fn execution_continues_after_stdout_truncation() {
let result = run_with_limits(r#"echo aaa; echo bbb; x=done; echo "$x""#, 5, 1_048_576).await;
assert!(result.stdout_truncated);
assert_eq!(result.exit_code, 0);
}
#[tokio::test]
async fn minimal_stdout_limit_truncates_immediately() {
let result = run_with_limits("echo hello", 1, 1_048_576).await;
assert!(result.stdout.len() <= 1);
assert!(result.stdout_truncated);
}
#[tokio::test]
async fn both_stdout_and_stderr_truncated() {
let result = run_with_limits("echo out; echo err >&2", 3, 3).await;
assert!(result.stdout_truncated);
assert!(result.stderr_truncated);
assert!(result.stdout.len() <= 3);
assert!(result.stderr.len() <= 3);
}
#[tokio::test]
async fn default_limits_are_1mb() {
let limits = bashkit::ExecutionLimits::default();
assert_eq!(limits.max_stdout_bytes, 1_048_576);
assert_eq!(limits.max_stderr_bytes, 1_048_576);
}
#[tokio::test]
async fn builder_sets_limits() {
let limits = bashkit::ExecutionLimits::new()
.max_stdout_bytes(500)
.max_stderr_bytes(300);
assert_eq!(limits.max_stdout_bytes, 500);
assert_eq!(limits.max_stderr_bytes, 300);
}