use api_gemini::
{
client ::Client,
models ::*,
error ::Error,
};
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
async fn test_audio_transcription_mp3()
{
let client = Client::new()
.expect( "Failed to create client for audio transcription test" );
let models_api = client.models();
let model = models_api.by_name( "gemini-1.5-pro" );
let audio_data = create_test_mp3_data();
let request = GenerateContentRequest
{
contents: vec![ Content
{
parts: vec![
Part
{
text: Some( "Please transcribe this audio and describe what you hear.".to_string() ),
inline_data: None,
function_call: None,
function_response: None,
..Default::default()
},
Part
{
text: None,
inline_data: Some( Blob
{
mime_type: "audio/mp3".to_string(),
data: audio_data,
} ),
function_call: None,
function_response: None,
..Default::default()
}
],
role: "user".to_string(),
} ],
tools: None,
tool_config: None,
system_instruction: None,
safety_settings: None,
generation_config: None,
cached_content: None,
};
let result = model.generate_content( &request ).await;
match result
{
Ok( response ) =>
{
assert!( !response.candidates.is_empty() );
let content = &response.candidates[ 0 ].content;
assert!( !content.parts.is_empty() );
if let Some( text ) = &content.parts[ 0 ].text
{
assert!( !text.is_empty() );
println!( "Audio transcription result : {text}" );
}
},
Err( e ) =>
{
println!( "Audio transcription test failed (expected): {e}" );
match e
{
Error::InvalidArgument( _ ) | Error::ApiError( _ ) => {
},
_ => panic!( "Unexpected error type : {e}" ),
}
}
}
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
async fn test_audio_analysis_wav()
{
let client = Client::new()
.expect( "Failed to create client for audio analysis test" );
let models_api = client.models();
let model = models_api.by_name( "gemini-1.5-pro" );
let audio_data = create_test_wav_data();
let request = GenerateContentRequest
{
contents: vec![ Content
{
parts: vec![
Part
{
text: Some( "Analyze the emotional tone and content of this audio recording.".to_string() ),
inline_data: None,
function_call: None,
function_response: None,
..Default::default()
},
Part
{
text: None,
inline_data: Some( Blob
{
mime_type: "audio/wav".to_string(),
data: audio_data,
} ),
function_call: None,
function_response: None,
..Default::default()
}
],
role: "user".to_string(),
} ],
tools: None,
tool_config: None,
system_instruction: None,
safety_settings: None,
generation_config: None,
cached_content: None,
};
let result = model.generate_content( &request ).await;
match result
{
Ok( response ) =>
{
assert!( !response.candidates.is_empty() );
let content = &response.candidates[ 0 ].content;
assert!( !content.parts.is_empty() );
if let Some( text ) = &content.parts[ 0 ].text
{
assert!( !text.is_empty() );
println!( "Audio analysis result : {text}" );
}
},
Err( e ) =>
{
println!( "Audio analysis test failed (expected): {e}" );
match e
{
Error::InvalidArgument( _ ) | Error::ApiError( _ ) => {
},
_ => panic!( "Unexpected error type : {e}" ),
}
}
}
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
async fn test_multiple_audio_formats()
{
let client = Client::new()
.expect( "Failed to create client for multi-format audio test" );
let models_api = client.models();
let model = models_api.by_name( "gemini-1.5-pro" );
let audio_formats = vec![
( "audio/mp3", create_test_mp3_data() ),
( "audio/wav", create_test_wav_data() ),
( "audio/ogg", create_test_ogg_data() ),
( "audio/flac", create_test_flac_data() ),
( "audio/m4a", create_test_m4a_data() ),
];
for ( mime_type, audio_data ) in audio_formats
{
let request = GenerateContentRequest
{
contents: vec![ Content
{
parts: vec![
Part
{
text : Some( format!( "Process this {mime_type} audio file." ) ),
inline_data: None,
function_call: None,
function_response: None,
..Default::default()
},
Part
{
text: None,
inline_data: Some( Blob
{
mime_type: mime_type.to_string(),
data: audio_data,
} ),
function_call: None,
function_response: None,
..Default::default()
}
],
role: "user".to_string(),
} ],
tools: None,
tool_config: None,
system_instruction: None,
safety_settings: None,
generation_config: None,
cached_content: None,
};
let result = model.generate_content( &request ).await;
match result
{
Ok( response ) =>
{
assert!( !response.candidates.is_empty() );
println!( "Successfully processed {mime_type} format" );
},
Err( e ) =>
{
println!( "Format {mime_type} failed (expected): {e}" );
match e
{
Error::InvalidArgument( _ ) | Error::ApiError( _ ) => {
},
_ => panic!( "Unexpected error for format {mime_type}: {e}" ),
}
}
}
}
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
async fn test_audio_safety_filtering()
{
let client = Client::new()
.expect( "Failed to create client for audio safety test" );
let models_api = client.models();
let model = models_api.by_name( "gemini-1.5-pro" );
let request = GenerateContentRequest
{
contents: vec![ Content
{
parts: vec![
Part
{
text: Some( "Analyze this audio for content safety.".to_string() ),
inline_data: None,
function_call: None,
function_response: None,
..Default::default()
},
Part
{
text: None,
inline_data: Some( Blob
{
mime_type: "audio/wav".to_string(),
data: create_test_wav_data(),
} ),
function_call: None,
function_response: None,
..Default::default()
}
],
role: "user".to_string(),
} ],
tools: None,
safety_settings: Some( vec![ SafetySetting
{
category: "HARM_CATEGORY_HARASSMENT".to_string(),
threshold: "BLOCK_MEDIUM_AND_ABOVE".to_string(),
} ] ),
tool_config: None,
system_instruction: None,
generation_config: None,
cached_content: None,
};
let result = model.generate_content( &request ).await;
match result
{
Ok( response ) =>
{
assert!( !response.candidates.is_empty() );
if let Some( safety_ratings ) = &response.candidates[ 0 ].safety_ratings
{
assert!( !safety_ratings.is_empty() );
println!( "Audio safety analysis completed with {} ratings", safety_ratings.len() );
}
},
Err( e ) =>
{
println!( "Audio safety test failed (expected): {e}" );
match e
{
Error::InvalidArgument( _ ) | Error::ApiError( _ ) => {
},
_ => panic!( "Unexpected error type : {e}" ),
}
}
}
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
async fn test_large_audio_file()
{
let client = Client::new()
.expect( "Failed to create client for large audio test" );
let models_api = client.models();
let model = models_api.by_name( "gemini-1.5-pro" );
let large_audio_data = create_large_test_audio_data();
let request = GenerateContentRequest
{
contents: vec![ Content
{
parts: vec![
Part
{
text: Some( "Summarize this long audio recording.".to_string() ),
inline_data: None,
function_call: None,
function_response: None,
..Default::default()
},
Part
{
text: None,
inline_data: Some( Blob
{
mime_type: "audio/mp3".to_string(),
data: large_audio_data,
} ),
function_call: None,
function_response: None,
..Default::default()
}
],
role: "user".to_string(),
} ],
tools: None,
tool_config: None,
system_instruction: None,
safety_settings: None,
generation_config: None,
cached_content: None,
};
let result = model.generate_content( &request ).await;
match result
{
Ok( response ) =>
{
assert!( !response.candidates.is_empty() );
println!( "Successfully processed large audio file" );
},
Err( e ) =>
{
println!( "Large audio test failed : {e}" );
match e
{
Error::InvalidArgument( _ ) | Error::ApiError( _ ) | Error::NetworkError( _ ) => {
},
_ => panic!( "Unexpected error type : {e}" ),
}
}
}
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
async fn test_invalid_audio_format()
{
let client = Client::new()
.expect( "Failed to create client for invalid audio test" );
let models_api = client.models();
let model = models_api.by_name( "gemini-1.5-pro" );
let request = GenerateContentRequest
{
contents: vec![ Content
{
parts: vec![
Part
{
text: Some( "Process this audio.".to_string() ),
inline_data: None,
function_call: None,
function_response: None,
..Default::default()
},
Part
{
text: None,
inline_data: Some( Blob
{
mime_type: "audio/mp3".to_string(),
data: "invalid_audio_data".to_string(), } ),
function_call: None,
function_response: None,
..Default::default()
}
],
role: "user".to_string(),
} ],
tools: None,
tool_config: None,
system_instruction: None,
safety_settings: None,
generation_config: None,
cached_content: None,
};
let result = model.generate_content( &request ).await;
match result
{
Ok( _ ) => panic!( "Expected failure for invalid audio data" ),
Err( e ) =>
{
match e
{
Error::InvalidArgument( _ ) | Error::DeserializationError( _ ) | Error::ApiError( _ ) => {
println!( "Correctly rejected invalid audio data : {e}" );
},
_ => panic!( "Unexpected error type for invalid audio : {e}" ),
}
}
}
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
async fn test_batch_audio_processing()
{
let client = Client::new()
.expect( "Failed to create client for batch audio test" );
let models_api = client.models();
let model = models_api.by_name( "gemini-1.5-pro" );
let audio_files = vec![
create_test_mp3_data(),
create_test_wav_data(),
create_test_ogg_data(),
];
let mut results = Vec::new();
for ( index, audio_data ) in audio_files.into_iter().enumerate()
{
let request = GenerateContentRequest
{
contents: vec![ Content
{
parts: vec![
Part
{
text : Some( format!( "Analyze audio file #{}", index + 1 ) ),
inline_data: None,
function_call: None,
function_response: None,
..Default::default()
},
Part
{
text: None,
inline_data: Some( Blob
{
mime_type: match index
{
0 => "audio/mp3",
1 => "audio/wav",
_ => "audio/ogg",
}.to_string(),
data: audio_data,
} ),
function_call: None,
function_response: None,
..Default::default()
}
],
role: "user".to_string(),
} ],
tools: None,
tool_config: None,
system_instruction: None,
safety_settings: None,
generation_config: None,
cached_content: None,
};
let result = model.generate_content( &request ).await;
results.push( result );
tokio ::time::sleep( core::time::Duration::from_millis( 100 ) ).await;
}
let successful = results.iter().filter( | r | r.is_ok() ).count();
let failed = results.iter().filter( | r | r.is_err() ).count();
println!( "Batch audio processing : {successful} successful, {failed} failed" );
assert_eq!( successful + failed, 3 );
}
fn create_test_mp3_data() -> String
{
use base64::Engine;
let mp3_header = vec![ 0xFF, 0xFB, 0x90, 0x00 ]; base64 ::engine::general_purpose::STANDARD.encode( &mp3_header )
}
fn create_test_wav_data() -> String
{
use base64::Engine;
let wav_header = b"RIFF\x24\x00\x00\x00WAVEfmt \x10\x00\x00\x00";
base64 ::engine::general_purpose::STANDARD.encode( wav_header )
}
fn create_test_ogg_data() -> String
{
use base64::Engine;
let ogg_header = b"OggS\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00";
base64 ::engine::general_purpose::STANDARD.encode( ogg_header )
}
fn create_test_flac_data() -> String
{
use base64::Engine;
let flac_header = b"fLaC\x00\x00\x00\x22";
base64 ::engine::general_purpose::STANDARD.encode( flac_header )
}
fn create_test_m4a_data() -> String
{
use base64::Engine;
let m4a_header = b"\x00\x00\x00\x20ftypM4A ";
base64 ::engine::general_purpose::STANDARD.encode( m4a_header )
}
fn create_large_test_audio_data() -> String
{
use base64::Engine;
let mut large_data = Vec::new();
large_data.extend_from_slice( &[ 0xFF, 0xFB, 0x90, 0x00 ] );
for _ in 0..1000
{
large_data.extend_from_slice( &[ 0x00, 0x01, 0x02, 0x03 ] );
}
base64 ::engine::general_purpose::STANDARD.encode( &large_data )
}