#[test]
fn test_positional_parameters_basic() {
let source = r#"
fn main() {
let args: Vec<String> = std::env::args().collect();
let first = args.get(1).unwrap_or("default");
echo(first);
}
fn echo(msg: &str) {}
"#;
let config = Config::default();
let result = transpile(source, &config);
assert!(result.is_ok(), "Should transpile positional parameters");
let shell = result.unwrap();
assert!(
shell.contains("${1:-default}") || shell.contains("first=\"${1:-default}\""),
"Should use positional parameter $1 with default"
);
assert!(shell.contains("\"$first\""), "Should quote variable usage");
assert!(
shell.contains("main \"$@\""),
"Should pass all arguments to main"
);
}
#[test]
fn test_positional_parameters_multiple() {
let source = r#"
fn main() {
let args: Vec<String> = std::env::args().collect();
let first = args.get(1).unwrap_or("a");
let second = args.get(2).unwrap_or("b");
let third = args.get(3).unwrap_or("c");
echo(first);
echo(second);
echo(third);
}
fn echo(msg: &str) {}
"#;
let config = Config::default();
let shell = transpile(source, &config).unwrap();
assert!(shell.contains("${1:-a}") || shell.contains("first=\"${1:-a}\""));
assert!(shell.contains("${2:-b}") || shell.contains("second=\"${2:-b}\""));
assert!(shell.contains("${3:-c}") || shell.contains("third=\"${3:-c}\""));
}
#[test]
fn test_positional_parameters_execution() {
let source = r#"
fn main() {
let args: Vec<String> = std::env::args().collect();
let name = args.get(1).unwrap_or("World");
echo(name);
}
fn echo(msg: &str) {}
"#;
let config = Config::default();
let shell = transpile(source, &config).unwrap();
use tempfile::TempDir;
let temp_dir = TempDir::new().unwrap();
let script_path = temp_dir.path().join("test_positional.sh");
fs::write(&script_path, &shell).unwrap();
let output = Command::new("sh")
.arg(&script_path)
.arg("Alice")
.output()
.expect("Failed to execute shell script");
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("Alice"), "Should use provided argument");
let output = Command::new("sh")
.arg(&script_path)
.output()
.expect("Failed to execute shell script");
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("World"), "Should use default value");
}
#[test]
fn test_positional_parameters_args_assignment() {
let source = r#"
fn main() {
let args: Vec<String> = std::env::args().collect();
// Just use the args variable in some way
println!("Got args");
}
"#;
let config = Config::default();
let result = transpile(source, &config);
assert!(result.is_ok(), "Should transpile positional parameters");
let shell = result.unwrap();
assert!(
shell.contains("args=\"$@\""),
"Should generate args=\"$@\" for std::env::args().collect(), got:\n{}",
shell
);
}
#[test]
fn test_param_spec_001_arg_count_basic() {
let source = r#"
fn main() {
let count = arg_count();
echo("Done");
}
fn arg_count() -> i32 { 0 }
fn echo(msg: &str) {}
"#;
let config = Config::default();
let result = transpile(source, &config);
assert!(
result.is_ok(),
"Should transpile arg_count() function: {:?}",
result.err()
);
let shell = result.unwrap();
assert!(
shell.contains("count=\"$#\""),
"Should convert arg_count() to $#, got:\n{}",
shell
);
}
#[test]
fn test_param_spec_001_arg_count_variable() {
let source = r#"
fn main() {
let count = arg_count();
let num = count;
echo("Done");
}
fn arg_count() -> i32 { 0 }
fn echo(msg: &str) {}
"#;
let config = Config::default();
let result = transpile(source, &config);
assert!(
result.is_ok(),
"Should handle arg_count in variable assignment"
);
let shell = result.unwrap();
assert!(
shell.contains("$#"),
"Should include $# in shell script, got:\n{}",
shell
);
}
#[test]
fn test_param_spec_001_arg_count_conditional() {
let source = r#"
fn main() {
let count = arg_count();
if count == 0 {
echo("No arguments");
} else {
echo("Has arguments");
}
}
fn arg_count() -> i32 { 0 }
fn echo(msg: &str) {}
"#;
let config = Config::default();
let result = transpile(source, &config);
assert!(result.is_ok(), "Should handle arg_count in conditionals");
let shell = result.unwrap();
assert!(
shell.contains("$#"),
"Should use $# in conditional, got:\n{}",
shell
);
}
#[test]
fn test_param_spec_001_arg_count_execution() {
let source = r#"
fn main() {
let count = arg_count();
wc("-l");
}
fn arg_count() -> i32 { 0 }
fn wc(arg: &str) {}
"#;
let config = Config::default();
let shell_script = transpile(source, &config).unwrap();
let temp_dir = TempDir::new().unwrap();
let script_path = temp_dir.path().join("test_arg_count.sh");
fs::write(&script_path, shell_script).unwrap();
let output = Command::new("sh")
.arg(&script_path)
.output()
.expect("Failed to execute shell script");
assert!(
output.status.success(),
"Script should execute successfully"
);
}
#[test]
fn test_param_spec_005_script_name_basic() {
let source = r#"
fn main() {
let script = std::env::args().nth(0).unwrap_or("unknown");
echo(script);
}
fn echo(msg: &str) {}
"#;
let config = Config::default();
let result = transpile(source, &config);
assert!(
result.is_ok(),
"Should transpile script name access: {:?}",
result.err()
);
let shell = result.unwrap();
assert!(
shell.contains("${0:-unknown}") || shell.contains("script=\"${0:-unknown}\""),
"Should convert std::env::args().nth(0).unwrap_or() to ${{0:-unknown}}, got:\n{}",
shell
);
}
#[test]
fn test_param_spec_005_script_name_with_default() {
let source = r#"
fn main() {
let name = std::env::args().nth(0).unwrap_or("my-script");
echo(name);
}
fn echo(msg: &str) {}
"#;
let config = Config::default();
let result = transpile(source, &config);
assert!(
result.is_ok(),
"Should transpile script name with default: {:?}",
result.err()
);
let shell = result.unwrap();
assert!(
shell.contains("${0:-my-script}") || shell.contains("name=\"${0:-my-script}\""),
"Should convert std::env::args().nth(0).unwrap_or() to ${{0:-default}}, got:\n{}",
shell
);
}
#[test]
fn test_param_spec_005_script_name_unwrap() {
let source = r#"
fn main() {
let script = std::env::args().nth(0).unwrap();
echo(script);
}
fn echo(msg: &str) {}
"#;
let config = Config::default();
let result = transpile(source, &config);
assert!(
result.is_ok(),
"Should transpile script name with unwrap: {:?}",
result.err()
);
let shell = result.unwrap();
assert!(
shell.contains("script=\"$0\"") || shell.contains("$0"),
"Should convert std::env::args().nth(0).unwrap() to $0, got:\n{}",
shell
);
}
#[test]
fn test_input_redirection_baseline() {
let source = r#"
fn main() {
cat("input.txt");
}
fn cat(file: &str) {}
"#;
let config = Config::default();
let result = transpile(source, &config);
if let Err(e) = &result {
eprintln!("Transpilation error: {:?}", e);
}
assert!(
result.is_ok(),
"Should transpile file command: {:?}",
result.err()
);
let shell = result.unwrap();
eprintln!("Generated shell script:\n{}", shell);
assert!(
shell.contains("cat") && shell.contains("input.txt"),
"Should transpile cat command with filename\nActual output:\n{}",
shell
);
}
#[test]
#[ignore] fn test_input_redirection_file_open() {
let source = r#"
fn main() {
let file = std::fs::File::open("input.txt");
let content = read_file(file);
echo(&content);
}
fn read_file(f: std::fs::File) -> String { String::new() }
fn echo(msg: &str) {}
"#;
let config = Config::default();
let result = transpile(source, &config);
if let Err(e) = &result {
eprintln!("Transpilation error: {:?}", e);
}
assert!(
result.is_ok(),
"Should transpile File::open: {:?}",
result.err()
);
let shell = result.unwrap();
eprintln!("Generated shell script:\n{}", shell);
assert!(
shell.contains("< \"input.txt\"") || shell.contains("< input.txt"),
"Should use input redirection < for File::open\nActual output:\n{}",
shell
);
}
#[test]
#[ignore]
fn test_input_redirection_with_quoting() {
let source = r#"
fn main() {
let data = read_file("data file.txt");
echo(&data);
}
fn read_file(filename: &str) -> String { String::new() }
fn echo(msg: &str) {}
"#;
let config = Config::default();
let shell = transpile(source, &config).unwrap();
assert!(
shell.contains("< \"data file.txt\""),
"Should quote filenames with spaces in redirection"
);
}