bashrs 6.66.0

Rust-to-Shell transpiler for deterministic bootstrap scripts
#[allow(clippy::unwrap_used)]
use super::*;
use crate::corpus::registry::CorpusTier;

#[test]
fn test_CORPUS_RUN_001_score_calculation_v2_full() {
    // All flags true: A(30) + B_L1(10) + B_L2(8) + B_L3(7) + C(15) + D(10) + E(10) + F(5) + G(5) = 100
    let result = CorpusResult {
        id: "T-001".to_string(),
        transpiled: true,
        output_contains: true,
        output_exact: true,
        output_behavioral: true,
        schema_valid: true,
        has_test: true,
        coverage_ratio: 1.0,
        lint_clean: true,
        deterministic: true,
        metamorphic_consistent: true,
        cross_shell_agree: true,
        expected_output: None,
        actual_output: Some("output".to_string()),
        error: None,
        error_category: None,
        error_confidence: None,
        decision_trace: None,
    };
    assert!((result.score() - 100.0).abs() < f64::EPSILON);
}

#[test]
fn test_CORPUS_RUN_002_score_transpile_only() {
    // Only transpilation succeeds: A(30) + nothing else = 30
    let result = CorpusResult {
        id: "T-002".to_string(),
        transpiled: true,
        output_contains: false,
        output_exact: false,
        output_behavioral: false,
        schema_valid: true,
        has_test: false,
        coverage_ratio: 0.0,
        lint_clean: false,
        deterministic: false,
        metamorphic_consistent: false,
        cross_shell_agree: false,
        expected_output: None,
        actual_output: Some("output".to_string()),
        error: None,
        error_category: None,
        error_confidence: None,
        decision_trace: None,
    };
    assert!((result.score() - 30.0).abs() < f64::EPSILON);
}

#[test]
fn test_CORPUS_RUN_003_score_failed_transpile() {
    // Failed transpilation: gateway blocks everything = 0
    let result = CorpusResult {
        id: "T-003".to_string(),
        transpiled: false,
        output_contains: false,
        output_exact: false,
        output_behavioral: false,
        schema_valid: false,
        has_test: true,
        coverage_ratio: 1.0,
        lint_clean: false,
        deterministic: false,
        metamorphic_consistent: false,
        cross_shell_agree: false,
        expected_output: None,
        actual_output: None,
        error: Some("parse error".to_string()),
        error_category: None,
        error_confidence: None,
        decision_trace: None,
    };
    assert!((result.score()).abs() < f64::EPSILON);
}

#[test]
fn test_CORPUS_RUN_004_convergence_not_enough_entries() {
    let entries = vec![ConvergenceEntry {
        iteration: 1,
        date: "2026-02-06".to_string(),
        total: 100,
        passed: 99,
        failed: 1,
        rate: 0.99,
        delta: 0.99,
        notes: "initial".to_string(),
        ..Default::default()
    }];
    assert!(!CorpusRunner::is_converged(&entries));
}

#[test]
fn test_CORPUS_RUN_005_convergence_met() {
    let entries = vec![
        ConvergenceEntry {
            iteration: 1,
            date: "2026-02-01".to_string(),
            total: 200,
            passed: 198,
            failed: 2,
            rate: 0.99,
            delta: 0.001,
            notes: "stable".to_string(),
            ..Default::default()
        },
        ConvergenceEntry {
            iteration: 2,
            date: "2026-02-08".to_string(),
            total: 200,
            passed: 199,
            failed: 1,
            rate: 0.995,
            delta: 0.004,
            notes: "stable".to_string(),
            ..Default::default()
        },
        ConvergenceEntry {
            iteration: 3,
            date: "2026-02-15".to_string(),
            total: 200,
            passed: 199,
            failed: 1,
            rate: 0.995,
            delta: 0.0,
            notes: "converged".to_string(),
            ..Default::default()
        },
    ];
    assert!(CorpusRunner::is_converged(&entries));
}

#[test]
fn test_CORPUS_RUN_006_convergence_rate_below_threshold() {
    let entries = vec![
        ConvergenceEntry {
            iteration: 1,
            date: "2026-02-01".to_string(),
            total: 200,
            passed: 190,
            failed: 10,
            rate: 0.95,
            delta: 0.001,
            notes: "not met".to_string(),
            ..Default::default()
        },
        ConvergenceEntry {
            iteration: 2,
            date: "2026-02-08".to_string(),
            total: 200,
            passed: 192,
            failed: 8,
            rate: 0.96,
            delta: 0.01,
            notes: "not met".to_string(),
            ..Default::default()
        },
        ConvergenceEntry {
            iteration: 3,
            date: "2026-02-15".to_string(),
            total: 200,
            passed: 194,
            failed: 6,
            rate: 0.97,
            delta: 0.01,
            notes: "not met".to_string(),
            ..Default::default()
        },
    ];
    assert!(!CorpusRunner::is_converged(&entries));
}

