From 4cffe9cc31b3c9573f5240be4dd52ba2d1758176 Mon Sep 17 00:00:00 2001 From: DanGould Date: Mon, 30 Dec 2024 16:48:54 -0500 Subject: [PATCH] Have ohttp_relay give US a port Previously, the ohttp_relay::listen_tcp, similar to the directory task, attempted to listen on a given free port, which occasionally caused test crashes due to port contention. The new version of ohttp_relay follows the same pattern as payjoin-directory so that we can test reliably. --- Cargo-minimal.lock | 3 +-- Cargo-recent.lock | 3 +-- payjoin-cli/Cargo.toml | 2 +- payjoin-cli/tests/e2e.rs | 19 ++++++++------ payjoin/Cargo.toml | 2 +- payjoin/tests/integration.rs | 49 ++++++++++++++++++++---------------- 6 files changed, 43 insertions(+), 35 deletions(-) diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock index f9fbea2e..d2a145f0 100644 --- a/Cargo-minimal.lock +++ b/Cargo-minimal.lock @@ -1451,8 +1451,7 @@ dependencies = [ [[package]] name = "ohttp-relay" version = "0.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7850c40a0aebcba289d3252c0a45f93cba6ad4b0c46b88a5fc51dba6ddce8632" +source = "git+https://github.com/payjoin/ohttp-relay?rev=d3f853f#d3f853f9186045a4334e248ac9f92399387673b9" dependencies = [ "futures", "http", diff --git a/Cargo-recent.lock b/Cargo-recent.lock index f9fbea2e..d2a145f0 100644 --- a/Cargo-recent.lock +++ b/Cargo-recent.lock @@ -1451,8 +1451,7 @@ dependencies = [ [[package]] name = "ohttp-relay" version = "0.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7850c40a0aebcba289d3252c0a45f93cba6ad4b0c46b88a5fc51dba6ddce8632" +source = "git+https://github.com/payjoin/ohttp-relay?rev=d3f853f#d3f853f9186045a4334e248ac9f92399387673b9" dependencies = [ "futures", "http", diff --git a/payjoin-cli/Cargo.toml b/payjoin-cli/Cargo.toml index bd7fa1fa..f163c841 100644 --- a/payjoin-cli/Cargo.toml +++ b/payjoin-cli/Cargo.toml @@ -50,7 +50,7 @@ url = { version = "2.3.1", features = ["serde"] } [dev-dependencies] bitcoind = { version = "0.36.0", features = ["0_21_2"] } http = "1" -ohttp-relay = "0.0.8" +ohttp-relay = { version = "0.0.8", git = "https://github.com/payjoin/ohttp-relay", rev = "d3f853f", features = ["_test-util"] } once_cell = "1" payjoin-directory = { path = "../payjoin-directory", features = ["_danger-local-https"] } testcontainers = "0.15.0" diff --git a/payjoin-cli/tests/e2e.rs b/payjoin-cli/tests/e2e.rs index 57dc2be5..bee2f564 100644 --- a/payjoin-cli/tests/e2e.rs +++ b/payjoin-cli/tests/e2e.rs @@ -151,6 +151,11 @@ mod e2e { payjoin_sent.unwrap().unwrap_or(Some(false)).unwrap(), "Payjoin send was not detected" ); + + fn find_free_port() -> u16 { + let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + listener.local_addr().unwrap().port() + } } #[cfg(feature = "v2")] @@ -179,8 +184,6 @@ mod e2e { init_tracing(); let (cert, key) = local_cert_key(); - let ohttp_relay_port = find_free_port(); - let ohttp_relay = Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); let docker: Cli = Cli::default(); let db = docker.run(Redis); let db_host = format!("127.0.0.1:{}", db.get_host_port_ipv4(6379)); @@ -189,12 +192,17 @@ mod e2e { let directory = Url::parse(&format!("https://localhost:{}", port)).unwrap(); let gateway_origin = http::Uri::from_str(directory.as_str()).unwrap(); + let (ohttp_relay_port, ohttp_relay_handle) = + ohttp_relay::listen_tcp_on_free_port(gateway_origin) + .await + .expect("Failed to init ohttp relay"); + let ohttp_relay = Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); let temp_dir = env::temp_dir(); let receiver_db_path = temp_dir.join("receiver_db"); let sender_db_path = temp_dir.join("sender_db"); let result: Result<()> = tokio::select! { - res = ohttp_relay::listen_tcp(ohttp_relay_port, gateway_origin) => Err(format!("Ohttp relay is long running: {:?}", res).into()), + res = ohttp_relay_handle => Err(format!("Ohttp relay is long running: {:?}", res).into()), res = directory_handle => Err(format!("Directory server is long running: {:?}", res).into()), res = send_receive_cli_async(ohttp_relay, directory, cert, receiver_db_path.clone(), sender_db_path.clone()) => res.map_err(|e| format!("send_receive failed: {:?}", e).into()), }; @@ -531,11 +539,6 @@ mod e2e { } } - fn find_free_port() -> u16 { - let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); - listener.local_addr().unwrap().port() - } - async fn cleanup_temp_file(path: &std::path::Path) { if let Err(e) = fs::remove_dir_all(path).await { eprintln!("Failed to remove {:?}: {}", path, e); diff --git a/payjoin/Cargo.toml b/payjoin/Cargo.toml index de01a1f7..e4d589e6 100644 --- a/payjoin/Cargo.toml +++ b/payjoin/Cargo.toml @@ -41,7 +41,7 @@ serde_json = "1.0.108" bitcoind = { version = "0.36.0", features = ["0_21_2"] } http = "1" payjoin-directory = { path = "../payjoin-directory", features = ["_danger-local-https"] } -ohttp-relay = "0.0.8" +ohttp-relay = { version = "0.0.8", git = "https://github.com/payjoin/ohttp-relay", rev = "d3f853f", features = ["_test-util"] } once_cell = "1" rcgen = { version = "0.11" } reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"] } diff --git a/payjoin/tests/integration.rs b/payjoin/tests/integration.rs index ee7c3043..01a41d1b 100644 --- a/payjoin/tests/integration.rs +++ b/payjoin/tests/integration.rs @@ -240,9 +240,6 @@ mod integration { async fn test_session_expiration() { init_tracing(); let (cert, key) = local_cert_key(); - let ohttp_relay_port = find_free_port(); - let ohttp_relay = - Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); let docker: Cli = Cli::default(); let db = docker.run(Redis); let db_host = format!("127.0.0.1:{}", db.get_host_port_ipv4(6379)); @@ -252,8 +249,14 @@ mod integration { .expect("Failed to init directory"); let directory = Url::parse(&format!("https://localhost:{}", directory_port)).unwrap(); let gateway_origin = http::Uri::from_str(directory.as_str()).unwrap(); + let (ohttp_relay_port, ohttp_relay_handle) = + ohttp_relay::listen_tcp_on_free_port(gateway_origin) + .await + .expect("Failed to init ohttp relay"); + let ohttp_relay = + Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); tokio::select!( - err = ohttp_relay::listen_tcp(ohttp_relay_port, gateway_origin) => panic!("Ohttp relay exited early: {:?}", err), + err = ohttp_relay_handle => panic!("Ohttp relay exited early: {:?}", err), err = directory_handle => panic!("Directory server exited early: {:?}", err), res = do_expiration_tests(ohttp_relay, directory, cert) => assert!(res.is_ok(), "v2 send receive failed: {:#?}", res) ); @@ -315,9 +318,6 @@ mod integration { async fn v2_to_v2() { init_tracing(); let (cert, key) = local_cert_key(); - let ohttp_relay_port = find_free_port(); - let ohttp_relay = - Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); let docker: Cli = Cli::default(); let db = docker.run(Redis); let db_host = format!("127.0.0.1:{}", db.get_host_port_ipv4(6379)); @@ -327,8 +327,14 @@ mod integration { .expect("Failed to init directory"); let directory = Url::parse(&format!("https://localhost:{}", directory_port)).unwrap(); let gateway_origin = http::Uri::from_str(directory.as_str()).unwrap(); + let (ohttp_relay_port, ohttp_relay_handle) = + ohttp_relay::listen_tcp_on_free_port(gateway_origin) + .await + .expect("Failed to init ohttp relay"); + let ohttp_relay = + Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); tokio::select!( - err = ohttp_relay::listen_tcp(ohttp_relay_port, gateway_origin) => panic!("Ohttp relay exited early: {:?}", err), + err = ohttp_relay_handle => panic!("Ohttp relay exited early: {:?}", err), err = directory_handle => panic!("Directory server exited early: {:?}", err), res = do_v2_send_receive(ohttp_relay, directory, cert) => assert!(res.is_ok(), "v2 send receive failed: {:#?}", res) ); @@ -450,9 +456,6 @@ mod integration { async fn v2_to_v2_mixed_input_script_types() { init_tracing(); let (cert, key) = local_cert_key(); - let ohttp_relay_port = find_free_port(); - let ohttp_relay = - Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); let docker: Cli = Cli::default(); let db = docker.run(Redis); let db_host = format!("127.0.0.1:{}", db.get_host_port_ipv4(6379)); @@ -462,8 +465,14 @@ mod integration { .expect("Failed to init directory"); let directory = Url::parse(&format!("https://localhost:{}", directory_port)).unwrap(); let gateway_origin = http::Uri::from_str(directory.as_str()).unwrap(); + let (ohttp_relay_port, ohttp_relay_handle) = + ohttp_relay::listen_tcp_on_free_port(gateway_origin) + .await + .expect("Failed to init ohttp relay"); + let ohttp_relay = + Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); tokio::select!( - err = ohttp_relay::listen_tcp(ohttp_relay_port, gateway_origin) => panic!("Ohttp relay exited early: {:?}", err), + err = ohttp_relay_handle => panic!("Ohttp relay exited early: {:?}", err), err = directory_handle => panic!("Directory server exited early: {:?}", err), res = do_v2_send_receive(ohttp_relay, directory, cert) => assert!(res.is_ok(), "v2 send receive failed: {:#?}", res) ); @@ -668,9 +677,6 @@ mod integration { async fn v1_to_v2() { init_tracing(); let (cert, key) = local_cert_key(); - let ohttp_relay_port = find_free_port(); - let ohttp_relay = - Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); let docker: Cli = Cli::default(); let db = docker.run(Redis); let db_host = format!("127.0.0.1:{}", db.get_host_port_ipv4(6379)); @@ -679,8 +685,14 @@ mod integration { .expect("Failed to init directory"); let directory = Url::parse(&format!("https://localhost:{}", directory_port)).unwrap(); let gateway_origin = http::Uri::from_str(directory.as_str()).unwrap(); + let (ohttp_relay_port, ohttp_relay_handle) = + ohttp_relay::listen_tcp_on_free_port(gateway_origin) + .await + .expect("Failed to init ohttp relay"); + let ohttp_relay = + Url::parse(&format!("http://localhost:{}", ohttp_relay_port)).unwrap(); tokio::select!( - err = ohttp_relay::listen_tcp(ohttp_relay_port, gateway_origin) => panic!("Ohttp relay exited early: {:?}", err), + err = ohttp_relay_handle => panic!("Ohttp relay exited early: {:?}", err), err = directory_handle => panic!("Directory server exited early: {:?}", err), res = do_v1_to_v2(ohttp_relay, directory, cert) => assert!(res.is_ok()), ); @@ -936,11 +948,6 @@ mod integration { )) } - fn find_free_port() -> u16 { - let listener = std::net::TcpListener::bind("0.0.0.0:0").unwrap(); - listener.local_addr().unwrap().port() - } - async fn wait_for_service_ready( service_url: Url, agent: Arc,