pinakes-server: add more integration tests
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I7c6c8eaad569404c7a13cfa8114d84516a6a6964
This commit is contained in:
parent
fd11b2b7c4
commit
30041c40c0
6 changed files with 517 additions and 1 deletions
65
crates/pinakes-server/tests/e2e.rs
Normal file
65
crates/pinakes-server/tests/e2e.rs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/// End-to-end tests that bind a real TCP listener and exercise the HTTP layer.
|
||||
///
|
||||
/// These tests differ from the router-level `oneshot` tests in that they verify
|
||||
/// the full Axum `serve` path: `TcpListener` binding, HTTP framing, and response
|
||||
/// serialization. Each test spins up a server on an ephemeral port, issues a
|
||||
/// real HTTP request via reqwest, then shuts down.
|
||||
mod common;
|
||||
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
/// Bind a listener on an ephemeral port, spawn the server in the background,
|
||||
/// and return the bound address as a string.
|
||||
///
|
||||
/// Uses `into_make_service_with_connect_info` so that the governor rate
|
||||
/// limiter can extract `ConnectInfo<SocketAddr>` from real TCP connections.
|
||||
async fn bind_and_serve() -> String {
|
||||
let app = common::setup_app().await;
|
||||
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
tokio::spawn(async move {
|
||||
axum::serve(
|
||||
listener,
|
||||
app.into_make_service_with_connect_info::<SocketAddr>(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
format!("http://{addr}")
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn health_endpoint_responds_over_real_tcp() {
|
||||
let base = bind_and_serve().await;
|
||||
let resp = reqwest::get(format!("{base}/api/v1/health"))
|
||||
.await
|
||||
.expect("health request failed");
|
||||
assert_eq!(resp.status(), 200);
|
||||
let body: serde_json::Value = resp.json().await.expect("body not JSON");
|
||||
assert!(
|
||||
body["status"].is_string(),
|
||||
"expected health response to contain 'status' field"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn media_list_responds_over_real_tcp() {
|
||||
// setup_app has authentication_disabled=true; verifies the router serves
|
||||
// real TCP traffic, not just in-process oneshot requests.
|
||||
let base = bind_and_serve().await;
|
||||
let resp = reqwest::get(format!("{base}/api/v1/media"))
|
||||
.await
|
||||
.expect("media list request failed");
|
||||
assert_eq!(resp.status(), 200);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unknown_route_returns_404_over_real_tcp() {
|
||||
let base = bind_and_serve().await;
|
||||
let resp = reqwest::get(format!("{base}/api/v1/nonexistent-route"))
|
||||
.await
|
||||
.expect("request failed");
|
||||
assert_eq!(resp.status(), 404);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue