firedbg-rust-debugger 1.74.1

FireDBG Debugger Engine for Rust
Documentation
mod util;
use util::*;

use anyhow::Result;
use firedbg_rust_debugger::{
    Breakpoint, BreakpointType, Bytes, Debugger, DebuggerParams, Event, EventStream, LineColumn,
    SourceFile, VariableCapture,
};
use pretty_assertions::assert_eq;
use sea_streamer::{Buffer, Consumer, Message, Producer};
use std::time::SystemTime;

#[tokio::test]
async fn main() -> Result<()> {
    let testcase = "return_object";

    rustc(&format!("testcases/{testcase}"));

    let debugger_params = DebuggerParams {
        binary: format!("testcases/{testcase}.o"),
        files: vec![
            Default::default(),
            SourceFile {
                id: 1,
                path: format!("testcases/{testcase}.rs"),
                crate_name: testcase.into(),
                modified: SystemTime::UNIX_EPOCH,
            },
        ],
        breakpoints: vec![
            Default::default(),
            Breakpoint {
                id: 1,
                file_id: 1,
                loc: LineColumn {
                    line: 60,
                    column: Some(12),
                },
                loc_end: Some(LineColumn {
                    line: 61,
                    column: Some(5),
                }),
                breakpoint_type: BreakpointType::FunctionCall {
                    fn_name: "main".into(),
                },
                capture: VariableCapture::Arguments,
            },
            Breakpoint {
                id: 2,
                file_id: 1,
                loc: LineColumn {
                    line: 72,
                    column: None,
                },
                loc_end: None,
                breakpoint_type: BreakpointType::Breakpoint,
                capture: VariableCapture::Only(vec!["car".to_owned()]),
            },
            Breakpoint {
                id: 3,
                file_id: 1,
                loc: LineColumn {
                    line: 29,
                    column: Some(32),
                },
                loc_end: Some(LineColumn {
                    line: 30,
                    column: Some(5),
                }),
                breakpoint_type: BreakpointType::FunctionCall {
                    fn_name: "create_manual_car".into(),
                },
                capture: VariableCapture::Arguments,
            },
            Breakpoint {
                id: 4,
                file_id: 1,
                loc: LineColumn {
                    line: 40,
                    column: Some(30),
                },
                loc_end: Some(LineColumn {
                    line: 41,
                    column: Some(5),
                }),
                breakpoint_type: BreakpointType::FunctionCall {
                    fn_name: "create_auto_car".into(),
                },
                capture: VariableCapture::Arguments,
            },
            Breakpoint {
                id: 5,
                file_id: 1,
                loc: LineColumn {
                    line: 52,
                    column: Some(64),
                },
                loc_end: Some(LineColumn {
                    line: 53,
                    column: Some(5),
                }),
                breakpoint_type: BreakpointType::FunctionCall {
                    fn_name: "choose_a_car_for_me".into(),
                },
                capture: VariableCapture::Arguments,
            },
        ],
        arguments: vec![],
    };

    let (producer, consumer) = setup(testcase).await?;

    Debugger::run(debugger_params, producer.clone());

    producer.end().await?;

    for i in 0..11 {
        let payload = consumer.next().await?.message().into_bytes();
        let event = EventStream::read_from(Bytes::from(payload));
        // println!("#{i} {:?}", event);
        match (i, event) {
            (3, Event::Breakpoint { locals, .. }) => {
                let (name, value) = locals.iter().next().unwrap();
                assert_eq!(name.as_str(), "car");
                let json = serde_json::to_string(value).unwrap();
                assert_eq!(
                    json,
                    r#"{"type":"Struct","typename":"return_object::Car","fields":{"brand":{"type":"String","typename":"&str","value":"Nil"},"engine":{"type":"Struct","typename":"return_object::Engine","fields":{"config":{"type":"Union","typeinfo":{"name":"return_object::EngineConfig","variants":["Inline","Vshape"]},"variant":"Inline","fields":{"i":{"type":"Prim","typename":"i32","value":0}}},"pistons":{"type":"Array","typename":"vec","data":[]}}},"gearbox":{"type":"Enum","typename":"return_object::Gearbox","variant":"Automatic"}}}"#
                );
            }
            (
                _,
                Event::FunctionCall {
                    function_name,
                    arguments,
                    ..
                },
            ) => {
                assert_eq!(
                    arguments.len(),
                    match i {
                        6 | 8 => 3,
                        _ => 0,
                    }
                );
                assert_eq!(
                    function_name,
                    match i {
                        0 => "return_object::main",
                        1 => "return_object::create_manual_car",
                        4 => "return_object::create_auto_car",
                        6 => "return_object::choose_a_car_for_me",
                        8 => "return_object::choose_a_car_for_me",
                        _ => panic!("Unexpected i {i}"),
                    }
                );
            }
            (
                _,
                Event::FunctionReturn {
                    function_name,
                    mut return_value,
                    ..
                },
            ) => {
                assert_eq!(
                    function_name,
                    match i {
                        2 => "return_object::create_manual_car",
                        5 => "return_object::create_auto_car",
                        7 => "return_object::choose_a_car_for_me",
                        9 => "return_object::choose_a_car_for_me",
                        10 => "return_object::main",
                        _ => panic!("Unexpected i {i}"),
                    }
                );
                return_value.redact_addr();
                let json = serde_json::to_string(&return_value).unwrap();
                assert_eq!(
                    json,
                    match i {
                        2 =>
                            r#"{"type":"Struct","typename":"return_object::Car","fields":{"brand":{"type":"String","typename":"&str","value":"Ford"},"engine":{"type":"Struct","typename":"return_object::Engine","fields":{"config":{"type":"Union","typeinfo":{"name":"return_object::EngineConfig","variants":["Inline","Vshape"]},"variant":"Inline","fields":{"i":{"type":"Prim","typename":"i32","value":4}}},"pistons":{"type":"Array","typename":"vec","data":[{"type":"Struct","typename":"return_object::Piston","fields":{"0":{"type":"Prim","typename":"u8","value":1}}},{"type":"Struct","typename":"return_object::Piston","fields":{"0":{"type":"Prim","typename":"u8","value":2}}},{"type":"Struct","typename":"return_object::Piston","fields":{"0":{"type":"Prim","typename":"u8","value":3}}},{"type":"Struct","typename":"return_object::Piston","fields":{"0":{"type":"Prim","typename":"u8","value":4}}}]}}},"gearbox":{"type":"Enum","typename":"return_object::Gearbox","variant":"Manual"}}}"#,
                        5 =>
                            r#"{"type":"Struct","typename":"return_object::Car","fields":{"brand":{"type":"String","typename":"&str","value":"Mazda"},"engine":{"type":"Struct","typename":"return_object::Engine","fields":{"config":{"type":"Union","typeinfo":{"name":"return_object::EngineConfig","variants":["Inline","Vshape"]},"variant":"Vshape","fields":{"0":{"type":"Prim","typename":"i16","value":3},"1":{"type":"Prim","typename":"i16","value":3}}},"pistons":{"type":"Array","typename":"vec","data":[]}}},"gearbox":{"type":"Enum","typename":"return_object::Gearbox","variant":"Automatic"}}}"#,
                        7 =>
                            r#"{"type":"Ref","typename":"ref","addr":"<redacted>","value":{"type":"Struct","typename":"return_object::Car","fields":{"brand":{"type":"String","typename":"&str","value":"Mazda"},"engine":{"type":"Struct","typename":"return_object::Engine","fields":{"config":{"type":"Union","typeinfo":{"name":"return_object::EngineConfig","variants":["Inline","Vshape"]},"variant":"Vshape","fields":{"0":{"type":"Prim","typename":"i16","value":3},"1":{"type":"Prim","typename":"i16","value":3}}},"pistons":{"type":"Array","typename":"vec","data":[]}}},"gearbox":{"type":"Enum","typename":"return_object::Gearbox","variant":"Automatic"}}}}"#,
                        9 =>
                            r#"{"type":"Ref","typename":"ref","addr":"<redacted>","value":{"type":"Struct","typename":"return_object::Car","fields":{"brand":{"type":"String","typename":"&str","value":"Ford"},"engine":{"type":"Struct","typename":"return_object::Engine","fields":{"config":{"type":"Union","typeinfo":{"name":"return_object::EngineConfig","variants":["Inline","Vshape"]},"variant":"Inline","fields":{"i":{"type":"Prim","typename":"i32","value":4}}},"pistons":{"type":"Array","typename":"vec","data":[{"type":"Struct","typename":"return_object::Piston","fields":{"0":{"type":"Prim","typename":"u8","value":1}}},{"type":"Struct","typename":"return_object::Piston","fields":{"0":{"type":"Prim","typename":"u8","value":2}}},{"type":"Struct","typename":"return_object::Piston","fields":{"0":{"type":"Prim","typename":"u8","value":3}}},{"type":"Struct","typename":"return_object::Piston","fields":{"0":{"type":"Prim","typename":"u8","value":4}}}]}}},"gearbox":{"type":"Enum","typename":"return_object::Gearbox","variant":"Manual"}}}}"#,
                        10 => r#"{"type":"Unit"}"#,
                        _ => panic!("Unexpected i {i}"),
                    }
                );
                println!("[{i}] {function_name}() -> {return_value}");
            }
            e => panic!("Unexpected {e:?}"),
        }
    }

    Ok(())
}