From 9cb7ee4d0eae6639b93ca8d87094262a4b98efe6 Mon Sep 17 00:00:00 2001 From: teor Date: Tue, 29 Jun 2021 11:20:32 +1000 Subject: [PATCH] Release Blocker? Disable IPv6 tests when $ZEBRA_SKIP_IPV6_TESTS is set (#2405) * Disable IPv6 tests when $ZEBRA_SKIP_IPV6_TESTS is set This allows users to disable IPv6 tests in environments where IPv6 is not configured. * Add network test env var constants * Replace env strings with constants fastmod '"ZEBRA_SKIP_NETWORK_TESTS"' zebra_test::net::ZEBRA_SKIP_NETWORK_TESTS fastmod '"ZEBRA_SKIP_IPV6_TESTS"' zebra_test::net::ZEBRA_SKIP_IPV6_TESTS * Add functions to skip network tests * Replace test network env var checks with test function fastmod --fixed-strings 'env::var_os(zebra_test::net::ZEBRA_SKIP_NETWORK_TESTS).is_some()' 'zebra_test::net::zebra_skip_network_tests()' fastmod --fixed-strings 'env::var_os(zebra_test::net::ZEBRA_SKIP_IPV6_TESTS).is_some()' 'zebra_test::net::zebra_skip_ipv6_tests()' * Remove redundant logging and use statements --- .../src/peer_set/initialize/tests/vectors.rs | 42 +++++++++++++++--- zebra-test/src/net.rs | 43 +++++++++++++++++++ zebrad/tests/acceptance.rs | 18 +++++--- 3 files changed, 92 insertions(+), 11 deletions(-) diff --git a/zebra-network/src/peer_set/initialize/tests/vectors.rs b/zebra-network/src/peer_set/initialize/tests/vectors.rs index 48324be8..7fe37256 100644 --- a/zebra-network/src/peer_set/initialize/tests/vectors.rs +++ b/zebra-network/src/peer_set/initialize/tests/vectors.rs @@ -1,9 +1,17 @@ //! Specific configs used for zebra-network initialization tests. //! -//! ### Note on port conflict +//! ## Failures due to Port Conflicts //! //! If the test has a port conflict with another test, or another process, then it will fail. //! If these conflicts cause test failures, run the tests in an isolated environment. +//! +//! ## Failures due to Configured Network Interfaces +//! +//! If your test environment does not have any IPv6 interfaces configured, skip IPv6 tests +//! by setting the `ZEBRA_SKIP_IPV6_TESTS` environmental variable. +//! +//! If it does not have any IPv4 interfaces, or IPv4 localhost is not on `127.0.0.1`, +//! skip all the network tests by setting the `ZEBRA_SKIP_NETWORK_TESTS` environmental variable. use std::{collections::HashSet, net::SocketAddr}; @@ -26,10 +34,20 @@ use Network::*; async fn local_listener_unspecified_port_unspecified_addr() { zebra_test::init(); + if zebra_test::net::zebra_skip_network_tests() { + return; + } + + // these tests might fail on machines with no configured IPv4 addresses + // (localhost should be enough) local_listener_port_with("0.0.0.0:0".parse().unwrap(), Mainnet).await; local_listener_port_with("0.0.0.0:0".parse().unwrap(), Testnet).await; - // these tests might fail on machines without IPv6 + if zebra_test::net::zebra_skip_ipv6_tests() { + return; + } + + // these tests might fail on machines with no configured IPv6 addresses local_listener_port_with("[::]:0".parse().unwrap(), Mainnet).await; local_listener_port_with("[::]:0".parse().unwrap(), Testnet).await; } @@ -40,11 +58,19 @@ async fn local_listener_unspecified_port_unspecified_addr() { async fn local_listener_unspecified_port_localhost_addr() { zebra_test::init(); + if zebra_test::net::zebra_skip_network_tests() { + return; + } + // these tests might fail on machines with unusual IPv4 localhost configs local_listener_port_with("127.0.0.1:0".parse().unwrap(), Mainnet).await; local_listener_port_with("127.0.0.1:0".parse().unwrap(), Testnet).await; - // these tests might fail on machines without IPv6 + if zebra_test::net::zebra_skip_ipv6_tests() { + return; + } + + // these tests might fail on machines with no configured IPv6 addresses local_listener_port_with("[::1]:0".parse().unwrap(), Mainnet).await; local_listener_port_with("[::1]:0".parse().unwrap(), Testnet).await; } @@ -57,11 +83,17 @@ async fn local_listener_fixed_port_localhost_addr() { let localhost_v4 = "127.0.0.1".parse().unwrap(); let localhost_v6 = "::1".parse().unwrap(); - // these tests might fail on machines with unusual IPv4 localhost configs + if zebra_test::net::zebra_skip_network_tests() { + return; + } + local_listener_port_with(SocketAddr::new(localhost_v4, random_known_port()), Mainnet).await; local_listener_port_with(SocketAddr::new(localhost_v4, random_known_port()), Testnet).await; - // these tests might fail on machines without IPv6 + if zebra_test::net::zebra_skip_ipv6_tests() { + return; + } + local_listener_port_with(SocketAddr::new(localhost_v6, random_known_port()), Mainnet).await; local_listener_port_with(SocketAddr::new(localhost_v6, random_known_port()), Testnet).await; } diff --git a/zebra-test/src/net.rs b/zebra-test/src/net.rs index 881cf42e..d92ff8f9 100644 --- a/zebra-test/src/net.rs +++ b/zebra-test/src/net.rs @@ -1,7 +1,50 @@ //! Network testing utility functions for Zebra. +use std::env; + use rand::Rng; +/// The name of the env var that skips Zebra tests which need reliable, +/// fast network connectivity. +/// +/// We use a constant so that the compiler detects typos. +const ZEBRA_SKIP_NETWORK_TESTS: &str = "ZEBRA_SKIP_NETWORK_TESTS"; + +/// The name of the env var that skips Zebra's IPv6 tests. +/// +/// We use a constant so that the compiler detects typos. +const ZEBRA_SKIP_IPV6_TESTS: &str = "ZEBRA_SKIP_IPV6_TESTS"; + +/// Should we skip Zebra tests which need reliable, fast network connectivity? +// +// TODO: separate "good and reliable" from "any network"? +pub fn zebra_skip_network_tests() -> bool { + if env::var_os(ZEBRA_SKIP_NETWORK_TESTS).is_some() { + // This message is captured by the test runner, use + // `cargo test -- --nocapture` to see it. + eprintln!("Skipping network test because '$ZEBRA_SKIP_NETWORK_TESTS' is set."); + return true; + } + + false +} + +/// Should we skip Zebra tests which need a local IPv6 network stack and +/// IPv6 interface addresses? +/// +/// Since `zebra_skip_network_tests` only disables tests which need reliable network connectivity, +/// we allow IPv6 tests even when `ZEBRA_SKIP_NETWORK_TESTS` is set. +pub fn zebra_skip_ipv6_tests() -> bool { + if env::var_os(ZEBRA_SKIP_IPV6_TESTS).is_some() { + eprintln!("Skipping IPv6 network test because '$ZEBRA_SKIP_IPV6_TESTS' is set."); + return true; + } + + // TODO: if we separate "good and reliable" from "any network", + // also skip IPv6 tests when we're skipping all network tests. + false +} + /// Returns a random port number from the ephemeral port range. /// /// Does not check if the port is already in use. It's impossible to do this diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index cde4a322..671a3a5b 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -1,7 +1,7 @@ //! Acceptance test: runs zebrad as a subprocess and asserts its //! output for given argument combinations matches what is expected. //! -//! ### Note on port conflict +//! ## Note on port conflict //! //! If the test child has a cache or port conflict with another test, or a //! running zebrad or zcashd, then it will panic. But the acceptance tests @@ -11,6 +11,15 @@ //! - run the tests in an isolated environment, //! - run zebrad on a custom cache path and port, //! - run zcashd on a custom port. +//! +//! ## Failures due to Configured Network Interfaces or Network Connectivity +//! +//! If your test environment does not have any IPv6 interfaces configured, skip IPv6 tests +//! by setting the `ZEBRA_SKIP_IPV6_TESTS` environmental variable. +//! +//! If it does not have any IPv4 interfaces, IPv4 localhost is not on `127.0.0.1`, +//! or you have poor network connectivity, +//! skip all the network tests by setting the `ZEBRA_SKIP_NETWORK_TESTS` environmental variable. // Standard lints #![warn(missing_docs)] @@ -24,7 +33,7 @@ use color_eyre::{ }; use tempdir::TempDir; -use std::{collections::HashSet, convert::TryInto, env, path::Path, path::PathBuf, time::Duration}; +use std::{collections::HashSet, convert::TryInto, path::Path, path::PathBuf, time::Duration}; use zebra_chain::{ block::Height, @@ -804,10 +813,7 @@ fn sync_until( ) -> Result { zebra_test::init(); - if env::var_os("ZEBRA_SKIP_NETWORK_TESTS").is_some() { - // This message is captured by the test runner, use - // `cargo test -- --nocapture` to see it. - eprintln!("Skipping network test because '$ZEBRA_SKIP_NETWORK_TESTS' is set."); + if zebra_test::net::zebra_skip_network_tests() { return testdir(); }