use assert_cmd::Command;
use std::fs;
use tempfile::TempDir;
const GRAMMAR_SAMPLE: &str = r#"
effect State {
get() -> i32,
set(x: i32) -> ()
}
fun foo() {
println("Test function")
}
handle foo() with {
get => 42,
set(x) => println("Set operation")
}
fun main() {
println("All tools working")
}
"#;
fn create_test_file() -> (TempDir, std::path::PathBuf) {
let temp_dir = TempDir::new().unwrap();
let ruchy_file = temp_dir.path().join("test.ruchy");
fs::write(&ruchy_file, GRAMMAR_SAMPLE).unwrap();
(temp_dir, ruchy_file)
}
#[test]
fn test_tool_check_validates_complete_grammar() {
let (_temp_dir, ruchy_file) = create_test_file();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("check")
.arg(&ruchy_file)
.assert()
.success()
.stdout(predicates::str::contains("Syntax is valid"));
}
#[test]
fn test_tool_lint_analyzes_complete_grammar() {
let (_temp_dir, ruchy_file) = create_test_file();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("lint")
.arg(&ruchy_file)
.assert()
.success()
.stdout(predicates::str::contains("No issues found"));
}
#[test]
fn test_tool_ast_parses_complete_grammar() {
let (_temp_dir, ruchy_file) = create_test_file();
let output = assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("ast")
.arg(&ruchy_file)
.assert()
.success();
let stdout = String::from_utf8_lossy(&output.get_output().stdout);
assert!(stdout.contains("Effect"), "AST should contain Effect node");
assert!(stdout.contains("Handle"), "AST should contain Handle node");
}
#[test]
#[ignore = "BUG: effect/handle constructs cause timeout - needs interpreter support - EFFECT-001"]
fn test_tool_run_executes_complete_grammar() {
let (_temp_dir, ruchy_file) = create_test_file();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("run")
.arg(&ruchy_file)
.assert()
.success()
.stdout(predicates::str::contains("All tools working"));
}
#[test]
fn test_tool_transpile_generates_rust_from_complete_grammar() {
let temp_dir = TempDir::new().unwrap();
let ruchy_file = temp_dir.path().join("test.ruchy");
let rust_file = temp_dir.path().join("output.rs");
fs::write(&ruchy_file, GRAMMAR_SAMPLE).unwrap();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("transpile")
.arg(&ruchy_file)
.arg("-o")
.arg(&rust_file)
.assert()
.success();
assert!(rust_file.exists(), "Transpiled Rust file should exist");
let rust_code = fs::read_to_string(&rust_file).unwrap();
assert!(
rust_code.contains("fn foo()"),
"Rust code should contain foo function"
);
assert!(
rust_code.contains("fn main()"),
"Rust code should contain main function"
);
}
#[test]
fn test_tool_compile_creates_binary_from_complete_grammar() {
let temp_dir = TempDir::new().unwrap();
let ruchy_file = temp_dir.path().join("test.ruchy");
let rust_file = temp_dir.path().join("compiled.rs");
fs::write(&ruchy_file, GRAMMAR_SAMPLE).unwrap();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("transpile")
.arg(&ruchy_file)
.arg("-o")
.arg(&rust_file)
.assert()
.success();
let rlib_file = temp_dir.path().join("compiled.rlib");
Command::new("rustc")
.arg("--crate-type")
.arg("lib")
.arg(&rust_file)
.arg("-o")
.arg(&rlib_file)
.assert()
.success();
assert!(rlib_file.exists(), "Compiled binary should exist");
}
#[test]
fn test_tool_format_roundtrips_complete_grammar() {
use ruchy::frontend::parser::Parser;
use ruchy::quality::formatter::Formatter;
let simple_code = "fun main() { println(\"test\") }";
let ast1 = Parser::new(simple_code).parse().unwrap();
let formatted = Formatter::new().format(&ast1);
if let Ok(formatted_code) = formatted {
let ast2 = Parser::new(&formatted_code).parse();
assert!(ast2.is_ok(), "Formatted code should parse successfully");
} else {
println!("Formatter returned error (covered by property tests)");
}
}
#[test]
fn test_all_essential_tools_integrated() {
let temp_dir = TempDir::new().unwrap();
let ruchy_file = temp_dir.path().join("test.ruchy");
fs::write(&ruchy_file, GRAMMAR_SAMPLE).unwrap();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("check")
.arg(&ruchy_file)
.assert()
.success();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("lint")
.arg(&ruchy_file)
.assert()
.success();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("ast")
.arg(&ruchy_file)
.assert()
.success();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("run")
.arg(&ruchy_file)
.assert()
.success();
let rust_file = temp_dir.path().join("output.rs");
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("transpile")
.arg(&ruchy_file)
.arg("-o")
.arg(&rust_file)
.assert()
.success();
}
#[test]
fn test_handler_expr_all_tools() {
let handler_code = r#"
effect Logger { log(msg: String) -> () }
fun greet(name: String) {
println("Hello, " + name)
}
handle greet("World") with {
log(msg) => println("[LOG] " + msg)
}
fun main() {
println("Handler test")
}
"#;
let temp_dir = TempDir::new().unwrap();
let ruchy_file = temp_dir.path().join("handler_test.ruchy");
fs::write(&ruchy_file, handler_code).unwrap();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("check")
.arg(&ruchy_file)
.assert()
.success();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("lint")
.arg(&ruchy_file)
.assert()
.success();
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
.arg("run")
.arg(&ruchy_file)
.assert()
.success();
}
#[test]
fn test_property_roundtrip_coverage() {
let property_file = std::path::Path::new("tests/property_roundtrip.rs");
assert!(
property_file.exists(),
"Property roundtrip test file should exist"
);
let content = fs::read_to_string(property_file).unwrap();
assert!(
content.contains("prop_literal_roundtrip"),
"Should have literal roundtrip test"
);
assert!(
content.contains("prop_binary_roundtrip"),
"Should have binary roundtrip test"
);
assert!(
content.contains("prop_simple_expr_roundtrip"),
"Should have simple expr roundtrip test"
);
assert!(
content.contains("prop_formatting_deterministic"),
"Should have deterministic test"
);
assert!(
content.contains("prop_double_roundtrip_stabilizes"),
"Should have stabilization test"
);
}