Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/e2e_tests/tests/snd.rs
5394 views
1
// Copyright 2023 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
use std::fs;
6
7
use fixture::vhost_user::CmdType;
8
use fixture::vhost_user::Config as VuConfig;
9
use fixture::vhost_user::VhostUserBackend;
10
use fixture::vm::Config;
11
use fixture::vm::TestVm;
12
use tempfile::NamedTempFile;
13
use tempfile::TempDir;
14
15
/// Tests audio playback on virtio-snd with file backend
16
///
17
/// 1. Create a temporal directory for the audio file.
18
/// 2. Start a VM with a virtiofs device for the temporal directory and a virtio-snd device with
19
/// file backend.
20
/// 3. Create a raw audio file in the temporal directory with sox.
21
/// 4. Do playback with aplay.
22
/// 5. Compare the generated audio file and the output from virtio-snd.
23
#[test]
24
fn do_playback() {
25
let temp_dir = tempfile::tempdir().unwrap();
26
let temp_dir_path_str = temp_dir.path().to_str().unwrap();
27
28
let config = get_test_vm_config(
29
temp_dir_path_str,
30
vec![
31
"--virtio-snd".to_string(),
32
get_virtio_snd_args(temp_dir_path_str),
33
],
34
);
35
playback_and_check(config, temp_dir)
36
}
37
38
/// Tests audio playback with vhost user.
39
#[test]
40
fn do_playback_with_vhost_user() {
41
let temp_dir = tempfile::tempdir().unwrap();
42
let temp_dir_path_str = temp_dir.path().to_str().unwrap();
43
44
let socket = NamedTempFile::new().unwrap();
45
let socket_path_str = socket.path().to_str().unwrap();
46
47
let vu_config = VuConfig::new(CmdType::Device, "snd").extra_args(vec![
48
"snd".to_string(),
49
"--config".to_string(),
50
get_virtio_snd_args(temp_dir_path_str),
51
"--socket-path".to_string(),
52
socket_path_str.to_string(),
53
]);
54
let _vu_device = VhostUserBackend::new(vu_config).unwrap();
55
56
let config = get_test_vm_config(
57
temp_dir_path_str,
58
vec![
59
"--vhost-user".to_string(),
60
format!("sound,socket={}", socket_path_str),
61
],
62
);
63
playback_and_check(config, temp_dir)
64
}
65
66
fn playback_and_check(config: Config, temp_dir: TempDir) {
67
let mut vm = TestVm::new(config).unwrap();
68
vm.exec_in_guest("mount -t virtiofs tmp2 /mnt").unwrap();
69
vm.exec_in_guest("ls /mnt 1>&2").unwrap();
70
vm.exec_in_guest(
71
"sox -n -b 16 -r 48000 -c 2 -e signed -t raw \
72
/mnt/test_440_48000.raw synth 1 sine 440 vol -10dB",
73
)
74
.unwrap();
75
vm.exec_in_guest(
76
"aplay --buffer-size=48000 --period-size=12000 \
77
-d 1 -f dat -Dhw:0,0 /mnt/test_440_48000.raw",
78
)
79
.unwrap();
80
81
assert!(compare_files(
82
temp_dir,
83
"test_440_48000.raw",
84
"stream-0.out"
85
));
86
}
87
88
fn get_virtio_snd_args(output_file_path_str: &str) -> String {
89
format!("backend=file,playback_path={output_file_path_str},playback_size=400000")
90
}
91
92
fn get_test_vm_config(temp_dir_path_str: &str, snd_args: Vec<String>) -> Config {
93
let mut args = vec![
94
"--shared-dir".to_string(),
95
format!("{}:tmp2:type=fs:cache=always", temp_dir_path_str),
96
];
97
args.extend(snd_args);
98
Config::new().extra_args(args)
99
}
100
101
fn compare_files(temp_dir: TempDir, golden_file_name: &str, output_file_name: &str) -> bool {
102
// 1 second, 2 channels, 16 bit (2 byte) format, 48000 frame rate.
103
const BYTES_TO_COMPARE: usize = 1 * 2 * 2 * 48000;
104
// Skip the first buffer-size bytes as it's 0 pads.
105
const SKIP_OFFSET: usize = 48000;
106
107
// Open the second file for reading
108
let buf1 = fs::read(temp_dir.path().join(golden_file_name)).unwrap();
109
let buf2 = fs::read(temp_dir.path().join(output_file_name)).unwrap();
110
111
if buf1[..BYTES_TO_COMPARE] != buf2[SKIP_OFFSET..(SKIP_OFFSET + BYTES_TO_COMPARE)] {
112
println!("Files differ");
113
return false;
114
}
115
116
true
117
}
118
119