@@ -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+ }
0 commit comments