use {
anyhow::{Result, anyhow, ensure},
reqwest::Response,
tokio::runtime::Runtime,
};
use crate::{
api::{
dev_server::{MockServer, SequentialMockServer, make_service},
requests::{download_stream, retry_with_backoff},
service_state::QobuzApiService,
},
errors::QobuzApiError,
};
fn rate_limit_response() -> (u16, String) {
(
429,
r#"{"status":"error","message":"rate limited"}"#.to_string(),
)
}
fn make_test_request(service: &QobuzApiService) -> Result<Response, QobuzApiError> {
let rt = Runtime::new()?;
let client = service.http_client();
rt.block_on(retry_with_backoff(
client,
&format!("{}/test", service.base_url()),
"token",
))
}
#[test]
fn rate_limit_retry_exhausts_retries() -> Result<()> {
let server = SequentialMockServer::start(vec![
rate_limit_response(),
rate_limit_response(),
rate_limit_response(),
rate_limit_response(),
])?;
let service = make_service(&server.base_url())?;
let result = make_test_request(&service);
let err = result.err().ok_or_else(|| anyhow!("expected error"))?;
ensure!(format!("{err}").contains("Rate limited"));
Ok(())
}
#[test]
fn rate_limit_retry_succeeds_after_backoff() -> Result<()> {
let server = SequentialMockServer::start(vec![
rate_limit_response(),
rate_limit_response(),
(
200,
r#"{"url":"https://example.com/file.flac"}"#.to_string(),
),
])?;
let service = make_service(&server.base_url())?;
let result = make_test_request(&service)?;
ensure!(result.status().is_success());
Ok(())
}
#[test]
fn download_stream_succeeds_on_ok() -> Result<()> {
let server = MockServer::start(200, "bytes")?;
let service = make_service(&server.base_url())?;
let rt = Runtime::new()?;
let response = rt.block_on(download_stream(
service.http_client(),
&format!("{}/file", service.base_url()),
"token",
None,
))?;
ensure!(response.status().is_success(), "expected success status");
Ok(())
}
#[test]
fn download_stream_errors_on_not_found() -> Result<()> {
let server = MockServer::start(404, "missing")?;
let service = make_service(&server.base_url())?;
let rt = Runtime::new()?;
let result = rt.block_on(download_stream(
service.http_client(),
&format!("{}/file", service.base_url()),
"token",
None,
));
ensure!(result.is_err(), "expected not-found error");
Ok(())
}