diff --git a/docs/TESTS.md b/docs/TESTS.md index 27d6518..e68222a 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -17,7 +17,7 @@ Install podman: Create test container for podman ``` cargo build -p vuinputd-tests -podman build -t vuinputd-tests -f vuinputd-tests/podman/Containerfile . +podman build --dns 1.1.1.1 -t vuinputd-tests -f vuinputd-tests/podman/Containerfile . ``` Run with `cargo test -p vuinputd-tests --features "requires-privileges requires-uinput requires-podman"`. diff --git a/vuinputd-tests/podman/Containerfile b/vuinputd-tests/podman/Containerfile index 283e593..0a8e4a1 100644 --- a/vuinputd-tests/podman/Containerfile +++ b/vuinputd-tests/podman/Containerfile @@ -1,8 +1,9 @@ # Build from project root # > cargo build -p vuinputd-tests -# > podman build -t vuinputd-tests -f vuinputd-tests/podman/Containerfile . +# > podman build --dns 1.1.1.1 -t vuinputd-tests -f vuinputd-tests/podman/Containerfile . FROM ubuntu:24.04 +RUN apt-get update && apt-get install -yy strace && apt-get clean COPY target/debug/test-ipc /test-ipc COPY target/debug/test-keyboard /test-keyboard COPY target/debug/test-ok /test-ok diff --git a/vuinputd-tests/src/podman.rs b/vuinputd-tests/src/podman.rs index 7a5d102..fc3821d 100644 --- a/vuinputd-tests/src/podman.rs +++ b/vuinputd-tests/src/podman.rs @@ -35,7 +35,7 @@ impl PodmanBuilder { } /// `podman run` - fn run_cmd(mut self) -> Self { + pub fn run_cmd(mut self) -> Self { self.args.push("run".into()); self } @@ -72,6 +72,11 @@ impl PodmanBuilder { self } + pub fn allow_input_devices(mut self) -> Self { + self.args.push("--device-cgroup-rule=\"c 13:* rwm\"".into()); + self + } + pub fn volume(mut self, spec: &str) -> Self { self.args.push("-v".into()); self.args.push(spec.into()); @@ -118,6 +123,8 @@ impl PodmanBuilder { // Child side must become FD 3 inside container self.ipc_child_fd = Some(child); + self.args.push("--preserve-fds=1".into()); + Ok((self, SandboxIpc { sock: parent_sock })) } diff --git a/vuinputd-tests/tests/podman_tests.rs b/vuinputd-tests/tests/podman_tests.rs new file mode 100644 index 0000000..bf974fe --- /dev/null +++ b/vuinputd-tests/tests/podman_tests.rs @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +// +// Author: Johannes Leupolz + +use std::{process::Command, time::Duration}; +use vuinputd_tests::podman; +use vuinputd_tests::run_vuinputd; + +#[cfg(all(feature = "requires-privileges", feature = "requires-podman"))] +#[test] +fn test_podman_simple() { + let out = podman::PodmanBuilder::new() + .run_cmd() + .rm() + //.detach() + //.name(&format!("vuinputd-podman-tests")) + .image("localhost/vuinputd-tests:latest") + .command(&["/test-ok"]) + .run() + .unwrap(); + + println!("Output"); + println!("stdout: {}", str::from_utf8(&out.stdout).unwrap()); + println!("stderr: {}", str::from_utf8(&out.stderr).unwrap()); +} + +#[cfg(all(feature = "requires-privileges", feature = "requires-podman"))] +#[test] +fn test_podman_ipc() { + let (builder, ipc) = podman::PodmanBuilder::new() + .run_cmd() + .rm() + .with_ipc() + .expect("failed to create IPC"); + let builder = builder + //.detach() + //.name(&format!("vuinputd-podman-tests")) + .image("localhost/vuinputd-tests:latest") + .command(&["/test-ipc"]); + + // Note that builder.run() will block. Thus, the send needs to happen before the child process blocks + // the host process. + ipc.send("continue".as_bytes()) + .unwrap_or_else(|e| panic!("failed to send data via ipc: {e}")); + + let out = builder + .run() + .unwrap_or_else(|e| panic!("failed to run podman!: {e}")); + + let result = ipc.recv(Some(Duration::from_secs(5))); + + println!("Output"); + println!("stdout: {}", str::from_utf8(&out.stdout).unwrap()); + println!("stderr: {}", str::from_utf8(&out.stderr).unwrap()); + + let result = result.expect("error receiving input from ipc as host within 5 seconds"); + let result_str = + str::from_utf8(&result).expect("message received from ipc is not encoded as utf8"); + println!("host received {}", result_str); +} + +#[cfg(all( + feature = "requires-privileges", + feature = "requires-uinput", + feature = "requires-podman" +))] +#[test] +fn test_keyboard_in_container_with_vuinput() { + run_vuinputd::ensure_vuinputd_running(); + + let (builder, ipc) = podman::PodmanBuilder::new() + .run_cmd() + .rm() + .with_ipc() + .expect("failed to create IPC"); + let builder = builder + //.detach() + //.name(&format!("vuinputd-podman-tests")) + .device("/dev/vuinput-test:/dev/uinput") + .allow_input_devices() + .image("localhost/vuinputd-tests:latest") + .command(&["/test-keyboard"]); + + let out = builder + .run() + .unwrap_or_else(|e| panic!("failed to run podman!: {e}")); + + println!("Output"); + println!("stdout: {}", str::from_utf8(&out.stdout).unwrap()); + println!("stderr: {}", str::from_utf8(&out.stderr).unwrap()); + + assert!(out.status.success()); +}