From c6aa724060abafa561a97aa9eee27347a9d36195 Mon Sep 17 00:00:00 2001 From: "shiro.lee" Date: Thu, 4 Jul 2024 23:26:25 +0800 Subject: [PATCH] test: add net tet --- ecstore/Cargo.toml | 5 +- ecstore/src/endpoint.rs | 142 +++++++++++++++++++++++++++++++++++++++ ecstore/src/utils/net.rs | 58 +++++++++++----- 3 files changed, 184 insertions(+), 21 deletions(-) diff --git a/ecstore/Cargo.toml b/ecstore/Cargo.toml index 8b7a5d17d..538ed8b4e 100644 --- a/ecstore/Cargo.toml +++ b/ecstore/Cargo.toml @@ -17,6 +17,8 @@ async-trait.workspace = true tracing.workspace = true serde.workspace = true anyhow.workspace = true +time.workspace = true +serde_json.workspace = true url = "2.5.2" uuid = { version = "1.8.0", features = ["v4", "fast-rng", "serde"] } reed-solomon-erasure = "6.0.0" @@ -25,15 +27,12 @@ lazy_static = "1.5.0" regex = "1.10.5" netif = "0.1.6" tracing-error = "0.2.0" -serde_json.workspace = true path-absolutize = "3.1.1" -time.workspace = true rmp-serde = "1.3.0" tokio-util = { version = "0.7.11", features = ["io"] } s3s = "0.10.0" crc32fast = "1.4.2" siphasher = "1.0.1" - [dev-dependencies] tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } diff --git a/ecstore/src/endpoint.rs b/ecstore/src/endpoint.rs index 08f8dddad..887eecc1b 100644 --- a/ecstore/src/endpoint.rs +++ b/ecstore/src/endpoint.rs @@ -500,3 +500,145 @@ impl EndpointServerPools { nodes } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_new_endpoint() { + #[derive(Default)] + struct TestCase<'a> { + arg: &'a str, + expected_endpoint: Option, + expected_type: Option, + expected_err: Option, + } + + let u2 = url::Url::parse("https://example.org/path").unwrap(); + let u4 = url::Url::parse("http://192.168.253.200/path").unwrap(); + let root_slash_foo = url::Url::from_file_path("d:/foo").unwrap(); + + let test_cases = [ + TestCase { + arg: "d:/foo", + expected_endpoint: Some(Endpoint { + url: root_slash_foo, + is_local: true, + pool_idx: None, + set_idx: None, + disk_idx: None, + }), + expected_type: Some(EndpointType::Path), + expected_err: None, + }, + TestCase { + arg: "https://example.org/path", + expected_endpoint: Some(Endpoint { + url: u2, + is_local: false, + pool_idx: None, + set_idx: None, + disk_idx: None, + }), + expected_type: Some(EndpointType::Url), + expected_err: None, + }, + TestCase { + arg: "http://192.168.253.200/path", + expected_endpoint: Some(Endpoint { + url: u4, + is_local: false, + pool_idx: None, + set_idx: None, + disk_idx: None, + }), + expected_type: Some(EndpointType::Url), + expected_err: None, + }, + TestCase { + arg: "", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("empty or root endpoint is not supported")), + }, + TestCase { + arg: "/", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("empty or root endpoint is not supported")), + }, + TestCase { + arg: "\\", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("empty or root endpoint is not supported")), + }, + TestCase { + arg: "c://foo", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("invalid URL endpoint format")), + }, + TestCase { + arg: "ftp://foo", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("invalid URL endpoint format")), + }, + TestCase { + arg: "http://server/path?location", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("invalid URL endpoint format")), + }, + TestCase { + arg: "http://:/path", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("invalid URL endpoint format: invalid port number")), + }, + TestCase { + arg: "http://:8080/path", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("invalid URL endpoint format: empty host name")), + }, + TestCase { + arg: "http://server:/path", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("invalid URL endpoint format: invalid port number")), + }, + TestCase { + arg: "https://93.184.216.34:808080/path", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("invalid URL endpoint format: port number must be between 1 to 65535")), + }, + TestCase { + arg: "http://server:8080//", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("empty or root path is not supported in URL endpoint")), + }, + TestCase { + arg: "http://server:8080/", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("empty or root path is not supported in URL endpoint")), + }, + TestCase { + arg: "192.168.1.210:9000", + expected_endpoint: None, + expected_type: None, + expected_err: Some(Error::from_string("invalid URL endpoint format: missing scheme http or https")), + }, + ]; + + for test_case in test_cases { + let ret = Endpoint::try_from(test_case.arg); + println!("{:?}", ret) + } + } +} diff --git a/ecstore/src/utils/net.rs b/ecstore/src/utils/net.rs index e11690b45..d12293d95 100644 --- a/ecstore/src/utils/net.rs +++ b/ecstore/src/utils/net.rs @@ -1,12 +1,19 @@ use crate::error::{Error, Result}; +use lazy_static::lazy_static; use std::{ collections::HashSet, net::{IpAddr, SocketAddr, ToSocketAddrs}, }; use url::Host; +lazy_static! { + static ref LOCAL_IPS: Vec = must_get_local_ips().unwrap(); +} + /// helper for validating if the provided arg is an ip address. pub fn is_socket_addr(host: &str) -> bool { + // TODO IPv6 zone information? + host.parse::().is_ok() || host.parse::().is_ok() } @@ -30,7 +37,7 @@ pub fn check_local_server_addr(server_addr: &str) -> Result { SocketAddr::V6(a) => Host::Ipv6(*a.ip()), }; - if is_local_host(host, 0, 0).is_ok() { + if is_local_host(host, 0, 0)? { return Ok(a); } } @@ -38,22 +45,10 @@ pub fn check_local_server_addr(server_addr: &str) -> Result { Err(Error::from_string("host in server address should be this server")) } -pub fn split_host_port(s: &str) -> Result<(String, u16)> { - let parts: Vec<&str> = s.split(':').collect(); - if parts.len() == 2 { - if let Ok(port) = parts[1].parse::() { - return Ok((parts[0].to_string(), port)); - } - } - Err(Error::from_string("Invalid address format or port number")) -} - /// checks if the given parameter correspond to one of /// the local IP of the current machine pub fn is_local_host(host: Host<&str>, port: u16, local_port: u16) -> Result { - let local_ips = must_get_local_ips(); - - let local_set: HashSet = local_ips.into_iter().collect(); + let local_set: HashSet = LOCAL_IPS.iter().copied().collect(); let is_local_host = match host { Host::Domain(domain) => { let ips = match (domain, 0).to_socket_addrs().map(|v| v.map(|v| v.ip()).collect::>()) { @@ -75,10 +70,10 @@ pub fn is_local_host(host: Host<&str>, port: u16, local_port: u16) -> Result Vec { +fn must_get_local_ips() -> Result> { match netif::up() { - Ok(up) => up.map(|x| x.address().to_owned()).collect(), - Err(_) => vec![], + Ok(up) => Ok(up.map(|x| x.address().to_owned()).collect()), + Err(err) => Err(Error::from_string(format!("Unable to get IP addresses of this host: {}", err))), } } @@ -106,9 +101,36 @@ mod test { } } + #[test] + fn test_check_local_server_addr() { + let test_cases = [ + (":54321", Ok(())), + ("localhost:54321", Ok(())), + ("0.0.0.0:9000", Ok(())), + (":0", Ok(())), + ("localhost", Err(Error::from_string("invalid socket address"))), + ("", Err(Error::from_string("invalid socket address"))), + ( + "example.org:54321", + Err(Error::from_string("host in server address should be this server")), + ), + (":-10", Err(Error::from_string("invalid port value"))), + ]; + + for test_case in test_cases { + let ret = check_local_server_addr(test_case.0); + if test_case.1.is_ok() && ret.is_err() { + panic!("{}: error: expected = , got = {:?}", test_case.0, ret); + } + if test_case.1.is_err() && ret.is_ok() { + panic!("{}: error: expected = {:?}, got = ", test_case.0, test_case.1); + } + } + } + #[test] fn test_must_get_local_ips() { - let local_ips = must_get_local_ips(); + let local_ips = must_get_local_ips().unwrap(); let local_set: HashSet = local_ips.into_iter().collect(); assert!(local_set.contains(&IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))));