#![allow(missing_docs)]
use assert_cmd::Command;
use std::fs;
use tempfile::TempDir;
fn ruchy_cmd() -> Command {
assert_cmd::cargo::cargo_bin_cmd!("ruchy")
}
fn temp_dir() -> TempDir {
TempDir::new().expect("Failed to create temp directory")
}
#[test]
fn test_bug_036_red_reports_line_counts() {
let temp = temp_dir();
let source = temp.path().join("test.ruchy");
let code = r"
fun add(a, b) {
a + b
}
fun main() {
let result = add(1, 2)
println(result)
}
";
fs::write(&source, code).expect("Failed to write test file");
let output = ruchy_cmd()
.arg("coverage")
.arg(&source)
.assert()
.success()
.get_output()
.stdout
.clone();
let output_str = String::from_utf8_lossy(&output);
assert!(
!output_str.contains("Total Lines: 0/0"),
"Should report actual line counts, not 0/0. Found: {output_str}"
);
}
#[test]
fn test_bug_036_red_reports_function_counts() {
let temp = temp_dir();
let source = temp.path().join("test.ruchy");
let code = r"
fun multiply(x, y) {
x * y
}
fun divide(x, y) {
x / y
}
";
fs::write(&source, code).expect("Failed to write test file");
let output = ruchy_cmd()
.arg("coverage")
.arg(&source)
.assert()
.success()
.get_output()
.stdout
.clone();
let output_str = String::from_utf8_lossy(&output);
assert!(
!output_str.contains("Total Functions: 0/0"),
"Should report actual function counts, not 0/0. Found: {output_str}"
);
}
#[test]
fn test_bug_036_red_reports_actual_coverage() {
let temp = temp_dir();
let source = temp.path().join("test.ruchy");
let code = r"
fun add(a, b) {
a + b
}
";
fs::write(&source, code).expect("Failed to write test file");
let output = ruchy_cmd()
.arg("coverage")
.arg(&source)
.assert()
.success()
.get_output()
.stdout
.clone();
let output_str = String::from_utf8_lossy(&output);
assert!(
output_str.contains("Total Lines:") && !output_str.contains("0/0"),
"Should report actual line numbers, not 0/0. Found: {output_str}"
);
}
#[cfg(test)]
mod property_tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn test_coverage_never_reports_zero_over_zero(line_count in 1usize..100) {
let temp = temp_dir();
let source = temp.path().join("test.ruchy");
let mut code = String::new();
for i in 0..line_count {
code.push_str(&format!("let x{i} = {i}\n"));
}
fs::write(&source, code).expect("Failed to write test file");
let output = ruchy_cmd()
.arg("coverage")
.arg(&source)
.assert()
.success()
.get_output()
.stdout
.clone();
let output_str = String::from_utf8_lossy(&output);
prop_assert!(
!output_str.contains("Total Lines: 0/0"),
"Coverage should not report 0/0 for file with {} lines",
line_count
);
}
#[test]
fn test_coverage_totals_are_non_negative(func_count in 0usize..10) {
let temp = temp_dir();
let source = temp.path().join("test.ruchy");
let mut code = String::new();
for i in 0..func_count {
code.push_str(&format!("fun func{i}() {{ {i} }}\n"));
}
fs::write(&source, code).expect("Failed to write test file");
let output = ruchy_cmd()
.arg("coverage")
.arg(&source)
.assert()
.success()
.get_output()
.stdout
.clone();
let output_str = String::from_utf8_lossy(&output);
prop_assert!(
!output_str.contains("Lines: -") && !output_str.contains("Functions: -"),
"Coverage should not have negative line/function counts"
);
}
}
}
#[test]
fn test_bug_036_red_phase_summary() {
println!("BUG-036 RED Phase: Coverage Reports 0/0");
println!();
println!("Problem: Coverage tool never calls analyze_file()");
println!("Impact: Always shows 0/0 = 100% (meaningless)");
println!();
println!("Root Cause:");
println!("- execute_with_coverage() line 378: if let Some(coverage) = self.coverage_data.get_mut(file_str)");
println!("- coverage_data is empty HashMap");
println!("- analyze_file() exists but is never called");
println!();
println!("Test Suite Created:");
println!("1. Reports actual line counts (not 0/0)");
println!("2. Reports actual function counts (not 0/0)");
println!("3. Coverage percentage not always 100%");
println!();
println!("Expected Results:");
println!("- RED Phase: All 3 tests FAIL (shows 0/0)");
println!("- GREEN Phase: ALL tests PASS after fix");
println!();
println!("Fix Strategy:");
println!("- Call analyze_file() before execute_with_coverage() marks coverage");
println!("- This populates total_lines and total_functions");
println!("- Then marking covered lines/functions will give real percentages");
}