#![allow(deprecated)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
#![allow(non_snake_case)]
use assert_cmd::Command;
use predicates::prelude::*;
use std::fs;
use std::io::Write;
use tempfile::{NamedTempFile, TempDir};
#[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
}
fn create_temp_shell_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
}
fn create_temp_makefile(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_CLI_001_help_flag() {
bashrs_cmd()
.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains("bashrs"))
.stdout(predicate::str::contains("Rust-to-Shell transpiler"));
}
#[test]
fn test_CLI_001_version_flag() {
bashrs_cmd()
.arg("--version")
.assert()
.success()
.stdout(predicate::str::contains("bashrs"));
}
#[test]
fn test_CLI_001_help_subcommand() {
bashrs_cmd()
.arg("help")
.assert()
.success()
.stdout(predicate::str::contains("bashrs"))
.stdout(predicate::str::contains("Commands:"));
}
#[test]
fn test_CLI_002_build_basic() {
let rust_code = r#"
fn main() {
let message = "Hello, World!";
println!(message);
}
"#;
let input_file = create_temp_rust_file(rust_code);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("output.sh");
bashrs_cmd()
.arg("build")
.arg(input_file.path())
.arg("--output")
.arg(&output_file)
.assert()
.success();
assert!(output_file.exists(), "Output file should exist");
let output_content = fs::read_to_string(&output_file).expect("Failed to read output");
assert!(
output_content.contains("#!/bin/sh") || output_content.contains("#!/bin/dash"),
"Output should have POSIX shebang"
);
}
#[test]
fn test_CLI_002_build_invalid_rust() {
let invalid_rust = r#"
fn main() {
let x = 10 +; // Syntax error
}
"#;
let input_file = create_temp_rust_file(invalid_rust);
bashrs_cmd()
.arg("build")
.arg(input_file.path())
.assert()
.failure()
.stderr(predicate::str::contains("error").or(predicate::str::contains("Error")));
}
#[test]
fn test_CLI_002_build_nonexistent_file() {
bashrs_cmd()
.arg("build")
.arg("nonexistent_file.rs")
.assert()
.failure()
.stderr(predicate::str::contains("No such file"));
}
#[test]
fn test_CLI_002_build_with_emit_proof() {
let rust_code = r#"
fn main() {
let x = 42;
}
"#;
let input_file = create_temp_rust_file(rust_code);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("output.sh");
bashrs_cmd()
.arg("build")
.arg(input_file.path())
.arg("--output")
.arg(&output_file)
.arg("--emit-proof")
.assert()
.success();
}
#[test]
fn test_CLI_003_check_valid_rust() {
let rust_code = r#"
fn main() {
let x = 42;
println!(x);
}
"#;
let input_file = create_temp_rust_file(rust_code);
bashrs_cmd()
.arg("check")
.arg(input_file.path())
.assert()
.success();
}
#[test]
fn test_CLI_003_check_invalid_rust() {
let invalid_rust = r#"
fn main() {
unsafe { let ptr = std::ptr::null::<i32>(); }
}
"#;
let input_file = create_temp_rust_file(invalid_rust);
bashrs_cmd()
.arg("check")
.arg(input_file.path())
.assert()
.failure();
}
#[test]
fn test_CLI_003_check_nonexistent_file() {
bashrs_cmd()
.arg("check")
.arg("nonexistent.rs")
.assert()
.failure()
.stderr(predicate::str::contains("No such file"));
}
#[test]
fn test_CLI_004_init_new_project() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
bashrs_cmd()
.arg("init")
.arg(temp_dir.path())
.arg("--name")
.arg("test_project")
.assert()
.success();
}
#[test]
fn test_CLI_004_init_current_directory() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
bashrs_cmd()
.current_dir(temp_dir.path())
.arg("init")
.assert()
.success();
}
#[test]
fn test_CLI_005_verify_matching_files() {
let rust_code = r#"
fn main() {
println!("Hello");
}
"#;
let shell_script = r#"#!/bin/sh
printf '%s\n' "Hello"
"#;
let rust_file = create_temp_rust_file(rust_code);
let shell_file = create_temp_shell_file(shell_script);
bashrs_cmd()
.arg("verify")
.arg(rust_file.path())
.arg(shell_file.path())
.assert()
.success();
}
#[test]
fn test_CLI_005_verify_nonexistent_rust() {
let shell_script = "#!/bin/sh\necho hello\n";
let shell_file = create_temp_shell_file(shell_script);
bashrs_cmd()
.arg("verify")
.arg("nonexistent.rs")
.arg(shell_file.path())
.assert()
.failure();
}
#[test]
fn test_CLI_006_inspect_ast_json() {
let ast_json = r#"{"type": "Program", "body": []}"#;
bashrs_cmd()
.arg("inspect")
.arg(ast_json)
.arg("--format")
.arg("json")
.assert()
.success();
}
#[test]
fn test_CLI_006_inspect_markdown_output() {
let ast_json = r#"{"type": "Program", "body": []}"#;
bashrs_cmd()
.arg("inspect")
.arg(ast_json)
.arg("--format")
.arg("markdown")
.assert()
.success();
}
#[test]
fn test_CLI_006_inspect_with_detailed_traces() {
let ast_json = r#"{"type": "Program", "body": []}"#;
bashrs_cmd()
.arg("inspect")
.arg(ast_json)
.arg("--detailed")
.assert()
.success();
}
#[test]
fn test_CLI_007_compile_to_binary() {
let rust_code = r#"
fn main() {
println!("Hello");
}
"#;
let input_file = create_temp_rust_file(rust_code);
let output_dir = TempDir::new().expect("Failed to create temp dir");
let output_file = output_dir.path().join("binary");
bashrs_cmd()
.arg("compile")
.arg(input_file.path())
.arg("--output")
.arg(&output_file)
.assert()
.success();
}
#[test]
include!("cli_integration_tests_CLI_2.rs");