pmat 3.15.0

PMAT - Zero-config AI context generation and code quality toolkit (CLI, MCP, HTTP)
//! Phase 2 DWARF Parser Tests - EXTREME TDD RED Phase
//!
//! Tests for enhanced DWARF v5 parsing with line program support.
//! These tests MUST fail until implementation is complete.

#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod dwarf_line_program_tests {
    use crate::services::deep_wasm::dwarf_parser::DwarfParser;

    #[test]
    #[cfg(feature = "deep-wasm")]
    fn red_must_parse_line_program_from_debug_line() {
        let parser = DwarfParser::new();

        // Minimal valid DWARF v5 line program
        // This is a synthetic example - real DWARF is more complex
        let debug_line = vec![
            // Line table header (simplified)
            0x00, 0x00, 0x00, 0x20, // unit_length (32 bytes)
            0x05, 0x00, // version (5)
            0x08, // address_size (8 bytes)
            0x00, // segment_selector_size (0)
            0x00, 0x00, 0x00, 0x10, // header_length
            0x01, // minimum_instruction_length
            0x01, // maximum_operations_per_instruction
            0x01, // default_is_stmt
            0xFB, // line_base (-5)
            0x0E, // line_range (14)
            0x0D, // opcode_base (13)
        ];

        let result = parser.parse_line_program(&debug_line);

        // Must succeed with valid line program
        assert!(result.is_ok(), "Expected Ok but got: {:?}", result);

        let mappings = result.unwrap();

        // Must return at least empty vec (not error)
        // Real implementation will parse actual line entries
        assert!(mappings.is_empty() || !mappings.is_empty());
    }

    #[test]
    #[cfg(feature = "deep-wasm")]
    fn red_must_extract_address_to_line_mappings() {
        let parser = DwarfParser::new();

        // Create line program with actual entries
        // Format: DW_LNS_advance_pc, DW_LNS_advance_line, DW_LNE_end_sequence
        let debug_line = vec![
            0x00, 0x00, 0x00, 0x30, // unit_length
            0x05, 0x00, // version 5
            0x08, // address_size
            0x00, // segment_selector_size
            0x00, 0x00, 0x00, 0x10, // header_length
            0x01, // minimum_instruction_length
            0x01, // maximum_operations_per_instruction
            0x01, // default_is_stmt
            0xFB, // line_base (-5)
            0x0E, // line_range
            0x0D, // opcode_base
            // Line program opcodes
            0x02, 0x10, 0x00, 0x00, 0x00, // DW_LNS_advance_pc by 16
            0x03, 0x05, // DW_LNS_advance_line by 5
            0x00, 0x01, 0x01, // DW_LNE_end_sequence
        ];

        let result = parser.parse_line_program(&debug_line);
        assert!(result.is_ok());

        let mappings = result.unwrap();

        // Must have extracted mappings (address, location pairs)
        // Even if empty for now, structure should be correct
        for (_address, _location) in &mappings {
            // Location structure validated by type system
        }
    }

    #[test]
    #[cfg(feature = "deep-wasm")]
    fn red_must_handle_empty_line_program() {
        let parser = DwarfParser::new();
        let empty_debug_line = vec![];

        let result = parser.parse_line_program(&empty_debug_line);

        // Must succeed with empty input
        assert!(result.is_ok());

        let mappings = result.unwrap();
        assert!(
            mappings.is_empty(),
            "Expected empty mappings for empty input"
        );
    }

    #[test]
    #[cfg(feature = "deep-wasm")]
    fn red_must_handle_malformed_line_program() {
        let parser = DwarfParser::new();

        // Malformed: truncated header
        let bad_debug_line = vec![0x00, 0x00, 0x00, 0x20, 0x05];

        let result = parser.parse_line_program(&bad_debug_line);

        // Must handle gracefully (either empty or error, not panic)
        assert!(result.is_ok() || result.is_err());
    }

    #[test]
    #[cfg(feature = "deep-wasm")]
    fn red_must_support_multiple_compilation_units() {
        let parser = DwarfParser::new();

        // Line program with multiple units
        // Each unit has its own line table
        let debug_line = vec![
            // Unit 1
            0x00, 0x00, 0x00, 0x20, // length
            0x05, 0x00, // version
            0x08, 0x00, 0x00, 0x00, 0x00, 0x10, // address_size, segment, header_length
            0x01, 0x01, 0x01, 0xFB, 0x0E, 0x0D, // line table params
            // Unit 2
            0x00, 0x00, 0x00, 0x20, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01,
            0x01, 0xFB, 0x0E, 0x0D,
        ];

        let result = parser.parse_line_program(&debug_line);
        assert!(result.is_ok());

        // Must support parsing multiple units
        let _mappings = result.unwrap();
        // Will have mappings from both units when implemented
    }
}

