返回 CodeWhale
speech_host_cli.rs
根目录 / crates / tui / src / tests / speech_host_cli.rs
1 //! Actual CLI consumers share the pinned speech adapter with ToolSpecs.
2 use crate::extension_host::TestManagerGuard;
3 use crate::extension_host::tests::node_for_tests;
4 use crate::plugins::activation::TestPolicyGuard;
5 use crate::tools::speech::speech_host_tests::{config, manager, provider};
6 use std::sync::Arc;
7 use wiremock::MockServer;
8
9 #[tokio::test(flavor = "current_thread")]
10 async fn real_cli_speech_and_tts_alias_share_host_plan_and_write_same_audio() {
11 use clap::Parser;
12 let _home = crate::test_support::SealedHome::new();
13 let _policy = TestPolicyGuard::extension_host(false);
14 let Some(node) = node_for_tests("real_cli_speech_host") else {
15 return;
16 };
17 let home = tempfile::tempdir().unwrap();
18 let manager = manager(node, home.path());
19 let _manager = TestManagerGuard::install(Arc::clone(&manager));
20 let server = MockServer::start().await;
21 provider(&server, 2).await;
22 let parsed = crate::Cli::try_parse_from(["codewhale", "tts", "hello"]).unwrap();
23 assert!(matches!(parsed.command, Some(crate::Commands::Speech(_))));
24 let args = || crate::SpeechArgs {
25 text: "hello".into(),
26 output: None,
27 output_dir: Some(home.path().join("audio")),
28 model: Some("mimo-tts".into()),
29 voice: Some("Mia".into()),
30 instruction: Some(" warm ".into()),
31 voice_prompt: None,
32 clone_voice: None,
33 format: "pcm".into(),
34 json: true,
35 };
36 crate::run_speech(&config(&server.uri(), false), args())
37 .await
38 .unwrap();
39 crate::run_speech(&config(&server.uri(), true), args())
40 .await
41 .unwrap();
42 let requests = server.received_requests().await.unwrap();
43 assert_eq!(requests.len(), 2);
44 assert_eq!(requests[0].body, requests[1].body);
45 assert_eq!(
46 std::fs::read(home.path().join("audio/speech.pcm16")).unwrap(),
47 b"hi"
48 );
49 manager.shutdown().await;
50 }
51
52 #[tokio::test(flavor = "current_thread")]
53 async fn selected_speech_host_refusal_never_falls_back_or_writes_cli_audio() {
54 let _home = crate::test_support::SealedHome::new();
55 let _policy = TestPolicyGuard::extension_host(false);
56 let home = tempfile::tempdir().unwrap();
57 let server = MockServer::start().await;
58 let manager = manager(home.path().join("missing-node"), home.path());
59 let _manager = TestManagerGuard::install(Arc::clone(&manager));
60 let args = crate::SpeechArgs {
61 text: "hello".into(),
62 output: Some(home.path().join("cli.wav")),
63 output_dir: None,
64 model: None,
65 voice: None,
66 instruction: None,
67 voice_prompt: None,
68 clone_voice: Some(home.path().join("missing.wav")),
69 format: "wav".into(),
70 json: true,
71 };
72 assert!(
73 crate::run_speech(&config(&server.uri(), true), args)
74 .await
75 .is_err()
76 );
77 assert!(server.received_requests().await.unwrap().is_empty());
78 assert!(!home.path().join("cli.wav").exists());
79 manager.shutdown().await;
80 }
81
82 #[tokio::test(flavor = "current_thread")]
83 async fn cli_speech_preserves_sample_file_error_before_format_validation() {
84 let _home = crate::test_support::SealedHome::new();
85 let _policy = TestPolicyGuard::extension_host(false);
86 let home = tempfile::tempdir().unwrap();
87 let server = MockServer::start().await;
88 let Some(node) = node_for_tests("cli_speech_error_order") else {
89 return;
90 };
91 let manager = manager(node, home.path());
92 let _manager = TestManagerGuard::install(Arc::clone(&manager));
93 // CLI's sample-read error still takes precedence over unsupported format.
94 let args = || crate::SpeechArgs {
95 text: "hello".into(),
96 output: None,
97 output_dir: Some(home.path().into()),
98 model: None,
99 voice: None,
100 instruction: None,
101 voice_prompt: None,
102 clone_voice: Some(home.path().join("missing.wav")),
103 format: "flac".into(),
104 json: true,
105 };
106 let rust = crate::run_speech(&config(&server.uri(), false), args())
107 .await
108 .unwrap_err();
109 let host = crate::run_speech(&config(&server.uri(), true), args())
110 .await
111 .unwrap_err();
112 assert_eq!(host.to_string(), rust.to_string());
113 assert!(server.received_requests().await.unwrap().is_empty());
114 manager.shutdown().await;
115 }
116
116 lines RUST