Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6d64107
fix(test): fix all unit tests for macOS Apple Silicon
litcc Mar 1, 2026
6504d5c
refactor(docker-utils): simplify container_ip and gateway_ip methods
litcc Mar 2, 2026
1cfb691
Merge branch 'master' into fix/unit-tests
ibigbug Mar 3, 2026
83479d7
feat(docker-test): support remote Docker connections via DOCKER_HOST
litcc Mar 3, 2026
61a3e63
Add GIT_CURL_VERBOSE and GIT_TRACE to CI config
Itsusinn Mar 3, 2026
b20b145
Update ci.yml
Itsusinn Mar 3, 2026
de572a4
feat(docker-test): add docker_gateway_ip method and update tests to u…
litcc Mar 3, 2026
ad1f0e8
Merge branch 'fix/unit-tests' into fix/unit-tests2
litcc Mar 3, 2026
bf88417
Update ci.yml
Itsusinn Mar 3, 2026
cdce863
fix(docker-test): docker remote mounts
litcc Mar 4, 2026
cf2501f
fix(docker-test): update container_ip method
litcc Mar 5, 2026
7aa059d
fix(docker-test): bug
litcc Mar 5, 2026
8300798
fix(docker-test): bugs and unit tests
litcc Mar 5, 2026
cd27e66
fix(docker-test): code warnings
litcc Mar 5, 2026
5fb33d6
fix(docker-test): bugs and unit tests
litcc Mar 5, 2026
7c5785f
fix(docker-test): bug
litcc Mar 5, 2026
2bd08b1
Merge branch 'master' into fix/unit-tests2
litcc Mar 7, 2026
298710c
fix(test_hysteria): resolve Windows-specific test failures
litcc Mar 8, 2026
bfa5c64
fix(test): resolve DNS handler test port conflicts
litcc Mar 8, 2026
fd7c3a7
Merge branch 'fix/unit-tests2' into fix/unit-tests
litcc Mar 8, 2026
9735648
fix(docker-test): bug
litcc Mar 9, 2026
a4ed931
fix(docker-test): bug
litcc Mar 10, 2026
e0a9e61
fix(docker-test): bug
litcc Mar 10, 2026
b7549ff
fix(docker-test): bug
litcc Mar 10, 2026
4f009cf
fix(clippy): resolve clippy warnings and improve code quality
litcc Mar 10, 2026
e807fed
Merge branch 'master' into fix/unit-tests
litcc Mar 10, 2026
1d2e1d7
fix(test): some writing issues
litcc Mar 11, 2026
8e2601b
fix(clippy): some
litcc Mar 11, 2026
fdae7b8
fix(test): test_connections_returns_proxy_chain_names
litcc Mar 12, 2026
4241e8f
Merge branch 'master' into fix/unit-tests-3
litcc Mar 12, 2026
a17b40b
fix(deps): Handling merged dependency issues
litcc Mar 12, 2026
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
28 changes: 28 additions & 0 deletions clash-bin/tests/data/config/socks5-auth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"log": {
"loglevel": "debug"
},
"inbounds": [
{
"port": 10002,
"listen": "0.0.0.0",
"protocol": "socks",
"settings": {
"auth": "password",
"accounts": [
{
"user": "user",
"pass": "password"
}
],
"udp": true,
"ip": "0.0.0.0"
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
22 changes: 22 additions & 0 deletions clash-bin/tests/data/config/socks5-noauth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"log": {
"loglevel": "debug"
},
"inbounds": [
{
"port": 10002,
"listen": "0.0.0.0",
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true,
"ip": "0.0.0.0"
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,10 @@ mod tests {
mock_vehicle.expect_read().returning(|| {
Ok(r#"
proxies:
- name: "ss"
type: ss
- name: "socks5"
type: socks5
server: localhost
port: 8388
cipher: aes-256-gcm
password: "password"
port: 1080
udp: true
"#
.as_bytes()
Expand Down
22 changes: 13 additions & 9 deletions clash-lib/src/proxy/group/relay/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,18 +208,20 @@ mod tests {

use tokio::sync::RwLock;

use crate::proxy::{
mocks::MockDummyProxyProvider,
utils::test_utils::{
Suite,
consts::*,
docker_runner::{DockerTestRunner, DockerTestRunnerBuilder},
run_test_suites_and_cleanup,
use super::*;
use crate::{
proxy::{
mocks::MockDummyProxyProvider,
utils::test_utils::{
Suite,
consts::*,
docker_runner::{DockerTestRunner, DockerTestRunnerBuilder},
run_test_suites_and_cleanup,
},
},
tests::initialize,
};

use super::*;

const PASSWORD: &str = "FzcLbKs2dY9mhL";
const CIPHER: &str = "aes-256-gcm";

Expand All @@ -236,6 +238,7 @@ mod tests {
#[tokio::test]
#[serial_test::serial]
async fn test_relay_1() -> anyhow::Result<()> {
initialize();
let ss_opts = crate::proxy::shadowsocks::outbound::HandlerOptions {
name: "test-ss".to_owned(),
common_opts: Default::default(),
Expand Down Expand Up @@ -273,6 +276,7 @@ mod tests {
#[tokio::test]
#[serial_test::serial]
async fn test_relay_2() -> anyhow::Result<()> {
initialize();
let ss_opts = crate::proxy::shadowsocks::outbound::HandlerOptions {
name: "test-ss".to_owned(),
common_opts: Default::default(),
Expand Down
4 changes: 3 additions & 1 deletion clash-lib/src/proxy/group/smart/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ mod tests {
run_test_suites_and_cleanup,
},
},
tests::initialize,
};
use tempfile::tempdir;
use tokio::sync::RwLock;
Expand All @@ -783,7 +784,8 @@ mod tests {
#[tokio::test]
#[serial_test::serial]
async fn test_smart_group_smoke() -> anyhow::Result<()> {
let ss_port = 10003;
initialize();
let ss_port = 10002;
let ss_opts = crate::proxy::shadowsocks::outbound::HandlerOptions {
name: "test-ss-for-smart".to_owned(),
common_opts: Default::default(),
Expand Down
10 changes: 8 additions & 2 deletions clash-lib/src/proxy/shadowsocks/outbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ mod tests {
let host = format!("0.0.0.0:{}", port);
DockerTestRunnerBuilder::new()
.image(IMAGE_SS_RUST)
.port(port)
.entrypoint(&["ssserver"])
.cmd(&["-s", &host, "-m", CIPHER, "-k", PASSWORD, "-U", "-vvv"])
.build()
Expand All @@ -280,6 +281,7 @@ mod tests {
let host = format!("0.0.0.0:{}", port);
DockerTestRunnerBuilder::new()
.image(IMAGE_SS_RUST)
.port(port)
.entrypoint(&["ssserver"])
.cmd(&[
"-s",
Expand Down Expand Up @@ -340,7 +342,9 @@ mod tests {
ss_port: u16,
stls_port: u16,
) -> anyhow::Result<DockerTestRunner> {
let ss_server_env = format!("SERVER=127.0.0.1:{}", ss_port);
// Use host.docker.internal to access SS server running in another
// container via host port mapping
let ss_server_env = format!("SERVER=host.docker.internal:{}", ss_port);
Comment thread
ibigbug marked this conversation as resolved.
Outdated
let listen_env = format!("LISTEN=0.0.0.0:{}", stls_port);
let password = format!("PASSWORD={}", SHADOW_TLS_PASSWORD);
DockerTestRunnerBuilder::new()
Expand All @@ -363,6 +367,7 @@ mod tests {
#[tokio::test]
#[serial_test::serial]
async fn test_shadowtls() -> anyhow::Result<()> {
initialize();
// the real port that used for communication
let shadow_tls_port = 10002;
// not important, you can assign any port that is not conflict with
Expand Down Expand Up @@ -398,7 +403,7 @@ mod tests {
obfs_port: u16,
mode: SimpleOBFSMode,
) -> anyhow::Result<DockerTestRunner> {
let ss_server_env = format!("127.0.0.1:{}", ss_port);
let ss_server_env = format!("host.docker.internal:{}", ss_port);
let port = format!("{}", obfs_port);
let mode = match mode {
SimpleOBFSMode::Http => "http",
Expand Down Expand Up @@ -453,6 +458,7 @@ mod tests {
#[tokio::test]
#[serial_test::serial]
async fn test_ss_obfs_http() -> anyhow::Result<()> {
initialize();
test_ss_obfs_inner(SimpleOBFSMode::Http).await
}

Expand Down
95 changes: 42 additions & 53 deletions clash-lib/src/proxy/socks/outbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,102 +262,91 @@ mod tests {

use std::sync::Arc;

use crate::proxy::{
socks::outbound::{Handler, HandlerOptions},
utils::{
GLOBAL_DIRECT_CONNECTOR,
test_utils::{
Suite,
consts::{IMAGE_SOCKS5, LOCAL_ADDR},
docker_runner::{DockerTestRunner, DockerTestRunnerBuilder},
run_test_suites_and_cleanup,
use crate::{
proxy::{
socks::outbound::{Handler, HandlerOptions},
utils::{
GLOBAL_DIRECT_CONNECTOR,
test_utils::{
Suite,
consts::{IMAGE_SOCKS5, LOCAL_ADDR},
docker_runner::{DockerTestRunner, DockerTestRunnerBuilder},
run_test_suites_and_cleanup,
},
},
},
tests::initialize,
};

use super::super::super::utils::test_utils::docker_utils::config_helper::test_config_base_dir;

const USER: &str = "user";
const PASSWORD: &str = "password";

async fn get_socks5_runner(
port: u16,
username: Option<String>,
password: Option<String>,
) -> anyhow::Result<DockerTestRunner> {
let host = format!("0.0.0.0:{}", port);
let username = username.unwrap_or_default();
let password = password.unwrap_or_default();
let cmd = if !username.is_empty() && !password.is_empty() {
vec![
"-a",
&host,
"-u",
username.as_str(),
"-p",
password.as_str(),
]
async fn get_socks5_runner(auth: bool) -> anyhow::Result<DockerTestRunner> {
let test_config_dir = test_config_base_dir();
let conf = if auth {
test_config_dir.join("socks5-auth.json")
} else {
vec!["-a", &host]
test_config_dir.join("socks5-noauth.json")
};

DockerTestRunnerBuilder::new()
.image(IMAGE_SOCKS5)
.cmd(&cmd)
.mounts(&[(conf.to_str().unwrap(), "/etc/v2ray/config.json")])
.build()
.await
}

fn server_addr(runner: &DockerTestRunner) -> String {
if cfg!(target_os = "macos") {
runner.container_ip().expect("container IP not found")
} else {
LOCAL_ADDR.to_owned()
}
}

#[tokio::test]
#[serial_test::serial]
async fn test_socks5_no_auth() -> anyhow::Result<()> {
initialize();
let port = 10002;
let runner = get_socks5_runner(false).await?;
let opts = HandlerOptions {
name: "test-socks5-no-auth".to_owned(),
common_opts: Default::default(),
server: LOCAL_ADDR.to_owned(),
port: 10002,
server: server_addr(&runner),
port,
user: None,
password: None,
udp: true,
..Default::default()
};
let port = opts.port;
let handler = Arc::new(Handler::new(opts));
run_test_suites_and_cleanup(
handler,
get_socks5_runner(port, None, None).await?,
Suite::all(),
)
.await
run_test_suites_and_cleanup(handler, runner, Suite::all()).await
}

#[tokio::test]
#[serial_test::serial]
async fn test_socks5_auth() -> anyhow::Result<()> {
use crate::proxy::DialWithConnector;

initialize();
let port = 10002;
let runner = get_socks5_runner(true).await?;
let opts = HandlerOptions {
name: "test-socks5-no-auth".to_owned(),
name: "test-socks5-auth".to_owned(),
common_opts: Default::default(),
server: LOCAL_ADDR.to_owned(),
port: 10002,
server: server_addr(&runner),
port,
user: Some(USER.to_owned()),
password: Some(PASSWORD.to_owned()),
udp: true,
..Default::default()
};
let port = opts.port;
let handler = Arc::new(Handler::new(opts));
handler
.register_connector(GLOBAL_DIRECT_CONNECTOR.clone())
.await;
run_test_suites_and_cleanup(
handler,
get_socks5_runner(
port,
Some(USER.to_owned()),
Some(PASSWORD.to_owned()),
)
.await?,
Suite::all(),
)
.await
run_test_suites_and_cleanup(handler, runner, Suite::all()).await
}
}
23 changes: 13 additions & 10 deletions clash-lib/src/proxy/trojan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,19 +217,21 @@ mod tests {

use std::collections::HashMap;

use crate::proxy::{
transport,
utils::test_utils::{
Suite,
config_helper::test_config_base_dir,
consts::*,
docker_runner::{DockerTestRunner, DockerTestRunnerBuilder},
run_test_suites_and_cleanup,
use super::*;
use crate::{
proxy::{
transport,
utils::test_utils::{
Suite,
config_helper::test_config_base_dir,
consts::*,
docker_runner::{DockerTestRunner, DockerTestRunnerBuilder},
run_test_suites_and_cleanup,
},
},
tests::initialize,
};

use super::*;

async fn get_ws_runner() -> anyhow::Result<DockerTestRunner> {
let test_config_dir = test_config_base_dir();
let trojan_conf = test_config_dir.join("trojan-ws.json");
Expand Down Expand Up @@ -305,6 +307,7 @@ mod tests {
#[tokio::test]
#[serial_test::serial]
async fn test_trojan_grpc() -> anyhow::Result<()> {
initialize();
let transport = transport::GrpcClient::new(
"example.org".to_owned(),
"example"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub const IMAGE_TROJAN_GO: &str = "p4gefau1t/trojan-go:latest";
pub const IMAGE_VMESS: &str = "v2fly/v2fly-core:v4.45.2";
pub const IMAGE_VLESS: &str = "v2fly/v2fly-core:v4.45.2";
pub const IMAGE_XRAY: &str = "teddysun/xray:latest";
pub const IMAGE_SOCKS5: &str = "ghcr.io/wzshiming/socks5/socks5:v0.4.3";
pub const IMAGE_SOCKS5: &str = "v2fly/v2fly-core:v4.45.2";
#[cfg(feature = "ssh")]
pub const IMAGE_OPENSSH: &str = "docker.io/linuxserver/openssh-server:latest";
pub const IMAGE_HYSTERIA: &str = "tobyxdd/hysteria:latest";
Expand Down
Loading
Loading