#![allow(deprecated)]
#![allow(clippy::ignore_without_reason)]
use assert_cmd::Command;
use predicates::prelude::*;
use std::path::PathBuf;
fn ruchy_cmd() -> Command {
Command::cargo_bin("ruchy").expect("Failed to find ruchy binary")
}
fn example_path(relative_path: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("examples/lang_comp/04-functions")
.join(relative_path)
}
fn validate_with_15_tools(example: &PathBuf) {
ruchy_cmd().arg("check").arg(example).assert().success();
ruchy_cmd().arg("transpile").arg(example).assert().success();
ruchy_cmd().arg("lint").arg(example).assert().success();
let compile_output = std::env::temp_dir().join(format!(
"compile_test_{}_{}",
example.file_stem().unwrap().to_string_lossy(),
std::process::id()
));
ruchy_cmd()
.arg("compile")
.arg(example)
.arg("-o")
.arg(&compile_output)
.assert()
.success();
std::fs::remove_file(&compile_output).ok();
ruchy_cmd().arg("run").arg(example).assert().success();
ruchy_cmd().arg("coverage").arg(example).assert().success();
ruchy_cmd()
.arg("runtime")
.arg(example)
.arg("--bigo")
.assert()
.success();
ruchy_cmd().arg("ast").arg(example).assert().success();
ruchy_cmd().arg("wasm").arg(example).assert().success();
ruchy_cmd()
.arg("provability")
.arg(example)
.assert()
.success();
ruchy_cmd()
.arg("property-tests")
.arg(example)
.arg("--cases")
.arg("100")
.assert()
.success();
ruchy_cmd()
.arg("mutations")
.arg(example)
.arg("--min-coverage")
.arg("0")
.arg("--timeout")
.arg("60")
.assert()
.success();
ruchy_cmd()
.arg("fuzz")
.arg(example)
.arg("--iterations")
.arg("10")
.assert()
.success();
}
#[test]
fn test_langcomp_004_01_function_declaration_no_params() {
let temp_file = std::env::temp_dir().join("langcomp_004_01_decl_no_params.ruchy");
std::fs::write(
&temp_file,
r#"
fn greet() {
println("Hello")
}
greet()
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Hello"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_004_01_function_declaration_with_return() {
let temp_file = std::env::temp_dir().join("langcomp_004_01_decl_return.ruchy");
std::fs::write(
&temp_file,
r#"
fn get_five() {
return 5
}
println(f"Result: {get_five()}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Result: 5"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_004_01_function_declaration_example_file() {
let example = example_path("01_declaration.ruchy");
validate_with_15_tools(&example);
}
#[test]
fn test_langcomp_004_02_function_single_parameter() {
let temp_file = std::env::temp_dir().join("langcomp_004_02_single_param.ruchy");
std::fs::write(
&temp_file,
r#"
fn double(x) {
x * 2
}
println(f"Result: {double(5)}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Result: 10"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_004_02_function_multiple_parameters() {
let temp_file = std::env::temp_dir().join("langcomp_004_02_multi_params.ruchy");
std::fs::write(
&temp_file,
r#"
fn add(a, b) {
a + b
}
println(f"Result: {add(3, 7)}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Result: 10"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_004_02_function_parameters_example_file() {
let example = example_path("02_parameters.ruchy");
validate_with_15_tools(&example);
}
#[test]
fn test_langcomp_004_03_function_implicit_return() {
let temp_file = std::env::temp_dir().join("langcomp_004_03_implicit_return.ruchy");
std::fs::write(
&temp_file,
r#"
fn square(x) {
x * x
}
println(f"Result: {square(4)}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Result: 16"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_004_03_function_explicit_return() {
let temp_file = std::env::temp_dir().join("langcomp_004_03_explicit_return.ruchy");
std::fs::write(
&temp_file,
r#"
fn max(a, b) {
if a > b {
return a
}
return b
}
println(f"Result: {max(10, 7)}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Result: 10"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_004_03_function_return_values_example_file() {
let example = example_path("03_return_values.ruchy");
validate_with_15_tools(&example);
}
#[test]
fn test_langcomp_004_04_closure_fat_arrow_syntax() {
let temp_file = std::env::temp_dir().join("langcomp_004_04_closure_fat_arrow.ruchy");
std::fs::write(
&temp_file,
r#"
let double = |x| x * 2
println(f"Result: {double(5)}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Result: 10"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_004_04_closure_example_file() {
let example = example_path("04_closures.ruchy");
validate_with_15_tools(&example);
}
#[cfg(test)]
mod property_tests {
use super::*;
#[test]
#[ignore = "Test disabled - run with --ignored"]
fn test_langcomp_004_property_function_calls_are_deterministic() {
for i in 1..20 {
let code = format!(
r#"
fn double(x) {{
x * 2
}}
println(f"Result: {{double({i})}}")
"#
);
let temp_file =
std::env::temp_dir().join(format!("langcomp_004_prop_deterministic_{i}.ruchy"));
std::fs::write(&temp_file, &code).unwrap();
let result1 = ruchy_cmd().arg("run").arg(&temp_file).output().unwrap();
let result2 = ruchy_cmd().arg("run").arg(&temp_file).output().unwrap();
assert_eq!(result1.stdout, result2.stdout);
std::fs::remove_file(&temp_file).ok();
}
}
#[test]
#[ignore = "Test disabled - run with --ignored"]
fn test_langcomp_004_property_nested_calls_work() {
for i in 1..10 {
let code = format!(
r#"
fn double(x) {{
x * 2
}}
fn square(x) {{
x * x
}}
println(f"Result: {{square(double({i}))}}")
"#
);
let temp_file =
std::env::temp_dir().join(format!("langcomp_004_prop_nested_{i}.ruchy"));
std::fs::write(&temp_file, &code).unwrap();
ruchy_cmd().arg("run").arg(&temp_file).assert().success();
std::fs::remove_file(&temp_file).ok();
}
}
#[test]
#[ignore = "Test disabled - run with --ignored"]
fn test_langcomp_004_property_parameter_count_matches() {
let code = r"
fn add(a, b) {
a + b
}
add(5)
";
let temp_file = std::env::temp_dir().join("langcomp_004_prop_param_count.ruchy");
std::fs::write(&temp_file, code).unwrap();
let _ = ruchy_cmd().arg("run").arg(&temp_file).output();
std::fs::remove_file(&temp_file).ok();
}
}