#[ cfg( feature = "audio_processing" ) ]
#[ allow( clippy::std_instead_of_core ) ] mod audio_processing_tests
{
use api_ollama::{
AudioFormat, SpeechToTextRequest,
TextToSpeechRequest, TextToSpeechResponse, AudioStreamRequest,
AudioStreamChunk, VoiceChatRequest, VoiceChatResponse,
AudioProcessingConfig
};
use std::time::{ Duration, Instant };
const SAMPLE_AUDIO_WAV: &[ u8 ] = b"RIFF\x24\x08\x00\x00WAVE";
const SAMPLE_AUDIO_MP3: &[ u8 ] = b"\xFF\xFB\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00";
#[ tokio::test ]
async fn test_speech_to_text_request_structure()
{
let speech_request = SpeechToTextRequest
{
model : "whisper".to_string(),
audio_data : SAMPLE_AUDIO_WAV.to_vec(),
format : AudioFormat::Wav,
language : Some( "en".to_string() ),
options : None,
};
assert_eq!( speech_request.model, "whisper" );
assert_eq!( speech_request.audio_data.len(), SAMPLE_AUDIO_WAV.len() );
assert_eq!( speech_request.format, AudioFormat::Wav );
assert_eq!( speech_request.language, Some( "en".to_string() ) );
assert!( speech_request.options.is_none() );
println!( "✓ Speech-to-text request structure validation successful" );
let serialized = serde_json::to_string( &speech_request );
assert!( serialized.is_ok() );
println!( "✓ Speech-to-text request serialization successful" );
}
#[ tokio::test ]
async fn test_text_to_speech_request_structure()
{
let tts_request = TextToSpeechRequest
{
model : "tts-1".to_string(),
text : "Hello, this is a test of text-to-speech functionality.".to_string(),
voice : Some( "alloy".to_string() ),
format : AudioFormat::Mp3,
speed : Some( 1.0 ),
options : None,
};
assert_eq!( tts_request.model, "tts-1" );
assert!( !tts_request.text.is_empty() );
assert_eq!( tts_request.voice, Some( "alloy".to_string() ) );
assert_eq!( tts_request.format, AudioFormat::Mp3 );
assert_eq!( tts_request.speed, Some( 1.0 ) );
println!( "✓ Text-to-speech request structure validation successful" );
let serialized = serde_json::to_string( &tts_request );
assert!( serialized.is_ok() );
println!( "✓ Text-to-speech request serialization successful" );
let response = TextToSpeechResponse
{
audio_data : SAMPLE_AUDIO_MP3.to_vec(),
format : AudioFormat::Mp3,
duration : Some( 5.0 ),
sample_rate : Some( 44100 ),
metadata : None,
};
assert!( !response.audio_data.is_empty() );
assert_eq!( response.format, AudioFormat::Mp3 );
assert_eq!( response.duration, Some( 5.0 ) );
println!( "✓ Text-to-speech response structure validation successful" );
}
#[ tokio::test ]
async fn test_audio_streaming_request_structure()
{
let wav_request = AudioStreamRequest
{
model : "whisper".to_string(),
audio_data : SAMPLE_AUDIO_WAV.to_vec(),
format : AudioFormat::Wav,
stream : true,
chunk_size : Some( 1024 ),
timeout : Some( 30 ),
};
assert_eq!( wav_request.model, "whisper" );
assert_eq!( wav_request.audio_data.len(), SAMPLE_AUDIO_WAV.len() );
assert_eq!( wav_request.format, AudioFormat::Wav );
assert!( wav_request.stream );
assert_eq!( wav_request.chunk_size, Some( 1024 ) );
println!( "✓ WAV audio streaming request structure validation successful" );
let mp3_request = AudioStreamRequest
{
model : "whisper".to_string(),
audio_data : SAMPLE_AUDIO_MP3.to_vec(),
format : AudioFormat::Mp3,
stream : true,
chunk_size : Some( 512 ),
timeout : Some( 30 ),
};
assert_eq!( mp3_request.format, AudioFormat::Mp3 );
assert_eq!( mp3_request.chunk_size, Some( 512 ) );
println!( "✓ MP3 audio streaming request structure validation successful" );
let chunk = AudioStreamChunk
{
data : SAMPLE_AUDIO_WAV.to_vec(),
timestamp : 1.5,
is_final : false,
sequence : Some( 1 ),
};
assert!( !chunk.data.is_empty() );
assert!( (chunk.timestamp - 1.5).abs() < f64::EPSILON );
assert!( !chunk.is_final );
println!( "✓ Audio stream chunk structure validation successful" );
}
#[ tokio::test ]
async fn test_voice_chat_structure_validation()
{
let chat_request = VoiceChatRequest
{
model : "llama3.2".to_string(),
audio_input : SAMPLE_AUDIO_WAV.to_vec(),
input_format : AudioFormat::Wav,
output_format : AudioFormat::Mp3,
conversation_id : Some( "test-chat-001".to_string() ),
real_time : true,
voice : Some( "alloy".to_string() ),
context : None,
};
assert_eq!( chat_request.model, "llama3.2" );
assert_eq!( chat_request.audio_input.len(), SAMPLE_AUDIO_WAV.len() );
assert_eq!( chat_request.input_format, AudioFormat::Wav );
assert_eq!( chat_request.output_format, AudioFormat::Mp3 );
assert_eq!( chat_request.conversation_id, Some( "test-chat-001".to_string() ) );
assert!( chat_request.real_time );
println!( "✓ Voice chat request structure validation successful" );
let response = VoiceChatResponse
{
audio_response : SAMPLE_AUDIO_MP3.to_vec(),
text_response : Some( "Hello! How can I help you today?".to_string() ),
output_format : AudioFormat::Mp3,
conversation_id : "test-chat-001".to_string(),
latency_ms : Some( 150 ),
metadata : None,
};
assert!( !response.audio_response.is_empty() );
assert!( response.text_response.is_some() );
assert_eq!( response.output_format, AudioFormat::Mp3 );
assert_eq!( response.conversation_id, "test-chat-001" );
println!( "✓ Voice chat response structure validation successful" );
}
#[ tokio::test ]
async fn test_audio_format_validation()
{
let invalid_request = SpeechToTextRequest
{
model : "whisper".to_string(),
audio_data : b"INVALID_AUDIO_DATA".to_vec(),
format : AudioFormat::Wav,
language : None,
options : None,
};
assert_eq!( invalid_request.model, "whisper" );
assert_eq!( invalid_request.audio_data, b"INVALID_AUDIO_DATA" );
assert_eq!( invalid_request.format, AudioFormat::Wav );
assert!( invalid_request.language.is_none() );
assert!( invalid_request.options.is_none() );
println!( "✓ Invalid audio data request structure validation successful" );
let wav_detected = AudioFormat::detect_format( SAMPLE_AUDIO_WAV );
assert_eq!( wav_detected, Some( AudioFormat::Wav ) );
let mp3_detected = AudioFormat::detect_format( SAMPLE_AUDIO_MP3 );
assert_eq!( mp3_detected, Some( AudioFormat::Mp3 ) );
let invalid_detected = AudioFormat::detect_format( b"INVALID_AUDIO_DATA" );
assert_eq!( invalid_detected, None );
println!( "✓ Audio format detection validation successful" );
}
#[ tokio::test ]
async fn test_audio_processing_serialization_performance()
{
let speech_request = SpeechToTextRequest
{
model : "whisper".to_string(),
audio_data : SAMPLE_AUDIO_WAV.to_vec(),
format : AudioFormat::Wav,
language : Some( "en".to_string() ),
options : None,
};
let start_time = Instant::now();
let serialized = serde_json::to_string( &speech_request );
let speech_latency = start_time.elapsed();
assert!( serialized.is_ok() );
assert!( speech_latency < Duration::from_millis( 10 ) );
let tts_request = TextToSpeechRequest
{
model : "tts-1".to_string(),
text : "Performance test".to_string(),
voice : Some( "alloy".to_string() ),
format : AudioFormat::Mp3,
speed : Some( 1.0 ),
options : None,
};
let start_time = Instant::now();
let tts_serialized = serde_json::to_string( &tts_request );
let tts_latency = start_time.elapsed();
assert!( tts_serialized.is_ok() );
assert!( tts_latency < Duration::from_millis( 10 ) );
println!( "✓ Audio processing serialization performance:" );
println!( " Speech-to-text serialization latency : {speech_latency:?}" );
println!( " Text-to-speech serialization latency : {tts_latency:?}" );
}
#[ tokio::test ]
async fn test_comprehensive_audio_format_support()
{
let formats = vec![ AudioFormat::Wav, AudioFormat::Mp3, AudioFormat::Flac, AudioFormat::Ogg ];
for format in formats
{
let speech_request = SpeechToTextRequest
{
model : "whisper".to_string(),
audio_data : SAMPLE_AUDIO_WAV.to_vec(),
format : format.clone(),
language : Some( "en".to_string() ),
options : None,
};
assert_eq!( speech_request.format, format );
let tts_request = TextToSpeechRequest
{
model : "tts-1".to_string(),
text : "Test".to_string(),
voice : Some( "alloy".to_string() ),
format : format.clone(),
speed : Some( 1.0 ),
options : None,
};
assert_eq!( tts_request.format, format );
}
println!( "✓ Comprehensive audio format support validation successful" );
}
#[ tokio::test ]
async fn test_audio_processing_configuration_structure()
{
let audio_config = AudioProcessingConfig::new()
.with_sample_rate( 44100 )
.with_bit_depth( 16 )
.with_channels( 2 )
.with_buffer_size( 1024 );
assert_eq!( audio_config.sample_rate(), 44100 );
assert_eq!( audio_config.bit_depth(), 16 );
assert_eq!( audio_config.channels(), 2 );
assert_eq!( audio_config.buffer_size(), 1024 );
println!( "✓ Audio processing configuration structure validation successful" );
let default_config = AudioProcessingConfig::new();
assert_eq!( default_config.sample_rate(), 44100 );
assert_eq!( default_config.bit_depth(), 16 );
assert_eq!( default_config.channels(), 1 );
assert_eq!( default_config.buffer_size(), 512 );
println!( "✓ Audio processing default configuration validation successful" );
}
}