use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use hyper::StatusCode;
use mini_serve::{RouteBuilder, State, handler};
#[tokio::test]
async fn state_sharing_is_a_refcount_bump_not_a_reallocation() {
let app = RouteBuilder::new(AtomicUsize::new(0))
.get("/ping", handler(|_req, state: State<AtomicUsize>| async move {
state.fetch_add(1, Ordering::SeqCst);
mini_serve::json(StatusCode::OK, &serde_json::json!({"ok": true}))
}))
.seal();
let original: Arc<AtomicUsize> = app.state_arc();
let weak = Arc::downgrade(&original);
drop(original);
let port = app.bind_ephemeral().await.expect("failed to bind");
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
for _ in 0..5 {
let resp = reqwest::get(&format!("http://127.0.0.1:{}/ping", port))
.await
.expect("request failed");
assert_eq!(resp.status(), StatusCode::OK);
}
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
let strong = weak
.upgrade()
.expect("App holds the original Arc<S> for its own lifetime");
assert_eq!(
Arc::strong_count(&strong),
2,
"only App's held Arc<S> and this upgraded handle should remain once requests finish \
— a growing count would mean state is reallocated per request"
);
assert_eq!(strong.load(Ordering::SeqCst), 5);
}