2022-08-24 14:46:14 +02:00
|
|
|
// SPDX-FileCopyrightText: 2022 Matteo Settenvini <matteo.settenvini@montecristosoftware.eu>
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
|
|
|
include!(concat!(
|
|
|
|
env!("CARGO_MANIFEST_DIR"),
|
|
|
|
"/src/policy_checker/dbus.rs"
|
|
|
|
));
|
|
|
|
|
2022-09-12 00:38:01 +02:00
|
|
|
use {
|
|
|
|
std::collections::HashMap,
|
|
|
|
std::sync::atomic::{AtomicUsize, Ordering},
|
|
|
|
zbus::dbus_interface,
|
|
|
|
};
|
2022-08-24 14:46:14 +02:00
|
|
|
|
2022-09-05 23:15:29 +02:00
|
|
|
#[derive(Debug)]
|
2022-08-24 14:46:14 +02:00
|
|
|
pub struct MalcontentDBusMock {
|
|
|
|
responses: HashMap<Uid, Vec<Restrictions>>,
|
2022-09-12 00:38:01 +02:00
|
|
|
invocations_left: AtomicUsize,
|
2022-08-24 14:46:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[dbus_interface(name = "com.endlessm.ParentalControls.Dns")]
|
|
|
|
impl MalcontentDBusMock {
|
|
|
|
fn get_restrictions(&mut self, user_id: u32) -> Restrictions {
|
2022-09-12 00:38:01 +02:00
|
|
|
let uid = Uid::from_raw(user_id);
|
|
|
|
let answers = self.responses.get_mut(&uid).expect(&format!(
|
|
|
|
"MockError: No mocked invocations available for user with id {}",
|
|
|
|
uid
|
|
|
|
));
|
|
|
|
|
2022-08-24 14:46:14 +02:00
|
|
|
let restrictions = answers.pop().expect(&format!(
|
|
|
|
"MockError: DBus mock is saturated for user with id {}",
|
2022-09-12 00:38:01 +02:00
|
|
|
uid
|
2022-08-24 14:46:14 +02:00
|
|
|
));
|
2022-09-05 23:15:29 +02:00
|
|
|
|
2022-09-12 00:38:01 +02:00
|
|
|
self.invocations_left.fetch_sub(1, Ordering::SeqCst);
|
2022-08-24 14:46:14 +02:00
|
|
|
restrictions
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MalcontentDBusMock {
|
|
|
|
pub fn new(mut responses: HashMap<Uid, Vec<Restrictions>>) -> Self {
|
2022-09-12 00:38:01 +02:00
|
|
|
let responses_size: usize = responses.values().map(Vec::len).sum();
|
|
|
|
|
2022-08-24 14:46:14 +02:00
|
|
|
for r in responses.values_mut() {
|
|
|
|
r.reverse(); // we pop responses from the back, so...
|
|
|
|
}
|
|
|
|
|
|
|
|
let ret = Self {
|
|
|
|
responses,
|
2022-09-12 00:38:01 +02:00
|
|
|
invocations_left: AtomicUsize::new(responses_size),
|
2022-08-24 14:46:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for MalcontentDBusMock {
|
|
|
|
fn drop(&mut self) {
|
2022-09-12 00:38:01 +02:00
|
|
|
let invocations_left = self.invocations_left.load(Ordering::Acquire);
|
2022-08-24 14:46:14 +02:00
|
|
|
assert_eq!(
|
2022-09-12 00:38:01 +02:00
|
|
|
invocations_left, 0,
|
2022-08-24 14:46:14 +02:00
|
|
|
"MockError: During teardown, {} invocations are still left on the mock object",
|
2022-09-12 00:38:01 +02:00
|
|
|
invocations_left
|
2022-08-24 14:46:14 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2022-08-25 01:00:18 +02:00
|
|
|
|
2022-09-12 00:38:01 +02:00
|
|
|
pub struct DBusServerGuard {
|
|
|
|
handle: tokio::task::JoinHandle<()>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for DBusServerGuard {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
self.handle.abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn mock_dbus(responses: HashMap<Uid, Vec<Restrictions>>) -> Result<DBusServerGuard> {
|
|
|
|
let guid = zbus::Guid::generate();
|
|
|
|
let socket_path =
|
|
|
|
std::path::PathBuf::from(std::env!("CARGO_TARGET_TMPDIR")).join(guid.as_str());
|
|
|
|
|
|
|
|
if socket_path.exists() {
|
|
|
|
std::fs::remove_file(&socket_path)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
let socket = tokio::net::UnixListener::bind(&socket_path)?;
|
|
|
|
std::env::set_var("TEST_DBUS_SOCKET", &socket_path);
|
|
|
|
|
2022-08-25 01:00:18 +02:00
|
|
|
let mock = MalcontentDBusMock::new(responses);
|
2022-09-12 00:38:01 +02:00
|
|
|
let handle = tokio::spawn(async move {
|
|
|
|
let (stream, _) = socket
|
|
|
|
.accept()
|
|
|
|
.await
|
|
|
|
.expect("Server socket closed unexpectedly");
|
|
|
|
std::fs::remove_file(socket_path).unwrap(); // Once we accepted, we can already remove the socket
|
|
|
|
|
|
|
|
let _ = zbus::ConnectionBuilder::unix_stream(stream)
|
|
|
|
.server(&guid)
|
|
|
|
.p2p()
|
|
|
|
.name("com.endlessm.ParentalControls")
|
|
|
|
.expect("Unable to serve given dbus name")
|
|
|
|
.serve_at("/com/endlessm/ParentalControls/Dns", mock)
|
|
|
|
.expect("Unable to server malcontent dbus mock object")
|
|
|
|
.build()
|
|
|
|
.await;
|
|
|
|
|
|
|
|
std::future::pending::<()>().await;
|
|
|
|
});
|
|
|
|
|
|
|
|
Ok(DBusServerGuard { handle })
|
2022-08-25 01:00:18 +02:00
|
|
|
}
|