#[cfg(test)]
pub mod tests {
use crate::tests::util::local_debug2;
use once_cell::sync::Lazy;
use std::{
cell::{Cell, RefCell},
rc::Rc,
sync::Mutex,
};
use wdext::{
callbacks::WdCallbacksErrorPolicy,
data::{DebugExecutionFlags, DebugOutctlFlags, DebugOutputFlags},
dbgeng::{
DebugOutCbText, DebugOutCbfFlags,
callbacks::DebugOutputCallbacksHandler,
},
};
mod util;
static GLOBAL_COUNT: Lazy<Mutex<usize>> = Lazy::new(|| Mutex::new(0));
pub struct TestOutputCallbacks {
output_count: Cell<usize>,
expected_mask: Cell<DebugOutputFlags>,
expected_text: RefCell<String>,
expected_global_count: Cell<usize>,
}
impl DebugOutputCallbacksHandler for TestOutputCallbacks {
fn output2(
&self,
_flags: DebugOutCbfFlags,
arg: DebugOutputFlags,
text: &DebugOutCbText,
) -> windows::core::Result<()> {
let text = text.get_text();
if text.is_none() {
return Ok(());
}
let text = text.unwrap();
self.output_count.set(self.output_count.get() + 1);
{
let cnt = {
let mut cnt = GLOBAL_COUNT.lock().unwrap();
*cnt += 1;
*cnt
};
assert_eq!(cnt, self.expected_global_count.get());
}
assert_eq!(arg, self.expected_mask.get());
assert_eq!(text, self.expected_text.borrow().as_str());
Ok(())
}
}
pub struct PanicTestOutputCallbacks;
impl DebugOutputCallbacksHandler for PanicTestOutputCallbacks {
fn output2(
&self,
_flags: DebugOutCbfFlags,
_arg: DebugOutputFlags,
_text: &DebugOutCbText,
) -> windows::core::Result<()> {
panic!("OutputCallbacks panic");
}
}
#[test]
fn test_output_callbacks() {
let ctx = local_debug2();
let client = ctx.client();
let control = ctx.control();
{
let callbacks1 = Rc::new(TestOutputCallbacks {
output_count: Cell::new(0),
expected_mask: Cell::new(DebugOutputFlags::Normal),
expected_text: RefCell::new(".echo test\ntest\n".to_string()),
expected_global_count: Cell::new(1),
});
assert!(client.get_output_callbacks().unwrap().is_none());
let _lock1 = client
.set_forward_output_callbacks(
callbacks1.clone(),
WdCallbacksErrorPolicy::BackwardError,
)
.unwrap();
assert!(client.get_output_callbacks().unwrap().is_some());
assert_eq!(callbacks1.output_count.get(), 0);
control
.execute(
DebugOutctlFlags::ThisClient,
".echo test",
DebugExecutionFlags::Echo,
)
.unwrap();
assert_eq!(callbacks1.output_count.get(), 1);
let callbacks2 = Rc::new(TestOutputCallbacks {
output_count: Cell::new(0),
expected_mask: Cell::new(DebugOutputFlags::Normal),
expected_text: RefCell::new(".echo test\ntest\n".to_string()),
expected_global_count: Cell::new(1),
});
let _lock2 = client
.set_forward_output_callbacks(
callbacks2.clone(),
WdCallbacksErrorPolicy::BackwardError,
)
.unwrap();
assert_eq!(callbacks1.output_count.get(), 1);
assert_eq!(callbacks2.output_count.get(), 0);
callbacks2.expected_global_count.set(2);
callbacks1.expected_global_count.set(3);
control
.execute(
DebugOutctlFlags::ThisClient,
".echo test",
DebugExecutionFlags::Echo,
)
.unwrap();
assert_eq!(callbacks1.output_count.get(), 2);
assert_eq!(callbacks2.output_count.get(), 1);
let callbacks3 = Rc::new(TestOutputCallbacks {
output_count: Cell::new(0),
expected_mask: Cell::new(DebugOutputFlags::Normal),
expected_text: RefCell::new(".echo test\ntest\n".to_string()),
expected_global_count: Cell::new(3),
});
{
let _lock3 = client
.set_backward_output_callbacks(
callbacks3.clone(),
WdCallbacksErrorPolicy::BackwardError,
)
.unwrap();
assert_eq!(callbacks1.output_count.get(), 2);
assert_eq!(callbacks2.output_count.get(), 1);
assert_eq!(callbacks3.output_count.get(), 0);
callbacks2.expected_global_count.set(4);
callbacks1.expected_global_count.set(5);
callbacks3.expected_global_count.set(6);
control
.execute(
DebugOutctlFlags::ThisClient,
".echo test",
DebugExecutionFlags::Echo,
)
.unwrap();
assert_eq!(callbacks1.output_count.get(), 3);
assert_eq!(callbacks2.output_count.get(), 2);
assert_eq!(callbacks3.output_count.get(), 1);
}
callbacks2.expected_global_count.set(7);
callbacks1.expected_global_count.set(8);
control
.execute(
DebugOutctlFlags::ThisClient,
".echo test",
DebugExecutionFlags::Echo,
)
.unwrap();
assert_eq!(callbacks1.output_count.get(), 4);
assert_eq!(callbacks2.output_count.get(), 3);
assert_eq!(callbacks3.output_count.get(), 1);
}
control
.execute(
DebugOutctlFlags::ThisClient,
".echo test",
DebugExecutionFlags::Echo,
)
.unwrap();
let callbacks4 = Rc::new(PanicTestOutputCallbacks);
let _lock4 = client
.set_forward_output_callbacks(
callbacks4.clone(),
WdCallbacksErrorPolicy::BackwardError,
)
.unwrap();
control
.execute(
DebugOutctlFlags::ThisClient,
".echo test",
DebugExecutionFlags::Echo,
)
.unwrap();
}
}