mod util; use util::*; use anyhow::Result; use firedbg_rust_debugger::{ Breakpoint, BreakpointType, Bytes, Debugger, Event, EventStream, LineColumn, RValue, Reason, VariableCapture, RUST_PANIC_BP_ID, }; use pretty_assertions::assert_eq; use sea_streamer::{Buffer, Consumer, Message, Producer}; #[tokio::test] async fn main() -> Result<()> { let testcase = "fn_call_panic"; let (producer, consumer) = setup(testcase).await?; let debugger_params = debugger_params_from_file(testcase); // println!("{:#?}", debugger_params.breakpoints); assert_eq!( debugger_params.breakpoints[1], Breakpoint { id: 1, file_id: 1, loc: LineColumn { line: 8, column: Some(27), }, loc_end: Some(LineColumn { line: 9, column: Some(5) }), breakpoint_type: BreakpointType::FunctionCall { fn_name: "hello_1".into(), }, capture: VariableCapture::Arguments, } ); assert_eq!( debugger_params.breakpoints[2], Breakpoint { id: 2, file_id: 1, loc: LineColumn { line: 12, column: Some(28), }, loc_end: Some(LineColumn { line: 13, column: Some(5) }), breakpoint_type: BreakpointType::FunctionCall { fn_name: "hello_2".into(), }, capture: VariableCapture::Arguments, } ); assert_eq!( debugger_params.breakpoints[3], Breakpoint { id: 3, file_id: 1, loc: LineColumn { line: 16, column: Some(28), }, loc_end: Some(LineColumn { line: 17, column: Some(5), }), breakpoint_type: BreakpointType::FunctionCall { fn_name: "hello_3".into() }, capture: VariableCapture::Arguments, }, ); assert_eq!( debugger_params.breakpoints[4], Breakpoint { id: 4, file_id: 1, loc: LineColumn { line: 22, column: Some(63), }, loc_end: Some(LineColumn { line: 23, column: Some(9) }), breakpoint_type: BreakpointType::FunctionCall { fn_name: "fmt".into(), }, capture: VariableCapture::Arguments, } ); assert_eq!( debugger_params.breakpoints[5], Breakpoint { id: 5, file_id: 1, loc: LineColumn { line: 27, column: Some(12), }, loc_end: Some(LineColumn { line: 28, column: Some(5) }), breakpoint_type: BreakpointType::FunctionCall { fn_name: "main".into(), }, capture: VariableCapture::Arguments, } ); Debugger::run(debugger_params, producer.clone()); producer.end().await?; let the_world = r#"{"type":"Struct","typename":"fn_call_panic::World","fields":{"nth":{"type":"Prim","typename":"i32","value":99}}}"#; 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 event { Event::FunctionCall { function_name, arguments: values, .. } => match i { 0 => { assert_eq!(values.len(), 0); assert_eq!(function_name, "fn_call_panic::main"); } 1 => { assert_eq!(values.len(), 1); assert_eq!(function_name, "fn_call_panic::hello_1"); let (name, value) = &values[0]; let json = serde_json::to_string(value).unwrap(); println!("{name} = {json}"); assert_eq!(json, the_world); } 2 | 6 => { assert_eq!(values.len(), 2); assert_eq!( function_name, "::fmt" ); let (name, value) = &values[0]; if let RValue::Ref { value, .. } = value { let json = serde_json::to_string(value).unwrap(); println!("{name} = {json}"); assert_eq!(json, the_world); } else { panic!("{value:?}"); } } 5 => { assert_eq!(values.len(), 1); assert_eq!(function_name, "fn_call_panic::hello_2"); let (name, value) = &values[0]; if let RValue::Ref { value, .. } = value { let json = serde_json::to_string(value).unwrap(); println!("{name} = {json}"); assert_eq!(json, the_world); } else { panic!("{value:?}"); } } 9 => { assert_eq!(values.len(), 1); assert_eq!(function_name, "fn_call_panic::hello_3"); let (name, value) = &values[0]; if let RValue::Ref { value, .. } = value { let json = serde_json::to_string(value).unwrap(); println!("{name} = {json}"); assert_eq!(json, the_world); } else { panic!("{value:?}"); } } other => panic!("Unexpected {other:?}"), }, Event::FunctionReturn { function_name, .. } => match i { 3 | 7 => { assert_eq!( function_name, "::fmt" ) } 4 => assert_eq!(function_name, "fn_call_panic::hello_1"), 8 => assert_eq!(function_name, "fn_call_panic::hello_2"), 9 => assert_eq!(function_name, "fn_call_panic::main"), other => panic!("Unexpected {other:?}"), }, Event::Breakpoint { breakpoint_id, reason, locals: values, .. } => { assert_eq!(i, 10); assert_eq!(breakpoint_id, RUST_PANIC_BP_ID.0); assert_eq!(reason, Reason::Panic); assert_eq!(values.len(), 1); let (name, value) = &values[0]; if let RValue::Ref { value, .. } = value { let json = serde_json::to_string(value).unwrap(); println!("{name} = {json}"); assert_eq!(json, the_world); } else { panic!("{value:?}"); } } } } Ok(()) }