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 = "pointer";
    let (producer, consumer) = setup(testcase).await?;

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

    Debugger::run(
        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: 30,
                        column: None,
                    },
                    loc_end: None,
                    breakpoint_type: BreakpointType::Breakpoint,
                    capture: VariableCapture::Locals,
                },
                Breakpoint {
                    id: 2,
                    file_id: 1,
                    loc: LineColumn {
                        line: 44,
                        column: None,
                    },
                    loc_end: None,
                    breakpoint_type: BreakpointType::Breakpoint,
                    capture: VariableCapture::Locals,
                },
            ],
            arguments: vec![],
        },
        producer.clone(),
    );

    producer.end().await?;
    for i in 0..2 {
        let payload = consumer.next().await?.message().into_bytes();
        let event = EventStream::read_from(Bytes::from(payload));
        match event {
            Event::Breakpoint { mut locals, .. } => match i {
                0 => {
                    assert!(locals.len() >= 3);
                    for (j, (name, value)) in locals.iter_mut().enumerate().take(3) {
                        value.redact_addr();
                        let json = serde_json::to_string(value).unwrap();
                        println!("{name} = {json}");
                        match j {
                            0 => {
                                assert_eq!(name.as_str(), "boxed");
                                assert_eq!(
                                    json,
                                    r#"{"type":"Ref","typename":"Box","addr":"<redacted>","value":{"type":"Struct","typename":"pointer::Object","fields":{"name":{"type":"String","typename":"String","value":"Boxed"}}}}"#
                                )
                            }
                            1 => {
                                assert_eq!(name.as_str(), "arc");
                                assert_eq!(
                                    json,
                                    r#"{"type":"RefCounted","typename":"Arc","addr":"<redacted>","strong":2,"weak":3,"value":{"type":"Struct","typename":"pointer::Object","fields":{"name":{"type":"String","typename":"String","value":"Arced"}}}}"#
                                )
                            }
                            2 => {
                                assert_eq!(name.as_str(), "rc");
                                assert_eq!(
                                    json,
                                    r#"{"type":"RefCounted","typename":"Rc","addr":"<redacted>","strong":3,"weak":2,"value":{"type":"Struct","typename":"pointer::Object","fields":{"name":{"type":"String","typename":"String","value":"Rced"}}}}"#
                                )
                            }
                            _ => (),
                        }
                    }
                }
                1 => {
                    assert!(locals.len() >= 5);
                    for (j, (name, value)) in locals.iter_mut().enumerate() {
                        value.redact_addr();
                        let json = serde_json::to_string(value).unwrap();
                        println!("{name} = {json}");
                        match j {
                            0 => {
                                assert_eq!(name.as_str(), "obj");
                                assert_eq!(
                                    json,
                                    r#"{"type":"Struct","typename":"pointer::Object","fields":{"name":{"type":"String","typename":"String","value":"Don't care"}}}"#
                                )
                            }
                            1 => {
                                assert_eq!(name.as_str(), "boxed");
                                assert_eq!(
                                    json,
                                    r#"{"type":"DynRef","typename":"alloc::boxed::Box<dyn pointer::Shape>","addr":"<redacted>","vtable":"<redacted>","value":{"type":"Struct","typename":"pointer::Object","fields":{"name":{"type":"String","typename":"String","value":"Don't care"}}}}"#
                                )
                            }
                            2 => {
                                assert_eq!(name.as_str(), "arc");
                                assert_eq!(
                                    json,
                                    r#"{"type":"DynRefCounted","typename":"alloc::sync::Arc<dyn pointer::Shape>","addr":"<redacted>","strong":1,"weak":1,"vtable":"<redacted>","value":{"type":"Struct","typename":"pointer::Object","fields":{"name":{"type":"String","typename":"String","value":"Don't care"}}}}"#
                                )
                            }
                            3 => {
                                assert_eq!(name.as_str(), "rc");
                                assert_eq!(
                                    json,
                                    r#"{"type":"DynRefCounted","typename":"alloc::rc::Rc<dyn pointer::Shape>","addr":"<redacted>","strong":1,"weak":1,"vtable":"<redacted>","value":{"type":"Struct","typename":"pointer::Object","fields":{"name":{"type":"String","typename":"String","value":"Don't care"}}}}"#
                                )
                            }
                            4 => {
                                assert_eq!(name.as_str(), "obj");
                                assert_eq!(
                                    json,
                                    r#"{"type":"DynRef","typename":"&dyn pointer::Shape","addr":"<redacted>","vtable":"<redacted>","value":{"type":"Opaque"}}"#
                                )
                            }
                            _ => (),
                        }
                    }
                }
                _ => unreachable!(),
            },
            other => panic!("Unexpected {other:?}"),
        }
    }

    Ok(())
}