summary refs log tree commit diff
path: root/tests/plugins.rs
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2018-01-16 17:59:03 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-02-09 19:03:16 -0800
commit8864cb0f3a9184e2420bbad64c43fcddf161e427 (patch)
treef15bf8191d19c270d346194515fb47de870a43cc /tests/plugins.rs
parentde01b8b32f1391acfd298c977bcd20a85d020ebb (diff)
downloadcrosvm-8864cb0f3a9184e2420bbad64c43fcddf161e427.tar
crosvm-8864cb0f3a9184e2420bbad64c43fcddf161e427.tar.gz
crosvm-8864cb0f3a9184e2420bbad64c43fcddf161e427.tar.bz2
crosvm-8864cb0f3a9184e2420bbad64c43fcddf161e427.tar.lz
crosvm-8864cb0f3a9184e2420bbad64c43fcddf161e427.tar.xz
crosvm-8864cb0f3a9184e2420bbad64c43fcddf161e427.tar.zst
crosvm-8864cb0f3a9184e2420bbad64c43fcddf161e427.zip
crosvm: add support for plugin process
The plugin process is good for running a VM that depends substantially
on devices that aren't implemented inside of crosvm.

TEST=cargo build --features plugin; ./build_test
BUG=chromium:800626

Change-Id: I7b4f656563742cd0bedc837205dd1240d497941d
Reviewed-on: https://chromium-review.googlesource.com/869357
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'tests/plugins.rs')
-rw-r--r--tests/plugins.rs115
1 files changed, 115 insertions, 0 deletions
diff --git a/tests/plugins.rs b/tests/plugins.rs
new file mode 100644
index 0000000..349634d
--- /dev/null
+++ b/tests/plugins.rs
@@ -0,0 +1,115 @@
+// Copyright 2017 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#![cfg(feature = "plugin")]
+
+extern crate rand;
+
+use rand::{thread_rng, Rng};
+
+use std::ffi::OsString;
+use std::fs::remove_file;
+use std::io::Write;
+use std::env::{current_exe, var_os};
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+use std::thread::sleep;
+use std::time::Duration;
+
+struct RemovePath(PathBuf);
+impl Drop for RemovePath {
+    fn drop(&mut self) {
+        if let Err(e) = remove_file(&self.0) {
+            eprintln!("failed to remove path: {:?}", e);
+        }
+    }
+}
+
+fn get_crosvm_path() -> PathBuf {
+    let mut crosvm_path = current_exe()
+        .ok()
+        .map(|mut path| {
+                 path.pop();
+                 if path.ends_with("deps") {
+                     path.pop();
+                 }
+                 path
+             })
+        .expect("failed to get crosvm binary directory");
+    crosvm_path.push("crosvm");
+    crosvm_path
+}
+
+fn build_plugin(src: &str) -> RemovePath {
+    let mut out_bin = PathBuf::from("target");
+    let mut libcrosvm_plugin = get_crosvm_path();
+    libcrosvm_plugin.set_file_name("libcrosvm_plugin.so");
+    out_bin.push(thread_rng()
+                     .gen_ascii_chars()
+                     .take(10)
+                     .collect::<String>());
+    let mut child = Command::new(var_os("CC").unwrap_or(OsString::from("cc")))
+        .args(&["-Icrosvm_plugin", "-pthread", "-o"])
+        .arg(&out_bin)
+        .arg(libcrosvm_plugin)
+        .args(&["-xc", "-"])
+        .stdin(Stdio::piped())
+        .spawn()
+        .expect("failed to spawn compiler");
+    {
+        let stdin = child.stdin.as_mut().expect("failed to open stdin");
+        stdin
+            .write_all(src.as_bytes())
+            .expect("failed to write source to stdin");
+    }
+
+    let status = child.wait().expect("failed to wait for compiler");
+    assert!(status.success(), "failed to build plugin");
+
+    RemovePath(PathBuf::from(out_bin))
+}
+
+fn run_plugin(bin_path: &Path) {
+    let mut child = Command::new(get_crosvm_path())
+        .args(&["run", "-c", "1", "--plugin"])
+        .arg(bin_path)
+        .spawn()
+        .expect("failed to spawn crosvm");
+    for _ in 0..12 {
+        match child.try_wait().expect("failed to wait for crosvm") {
+            Some(status) => {
+                assert!(status.success());
+                return;
+            }
+            None => sleep(Duration::from_millis(100)),
+        }
+    }
+    child.kill().expect("failed to kill crosvm");
+    panic!("crosvm process has timed out");
+}
+
+fn test_plugin(src: &str) {
+    let bin_path = build_plugin(src);
+    run_plugin(&bin_path.0);
+}
+
+#[test]
+fn test_adder() {
+    test_plugin(include_str!("plugin_adder.c"));
+}
+
+#[test]
+fn test_dirty_log() {
+    test_plugin(include_str!("plugin_dirty_log.c"));
+}
+
+#[test]
+fn test_ioevent() {
+    test_plugin(include_str!("plugin_ioevent.c"));
+}
+
+#[test]
+fn test_irqfd() {
+    test_plugin(include_str!("plugin_irqfd.c"));
+}