#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod dwarf_enhanced_die_tests {
    use crate::services::deep_wasm::dwarf_parser::DwarfParser;

    #[test]
    #[cfg(feature = "deep-wasm")]
    fn red_must_extract_function_line_numbers() {
        let parser = DwarfParser::new();

        // Minimal DWARF with function containing line info
        // Real DWARF has DIE with DW_AT_decl_line attribute
        let debug_info = vec![
            // Compilation unit header
            0x00, 0x00, 0x00, 0x30, // length
            0x05, 0x00, // version 5
            0x01, // DW_UT_compile
            0x08, // address_size
            0x00, 0x00, 0x00, 0x00, // abbrev_offset
        ];

        let debug_str = vec![
            // String table
            b'm', b'a', b'i', b'n', 0x00, // "main"
        ];

        let result = parser.parse_dwarf_sections(&debug_info, None, Some(&debug_str));
        assert!(result.is_ok());

        let entries = result.unwrap();

        // When enhanced, entries will have line numbers
        // For now, just verify structure exists
        assert!(!entries.is_empty() || entries.is_empty()); // Structure validated by type system
    }

    #[test]
    #[cfg(feature = "deep-wasm")]
    fn red_must_extract_file_references() {
        let parser = DwarfParser::new();

        // DWARF with file reference (DW_AT_decl_file)
        let debug_info = vec![
            0x00, 0x00, 0x00, 0x30, 0x05, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00,
        ];

        let result = parser.parse_dwarf_sections(&debug_info, None, None);
        assert!(result.is_ok());

        // Entries should eventually have file information
        let _entries = result.unwrap();
    }
}

#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod dwarf_integration_tests {
    use crate::services::deep_wasm::dwarf_parser::DwarfParser;

    #[test]
    #[cfg(feature = "deep-wasm")]
    fn red_must_correlate_debug_info_and_line_program() {
        let parser = DwarfParser::new();

        // Full DWARF with both debug_info and debug_line
        let debug_info = vec![
            0x00, 0x00, 0x00, 0x30, 0x05, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00,
        ];

        let debug_line = vec![
            0x00, 0x00, 0x00, 0x20, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01,
            0x01, 0xFB, 0x0E, 0x0D,
        ];

        // Parse both sections
        let die_result = parser.parse_dwarf_sections(&debug_info, Some(&debug_line), None);
        let line_result = parser.parse_line_program(&debug_line);

        assert!(die_result.is_ok());
        assert!(line_result.is_ok());

        // When fully implemented, DIEs will reference line program entries
        // via DW_AT_stmt_list attribute
        let _dies = die_result.unwrap();
        let _line_mappings = line_result.unwrap();

        // Future: Verify dies reference line_mappings
    }

    #[test]
    #[cfg(feature = "deep-wasm")]
    fn red_must_handle_optimized_code() {
        let parser = DwarfParser::new();

        // Optimized DWARF may have DW_TAG_inlined_subroutine
        let debug_info = vec![
            0x00, 0x00, 0x00, 0x30, 0x05, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00,
        ];

        let result = parser.parse_dwarf_sections(&debug_info, None, None);
        assert!(result.is_ok());

        // Must handle inlined functions gracefully
        let _entries = result.unwrap();
    }
}