// SPDX-FileCopyrightText: 2022 Matteo Settenvini // SPDX-License-Identifier: GPL-3.0-or-later include!(concat!( env!("CARGO_MANIFEST_DIR"), "/src/policy_checker/dbus.rs" )); use { event_listener::{Event, EventListener}, nix::unistd::Uid, std::collections::HashMap, zbus::dbus_interface, }; pub struct MalcontentDBusMock { responses: HashMap>, invocations_left: usize, finished: Event, } #[dbus_interface(name = "com.endlessm.ParentalControls.Dns")] impl MalcontentDBusMock { fn get_restrictions(&mut self, user_id: u32) -> Restrictions { let answers = self .responses .get_mut(&Uid::from_raw(user_id)) .expect(&format!( "MockError: No mocked invocations available for user with id {}", user_id )); let restrictions = answers.pop().expect(&format!( "MockError: DBus mock is saturated for user with id {}", user_id )); self.invocations_left -= 1; if self.invocations_left == 0 { self.finished.notify(1); } restrictions } } impl MalcontentDBusMock { pub fn new(mut responses: HashMap>) -> Self { let responses_size: usize = responses.values().map(|v| v.len()).sum(); for r in responses.values_mut() { r.reverse(); // we pop responses from the back, so... } let ret = Self { responses, invocations_left: responses_size, finished: Event::new(), }; if ret.invocations_left == 0 { ret.finished.notify(1); } ret } pub fn waiter(&self) -> EventListener { self.finished.listen() } } impl Drop for MalcontentDBusMock { fn drop(&mut self) { assert_eq!( self.invocations_left, 0, "MockError: During teardown, {} invocations are still left on the mock object", self.invocations_left ); self.finished.notify(1); } } pub async fn mock_dbus(responses: HashMap>) -> Result { let mock = MalcontentDBusMock::new(responses); let connection = zbus::ConnectionBuilder::session()? .serve_at("/com/endlessm/ParentalControls/Dns", mock)? .build() .await?; std::env::set_var( "TEST_DBUS_SERVICE_NAME", connection.unique_name().unwrap().as_str(), ); Ok(connection) }