From faf1d756185505c6234eb4248a1f7547d143c4ac Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 9 Jan 2022 07:25:17 +0100 Subject: [PATCH] Introduce a `#[nightly_test]` attribute Introduce a `#[nightly_test]` attribute to be used to mark tests as expensive (i.e. to be run nightly on NayDuck but omitted from casual `cargo test` invocations or CI runs). It replaces the use of `#[cfg(feature = "expensive_tests")]` directive and under the hood marks tests as ignored rather than skipping their compilation. This means that while previously nightly tests would be built only if `expensive_tests` feature is set now they are always compiled. This further means that changes that break such tests will be caught by CI (previously they would break only once NayDuck decides to run them) and there is no longer need to conditionally compile helper functions which are used by such tests only. Issue: https://github.com/near/nearcore/issues/4490 --- Cargo.lock | 16 +++- Cargo.toml | 1 + chain/chain/Cargo.toml | 1 + chain/chain/src/store.rs | 7 +- chain/chain/src/tests/doomslug.rs | 4 +- chain/chain/src/tests/gc.rs | 19 ++--- chain/chain/src/tests/mod.rs | 1 - chain/chunks/Cargo.toml | 1 + chain/chunks/src/lib.rs | 7 +- chain/client/Cargo.toml | 1 + chain/client/src/tests/catching_up.rs | 43 ++++------- chain/client/src/tests/consensus.rs | 4 +- chain/client/src/tests/cross_shard_tx.rs | 25 ++----- chain/client/src/tests/mod.rs | 2 - chain/client/src/tests/query_client.rs | 21 +++--- integration-tests/Cargo.toml | 1 + .../src/tests/client/process_blocks.rs | 4 +- .../src/tests/nearcore/sync_state_nodes.rs | 6 +- .../src/tests/standard_cases/rpc.rs | 56 +++++++------- integration-tests/src/tests/test_catchup.rs | 16 ++-- integration-tests/src/tests/test_simple.rs | 9 +-- .../src/tests/test_tps_regression.rs | 5 +- nightly/expensive.txt | 3 + scripts/check_nightly.py | 75 ++++++------------- utils/near-macros/Cargo.toml | 9 +++ utils/near-macros/src/lib.rs | 34 +++++++++ 26 files changed, 180 insertions(+), 191 deletions(-) create mode 100644 utils/near-macros/Cargo.toml create mode 100644 utils/near-macros/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b23e78fef17..63f81eb6f95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2184,6 +2184,7 @@ dependencies = [ "near-jsonrpc-client", "near-jsonrpc-primitives", "near-logger-utils", + "near-macros", "near-metrics", "near-network", "near-network-primitives", @@ -2641,6 +2642,7 @@ dependencies = [ "near-chain-primitives", "near-crypto", "near-logger-utils", + "near-macros", "near-metrics", "near-pool", "near-primitives", @@ -2698,6 +2700,7 @@ dependencies = [ "near-chunks-primitives", "near-crypto", "near-logger-utils", + "near-macros", "near-network", "near-network-primitives", "near-pool", @@ -2734,6 +2737,7 @@ dependencies = [ "near-client-primitives", "near-crypto", "near-logger-utils", + "near-macros", "near-metrics", "near-network", "near-network-primitives", @@ -2964,6 +2968,10 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "near-macros" +version = "0.0.0" + [[package]] name = "near-metrics" version = "0.0.0" @@ -3933,9 +3941,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.30" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] @@ -4003,9 +4011,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" dependencies = [ "proc-macro2", ] diff --git a/Cargo.toml b/Cargo.toml index 5946f32e791..74694963c16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ members = [ "integration-tests", "utils/near-rate-limiter", "utils/near-cache", + "utils/near-macros", ] [workspace.metadata.workspaces] diff --git a/chain/chain/Cargo.toml b/chain/chain/Cargo.toml index e8d4c4e9f3c..c0dc632f549 100644 --- a/chain/chain/Cargo.toml +++ b/chain/chain/Cargo.toml @@ -27,6 +27,7 @@ delay-detector = { path = "../../tools/delay_detector", optional = true} near-chain-configs = { path = "../../core/chain-configs" } near-chain-primitives = { path = "../chain-primitives" } near-crypto = { path = "../../core/crypto" } +near-macros = { path = "../../utils/near-macros" } near-metrics = { path = "../../core/metrics" } near-pool = { path = "../pool" } near-primitives = { path = "../../core/primitives" } diff --git a/chain/chain/src/store.rs b/chain/chain/src/store.rs index a0b61ee8ad0..b964fad57d4 100644 --- a/chain/chain/src/store.rs +++ b/chain/chain/src/store.rs @@ -2944,8 +2944,8 @@ mod tests { use strum::IntoEnumIterator; use near_crypto::KeyType; + use near_macros::nightly_test; use near_primitives::block::{Block, Tip}; - #[cfg(feature = "expensive_tests")] use near_primitives::epoch_manager::block_info::BlockInfo; use near_primitives::errors::InvalidTxError; use near_primitives::hash::hash; @@ -2954,7 +2954,6 @@ mod tests { use near_primitives::validator_signer::InMemoryValidatorSigner; use near_store::test_utils::create_test_store; use near_store::DBCol; - #[cfg(feature = "expensive_tests")] use {crate::store_validator::StoreValidator, near_chain_configs::GenesisConfig}; use crate::store::{ChainStoreAccess, GCMode}; @@ -3366,8 +3365,7 @@ mod tests { } /// Test that `gc_blocks_limit` works properly - #[cfg(feature = "expensive_tests")] - #[test] + #[nightly_test] fn test_clear_old_data_too_many_heights() { for i in 1..5 { println!("gc_blocks_limit == {:?}", i); @@ -3378,7 +3376,6 @@ mod tests { test_clear_old_data_too_many_heights_common(87); } - #[cfg(feature = "expensive_tests")] fn test_clear_old_data_too_many_heights_common(gc_blocks_limit: NumBlocks) { let mut chain = get_chain_with_epoch_length(1); let genesis = chain.get_block_by_height(0).unwrap().clone(); diff --git a/chain/chain/src/tests/doomslug.rs b/chain/chain/src/tests/doomslug.rs index 6036b1e1c7c..11926adf11d 100644 --- a/chain/chain/src/tests/doomslug.rs +++ b/chain/chain/src/tests/doomslug.rs @@ -6,6 +6,7 @@ use std::time::{Duration, Instant}; use crate::{Doomslug, DoomslugThresholdMode}; use near_crypto::{KeyType, SecretKey}; +use near_macros::nightly_test; use near_primitives::block::Approval; use near_primitives::hash::{hash, CryptoHash}; use near_primitives::types::{ApprovalStake, BlockHeight}; @@ -301,8 +302,7 @@ fn one_iter( (now - started, largest_produced_height) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_fuzzy_doomslug_liveness_and_safety() { for (time_to_gst_millis, height_goal) in &[(0, 200), (1000, 200), (10000, 300), (100000, 400), (500000, 500)] diff --git a/chain/chain/src/tests/gc.rs b/chain/chain/src/tests/gc.rs index 24c74b0caf3..d9053b0787a 100644 --- a/chain/chain/src/tests/gc.rs +++ b/chain/chain/src/tests/gc.rs @@ -5,6 +5,7 @@ use crate::test_utils::KeyValueRuntime; use crate::types::{ChainGenesis, Tip}; use crate::DoomslugThresholdMode; use near_crypto::KeyType; +use near_macros::nightly_test; use near_primitives::block::Block; use near_primitives::merkle::PartialMerkleTree; use near_primitives::shard_layout::ShardUId; @@ -293,8 +294,7 @@ fn test_gc_remove_fork_small() { test_gc_remove_fork_common(1) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_gc_remove_fork_large() { test_gc_remove_fork_common(20) } @@ -340,8 +340,7 @@ fn test_gc_not_remove_fork_small() { test_gc_not_remove_fork_common(1) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_gc_not_remove_fork_large() { test_gc_not_remove_fork_common(20) } @@ -426,8 +425,7 @@ fn test_gc_boundaries_small() { test_gc_boundaries_common(1) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_gc_boundaries_large() { test_gc_boundaries_common(20) } @@ -455,8 +453,7 @@ fn test_gc_random_small() { test_gc_random_common(3); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_gc_random_large() { test_gc_random_common(25); } @@ -500,8 +497,7 @@ fn test_gc_pine_small() { gc_fork_common(chains, 1); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_gc_pine() { for max_changes in 1..=20 { let mut chains = vec![SimpleChain { from: 0, length: 101, is_removed: false }]; @@ -542,8 +538,7 @@ fn test_gc_star_small() { test_gc_star_common(1) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_gc_star_large() { test_gc_star_common(20) } diff --git a/chain/chain/src/tests/mod.rs b/chain/chain/src/tests/mod.rs index ed67768feaa..c23fcda29dc 100644 --- a/chain/chain/src/tests/mod.rs +++ b/chain/chain/src/tests/mod.rs @@ -1,5 +1,4 @@ mod challenges; -#[cfg(feature = "expensive_tests")] mod doomslug; mod gc; mod simple_chain; diff --git a/chain/chunks/Cargo.toml b/chain/chunks/Cargo.toml index 4729a620388..2425a323c32 100644 --- a/chain/chunks/Cargo.toml +++ b/chain/chunks/Cargo.toml @@ -25,6 +25,7 @@ near-network = { path = "../network" } near-chain = { path = "../chain" } near-pool = { path = "../pool" } near-network-primitives = { path = "../network-primitives" } +near-macros = { path = "../../utils/near-macros" } [dev-dependencies] near-logger-utils = { path = "../../test-utils/logger" } diff --git a/chain/chunks/src/lib.rs b/chain/chunks/src/lib.rs index d993d6aec96..ef5748a64d2 100644 --- a/chain/chunks/src/lib.rs +++ b/chain/chunks/src/lib.rs @@ -863,7 +863,7 @@ impl ShardsManager { if stored_chunk.len() < MAX_STORED_PARTIAL_CHUNK_SIZE { stored_chunk.push(partial_encoded_chunk.clone()); } else { - warn!(target:"shards_manager", "Drop partial encoded chunk because stored partial encoded chunks already exceed limit, height: {} shard: {}", + warn!(target:"shards_manager", "Drop partial encoded chunk because stored partial encoded chunks already exceed limit, height: {} shard: {}", height, shard_id); } } @@ -1869,10 +1869,10 @@ mod test { use std::sync::Arc; use std::time::Duration; + use near_macros::nightly_test; use near_network::types::NetworkRequests; use near_primitives::block::Tip; use near_primitives::types::EpochId; - #[cfg(feature = "expensive_tests")] use { crate::ACCEPTING_SEAL_PERIOD_MS, near_chain::ChainStore, near_chain::RuntimeAdapter, near_crypto::KeyType, near_logger_utils::init_test_logger, @@ -1926,8 +1926,7 @@ mod test { }; } - #[cfg(feature = "expensive_tests")] - #[test] + #[nightly_test] fn test_seal_removal() { init_test_logger(); let runtime_adapter = Arc::new(KeyValueRuntime::new_with_validators( diff --git a/chain/client/Cargo.toml b/chain/client/Cargo.toml index 63ebc04d0ca..b50e107221e 100644 --- a/chain/client/Cargo.toml +++ b/chain/client/Cargo.toml @@ -33,6 +33,7 @@ near-metrics = { path = "../../core/metrics" } near-chain-configs = { path = "../../core/chain-configs" } near-chain = { path = "../chain" } near-client-primitives = { path = "../client-primitives" } +near-macros = { path = "../../utils/near-macros" } near-network = { path = "../network" } near-pool = { path = "../pool" } near-chunks = { path = "../chunks" } diff --git a/chain/client/src/tests/catching_up.rs b/chain/client/src/tests/catching_up.rs index 9cc2457a7a7..5fcf718825b 100644 --- a/chain/client/src/tests/catching_up.rs +++ b/chain/client/src/tests/catching_up.rs @@ -13,6 +13,7 @@ use near_chain::test_utils::account_id_to_shard_id; use near_chain_configs::TEST_STATE_SYNC_TIMEOUT; use near_crypto::{InMemorySigner, KeyType}; use near_logger_utils::init_integration_logger; +use near_macros::nightly_test; use near_network::types::{ NetworkClientMessages, NetworkRequests, NetworkResponses, PeerManagerMessageRequest, }; @@ -96,8 +97,7 @@ pub struct StateRequestStruct { } /// Sanity checks that the incoming and outgoing receipts are properly sent and received -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_receipts_sync_third_epoch() { test_catchup_receipts_sync_common(13, 1, false) } @@ -109,20 +109,17 @@ fn test_catchup_receipts_sync_third_epoch() { /// It will be executed 10 times faster. /// The reason of increasing block_prod_time in the test is to allow syncing complete. /// Otherwise epochs will be changing faster than state sync happen. -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_receipts_sync_hold() { test_catchup_receipts_sync_common(13, 1, true) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_receipts_sync_last_block() { test_catchup_receipts_sync_common(13, 5, false) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_receipts_sync_distant_epoch() { test_catchup_receipts_sync_common(35, 1, false) } @@ -376,8 +373,7 @@ enum RandomSinglePartPhases { /// If random one parts fetched during the epoch preceding the epoch a block producer is /// assigned to were to have incorrect receipts, the balances in the fourth epoch would have /// been incorrect due to wrong receipts applied during the third epoch. -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_random_single_part_sync() { test_catchup_random_single_part_sync_common(false, false, 13) } @@ -385,28 +381,24 @@ fn test_catchup_random_single_part_sync() { // Same test as `test_catchup_random_single_part_sync`, but skips the chunks on height 14 and 15 // It causes all the receipts to be applied only on height 16, which is the next epoch. // It tests that the incoming receipts are property synced through epochs -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_random_single_part_sync_skip_15() { test_catchup_random_single_part_sync_common(true, false, 13) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_random_single_part_sync_send_15() { test_catchup_random_single_part_sync_common(false, false, 15) } // Make sure that transactions are at least applied. -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_random_single_part_sync_non_zero_amounts() { test_catchup_random_single_part_sync_common(false, true, 13) } // Use another height to send txs. -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_random_single_part_sync_height_6() { test_catchup_random_single_part_sync_common(false, false, 6) } @@ -618,8 +610,7 @@ fn test_catchup_random_single_part_sync_common(skip_15: bool, non_zero: bool, he /// to be skipped) /// This test would fail if at any point validators got stuck with state sync, or block /// production stalled for any other reason. -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_catchup_sanity_blocks_produced() { let validator_groups = 2; init_integration_logger(); @@ -693,8 +684,7 @@ enum ChunkGrievingPhases { } // TODO(#3180): seals are disabled in single shard setting -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] #[ignore] fn test_chunk_grieving() { let validator_groups = 1; @@ -847,20 +837,17 @@ fn test_chunk_grieving() { }); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_all_chunks_accepted_1000() { test_all_chunks_accepted_common(1000, 3000, 5) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_all_chunks_accepted_1000_slow() { test_all_chunks_accepted_common(1000, 6000, 5) } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_all_chunks_accepted_1000_rare_epoch_changing() { test_all_chunks_accepted_common(1000, 1500, 100) } diff --git a/chain/client/src/tests/consensus.rs b/chain/client/src/tests/consensus.rs index 152a3908611..e9ff82f9c2a 100644 --- a/chain/client/src/tests/consensus.rs +++ b/chain/client/src/tests/consensus.rs @@ -9,6 +9,7 @@ use crate::{ClientActor, ViewClientActor}; use near_actix_test_utils::run_actix; use near_chain::Block; use near_logger_utils::init_integration_logger; +use near_macros::nightly_test; use near_network::types::{ NetworkClientMessages, NetworkRequests, NetworkResponses, PeerManagerMessageRequest, }; @@ -21,8 +22,7 @@ use near_primitives::types::{AccountId, BlockHeight}; /// the future, and delay the distribution of the block produced this way. /// Periodically verify finality is not violated. /// This test is designed to reproduce finality bugs on the epoch boundaries. -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_consensus_with_epoch_switches() { init_integration_logger(); diff --git a/chain/client/src/tests/cross_shard_tx.rs b/chain/client/src/tests/cross_shard_tx.rs index 650436c17f9..ac4ba51de3c 100644 --- a/chain/client/src/tests/cross_shard_tx.rs +++ b/chain/client/src/tests/cross_shard_tx.rs @@ -11,6 +11,7 @@ use near_actix_test_utils::run_actix; use near_chain::test_utils::account_id_to_shard_id; use near_crypto::{InMemorySigner, KeyType}; use near_logger_utils::init_integration_logger; +use near_macros::nightly_test; use near_network::types::{ NetworkClientMessages, NetworkClientResponses, NetworkResponses, PeerManagerMessageRequest, PeerManagerMessageResponse, @@ -96,7 +97,6 @@ fn test_keyvalue_runtime_balances() { }); } -#[cfg(feature = "expensive_tests")] fn send_tx( num_validators: usize, connectors: Arc, Addr)>>>, @@ -155,7 +155,6 @@ fn send_tx( ); } -#[cfg(feature = "expensive_tests")] fn test_cross_shard_tx_callback( res: Result, MailboxError>, account_id: AccountId, @@ -373,7 +372,6 @@ fn test_cross_shard_tx_callback( } } -#[cfg(feature = "expensive_tests")] fn test_cross_shard_tx_common( num_iters: usize, rotate_validators: bool, @@ -510,44 +508,37 @@ fn test_cross_shard_tx_common( }); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_cross_shard_tx() { test_cross_shard_tx_common(64, false, false, false, 70, Some(2.3), None); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_cross_shard_tx_doomslug() { test_cross_shard_tx_common(64, false, false, true, 200, None, Some(1.5)); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_cross_shard_tx_drop_chunks() { test_cross_shard_tx_common(64, false, true, false, 250, None, None); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_cross_shard_tx_8_iterations() { test_cross_shard_tx_common(8, false, false, false, 200, Some(2.4), None); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_cross_shard_tx_8_iterations_drop_chunks() { test_cross_shard_tx_common(8, false, true, false, 200, Some(2.4), None); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_cross_shard_tx_with_validator_rotation_1() { test_cross_shard_tx_common(8, true, false, false, 220, Some(2.4), None); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_cross_shard_tx_with_validator_rotation_2() { test_cross_shard_tx_common(24, true, false, false, 400, Some(2.4), None); } diff --git a/chain/client/src/tests/mod.rs b/chain/client/src/tests/mod.rs index f03f939d45d..52390dba87f 100644 --- a/chain/client/src/tests/mod.rs +++ b/chain/client/src/tests/mod.rs @@ -1,8 +1,6 @@ mod bug_repros; -#[cfg(feature = "expensive_tests")] mod catching_up; mod chunks_management; -#[cfg(feature = "expensive_tests")] mod consensus; mod cross_shard_tx; mod query_client; diff --git a/chain/client/src/tests/query_client.rs b/chain/client/src/tests/query_client.rs index ab3763a5c81..67f285714b7 100644 --- a/chain/client/src/tests/query_client.rs +++ b/chain/client/src/tests/query_client.rs @@ -221,18 +221,15 @@ fn test_state_request() { .await .unwrap(); assert!(matches!(res, NetworkViewClientResponses::NoResponse)); - #[cfg(feature = "expensive_tests")] - { - actix::clock::sleep(Duration::from_secs(40)).await; - let res = view_client - .send(NetworkViewClientMessages::StateRequestHeader { - shard_id: 0, - sync_hash: block_hash, - }) - .await - .unwrap(); - assert!(matches!(res, NetworkViewClientResponses::StateResponse(_))); - } + actix::clock::sleep(Duration::from_secs(40)).await; + let res = view_client + .send(NetworkViewClientMessages::StateRequestHeader { + shard_id: 0, + sync_hash: block_hash, + }) + .await + .unwrap(); + assert!(matches!(res, NetworkViewClientResponses::StateResponse(_))); System::current().stop(); }); near_network::test_utils::wait_or_panic(50000); diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index c569d464d95..a00474018cb 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -38,6 +38,7 @@ near-crypto = { path = "../core/crypto" } near-jsonrpc = { path = "../chain/jsonrpc" } near-jsonrpc-client = { path = "../chain/jsonrpc/client" } near-jsonrpc-primitives = { path = "../chain/jsonrpc-primitives" } +near-macros = { path = "../utils/near-macros" } near-metrics = { path = "../core/metrics" } near-network = { path = "../chain/network" } near-network-primitives = { path = "../chain/network-primitives" } diff --git a/integration-tests/src/tests/client/process_blocks.rs b/integration-tests/src/tests/client/process_blocks.rs index 277b5f7bc6f..4f1b714191c 100644 --- a/integration-tests/src/tests/client/process_blocks.rs +++ b/integration-tests/src/tests/client/process_blocks.rs @@ -25,6 +25,7 @@ use near_client::test_utils::{ use near_client::{Client, GetBlock, GetBlockWithMerkleTree}; use near_crypto::{InMemorySigner, KeyType, PublicKey, Signature, Signer}; use near_logger_utils::init_test_logger; +use near_macros::nightly_test; use near_network::test_utils::{wait_or_panic, MockPeerManagerAdapter}; use near_network::types::PartialEdgeInfo; use near_network::types::{ @@ -1525,8 +1526,7 @@ fn test_gc_execution_outcome() { assert!(env.clients[0].chain.get_final_transaction_result(&tx_hash).is_err()); } -#[cfg(feature = "expensive_tests")] -#[test] +#[nightly_test] fn test_gc_after_state_sync() { let epoch_length = 1024; let mut genesis = Genesis::test(vec!["test0".parse().unwrap(), "test1".parse().unwrap()], 1); diff --git a/integration-tests/src/tests/nearcore/sync_state_nodes.rs b/integration-tests/src/tests/nearcore/sync_state_nodes.rs index 7cd7ce22701..8f7d181656c 100644 --- a/integration-tests/src/tests/nearcore/sync_state_nodes.rs +++ b/integration-tests/src/tests/nearcore/sync_state_nodes.rs @@ -9,6 +9,7 @@ use near_actix_test_utils::run_actix; use near_chain_configs::Genesis; use near_client::GetBlock; use near_logger_utils::init_integration_logger; +use near_macros::nightly_test; use near_network::test_utils::{convert_boot_nodes, open_port, WaitOrTimeoutActor}; use nearcore::{config::GenesisExt, load_test_config, start_with_config}; @@ -104,11 +105,8 @@ fn sync_state_nodes() { } /// One client is in front, another must sync to it using state (fast) sync. -#[test] +#[nightly_test] fn sync_state_nodes_multishard() { - if !cfg!(feature = "expensive_tests") { - return; - } heavy_test(|| { init_integration_logger(); diff --git a/integration-tests/src/tests/standard_cases/rpc.rs b/integration-tests/src/tests/standard_cases/rpc.rs index 46e42a75cfe..4b984b27b73 100644 --- a/integration-tests/src/tests/standard_cases/rpc.rs +++ b/integration-tests/src/tests/standard_cases/rpc.rs @@ -1,6 +1,5 @@ //! Runs standard test cases against testnet with several nodes running in separate threads. //! The communication is performed through `RPCUser` that uses the standard RPC API to communicate. -#[cfg(feature = "expensive_tests")] mod test { use std::thread; use std::time::Duration; @@ -9,6 +8,7 @@ mod test { use crate::test_helpers::heavy_test; use crate::tests::standard_cases::*; use near_logger_utils::init_test_module_logger; + use near_macros::nightly_test; use testlib::runtime_utils::alice_account; fn create_thread_nodes_rpc() -> Vec { @@ -56,137 +56,137 @@ mod test { }; } - #[test] + #[nightly_test] fn test_smart_contract_simple_testnet() { run_testnet_test!(test_smart_contract_simple); } - #[test] + #[nightly_test] fn test_smart_contract_self_call_testnet() { run_testnet_test!(test_smart_contract_self_call); } - #[test] + #[nightly_test] fn test_smart_contract_bad_method_name_testnet() { run_testnet_test!(test_smart_contract_bad_method_name); } - #[test] + #[nightly_test] fn test_smart_contract_empty_method_name_with_no_tokens_testnet() { run_testnet_test!(test_smart_contract_empty_method_name_with_no_tokens); } - #[test] + #[nightly_test] fn test_smart_contract_empty_method_name_with_tokens_testnet() { run_testnet_test!(test_smart_contract_empty_method_name_with_tokens); } - #[test] + #[nightly_test] fn test_smart_contract_with_args_testnet() { run_testnet_test!(test_smart_contract_with_args); } - #[test] + #[nightly_test] fn test_nonce_update_when_deploying_contract_testnet() { run_testnet_test!(test_nonce_update_when_deploying_contract); } - #[test] + #[nightly_test] fn test_nonce_updated_when_tx_failed_testnet() { run_testnet_test!(test_nonce_updated_when_tx_failed); } - #[test] + #[nightly_test] fn test_upload_contract_testnet() { run_testnet_test!(test_upload_contract); } - #[test] + #[nightly_test] fn test_redeploy_contract_testnet() { run_testnet_test!(test_redeploy_contract); } - #[test] + #[nightly_test] fn test_send_money_testnet() { run_testnet_test!(test_send_money); } - #[test] + #[nightly_test] fn test_send_money_over_balance_testnet() { run_testnet_test!(test_send_money_over_balance); } - #[test] + #[nightly_test] fn test_refund_on_send_money_to_non_existent_account_testnet() { run_testnet_test!(test_refund_on_send_money_to_non_existent_account); } - #[test] + #[nightly_test] fn test_create_account_testnet() { run_testnet_test!(test_create_account); } - #[test] + #[nightly_test] fn test_create_account_again_testnet() { run_testnet_test!(test_create_account_again); } - #[test] + #[nightly_test] fn test_create_account_failure_already_exists_testnet() { run_testnet_test!(test_create_account_failure_already_exists); } - #[test] + #[nightly_test] fn test_swap_key_testnet() { run_testnet_test!(test_swap_key); } - #[test] + #[nightly_test] fn test_add_access_key_function_call_testnet() { run_testnet_test!(test_add_access_key_function_call); } - #[test] + #[nightly_test] fn test_add_existing_key_testnet() { run_testnet_test!(test_add_existing_key); } - #[test] + #[nightly_test] fn test_delete_key_testnet() { run_testnet_test!(test_delete_key); } - #[test] + #[nightly_test] fn test_delete_key_not_owned_testnet() { run_testnet_test!(test_delete_key_not_owned); } - #[test] + #[nightly_test] fn test_delete_key_last_testnet() { run_testnet_test!(test_delete_key_last); } - #[test] + #[nightly_test] fn test_add_key_testnet() { run_testnet_test!(test_add_key); } - #[test] + #[nightly_test] fn test_delete_access_key_testnet() { run_testnet_test!(test_delete_access_key); } - #[test] + #[nightly_test] fn test_add_access_key_with_allowance_testnet() { run_testnet_test!(test_add_access_key_with_allowance); } - #[test] + #[nightly_test] fn test_delete_access_key_with_allowance_testnet() { run_testnet_test!(test_delete_access_key_with_allowance); } - #[test] + #[nightly_test] fn test_access_key_smart_contract_testnet() { run_testnet_test!(test_access_key_smart_contract); } diff --git a/integration-tests/src/tests/test_catchup.rs b/integration-tests/src/tests/test_catchup.rs index 4b60d4bc8a9..b2650c5424d 100644 --- a/integration-tests/src/tests/test_catchup.rs +++ b/integration-tests/src/tests/test_catchup.rs @@ -1,13 +1,15 @@ //! Checks that late validator can catch-up and start validating. -#[test] -#[cfg(feature = "expensive_tests")] -fn test_catchup() { - use std::time::Duration; - use crate::node::{create_nodes, Node}; - use crate::test_helpers::{heavy_test, wait}; - use std::sync::{Arc, RwLock}; +use std::time::Duration; + +use crate::node::{create_nodes, Node}; +use crate::test_helpers::{heavy_test, wait}; +use std::sync::{Arc, RwLock}; +use near_macros::nightly_test; + +#[nightly_test] +fn test_catchup() { /// Creates a network of `num_nodes` nodes, but starts only `num_nodes - 1`. After /// `num_blocks_to_wait` starts the last node and verifies that it can start validating within /// `catchup_timeout`. diff --git a/integration-tests/src/tests/test_simple.rs b/integration-tests/src/tests/test_simple.rs index 546b4cbc4c9..e20e6ac2b6d 100644 --- a/integration-tests/src/tests/test_simple.rs +++ b/integration-tests/src/tests/test_simple.rs @@ -1,10 +1,9 @@ //! Simply starts and runs testnet for a while. -#[cfg(test)] -#[cfg(feature = "expensive_tests")] mod test { use crate::node::{create_nodes, sample_two_nodes, Node}; use crate::test_helpers::{heavy_test, wait}; use near_logger_utils::init_integration_logger; + use near_macros::nightly_test; use near_primitives::time::Clock; use near_primitives::transaction::SignedTransaction; use std::time::Duration; @@ -73,17 +72,17 @@ mod test { } } - #[test] + #[nightly_test] fn test_2_10_multiple_nodes() { heavy_test(|| run_multiple_nodes(2, 10, "2_10")); } - #[test] + #[nightly_test] fn test_4_10_multiple_nodes() { heavy_test(|| run_multiple_nodes(4, 10, "4_10")); } - #[test] + #[nightly_test] fn test_7_10_multiple_nodes() { heavy_test(|| run_multiple_nodes(7, 10, "7_10")); } diff --git a/integration-tests/src/tests/test_tps_regression.rs b/integration-tests/src/tests/test_tps_regression.rs index 7d0509abf77..1edd932befc 100644 --- a/integration-tests/src/tests/test_tps_regression.rs +++ b/integration-tests/src/tests/test_tps_regression.rs @@ -2,8 +2,6 @@ //! and verifies that the output tps is not much different from the input tps (makes sure there is //! no choking on transactions). The input tps -- is how fast the nodes can be accepting //! transactions. The output tps -- is how fast the nodes propagate transactions into the blocks. -#[cfg(any(feature = "expensive_tests", feature = "regression_tests"))] -#[cfg(test)] mod test { use std::io::stdout; use std::io::Write; @@ -12,6 +10,7 @@ mod test { use crate::node::{create_nodes, sample_queryable_node, sample_two_nodes, Node}; use crate::test_helpers::heavy_test; + use near_macros::nightly_test; use near_primitives::transaction::SignedTransaction; use std::time::{Duration, Instant}; @@ -165,7 +164,7 @@ mod test { assert!((target_tps as f64) * 0.8 < (observed_xacts_num as f64 / timeout.as_secs_f64())); } - #[test] + #[nightly_test] #[ignore] fn test_highload() { // Run 4 nodes with 20 input tps and check the output tps to be 20. diff --git a/nightly/expensive.txt b/nightly/expensive.txt index 8527510b396..ce641c26c2b 100644 --- a/nightly/expensive.txt +++ b/nightly/expensive.txt @@ -141,3 +141,6 @@ expensive integration-tests integration_tests tests::test_simple::test::test_4_1 expensive integration-tests integration_tests tests::test_simple::test::test_4_10_multiple_nodes --features nightly_protocol,nightly_protocol_features expensive integration-tests integration_tests tests::test_simple::test::test_7_10_multiple_nodes expensive integration-tests integration_tests tests::test_simple::test::test_7_10_multiple_nodes --features nightly_protocol,nightly_protocol_features + +expensive integration-tests integration_tests tests::nearcore::sync_state_nodes::sync_state_nodes_multishard +expensive integration-tests integration_tests tests::nearcore::sync_state_nodes::sync_state_nodes_multishard --features nightly_protocol,nightly_protocol_features diff --git a/scripts/check_nightly.py b/scripts/check_nightly.py index cf20213c424..076124f123d 100644 --- a/scripts/check_nightly.py +++ b/scripts/check_nightly.py @@ -1,57 +1,21 @@ #!/usr/bin/env python3 -import glob +import os import pathlib import re import sys +import typing import nayduck -expensive_pattern = '#[cfg(feature = "expensive_tests")]' -test_pattern = '#[test]' +TEST_RE = re.compile(r'^\s*#\[(?:near_macros::)?nightly_test\].*?' + r'\bfn ([a-zA-Z0-9_]+)\b', + re.MULTILINE | re.DOTALL) +IGNORED_SUBDIRS = ('target', 'target_expensive', 'sandbox') -def find_first(data, tokens, start): - found = [(data.find(token, start), token) for token in tokens] - try: - return min((pos, token) for pos, token in found if pos >= 0) - except ValueError: - return -1, None - - -def find_fn(str1, start): - fn_start = str1.find('fn ', start) - match = re.search(r'[a-zA-Z0-9_]+', str1[fn_start + 3:]) - if match: - return match.group(0) - return None - - -def expensive_tests_in_file(file): - with (open(file)) as f: - content = f.read() - start = 0 - while True: - start = content.find(expensive_pattern, start) - if start == -1: - return - start += len(expensive_pattern) - level = 0 - while True: - start, tok = find_first(content, ['{', '}', test_pattern], start) - if start == -1: - break - start += len(tok) - if tok == '{': - level += 1 - elif tok == '}': - level -= 1 - if level == 0: - break - elif tok == test_pattern: - fn = find_fn(content, start) - if fn: - yield fn +def nightly_tests_in_file(path: pathlib.Path) -> typing.Sequence[str]: + return [match.group(1) for match in TEST_RE.finditer(path.read_text())] def nightly_tests(repo_dir): @@ -67,17 +31,22 @@ def nightly_tests(repo_dir): pass -def main(): +def main() -> typing.Optional[str]: repo_dir = pathlib.Path(__file__).parent.parent nightly_txt_tests = set(nightly_tests(repo_dir)) - for rs in glob.glob(str(repo_dir / '**/*.rs'), recursive=True): - if '/target/' in rs: - continue - print(f'checking file {rs}') - for t in expensive_tests_in_file(rs): - print(f' expensive test {t}') - if t not in nightly_txt_tests: - return f'error: file {rs} test {t} not in nightly.txt' + for root, dirs, files in os.walk(repo_dir): + dirs[:] = [dirname + for dirname in dirs + if dirname not in IGNORED_SUBDIRS] + path = pathlib.Path(root) + for filename in files: + if filename.endswith('.rs'): + filepath = path / filename + print(f'checking file {filepath}') + for test in nightly_tests_in_file(filepath): + print(f' expensive test {test}') + if test not in nightly_txt_tests: + return f'error: file {filepath} test {test} not in nightly.txt' print('all tests in nightly') return None diff --git a/utils/near-macros/Cargo.toml b/utils/near-macros/Cargo.toml new file mode 100644 index 00000000000..7ccab6a14b5 --- /dev/null +++ b/utils/near-macros/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "near-macros" +version = "0.0.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] diff --git a/utils/near-macros/src/lib.rs b/utils/near-macros/src/lib.rs new file mode 100644 index 00000000000..51b8bc10bbf --- /dev/null +++ b/utils/near-macros/src/lib.rs @@ -0,0 +1,34 @@ +use proc_macro::TokenStream; + +/// Marks function as a test to be run on NayDuck during nightly tests run. +/// +/// This attribute marks function as a test and marks it ignored unless +/// `expensive_tests` feature is enabled on the crate defining the function. +/// +/// Long-running tests should be marked with `#[nightly_test]` rather than +/// `#[test]` so that the tests are not executed by default by `cargo test`. +/// +/// # Example +/// +/// ```console +/// #[test] +/// fn fast_unit_test() { /* ... */ } +/// +/// #[nightly_test] +/// fn slow_nightly_test() { /* ... */ } +/// ``` +#[proc_macro_attribute] +pub fn nightly_test(attr: TokenStream, stream: TokenStream) -> TokenStream { + if !attr.is_empty() { + panic!("#[nightly_test] attribute macro does not take arguments"); + } + + let mut result: TokenStream = r#" + #[test] + #[cfg_attr(not(feature = "expensive_tests"), ignore)] + "# + .parse() + .unwrap(); + result.extend(stream); + result +}