#![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/05-string-interpolation")
.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_005_01_basic_variable_interpolation() {
let temp_file = std::env::temp_dir().join("langcomp_005_01_basic_var.ruchy");
std::fs::write(
&temp_file,
r#"
let name = "World"
println(f"Hello, {name}!")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Hello, World!"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_01_basic_integer_interpolation() {
let temp_file = std::env::temp_dir().join("langcomp_005_01_basic_int.ruchy");
std::fs::write(
&temp_file,
r#"
let x = 42
println(f"The answer is {x}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("The answer is 42"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_01_multiple_interpolations() {
let temp_file = std::env::temp_dir().join("langcomp_005_01_multiple.ruchy");
std::fs::write(
&temp_file,
r#"
let name = "Alice"
let age = 30
println(f"Hello, {name}! You are {age} years old.")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains(
"Hello, Alice! You are 30 years old.",
));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_01_basic_interpolation_example_file() {
let example = example_path("01_basic_interpolation.ruchy");
validate_with_15_tools(&example);
ruchy_cmd()
.arg("run")
.arg(&example)
.assert()
.success()
.stdout(predicate::str::contains("Name: Alice"))
.stdout(predicate::str::contains("Age: 30"))
.stdout(predicate::str::contains(
"Hello, Alice! You are 30 years old.",
));
}
#[test]
fn test_langcomp_005_02_arithmetic_expression_interpolation() {
let temp_file = std::env::temp_dir().join("langcomp_005_02_arithmetic.ruchy");
std::fs::write(
&temp_file,
r#"
let x = 10
let y = 20
println(f"x + y = {x + y}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("x + y = 30"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_02_comparison_expression_interpolation() {
let temp_file = std::env::temp_dir().join("langcomp_005_02_comparison.ruchy");
std::fs::write(
&temp_file,
r#"
let x = 10
let y = 20
println(f"x > y is {x > y}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("x > y is false"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_02_complex_expression_interpolation() {
let temp_file = std::env::temp_dir().join("langcomp_005_02_complex.ruchy");
std::fs::write(
&temp_file,
r#"
let x = 10
let y = 20
println(f"Result: {x + y * 2}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Result: 50"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_02_expression_interpolation_example_file() {
ruchy_cmd()
.arg("run")
.arg(example_path("02_expressions.ruchy"))
.assert()
.success()
.stdout(predicate::str::contains("x + y = 30"))
.stdout(predicate::str::contains("x * y = 200"))
.stdout(predicate::str::contains("x > y is false"))
.stdout(predicate::str::contains("Result: 50"));
}
#[test]
fn test_langcomp_005_03_function_call_interpolation() {
let temp_file = std::env::temp_dir().join("langcomp_005_03_func_call.ruchy");
std::fs::write(
&temp_file,
r#"
fn double(x) {
x * 2
}
let num = 21
println(f"double({num}) = {double(num)}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("double(21) = 42"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_03_function_with_interpolated_result() {
let temp_file = std::env::temp_dir().join("langcomp_005_03_func_result.ruchy");
std::fs::write(
&temp_file,
r#"
fn add(a, b) {
a + b
}
let result = add(10, 20)
println(f"Result: {result}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Result: 30"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_03_function_call_interpolation_example_file() {
ruchy_cmd()
.arg("run")
.arg(example_path("03_function_calls.ruchy"))
.assert()
.success()
.stdout(predicate::str::contains("double(21) = 42"))
.stdout(predicate::str::contains("add(10, 20) = 30"));
}
#[test]
fn test_langcomp_005_04_nested_variable_interpolation() {
let temp_file = std::env::temp_dir().join("langcomp_005_04_nested_var.ruchy");
std::fs::write(
&temp_file,
r#"
let first = "John"
let last = "Doe"
let full_name = f"{first} {last}"
println(f"Full name: {full_name}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Full name: John Doe"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_04_interpolated_fstring_variable() {
let temp_file = std::env::temp_dir().join("langcomp_005_04_fstring_var.ruchy");
std::fs::write(
&temp_file,
r#"
let name = "Alice"
let greeting = f"Hello, {name}!"
println(f"Message: {greeting}")
"#,
)
.unwrap();
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains("Message: Hello, Alice!"));
std::fs::remove_file(&temp_file).ok();
}
#[test]
fn test_langcomp_005_04_nested_interpolation_example_file() {
ruchy_cmd()
.arg("run")
.arg(example_path("04_nested_interpolation.ruchy"))
.assert()
.success()
.stdout(predicate::str::contains("Full name: John Doe"))
.stdout(predicate::str::contains("Greeting: Hello, John Doe!"));
}
#[cfg(test)]
mod property_tests {
use super::*;
#[test]
#[ignore = "Test disabled - run with --ignored"]
fn test_langcomp_005_property_interpolation_is_deterministic() {
for i in 1..20 {
let code = format!(
r#"
let x = {i}
println(f"Value: {{x}}")
"#
);
let temp_file =
std::env::temp_dir().join(format!("langcomp_005_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_005_property_expression_evaluation_in_interpolation() {
for i in 1..10 {
for j in 1..10 {
let code = format!(
r#"
let a = {i}
let b = {j}
println(f"Result: {{a + b}}")
"#
);
let temp_file =
std::env::temp_dir().join(format!("langcomp_005_prop_expr_eval_{i}_{j}.ruchy"));
std::fs::write(&temp_file, &code).unwrap();
let expected = format!("Result: {}", i + j);
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains(expected));
std::fs::remove_file(&temp_file).ok();
}
}
}
#[test]
#[ignore = "Test disabled - run with --ignored"]
fn test_langcomp_005_property_multiple_interpolations_independent() {
for i in 1..10 {
let code = format!(
r#"
let a = {}
let b = {}
println(f"{{a}} {{b}}")
"#,
i,
i * 2
);
let temp_file =
std::env::temp_dir().join(format!("langcomp_005_prop_multi_interp_{i}.ruchy"));
std::fs::write(&temp_file, &code).unwrap();
let expected = format!("{} {}", i, i * 2);
ruchy_cmd()
.arg("run")
.arg(&temp_file)
.assert()
.success()
.stdout(predicate::str::contains(expected));
std::fs::remove_file(&temp_file).ok();
}
}
}