Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/e2e_tests/fixture/src/vhost_user.rs
5394 views
1
// Copyright 2022 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
//! Provides `VhostUserBackend`, a fixture of a vhost-user backend process.
6
7
use std::process;
8
use std::process::Command;
9
use std::process::Stdio;
10
use std::thread;
11
use std::time::Duration;
12
13
use anyhow::Result;
14
use base::test_utils::check_can_sudo;
15
16
use crate::utils::find_crosvm_binary;
17
18
pub enum CmdType {
19
/// `crosvm device` command
20
Device,
21
/// `crosvm devices` command that is newer and supports sandboxing and multiple device
22
/// processes.
23
Devices,
24
}
25
26
impl CmdType {
27
fn to_subcommand(&self) -> &str {
28
match self {
29
// `crosvm device`
30
CmdType::Device => "device",
31
// `crosvm devices`
32
CmdType::Devices => "devices",
33
}
34
}
35
}
36
37
pub struct Config {
38
cmd_type: CmdType,
39
dev_name: String,
40
extra_args: Vec<String>,
41
}
42
43
impl Config {
44
pub fn new(cmd_type: CmdType, name: &str) -> Self {
45
Config {
46
cmd_type,
47
dev_name: name.to_string(),
48
extra_args: Default::default(),
49
}
50
}
51
52
/// Uses extra arguments for `crosvm (device|devices)`.
53
pub fn extra_args(mut self, args: Vec<String>) -> Self {
54
self.extra_args = args;
55
self
56
}
57
}
58
59
#[derive(Default)]
60
pub struct VhostUserBackend {
61
name: String,
62
process: Option<process::Child>,
63
}
64
65
impl VhostUserBackend {
66
pub fn new(cfg: Config) -> Result<Self> {
67
let cmd = Command::new(find_crosvm_binary());
68
Self::new_common(cmd, cfg)
69
}
70
71
/// Start up Vhost User Backend `sudo`.
72
pub fn new_sudo(cfg: Config) -> Result<Self> {
73
check_can_sudo();
74
75
let mut cmd = Command::new("sudo");
76
cmd.arg(find_crosvm_binary());
77
Self::new_common(cmd, cfg)
78
}
79
80
fn new_common(mut cmd: Command, cfg: Config) -> Result<Self> {
81
cmd.args([cfg.cmd_type.to_subcommand()]);
82
cmd.args(cfg.extra_args);
83
84
cmd.stdout(Stdio::piped());
85
cmd.stderr(Stdio::piped());
86
87
println!("$ {cmd:?}");
88
89
let process = Some(cmd.spawn()?);
90
// TODO(b/269174700): Wait for the VU socket to be available instead.
91
thread::sleep(Duration::from_millis(100));
92
93
Ok(Self {
94
name: cfg.dev_name,
95
process,
96
})
97
}
98
}
99
100
impl Drop for VhostUserBackend {
101
fn drop(&mut self) {
102
let output = self.process.take().unwrap().wait_with_output().unwrap();
103
104
// Print both the crosvm's stdout/stderr to stdout so that they'll be shown when the test
105
// is failed.
106
println!(
107
"VhostUserBackend {} stdout:\n{}",
108
self.name,
109
std::str::from_utf8(&output.stdout).unwrap()
110
);
111
println!(
112
"VhostUserBackend {} stderr:\n{}",
113
self.name,
114
std::str::from_utf8(&output.stderr).unwrap()
115
);
116
117
if !output.status.success() {
118
panic!(
119
"VhostUserBackend {} exited illegally: {}",
120
self.name, output.status
121
);
122
}
123
}
124
}
125
126