#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
#![allow(non_snake_case)]
use assert_cmd::Command;
use std::io::Write;
use tempfile::NamedTempFile;
#[allow(deprecated)]
fn bashrs_cmd() -> Command {
assert_cmd::cargo_bin_cmd!("bashrs")
}
fn create_temp_rust_file(content: &str) -> NamedTempFile {
let mut file = NamedTempFile::new().expect("Failed to create temp file");
file.write_all(content.as_bytes())
.expect("Failed to write to temp file");
file
}
#[test]
fn test_RUNTIME_001_trivial_script_no_stdlib() {
let rust_code = r#"
fn main() {
let x = 42;
}
"#;
let result = bashrs::transpile(rust_code, &bashrs::Config::default()).unwrap();
assert!(
!result.contains("rash_println()"),
"Trivial script should not emit rash_println"
);
assert!(
!result.contains("rash_require()"),
"Trivial script should not emit rash_require"
);
assert!(
!result.contains("rash_fs_exists()"),
"Trivial script should not emit rash_fs_exists"
);
assert!(
!result.contains("rash_string_trim()"),
"Trivial script should not emit rash_string_trim"
);
assert!(
!result.contains("# Rash runtime functions"),
"Trivial script should not emit runtime header"
);
}
#[test]
fn test_RUNTIME_002_echo_emits_no_stdlib() {
let rust_code = r#"
fn main() {
echo("hello");
}
fn echo(msg: &str) {}
"#;
let result = bashrs::transpile(rust_code, &bashrs::Config::default()).unwrap();
assert!(
!result.contains("rash_string_trim()"),
"Echo-only script should not emit string stdlib"
);
assert!(
!result.contains("rash_fs_exists()"),
"Echo-only script should not emit fs stdlib"
);
}
#[test]
fn test_RUNTIME_003_selective_stdlib_emission() {
let rust_code = r#"
fn main() {
let exists = fs_exists("/tmp/test");
}
fn fs_exists(path: &str) -> bool { true }
"#;
let result = bashrs::transpile(rust_code, &bashrs::Config::default()).unwrap();
assert!(
result.contains("rash_fs_exists()"),
"Should emit rash_fs_exists when fs_exists is called"
);
assert!(
!result.contains("rash_string_trim()"),
"Should not emit rash_string_trim when not used"
);
assert!(
!result.contains("rash_array_len()"),
"Should not emit rash_array_len when not used"
);
}
#[test]
fn test_TRANSPILE_001_basic_build_produces_posix_shell() {
let rust_code = r#"
fn main() {
let greeting = "Hello, World!";
}
"#;
let result = bashrs::transpile(rust_code, &bashrs::Config::default()).unwrap();
assert!(
result.starts_with("#!/bin/sh"),
"Transpiled output must start with #!/bin/sh"
);
assert!(
result.contains("set -euf"),
"Transpiled output must enable strict error handling"
);
assert!(
result.contains("main()"),
"Transpiled output must have main() wrapper"
);
assert!(
result.contains("trap"),
"Transpiled output must have cleanup trap"
);
}
#[test]
fn test_TRANSPILE_002_determinism_identical_output() {
let rust_code = r#"
fn main() {
let x = 42;
let y = "hello";
let z = true;
}
"#;
let config = bashrs::Config::default();
let result1 = bashrs::transpile(rust_code, &config).unwrap();
let result2 = bashrs::transpile(rust_code, &config).unwrap();
assert_eq!(
result1, result2,
"Same input must produce identical output (determinism)"
);
}
#[test]
fn test_TRANSPILE_003_cli_build_produces_output() {
let rust_code = r#"
fn main() {
let x = 42;
}
"#;
let input_file = create_temp_rust_file(rust_code);
let output_file = NamedTempFile::new().unwrap();
bashrs_cmd()
.arg("build")
.arg(input_file.path())
.arg("-o")
.arg(output_file.path())
.assert()
.success();
let output = std::fs::read_to_string(output_file.path()).unwrap();
assert!(output.starts_with("#!/bin/sh"));
}
#[test]
fn test_TRANSPILE_004_transpile_with_lint_api() {
let rust_code = r#"
fn main() {
let x = 42;
}
"#;
let (shell_code, lint_result) =
bashrs::transpile_with_lint(rust_code, &bashrs::Config::default()).unwrap();
assert!(shell_code.contains("#!/bin/sh"));
let _ = lint_result.diagnostics.len();
}
#[test]
fn test_TRANSPILE_005_no_nondeterminism_in_output() {
let rust_code = r#"
fn main() {
let x = 42;
let name = "test";
}
"#;
let result = bashrs::transpile(rust_code, &bashrs::Config::default()).unwrap();
assert!(
!result.contains("$RANDOM"),
"Transpiled output must not contain $RANDOM"
);
let result2 = bashrs::transpile(rust_code, &bashrs::Config::default()).unwrap();
assert_eq!(result, result2, "Transpilation must be deterministic");
}