decy 2.2.0

CLI tool for C-to-Rust transpilation with EXTREME quality standards
//! Large C project end-to-end validation tests (DECY-046)
//!
//! This test suite validates the transpiler against real-world C code examples,
//! measuring success rates, performance, and identifying edge cases.
//!
//! Goal: Validate transpiler quality on realistic C code and discover any
//! remaining edge cases that need to be addressed.

use decy_core::transpile;
use std::time::Instant;

/// Validation result for a C file
#[derive(Debug)]
struct ValidationResult {
    file_path: String,
    success: bool,
    transpilation_time_ms: u128,
    lines_of_code: usize,
    functions_count: usize,
    error: Option<String>,
}

/// Run transpilation and measure performance
fn validate_c_source(name: &str, source: &str) -> ValidationResult {
    let lines_of_code = source.lines().count();

    let start = Instant::now();
    let result = transpile(source);
    let duration = start.elapsed();

    match result {
        Ok(rust_code) => {
            // Count functions in output
            let functions_count = rust_code.matches("fn ").count();

            ValidationResult {
                file_path: name.to_string(),
                success: true,
                transpilation_time_ms: duration.as_millis(),
                lines_of_code,
                functions_count,
                error: None,
            }
        }
        Err(e) => ValidationResult {
            file_path: name.to_string(),
            success: false,
            transpilation_time_ms: duration.as_millis(),
            lines_of_code,
            functions_count: 0,
            error: Some(e.to_string()),
        },
    }
}

