#![allow(missing_docs)]
use assert_cmd::Command;
use predicates::prelude::*;
use std::fs;
use tempfile::TempDir;
fn ruchy_cmd() -> Command {
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
}
fn create_temp_file(dir: &TempDir, name: &str, content: &str) -> std::path::PathBuf {
let path = dir.path().join(name);
fs::write(&path, content).expect("Failed to write temp file");
path
}
#[test]
fn cli_runtime_valid_program_exits_zero() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "simple.ruchy", "let x = 42\nprintln(x)\n");
ruchy_cmd().arg("runtime").arg(&file).assert().success(); }
#[test]
fn cli_runtime_missing_file_exits_nonzero() {
ruchy_cmd()
.arg("runtime")
.arg("nonexistent_xyz.ruchy")
.assert()
.failure(); }
#[test]
fn cli_runtime_syntax_error_exits_nonzero() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "invalid.ruchy", "let x = \n");
ruchy_cmd().arg("runtime").arg(&file).assert().failure(); }
#[test]
fn cli_runtime_outputs_performance_report() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "perf_test.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.assert()
.success()
.stdout(
predicate::str::contains("Performance")
.or(predicate::str::contains("Runtime"))
.or(predicate::str::contains("Execution")),
);
}
#[test]
fn cli_runtime_profile_flag() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "profile_test.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--profile")
.assert()
.success()
.stdout(
predicate::str::contains("profil")
.or(predicate::str::contains("Profil"))
.or(predicate::str::contains("Performance")),
);
}
#[test]
fn cli_runtime_profile_with_loop() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"profile_loop.ruchy",
r"
for i in range(10) {
println(i)
}
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--profile")
.assert()
.success();
}
#[test]
fn cli_runtime_bigo_flag() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "bigo_test.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bigo")
.assert()
.success()
.stdout(
predicate::str::contains("BigO")
.or(predicate::str::contains("O("))
.or(predicate::str::contains("complexity")),
);
}
#[test]
fn cli_runtime_bigo_with_loop() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"bigo_loop.ruchy",
r"
for i in range(100) {
let x = i * 2
}
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bigo")
.assert()
.success()
.stdout(predicate::str::contains("O(").or(predicate::str::contains("complexity")));
}
#[test]
fn cli_runtime_bigo_with_nested_loops() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"bigo_nested.ruchy",
r"
for i in range(10) {
for j in range(10) {
let x = i * j
}
}
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bigo")
.assert()
.success();
}
#[test]
fn cli_runtime_bench_flag() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "bench_test.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bench")
.assert()
.success()
.stdout(
predicate::str::contains("bench")
.or(predicate::str::contains("Bench"))
.or(predicate::str::contains("statistical")),
);
}
#[test]
fn cli_runtime_bench_with_computation() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"bench_compute.ruchy",
r"
let sum = 0
for i in range(100) {
sum = sum + i
}
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bench")
.assert()
.success();
}
#[test]
fn cli_runtime_compare_two_files() {
let temp = TempDir::new().unwrap();
let file1 = create_temp_file(&temp, "file1.ruchy", "let x = 42\n");
let file2 = create_temp_file(&temp, "file2.ruchy", "let y = 100\n");
ruchy_cmd()
.arg("runtime")
.arg(&file1)
.arg("--compare")
.arg(&file2)
.assert()
.success()
.stdout(
predicate::str::contains("compar")
.or(predicate::str::contains("Compar"))
.or(predicate::str::contains("vs")),
);
}
#[test]
fn cli_runtime_compare_with_nonexistent_baseline() {
let temp = TempDir::new().unwrap();
let file1 = create_temp_file(&temp, "file1.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file1)
.arg("--compare")
.arg("nonexistent.ruchy")
.assert()
.success()
.stdout(
predicate::str::contains("Comparison")
.or(predicate::str::contains("Baseline"))
.or(predicate::str::contains("faster")),
);
}
#[test]
fn cli_runtime_memory_flag() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "memory_test.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--memory")
.assert()
.success()
.stdout(
predicate::str::contains("memory")
.or(predicate::str::contains("Memory"))
.or(predicate::str::contains("allocation")),
);
}
#[test]
fn cli_runtime_memory_with_allocations() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"memory_alloc.ruchy",
r"
let arr = [1, 2, 3, 4, 5]
let sum = 0
for i in arr {
sum = sum + i
}
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--memory")
.assert()
.success();
}
#[test]
fn cli_runtime_profile_and_bigo() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "combined1.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--profile")
.arg("--bigo")
.assert()
.success();
}
#[test]
fn cli_runtime_all_flags() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "all_flags.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--profile")
.arg("--bigo")
.arg("--bench")
.arg("--memory")
.assert()
.success();
}
#[test]
fn cli_runtime_output_to_file() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "output_test.ruchy", "let x = 42\n");
let output_file = temp.path().join("runtime_report.txt");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--output")
.arg(&output_file)
.assert()
.success();
assert!(output_file.exists(), "Output file should be created");
}
#[test]
fn cli_runtime_output_with_bigo() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "output_bigo.ruchy", "let x = 42\n");
let output_file = temp.path().join("bigo_report.txt");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bigo")
.arg("--output")
.arg(&output_file)
.assert()
.success();
assert!(output_file.exists(), "Output file should be created");
}
#[test]
fn cli_runtime_verbose_flag() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "verbose.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--verbose")
.assert()
.success();
}
#[test]
fn cli_runtime_verbose_with_profile() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "verbose_profile.ruchy", "let x = 42\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--verbose")
.arg("--profile")
.assert()
.success();
}
#[test]
fn cli_runtime_missing_file_writes_stderr() {
ruchy_cmd()
.arg("runtime")
.arg("missing.ruchy")
.assert()
.failure()
.stderr(
predicate::str::contains("not found")
.or(predicate::str::contains("No such file"))
.or(predicate::str::contains("does not exist")),
);
}
#[test]
fn cli_runtime_syntax_error_writes_stderr() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "bad_syntax.ruchy", "fun f( { }\n");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.assert()
.failure()
.stderr(predicate::str::is_empty().not()); }
#[test]
fn cli_runtime_empty_file_fails() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(&temp, "empty.ruchy", "");
ruchy_cmd()
.arg("runtime")
.arg(&file)
.assert()
.failure()
.stderr(
predicate::str::contains("Unexpected end of input")
.or(predicate::str::contains("Parse error")),
);
}
#[test]
fn cli_runtime_complex_program() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"complex.ruchy",
r"
fun factorial(n) {
if n <= 1 {
1
} else {
n * factorial(n - 1)
}
}
let result = factorial(5)
println(result)
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bigo")
.assert()
.success();
}
#[test]
fn cli_runtime_recursive_function_bigo() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"recursive.ruchy",
r"
fun fib(n) {
if n <= 1 {
n
} else {
fib(n - 1) + fib(n - 2)
}
}
fib(10)
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bigo")
.assert()
.success();
}
#[test]
fn cli_runtime_help_flag() {
ruchy_cmd()
.arg("runtime")
.arg("--help")
.assert()
.success()
.stdout(
predicate::str::contains("runtime")
.or(predicate::str::contains("Runtime"))
.or(predicate::str::contains("performance")),
);
}
#[test]
fn cli_runtime_constant_time_program() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"constant.ruchy",
r"
let x = 42
let y = x * 2
println(y)
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bigo")
.assert()
.success()
.stdout(predicate::str::contains("O(1)").or(predicate::str::contains("constant")));
}
#[test]
fn cli_runtime_linear_time_program() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"linear.ruchy",
r"
for i in range(100) {
println(i)
}
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bigo")
.assert()
.success()
.stdout(predicate::str::contains("O(n)").or(predicate::str::contains("linear")));
}
#[test]
fn cli_runtime_quadratic_time_program() {
let temp = TempDir::new().unwrap();
let file = create_temp_file(
&temp,
"quadratic.ruchy",
r"
for i in range(10) {
for j in range(10) {
println(i * j)
}
}
",
);
ruchy_cmd()
.arg("runtime")
.arg(&file)
.arg("--bigo")
.assert()
.success()
.stdout(predicate::str::contains("O(n").or(predicate::str::contains("quadratic")));
}