sound: add StreamDirection enum and --streams CLI arg
Add a StreamDirection enum (Output, Input) with ValueEnum derive and a Display impl, and a --streams field to SoundArgs that accepts comma-separated stream direction values with output,input as the default. Add 7 CLI parsing tests covering the common cases. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cde9d12ad9
commit
7147a41ec0
2 changed files with 121 additions and 0 deletions
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
//! An arguments type for the binary interface of this library.
|
||||
|
||||
use std::fmt;
|
||||
use std::os::fd::RawFd;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
|
@ -24,6 +25,24 @@ pub struct SoundArgs {
|
|||
#[clap(long)]
|
||||
#[clap(value_enum)]
|
||||
pub backend: BackendType,
|
||||
/// Stream directions to enable (comma-separated).
|
||||
#[clap(long, value_delimiter = ',', default_values_t = [StreamDirection::Output, StreamDirection::Input])]
|
||||
pub streams: Vec<StreamDirection>,
|
||||
}
|
||||
|
||||
#[derive(ValueEnum, Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum StreamDirection {
|
||||
Output,
|
||||
Input,
|
||||
}
|
||||
|
||||
impl fmt::Display for StreamDirection {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.to_possible_value()
|
||||
.expect("no values are skipped")
|
||||
.get_name()
|
||||
.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(ValueEnum, Clone, Copy, Default, Debug, Eq, PartialEq)]
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ mod tests {
|
|||
use clap::Parser;
|
||||
use rstest::*;
|
||||
use std::path::PathBuf;
|
||||
use vhost_device_sound::args::StreamDirection;
|
||||
use vhost_device_sound::BackendType;
|
||||
|
||||
use super::*;
|
||||
|
|
@ -56,6 +57,107 @@ mod tests {
|
|||
assert_eq!(args.socket_fd, Some(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cli_streams_output_only() {
|
||||
let args: SoundArgs = Parser::parse_from([
|
||||
"",
|
||||
"--socket",
|
||||
"/tmp/vhost-sound.socket",
|
||||
"--backend",
|
||||
"null",
|
||||
"--streams",
|
||||
"output",
|
||||
]);
|
||||
assert_eq!(args.streams, vec![StreamDirection::Output]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cli_streams_input_only() {
|
||||
let args: SoundArgs = Parser::parse_from([
|
||||
"",
|
||||
"--socket",
|
||||
"/tmp/vhost-sound.socket",
|
||||
"--backend",
|
||||
"null",
|
||||
"--streams",
|
||||
"input",
|
||||
]);
|
||||
assert_eq!(args.streams, vec![StreamDirection::Input]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cli_streams_both() {
|
||||
let args: SoundArgs = Parser::parse_from([
|
||||
"",
|
||||
"--socket",
|
||||
"/tmp/vhost-sound.socket",
|
||||
"--backend",
|
||||
"null",
|
||||
"--streams",
|
||||
"output,input",
|
||||
]);
|
||||
assert!(args.streams.contains(&StreamDirection::Output));
|
||||
assert!(args.streams.contains(&StreamDirection::Input));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cli_streams_default() {
|
||||
let args: SoundArgs = Parser::parse_from([
|
||||
"",
|
||||
"--socket",
|
||||
"/tmp/vhost-sound.socket",
|
||||
"--backend",
|
||||
"null",
|
||||
]);
|
||||
assert!(args.streams.contains(&StreamDirection::Output));
|
||||
assert!(args.streams.contains(&StreamDirection::Input));
|
||||
assert_eq!(args.streams.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cli_streams_invalid() {
|
||||
let result = SoundArgs::try_parse_from([
|
||||
"",
|
||||
"--socket",
|
||||
"/tmp/vhost-sound.socket",
|
||||
"--backend",
|
||||
"null",
|
||||
"--streams",
|
||||
"foobar",
|
||||
]);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cli_streams_duplicate() {
|
||||
let args: SoundArgs = Parser::parse_from([
|
||||
"",
|
||||
"--socket",
|
||||
"/tmp/vhost-sound.socket",
|
||||
"--backend",
|
||||
"null",
|
||||
"--streams",
|
||||
"output,output",
|
||||
]);
|
||||
// Duplicates are accepted by clap; the contains() conversion in main.rs
|
||||
// naturally deduplicates since it produces booleans.
|
||||
assert!(args.streams.contains(&StreamDirection::Output));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cli_streams_empty() {
|
||||
let result = SoundArgs::try_parse_from([
|
||||
"",
|
||||
"--socket",
|
||||
"/tmp/vhost-sound.socket",
|
||||
"--backend",
|
||||
"null",
|
||||
"--streams",
|
||||
"",
|
||||
]);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case::null_backend("null", BackendType::Null)]
|
||||
#[cfg_attr(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue