OpenPay (3 crates, ~13k LOC, 175 tests) op-connect sub-merchant onboarding + KYB + split-payments + payouts + 1099-K op-3ds2 3DS2.3 SCA processor (AReq/ARes/CReq/CRes/RReq/RRes + exemptions) op-tax US/EU/UK/AU/CA/IN tax with Avalara/Stripe/CCH/Vertex/TaxJar adapters Smart Byte (3 crates, ~7k LOC, 57 tests) smart-byte-libp2p libp2p transport (kad/gossipsub/mdns/autonat/relay/dcutr/identify/ping/req_resp) smart-byte-crdt LWW/GCounter/PnCounter/OrSet/LwwMap/RgaList/2P-Set + HLC + vector clock + Automerge/Yjs interop smart-byte-keri-witness KERI key-rotation cycle + witness layer + watchers + recovery + delegation EOC (3 crates, ~8k LOC, 108 tests) eoc-tools function-calling across Anthropic/OpenAI/Google/Mistral/Cohere + parallel exec + sandbox eoc-multimodal vision (CLIP/SigLIP/ColPali) + audio (Whisper/MMS) + video sampling + modality router eoc-spec-decode vanilla + SpS-with-temp + lookahead speculative decoding + EAGLE/Medusa stubs All three workspaces compile cleanly. Forbidden-unsafe, no unwrap outside tests. Co-Authored-By: Claude Opus 4.7 <[email protected]>
92 lines
3.3 KiB
Rust
92 lines
3.3 KiB
Rust
//! End-to-end HTTP behaviour tests using `wiremock`.
|
|
//!
|
|
//! Covers Whisper transcription and OpenAI TTS — the two vendor calls
|
|
//! that don't share the chat-completions body schema and therefore need
|
|
//! their own fixtures.
|
|
|
|
use eoc_multimodal::audio::tts::{OpenAiTtsBackend, Synthesizer, VoiceSpec};
|
|
use eoc_multimodal::audio::whisper_api::{Transcriber, WhisperApiBackend};
|
|
use eoc_multimodal::modality::AudioRef;
|
|
use serde_json::json;
|
|
use wiremock::matchers::{header, header_exists, method, path};
|
|
use wiremock::{Mock, MockServer, ResponseTemplate};
|
|
|
|
#[tokio::test]
|
|
async fn whisper_known_bytes_returns_expected_text() {
|
|
let server = MockServer::start().await;
|
|
let body = json!({
|
|
"text": "hello world",
|
|
"language": "en",
|
|
"duration": 1.5,
|
|
"segments": [
|
|
{"start": 0.0, "end": 1.5, "text": "hello world"}
|
|
]
|
|
});
|
|
Mock::given(method("POST"))
|
|
.and(path("/"))
|
|
.and(header("Authorization", "Bearer sk-test"))
|
|
.and(header_exists("Content-Type"))
|
|
.respond_with(ResponseTemplate::new(200).set_body_json(body))
|
|
.mount(&server)
|
|
.await;
|
|
|
|
let backend = WhisperApiBackend::new("sk-test", "whisper-1").with_endpoint(server.uri());
|
|
let audio = AudioRef::Bytes {
|
|
content_type: "audio/wav".to_string(),
|
|
bytes: vec![0x00, 0x01, 0x02, 0x03],
|
|
};
|
|
let result = backend.transcribe(&audio).await.expect("ok");
|
|
assert_eq!(result.text, "hello world");
|
|
assert_eq!(result.language.as_deref(), Some("en"));
|
|
assert_eq!(result.segments.len(), 1);
|
|
// 1.5 s * 5 J/s = 7.5 J = 7_500_000 µJ.
|
|
assert_eq!(result.joule_cost.microjoules, 7_500_000);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn whisper_401_returns_invalid_api_key() {
|
|
let server = MockServer::start().await;
|
|
Mock::given(method("POST"))
|
|
.and(path("/"))
|
|
.respond_with(ResponseTemplate::new(401).set_body_string("denied"))
|
|
.mount(&server)
|
|
.await;
|
|
|
|
let backend = WhisperApiBackend::new("sk-bad", "whisper-1").with_endpoint(server.uri());
|
|
let audio = AudioRef::Bytes {
|
|
content_type: "audio/wav".to_string(),
|
|
bytes: vec![0x00],
|
|
};
|
|
let err = backend.transcribe(&audio).await.expect_err("should fail");
|
|
assert!(matches!(
|
|
err,
|
|
eoc_multimodal::MultimodalError::InvalidApiKey
|
|
));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn tts_returns_audio_bytes_with_content_type() {
|
|
let server = MockServer::start().await;
|
|
let synthetic_wav: Vec<u8> = b"RIFF....WAVEfmt ".to_vec();
|
|
Mock::given(method("POST"))
|
|
.and(path("/"))
|
|
.and(header("Authorization", "Bearer sk-test"))
|
|
.respond_with(
|
|
ResponseTemplate::new(200)
|
|
.insert_header("Content-Type", "audio/wav")
|
|
.set_body_bytes(synthetic_wav.clone()),
|
|
)
|
|
.mount(&server)
|
|
.await;
|
|
|
|
let backend = OpenAiTtsBackend::new("sk-test", "tts-1").with_endpoint(server.uri());
|
|
let out = backend
|
|
.synthesize("hello world", VoiceSpec::default_alloy())
|
|
.await
|
|
.expect("ok");
|
|
assert_eq!(out.content_type, "audio/wav");
|
|
assert_eq!(out.bytes, synthetic_wav);
|
|
// "hello world" is 11 chars / 150 cps = 0.0733 s * 1.5 J/s ≈ 110_000 µJ.
|
|
assert!(out.joule_cost.microjoules > 0);
|
|
assert!(out.joule_cost.microjoules < 1_000_000);
|
|
}
|