refactor: slop cleanup

This commit is contained in:
zhom
2025-07-31 05:28:45 +04:00
parent 63000c72bd
commit fc6ddb7cbf
9 changed files with 185 additions and 242 deletions
+12
View File
@@ -136,6 +136,18 @@ impl BrowserRunner {
url: Option<String>,
local_proxy_settings: Option<&ProxySettings>,
) -> Result<BrowserProfile, Box<dyn std::error::Error + Send + Sync>> {
// Check if browser is disabled due to ongoing update
let auto_updater = crate::auto_updater::AutoUpdater::new();
if auto_updater.is_browser_disabled(&profile.browser)? {
return Err(
format!(
"{} is currently being updated. Please wait for the update to complete.",
profile.browser
)
.into(),
);
}
// Handle camoufox profiles using nodecar launcher
if profile.browser == "camoufox" {
if let Some(mut camoufox_config) = profile.camoufox_config.clone() {
+2 -3
View File
@@ -86,8 +86,8 @@ impl Default for CamoufoxConfig {
additional_args: None,
env_vars: None,
firefox_prefs: None,
disable_theming: Some(true), // Required for anti-detect
showcursor: Some(false), // Required for anti-detect
disable_theming: Some(true),
showcursor: Some(false),
}
}
}
@@ -415,7 +415,6 @@ impl CamoufoxNodecarLauncher {
args.extend(["--firefox-prefs".to_string(), prefs_json]);
}
// Required anti-detect options
if let Some(disable_theming) = config.disable_theming {
if disable_theming {
args.push("--disable-theming".to_string());
-3
View File
@@ -82,9 +82,6 @@ impl TestUtils {
let mut cmd = Command::new(binary_path);
cmd.args(args);
// Add environment variable to ensure nodecar doesn't hang
cmd.env("NODE_ENV", "test");
let output = timeout(Duration::from_secs(timeout_secs), async {
tokio::process::Command::from(cmd).output().await
})
+144 -91
View File
@@ -12,25 +12,74 @@ async fn setup_test() -> Result<std::path::PathBuf, Box<dyn std::error::Error +
Ok(nodecar_path)
}
/// Cleanup function to ensure clean state after tests
async fn cleanup_test(nodecar_path: &std::path::PathBuf) {
let _ = TestUtils::cleanup_all_nodecar_processes(nodecar_path).await;
/// Helper to track and cleanup specific test resources
struct TestResourceTracker {
proxy_ids: Vec<String>,
camoufox_ids: Vec<String>,
nodecar_path: std::path::PathBuf,
}
/// Helper function to stop a specific camoufox by ID
async fn stop_camoufox_by_id(
nodecar_path: &std::path::PathBuf,
camoufox_id: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let stop_args = ["camoufox", "stop", "--id", camoufox_id];
let _ = TestUtils::execute_nodecar_command(nodecar_path, &stop_args, 10).await?;
Ok(())
impl TestResourceTracker {
fn new(nodecar_path: std::path::PathBuf) -> Self {
Self {
proxy_ids: Vec::new(),
camoufox_ids: Vec::new(),
nodecar_path,
}
}
fn track_proxy(&mut self, proxy_id: String) {
self.proxy_ids.push(proxy_id);
}
fn track_camoufox(&mut self, camoufox_id: String) {
self.camoufox_ids.push(camoufox_id);
}
async fn cleanup_all(&self) {
// Clean up tracked proxies
for proxy_id in &self.proxy_ids {
let stop_args = ["proxy", "stop", "--id", proxy_id];
let _ = TestUtils::execute_nodecar_command(&self.nodecar_path, &stop_args, 10).await;
}
// Clean up tracked camoufox instances
for camoufox_id in &self.camoufox_ids {
let stop_args = ["camoufox", "stop", "--id", camoufox_id];
let _ = TestUtils::execute_nodecar_command(&self.nodecar_path, &stop_args, 30).await;
}
// Give processes time to clean up
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
}
}
impl Drop for TestResourceTracker {
fn drop(&mut self) {
// Ensure cleanup happens even if test panics
let proxy_ids = self.proxy_ids.clone();
let camoufox_ids = self.camoufox_ids.clone();
let nodecar_path = self.nodecar_path.clone();
tokio::spawn(async move {
for proxy_id in &proxy_ids {
let stop_args = ["proxy", "stop", "--id", proxy_id];
let _ = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 10).await;
}
for camoufox_id in &camoufox_ids {
let stop_args = ["camoufox", "stop", "--id", camoufox_id];
let _ = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 30).await;
}
});
}
}
/// Integration tests for nodecar proxy functionality
#[tokio::test]
async fn test_nodecar_proxy_lifecycle() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
// Test proxy start with a known working upstream
let args = [
@@ -50,6 +99,7 @@ async fn test_nodecar_proxy_lifecycle() -> Result<(), Box<dyn std::error::Error
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
tracker.cleanup_all().await;
return Err(format!("Proxy start failed - stdout: {stdout}, stderr: {stderr}").into());
}
@@ -67,8 +117,9 @@ async fn test_nodecar_proxy_lifecycle() -> Result<(), Box<dyn std::error::Error
"Local URL should be a string"
);
let proxy_id = config["id"].as_str().unwrap();
let proxy_id = config["id"].as_str().unwrap().to_string();
let local_port = config["localPort"].as_u64().unwrap() as u16;
tracker.track_proxy(proxy_id.clone());
println!("Proxy started with ID: {proxy_id} on port: {local_port}");
@@ -80,7 +131,7 @@ async fn test_nodecar_proxy_lifecycle() -> Result<(), Box<dyn std::error::Error
);
// Test stopping the proxy
let stop_args = ["proxy", "stop", "--id", proxy_id];
let stop_args = ["proxy", "stop", "--id", &proxy_id];
let stop_output = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 10).await?;
assert!(stop_output.status.success(), "Proxy stop should succeed");
@@ -91,7 +142,7 @@ async fn test_nodecar_proxy_lifecycle() -> Result<(), Box<dyn std::error::Error
"Port should be available after stopping proxy"
);
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -99,6 +150,7 @@ async fn test_nodecar_proxy_lifecycle() -> Result<(), Box<dyn std::error::Error
#[tokio::test]
async fn test_nodecar_proxy_with_auth() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
let args = [
"proxy",
@@ -121,10 +173,8 @@ async fn test_nodecar_proxy_with_auth() -> Result<(), Box<dyn std::error::Error
let stdout = String::from_utf8(output.stdout)?;
let config: Value = serde_json::from_str(&stdout)?;
// Clean up
let proxy_id = config["id"].as_str().unwrap();
let stop_args = ["proxy", "stop", "--id", proxy_id];
let _ = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 10).await;
let proxy_id = config["id"].as_str().unwrap().to_string();
tracker.track_proxy(proxy_id.clone());
// Verify upstream URL contains encoded credentials
if let Some(upstream_url) = config["upstreamUrl"].as_str() {
@@ -140,7 +190,7 @@ async fn test_nodecar_proxy_with_auth() -> Result<(), Box<dyn std::error::Error
}
}
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -148,6 +198,7 @@ async fn test_nodecar_proxy_with_auth() -> Result<(), Box<dyn std::error::Error
#[tokio::test]
async fn test_nodecar_proxy_list() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
// Start a proxy first
let start_args = [
@@ -166,7 +217,8 @@ async fn test_nodecar_proxy_list() -> Result<(), Box<dyn std::error::Error + Sen
if start_output.status.success() {
let stdout = String::from_utf8(start_output.stdout)?;
let config: Value = serde_json::from_str(&stdout)?;
let proxy_id = config["id"].as_str().unwrap();
let proxy_id = config["id"].as_str().unwrap().to_string();
tracker.track_proxy(proxy_id.clone());
// Test list command
let list_args = ["proxy", "list"];
@@ -186,15 +238,11 @@ async fn test_nodecar_proxy_list() -> Result<(), Box<dyn std::error::Error + Sen
);
// Find our proxy in the list
let found_proxy = proxies.iter().find(|p| p["id"].as_str() == Some(proxy_id));
let found_proxy = proxies.iter().find(|p| p["id"].as_str() == Some(&proxy_id));
assert!(found_proxy.is_some(), "Started proxy should be in the list");
// Clean up
let stop_args = ["proxy", "stop", "--id", proxy_id];
let _ = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 10).await;
}
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -202,6 +250,7 @@ async fn test_nodecar_proxy_list() -> Result<(), Box<dyn std::error::Error + Sen
#[tokio::test]
async fn test_nodecar_camoufox_lifecycle() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
let temp_dir = TestUtils::create_temp_dir()?;
let profile_path = temp_dir.path().join("test_profile");
@@ -229,11 +278,11 @@ async fn test_nodecar_camoufox_lifecycle() -> Result<(), Box<dyn std::error::Err
|| stdout.contains("timeout")
{
println!("Skipping Camoufox test - Camoufox not available or timed out");
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
return Ok(());
}
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
return Err(format!("Camoufox start failed - stdout: {stdout}, stderr: {stderr}").into());
}
@@ -243,16 +292,17 @@ async fn test_nodecar_camoufox_lifecycle() -> Result<(), Box<dyn std::error::Err
// Verify Camoufox configuration structure
assert!(config["id"].is_string(), "Camoufox ID should be a string");
let camoufox_id = config["id"].as_str().unwrap();
let camoufox_id = config["id"].as_str().unwrap().to_string();
tracker.track_camoufox(camoufox_id.clone());
println!("Camoufox started with ID: {camoufox_id}");
// Test stopping Camoufox
let stop_args = ["camoufox", "stop", "--id", camoufox_id];
let stop_args = ["camoufox", "stop", "--id", &camoufox_id];
let stop_output = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 30).await?;
assert!(stop_output.status.success(), "Camoufox stop should succeed");
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -260,6 +310,7 @@ async fn test_nodecar_camoufox_lifecycle() -> Result<(), Box<dyn std::error::Err
#[tokio::test]
async fn test_nodecar_camoufox_with_url() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
let temp_dir = TestUtils::create_temp_dir()?;
let profile_path = temp_dir.path().join("test_profile_url");
@@ -281,7 +332,8 @@ async fn test_nodecar_camoufox_with_url() -> Result<(), Box<dyn std::error::Erro
let stdout = String::from_utf8(output.stdout)?;
let config: Value = serde_json::from_str(&stdout)?;
let camoufox_id = config["id"].as_str().unwrap();
let camoufox_id = config["id"].as_str().unwrap().to_string();
tracker.track_camoufox(camoufox_id.clone());
// Verify URL is set
if let Some(url) = config["url"].as_str() {
@@ -291,14 +343,17 @@ async fn test_nodecar_camoufox_with_url() -> Result<(), Box<dyn std::error::Erro
);
}
// Clean up
let _ = stop_camoufox_by_id(&nodecar_path, camoufox_id).await;
// Test stopping Camoufox explicitly
let stop_args = ["camoufox", "stop", "--id", &camoufox_id];
let stop_output = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 30).await?;
assert!(stop_output.status.success(), "Camoufox stop should succeed");
} else {
println!("Skipping Camoufox URL test - likely not installed");
tracker.cleanup_all().await;
return Ok(());
}
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -306,6 +361,7 @@ async fn test_nodecar_camoufox_with_url() -> Result<(), Box<dyn std::error::Erro
#[tokio::test]
async fn test_nodecar_camoufox_list() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let tracker = TestResourceTracker::new(nodecar_path.clone());
// Test list command (should work even without Camoufox installed)
let list_args = ["camoufox", "list"];
@@ -318,7 +374,7 @@ async fn test_nodecar_camoufox_list() -> Result<(), Box<dyn std::error::Error +
assert!(camoufox_list.is_array(), "Camoufox list should be an array");
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -327,6 +383,7 @@ async fn test_nodecar_camoufox_list() -> Result<(), Box<dyn std::error::Error +
async fn test_nodecar_camoufox_process_tracking(
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
let temp_dir = TestUtils::create_temp_dir()?;
let profile_path = temp_dir.path().join("test_profile_tracking");
@@ -355,16 +412,11 @@ async fn test_nodecar_camoufox_process_tracking(
// If Camoufox is not installed, skip the test
if stderr.contains("not installed") || stderr.contains("not found") {
println!("Skipping Camoufox process tracking test - Camoufox not installed");
// Clean up any instances that were started
for instance_id in &instance_ids {
let stop_args = ["camoufox", "stop", "--id", instance_id];
let _ = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 30).await;
}
tracker.cleanup_all().await;
return Ok(());
}
tracker.cleanup_all().await;
return Err(
format!("Camoufox instance {i} start failed - stdout: {stdout}, stderr: {stderr}").into(),
);
@@ -375,6 +427,7 @@ async fn test_nodecar_camoufox_process_tracking(
let camoufox_id = config["id"].as_str().unwrap().to_string();
instance_ids.push(camoufox_id.clone());
tracker.track_camoufox(camoufox_id.clone());
println!("Camoufox instance {i} started with ID: {camoufox_id}");
}
@@ -385,7 +438,7 @@ async fn test_nodecar_camoufox_process_tracking(
assert!(list_output.status.success(), "Camoufox list should succeed");
let list_stdout = String::from_utf8(list_output.stdout)?;
println!("Camoufox list output: {}", list_stdout);
println!("Camoufox list output: {list_stdout}");
let instances: Value = serde_json::from_str(&list_stdout)?;
let instances_array = instances.as_array().unwrap();
@@ -397,13 +450,10 @@ async fn test_nodecar_camoufox_process_tracking(
.iter()
.any(|i| i["id"].as_str() == Some(instance_id));
if !instance_found {
println!(
"Instance {} not found in list. Available instances:",
instance_id
);
println!("Instance {instance_id} not found in list. Available instances:");
for instance in instances_array {
if let Some(id) = instance["id"].as_str() {
println!(" - {}", id);
println!(" - {id}");
}
}
}
@@ -419,17 +469,19 @@ async fn test_nodecar_camoufox_process_tracking(
let stop_args = ["camoufox", "stop", "--id", instance_id];
let stop_output = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 30).await?;
assert!(
stop_output.status.success(),
"Camoufox stop should succeed for instance {instance_id}"
);
let stop_stdout = String::from_utf8(stop_output.stdout)?;
let stop_result: Value = serde_json::from_str(&stop_stdout)?;
assert!(
stop_result["success"].as_bool().unwrap_or(false),
"Stop result should indicate success for instance {instance_id}"
);
if stop_output.status.success() {
let stop_stdout = String::from_utf8(stop_output.stdout)?;
if let Ok(stop_result) = serde_json::from_str::<Value>(&stop_stdout) {
let success = stop_result["success"].as_bool().unwrap_or(false);
if !success {
println!("Warning: Stop command returned success=false for instance {instance_id}");
}
} else {
println!("Warning: Could not parse stop result for instance {instance_id}");
}
} else {
println!("Warning: Stop command failed for instance {instance_id}");
}
}
// Verify all instances are removed
@@ -449,7 +501,7 @@ async fn test_nodecar_camoufox_process_tracking(
}
println!("Camoufox process tracking test completed successfully");
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -458,6 +510,7 @@ async fn test_nodecar_camoufox_process_tracking(
async fn test_nodecar_camoufox_configuration_options(
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
let temp_dir = TestUtils::create_temp_dir()?;
let profile_path = temp_dir.path().join("test_profile_config");
@@ -481,7 +534,7 @@ async fn test_nodecar_camoufox_configuration_options(
];
println!("Starting Camoufox with configuration options...");
let output = TestUtils::execute_nodecar_command(&nodecar_path, &args, 15).await?;
let output = TestUtils::execute_nodecar_command(&nodecar_path, &args, 45).await?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
@@ -490,9 +543,11 @@ async fn test_nodecar_camoufox_configuration_options(
// If Camoufox is not installed, skip the test
if stderr.contains("not installed") || stderr.contains("not found") {
println!("Skipping Camoufox configuration test - Camoufox not installed");
tracker.cleanup_all().await;
return Ok(());
}
tracker.cleanup_all().await;
return Err(
format!("Camoufox with config start failed - stdout: {stdout}, stderr: {stderr}").into(),
);
@@ -501,7 +556,8 @@ async fn test_nodecar_camoufox_configuration_options(
let stdout = String::from_utf8(output.stdout)?;
let config: Value = serde_json::from_str(&stdout)?;
let camoufox_id = config["id"].as_str().unwrap();
let camoufox_id = config["id"].as_str().unwrap().to_string();
tracker.track_camoufox(camoufox_id.clone());
println!("Camoufox with configuration started with ID: {camoufox_id}");
// Verify configuration was applied by checking the profile path
@@ -512,11 +568,14 @@ async fn test_nodecar_camoufox_configuration_options(
);
}
// Clean up
let _ = stop_camoufox_by_id(&nodecar_path, camoufox_id).await;
// Test stopping Camoufox explicitly
let stop_args = ["camoufox", "stop", "--id", &camoufox_id];
let stop_output = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 30).await?;
assert!(stop_output.status.success(), "Camoufox stop should succeed");
println!("Camoufox configuration test completed successfully");
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -524,6 +583,7 @@ async fn test_nodecar_camoufox_configuration_options(
#[tokio::test]
async fn test_nodecar_command_validation() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let tracker = TestResourceTracker::new(nodecar_path.clone());
// Test invalid command
let invalid_args = ["invalid", "command"];
@@ -540,7 +600,7 @@ async fn test_nodecar_command_validation() -> Result<(), Box<dyn std::error::Err
"Incomplete proxy command should fail"
);
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -548,10 +608,10 @@ async fn test_nodecar_command_validation() -> Result<(), Box<dyn std::error::Err
#[tokio::test]
async fn test_nodecar_concurrent_proxies() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
// Start multiple proxies concurrently
let mut handles = vec![];
let mut proxy_ids: Vec<String> = vec![];
for i in 0..3 {
let nodecar_path_clone = nodecar_path.clone();
@@ -579,7 +639,7 @@ async fn test_nodecar_concurrent_proxies() -> Result<(), Box<dyn std::error::Err
let stdout = String::from_utf8(output.stdout)?;
let config: Value = serde_json::from_str(&stdout)?;
let proxy_id = config["id"].as_str().unwrap().to_string();
proxy_ids.push(proxy_id);
tracker.track_proxy(proxy_id.clone());
println!("Proxy {i} started successfully");
}
Ok(output) => {
@@ -592,13 +652,7 @@ async fn test_nodecar_concurrent_proxies() -> Result<(), Box<dyn std::error::Err
}
}
// Clean up all started proxies
for proxy_id in proxy_ids {
let stop_args = ["proxy", "stop", "--id", &proxy_id];
let _ = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 10).await;
}
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -606,6 +660,7 @@ async fn test_nodecar_concurrent_proxies() -> Result<(), Box<dyn std::error::Err
#[tokio::test]
async fn test_nodecar_proxy_types() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
let test_cases = vec![
("http", "httpbin.org", "80"),
@@ -631,11 +686,8 @@ async fn test_nodecar_proxy_types() -> Result<(), Box<dyn std::error::Error + Se
if output.status.success() {
let stdout = String::from_utf8(output.stdout)?;
let config: Value = serde_json::from_str(&stdout)?;
let proxy_id = config["id"].as_str().unwrap();
// Clean up
let stop_args = ["proxy", "stop", "--id", proxy_id];
let _ = TestUtils::execute_nodecar_command(&nodecar_path, &stop_args, 10).await;
let proxy_id = config["id"].as_str().unwrap().to_string();
tracker.track_proxy(proxy_id.clone());
println!("{proxy_type} proxy test passed");
} else {
@@ -644,7 +696,7 @@ async fn test_nodecar_proxy_types() -> Result<(), Box<dyn std::error::Error + Se
}
}
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}
@@ -653,6 +705,7 @@ async fn test_nodecar_proxy_types() -> Result<(), Box<dyn std::error::Error + Se
async fn test_nodecar_socks5_proxy_chaining() -> Result<(), Box<dyn std::error::Error + Send + Sync>>
{
let nodecar_path = setup_test().await?;
let mut tracker = TestResourceTracker::new(nodecar_path.clone());
// Step 1: Start a SOCKS5 proxy with a known working upstream (httpbin.org)
let socks5_args = [
@@ -672,14 +725,16 @@ async fn test_nodecar_socks5_proxy_chaining() -> Result<(), Box<dyn std::error::
if !socks5_output.status.success() {
let stderr = String::from_utf8_lossy(&socks5_output.stderr);
let stdout = String::from_utf8_lossy(&socks5_output.stdout);
tracker.cleanup_all().await;
return Err(format!("First proxy start failed - stdout: {stdout}, stderr: {stderr}").into());
}
let socks5_stdout = String::from_utf8(socks5_output.stdout)?;
let socks5_config: Value = serde_json::from_str(&socks5_stdout)?;
let socks5_proxy_id = socks5_config["id"].as_str().unwrap();
let socks5_proxy_id = socks5_config["id"].as_str().unwrap().to_string();
let socks5_local_port = socks5_config["localPort"].as_u64().unwrap() as u16;
tracker.track_proxy(socks5_proxy_id.clone());
println!("First proxy started with ID: {socks5_proxy_id} on port: {socks5_local_port}");
@@ -695,12 +750,9 @@ async fn test_nodecar_socks5_proxy_chaining() -> Result<(), Box<dyn std::error::
let http_output = TestUtils::execute_nodecar_command(&nodecar_path, &http_proxy_args, 30).await?;
if !http_output.status.success() {
// Clean up first proxy before failing
let stop_socks5_args = ["proxy", "stop", "--id", socks5_proxy_id, "--type", "socks5"];
let _ = TestUtils::execute_nodecar_command(&nodecar_path, &stop_socks5_args, 10).await;
let stderr = String::from_utf8_lossy(&http_output.stderr);
let stdout = String::from_utf8_lossy(&http_output.stdout);
tracker.cleanup_all().await;
return Err(
format!("Second proxy with chained upstream failed - stdout: {stdout}, stderr: {stderr}")
.into(),
@@ -710,8 +762,9 @@ async fn test_nodecar_socks5_proxy_chaining() -> Result<(), Box<dyn std::error::
let http_stdout = String::from_utf8(http_output.stdout)?;
let http_config: Value = serde_json::from_str(&http_stdout)?;
let http_proxy_id = http_config["id"].as_str().unwrap();
let http_proxy_id = http_config["id"].as_str().unwrap().to_string();
let http_local_port = http_config["localPort"].as_u64().unwrap() as u16;
tracker.track_proxy(http_proxy_id.clone());
println!(
"Second proxy started with ID: {http_proxy_id} on port: {http_local_port} (chained through first proxy)"
@@ -731,8 +784,8 @@ async fn test_nodecar_socks5_proxy_chaining() -> Result<(), Box<dyn std::error::
);
// Clean up both proxies
let stop_http_args = ["proxy", "stop", "--id", http_proxy_id];
let stop_socks5_args = ["proxy", "stop", "--id", socks5_proxy_id];
let stop_http_args = ["proxy", "stop", "--id", &http_proxy_id];
let stop_socks5_args = ["proxy", "stop", "--id", &socks5_proxy_id];
let http_stop_result =
TestUtils::execute_nodecar_command(&nodecar_path, &stop_http_args, 10).await;
@@ -762,6 +815,6 @@ async fn test_nodecar_socks5_proxy_chaining() -> Result<(), Box<dyn std::error::
);
println!("Proxy chaining test completed successfully");
cleanup_test(&nodecar_path).await;
tracker.cleanup_all().await;
Ok(())
}