Use unique name for dbus connection during integration testing

This commit is contained in:
Matteo Settenvini 2022-08-25 01:00:18 +02:00
parent c52195dd8b
commit 9978bfd783
Signed by: matteo
GPG key ID: 8576CC1AD97D42DF
5 changed files with 74 additions and 54 deletions

View file

@ -73,5 +73,21 @@ impl Drop for MalcontentDBusMock {
"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<Uid, Vec<Restrictions>>) -> Result<zbus::Connection> {
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)
}

View file

@ -11,12 +11,9 @@ include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
mod dbus;
use {
self::dbus::MalcontentDBusMock,
anyhow::{anyhow, bail, ensure, Result},
libc::{freeaddrinfo, gai_strerror, getaddrinfo},
nix::sys::socket::{SockaddrLike as _, SockaddrStorage},
nix::unistd::Uid,
std::collections::HashMap,
std::env,
std::ffi::{CStr, CString},
std::net::{IpAddr, Ipv4Addr, Ipv6Addr},
@ -24,11 +21,9 @@ use {
std::process::Command,
std::str::FromStr,
std::sync::Once,
tokio::task,
tokio::task::JoinHandle,
};
pub use self::dbus::{Restriction, Restrictions};
pub use self::dbus::{mock_dbus, Restriction, Restrictions};
// Adapted from rusty_forkfork (which inherits it from rusty_fork)
// to allow a custom pre-fork function
@ -181,19 +176,3 @@ fn convert_addrinfo(sa: &SockaddrStorage) -> Result<IpAddr> {
bail!("addrinfo is not either an IPv4 or IPv6 address")
}
}
pub fn mock_dbus(responses: HashMap<Uid, Vec<Restrictions>>) -> JoinHandle<Result<()>> {
async fn dbus_loop(responses: HashMap<Uid, Vec<Restrictions>>) -> Result<()> {
let mock = MalcontentDBusMock::new(responses);
let waiter = mock.waiter();
let _connection = zbus::ConnectionBuilder::session()?
.serve_at("/com/endlessm/ParentalControls/Dns", mock)?
.build()
.await?;
waiter.wait();
Ok(())
}
task::spawn(async { dbus_loop(responses).await })
}

View file

@ -11,8 +11,6 @@ use {
once_cell::sync::Lazy,
std::collections::HashMap,
std::net::{IpAddr, Ipv4Addr, Ipv6Addr},
std::time::Duration,
tokio::time::timeout,
};
static CLOUDFLARE_PARENTALCONTROL_ADDRS: Lazy<Restrictions> = Lazy::new(|| {
@ -48,10 +46,10 @@ fork_test! {
fn application_dns_is_nxdomain() -> Result<()> {
common::setup()?;
tokio::runtime::Runtime::new().unwrap().block_on(async {
let dbus = common::mock_dbus(HashMap::from([(
let _dbus = common::mock_dbus(HashMap::from([(
getuid(),
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
)]));
)])).await?;
let hostname = std::ffi::CString::new("use-application-dns.net").unwrap();
unsafe {
@ -73,7 +71,7 @@ fork_test! {
freeaddrinfo(addr);
};
timeout(Duration::from_secs(1), dbus).await??
Ok(())
})
}
@ -84,10 +82,10 @@ fork_test! {
const HOSTNAME: &str = "gnome.org";
tokio::runtime::Runtime::new().unwrap().block_on(async {
let dbus = common::mock_dbus(HashMap::from([(
let _dbus = common::mock_dbus(HashMap::from([(
getuid(),
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
)]));
)])).await?;
unsafe {
let mut addr = std::ptr::null_mut();
@ -108,11 +106,10 @@ fork_test! {
freeaddrinfo(addr);
};
timeout(Duration::from_secs(1), dbus).await??
Ok(())
})
}
#[test]
fn wikipedia_is_unrestricted() -> Result<()> {
common::setup()?;
@ -121,16 +118,14 @@ fork_test! {
tokio::runtime::Runtime::new().unwrap().block_on(async {
for family in [libc::AF_INET, libc::AF_INET6] {
let dbus = common::mock_dbus(HashMap::from([(
let _dbus = common::mock_dbus(HashMap::from([(
getuid(),
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
)]));
)])).await?;
let system_addr = common::resolve_with_system(family, HOSTNAME)?;
let our_addr = common::resolve_with_module(family, HOSTNAME)?;
assert_eq!(system_addr, our_addr);
timeout(Duration::from_secs(1), dbus).await???;
}
Ok(())
})
@ -143,17 +138,17 @@ fork_test! {
const HOSTNAME: &str = "nudity.testcategory.com";
tokio::runtime::Runtime::new().unwrap().block_on(async {
let dbus = common::mock_dbus(HashMap::from([(
let _dbus = common::mock_dbus(HashMap::from([(
getuid(),
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
)]));
)])).await?;
let system_addr = common::resolve_with_system(libc::AF_INET, HOSTNAME)?;
let our_addr = common::resolve_with_module(libc::AF_INET, HOSTNAME)?;
assert_ne!(system_addr, our_addr);
assert_eq!(our_addr, IpAddr::V4(Ipv4Addr::UNSPECIFIED));
timeout(Duration::from_secs(1), dbus).await??
Ok(())
})
}
@ -164,22 +159,20 @@ fork_test! {
const HOSTNAME: &str = "nudity.testcategory.com";
tokio::runtime::Runtime::new().unwrap().block_on(async {
let dbus = common::mock_dbus(HashMap::from([(
let _dbus = common::mock_dbus(HashMap::from([(
getuid(),
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
)]));
)])).await;
let system_addr = common::resolve_with_system(libc::AF_INET6, HOSTNAME)?;
let our_addr = common::resolve_with_module(libc::AF_INET6, HOSTNAME)?;
assert_ne!(system_addr, our_addr);
assert_eq!(our_addr, IpAddr::V6(Ipv6Addr::UNSPECIFIED));
timeout(Duration::from_secs(1), dbus).await??
Ok(())
})
}
#[test]
#[ignore]
fn privileged_user_bypasses_restrictions() -> Result<()> {
common::setup()?;
@ -187,11 +180,10 @@ fork_test! {
tokio::runtime::Runtime::new().unwrap().block_on(async {
for family in [libc::AF_INET, libc::AF_INET6] {
let dbus = common::mock_dbus(HashMap::from([(getuid(), vec![ /* no restriction */])]));
let _dbus = common::mock_dbus(HashMap::from([(getuid(), vec![ /* no restriction */])])).await?;
let system_addr = common::resolve_with_system(family, HOSTNAME)?;
let our_addr = common::resolve_with_module(family, HOSTNAME)?;
assert_eq!(system_addr, our_addr);
timeout(Duration::from_secs(1), dbus).await???
}
Ok(())
})