xref: /aosp_15_r20/external/crosvm/e2e_tests/tests/block.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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 //! Testing virtio-block.
6 
7 #![cfg(any(target_os = "android", target_os = "linux"))]
8 
9 use std::time;
10 
11 use fixture::utils::create_vu_block_config;
12 use fixture::utils::prepare_disk_img;
13 use fixture::utils::DEFAULT_BLOCK_SIZE;
14 use fixture::vhost_user::CmdType;
15 use fixture::vhost_user::VhostUserBackend;
16 use fixture::vm::Config as VmConfig;
17 use fixture::vm::TestVm;
18 use tempfile::NamedTempFile;
19 
20 /// Tests virtio-blk device is mountable.
21 // TODO(b/243127498): Add tests for write and sync operations.
22 #[test]
test_mount_block()23 fn test_mount_block() {
24     let config = VmConfig::new();
25     mount_block(config);
26 }
27 
28 #[test]
test_mount_block_disable_sandbox()29 fn test_mount_block_disable_sandbox() {
30     let config = VmConfig::new().disable_sandbox();
31     mount_block(config);
32 }
33 
mount_block(config: VmConfig)34 fn mount_block(config: VmConfig) {
35     let disk = prepare_disk_img();
36     let disk_path = disk.path().to_str().unwrap();
37     println!("disk={disk_path}");
38 
39     let config = config.extra_args(vec!["--block".to_string(), format!("{},ro", disk_path)]);
40     let mut vm = TestVm::new(config).unwrap();
41     assert_eq!(
42         vm.exec_in_guest("mount -t ext4 /dev/vdb /mnt && echo 42")
43             .unwrap()
44             .stdout
45             .trim(),
46         "42"
47     );
48 }
49 
50 /// Tests `crosvm disk resize` works.
51 #[test]
test_resize()52 fn test_resize() {
53     let config = VmConfig::new();
54     resize(config);
55 }
56 
57 #[test]
test_resize_disable_sandbox()58 fn test_resize_disable_sandbox() {
59     let config = VmConfig::new().disable_sandbox();
60     resize(config);
61 }
62 
resize(config: VmConfig)63 fn resize(config: VmConfig) {
64     let disk = prepare_disk_img();
65     let disk_path = disk.path().to_str().unwrap().to_string();
66     println!("disk={disk_path}");
67 
68     let config = config.extra_args(vec!["--block".to_string(), disk_path]);
69     let mut vm = TestVm::new(config).unwrap();
70 
71     // Check the initial block device size.
72     assert_eq!(
73         vm.exec_in_guest("blockdev --getsize64 /dev/vdb")
74             .unwrap()
75             .stdout
76             .trim()
77             .parse::<u64>()
78             .unwrap(),
79         DEFAULT_BLOCK_SIZE
80     );
81 
82     let new_size = DEFAULT_BLOCK_SIZE * 2;
83 
84     // The index of the disk to resize.
85     let disk_index = 1;
86 
87     vm.disk(vec![
88         "resize".to_string(),
89         disk_index.to_string(),
90         new_size.to_string(),
91     ])
92     .expect("Disk resizing command failed");
93 
94     // Allow block device size to be updated within 500ms
95     let now = time::Instant::now();
96 
97     while now.elapsed() <= time::Duration::from_millis(500) {
98         if vm
99             .exec_in_guest("blockdev --getsize64 /dev/vdb")
100             .unwrap()
101             .stdout
102             .trim()
103             .parse::<u64>()
104             .unwrap()
105             == new_size
106         {
107             return;
108         }
109     }
110     // Check the new block device size.
111     assert_eq!(
112         vm.exec_in_guest("blockdev --getsize64 /dev/vdb")
113             .unwrap()
114             .stdout
115             .trim()
116             .parse::<u64>()
117             .unwrap(),
118         new_size
119     );
120 }
121 
run_vhost_user_test(cmd_type: CmdType, config: VmConfig)122 fn run_vhost_user_test(cmd_type: CmdType, config: VmConfig) {
123     let socket = NamedTempFile::new().unwrap();
124     let disk = prepare_disk_img();
125 
126     let vu_config = create_vu_block_config(cmd_type, socket.path(), disk.path());
127     let _vu_device = VhostUserBackend::new(vu_config).unwrap();
128 
129     let config = config.with_vhost_user("block", socket.path());
130     let mut vm = TestVm::new(config).unwrap();
131     assert_eq!(
132         vm.exec_in_guest("mount -t ext4 /dev/vdb /mnt && echo 42")
133             .unwrap()
134             .stdout
135             .trim(),
136         "42"
137     );
138 }
139 
140 /// Tests vhost-user block device with `crosvm device`.
141 #[test]
vhost_user_mount()142 fn vhost_user_mount() {
143     let config = VmConfig::new();
144     run_vhost_user_test(CmdType::Device, config);
145 }
146 
147 /// Tests vhost-user block device with `crosvm devices` (not `device`).
148 #[test]
vhost_user_mount_with_devices()149 fn vhost_user_mount_with_devices() {
150     let config = VmConfig::new();
151     run_vhost_user_test(CmdType::Devices, config);
152 }
153 
154 /// Tests vhost-user block device with `crosvm device`.
155 #[test]
vhost_user_mount_disable_sandbox()156 fn vhost_user_mount_disable_sandbox() {
157     let config = VmConfig::new().disable_sandbox();
158     run_vhost_user_test(CmdType::Device, config);
159 }
160 
161 /// Tests vhost-user block device with `crosvm devices` (not `device`).
162 #[test]
vhost_user_mount_with_devices_disable_sandbox()163 fn vhost_user_mount_with_devices_disable_sandbox() {
164     let config = VmConfig::new().disable_sandbox();
165     run_vhost_user_test(CmdType::Devices, config);
166 }
167