Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,233 @@
|
||||
use super::*;
|
||||
use tokio::sync::Notify;
|
||||
|
||||
#[test]
|
||||
fn head_and_disconnect_cancel_requests_before_reusing_the_connection() {
|
||||
runtime()
|
||||
.run(async |scope| {
|
||||
let listener = net::listen("127.0.0.1", 0, scope).await.unwrap();
|
||||
let incoming = listener.clone();
|
||||
let active = Arc::new(AtomicUsize::new(0));
|
||||
let running = active.clone();
|
||||
let server = scope
|
||||
.spawn(move |child| async move {
|
||||
http::serve_live(
|
||||
&incoming,
|
||||
&Limits::default(),
|
||||
&http::LiveLimits::default(),
|
||||
&child,
|
||||
move |request, reply, _| {
|
||||
let active = active.clone();
|
||||
async move {
|
||||
assert_eq!(active.fetch_add(1, Ordering::SeqCst), 0);
|
||||
let _running = Running(active);
|
||||
reply.start(200, vec![]).await.unwrap();
|
||||
if request.method == "HEAD" {
|
||||
std::future::pending::<()>().await;
|
||||
}
|
||||
reply.write(b"data").await.unwrap();
|
||||
std::future::pending::<Result<(), String>>().await
|
||||
}
|
||||
},
|
||||
)
|
||||
.await
|
||||
})
|
||||
.unwrap();
|
||||
let (mut sender, driver) = client(listener.port().unwrap(), scope).await;
|
||||
let response = sender.send_request(message("HEAD")).await.unwrap();
|
||||
assert!(
|
||||
response
|
||||
.into_body()
|
||||
.collect()
|
||||
.await
|
||||
.unwrap()
|
||||
.to_bytes()
|
||||
.is_empty()
|
||||
);
|
||||
assert_eq!(running.load(Ordering::SeqCst), 0);
|
||||
let response = sender.send_request(message("GET")).await.unwrap();
|
||||
let mut body = response.into_body();
|
||||
assert_eq!(
|
||||
body.frame().await.unwrap().unwrap().into_data().unwrap(),
|
||||
b"data"[..]
|
||||
);
|
||||
drop(body);
|
||||
drop(sender);
|
||||
driver.wait().await.unwrap();
|
||||
tokio::time::timeout(Duration::from_secs(2), async {
|
||||
while running.load(Ordering::SeqCst) != 0 {
|
||||
tokio::task::yield_now().await;
|
||||
}
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
listener.close().unwrap();
|
||||
server.wait().await.unwrap().unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slow_peer_bounds_writer_and_parent_stop_drains_blocking_descendants() {
|
||||
for sse in [false, true] {
|
||||
slow_peer_case(sse);
|
||||
}
|
||||
}
|
||||
|
||||
fn slow_peer_case(sse: bool) {
|
||||
runtime()
|
||||
.run(async |scope| {
|
||||
let listener = net::listen("127.0.0.1", 0, scope).await.unwrap();
|
||||
let incoming = listener.clone();
|
||||
let count = Arc::new(AtomicUsize::new(0));
|
||||
let written = count.clone();
|
||||
let active = Arc::new(AtomicUsize::new(0));
|
||||
let running = active.clone();
|
||||
let ready = Arc::new(Notify::new());
|
||||
let started = ready.clone();
|
||||
let server = scope
|
||||
.spawn(move |child| async move {
|
||||
http::serve_live(
|
||||
&incoming,
|
||||
&Limits {
|
||||
timeout_ms: 5000,
|
||||
..Limits::default()
|
||||
},
|
||||
&http::LiveLimits::default(),
|
||||
&child,
|
||||
move |_, reply, scope| {
|
||||
let written = written.clone();
|
||||
let active = active.clone();
|
||||
let ready = ready.clone();
|
||||
async move {
|
||||
let worker = scope
|
||||
.spawn(move |child| async move {
|
||||
child
|
||||
.blocking(move || {
|
||||
active.fetch_add(1, Ordering::SeqCst);
|
||||
let _running = Running(active);
|
||||
ready.notify_one();
|
||||
std::thread::sleep(Duration::from_millis(400));
|
||||
})
|
||||
.await
|
||||
})
|
||||
.unwrap();
|
||||
if sse {
|
||||
reply.sse_start(vec![]).await.unwrap();
|
||||
} else {
|
||||
reply.start(200, vec![]).await.unwrap();
|
||||
}
|
||||
let bytes = vec![0; 65536];
|
||||
let event = http::Event {
|
||||
event: String::new(),
|
||||
data: "a".repeat(65528),
|
||||
id: None,
|
||||
retry_ms: None,
|
||||
};
|
||||
for _ in 0..10000 {
|
||||
let result = if sse {
|
||||
reply.sse_send(&event).await
|
||||
} else {
|
||||
reply.write(&bytes).await
|
||||
};
|
||||
result.map_err(|error| error.to_string())?;
|
||||
written.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
worker.wait().await.unwrap().unwrap();
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
)
|
||||
.await
|
||||
})
|
||||
.unwrap();
|
||||
let mut socket =
|
||||
tokio::net::TcpStream::connect(("127.0.0.1", listener.port().unwrap() as u16))
|
||||
.await
|
||||
.unwrap();
|
||||
use tokio::io::AsyncWriteExt;
|
||||
socket
|
||||
.write_all(b"GET / HTTP/1.1\r\nHost: fixture.test\r\n\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
started.notified().await;
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
assert!(count.load(Ordering::SeqCst) < 10000);
|
||||
server.stop().await.unwrap();
|
||||
assert_eq!(running.load(Ordering::SeqCst), 0);
|
||||
listener.close().unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn live_header_and_idle_deadlines_are_distinct_and_faults_truncate() {
|
||||
runtime()
|
||||
.run(async |scope| {
|
||||
for mode in ["headers", "idle", "fault", "missing"] {
|
||||
let gate = Arc::new(Semaphore::new(0));
|
||||
let failed = gate.clone();
|
||||
let listener = net::listen("127.0.0.1", 0, scope).await.unwrap();
|
||||
let incoming = listener.clone();
|
||||
let server = scope
|
||||
.spawn(move |child| async move {
|
||||
http::serve_live(
|
||||
&incoming,
|
||||
&Limits {
|
||||
timeout_ms: 100,
|
||||
..Limits::default()
|
||||
},
|
||||
&http::LiveLimits {
|
||||
idle_ms: 60,
|
||||
heartbeat_ms: 20,
|
||||
chunk_bytes: 64,
|
||||
},
|
||||
&child,
|
||||
move |_, reply, _| {
|
||||
let gate = failed.clone();
|
||||
async move {
|
||||
if mode == "missing" {
|
||||
return Ok(());
|
||||
}
|
||||
if mode == "headers" {
|
||||
std::future::pending::<()>().await;
|
||||
}
|
||||
reply.start(200, vec![]).await.unwrap();
|
||||
if mode == "idle" {
|
||||
std::future::pending::<()>().await;
|
||||
}
|
||||
reply.write(b"partial").await.unwrap();
|
||||
let _permit = gate.acquire().await.unwrap();
|
||||
Err("located handler failure".into())
|
||||
}
|
||||
},
|
||||
)
|
||||
.await
|
||||
})
|
||||
.unwrap();
|
||||
let (mut sender, driver) = client(listener.port().unwrap(), scope).await;
|
||||
let response = sender.send_request(message("GET")).await.unwrap();
|
||||
match mode {
|
||||
"headers" => assert_eq!(response.status(), 504),
|
||||
"missing" => assert_eq!(response.status(), 500),
|
||||
_ => {
|
||||
assert_eq!(response.status(), 200);
|
||||
let mut body = response.into_body();
|
||||
if mode == "fault" {
|
||||
assert_eq!(
|
||||
body.frame().await.unwrap().unwrap().into_data().unwrap(),
|
||||
b"partial"[..]
|
||||
);
|
||||
gate.add_permits(1);
|
||||
}
|
||||
assert!(body.collect().await.is_err());
|
||||
}
|
||||
}
|
||||
drop(sender);
|
||||
driver.wait().await.unwrap();
|
||||
listener.close().unwrap();
|
||||
server.wait().await.unwrap().unwrap();
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
Reference in new issue
Block a user