use std::cell::Cell;
use std::ffi::c_void;
use std::rc::Rc;
use windows_sys::Win32::Foundation::{E_FAIL, S_OK};
use windows_sys::core::HRESULT;
use super::{Responses, install};
struct Reporting {
answer: HRESULT,
seen: Rc<Cell<usize>>,
}
impl Responses for Reporting {
unsafe fn submit(
&mut self,
_ring: *mut c_void,
_wait_operations: u32,
_milliseconds: u32,
_submitted: *mut u32,
) -> HRESULT {
self.seen.set(self.seen.get() + 1);
self.answer
}
}
unsafe fn submit_through_seam() -> HRESULT {
let mut submitted = 0_u32;
unsafe { crate::sys::submit(std::ptr::null_mut(), 0, 0, &raw mut submitted) }
}
#[test]
fn an_installed_responder_answers_instead_of_the_kernel() {
let seen = Rc::new(Cell::new(0));
let guard = install(Box::new(Reporting {
answer: E_FAIL,
seen: Rc::clone(&seen),
}));
let answer = unsafe { submit_through_seam() };
assert_eq!(
answer, E_FAIL,
"the seam must return what the responder said, not what the kernel would"
);
assert_eq!(seen.get(), 1, "the responder must have been consulted once");
drop(guard);
}
#[test]
fn the_responder_is_gone_once_its_guard_drops() {
let seen = Rc::new(Cell::new(0));
{
let _guard = install(Box::new(Reporting {
answer: S_OK,
seen: Rc::clone(&seen),
}));
let _ = unsafe { submit_through_seam() };
}
assert_eq!(seen.get(), 1, "the responder answered while installed");
assert!(
super::with(|_| ()).is_none(),
"the guard must uninstall on drop, or a later test inherits this one's responder"
);
}
#[test]
fn a_responder_is_scoped_to_the_thread_that_installed_it() {
let seen = Rc::new(Cell::new(0));
let _guard = install(Box::new(Reporting {
answer: S_OK,
seen: Rc::clone(&seen),
}));
let elsewhere = std::thread::spawn(|| super::with(|_| ()).is_some())
.join()
.expect("the probe thread does not panic");
assert!(
!elsewhere,
"another thread must not see this thread's responder"
);
assert_eq!(seen.get(), 0, "and must not have consulted it");
}
#[test]
#[should_panic(expected = "already installed")]
fn installing_twice_on_one_thread_is_refused() {
let _first = install(Box::new(Reporting {
answer: S_OK,
seen: Rc::new(Cell::new(0)),
}));
let _second = install(Box::new(Reporting {
answer: S_OK,
seen: Rc::new(Cell::new(0)),
}));
}
#[test]
fn nothing_is_installed_by_default() {
assert!(
super::with(|_| ()).is_none(),
"a thread with no responder must fall through to the kernel"
);
}
#[test]
fn a_responder_is_not_consulted_re_entrantly() {
struct Reentrant {
depth: Rc<Cell<usize>>,
}
impl Responses for Reentrant {
unsafe fn submit(
&mut self,
_ring: *mut c_void,
_wait: u32,
_ms: u32,
_submitted: *mut u32,
) -> HRESULT {
self.depth.set(self.depth.get() + 1);
assert!(
super::with(|_| ()).is_none(),
"a nested call must not reach the responder again"
);
S_OK
}
}
let depth = Rc::new(Cell::new(0));
let _guard = install(Box::new(Reentrant {
depth: Rc::clone(&depth),
}));
let _ = unsafe { submit_through_seam() };
assert_eq!(depth.get(), 1, "the outer call is consulted exactly once");
}