From 966a6657387cc8c074d1f2bcbac164e0bd3089b9 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Thu, 5 Sep 2024 11:30:08 +0200 Subject: [PATCH] Improve test coverage Improved test coverage for genesis block sanity check, especially when run locally in debug mode. This PR removed the need for all `fn XXXX_genesis_sanity_check()` tests to be compiled for a specific target network. `cargo.exe test --release --lib blocks::genesis_block` will now run all 6x tests. This also works in a CI environment where `cargo nextest` is called. --- Cargo.lock | 23 ++++ base_layer/core/Cargo.toml | 1 + base_layer/core/src/blocks/genesis_block.rs | 101 ++++++++++++++---- .../consensus/consensus_encoding/hashing.rs | 85 +++++++++------ 4 files changed, 157 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d9e861b8d..ad5d7eb5e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5455,6 +5455,28 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serial_test" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d" +dependencies = [ + "lazy_static", + "parking_lot 0.11.2", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "servo_arc" version = "0.3.0" @@ -6229,6 +6251,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "serial_test", "sha2 0.10.8", "sha3", "strum", diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index b8afde4e04..e8977ce7c1 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -107,6 +107,7 @@ env_logger = "0.7.0" tempfile = "3.1.0" toml = { version = "0.5" } quickcheck = "1.0" +serial_test = "0.5" [build-dependencies] tari_common = { path = "../../common", features = ["build"], version = "1.4.0-pre.0" } diff --git a/base_layer/core/src/blocks/genesis_block.rs b/base_layer/core/src/blocks/genesis_block.rs index 8429a9a3e1..024ba3a4e6 100644 --- a/base_layer/core/src/blocks/genesis_block.rs +++ b/base_layer/core/src/blocks/genesis_block.rs @@ -469,10 +469,12 @@ fn get_raw_block(genesis_timestamp: &DateTime, not_before_proof: &P } } +// Note: Tests in this module are serialized to prevent domain separated network hash conflicts #[cfg(test)] mod test { use std::convert::TryFrom; + use serial_test::serial; use tari_common_types::{epoch::VnEpoch, types::Commitment}; use super::*; @@ -489,61 +491,91 @@ mod test { }; #[test] - #[cfg(tari_target_network_testnet)] + #[serial] fn esmeralda_genesis_sanity_check() { - let _ = Network::set_current(Network::Esmeralda); + let network = Network::Esmeralda; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('esmeralda_genesis_sanity_check()')"); + } // Note: Generate new data for `pub fn get_esmeralda_genesis_block()` and `fn get_esmeralda_genesis_block_raw()` // if consensus values change, e.g. new pre_mine or other let block = get_esmeralda_genesis_block(); - check_block(Network::Esmeralda, &block, 164, 1); + check_block(network, &block, 164, 1); + remove_network_env_var(); } #[test] - #[cfg(tari_target_network_nextnet)] + #[serial] fn nextnet_genesis_sanity_check() { - let _ = Network::set_current(Network::NextNet); + let network = Network::NextNet; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('nextnet_genesis_sanity_check()')"); + } // Note: Generate new data for `pub fn get_nextnet_genesis_block()` and `fn get_stagenet_genesis_block_raw()` // if consensus values change, e.g. new pre_mine or other let block = get_nextnet_genesis_block(); - check_block(Network::NextNet, &block, 0, 0); + check_block(network, &block, 0, 0); + remove_network_env_var(); } #[test] - #[cfg(tari_target_network_mainnet)] + #[serial] fn mainnet_genesis_sanity_check() { - let _ = Network::set_current(Network::MainNet); + let network = Network::MainNet; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('mainnet_genesis_sanity_check()')"); + } // Note: Generate new data for `pub fn get_nextnet_genesis_block()` and `fn get_stagenet_genesis_block_raw()` // if consensus values change, e.g. new pre_mine or other let block = get_mainnet_genesis_block(); - check_block(Network::MainNet, &block, 164, 1); + check_block(network, &block, 164, 1); + remove_network_env_var(); } #[test] - #[cfg(tari_target_network_mainnet)] + #[serial] fn stagenet_genesis_sanity_check() { - let _ = Network::set_current(Network::StageNet); + let network = Network::StageNet; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('stagenet_genesis_sanity_check()')"); + } // Note: Generate new data for `pub fn get_stagenet_genesis_block()` and `fn get_stagenet_genesis_block_raw()` // if consensus values change, e.g. new pre_mine or other let block = get_stagenet_genesis_block(); - check_block(Network::StageNet, &block, 0, 0); + check_block(network, &block, 0, 0); + remove_network_env_var(); } #[test] - #[cfg(tari_target_network_testnet)] + #[serial] fn igor_genesis_sanity_check() { - let _ = Network::set_current(Network::Igor); + let network = Network::Igor; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('igor_genesis_sanity_check()')"); + } // Note: If outputs and kernels are added, this test will fail unless you explicitly check that network == Igor let block = get_igor_genesis_block(); - check_block(Network::Igor, &block, 0, 0); + check_block(network, &block, 0, 0); + remove_network_env_var(); } #[test] - #[cfg(tari_target_network_testnet)] + #[serial] fn localnet_genesis_sanity_check() { - let _ = Network::set_current(Network::LocalNet); + let network = Network::LocalNet; + set_network_by_env_var_or_force_set(network); + if !network_matches(network) { + panic!("Network could not be set ('localnet_genesis_sanity_check()')"); + } // Note: If outputs and kernels are added, this test will fail unless you explicitly check that network == Igor let block = get_localnet_genesis_block(); - check_block(Network::LocalNet, &block, 0, 0); + check_block(network, &block, 0, 0); + remove_network_env_var(); } fn check_block(network: Network, block: &ChainBlock, expected_outputs: usize, expected_kernels: usize) { @@ -624,4 +656,37 @@ mod test { .validate(&*lock, 0, &utxo_sum, &kernel_sum, &Commitment::default()) .unwrap(); } + + fn set_network_by_env_var_or_force_set(network: Network) { + set_network_by_env_var(network); + if Network::get_current_or_user_setting_or_default() != network { + let _ = Network::set_current(network); + } + } + + // Targeted network compilations will override inferred network hashes; this has effect only if + // `Network::set_current()` has not been called. + fn set_network_by_env_var(network: Network) { + // Do not override the env_var if network is already set; another test may fail + if std::env::var("TARI_NETWORK").is_err() { + std::env::set_var("TARI_NETWORK", network.as_key_str()); + } + } + + fn remove_network_env_var() { + std::env::remove_var("TARI_NETWORK"); + } + + fn network_matches(network: Network) -> bool { + let current_network = Network::get_current_or_user_setting_or_default(); + if current_network == network { + true + } else { + println!( + "\nNetwork mismatch!! Required: {:?}, current: {:?}.\n", + network, current_network + ); + false + } + } } diff --git a/base_layer/core/src/consensus/consensus_encoding/hashing.rs b/base_layer/core/src/consensus/consensus_encoding/hashing.rs index f0606e9450..811cdc8d40 100644 --- a/base_layer/core/src/consensus/consensus_encoding/hashing.rs +++ b/base_layer/core/src/consensus/consensus_encoding/hashing.rs @@ -145,44 +145,59 @@ mod tests { #[test] fn it_uses_the_network_environment_variable_if_set() { - // This test will not pass if `Network::set_current()` is called before the test - if !Network::is_set() { - let label = "test"; - let input = [1u8; 32]; - - for network in [ - Network::MainNet, - Network::StageNet, - Network::NextNet, - Network::LocalNet, - Network::Igor, - Network::Esmeralda, - ] { - println!("Testing network: {:?}", network); - // Generate a specific network hash - let hash_specify_network = - DomainSeparatedConsensusHasher::>::new_with_network(label, network) - .chain(&input) - .finalize(); - - // Generate an inferred network hash - std::env::set_var("TARI_NETWORK", network.as_key_str()); - println!( - "TARI_NETWORK: {:?}", - std::env::var("TARI_NETWORK").unwrap_or_default() - ); - println!( - "Network: {:?}\n", - Network::get_current_or_user_setting_or_default() - ); - let inferred_network_hash = DomainSeparatedConsensusHasher::>::new(label) + // Targeted network compilations will override inferred network hashes; this only has effect if + // `Network::set_current()` has not been called. The test may also not run if + // `std::env::var("TARI_NETWORK")` has been set by some other test. + if Network::is_set() { + println!( + "\nNote!! Static network constant is set, cannot run \ + `it_uses_the_network_environment_variable_if_set`\n" + ); + return; + } + if std::env::var("TARI_NETWORK").is_ok() { + println!( + "\nNote!! env_var 'TARI_NETWORK' in use, cannot run \ + `it_uses_the_network_environment_variable_if_set`\n" + ); + return; + } + + let label = "test"; + let input = [1u8; 32]; + + for network in [ + Network::MainNet, + Network::StageNet, + Network::NextNet, + Network::LocalNet, + Network::Igor, + Network::Esmeralda, + ] { + println!("Testing network: {:?}", network); + // Generate a specific network hash + let hash_specify_network = + DomainSeparatedConsensusHasher::>::new_with_network(label, network) .chain(&input) .finalize(); - std::env::remove_var("TARI_NETWORK"); - // They should be equal - assert_eq!(hash_specify_network, inferred_network_hash); - } + // Generate an inferred network hash + std::env::set_var("TARI_NETWORK", network.as_key_str()); + println!( + "TARI_NETWORK: {:?}", + std::env::var("TARI_NETWORK").unwrap_or_default() + ); + println!( + "Network: {:?}\n", + Network::get_current_or_user_setting_or_default() + ); + let inferred_network_hash = DomainSeparatedConsensusHasher::>::new(label) + .chain(&input) + .finalize(); + std::env::remove_var("TARI_NETWORK"); + + // They should be equal + assert_eq!(hash_specify_network, inferred_network_hash); } } }