#![cfg(feature = "test-utils")]
use axum::body::Body;
use axum::http::{Request, StatusCode};
use gradatum_engine::server::EngineServer;
use tower::ServiceExt;
#[tokio::test]
async fn health_endpoint_reports_ready() {
let app =
EngineServer::test_app_with_child("http://127.0.0.1:1".to_string(), 30, 32 * 1024 * 1024);
let resp = app
.oneshot(
Request::builder()
.uri("/health")
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
}
#[tokio::test]
async fn metrics_absent_from_main_router() {
let app =
EngineServer::test_app_with_child("http://127.0.0.1:1".to_string(), 30, 32 * 1024 * 1024);
let resp = app
.oneshot(
Request::builder()
.uri("/metrics")
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(
resp.status(),
StatusCode::NOT_FOUND,
"C2 : /metrics doit retourner 404 sur le router principal (LAN) — \
métriques séparées sur le listener loopback-only"
);
}
#[tokio::test]
async fn metrics_available_on_metrics_router() {
use gradatum_engine::metrics::EngineMetrics;
use std::sync::Arc;
let metrics = Arc::new(EngineMetrics::new());
metrics.record_request("/v1/chat/completions", 200, 42);
let app = EngineServer::metrics_router(metrics);
let resp = app
.oneshot(
Request::builder()
.uri("/metrics")
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(
resp.status(),
StatusCode::OK,
"C2 : /metrics doit être disponible sur le metrics_router loopback-only"
);
let bytes = axum::body::to_bytes(resp.into_body(), usize::MAX)
.await
.unwrap();
let body = std::str::from_utf8(&bytes).unwrap();
assert!(
body.contains("engine_requests_total"),
"C2 : corps /metrics doit contenir les métriques Prometheus"
);
}
#[tokio::test]
async fn bind_is_loopback_in_test_state() {
let url = "http://127.0.0.1:11435";
assert!(
url.contains("127.0.0.1") || url.contains("localhost"),
"bind doit être loopback (P1-4)"
);
}