Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ pub(crate) async fn connect_tls_inner(
/// and runs them until one of them succeeds
/// or all of them fail.
///
/// If all connection attempts fail, returns the first error.
/// If all connection attempts fail, returns an error
/// that includes the reasons for all failures.
///
/// This functions starts with one connection attempt and maintains
/// up to five parallel connection attempts if connecting takes time.
Expand Down Expand Up @@ -209,6 +210,9 @@ where
}
}
None => {
// We should never return an error with connection attempts left to try.
debug_assert!(futures.next().is_none());

// Out of connection attempts.
//
// Break out of the loop and return error.
Expand Down Expand Up @@ -261,3 +265,43 @@ pub(crate) async fn connect_tcp(
.map(connect_tcp_inner);
run_connection_attempts(connection_futures).await
}

#[cfg(test)]
mod tests {
use super::*;

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_run_connection_attempts() {
let futures: Vec<Pin<Box<dyn Future<Output = Result<u32>> + Send>>> =
vec![Box::pin(async { Ok(1) }), Box::pin(async { Ok(2) })];
assert_eq!(
run_connection_attempts(futures.into_iter()).await.unwrap(),
1
);

let futures: Vec<Pin<Box<dyn Future<Output = Result<u32>> + Send>>> = vec![
Box::pin(async { Err(format_err!("fail")) }),
Box::pin(async { Ok(2) }),
];
assert_eq!(
run_connection_attempts(futures.into_iter()).await.unwrap(),
2
);

let futures: Vec<Pin<Box<dyn Future<Output = Result<u32>> + Send>>> = vec![
Box::pin(async { Err(format_err!("fail")) }),
Box::pin(async { Err(format_err!("fail")) }),
Box::pin(async { Err(format_err!("fail")) }),
Box::pin(async { Err(format_err!("fail")) }),
Box::pin(async { Err(format_err!("fail")) }),
Box::pin(async { Err(format_err!("last")) }),
];
assert!(
run_connection_attempts(futures.into_iter())
.await
.unwrap_err()
.to_string()
.contains("last"),
);
}
}