summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2025-11-03 10:08:35 +0100
committerMarkus Pettersson <markus.pettersson@mullvad.net>2025-11-03 10:08:35 +0100
commitab3c9645794756a1897aea7201fdd2e106c393c9 (patch)
tree3884a37a52b305d481fb04a7af7d6e71157d6baf
parentd99ba914324849cc5c161980e1a488bc64f41163 (diff)
parentce63939ce1a5aa1dbb2dc86c17431c9a56519742 (diff)
downloadmullvadvpn-ab3c9645794756a1897aea7201fdd2e106c393c9.tar.xz
mullvadvpn-ab3c9645794756a1897aea7201fdd2e106c393c9.zip
Merge branch 'general-test-framework-touchups'
-rw-r--r--README.md2
-rw-r--r--test/README.md10
-rw-r--r--test/test-manager/src/container.rs4
-rw-r--r--test/test-manager/src/vm/network/linux.rs35
-rw-r--r--test/test-manager/src/vm/provision.rs6
-rw-r--r--test/test-runner/src/package.rs18
6 files changed, 47 insertions, 28 deletions
diff --git a/README.md b/README.md
index 37e9504b28..9f83c8b4fd 100644
--- a/README.md
+++ b/README.md
@@ -174,7 +174,7 @@ See [this](Release.md) for instructions on how to make a new release.
(macOS only).
* `TALPID_FORCE_USERSPACE_WIREGUARD` - Forces the daemon to use the userspace implementation of
- WireGuard on Linux.
+ WireGuard.
* `TALPID_DISABLE_OFFLINE_MONITOR` - Forces the daemon to always assume the host is online.
diff --git a/test/README.md b/test/README.md
index 66ba136ddf..fea575425f 100644
--- a/test/README.md
+++ b/test/README.md
@@ -54,6 +54,7 @@ This lets us monitor traffic on network interfaces without root access.
For running tests on Linux and Windows guests, you will need these tools and libraries:
+#### Fedora
```bash
dnf install git gcc protobuf-devel libpcap-devel qemu \
podman golang-github-rootless-containers-rootlesskit slirp4netns dnsmasq \
@@ -61,6 +62,15 @@ dnf install git gcc protobuf-devel libpcap-devel qemu \
wireguard-tools
```
+
+#### Debian / Ubuntu
+```bash
+apt install qemu-utils qemu-system-x86 libpcap-dev slirp4netns rootlesskit dnsmasq nftables
+```
+
+##### Note for Debian
+By default `sysctl` is only invokable by root.
+
## Setting up testing environment
First you need to build the images for running tests on, see [`BUILD_OS_IMAGE.md`](./docs/BUILD_OS_IMAGE.md). The `test-manager` then needs to be configured to use the image.
diff --git a/test/test-manager/src/container.rs b/test/test-manager/src/container.rs
index 9560f48b3e..a4ab6725d9 100644
--- a/test/test-manager/src/container.rs
+++ b/test/test-manager/src/container.rs
@@ -1,12 +1,14 @@
#![cfg(target_os = "linux")]
+use nix::unistd::geteuid;
use tokio::process::Command;
/// Re-launch self with rootlesskit if we're not root.
/// Allows for rootless and containerized networking.
/// The VNC port is published to localhost.
pub async fn relaunch_with_rootlesskit(vnc_port: Option<u16>) {
- if unsafe { libc::geteuid() } == 0 {
+ // check if user is root (`man getuid`).
+ if geteuid().is_root() {
return;
}
diff --git a/test/test-manager/src/vm/network/linux.rs b/test/test-manager/src/vm/network/linux.rs
index b6df187dcc..d6f12df6b0 100644
--- a/test/test-manager/src/vm/network/linux.rs
+++ b/test/test-manager/src/vm/network/linux.rs
@@ -219,7 +219,8 @@ impl NetworkHandle {
/// dnsmasq will serve IPv4 addresses within the range [TEST_SUBNET_IPV4_DHCP] using regular DHCP.
/// It will also advertise SLAAC for IPv6 within [TEST_SUBNET_IPV6].
async fn start_dnsmasq() -> Result<DhcpProcHandle> {
- let mut cmd = Command::new("dnsmasq");
+ let dnsmasq = "/usr/sbin/dnsmasq";
+ let mut cmd = Command::new(dnsmasq);
cmd.kill_on_drop(true);
cmd.stdout(Stdio::piped());
@@ -350,11 +351,9 @@ where
}
pub async fn run_nft(input: &str) -> Result<()> {
- let mut cmd = Command::new("nft");
- cmd.args(["-f", "-"]);
-
- cmd.stdin(Stdio::piped());
-
+ let nft = "/usr/sbin/nft";
+ let mut cmd = Command::new(nft);
+ cmd.args(["-f", "-"]).stdin(Stdio::piped());
let mut child = cmd.spawn().map_err(Error::NftStart)?;
let mut stdin = child.stdin.take().unwrap();
@@ -373,19 +372,15 @@ pub async fn run_nft(input: &str) -> Result<()> {
}
async fn enable_forwarding() -> Result<()> {
- let mut cmd = Command::new("sysctl");
- cmd.arg("net.ipv4.ip_forward=1");
- let output = cmd.output().await.map_err(Error::SysctlStart)?;
- if !output.status.success() {
- return Err(Error::SysctlFailed(output.status.code().unwrap()));
- }
-
- let mut cmd = Command::new("sysctl");
- cmd.arg("net.ipv6.conf.all.forwarding=1");
- let output = cmd.output().await.map_err(Error::SysctlStart)?;
- if !output.status.success() {
- return Err(Error::SysctlFailed(output.status.code().unwrap()));
- }
-
+ let sysctl = "/usr/sbin/sysctl";
+ let run = async |cmd: &mut Command| {
+ let exit_status = cmd.output().await.map_err(Error::SysctlStart)?.status;
+ match exit_status.success() {
+ true => Ok(()),
+ false => Err(Error::SysctlFailed(exit_status.code().unwrap())),
+ }
+ };
+ run(Command::new(sysctl).arg("net.ipv4.ip_forward=1")).await?;
+ run(Command::new(sysctl).arg("net.ipv6.conf.all.forwarding=1")).await?;
Ok(())
}
diff --git a/test/test-manager/src/vm/provision.rs b/test/test-manager/src/vm/provision.rs
index 818393cd33..32953230e5 100644
--- a/test/test-manager/src/vm/provision.rs
+++ b/test/test-manager/src/vm/provision.rs
@@ -114,7 +114,11 @@ fn blocking_ssh(
OsType::Macos | OsType::Linux => r"/tmp/",
};
- let stream = TcpStream::connect(SocketAddr::new(guest_ip, 22)).context("TCP connect failed")?;
+ let stream = {
+ let ssh = SocketAddr::new(guest_ip, 22);
+ log::debug!("Connecting to {user}@{ssh} over ssh");
+ TcpStream::connect(ssh).context("TCP connect failed")?
+ };
let mut session = Session::new().context("Failed to connect to SSH server")?;
session.set_tcp_stream(stream);
diff --git a/test/test-runner/src/package.rs b/test/test-runner/src/package.rs
index 5cc0b92dab..8ab3bc6d5e 100644
--- a/test/test-runner/src/package.rs
+++ b/test/test-runner/src/package.rs
@@ -14,6 +14,8 @@ pub async fn uninstall_app(env: HashMap<String, String>) -> Result<()> {
uninstall_apt("mullvad-vpn", env, true).await
}
Distribution::Fedora => uninstall_rpm("mullvad-vpn", env).await,
+ // FIXME: Do not assume that it is Debian/Ubuntu-based.
+ Distribution::Unofficial { name: _ } => uninstall_apt("mullvad-vpn", env, true).await,
}
}
@@ -105,6 +107,8 @@ pub async fn install_package(package: Package) -> Result<()> {
match get_distribution()? {
Distribution::Debian | Distribution::Ubuntu => install_apt(&package.path).await,
Distribution::Fedora => install_rpm(&package.path).await,
+ // FIXME: Do not assume that it is Debian/Ubuntu-based.
+ Distribution::Unofficial { name: _ } => install_apt(&package.path).await,
}
}
@@ -263,26 +267,30 @@ async fn install_nsis_exe(path: &Path) -> Result<()> {
}
#[cfg(target_os = "linux")]
+#[allow(unused)]
enum Distribution {
Debian,
Ubuntu,
Fedora,
+ // Not an officially supported Linux distro.
+ Unofficial { name: String },
}
#[cfg(target_os = "linux")]
fn get_distribution() -> Result<Distribution> {
let os_release =
rs_release::get_os_release().map_err(|_error| Error::UnknownOs("unknown".to_string()))?;
- match os_release
+ let id = os_release
.get("id")
.or(os_release.get("ID"))
- .ok_or(Error::UnknownOs("unknown".to_string()))?
- .as_str()
- {
+ .ok_or(Error::UnknownOs("unknown".to_string()))?;
+ match id.as_str() {
"debian" => Ok(Distribution::Debian),
"ubuntu" => Ok(Distribution::Ubuntu),
"fedora" => Ok(Distribution::Fedora),
- os => Err(Error::UnknownOs(os.to_string())),
+ other => Ok(Distribution::Unofficial {
+ name: other.to_string(),
+ }),
}
}