1#![cfg(target_os = "linux")]
11#![forbid(unsafe_code)]
12
13pub mod api;
14pub mod error;
15pub mod resolver;
16
17mod client;
18mod process_loop;
19mod worker;
20
21pub use client::GuestEmulationTransportClient;
22
23#[derive(Debug, thiserror::Error)]
25#[error("failed to initialize GET worker")]
26pub struct SpawnGetError(#[source] process_loop::FatalError);
27
28#[derive(Debug, thiserror::Error)]
32#[error("encountered fatal GET error")]
33pub struct FatalGetError(#[source] process_loop::FatalError);
34
35pub async fn spawn_get_worker(
38 driver: impl pal_async::driver::SpawnDriver,
39) -> Result<
40 (
41 GuestEmulationTransportClient,
42 pal_async::task::Task<Result<(), FatalGetError>>,
43 ),
44 SpawnGetError,
45> {
46 let (worker, task) = worker::GuestEmulationTransportWorker::new(driver)
47 .await
48 .map_err(SpawnGetError)?;
49 Ok((worker.new_client(), task))
50}
51
52#[cfg(any(feature = "test_utilities", test))]
53#[expect(missing_docs)]
54pub mod test_utilities {
55 use super::*;
56 use crate::worker::GuestEmulationTransportWorker;
57 use client::GuestEmulationTransportClient;
58 use get_protocol::ProtocolVersion;
59 use guest_emulation_device::IgvmAgentTestPlan;
60 use guest_emulation_device::test_utilities::TestGedClient;
61 use guest_emulation_device::test_utilities::TestGetResponses;
62 use mesh::Receiver;
63 use pal_async::task::Spawn;
64 use pal_async::task::Task;
65
66 pub const DEFAULT_SIZE: usize = 4194816; #[cfg_attr(not(test), expect(dead_code))]
69 pub struct TestGet {
70 pub client: GuestEmulationTransportClient,
71 pub(crate) gen_id: Receiver<[u8; 16]>,
72 pub(crate) guest_task: Task<Result<(), FatalGetError>>,
73 pub(crate) test_ged_client: TestGedClient,
74 }
75
76 pub async fn new_transport_pair(
82 spawn: impl Spawn,
83 ged_responses: Option<Vec<TestGetResponses>>,
84 version: ProtocolVersion,
85 guest_memory: Option<guestmem::GuestMemory>,
86 igvm_agent_script: Option<IgvmAgentTestPlan>,
87 ) -> TestGet {
88 let (host_vmbus, guest_vmbus) = vmbus_async::pipe::connected_message_pipes(
89 get_protocol::MAX_MESSAGE_SIZE + vmbus_ring::PAGE_SIZE,
90 );
91
92 let test_ged_client = guest_emulation_device::test_utilities::create_host_channel(
93 &spawn,
94 host_vmbus,
95 ged_responses,
96 version,
97 guest_memory,
98 igvm_agent_script,
99 );
100
101 let (guest_transport, guest_task) =
103 GuestEmulationTransportWorker::with_pipe(&spawn, guest_vmbus)
104 .await
105 .unwrap();
106
107 let client = guest_transport.new_client();
108
109 TestGet {
110 gen_id: client.take_generation_id_recv().await.unwrap(),
111 client,
112 guest_task,
113 test_ged_client,
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::test_utilities::*;
121 use super::worker::GuestEmulationTransportWorker;
122 use crate::process_loop::FatalError;
123 use get_protocol::ProtocolVersion;
124 use get_protocol::VmgsIoStatus;
125 use get_protocol::test_utilities::TEST_VMGS_SECTOR_SIZE;
126 use guest_emulation_device::test_utilities::Event;
127 use guest_emulation_device::test_utilities::TestGetResponses;
128 use pal_async::DefaultDriver;
129 use pal_async::async_test;
130 use pal_async::task::Spawn;
131 use test_with_tracing::test;
132 use vmbus_async::async_dgram::AsyncRecvExt;
133 use vmbus_async::async_dgram::AsyncSendExt;
134 use zerocopy::FromZeros;
135 use zerocopy::IntoBytes;
136
137 #[async_test]
138 async fn test_version_negotiation_failed(driver: DefaultDriver) {
139 let (mut host_vmbus, guest_vmbus) =
140 vmbus_async::pipe::connected_message_pipes(get_protocol::MAX_MESSAGE_SIZE);
141
142 let host_task = driver.spawn("host task", async move {
143 for protocol in [ProtocolVersion::NICKEL_REV2] {
144 let mut version_request = get_protocol::VersionRequest::new_zeroed();
145 let len = version_request.as_bytes().len();
146 assert_eq!(
147 len,
148 host_vmbus
149 .recv(version_request.as_mut_bytes())
150 .await
151 .unwrap()
152 );
153
154 assert_eq!(
155 version_request.message_header.message_id(),
156 get_protocol::HostRequests::VERSION
157 );
158 assert_eq!(version_request.version, protocol);
159
160 let version_response = get_protocol::VersionResponse::new(false);
162
163 host_vmbus.send(version_response.as_bytes()).await.unwrap();
164 }
165 });
166
167 let transport = GuestEmulationTransportWorker::with_pipe(driver, guest_vmbus).await;
168
169 match transport.unwrap_err() {
170 FatalError::VersionNegotiationFailed => {}
171 e => panic!("Wrong error type returned: {}", e),
172 }
173
174 host_task.await;
175 }
176
177 #[async_test]
178 async fn test_all_basic(driver: DefaultDriver) {
179 let time_zone = 5;
180 let utc = 3;
181
182 let time_response = TestGetResponses::new(Event::Response(
183 get_protocol::TimeResponse::new(0, utc, time_zone, false)
184 .as_bytes()
185 .to_vec(),
186 ));
187
188 let vmgs_device_info_response = TestGetResponses::new(Event::Response(
189 get_protocol::VmgsGetDeviceInfoResponse::new(VmgsIoStatus::SUCCESS, 1, 2, 3, 4)
190 .as_bytes()
191 .to_vec(),
192 ));
193
194 let flush_response = TestGetResponses::new(Event::Response(
195 get_protocol::VmgsFlushResponse::new(VmgsIoStatus::SUCCESS)
196 .as_bytes()
197 .to_vec(),
198 ));
199
200 let guest_state_protection = TestGetResponses::new(Event::Response(
201 get_protocol::GuestStateProtectionResponse {
202 message_header: get_protocol::HeaderGeneric::new(
203 get_protocol::HostRequests::GUEST_STATE_PROTECTION,
204 ),
205 encrypted_gsp: get_protocol::GspCiphertextContent::new_zeroed(),
206 decrypted_gsp: [get_protocol::GspCleartextContent::new_zeroed();
207 get_protocol::NUMBER_GSP as usize],
208 extended_status_flags: get_protocol::GspExtendedStatusFlags::new()
209 .with_state_refresh_request(true),
210 }
211 .as_bytes()
212 .to_vec(),
213 ));
214
215 let gsp_id = TestGetResponses::new(Event::Response(
216 get_protocol::GuestStateProtectionByIdResponse {
217 message_header: get_protocol::HeaderGeneric::new(
218 get_protocol::HostRequests::GUEST_STATE_PROTECTION_BY_ID,
219 ),
220 seed: get_protocol::GspCleartextContent::new_zeroed(),
221 extended_status_flags: get_protocol::GspExtendedStatusFlags::new()
222 .with_no_registry_file(true)
223 .with_state_refresh_request(true),
224 }
225 .as_bytes()
226 .to_vec(),
227 ));
228
229 let igvm_attest = TestGetResponses::new(Event::Response(
230 get_protocol::IgvmAttestResponse {
231 message_header: get_protocol::HeaderGeneric::new(
232 get_protocol::HostRequests::IGVM_ATTEST,
233 ),
234 length: 512,
235 }
236 .as_bytes()
237 .to_vec(),
238 ));
239
240 let ged_responses = vec![
241 time_response,
242 vmgs_device_info_response,
243 flush_response,
244 guest_state_protection,
245 gsp_id,
246 igvm_attest,
247 ];
248
249 let get = new_transport_pair(
250 driver,
251 Some(ged_responses),
252 ProtocolVersion::NICKEL_REV2,
253 None,
254 None,
255 )
256 .await;
257
258 let result = get.client.host_time().await;
259
260 assert_eq!(result.utc, utc);
261 assert_eq!(result.time_zone, time_zone);
262
263 let response = get.client.vmgs_get_device_info().await.unwrap();
264 assert_eq!(response.capacity, 1);
265 assert_eq!(response.bytes_per_logical_sector, 2);
266 assert_eq!(response.bytes_per_physical_sector, 3);
267 assert_eq!(response.maximum_transfer_size_bytes, 4);
268
269 get.client.vmgs_flush().await.unwrap();
270
271 let gsp_response = get
272 .client
273 .guest_state_protection_data(
274 [get_protocol::GspCiphertextContent::new_zeroed();
275 get_protocol::NUMBER_GSP as usize],
276 get_protocol::GspExtendedStatusFlags::new().with_state_refresh_request(true),
277 )
278 .await;
279
280 assert_eq!(
281 gsp_response.extended_status_flags,
282 get_protocol::GspExtendedStatusFlags::new().with_state_refresh_request(true)
283 );
284
285 let gsp_id_response = get
286 .client
287 .guest_state_protection_data_by_id()
288 .await
289 .unwrap();
290
291 assert_eq!(
292 gsp_id_response.extended_status_flags,
293 get_protocol::GspExtendedStatusFlags::new()
294 .with_no_registry_file(true)
295 .with_state_refresh_request(true)
296 );
297 }
298
299 #[async_test]
300 async fn test_vmgs_basic_write(driver: DefaultDriver) {
301 let vmgs_write_response = TestGetResponses::new(Event::Response(
302 get_protocol::VmgsWriteResponse::new(VmgsIoStatus::SUCCESS)
303 .as_bytes()
304 .to_vec(),
305 ));
306
307 let vmgs_read_response = TestGetResponses::new(Event::Response(
308 get_protocol::VmgsReadResponse::new(VmgsIoStatus::SUCCESS)
309 .as_bytes()
310 .to_vec(),
311 ));
312 let ged_responses = vec![vmgs_write_response, vmgs_read_response];
313
314 let get = new_transport_pair(
315 driver,
316 Some(ged_responses),
317 ProtocolVersion::NICKEL_REV2,
318 None,
319 None,
320 )
321 .await;
322 let buf = (0..512).map(|x| x as u8).collect::<Vec<u8>>();
323 get.client
324 .vmgs_write(0, buf.clone(), TEST_VMGS_SECTOR_SIZE)
325 .await
326 .unwrap();
327
328 let read_buf = get
329 .client
330 .vmgs_read(0, 1, TEST_VMGS_SECTOR_SIZE)
331 .await
332 .unwrap();
333 assert_eq!(read_buf, buf);
334 }
335
336 #[async_test]
337 async fn different_get_versions_nickel(driver: DefaultDriver) {
338 let json = get_protocol::dps_json::DevicePlatformSettingsV2Json {
340 v1: get_protocol::dps_json::HclDevicePlatformSettings {
341 com1: get_protocol::dps_json::HclUartSettings {
342 enable_port: true,
343 debugger_mode: false,
344 enable_vmbus_redirector: true,
345 },
346 com2: get_protocol::dps_json::HclUartSettings {
347 enable_port: false,
348 debugger_mode: false,
349 enable_vmbus_redirector: false,
350 },
351 enable_firmware_debugging: true,
352 enable_ipmi: true,
353 ..Default::default()
354 },
355 v2: get_protocol::dps_json::HclDevicePlatformSettingsV2 {
356 r#static: get_protocol::dps_json::HclDevicePlatformSettingsV2Static {
357 legacy_memory_map: true,
358 pxe_ip_v6: true,
359 ..Default::default()
360 },
361 ..Default::default()
362 },
363 };
364 let json_data = serde_json::to_vec(&json).unwrap();
365
366 let mut dps_response = get_protocol::DevicePlatformSettingsResponseV2Rev1::new_zeroed();
367 dps_response.message_header = get_protocol::HeaderGeneric::new(
368 get_protocol::HostRequests::DEVICE_PLATFORM_SETTINGS_V2_REV1,
369 );
370 dps_response.size = json_data.len() as u32;
371 dps_response.payload_state = get_protocol::LargePayloadState::END;
372
373 let device_platform_settings = TestGetResponses::new(Event::Response(
374 [dps_response.as_bytes().to_vec(), json_data].concat(),
375 ));
376
377 let ged_responses = vec![device_platform_settings];
378
379 let get = new_transport_pair(
380 driver,
381 Some(ged_responses),
382 ProtocolVersion::NICKEL_REV2,
383 None,
384 None,
385 )
386 .await;
387
388 let dps = get.client.device_platform_settings().await.unwrap();
389 assert_eq!(dps.general.tpm_enabled, false);
390 assert_eq!(dps.general.com1_enabled, true);
391 assert_eq!(dps.general.secure_boot_enabled, false);
392 assert!(dps.general.ipmi_enabled);
393
394 assert_eq!(dps.general.legacy_memory_map, true);
395 assert_eq!(dps.general.pxe_ip_v6, true);
396 assert_eq!(dps.general.nvdimm_count, 0);
397
398 assert_eq!(dps.general.generation_id, Some([0; 16]));
399 }
400
401 #[async_test]
402 async fn test_send_notification(driver: DefaultDriver) {
403 let vmgs_read_response = TestGetResponses::new(Event::Response(
406 get_protocol::VmgsReadResponse::new(VmgsIoStatus::SUCCESS)
407 .as_bytes()
408 .to_vec(),
409 ));
410 let ged_responses = vec![TestGetResponses::default(), vmgs_read_response];
411
412 let get = new_transport_pair(
413 driver,
414 Some(ged_responses),
415 ProtocolVersion::NICKEL_REV2,
416 None,
417 None,
418 )
419 .await;
420
421 get.client
422 .event_log(get_protocol::EventLogId::NO_BOOT_DEVICE);
423
424 let read_buf = get
425 .client
426 .vmgs_read(0, 1, TEST_VMGS_SECTOR_SIZE)
427 .await
428 .unwrap();
429
430 assert_eq!(read_buf[0], 5);
431 }
432
433 #[async_test]
434 async fn test_send_ipmi_sel_notification(driver: DefaultDriver) {
435 let record_id = 0x1234;
436 let record = [
437 0x34, 0x12, 0x02, 0x78, 0x56, 0x34, 0x12, 0x20, 0x00, 0x04, 0x01, 0x6f, 0xaa, 0xbb,
438 0xcc, 0xdd,
439 ];
440 let expected = get_protocol::IpmiSelNotification::new(record_id, record)
441 .as_bytes()
442 .to_vec();
443
444 let vmgs_read_response = TestGetResponses::new(Event::Response(
445 get_protocol::VmgsReadResponse::new(VmgsIoStatus::SUCCESS)
446 .as_bytes()
447 .to_vec(),
448 ));
449 let ged_responses = vec![TestGetResponses::default(), vmgs_read_response];
450
451 let get = new_transport_pair(
452 driver,
453 Some(ged_responses),
454 ProtocolVersion::NICKEL_REV2,
455 None,
456 None,
457 )
458 .await;
459
460 get.client.ipmi_sel(record_id, record);
461
462 let read_buf = get
463 .client
464 .vmgs_read(0, 1, TEST_VMGS_SECTOR_SIZE)
465 .await
466 .unwrap();
467
468 assert_eq!(&read_buf[..expected.len()], expected.as_slice());
469 }
470
471 #[async_test]
472 async fn notification_in_between_requests(driver: DefaultDriver) {
473 let time_response = TestGetResponses::new(Event::Response(
474 get_protocol::UpdateGenerationId::new([1; 16])
475 .as_bytes()
476 .to_vec(),
477 ))
478 .add_response(Event::Response(
479 get_protocol::TimeResponse::new(0, 1, 2, false)
480 .as_bytes()
481 .to_vec(),
482 ));
483
484 let ged_responses = vec![time_response];
485
486 let mut get = new_transport_pair(
487 driver,
488 Some(ged_responses),
489 ProtocolVersion::NICKEL_REV2,
490 None,
491 None,
492 )
493 .await;
494
495 let result = get.client.host_time().await;
496
497 let gen_id = get.gen_id.recv().await.unwrap();
498
499 assert_eq!(gen_id, [1; 16]);
500
501 assert_eq!(result.utc, 1);
502 assert_eq!(result.time_zone, 2);
503 }
504
505 #[async_test]
506 async fn host_send_multiple_response(driver: DefaultDriver) {
507 let time_response = TestGetResponses::new(Event::Response(
508 get_protocol::TimeResponse::new(0, 1, 2, false)
509 .as_bytes()
510 .to_vec(),
511 ))
512 .add_response(Event::Response(
513 get_protocol::TimeResponse::new(0, 1, 2, false)
514 .as_bytes()
515 .to_vec(),
516 ));
517
518 let ged_responses = vec![time_response];
519
520 let get = new_transport_pair(
521 driver,
522 Some(ged_responses),
523 ProtocolVersion::NICKEL_REV2,
524 None,
525 None,
526 )
527 .await;
528
529 let result = get.client.host_time().await;
530
531 assert_eq!(result.utc, 1);
532 assert_eq!(result.time_zone, 2);
533
534 assert!(futures::poll!(get.guest_task).is_pending());
536 }
537
538 #[async_test]
539 async fn host_send_mismatched_multiple_response(driver: DefaultDriver) {
540 let responses = TestGetResponses::new(Event::Response(
541 get_protocol::VpciDeviceControlResponse::new(
542 get_protocol::VpciDeviceControlStatus::SUCCESS,
543 )
544 .as_bytes()
545 .to_vec(),
546 ))
547 .add_response(Event::Response(
548 get_protocol::TimeResponse::new(0, 1, 2, false)
549 .as_bytes()
550 .to_vec(),
551 ))
552 .add_response(Event::Response(
553 get_protocol::VpciDeviceControlResponse::new(
554 get_protocol::VpciDeviceControlStatus::SUCCESS,
555 )
556 .as_bytes()
557 .to_vec(),
558 ));
559
560 let ged_responses = vec![responses];
561
562 let get = new_transport_pair(
563 driver,
564 Some(ged_responses),
565 ProtocolVersion::NICKEL_REV2,
566 None,
567 None,
568 )
569 .await;
570
571 let time_req = get.client.host_time();
572
573 let result = time_req.await;
574 assert_eq!(result.utc, 1);
575 assert_eq!(result.time_zone, 2);
576 }
577
578 #[async_test]
579 async fn host_send_mismatched_multiple_request_response(driver: DefaultDriver) {
580 let responses = TestGetResponses::new(Event::Response(
581 get_protocol::TimeResponse::new(0, 1, 2, false)
582 .as_bytes()
583 .to_vec(),
584 ))
585 .add_response(Event::Response(
586 get_protocol::VpciDeviceControlResponse::new(
587 get_protocol::VpciDeviceControlStatus::SUCCESS,
588 )
589 .as_bytes()
590 .to_vec(),
591 ))
592 .add_response(Event::Response(
593 get_protocol::TimeResponse::new(0, 1, 2, false)
594 .as_bytes()
595 .to_vec(),
596 ))
597 .add_response(Event::Response(
598 get_protocol::VpciDeviceControlResponse::new(
599 get_protocol::VpciDeviceControlStatus::SUCCESS,
600 )
601 .as_bytes()
602 .to_vec(),
603 ));
604
605 let ged_responses = vec![responses];
606
607 let get = new_transport_pair(
608 driver,
609 Some(ged_responses),
610 ProtocolVersion::NICKEL_REV2,
611 None,
612 None,
613 )
614 .await;
615
616 let time_req = get.client.host_time();
617 let mut vpci_req = std::pin::pin!(get.client.offer_vpci_device(guid::Guid::new_random()));
618
619 assert!(futures::poll!(&mut vpci_req).is_pending());
621
622 let result = time_req.await;
624 assert_eq!(result.utc, 1);
625 assert_eq!(result.time_zone, 2);
626
627 vpci_req.await.unwrap();
629 }
630
631 #[async_test]
632 async fn host_send_incorrect_response(driver: DefaultDriver) {
633 let time_response = TestGetResponses::new(Event::Response(
634 get_protocol::TimeResponse::new(0, 1, 2, false)
635 .as_bytes()
636 .to_vec(),
637 ));
638
639 let ged_responses = vec![time_response];
640
641 let get = new_transport_pair(
642 driver.clone(),
643 Some(ged_responses),
644 ProtocolVersion::NICKEL_REV2,
645 None,
646 None,
647 )
648 .await;
649
650 let _never_returns = driver.spawn("badness", async move {
651 let _ = get.client.vmgs_get_device_info().await;
652 });
653
654 let internal_error = get.guest_task.await;
655
656 assert!(matches!(
657 internal_error.map_err(|x| x.0),
658 Err(FatalError::ResponseHeaderMismatchId(_, _))
659 ));
660 }
661
662 #[async_test]
663 async fn test_send_halt_reason(driver: DefaultDriver) {
664 let power_off_check =
665 TestGetResponses::new(Event::Halt(power_resources::PowerRequest::PowerOff));
666 let reset_check = TestGetResponses::new(Event::Halt(power_resources::PowerRequest::Reset));
667
668 let vmgs_device_info_response = TestGetResponses::new(Event::Response(
669 get_protocol::VmgsGetDeviceInfoResponse::new(VmgsIoStatus::SUCCESS, 1, 2, 3, 4)
670 .as_bytes()
671 .to_vec(),
672 ));
673
674 let ged_responses = vec![power_off_check, reset_check, vmgs_device_info_response];
675
676 let get = new_transport_pair(
677 driver,
678 Some(ged_responses),
679 ProtocolVersion::NICKEL_REV2,
680 None,
681 None,
682 )
683 .await;
684
685 get.client.send_power_off();
686 get.client.send_reset();
687
688 let response = get.client.vmgs_get_device_info().await.unwrap();
693 assert_eq!(response.capacity, 1);
694 assert_eq!(response.bytes_per_logical_sector, 2);
695 assert_eq!(response.bytes_per_physical_sector, 3);
696 assert_eq!(response.maximum_transfer_size_bytes, 4);
697 }
698
699 #[async_test]
700 async fn test_send_multiple_host_request(driver: DefaultDriver) {
701 let time_response = TestGetResponses::new(Event::Response(
702 get_protocol::TimeResponse::new(0, 1, 2, false)
703 .as_bytes()
704 .to_vec(),
705 ));
706
707 let ged_responses = vec![
708 time_response.clone(),
709 time_response.clone(),
710 time_response.clone(),
711 time_response.clone(),
712 time_response.clone(),
713 time_response,
714 ];
715
716 let get = new_transport_pair(
717 driver.clone(),
718 Some(ged_responses),
719 ProtocolVersion::NICKEL_REV2,
720 None,
721 None,
722 )
723 .await;
724
725 let mut tasks = Vec::new();
726
727 for i in 0..6 {
728 let client = get.client.clone();
729 tasks.push(driver.spawn(
730 format!("task {}", i),
731 async move { client.host_time().await },
732 ));
733 }
734
735 for task in tasks {
739 let time = task.await;
740 assert_eq!(time.utc, 1);
741 assert_eq!(time.time_zone, 2);
742 }
743 }
744 #[async_test]
745 async fn test_vpci_control(driver: DefaultDriver) {
746 let bus_id = guid::Guid::new_random();
747 let vpci_offer_response = TestGetResponses::new(Event::Response(
748 get_protocol::VpciDeviceControlResponse::new(
749 get_protocol::VpciDeviceControlStatus::SUCCESS,
750 )
751 .as_bytes()
752 .to_vec(),
753 ));
754
755 let vpci_revoke_response = TestGetResponses::new(Event::Response(
756 get_protocol::VpciDeviceControlResponse::new(
757 get_protocol::VpciDeviceControlStatus::SUCCESS,
758 )
759 .as_bytes()
760 .to_vec(),
761 ));
762
763 let vpci_bind_response = TestGetResponses::new(Event::Response(
764 get_protocol::VpciDeviceBindingChangeResponse::new(
765 bus_id,
766 get_protocol::VpciDeviceControlStatus::SUCCESS,
767 )
768 .as_bytes()
769 .to_vec(),
770 ));
771
772 let vpci_unbind_response = TestGetResponses::new(Event::Response(
773 get_protocol::VpciDeviceBindingChangeResponse::new(
774 bus_id,
775 get_protocol::VpciDeviceControlStatus::SUCCESS,
776 )
777 .as_bytes()
778 .to_vec(),
779 ));
780
781 let ged_responses = vec![
782 vpci_offer_response,
783 vpci_revoke_response,
784 vpci_bind_response,
785 vpci_unbind_response,
786 ];
787
788 let get = new_transport_pair(
789 driver,
790 Some(ged_responses),
791 ProtocolVersion::NICKEL_REV2,
792 None,
793 None,
794 )
795 .await;
796 get.client.offer_vpci_device(bus_id).await.unwrap();
797 get.client.revoke_vpci_device(bus_id).await.unwrap();
798 get.client
799 .report_vpci_device_binding_state(bus_id, true)
800 .await
801 .unwrap();
802 get.client
803 .report_vpci_device_binding_state(bus_id, false)
804 .await
805 .unwrap();
806
807 get.client.connect_to_vpci_event_source(bus_id).await;
808 get.client.disconnect_from_vpci_event_source(bus_id);
809 }
810
811 #[ignore]
813 #[async_test]
814 async fn test_save_guest_vtl2_state(driver: DefaultDriver) {
815 let mut get =
816 new_transport_pair(driver, None, ProtocolVersion::NICKEL_REV2, None, None).await;
817
818 get.test_ged_client.test_save_guest_vtl2_state().await;
819 }
820
821 #[async_test]
822 async fn test_load_firmware(driver: DefaultDriver) {
823 let get = new_transport_pair(driver, None, ProtocolVersion::NICKEL_REV2, None, None).await;
827
828 let entry_offset = get.client.load_firmware(0x0107).await.unwrap();
829 assert_eq!(entry_offset, 0);
830 }
831}