From 309a2252c789162a893c0c3b7d43be637cf9a473 Mon Sep 17 00:00:00 2001 From: Congyu WANG Date: Thu, 25 Jul 2024 14:00:46 +0800 Subject: [PATCH] add tests for futures-io feature --- tests/common/futures_utils.rs | 105 +++++++++++++++++++++ tests/common/mod.rs | 17 ++++ tests/{common.rs => common/tokio_utils.rs} | 16 ++-- tests/integration_tests.sh | 2 +- tests/long_username_password_auth.rs | 33 ++++++- tests/no_auth.rs | 27 +++++- tests/socks4_no_auth.rs | 34 ++++++- tests/socks4_userid.rs | 40 +++++++- tests/username_auth.rs | 36 ++++++- 9 files changed, 289 insertions(+), 21 deletions(-) create mode 100644 tests/common/futures_utils.rs create mode 100644 tests/common/mod.rs rename tests/{common.rs => common/tokio_utils.rs} (83%) diff --git a/tests/common/futures_utils.rs b/tests/common/futures_utils.rs new file mode 100644 index 0000000..7e8f523 --- /dev/null +++ b/tests/common/futures_utils.rs @@ -0,0 +1,105 @@ +use super::*; +use async_std::{net::TcpListener, os::unix::net::UnixStream}; +use futures_util::{io::copy, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; +use once_cell::sync::OnceCell; +use std::{ + future::Future, + io::{Read, Write}, + net::{SocketAddr, TcpStream as StdTcpStream}, + sync::Mutex, +}; +use tokio_socks::{ + io::Compat, + tcp::{socks4::Socks4Listener, socks5::Socks5Listener}, + Error, + Result, +}; + +pub async fn echo_server() -> Result<()> { + let listener = TcpListener::bind(&SocketAddr::from(([0, 0, 0, 0], 10007))).await?; + loop { + let (stream, _) = listener.accept().await?; + async_std::task::spawn(async move { + let (mut reader, mut writer) = stream.split(); + copy(&mut reader, &mut writer).await.unwrap(); + }); + } +} + +pub async fn reply_response(mut socket: S) -> Result<[u8; 5]> { + socket.write_all(MSG).await?; + let mut buf = [0; 5]; + socket.read_exact(&mut buf).await?; + Ok(buf) +} + +pub async fn test_connect(socket: S) -> Result<()> { + let res = reply_response(socket).await?; + assert_eq!(&res[..], MSG); + Ok(()) +} + +pub fn test_bind( + listener: Socks5Listener>, +) -> Result<()> { + let bind_addr = listener.bind_addr().to_owned(); + runtime().lock().unwrap().spawn(async move { + let stream = listener.accept().await.unwrap(); + let (mut reader, mut writer) = stream.split(); + copy(&mut reader, &mut writer).await.unwrap(); + }); + + let mut tcp = StdTcpStream::connect(bind_addr)?; + tcp.write_all(MSG)?; + let mut buf = [0; 5]; + tcp.read_exact(&mut buf[..])?; + assert_eq!(&buf[..], MSG); + Ok(()) +} + +pub async fn connect_unix(proxy_addr: &str) -> Result { + UnixStream::connect(proxy_addr).await.map_err(Error::Io) +} + +pub struct Runtime; + +impl Runtime { + pub fn spawn(&self, future: F) + where + F: Future + Send + 'static, + T: Send + 'static, + { + async_std::task::spawn(future); + } + + pub fn block_on(&self, future: F) -> T + where F: Future { + async_std::task::block_on(future) + } +} + +pub fn runtime() -> &'static Mutex { + static RUNTIME: OnceCell> = OnceCell::new(); + RUNTIME.get_or_init(|| { + async_std::task::spawn(async { echo_server().await.expect("Unable to bind") }); + Mutex::new(Runtime) + }) +} + +pub fn test_bind_socks4( + listener: Socks4Listener>, +) -> Result<()> { + let bind_addr = listener.bind_addr().to_owned(); + runtime().lock().unwrap().spawn(async move { + let stream = listener.accept().await.unwrap(); + let (mut reader, mut writer) = AsyncReadExt::split(stream); + copy(&mut reader, &mut writer).await.unwrap(); + }); + + let mut tcp = StdTcpStream::connect(bind_addr)?; + tcp.write_all(MSG)?; + let mut buf = [0; 5]; + tcp.read_exact(&mut buf[..])?; + assert_eq!(&buf[..], MSG); + Ok(()) +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..1d1f391 --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,17 @@ +#![allow(dead_code)] +#[cfg(feature = "futures-io")] +pub mod futures_utils; +#[cfg(feature = "tokio")] +pub mod tokio_utils; + +#[cfg(feature = "futures-io")] +pub use tokio_socks::io::FuturesIoCompatExt as _; +#[cfg(feature = "tokio")] +pub use tokio_utils::*; + +pub const UNIX_PROXY_ADDR: &str = "/tmp/proxy.s"; +pub const PROXY_ADDR: &str = "127.0.0.1:41080"; +pub const UNIX_SOCKS4_PROXY_ADDR: &str = "/tmp/socks4_proxy.s"; +pub const SOCKS4_PROXY_ADDR: &str = "127.0.0.1:41081"; +pub const ECHO_SERVER_ADDR: &str = "localhost:10007"; +pub const MSG: &[u8] = b"hello"; diff --git a/tests/common.rs b/tests/common/tokio_utils.rs similarity index 83% rename from tests/common.rs rename to tests/common/tokio_utils.rs index 6d6c887..7982dfc 100644 --- a/tests/common.rs +++ b/tests/common/tokio_utils.rs @@ -1,3 +1,4 @@ +use super::*; use once_cell::sync::OnceCell; use std::{ io::{Read, Write}, @@ -9,14 +10,11 @@ use tokio::{ net::{TcpListener, UnixStream}, runtime::Runtime, }; -use tokio_socks::{tcp::socks4::Socks4Listener, tcp::socks5::Socks5Listener, Error, Result}; - -pub const UNIX_PROXY_ADDR: &'static str = "/tmp/proxy.s"; -pub const PROXY_ADDR: &'static str = "127.0.0.1:41080"; -pub const UNIX_SOCKS4_PROXY_ADDR: &'static str = "/tmp/socks4_proxy.s"; -pub const SOCKS4_PROXY_ADDR: &'static str = "127.0.0.1:41081"; -pub const ECHO_SERVER_ADDR: &'static str = "localhost:10007"; -pub const MSG: &[u8] = b"hello"; +use tokio_socks::{ + tcp::{socks4::Socks4Listener, socks5::Socks5Listener}, + Error, + Result, +}; pub async fn echo_server() -> Result<()> { let listener = TcpListener::bind(&SocketAddr::from(([0, 0, 0, 0], 10007))).await?; @@ -58,7 +56,7 @@ pub fn test_bind(listener: S Ok(()) } -pub async fn connect_unix(proxy_addr: &'static str) -> Result { +pub async fn connect_unix(proxy_addr: &str) -> Result { UnixStream::connect(proxy_addr).await.map_err(Error::Io) } diff --git a/tests/integration_tests.sh b/tests/integration_tests.sh index 100182e..3745638 100755 --- a/tests/integration_tests.sh +++ b/tests/integration_tests.sh @@ -24,7 +24,7 @@ sleep 2 for test in ${list}; do 3proxy ${dir}/${test}.cfg sleep 1 - cargo test --test ${test} -- --test-threads 1 + cargo test --test ${test} --all-features -- --test-threads 1 test_exit_code=$? pkill -F /tmp/3proxy-test.pid diff --git a/tests/long_username_password_auth.rs b/tests/long_username_password_auth.rs index 368a2d4..4f7b06c 100644 --- a/tests/long_username_password_auth.rs +++ b/tests/long_username_password_auth.rs @@ -1,11 +1,12 @@ mod common; -use common::{connect_unix, runtime, test_bind, test_connect, ECHO_SERVER_ADDR, PROXY_ADDR, UNIX_PROXY_ADDR}; +use common::*; use tokio_socks::{ tcp::socks5::{Socks5Listener, Socks5Stream}, Result, }; +#[cfg(feature = "tokio")] #[test] fn connect_long_username_password() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -15,6 +16,7 @@ fn connect_long_username_password() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_long_username_password() -> Result<()> { let bind = { @@ -29,6 +31,7 @@ fn bind_long_username_password() -> Result<()> { test_bind(bind) } +#[cfg(feature = "tokio")] #[test] fn connect_with_socket_long_username_password() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -39,6 +42,7 @@ fn connect_with_socket_long_username_password() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_with_socket_long_username_password() -> Result<()> { let bind = { @@ -53,3 +57,30 @@ fn bind_with_socket_long_username_password() -> Result<()> { }?; test_bind(bind) } + +#[cfg(feature = "futures-io")] +#[test] +fn connect_with_socket_long_username_password_futures_io() -> Result<()> { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime.block_on(futures_utils::connect_unix(UNIX_PROXY_ADDR))?.compat(); + let conn = runtime.block_on(Socks5Stream::connect_with_password_and_socket( + socket, ECHO_SERVER_ADDR, "mylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglogin", + "longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongpassword"))?; + runtime.block_on(futures_utils::test_connect(conn)) +} + +#[cfg(feature = "futures-io")] +#[test] +fn bind_with_socket_long_username_password_futures_io() -> Result<()> { + let bind = { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime.block_on(futures_utils::connect_unix(UNIX_PROXY_ADDR))?.compat(); + runtime.block_on(Socks5Listener::bind_with_password_and_socket( + socket, + ECHO_SERVER_ADDR, + "mylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglogin", + "longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongpassword" + )) + }?; + futures_utils::test_bind(bind) +} diff --git a/tests/no_auth.rs b/tests/no_auth.rs index cc75a3b..8bd5fb6 100644 --- a/tests/no_auth.rs +++ b/tests/no_auth.rs @@ -1,12 +1,12 @@ mod common; -use crate::common::{runtime, test_bind}; -use common::{connect_unix, test_connect, ECHO_SERVER_ADDR, PROXY_ADDR, UNIX_PROXY_ADDR}; +use common::*; use tokio_socks::{ tcp::socks5::{Socks5Listener, Socks5Stream}, Result, }; +#[cfg(feature = "tokio")] #[test] fn connect_no_auth() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -14,6 +14,7 @@ fn connect_no_auth() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_no_auth() -> Result<()> { let bind = { @@ -23,6 +24,7 @@ fn bind_no_auth() -> Result<()> { test_bind(bind) } +#[cfg(feature = "tokio")] #[test] fn connect_with_socket_no_auth() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -31,6 +33,7 @@ fn connect_with_socket_no_auth() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_with_socket_no_auth() -> Result<()> { let bind = { @@ -40,3 +43,23 @@ fn bind_with_socket_no_auth() -> Result<()> { }?; test_bind(bind) } + +#[cfg(feature = "futures-io")] +#[test] +fn connect_with_socket_no_auth_futures_io() -> Result<()> { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime.block_on(futures_utils::connect_unix(UNIX_PROXY_ADDR))?.compat(); + let conn = runtime.block_on(Socks5Stream::connect_with_socket(socket, ECHO_SERVER_ADDR))?; + runtime.block_on(futures_utils::test_connect(conn)) +} + +#[cfg(feature = "futures-io")] +#[test] +fn bind_with_socket_no_auth_futures_io() -> Result<()> { + let bind = { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime.block_on(futures_utils::connect_unix(UNIX_PROXY_ADDR))?.compat(); + runtime.block_on(Socks5Listener::bind_with_socket(socket, ECHO_SERVER_ADDR)) + }?; + futures_utils::test_bind(bind) +} diff --git a/tests/socks4_no_auth.rs b/tests/socks4_no_auth.rs index 891bcda..8d98ee3 100644 --- a/tests/socks4_no_auth.rs +++ b/tests/socks4_no_auth.rs @@ -1,14 +1,12 @@ mod common; -use crate::common::runtime; -use common::{ - connect_unix, test_bind_socks4, test_connect, ECHO_SERVER_ADDR, SOCKS4_PROXY_ADDR, UNIX_SOCKS4_PROXY_ADDR, -}; +use common::*; use tokio_socks::{ tcp::socks4::{Socks4Listener, Socks4Stream}, Result, }; +#[cfg(feature = "tokio")] #[test] fn connect_no_auth() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -16,6 +14,7 @@ fn connect_no_auth() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_no_auth() -> Result<()> { let bind = { @@ -25,6 +24,7 @@ fn bind_no_auth() -> Result<()> { test_bind_socks4(bind) } +#[cfg(feature = "tokio")] #[test] fn connect_with_socket_no_auth() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -34,6 +34,7 @@ fn connect_with_socket_no_auth() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_with_socket_no_auth() -> Result<()> { let bind = { @@ -43,3 +44,28 @@ fn bind_with_socket_no_auth() -> Result<()> { }?; test_bind_socks4(bind) } + +#[cfg(feature = "futures-io")] +#[test] +fn connect_with_socket_no_auth_futures_io() -> Result<()> { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime + .block_on(futures_utils::connect_unix(UNIX_SOCKS4_PROXY_ADDR))? + .compat(); + println!("socket connected"); + let conn = runtime.block_on(Socks4Stream::connect_with_socket(socket, ECHO_SERVER_ADDR))?; + runtime.block_on(futures_utils::test_connect(conn)) +} + +#[cfg(feature = "futures-io")] +#[test] +fn bind_with_socket_no_auth_futures_io() -> Result<()> { + let bind = { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime + .block_on(futures_utils::connect_unix(UNIX_SOCKS4_PROXY_ADDR))? + .compat(); + runtime.block_on(Socks4Listener::bind_with_socket(socket, ECHO_SERVER_ADDR)) + }?; + futures_utils::test_bind_socks4(bind) +} diff --git a/tests/socks4_userid.rs b/tests/socks4_userid.rs index e710de4..49586b4 100644 --- a/tests/socks4_userid.rs +++ b/tests/socks4_userid.rs @@ -1,10 +1,9 @@ mod common; -use common::{ - connect_unix, runtime, test_bind_socks4, test_connect, ECHO_SERVER_ADDR, SOCKS4_PROXY_ADDR, UNIX_SOCKS4_PROXY_ADDR, -}; +use common::*; use tokio_socks::{tcp::socks4::*, Result}; +#[cfg(feature = "tokio")] #[test] fn connect_userid() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -16,6 +15,7 @@ fn connect_userid() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_userid() -> Result<()> { let bind = { @@ -29,6 +29,7 @@ fn bind_userid() -> Result<()> { test_bind_socks4(bind) } +#[cfg(feature = "tokio")] #[test] fn connect_with_socket_userid() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -41,6 +42,7 @@ fn connect_with_socket_userid() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_with_socket_userid() -> Result<()> { let bind = { @@ -54,3 +56,35 @@ fn bind_with_socket_userid() -> Result<()> { }?; test_bind_socks4(bind) } + +#[cfg(feature = "futures-io")] +#[test] +fn connect_with_socket_userid_futures_io() -> Result<()> { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime + .block_on(futures_utils::connect_unix(UNIX_SOCKS4_PROXY_ADDR))? + .compat(); + let conn = runtime.block_on(Socks4Stream::connect_with_userid_and_socket( + socket, + ECHO_SERVER_ADDR, + "mylogin", + ))?; + runtime.block_on(futures_utils::test_connect(conn)) +} + +#[cfg(feature = "futures-io")] +#[test] +fn bind_with_socket_userid_futures_io() -> Result<()> { + let bind = { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime + .block_on(futures_utils::connect_unix(UNIX_SOCKS4_PROXY_ADDR))? + .compat(); + runtime.block_on(Socks4Listener::bind_with_user_and_socket( + socket, + ECHO_SERVER_ADDR, + "mylogin", + )) + }?; + futures_utils::test_bind_socks4(bind) +} diff --git a/tests/username_auth.rs b/tests/username_auth.rs index 7e2bcff..d9d4c53 100644 --- a/tests/username_auth.rs +++ b/tests/username_auth.rs @@ -1,11 +1,12 @@ mod common; -use common::{connect_unix, runtime, test_bind, test_connect, ECHO_SERVER_ADDR, PROXY_ADDR, UNIX_PROXY_ADDR}; +use common::*; use tokio_socks::{ tcp::socks5::{Socks5Listener, Socks5Stream}, Result, }; +#[cfg(feature = "tokio")] #[test] fn connect_username_auth() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -18,6 +19,7 @@ fn connect_username_auth() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_username_auth() -> Result<()> { let bind = { @@ -32,6 +34,7 @@ fn bind_username_auth() -> Result<()> { test_bind(bind) } +#[cfg(feature = "tokio")] #[test] fn connect_with_socket_username_auth() -> Result<()> { let runtime = runtime().lock().unwrap(); @@ -45,6 +48,7 @@ fn connect_with_socket_username_auth() -> Result<()> { runtime.block_on(test_connect(conn)) } +#[cfg(feature = "tokio")] #[test] fn bind_with_socket_username_auth() -> Result<()> { let bind = { @@ -59,3 +63,33 @@ fn bind_with_socket_username_auth() -> Result<()> { }?; test_bind(bind) } + +#[cfg(feature = "futures-io")] +#[test] +fn connect_with_socket_username_auth_futures_io() -> Result<()> { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime.block_on(futures_utils::connect_unix(UNIX_PROXY_ADDR))?.compat(); + let conn = runtime.block_on(Socks5Stream::connect_with_password_and_socket( + socket, + ECHO_SERVER_ADDR, + "mylogin", + "mypassword", + ))?; + runtime.block_on(futures_utils::test_connect(conn)) +} + +#[cfg(feature = "futures-io")] +#[test] +fn bind_with_socket_username_auth_futures_io() -> Result<()> { + let bind = { + let runtime = futures_utils::runtime().lock().unwrap(); + let socket = runtime.block_on(futures_utils::connect_unix(UNIX_PROXY_ADDR))?.compat(); + runtime.block_on(Socks5Listener::bind_with_password_and_socket( + socket, + ECHO_SERVER_ADDR, + "mylogin", + "mypassword", + )) + }?; + futures_utils::test_bind(bind) +}