diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2016-12-05 15:09:49 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2016-12-05 15:09:49 +0100 |
| commit | 22da2098045bdf69a178eb7e4eaaaf38989235af (patch) | |
| tree | 45207af982855eb3b0762c3382df55e4684779aa | |
| parent | f0ee88a4c02039ad198e42f78b39905ce7c89436 (diff) | |
| parent | 057a45c28be721d44d76ed64c4dba6f8a0cbffdf (diff) | |
| download | mullvadvpn-22da2098045bdf69a178eb7e4eaaaf38989235af.tar.xz mullvadvpn-22da2098045bdf69a178eb7e4eaaaf38989235af.zip | |
Merge branch 'add-process'
| -rw-r--r-- | .travis.yml | 3 | ||||
| -rw-r--r-- | src/lib.rs | 3 | ||||
| -rw-r--r-- | src/process.rs | 50 | ||||
| -rw-r--r-- | tests/process.rs | 36 | ||||
| -rw-r--r-- | tests/util.rs | 16 |
5 files changed, 108 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml index 50a05a487f..5b9368c0b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,9 @@ rust: os: - linux - osx +env: + global: + - RUST_TEST_THREADS=1 before_script: - (cargo install rustfmt || true) diff --git a/src/lib.rs b/src/lib.rs index 949a029d45..fec2e1da5e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,9 @@ //! The core components of the talpidaemon VPN client. +/// Working with processes. +pub mod process; + #[cfg(test)] mod tests { #[test] diff --git a/src/process.rs b/src/process.rs new file mode 100644 index 0000000000..7143b85eb3 --- /dev/null +++ b/src/process.rs @@ -0,0 +1,50 @@ +use std::ffi::{OsString, OsStr}; +use std::io; +use std::path::{Path, PathBuf}; +use std::process::{Command, Child, Stdio}; + +/// An OpenVPN process builder, providing control over the different arguments that the OpenVPN +/// binary accepts. +pub struct OpenVpnBuilder { + openvpn_bin: OsString, + config: Option<PathBuf>, +} + +impl OpenVpnBuilder { + /// Constructs a new `OpenVpnBuilder` for launching OpenVPN processes from the binary at + /// `openvpn_bin`. + pub fn new<P: AsRef<OsStr>>(openvpn_bin: P) -> Self { + OpenVpnBuilder { + openvpn_bin: OsString::from(openvpn_bin.as_ref()), + config: None, + } + } + + /// Sets what configuration file will be given to OpenVPN + pub fn config<P: AsRef<Path>>(&mut self, path: P) -> &mut Self { + self.config = Some(path.as_ref().to_path_buf()); + self + } + + /// Executes the OpenVPN process as a child process, returning a handle to it. + pub fn spawn(&mut self) -> io::Result<Child> { + let mut command = self.create_command(); + self.apply_settings(&mut command); + command.spawn() + } + + fn create_command(&mut self) -> Command { + let mut command = Command::new(&self.openvpn_bin); + command.env_clear() + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()); + command + } + + fn apply_settings(&self, command: &mut Command) { + if let Some(ref config) = self.config { + command.arg("--config").arg(config); + } + } +} diff --git a/tests/process.rs b/tests/process.rs new file mode 100644 index 0000000000..2281a9d990 --- /dev/null +++ b/tests/process.rs @@ -0,0 +1,36 @@ +extern crate talpid_core; + +mod util; + +use talpid_core::process::OpenVpnBuilder; + +#[cfg(target_os = "linux")] +#[test] +fn check_test_environment() { + use std::env; + let test_threads = env::var("RUST_TEST_THREADS"); + if !test_threads.is_ok() || test_threads.unwrap() != "1" { + panic!("Tests must be run with environment variable RUST_TEST_THREADS=1"); + } +} + +#[cfg(target_os = "linux")] +#[test] +fn openvpn_builder_starts_correct_process() { + let mut child = OpenVpnBuilder::new("echo").spawn().unwrap(); + let args = util::read_args_for_proc(child.id()); + + assert_eq!(vec!["echo"], args); + child.kill().unwrap(); +} + +#[cfg(target_os = "linux")] +#[test] +fn openvpn_builder_passes_config() { + let config_path = "/path/to/config".to_owned(); + let mut child = OpenVpnBuilder::new("echo").config(&config_path).spawn().unwrap(); + let args = util::read_args_for_proc(child.id()); + + assert!(args.contains(&config_path)); + child.kill().unwrap(); +} diff --git a/tests/util.rs b/tests/util.rs new file mode 100644 index 0000000000..8fe87e5783 --- /dev/null +++ b/tests/util.rs @@ -0,0 +1,16 @@ +use std::fs::File; +use std::io::Read; +use std::path::Path; + +pub fn read_file<P: AsRef<Path>>(path: P) -> String { + let mut string = String::new(); + let mut f = File::open(path).unwrap(); + f.read_to_string(&mut string).unwrap(); + string +} + +#[cfg(target_os = "linux")] +pub fn read_args_for_proc(pid: u32) -> Vec<String> { + let cmdline = read_file(format!("/proc/{}/cmdline", pid)); + cmdline.split_terminator('\0').map(String::from).collect() +} |
