use predicates::prelude::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_profiling_001_01_basic_binary_profiling() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("fibonacci.ruchy");
fs::write(
&test_file,
r#"
fun fibonacci(n: i32) -> i32 {
if n <= 1 {
n
} else {
fibonacci(n - 1) + fibonacci(n - 2)
}
}
fun main() {
let result = fibonacci(10);
println!("fibonacci(10) = {}", result);
}
"#,
)
.unwrap();
let mut cmd = assert_cmd::cargo::cargo_bin_cmd!("ruchy");
cmd.arg("runtime")
.arg("--profile")
.arg("--binary") .arg(&test_file);
cmd.assert()
.success()
.stdout(predicate::str::contains("=== Binary Execution Profile ==="))
.stdout(predicate::str::contains("fibonacci()")) .stdout(predicate::str::contains("main()")) .stdout(predicate::str::contains("ms")) .stdout(predicate::str::contains("calls")); }
#[test]
fn test_profiling_001_02_binary_profiling_verbose() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("simple.ruchy");
fs::write(
&test_file,
r#"
fun square(n: i32) -> i32 {
n * n
}
fun main() {
let result = square(5);
println!("Result: {}", result);
}
"#,
)
.unwrap();
let mut cmd = assert_cmd::cargo::cargo_bin_cmd!("ruchy");
cmd.arg("runtime")
.arg("--profile")
.arg("--binary")
.arg("--verbose") .arg(&test_file);
cmd.assert()
.success()
.stdout(predicate::str::contains("Binary Execution Profile"))
.stdout(predicate::str::contains("Iterations:")) .stdout(predicate::str::contains("square()")) .stdout(predicate::str::contains("File:")); }
#[test]
fn test_profiling_001_03_binary_profiling_text_format() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("loop.ruchy");
fs::write(
&test_file,
r#"
fun sum_numbers(n: i32) -> i32 {
let mut total = 0;
for i in 0..n {
total = total + i;
}
total
}
fun main() {
let result = sum_numbers(100);
println!("Sum: {}", result);
}
"#,
)
.unwrap();
let mut cmd = assert_cmd::cargo::cargo_bin_cmd!("ruchy");
cmd.arg("runtime")
.arg("--profile")
.arg("--binary")
.arg(&test_file);
cmd.assert()
.success()
.stdout(predicate::str::contains("=== Binary Execution Profile ==="))
.stdout(predicate::str::contains("Function-level timings:"))
.stdout(predicate::str::contains("sum_numbers()"))
.stdout(predicate::str::contains("main()"))
.stdout(predicate::str::contains("Memory:")) .stdout(predicate::str::contains("Allocations:")); }
#[test]
fn test_profiling_001_04_binary_profiling_iterations() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("benchmark.ruchy");
fs::write(
&test_file,
r#"
fun multiply(a: i32, b: i32) -> i32 {
a * b
}
fun main() {
let result = multiply(3, 4);
println!("3 * 4 = {}", result);
}
"#,
)
.unwrap();
let mut cmd = assert_cmd::cargo::cargo_bin_cmd!("ruchy");
cmd.arg("runtime")
.arg("--profile")
.arg("--binary")
.arg("--iterations")
.arg("100") .arg(&test_file);
cmd.assert()
.success()
.stdout(predicate::str::contains("Iterations: 100"))
.stdout(predicate::str::contains("multiply()"))
.stdout(predicate::str::contains("ms")); }
#[test]
fn test_profiling_001_05_interpreter_profiling_fallback() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.ruchy");
fs::write(
&test_file,
r#"
fun add(a: i32, b: i32) -> i32 {
a + b
}
fun main() {
let result = add(2, 3);
println!("Result: {}", result);
}
"#,
)
.unwrap();
let mut cmd = assert_cmd::cargo::cargo_bin_cmd!("ruchy");
cmd.arg("runtime")
.arg("--profile") .arg(&test_file);
cmd.assert()
.success()
.stdout(predicate::str::contains("Profiling")); }
#[test]
fn test_profiling_001_06_binary_profiling_compile_error() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("broken.ruchy");
fs::write(
&test_file,
r"
fun broken() {
let x = ; // Syntax error
}
",
)
.unwrap();
let mut cmd = assert_cmd::cargo::cargo_bin_cmd!("ruchy");
cmd.arg("runtime")
.arg("--profile")
.arg("--binary")
.arg(&test_file);
cmd.assert().failure().stderr(
predicate::str::contains("Parse error")
.or(predicate::str::contains("Transpilation failed"))
.or(predicate::str::contains("Compilation failed")),
);
}
#[test]
fn test_profiling_001_07_binary_profiling_recommendations() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("allocations.ruchy");
fs::write(
&test_file,
r#"
fun create_vec(size: i32) -> Vec<i32> {
let mut v = [];
for i in 0..size {
v.push(i);
}
v
}
fun main() {
let v = create_vec(1000);
println!("Created vector with {} elements", v.len());
}
"#,
)
.unwrap();
let mut cmd = assert_cmd::cargo::cargo_bin_cmd!("ruchy");
cmd.arg("runtime")
.arg("--profile")
.arg("--binary")
.arg(&test_file);
cmd.assert()
.success()
.stdout(predicate::str::contains("Recommendations:"))
.stdout(predicate::str::contains("Memory:"));
}
#[test]
fn test_profiling_001_08_binary_profiling_json_output() {
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("json_test.ruchy");
fs::write(
&test_file,
r#"
fun calculate() -> i32 {
42
}
fun main() {
let result = calculate();
println!("Result: {}", result);
}
"#,
)
.unwrap();
let mut cmd = assert_cmd::cargo::cargo_bin_cmd!("ruchy");
cmd.arg("runtime")
.arg("--profile")
.arg("--binary")
.arg("--output")
.arg(temp_dir.path().join("profile.json"))
.arg(&test_file);
cmd.assert().success();
let json_output = fs::read_to_string(temp_dir.path().join("profile.json")).unwrap();
assert!(json_output.contains("functions"));
assert!(json_output.contains("timings"));
assert!(json_output.contains("calculate"));
}