Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+264
View File
@@ -0,0 +1,264 @@
use super::*;
use dever_runtime::{http::PoolLimits, tls};
fn message() -> Request {
Request {
method: "POST".into(),
target: "/echo".into(),
headers: vec![],
body: b"pooled".to_vec().into(),
}
}
#[test]
fn origins_reject_invalid_ports_before_connecting() {
runtime()
.run(async |scope| {
for host in ["127.0.0.1", "[::1]", "localhost"] {
for port in ["99999", "65536", "abc", "-1", ""] {
for scheme in ["http", "https"] {
assert!(
http::client(
&format!("{scheme}://{host}:{port}"),
&tls::system(),
&Limits::default(),
&PoolLimits::default(),
scope
)
.is_err()
);
}
for scheme in ["ws", "wss"] {
let error = http::websocket::open(
&format!("{scheme}://{host}:{port}/"),
&tls::system(),
&http::websocket::Limits::default(),
scope,
)
.await
.unwrap_err();
assert!(
error.contains("port") || error.contains("invalid WebSocket URL"),
"{error}"
);
}
}
for suffix in ["", ":80", ":443", ":65535"] {
let client = http::client(
&format!("http://{host}{suffix}"),
&tls::system(),
&Limits::default(),
&PoolLimits::default(),
scope,
)
.unwrap();
client.close().await.unwrap();
}
}
})
.unwrap();
}
#[test]
fn pool_bounds_http2_concurrency_and_cancels_active_requests() {
use std::sync::atomic::{AtomicUsize, Ordering};
runtime()
.run(async |scope| {
let listener = net::listen("127.0.0.1", 0, scope).await.unwrap();
let port = listener.port().unwrap();
let limits = Limits {
connections: 1,
http2: Some(http::Http2Limits {
streams: 2,
..Default::default()
}),
..Default::default()
};
let active = Arc::new(AtomicUsize::new(0));
let peak = Arc::new(AtomicUsize::new(0));
let peak_read = peak.clone();
let incoming = listener.clone();
let server_limits = limits.clone();
let server = scope
.spawn(move |child| async move {
http::serve::<_, _, false>(
&incoming,
&server_limits,
&child,
move |request, _| {
let active = active.clone();
let peak = peak.clone();
async move {
let count = active.fetch_add(1, Ordering::SeqCst) + 1;
peak.fetch_max(count, Ordering::SeqCst);
tokio::time::sleep(Duration::from_millis(20)).await;
active.fetch_sub(1, Ordering::SeqCst);
Ok(Response {
status: 200,
headers: vec![],
body: request.body,
})
}
},
)
.await
})
.unwrap();
let client = http::client(
&format!("http://127.0.0.1:{port}"),
&tls::system(),
&limits,
&PoolLimits::default(),
scope,
)
.unwrap();
let replies =
futures_util::future::join_all((0..8).map(|_| client.request(message()))).await;
for response in replies {
assert_eq!(response.unwrap().body.as_ref(), b"pooled");
}
assert_eq!(peak_read.load(Ordering::SeqCst), 2);
let alias = client.clone();
let pending = scope
.spawn_leaf(move || async move { alias.request(message()).await })
.unwrap();
tokio::time::sleep(Duration::from_millis(5)).await;
client.close().await.unwrap();
assert!(pending.wait().await.unwrap().is_err());
listener.close().unwrap();
server.wait().await.unwrap().unwrap();
})
.unwrap();
}
#[test]
fn pool_http1_http2_tls_reuse_close_and_scope_ownership() {
for protocol in [false, true] {
for secure in [false, true] {
let escaped = runtime()
.run(async |scope| {
let listener = net::listen("127.0.0.1", 0, scope).await.unwrap();
let port = listener.port().unwrap();
let limits = Limits {
connections: 1,
http2: protocol.then(Default::default),
..Limits::default()
};
let incoming = listener.clone();
let server_limits = limits.clone();
let server = scope
.spawn(move |child| async move {
if secure {
let config =
tls::server(super::tls::CERTIFICATE, super::tls::KEY).unwrap();
http::serve_tls::<_, _, false>(
&incoming,
&server_limits,
&child,
&config,
route,
)
.await
} else {
http::serve::<_, _, false>(&incoming, &server_limits, &child, route)
.await
}
})
.unwrap();
let origin = format!(
"{}://localhost:{port}",
if secure { "https" } else { "http" }
);
let config = tls::client(super::tls::ROOT).unwrap();
let client =
http::client(&origin, &config, &limits, &PoolLimits::default(), scope)
.unwrap();
for _ in 0..3 {
assert_eq!(
client.request(message()).await.unwrap().body.as_ref(),
b"pooled"
);
}
let mut changed = message();
changed.headers.push(Header {
name: "Host".into(),
value: b"other.test".to_vec().into(),
});
assert!(client.request(changed).await.is_err());
client.close().await.unwrap();
client.close().await.unwrap();
assert!(client.request(message()).await.is_err());
listener.close().unwrap();
server.wait().await.unwrap().unwrap();
http::client(&origin, &config, &limits, &PoolLimits::default(), scope).unwrap()
})
.unwrap();
runtime()
.run(async |_| {
assert!(
escaped
.request(message())
.await
.unwrap_err()
.contains("closed")
);
escaped.close().await.unwrap();
})
.unwrap();
}
}
}
#[test]
fn pool_reuses_one_tcp_connection_and_closes_it_before_returning() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let port = listener.local_addr().unwrap().port();
let peer = std::thread::spawn(move || {
let (stream, _) = listener.accept().unwrap();
stream
.set_read_timeout(Some(Duration::from_secs(5)))
.unwrap();
let mut stream = BufReader::new(stream);
for _ in 0..3 {
let mut size = 0;
loop {
let mut line = String::new();
assert!(stream.read_line(&mut line).unwrap() > 0);
if line == "\r\n" {
break;
}
if let Some(length) = line.to_ascii_lowercase().strip_prefix("content-length:") {
size = length.trim().parse().unwrap();
}
}
let mut body = vec![0; size];
stream.read_exact(&mut body).unwrap();
assert_eq!(body, b"pooled");
stream
.get_mut()
.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok")
.unwrap();
}
assert_eq!(stream.read(&mut [0]).unwrap(), 0);
});
runtime()
.run(async |scope| {
let client = http::client(
&format!("http://127.0.0.1:{port}"),
&tls::system(),
&Limits::default(),
&PoolLimits::default(),
scope,
)
.unwrap();
for _ in 0..3 {
assert_eq!(
client.request(message()).await.unwrap().body.as_ref(),
b"ok"
);
}
client.close().await.unwrap();
})
.unwrap();
peer.join().unwrap();
}