Skip to content

Commit f30be3b

Browse files
committed
Add a test for connection timeouts
1 parent fa9359c commit f30be3b

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

.github/workflows/cont_integration.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ jobs:
3131
run: cargo fmt -- --check --verbose
3232
- name: Test
3333
run: cargo test --verbose --all-features
34+
- name: Setup iptables for the timeout test
35+
run: sudo ip6tables -I INPUT 1 -p tcp -d ::1 --dport 60000 -j DROP
36+
- name: Timeout test
37+
run: cargo test -- --ignored test_local_timeout
3438
- run: cargo check --verbose --features=use-openssl
3539
- run: cargo check --verbose --no-default-features --features=proxy
3640
- run: cargo check --verbose --no-default-features --features=minimal

src/client.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,4 +341,55 @@ mod tests {
341341

342342
assert_eq!(exhausted, false)
343343
}
344+
345+
#[test]
346+
#[ignore]
347+
fn test_local_timeout() {
348+
// This test assumes a couple things:
349+
// - that `localhost` is resolved to two IP addresses, `127.0.0.1` and `::1` (with the v6
350+
// one having higher priority)
351+
// - that the system silently drops packets to `[::1]:60000` or a different port if
352+
// specified through `TEST_ELECTRUM_TIMEOUT_PORT`
353+
//
354+
// this can be setup with: ip6tables -I INPUT 1 -p tcp -d ::1 --dport 60000 -j DROP
355+
// and removed with: ip6tables -D INPUT -p tcp -d ::1 --dport 60000 -j DROP
356+
//
357+
// The test tries to create a client to `localhost` and expects it to succeed, but only
358+
// after at least 2 seconds have passed which is roughly the timeout time for the first
359+
// try.
360+
361+
use std::net::TcpListener;
362+
use std::sync::mpsc::channel;
363+
use std::time::{Duration, Instant};
364+
365+
let endpoint =
366+
std::env::var("TEST_ELECTRUM_TIMEOUT_PORT").unwrap_or("localhost:60000".into());
367+
let (sender, receiver) = channel();
368+
369+
std::thread::spawn(move || {
370+
let listener = TcpListener::bind("127.0.0.1:60000").unwrap();
371+
sender.send(()).unwrap();
372+
373+
for _stream in listener.incoming() {
374+
loop {}
375+
}
376+
});
377+
378+
receiver
379+
.recv_timeout(Duration::from_secs(5))
380+
.expect("Can't start local listener");
381+
382+
let now = Instant::now();
383+
let client = Client::from_config(
384+
&endpoint,
385+
crate::config::ConfigBuilder::new()
386+
.timeout(Some(5))
387+
.unwrap()
388+
.build(),
389+
);
390+
let elapsed = now.elapsed();
391+
392+
assert!(client.is_ok());
393+
assert!(elapsed > Duration::from_secs(2));
394+
}
344395
}

0 commit comments

Comments
 (0)