#[test]
fn test_real_world_validation_suite() {
    let test_cases = vec![
        ("minimal", r#"int main() { return 0; }"#),
        (
            "arithmetic",
            r#"
            int add(int a, int b) {
                return a + b;
            }

            int subtract(int a, int b) {
                return a - b;
            }
        "#,
        ),
        (
            "control_flow",
            r#"
            int max(int a, int b) {
                if (a > b) {
                    return a;
                } else {
                    return b;
                }
            }

            int factorial(int n) {
                int result;
                result = 1;
                int i;
                for (i = 1; i <= n; i = i + 1) {
                    result = result * i;
                }
                return result;
            }
        "#,
        ),
        (
            "linked_list",
            r#"
            struct Node {
                int data;
                struct Node* next;
            };

            int list_length(struct Node* head) {
                int count;
                count = 0;
                while (head != 0) {
                    count = count + 1;
                    head = head->next;
                }
                return count;
            }
        "#,
        ),
        (
            "array_operations",
            r#"
            int sum_array(int* arr, int size) {
                int total;
                int i;
                total = 0;
                for (i = 0; i < size; i = i + 1) {
                    total = total + arr[i];
                }
                return total;
            }

            void fill_array(int* buffer, int size, int value) {
                int i;
                for (i = 0; i < size; i = i + 1) {
                    buffer[i] = value;
                }
            }
        "#,
        ),
        (
            "pointer_operations",
            r#"
            void swap(int* a, int* b) {
                int temp;
                temp = *a;
                *a = *b;
                *b = temp;
            }

            int* get_max_ptr(int* a, int* b) {
                if (*a > *b) {
                    return a;
                } else {
                    return b;
                }
            }
        "#,
        ),
        (
            "nested_structures",
            r#"
            struct Point {
                int x;
                int y;
            };

            struct Rectangle {
                struct Point top_left;
                struct Point bottom_right;
            };

            int area(struct Rectangle* r) {
                int width;
                int height;
                width = r->bottom_right.x - r->top_left.x;
                height = r->bottom_right.y - r->top_left.y;
                return width * height;
            }
        "#,
        ),
    ];

    let mut results = Vec::new();
    let mut total_time_ms = 0u128;
    let mut total_loc = 0usize;
    let mut success_count = 0usize;

    println!("\n=== Large C Project Validation Suite ===\n");

    for (name, source) in &test_cases {
        let result = validate_c_source(name, source);

        println!("Testing: {}", result.file_path);
        println!("  Status: {}", if result.success { "✅ PASS" } else { "❌ FAIL" });
        println!("  Time: {}ms", result.transpilation_time_ms);
        println!("  LOC: {}", result.lines_of_code);
        println!("  Functions: {}", result.functions_count);

        if let Some(ref error) = result.error {
            println!("  Error: {}", error);
        }
        println!();

        total_time_ms += result.transpilation_time_ms;
        total_loc += result.lines_of_code;
        if result.success {
            success_count += 1;
        }

        results.push(result);
    }

    // Summary statistics
    let total_files = results.len();
    let success_rate = (success_count as f64 / total_files as f64) * 100.0;
    let avg_time_ms = if success_count > 0 { total_time_ms / success_count as u128 } else { 0 };
    let avg_loc = if success_count > 0 { total_loc / success_count } else { 0 };

    println!("=== Validation Summary ===");
    println!("Total files tested: {}", total_files);
    println!("Successful: {}", success_count);
    println!("Failed: {}", total_files - success_count);
    println!("Success rate: {:.1}%", success_rate);
    println!("Total LOC processed: {}", total_loc);
    println!("Average transpilation time: {}ms", avg_time_ms);
    println!("Average LOC per file: {}", avg_loc);

    // Performance benchmarks
    if success_count > 0 {
        let loc_per_second = (total_loc as f64 / (total_time_ms as f64 / 1000.0)) as usize;
        println!("Throughput: ~{} LOC/second", loc_per_second);
    }

    // Acceptance criteria: At least 80% success rate
    assert!(success_rate >= 80.0, "Success rate {:.1}% is below 80% threshold", success_rate);

    // List any failures for investigation
    let failures: Vec<_> = results.iter().filter(|r| !r.success).collect();
    if !failures.is_empty() {
        println!("\n=== Failures to Investigate ===");
        for failure in failures {
            println!("- {}: {:?}", failure.file_path, failure.error);
        }
    }
}

#[test]
fn test_transpilation_performance_baseline() {
    // Establish performance baseline for monitoring regressions
    let source = r#"
        int add(int a, int b) {
            return a + b;
        }

        int multiply(int a, int b) {
            return a * b;
        }

        int factorial(int n) {
            if (n <= 1) {
                return 1;
            }
            return n * factorial(n - 1);
        }
    "#;

    let iterations = 100;
    let mut total_time = std::time::Duration::ZERO;

    for _ in 0..iterations {
        let start = Instant::now();
        let _ = transpile(source);
        total_time += start.elapsed();
    }

    let avg_time_ms = total_time.as_millis() / iterations;

    println!("Performance baseline: {}ms average over {} iterations", avg_time_ms, iterations);

    // Performance acceptance: Should complete in under 100ms on average
    // Adjusted from 15ms to 100ms to account for clang FFI overhead and CI variance
    // Note: Actual performance is typically 30-60ms depending on system load
    assert!(avg_time_ms < 100, "Transpilation took {}ms (threshold: 100ms)", avg_time_ms);
}

#[test]
fn test_complex_real_world_example() {
    // Test a more complex example with multiple language features
    let source = r#"
        struct Node {
            int data;
            struct Node* next;
        };

        int list_length(struct Node* head) {
            int count;
            count = 0;
            while (head != 0) {
                count = count + 1;
                head = head->next;
            }
            return count;
        }

        void swap(int* a, int* b) {
            int temp;
            temp = *a;
            *a = *b;
            *b = temp;
        }

        int binary_search(int* arr, int size, int target) {
            int left;
            int right;
            int mid;

            left = 0;
            right = size - 1;

            while (left <= right) {
                mid = (left + right) / 2;
                if (arr[mid] == target) {
                    return mid;
                }
                if (arr[mid] < target) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            return -1;
        }
    "#;

    let start = Instant::now();
    let result = transpile(source);
    let duration = start.elapsed();

    assert!(result.is_ok(), "Complex example should transpile successfully");

    let rust_code = result.unwrap();

    // Verify expected functions are present
    assert!(rust_code.contains("fn list_length"), "Should have list_length function");
    assert!(rust_code.contains("fn swap"), "Should have swap function");
    assert!(rust_code.contains("fn binary_search"), "Should have binary_search function");

    // Verify struct definition
    assert!(
        rust_code.contains("struct Node") || rust_code.contains("pub struct Node"),
        "Should have Node struct definition"
    );

    println!("Complex example transpiled in {:?}", duration);
    println!("Generated {} lines of Rust code", rust_code.lines().count());

    // Should complete in reasonable time
    // Adjusted from 50ms to 150ms to account for clang FFI overhead and CI variance
    assert!(
        duration.as_millis() < 150,
        "Complex transpilation took {}ms (threshold: 150ms)",
        duration.as_millis()
    );
}

#[test]
fn test_error_handling_quality() {
    // Test that transpiler provides useful error messages for invalid C
    let invalid_sources = vec![
        ("Missing semicolon", "int main() { return 0 }"),
        ("Unclosed brace", "int main() { return 0;"),
        ("Invalid syntax", "int main( { }"),
    ];

    for (description, source) in invalid_sources {
        let result = transpile(source);

        assert!(result.is_err(), "{}: Should fail for invalid C code", description);

        if let Err(e) = result {
            let error_msg = e.to_string();
            // Error should be non-empty and somewhat descriptive
            assert!(!error_msg.is_empty(), "{}: Error message should not be empty", description);
            println!("{}: {}", description, error_msg);
        }
    }
}