diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index 4a797d4b..11793002 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -133,7 +133,9 @@ mod common; use common::{ check::{is_zebrad_version, EphemeralCheck, EphemeralConfig}, - config::{default_test_config, persistent_test_config, stored_config_path, testdir}, + config::{ + config_file_full_path, configs_dir, default_test_config, persistent_test_config, testdir, + }, launch::{ spawn_zebrad_for_rpc_without_initial_peers, ZebradTestDirExt, BETWEEN_NODES_DELAY, LAUNCH_DELAY, @@ -503,14 +505,17 @@ fn version_args() -> Result<()> { /// they use the generated config. So parallel execution can cause port and /// cache conflicts. #[test] -fn config_test() -> Result<()> { +fn config_tests() -> Result<()> { valid_generated_config("start", "Starting zebrad")?; // Check what happens when Zebra parses an invalid config invalid_generated_config()?; - // Check that an older stored configuration we have for Zebra works - stored_config_works()?; + // Check that we have a current version of the config stored + last_config_is_stored()?; + + // Check that Zebra stored configuration works + stored_configs_works()?; // Runs `zebrad` serially to avoid potential port conflicts app_no_args()?; @@ -597,6 +602,63 @@ fn valid_generated_config(command: &str, expect_stdout_line_contains: &str) -> R Ok(()) } +/// Check if the config produced by current zebrad is stored. +fn last_config_is_stored() -> Result<()> { + let _init_guard = zebra_test::init(); + + let testdir = testdir()?; + + // Add a config file name to tempdir path + let generated_config_path = testdir.path().join("zebrad.toml"); + + // Generate configuration in temp dir path + let child = + testdir.spawn_child(args!["generate", "-o": generated_config_path.to_str().unwrap()])?; + + let output = child.wait_with_output()?; + let output = output.assert_success()?; + + assert_with_context!( + generated_config_path.exists(), + &output, + "generated config file not found" + ); + + // Get the contents of the generated config file + let generated_content = + fs::read_to_string(generated_config_path).expect("Should have been able to read the file"); + + // We need to replace the cache dir path as stored configs has a dummy `cache_dir` string there. + let processed_generated_content = generated_content.replace( + zebra_state::Config::default() + .cache_dir + .to_str() + .expect("a valid cache dir"), + "cache_dir", + ); + + // Loop all the stored configs + for config_file in configs_dir() + .read_dir() + .expect("read_dir call failed") + .flatten() + { + // Read stored config + let stored_content = fs::read_to_string(config_file_full_path(config_file.path())) + .expect("Should have been able to read the file"); + + // If any stored config is equal to the generated then we are good. + if stored_content.eq(&processed_generated_content) { + return Ok(()); + } + } + Err(eyre!( + "latest zebrad config is not being tested for compatibility.\n\ + Run `zebrad generate -o zebrad/tests/common/configs/.toml`\n\ + and commit the latest config to Zebra's git repository" + )) +} + /// Checks that Zebra prints an informative message when it cannot parse the /// config file. fn invalid_generated_config() -> Result<()> { @@ -670,28 +732,36 @@ fn invalid_generated_config() -> Result<()> { Ok(()) } -/// Test that an older `zebrad.toml` can still be parsed by the latest `zebrad`. -fn stored_config_works() -> Result<()> { - let stored_config_path = stored_config_path(); - let run_dir = testdir()?; +/// Test all versions of `zebrad.toml` we have stored can be parsed by the latest `zebrad`. +fn stored_configs_works() -> Result<()> { + let old_configs_dir = configs_dir(); - // run zebra with stored config - let mut child = - run_dir.spawn_child(args!["-c", stored_config_path.to_str().unwrap(), "start"])?; + for config_file in old_configs_dir + .read_dir() + .expect("read_dir call failed") + .flatten() + { + let run_dir = testdir()?; + let stored_config_path = config_file_full_path(config_file.path()); - // zebra was able to start with the stored config - child.expect_stdout_line_matches("Starting zebrad".to_string())?; + // run zebra with stored config + let mut child = + run_dir.spawn_child(args!["-c", stored_config_path.to_str().unwrap(), "start"])?; - // finish - child.kill(false)?; + // zebra was able to start with the stored config + child.expect_stdout_line_matches("Starting zebrad".to_string())?; - let output = child.wait_with_output()?; - let output = output.assert_failure()?; + // finish + child.kill(false)?; - // [Note on port conflict](#Note on port conflict) - output - .assert_was_killed() - .wrap_err("Possible port conflict. Are there other acceptance tests running?")?; + let output = child.wait_with_output()?; + let output = output.assert_failure()?; + + // [Note on port conflict](#Note on port conflict) + output + .assert_was_killed() + .wrap_err("Possible port conflict. Are there other acceptance tests running?")?; + } Ok(()) } diff --git a/zebrad/tests/common/config.rs b/zebrad/tests/common/config.rs index 3a22e4ee..fbc79716 100644 --- a/zebrad/tests/common/config.rs +++ b/zebrad/tests/common/config.rs @@ -85,7 +85,13 @@ pub fn testdir() -> Result { .map_err(Into::into) } -/// Get stored config path -pub fn stored_config_path() -> PathBuf { - Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/common/config.toml") +/// Get the directory where we have different config files. +pub fn configs_dir() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/common/configs") +} + +/// Given a config file name, return full path to it. +pub fn config_file_full_path(config_file: PathBuf) -> PathBuf { + let path = configs_dir().join(config_file); + Path::new(&path).into() } diff --git a/zebrad/tests/common/config.toml b/zebrad/tests/common/configs/v1.0.0-beta.12.toml similarity index 96% rename from zebrad/tests/common/config.toml rename to zebrad/tests/common/configs/v1.0.0-beta.12.toml index 2291b5fb..32421cf0 100644 --- a/zebrad/tests/common/config.toml +++ b/zebrad/tests/common/configs/v1.0.0-beta.12.toml @@ -55,8 +55,8 @@ delete_old_database = true ephemeral = false [sync] -lookahead_limit = 400 -max_concurrent_block_requests = 25 +lookahead_limit = 1200 +max_concurrent_block_requests = 40 [tracing] force_use_color = false diff --git a/zebrad/tests/common/configs/v1.0.0-beta.13.toml b/zebrad/tests/common/configs/v1.0.0-beta.13.toml new file mode 100644 index 00000000..14dc310a --- /dev/null +++ b/zebrad/tests/common/configs/v1.0.0-beta.13.toml @@ -0,0 +1,66 @@ +# Default configuration for zebrad. +# +# This file can be used as a skeleton for custom configs. +# +# Unspecified fields use default values. Optional fields are Some(field) if the +# field is present and None if it is absent. +# +# This file is generated as an example using zebrad's current defaults. +# You should set only the config options you want to keep, and delete the rest. +# Only a subset of fields are present in the skeleton, since optional values +# whose default is None are omitted. +# +# The config format (including a complete list of sections and fields) is +# documented here: +# https://doc.zebra.zfnd.org/zebrad/config/struct.ZebradConfig.html +# +# zebrad attempts to load configs in the following order: +# +# 1. The -c flag on the command line, e.g., `zebrad -c myconfig.toml start`; +# 2. The file `zebrad.toml` in the users's preference directory (platform-dependent); +# 3. The default config. + +[consensus] +checkpoint_sync = true +debug_skip_parameter_preload = false + +[mempool] +eviction_memory_time = '1h' +tx_cost_limit = 80000000 + +[metrics] + +[network] +crawl_new_peer_interval = '1m 1s' +initial_mainnet_peers = [ + 'dnsseed.z.cash:8233', + 'dnsseed.str4d.xyz:8233', + 'mainnet.seeder.zfnd.org:8233', + 'mainnet.is.yolo.money:8233', +] +initial_testnet_peers = [ + 'dnsseed.testnet.z.cash:18233', + 'testnet.seeder.zfnd.org:18233', + 'testnet.is.yolo.money:18233', +] +listen_addr = '0.0.0.0:8233' +network = 'Mainnet' +peerset_initial_target_size = 25 + +[rpc] + +[state] +cache_dir = 'cache_dir' +delete_old_database = true +ephemeral = false + +[sync] +checkpoint_verify_concurrency_limit = 1200 +download_concurrency_limit = 50 +full_verify_concurrency_limit = 20 +parallel_cpu_threads = 0 + +[tracing] +force_use_color = false +use_color = true +use_journald = false diff --git a/zebrad/tests/common/configs/v1.0.0-beta.15.toml b/zebrad/tests/common/configs/v1.0.0-beta.15.toml new file mode 100644 index 00000000..c38cc253 --- /dev/null +++ b/zebrad/tests/common/configs/v1.0.0-beta.15.toml @@ -0,0 +1,69 @@ +# Default configuration for zebrad. +# +# This file can be used as a skeleton for custom configs. +# +# Unspecified fields use default values. Optional fields are Some(field) if the +# field is present and None if it is absent. +# +# This file is generated as an example using zebrad's current defaults. +# You should set only the config options you want to keep, and delete the rest. +# Only a subset of fields are present in the skeleton, since optional values +# whose default is None are omitted. +# +# The config format (including a complete list of sections and fields) is +# documented here: +# https://doc.zebra.zfnd.org/zebrad/config/struct.ZebradConfig.html +# +# zebrad attempts to load configs in the following order: +# +# 1. The -c flag on the command line, e.g., `zebrad -c myconfig.toml start`; +# 2. The file `zebrad.toml` in the users's preference directory (platform-dependent); +# 3. The default config. + +[consensus] +checkpoint_sync = true +debug_skip_parameter_preload = false + +[mempool] +eviction_memory_time = '1h' +tx_cost_limit = 80000000 + +[metrics] + +[network] +crawl_new_peer_interval = '1m 1s' +initial_mainnet_peers = [ + 'dnsseed.z.cash:8233', + 'dnsseed.str4d.xyz:8233', + 'mainnet.seeder.zfnd.org:8233', + 'mainnet.is.yolo.money:8233', +] +initial_testnet_peers = [ + 'dnsseed.testnet.z.cash:18233', + 'testnet.seeder.zfnd.org:18233', + 'testnet.is.yolo.money:18233', +] +listen_addr = '0.0.0.0:8233' +network = 'Mainnet' +peerset_initial_target_size = 25 + +[rpc] +debug_force_finished_sync = false +parallel_cpu_threads = 1 + +[state] +cache_dir = 'cache_dir' +delete_old_database = true +ephemeral = false + +[sync] +checkpoint_verify_concurrency_limit = 1200 +download_concurrency_limit = 50 +full_verify_concurrency_limit = 20 +parallel_cpu_threads = 0 + +[tracing] +buffer_limit = 128000 +force_use_color = false +use_color = true +use_journald = false