From 5d1ac261aafe108bbf06ee1e377c1568b7917d6c Mon Sep 17 00:00:00 2001 From: Wukong Date: Thu, 14 Aug 2025 13:47:16 +0530 Subject: [PATCH] add integration test feature flag --- Cargo.toml | 5 +++ src/indexer/tracker_indexer.rs | 71 +++++++++++++++++++++++++++++++++- src/lib.rs | 20 +++++++++- src/main.rs | 9 +++++ src/server/tracker_monitor.rs | 8 +++- src/server/tracker_server.rs | 3 +- 6 files changed, 112 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 11fd552..0b17a9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,3 +27,8 @@ tokio-socks = "0.5.2" tokio-util = "0.7.15" tracing = "0.1.41" tracing-subscriber = "0.3.19" + + +[features] +default = [] +integration-test = [] \ No newline at end of file diff --git a/src/indexer/tracker_indexer.rs b/src/indexer/tracker_indexer.rs index c1b5aff..7874018 100644 --- a/src/indexer/tracker_indexer.rs +++ b/src/indexer/tracker_indexer.rs @@ -5,6 +5,7 @@ use r2d2::Pool; use tokio::{sync::mpsc::Sender, time::Instant}; use bitcoincore_rpc::bitcoin::absolute::{Height, LockTime}; +use std::str::FromStr; use tracing::info; use super::rpc::BitcoinRpc; @@ -38,7 +39,7 @@ pub async fn run( continue; } - if tx.output.len() < 2 { + if tx.output.len() < 2 || tx.output.len() > 5 { continue; } @@ -96,13 +97,23 @@ fn extract_onion_address_from_script(script: &[u8]) -> Option { let data = &script[data_start..data_start + data_len]; let decoded = String::from_utf8(data.to_vec()).ok()?; + + #[cfg(not(feature = "integration-test"))] if is_valid_onion_address(&decoded) { Some(decoded) } else { None } + + #[cfg(feature = "integration-test")] + if is_valid_address(&decoded) { + Some(decoded) + } else { + None + } } +#[cfg(not(feature = "integration-test"))] fn is_valid_onion_address(s: &str) -> bool { let parts: Vec<&str> = s.split(':').collect(); if parts.len() != 2 { @@ -115,3 +126,61 @@ fn is_valid_onion_address(s: &str) -> bool { } matches!(port.parse::(), Ok(p) if p > 0) } + +#[cfg(feature = "integration-test")] +fn is_valid_address(s: &str) -> bool { + let parts: Vec<&str> = s.split(':').collect(); + if parts.len() != 2 { + return false; + } + + let ip = parts[0]; + let port = parts[1]; + + if std::net::Ipv4Addr::from_str(ip).is_err() { + return false; + } + + matches!(port.parse::(), Ok(p) if p > 0) +} + +#[cfg(not(feature = "integration-test"))] +#[cfg(test)] +mod tests_onion { + use super::*; + + #[test] + fn test_valid_onion_address() { + assert!(is_valid_onion_address("example.onion:1234")); + assert!(is_valid_onion_address("abc1234567890def.onion:65535")); + } + + #[test] + fn test_invalid_onion_address() { + assert!(!is_valid_onion_address("example.com:1234")); + assert!(!is_valid_onion_address("example.onion:0")); + assert!(!is_valid_onion_address("example.onion")); + assert!(!is_valid_onion_address("127.0.0.1:8080")); + } +} + +#[cfg(feature = "integration-test")] +#[cfg(test)] +mod tests_ipv4 { + use super::*; + + #[test] + fn test_valid_ipv4_address() { + assert!(is_valid_address("127.0.0.1:8080")); + assert!(is_valid_address("192.168.1.1:65535")); + } + + #[test] + fn test_invalid_ipv4_address() { + assert!(!is_valid_address("example.onion:1234")); + assert!(!is_valid_address("256.0.0.1:8080")); + assert!(!is_valid_address("127.0.0.1:0")); + assert!(!is_valid_address("127.0.0.1")); + assert!(!is_valid_address("::1:8080")); + } +} diff --git a/src/lib.rs b/src/lib.rs index 298df41..b201f7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ mod utils; use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations}; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!(); +#[cfg(not(feature = "integration-test"))] #[derive(Debug, Clone)] pub struct Config { pub rpc_url: String, @@ -35,6 +36,15 @@ pub struct Config { pub datadir: String, } +#[cfg(feature = "integration-test")] +#[derive(Debug, Clone)] +pub struct Config { + pub rpc_url: String, + pub rpc_auth: Auth, + pub address: String, + pub datadir: String, +} + fn run_migrations(pool: Arc>>) { let mut conn = pool .get() @@ -58,10 +68,12 @@ pub async fn start(cfg: Config) { run_migrations(pool.clone()); info!("Connected to indexer db"); + #[cfg(not(feature = "integration-test"))] tor::check_tor_status(cfg.control_port, &cfg.tor_auth_password) .await .expect("Failed to check Tor status"); + #[cfg(not(feature = "integration-test"))] let hostname = match cfg.address.split_once(':') { Some((_, port)) => { let port = port.parse::().expect("Invalid port in address"); @@ -80,6 +92,9 @@ pub async fn start(cfg: Config) { } }; + #[cfg(feature = "integration-test")] + let hostname = cfg.address.clone(); + info!("Tracker is listening at {}", hostname); let (mut db_tx, db_rx) = mpsc::channel::(10); @@ -93,6 +108,7 @@ pub async fn start(cfg: Config) { db_tx.clone(), status_tx.clone(), cfg.address.clone(), + #[cfg(not(feature = "integration-test"))] cfg.socks_port, hostname.clone(), ) @@ -125,6 +141,7 @@ pub async fn start(cfg: Config) { db_tx.clone(), status_tx.clone(), cfg.address.clone(), + #[cfg(not(feature = "integration-test"))] cfg.socks_port, hostname.clone(), ) @@ -162,7 +179,7 @@ async fn spawn_server( db_tx: tokio::sync::mpsc::Sender, status_tx: tokio::sync::mpsc::Sender, address: String, - socks_port: u16, + #[cfg(not(feature = "integration-test"))] socks_port: u16, hostname: String, ) { info!("Spawning server instance"); @@ -170,6 +187,7 @@ async fn spawn_server( db_tx, status::Sender::Server(status_tx), address, + #[cfg(not(feature = "integration-test"))] socks_port, hostname, )); diff --git a/src/main.rs b/src/main.rs index 4416e06..a59aa7f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,6 +30,7 @@ async fn main() { (parts[0].to_string(), parts[1].to_string()) }; + #[cfg(not(feature = "integration-test"))] let cfg = Config { rpc_url: args.rpc, rpc_auth: Auth::UserPass(user, pass), @@ -40,5 +41,13 @@ async fn main() { datadir: args.datadir, }; + #[cfg(feature = "integration-test")] + let cfg = Config { + rpc_url: args.rpc, + rpc_auth: Auth::UserPass(user, pass), + address: args.address, + datadir: args.datadir, + }; + start(cfg).await; } diff --git a/src/server/tracker_monitor.rs b/src/server/tracker_monitor.rs index 9719045..c3a114f 100644 --- a/src/server/tracker_monitor.rs +++ b/src/server/tracker_monitor.rs @@ -1,5 +1,7 @@ use std::time::Duration; +#[cfg(feature = "integration-test")] +use tokio::net::TcpStream; use tokio::{ io::BufWriter, sync::mpsc::Sender, @@ -23,7 +25,7 @@ const COOLDOWN_PERIOD: u64 = 5; pub async fn monitor_systems( db_tx: Sender, status_tx: status::Sender, - socks_port: u16, + #[cfg(not(feature = "integration-test"))] socks_port: u16, onion_address: String, port: u16, ) -> Result<(), TrackerError> { @@ -45,12 +47,16 @@ pub async fn monitor_systems( let mut success = false; for attempt in 1..=3 { + #[cfg(not(feature = "integration-test"))] let connect_result = Socks5Stream::connect( format!("127.0.0.1:{socks_port:?}").as_str(), address.clone(), ) .await; + #[cfg(feature = "integration-test")] + let connect_result = TcpStream::connect(address.clone()).await; + match connect_result { Ok(mut stream) => { success = true; diff --git a/src/server/tracker_server.rs b/src/server/tracker_server.rs index 37c8a8d..51e92eb 100644 --- a/src/server/tracker_server.rs +++ b/src/server/tracker_server.rs @@ -19,7 +19,7 @@ pub async fn run( db_tx: Sender, status_tx: status::Sender, address: String, - socks_port: u16, + #[cfg(not(feature = "integration-test"))] socks_port: u16, onion_address: String, ) -> Result<(), Box> { let port = address @@ -31,6 +31,7 @@ pub async fn run( tokio::spawn(monitor_systems( db_tx.clone(), status_tx.clone(), + #[cfg(not(feature = "integration-test"))] socks_port, onion_address, port,