Skip to content

Commit 50e0b9b

Browse files
api_server: added unit tests for generate response
Also, removed 2 unused errors from DriveError and moved net_util dependency to dev-dependencies as it was only used in tests. Signed-off-by: Andreea Florescu <[email protected]>
1 parent 9513575 commit 50e0b9b

File tree

5 files changed

+235
-5
lines changed

5 files changed

+235
-5
lines changed

api_server/Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ data_model = { path = "../data_model" }
1818
fc_util = { path = "../fc_util" }
1919
jailer = { path = "../jailer" }
2020
logger = { path = "../logger" }
21-
net_util = { path = "../net_util" }
2221
sys_util = { path = "../sys_util" }
2322
vmm = { path = "../vmm" }
23+
24+
[dev-dependencies]
25+
devices = { path = "../devices" }
26+
kernel_loader = { path = "../kernel_loader" }
27+
memory_model = { path = "../memory_model" }
28+
net_util = { path = "../net_util" }
29+
x86_64 = { path = "../x86_64" }

api_server/src/http_service.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,9 @@ fn describe(method: &Method, path: &String, body: &String) -> String {
576576

577577
#[cfg(test)]
578578
mod tests {
579+
extern crate net_util;
580+
581+
use self::net_util::MacAddr;
579582
use super::*;
580583

581584
use serde_json::{Map, Value};
@@ -585,7 +588,6 @@ mod tests {
585588
use futures::sync::oneshot;
586589
use hyper::header::{ContentType, Headers};
587590
use hyper::Body;
588-
use net_util::MacAddr;
589591
use vmm::vmm_config::DeviceState;
590592
use vmm::VmmAction;
591593

api_server/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ extern crate jailer;
1414
extern crate vmm;
1515
#[macro_use]
1616
extern crate logger;
17-
extern crate net_util;
1817
extern crate sys_util;
1918

2019
mod http_service;

api_server/src/request/mod.rs

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,225 @@ impl PartialEq for ParsedRequest {
9797
}
9898
}
9999
}
100+
101+
#[cfg(test)]
102+
mod tests {
103+
extern crate devices;
104+
extern crate kernel_loader;
105+
extern crate memory_model;
106+
extern crate net_util;
107+
extern crate x86_64;
108+
109+
use self::devices::virtio::net::Error as VirtioNetError;
110+
use self::memory_model::GuestMemoryError;
111+
use self::net_util::TapError;
112+
use super::*;
113+
114+
use data_model::vm::{DriveError, VmConfig, VmConfigError};
115+
use sys_util;
116+
use vmm::vmm_config::boot_source::BootSourceConfigError;
117+
use vmm::vmm_config::instance_info::StartMicrovmError;
118+
use vmm::vmm_config::logger::LoggerConfigError;
119+
use vmm::vmm_config::net::NetworkInterfaceError;
120+
121+
use futures::{Future, Stream};
122+
use hyper::{Body, Response};
123+
use serde_json;
124+
use std;
125+
126+
fn get_body(
127+
response: Response<Body>,
128+
) -> std::result::Result<serde_json::Value, serde_json::Error> {
129+
let body = response
130+
.body()
131+
.map_err(|_| ())
132+
.fold(vec![], |mut acc, chunk| {
133+
acc.extend_from_slice(&chunk);
134+
Ok(acc)
135+
}).and_then(|v| String::from_utf8(v).map_err(|_| ()));
136+
serde_json::from_str::<Value>(body.wait().unwrap().as_ref())
137+
}
138+
139+
fn check_error_response(error: VmmActionError, status_code: StatusCode) {
140+
let hyper_resp = Err(error).generate_response();
141+
assert_eq!(hyper_resp.status(), status_code);
142+
assert!(get_body(hyper_resp).is_ok());
143+
}
144+
145+
#[test]
146+
fn test_generate_response() {
147+
// Test OK Empty response from VMM.
148+
let vmm_resp = Ok(VmmData::Empty);
149+
let hyper_resp = vmm_resp.generate_response();
150+
assert_eq!(hyper_resp.status(), StatusCode::NoContent);
151+
// assert that the body is empty. When the JSON is empty, serde returns and EOF error.
152+
let body_err = get_body(hyper_resp).unwrap_err();
153+
assert_eq!(
154+
body_err.to_string(),
155+
"EOF while parsing a value at line 1 column 0"
156+
);
157+
158+
// Test OK response from VMM that contains the Machine Configuration.
159+
let vmm_resp = Ok(VmmData::MachineConfiguration(VmConfig::default()));
160+
let hyper_resp = vmm_resp.generate_response();
161+
assert_eq!(hyper_resp.status(), StatusCode::Ok);
162+
let vm_config_json = r#"{
163+
"vcpu_count": 1,
164+
"mem_size_mib": 128,
165+
"ht_enabled": false,
166+
"cpu_template": "Uninitialized"
167+
}"#;
168+
let vm_config_json: serde_json::Value = serde_json::from_str(vm_config_json).unwrap();
169+
assert_eq!(get_body(hyper_resp).unwrap(), vm_config_json);
170+
171+
// Tests Error Cases
172+
// Tests for BootSource Errors.
173+
let vmm_resp =
174+
VmmActionError::BootSource(ErrorKind::User, BootSourceConfigError::InvalidKernelPath);
175+
check_error_response(vmm_resp, StatusCode::BadRequest);
176+
let vmm_resp = VmmActionError::BootSource(
177+
ErrorKind::User,
178+
BootSourceConfigError::InvalidKernelCommandLine,
179+
);
180+
check_error_response(vmm_resp, StatusCode::BadRequest);
181+
let vmm_resp = VmmActionError::BootSource(
182+
ErrorKind::User,
183+
BootSourceConfigError::UpdateNotAllowedPostBoot,
184+
);
185+
check_error_response(vmm_resp, StatusCode::BadRequest);
186+
187+
// Tests for DriveConfig Errors.
188+
let vmm_resp =
189+
VmmActionError::DriveConfig(ErrorKind::User, DriveError::CannotOpenBlockDevice);
190+
check_error_response(vmm_resp, StatusCode::BadRequest);
191+
let vmm_resp =
192+
VmmActionError::DriveConfig(ErrorKind::User, DriveError::InvalidBlockDeviceID);
193+
check_error_response(vmm_resp, StatusCode::BadRequest);
194+
let vmm_resp =
195+
VmmActionError::DriveConfig(ErrorKind::User, DriveError::InvalidBlockDevicePath);
196+
check_error_response(vmm_resp, StatusCode::BadRequest);
197+
let vmm_resp =
198+
VmmActionError::DriveConfig(ErrorKind::User, DriveError::BlockDevicePathAlreadyExists);
199+
check_error_response(vmm_resp, StatusCode::BadRequest);
200+
let vmm_resp =
201+
VmmActionError::DriveConfig(ErrorKind::User, DriveError::OperationNotAllowedPreBoot);
202+
check_error_response(vmm_resp, StatusCode::BadRequest);
203+
let vmm_resp =
204+
VmmActionError::DriveConfig(ErrorKind::User, DriveError::RootBlockDeviceAlreadyAdded);
205+
check_error_response(vmm_resp, StatusCode::BadRequest);
206+
let vmm_resp =
207+
VmmActionError::DriveConfig(ErrorKind::User, DriveError::UpdateNotAllowedPostBoot);
208+
check_error_response(vmm_resp, StatusCode::BadRequest);
209+
210+
// Tests for Logger Errors.
211+
let vmm_resp = VmmActionError::Logger(
212+
ErrorKind::User,
213+
LoggerConfigError::InitializationFailure(
214+
"Could not open logging fifo: dummy".to_string(),
215+
),
216+
);
217+
check_error_response(vmm_resp, StatusCode::BadRequest);
218+
219+
// Tests for MachineConfig Errors.
220+
let vmm_resp =
221+
VmmActionError::MachineConfig(ErrorKind::User, VmConfigError::InvalidVcpuCount);
222+
check_error_response(vmm_resp, StatusCode::BadRequest);
223+
let vmm_resp =
224+
VmmActionError::MachineConfig(ErrorKind::User, VmConfigError::InvalidMemorySize);
225+
check_error_response(vmm_resp, StatusCode::BadRequest);
226+
227+
// Tests for NetworkConfig Errors.
228+
let vmm_resp = VmmActionError::NetworkConfig(
229+
ErrorKind::User,
230+
NetworkInterfaceError::OpenTap(TapError::OpenTun(std::io::Error::from_raw_os_error(
231+
22,
232+
))),
233+
);
234+
check_error_response(vmm_resp, StatusCode::BadRequest);
235+
let vmm_resp = VmmActionError::NetworkConfig(
236+
ErrorKind::User,
237+
NetworkInterfaceError::GuestMacAddressInUse(String::from("12:34:56:78:9a:bc")),
238+
);
239+
check_error_response(vmm_resp, StatusCode::BadRequest);
240+
let vmm_resp = VmmActionError::NetworkConfig(
241+
ErrorKind::User,
242+
NetworkInterfaceError::UpdateNotAllowedPostBoot,
243+
);
244+
check_error_response(vmm_resp, StatusCode::BadRequest);
245+
246+
// Tests for MicrovmStart Errors.
247+
// RegisterBlockDevice, RegisterNetDevice, and LegacyIOBus cannot be tested because the
248+
// device manager is a private module in the vmm crate.
249+
// ConfigureVm, Vcpu, VcpuConfigure, and VmConfigure cannot be tested because vstate is a
250+
// private module in the vmm crate.
251+
let vmm_resp =
252+
VmmActionError::StartMicrovm(ErrorKind::User, StartMicrovmError::MicroVMAlreadyRunning);
253+
check_error_response(vmm_resp, StatusCode::BadRequest);
254+
let vmm_resp =
255+
VmmActionError::StartMicrovm(ErrorKind::User, StartMicrovmError::MissingKernelConfig);
256+
check_error_response(vmm_resp, StatusCode::BadRequest);
257+
let vmm_resp = VmmActionError::StartMicrovm(
258+
ErrorKind::Internal,
259+
StartMicrovmError::GuestMemory(GuestMemoryError::MemoryNotInitialized),
260+
);
261+
check_error_response(vmm_resp, StatusCode::InternalServerError);
262+
let vmm_resp = VmmActionError::StartMicrovm(
263+
ErrorKind::Internal,
264+
StartMicrovmError::KernelCmdline(String::from("dummy error.")),
265+
);
266+
check_error_response(vmm_resp, StatusCode::InternalServerError);
267+
let vmm_resp = VmmActionError::StartMicrovm(
268+
ErrorKind::Internal,
269+
StartMicrovmError::CreateBlockDevice(sys_util::Error::new(22)),
270+
);
271+
check_error_response(vmm_resp, StatusCode::InternalServerError);
272+
let vmm_resp = VmmActionError::StartMicrovm(
273+
ErrorKind::User,
274+
StartMicrovmError::OpenBlockDevice(std::io::Error::from_raw_os_error(22)),
275+
);
276+
check_error_response(vmm_resp, StatusCode::BadRequest);
277+
let vmm_resp = VmmActionError::StartMicrovm(
278+
ErrorKind::Internal,
279+
StartMicrovmError::CreateRateLimiter(std::io::Error::from_raw_os_error(22)),
280+
);
281+
check_error_response(vmm_resp, StatusCode::InternalServerError);
282+
let vmm_resp = VmmActionError::StartMicrovm(
283+
ErrorKind::Internal,
284+
StartMicrovmError::NetDeviceNotConfigured,
285+
);
286+
check_error_response(vmm_resp, StatusCode::InternalServerError);
287+
let vmm_resp = VmmActionError::StartMicrovm(
288+
ErrorKind::Internal,
289+
StartMicrovmError::CreateNetDevice(VirtioNetError::TapOpen(TapError::OpenTun(
290+
std::io::Error::from_raw_os_error(22),
291+
))),
292+
);
293+
check_error_response(vmm_resp, StatusCode::InternalServerError);
294+
let vmm_resp = VmmActionError::StartMicrovm(
295+
ErrorKind::Internal,
296+
StartMicrovmError::DeviceVmRequest(sys_util::Error::new(22)),
297+
);
298+
check_error_response(vmm_resp, StatusCode::InternalServerError);
299+
let vmm_resp = VmmActionError::StartMicrovm(
300+
ErrorKind::Internal,
301+
StartMicrovmError::ConfigureSystem(x86_64::Error::E820Configuration),
302+
);
303+
check_error_response(vmm_resp, StatusCode::InternalServerError);
304+
let vmm_resp = VmmActionError::StartMicrovm(
305+
ErrorKind::User,
306+
StartMicrovmError::Loader(kernel_loader::Error::BigEndianElfOnLittle),
307+
);
308+
check_error_response(vmm_resp, StatusCode::BadRequest);
309+
let vmm_resp =
310+
VmmActionError::StartMicrovm(ErrorKind::Internal, StartMicrovmError::EventFd);
311+
check_error_response(vmm_resp, StatusCode::InternalServerError);
312+
let vmm_resp =
313+
VmmActionError::StartMicrovm(ErrorKind::Internal, StartMicrovmError::RegisterEvent);
314+
check_error_response(vmm_resp, StatusCode::InternalServerError);
315+
let vmm_resp = VmmActionError::StartMicrovm(
316+
ErrorKind::Internal,
317+
StartMicrovmError::VcpuSpawn(std::io::Error::from_raw_os_error(11)),
318+
);
319+
check_error_response(vmm_resp, StatusCode::InternalServerError);
320+
}
321+
}

api_server/src/request/net.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,16 @@ impl IntoParsedRequest for NetworkInterfaceBody {
3030

3131
#[cfg(test)]
3232
mod tests {
33+
extern crate net_util;
34+
35+
use self::net_util::MacAddr;
3336
use super::*;
3437

3538
use serde_json;
3639

3740
use data_model::vm::RateLimiterDescription;
3841
use vmm::vmm_config::DeviceState;
3942

40-
use net_util::MacAddr;
41-
4243
#[test]
4344
fn test_netif_into_parsed_request() {
4445
let netif = NetworkInterfaceBody {

0 commit comments

Comments
 (0)