#[test]
fn test_CORPUS_RUN_007_gateway_logic_v2() {
    // All v2 flags true: score = 100
    let perfect = CorpusResult {
        id: "T-007".to_string(),
        transpiled: true,
        output_contains: true,
        output_exact: true,
        output_behavioral: true,
        schema_valid: true,
        has_test: true,
        coverage_ratio: 1.0,
        lint_clean: true,
        deterministic: true,
        metamorphic_consistent: true,
        cross_shell_agree: true,
        expected_output: None,
        actual_output: Some("out".to_string()),
        error: None,
        error_category: None,
        error_confidence: None,
        decision_trace: None,
    };
    assert!((perfect.score() - 100.0).abs() < f64::EPSILON);

    // Gateway: failed transpile = 0 total (all other flags ignored)
    let failed = CorpusResult {
        id: "T-007b".to_string(),
        transpiled: false,
        output_contains: true,
        output_exact: true,
        output_behavioral: true,
        schema_valid: true,
        has_test: true,
        coverage_ratio: 1.0,
        lint_clean: true,
        deterministic: true,
        metamorphic_consistent: true,
        cross_shell_agree: true,
        expected_output: None,
        actual_output: None,
        error: Some("err".to_string()),
        error_category: None,
        error_confidence: None,
        decision_trace: None,
    };
    assert!((failed.score()).abs() < f64::EPSILON);
}

#[test]
fn test_CORPUS_RUN_008_partial_score_v2() {
    // Transpiles + containment + exact + test + deterministic + metamorphic, but NOT lint clean
    // A(30) + B_L1(10) + B_L2(8) + C(15) + D(0) + E(10) + F(5) = 78
    let partial = CorpusResult {
        id: "T-008".to_string(),
        transpiled: true,
        output_contains: true,
        output_exact: true,
        output_behavioral: false,
        schema_valid: true,
        has_test: true,
        coverage_ratio: 1.0,
        lint_clean: false,
        deterministic: true,
        metamorphic_consistent: true,
        cross_shell_agree: false,
        expected_output: None,
        actual_output: Some("out".to_string()),
        error: None,
        error_category: None,
        error_confidence: None,
        decision_trace: None,
    };
    assert!((partial.score() - 78.0).abs() < f64::EPSILON);
}

#[test]
fn test_CORPUS_RUN_009_secondary_gate_l1_blocks_l2() {
    // L1 fails: L2 and L3 are gated to 0 even if set true
    // A(30) + B_L1(0) + B_L2(0) + B_L3(0) + C(15) + D(10) + E(10) + F(5) + G(5) = 75
    let result = CorpusResult {
        id: "T-009".to_string(),
        transpiled: true,
        output_contains: false,
        output_exact: true,      // gated by L1
        output_behavioral: true, // gated by L1
        schema_valid: true,
        has_test: true,
        coverage_ratio: 1.0,
        lint_clean: true,
        deterministic: true,
        metamorphic_consistent: true,
        cross_shell_agree: true,
        expected_output: None,
        actual_output: Some("out".to_string()),
        error: None,
        error_category: None,
        error_confidence: None,
        decision_trace: None,
    };
    assert!((result.score() - 75.0).abs() < f64::EPSILON);
}

#[test]
fn test_CORPUS_RUN_010_v1_backward_compat() {
    // v1 scoring: A(40) + B(25) + C(15) + D(10) + E(10) = 100
    let result = CorpusResult {
        id: "T-010".to_string(),
        transpiled: true,
        output_contains: true,
        output_exact: true,
        output_behavioral: false,
        schema_valid: true,
        has_test: true,
        coverage_ratio: 1.0,
        lint_clean: true,
        deterministic: true,
        metamorphic_consistent: true,
        cross_shell_agree: false,
        expected_output: None,
        actual_output: Some("out".to_string()),
        error: None,
        error_category: None,
        error_confidence: None,
        decision_trace: None,
    };
    assert!((result.score_v1() - 100.0).abs() < f64::EPSILON);
}

#[test]
fn test_CORPUS_RUN_011_exact_match_single_line() {
    assert!(check_exact_match("hello world\nfoo bar\n", "foo bar"));
    assert!(!check_exact_match("hello world\nfoo bar baz\n", "foo bar"));
}

#[test]
fn test_CORPUS_RUN_012_exact_match_multi_line() {
    let actual = "line1\nline2\nline3\nline4\n";
    assert!(check_exact_match(actual, "line2\nline3"));
    assert!(!check_exact_match(actual, "line2\nline4"));
}

#[test]
fn test_CORPUS_RUN_013_exact_match_empty_expected() {
    assert!(check_exact_match("anything", ""));
    assert!(check_exact_match("anything", "  "));
}

#[test]
fn test_CORPUS_RUN_014_detect_test_exists() {
    // Empty ID should always return false
    assert!(!detect_test_exists(""));
    // B-001 is tested via test_CORPUS_002 (registry bash entries) — but the
    // detection checks for ID patterns in test function names.
    // If test names can't be loaded (e.g., in CI), falls back to true.
    let result = detect_test_exists("B-001");
    // Either we found the test or fell back to true (both acceptable)
    // detect_test_exists returns true (found) or true (fallback) — always succeeds
    let _detected = result;
}

#[test]
fn test_CORPUS_RUN_016_classify_error_syntax() {
    let (cat, conf) = classify_error("unexpected token: parse error near line 5");
    assert_eq!(cat.as_deref(), Some("syntax_error"));
    assert!(conf.is_some());
}

#[test]
fn test_CORPUS_RUN_017_classify_error_unsupported() {
    let (cat, conf) = classify_error("unsupported feature: process substitution");
    assert_eq!(cat.as_deref(), Some("unsupported_construct"));
    assert!(conf.is_some());
}


include!("runner_tests_tests_CORPUS_3.rs");