Add regression tests for boot_node (#2749)
## Issue Addressed
Resolves #2602
## Proposed Changes
*Note: For a review it might help to look at the individual commits.*
### `boot_node`
Add support for the flags `dump-config` and `immediate-shutdown`. For `immediate-shutdown` the actual behavior could be described as `dump-config-and-exit`.
Both flags are handled in `boot_node::main`, which appears to be the simplest approach.
### `boot_node` regression tests
Added in `lighthouse/tests/boot_node.rs`.
### `CommandLineTestExec`
Factors out boilerplate related to CLI tests. It's used in the regression tests for `boot_node`, `beacon_node` and `validator_client`.
## Open TODO
Add tests for `boot_node` flags `enable-enr-auto-update` and `disable-packet-filter`. They end up in [`Discv5Config`](9ed2cba6bc/boot_node/src/config.rs (L29)
), which doesn't support serde (de)serialization.
I haven't found a workaround - guidance would be appreciated.
This commit is contained in:
parent
fbafe416d1
commit
d01fe02824
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -479,11 +479,15 @@ version = "2.0.1"
|
||||
dependencies = [
|
||||
"beacon_node",
|
||||
"clap",
|
||||
"clap_utils",
|
||||
"eth2_ssz",
|
||||
"hex",
|
||||
"lighthouse_network",
|
||||
"log",
|
||||
"logging",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"slog",
|
||||
"slog-async",
|
||||
"slog-scope",
|
||||
@ -3193,6 +3197,7 @@ dependencies = [
|
||||
"lighthouse_network",
|
||||
"lighthouse_version",
|
||||
"malloc_utils",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"slashing_protection",
|
||||
"slog",
|
||||
|
@ -7,6 +7,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
beacon_node = { path = "../beacon_node" }
|
||||
clap = "2.33.3"
|
||||
clap_utils = { path = "../common/clap_utils" }
|
||||
lighthouse_network = { path = "../beacon_node/lighthouse_network" }
|
||||
types = { path = "../consensus/types" }
|
||||
eth2_ssz = "0.4.0"
|
||||
@ -19,3 +20,6 @@ slog-async = "2.5.0"
|
||||
slog-scope = "4.3.0"
|
||||
slog-stdlog = "4.0.0"
|
||||
hex = "0.4.2"
|
||||
serde = "1.0.116"
|
||||
serde_derive = "1.0.116"
|
||||
serde_json = "1.0.66"
|
||||
|
@ -5,6 +5,7 @@ use lighthouse_network::{
|
||||
discovery::{create_enr_builder_from_config, load_enr_from_disk, use_or_load_enr},
|
||||
load_private_key, CombinedKeyExt, NetworkConfig,
|
||||
};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz::Encode;
|
||||
use std::convert::TryFrom;
|
||||
use std::net::SocketAddr;
|
||||
@ -130,3 +131,35 @@ impl<T: EthSpec> TryFrom<&ArgMatches<'_>> for BootNodeConfig<T> {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The set of configuration parameters that can safely be (de)serialized.
|
||||
///
|
||||
/// Its fields are a subset of the fields of `BootNodeConfig`.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct BootNodeConfigSerialization {
|
||||
pub listen_socket: SocketAddr,
|
||||
// TODO: Generalise to multiaddr
|
||||
pub boot_nodes: Vec<Enr>,
|
||||
pub local_enr: Enr,
|
||||
}
|
||||
|
||||
impl BootNodeConfigSerialization {
|
||||
/// Returns a `BootNodeConfigSerialization` obtained from copying resp. cloning the
|
||||
/// relevant fields of `config`
|
||||
pub fn from_config_ref<T: EthSpec>(config: &BootNodeConfig<T>) -> Self {
|
||||
let BootNodeConfig {
|
||||
listen_socket,
|
||||
boot_nodes,
|
||||
local_enr,
|
||||
local_key: _,
|
||||
discv5_config: _,
|
||||
phantom: _,
|
||||
} = config;
|
||||
|
||||
BootNodeConfigSerialization {
|
||||
listen_socket: *listen_socket,
|
||||
boot_nodes: boot_nodes.clone(),
|
||||
local_enr: local_enr.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,17 +3,24 @@ use clap::ArgMatches;
|
||||
use slog::{o, Drain, Level, Logger};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
mod cli;
|
||||
mod config;
|
||||
pub mod config;
|
||||
mod server;
|
||||
pub use cli::cli_app;
|
||||
use config::BootNodeConfig;
|
||||
use config::{BootNodeConfig, BootNodeConfigSerialization};
|
||||
use types::{EthSpec, EthSpecId};
|
||||
|
||||
const LOG_CHANNEL_SIZE: usize = 2048;
|
||||
|
||||
/// Run the bootnode given the CLI configuration.
|
||||
pub fn run(matches: &ArgMatches<'_>, eth_spec_id: EthSpecId, debug_level: String) {
|
||||
pub fn run(
|
||||
lh_matches: &ArgMatches<'_>,
|
||||
bn_matches: &ArgMatches<'_>,
|
||||
eth_spec_id: EthSpecId,
|
||||
debug_level: String,
|
||||
) {
|
||||
let debug_level = match debug_level.as_str() {
|
||||
"trace" => log::Level::Trace,
|
||||
"debug" => log::Level::Debug,
|
||||
@ -49,24 +56,40 @@ pub fn run(matches: &ArgMatches<'_>, eth_spec_id: EthSpecId, debug_level: String
|
||||
let log = slog_scope::logger();
|
||||
// Run the main function emitting any errors
|
||||
if let Err(e) = match eth_spec_id {
|
||||
EthSpecId::Minimal => main::<types::MinimalEthSpec>(matches, log),
|
||||
EthSpecId::Mainnet => main::<types::MainnetEthSpec>(matches, log),
|
||||
EthSpecId::Minimal => main::<types::MinimalEthSpec>(lh_matches, bn_matches, log),
|
||||
EthSpecId::Mainnet => main::<types::MainnetEthSpec>(lh_matches, bn_matches, log),
|
||||
} {
|
||||
slog::crit!(slog_scope::logger(), "{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
fn main<T: EthSpec>(matches: &ArgMatches<'_>, log: slog::Logger) -> Result<(), String> {
|
||||
fn main<T: EthSpec>(
|
||||
lh_matches: &ArgMatches<'_>,
|
||||
bn_matches: &ArgMatches<'_>,
|
||||
log: slog::Logger,
|
||||
) -> Result<(), String> {
|
||||
// Builds a custom executor for the bootnode
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.map_err(|e| format!("Failed to build runtime: {}", e))?;
|
||||
|
||||
// parse the CLI args into a useable config
|
||||
let config: BootNodeConfig<T> = BootNodeConfig::try_from(matches)?;
|
||||
// Parse the CLI args into a useable config
|
||||
let config: BootNodeConfig<T> = BootNodeConfig::try_from(bn_matches)?;
|
||||
|
||||
// Dump config if `dump-config` flag is set
|
||||
let dump_config = clap_utils::parse_optional::<PathBuf>(lh_matches, "dump-config")?;
|
||||
if let Some(dump_path) = dump_config {
|
||||
let config_sz = BootNodeConfigSerialization::from_config_ref(&config);
|
||||
let mut file = File::create(dump_path)
|
||||
.map_err(|e| format!("Failed to create dumped config: {:?}", e))?;
|
||||
serde_json::to_writer(&mut file, &config_sz)
|
||||
.map_err(|e| format!("Error serializing config: {:?}", e))?;
|
||||
}
|
||||
|
||||
// Run the boot node
|
||||
runtime.block_on(server::run(config, log));
|
||||
if !lh_matches.is_present("immediate-shutdown") {
|
||||
runtime.block_on(server::run(config, log));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ lighthouse_version = { path = "../common/lighthouse_version" }
|
||||
account_utils = { path = "../common/account_utils" }
|
||||
lighthouse_metrics = { path = "../common/lighthouse_metrics" }
|
||||
lazy_static = "1.4.0"
|
||||
serde = { version = "1.0.116", features = ["derive"] }
|
||||
serde_json = "1.0.59"
|
||||
task_executor = { path = "../common/task_executor" }
|
||||
malloc_utils = { path = "../common/malloc_utils" }
|
||||
|
@ -204,7 +204,7 @@ fn main() {
|
||||
.expect("Debug-level must be present")
|
||||
.into();
|
||||
|
||||
boot_node::run(bootnode_matches, eth_spec_id, debug_info);
|
||||
boot_node::run(&matches, bootnode_matches, eth_spec_id, debug_info);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -1,25 +1,21 @@
|
||||
use beacon_node::ClientConfig as Config;
|
||||
|
||||
use crate::exec::{CommandLineTestExec, CompletedTest};
|
||||
use lighthouse_network::PeerId;
|
||||
use serde_json::from_reader;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::net::{TcpListener, UdpSocket};
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, Output};
|
||||
use std::str::{from_utf8, FromStr};
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use std::string::ToString;
|
||||
use tempfile::TempDir;
|
||||
use types::{Checkpoint, Epoch, Hash256};
|
||||
|
||||
const BEACON_CMD: &str = "beacon_node";
|
||||
const CONFIG_NAME: &str = "bn_dump.json";
|
||||
const DUMP_CONFIG_CMD: &str = "dump-config";
|
||||
const IMMEDIATE_SHUTDOWN_CMD: &str = "immediate-shutdown";
|
||||
const DEFAULT_ETH1_ENDPOINT: &str = "http://localhost:8545/";
|
||||
|
||||
/// Returns the `lighthouse beacon_node --immediate-shutdown` command.
|
||||
/// Returns the `lighthouse beacon_node` command.
|
||||
fn base_cmd() -> Command {
|
||||
let lighthouse_bin = env!("CARGO_BIN_EXE_lighthouse");
|
||||
let path = lighthouse_bin
|
||||
@ -27,25 +23,10 @@ fn base_cmd() -> Command {
|
||||
.expect("should parse CARGO_TARGET_DIR");
|
||||
|
||||
let mut cmd = Command::new(path);
|
||||
cmd.arg(BEACON_CMD)
|
||||
.arg(format!("--{}", IMMEDIATE_SHUTDOWN_CMD));
|
||||
|
||||
cmd.arg("beacon_node");
|
||||
cmd
|
||||
}
|
||||
|
||||
/// Executes a `Command`, returning a `Result` based upon the success exit code of the command.
|
||||
fn output_result(cmd: &mut Command) -> Result<Output, String> {
|
||||
let output = cmd.output().expect("should run command");
|
||||
|
||||
if output.status.success() {
|
||||
Ok(output)
|
||||
} else {
|
||||
Err(from_utf8(&output.stderr)
|
||||
.expect("stderr is not utf8")
|
||||
.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper around `Command` for easier Command Line Testing.
|
||||
struct CommandLineTest {
|
||||
cmd: Command,
|
||||
@ -56,89 +37,24 @@ impl CommandLineTest {
|
||||
CommandLineTest { cmd: base_cmd }
|
||||
}
|
||||
|
||||
fn flag(mut self, flag: &str, value: Option<&str>) -> Self {
|
||||
// Build the command by adding the flag and any values.
|
||||
self.cmd.arg(format!("--{}", flag));
|
||||
if let Some(value) = value {
|
||||
self.cmd.arg(value);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn run(&mut self) -> CompletedTest {
|
||||
// Setup temp directories.
|
||||
let tmp_dir = TempDir::new().expect("Unable to create temporary directory");
|
||||
let tmp_path: PathBuf = tmp_dir.path().join(CONFIG_NAME);
|
||||
|
||||
// Add --datadir <temp_dir> --dump-config <temp_path> -z to cmd.
|
||||
self.cmd
|
||||
.arg("--datadir")
|
||||
.arg(tmp_dir.path().as_os_str())
|
||||
.arg(format!("--{}", DUMP_CONFIG_CMD))
|
||||
.arg(tmp_path.as_os_str())
|
||||
.arg("-z");
|
||||
|
||||
// Run the command.
|
||||
let output = output_result(&mut self.cmd);
|
||||
if let Err(e) = output {
|
||||
panic!("{:?}", e);
|
||||
}
|
||||
|
||||
// Grab the config.
|
||||
let config: Config =
|
||||
from_reader(File::open(tmp_path).expect("Unable to open dumped config"))
|
||||
.expect("Unable to deserialize to ClientConfig");
|
||||
CompletedTest {
|
||||
config,
|
||||
dir: tmp_dir,
|
||||
}
|
||||
}
|
||||
|
||||
fn run_with_no_zero_port(&mut self) -> CompletedTest {
|
||||
// Setup temp directories.
|
||||
let tmp_dir = TempDir::new().expect("Unable to create temporary directory");
|
||||
let tmp_path: PathBuf = tmp_dir.path().join(CONFIG_NAME);
|
||||
|
||||
// Add --datadir <temp_dir> --dump-config <temp_path> to cmd.
|
||||
self.cmd
|
||||
.arg("--datadir")
|
||||
.arg(tmp_dir.path().as_os_str())
|
||||
.arg(format!("--{}", DUMP_CONFIG_CMD))
|
||||
.arg(tmp_path.as_os_str());
|
||||
|
||||
// Run the command.
|
||||
let output = output_result(&mut self.cmd);
|
||||
if let Err(e) = output {
|
||||
panic!("{:?}", e);
|
||||
}
|
||||
|
||||
// Grab the config.
|
||||
let config: Config =
|
||||
from_reader(File::open(tmp_path).expect("Unable to open dumped config"))
|
||||
.expect("Unable to deserialize to ClientConfig");
|
||||
CompletedTest {
|
||||
config,
|
||||
dir: tmp_dir,
|
||||
}
|
||||
fn run_with_zero_port(&mut self) -> CompletedTest<Config> {
|
||||
self.cmd.arg("-z");
|
||||
self.run()
|
||||
}
|
||||
}
|
||||
struct CompletedTest {
|
||||
config: Config,
|
||||
dir: TempDir,
|
||||
}
|
||||
impl CompletedTest {
|
||||
fn with_config<F: Fn(&Config)>(self, func: F) {
|
||||
func(&self.config);
|
||||
}
|
||||
fn with_config_and_dir<F: Fn(&Config, &TempDir)>(self, func: F) {
|
||||
func(&self.config, &self.dir);
|
||||
|
||||
impl CommandLineTestExec for CommandLineTest {
|
||||
type Config = Config;
|
||||
|
||||
fn cmd_mut(&mut self) -> &mut Command {
|
||||
&mut self.cmd
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn datadir_flag() {
|
||||
CommandLineTest::new()
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config_and_dir(|config, dir| assert_eq!(config.data_dir, dir.path().join("beacon")));
|
||||
}
|
||||
|
||||
@ -146,7 +62,7 @@ fn datadir_flag() {
|
||||
fn staking_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("staking", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert!(config.http_api.enabled);
|
||||
assert!(config.sync_eth1_chain);
|
||||
@ -166,21 +82,21 @@ fn wss_checkpoint_flag() {
|
||||
"wss-checkpoint",
|
||||
Some("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef:1010"),
|
||||
)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.chain.weak_subjectivity_checkpoint, state));
|
||||
}
|
||||
#[test]
|
||||
fn max_skip_slots_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("max-skip-slots", Some("10"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.chain.import_max_skip_slots, Some(10)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enable_lock_timeouts_default() {
|
||||
CommandLineTest::new()
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.chain.enable_lock_timeouts));
|
||||
}
|
||||
|
||||
@ -188,7 +104,7 @@ fn enable_lock_timeouts_default() {
|
||||
fn disable_lock_timeouts_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("disable-lock-timeouts", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(!config.chain.enable_lock_timeouts));
|
||||
}
|
||||
|
||||
@ -197,7 +113,7 @@ fn freezer_dir_flag() {
|
||||
let dir = TempDir::new().expect("Unable to create temporary directory");
|
||||
CommandLineTest::new()
|
||||
.flag("freezer-dir", dir.path().as_os_str().to_str())
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.freezer_db_path, Some(dir.path().to_path_buf())));
|
||||
}
|
||||
|
||||
@ -205,7 +121,7 @@ fn freezer_dir_flag() {
|
||||
fn graffiti_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("graffiti", Some("nice-graffiti"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(
|
||||
config.graffiti.to_string(),
|
||||
@ -222,7 +138,7 @@ fn trusted_peers_flag() {
|
||||
"trusted-peers",
|
||||
Some(format!("{},{}", peers[0].to_string(), peers[1].to_string()).as_str()),
|
||||
)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(
|
||||
PeerId::from(config.network.trusted_peers[0].clone()).to_bytes(),
|
||||
@ -240,14 +156,14 @@ fn trusted_peers_flag() {
|
||||
fn dummy_eth1_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("dummy-eth1", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.dummy_eth1_backend));
|
||||
}
|
||||
#[test]
|
||||
fn eth1_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("eth1", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.sync_eth1_chain));
|
||||
}
|
||||
#[test]
|
||||
@ -257,7 +173,7 @@ fn eth1_endpoints_flag() {
|
||||
"eth1-endpoints",
|
||||
Some("http://localhost:9545,https://infura.io/secret"),
|
||||
)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(
|
||||
config.eth1.endpoints[0].full.to_string(),
|
||||
@ -279,14 +195,14 @@ fn eth1_endpoints_flag() {
|
||||
fn eth1_blocks_per_log_query_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("eth1-blocks-per-log-query", Some("500"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.eth1.blocks_per_log_query, 500));
|
||||
}
|
||||
#[test]
|
||||
fn eth1_purge_cache_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("eth1-purge-cache", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.eth1.purge_cache));
|
||||
}
|
||||
|
||||
@ -296,14 +212,14 @@ fn network_dir_flag() {
|
||||
let dir = TempDir::new().expect("Unable to create temporary directory");
|
||||
CommandLineTest::new()
|
||||
.flag("network-dir", dir.path().as_os_str().to_str())
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.network.network_dir, dir.path()));
|
||||
}
|
||||
#[test]
|
||||
fn network_target_peers_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("target-peers", Some("55"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.network.target_peers, "55".parse::<usize>().unwrap());
|
||||
});
|
||||
@ -312,27 +228,27 @@ fn network_target_peers_flag() {
|
||||
fn network_subscribe_all_subnets_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("subscribe-all-subnets", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.network.subscribe_all_subnets));
|
||||
}
|
||||
#[test]
|
||||
fn network_import_all_attestations_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("import-all-attestations", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.network.import_all_attestations));
|
||||
}
|
||||
#[test]
|
||||
fn network_shutdown_after_sync_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("shutdown-after-sync", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.network.shutdown_after_sync));
|
||||
}
|
||||
#[test]
|
||||
fn network_shutdown_after_sync_disabled_flag() {
|
||||
CommandLineTest::new()
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(!config.network.shutdown_after_sync));
|
||||
}
|
||||
#[test]
|
||||
@ -340,7 +256,7 @@ fn network_listen_address_flag() {
|
||||
let addr = "127.0.0.2".parse::<Ipv4Addr>().unwrap();
|
||||
CommandLineTest::new()
|
||||
.flag("listen-address", Some("127.0.0.2"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.network.listen_address, addr));
|
||||
}
|
||||
#[test]
|
||||
@ -348,7 +264,7 @@ fn network_port_flag() {
|
||||
let port = unused_port("tcp").expect("Unable to find unused port.");
|
||||
CommandLineTest::new()
|
||||
.flag("port", Some(port.to_string().as_str()))
|
||||
.run_with_no_zero_port()
|
||||
.run()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.network.libp2p_port, port);
|
||||
assert_eq!(config.network.discovery_port, port);
|
||||
@ -361,7 +277,7 @@ fn network_port_and_discovery_port_flags() {
|
||||
CommandLineTest::new()
|
||||
.flag("port", Some(port1.to_string().as_str()))
|
||||
.flag("discovery-port", Some(port2.to_string().as_str()))
|
||||
.run_with_no_zero_port()
|
||||
.run()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.network.libp2p_port, port1);
|
||||
assert_eq!(config.network.discovery_port, port2);
|
||||
@ -371,14 +287,14 @@ fn network_port_and_discovery_port_flags() {
|
||||
fn disable_discovery_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("disable-discovery", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.network.disable_discovery));
|
||||
}
|
||||
#[test]
|
||||
fn disable_upnp_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("disable-upnp", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(!config.network.upnp_enabled));
|
||||
}
|
||||
#[test]
|
||||
@ -386,7 +302,7 @@ fn default_boot_nodes() {
|
||||
let mainnet = vec![
|
||||
// Lighthouse Team (Sigma Prime)
|
||||
"enr:-Jq4QItoFUuug_n_qbYbU0OY04-np2wT8rUCauOOXNi0H3BWbDj-zbfZb7otA7jZ6flbBpx1LNZK2TDebZ9dEKx84LYBhGV0aDKQtTA_KgEAAAD__________4JpZIJ2NIJpcISsaa0ZiXNlY3AyNTZrMaEDHAD2JKYevx89W0CcFJFiskdcEzkH_Wdv9iW42qLK79ODdWRwgiMo",
|
||||
"enr:-Jq4QN_YBsUOqQsty1OGvYv48PMaiEt1AzGD1NkYQHaxZoTyVGqMYXg0K9c0LPNWC9pkXmggApp8nygYLsQwScwAgfgBhGV0aDKQtTA_KgEAAAD__________4JpZIJ2NIJpcISLosQxiXNlY3AyNTZrMaEDBJj7_dLFACaxBfaI8KZTh_SSJUjhyAyfshimvSqo22WDdWRwgiMo",
|
||||
"enr:-Jq4QN_YBsUOqQsty1OGvYv48PMaiEt1AzGD1NkYQHaxZoTyVGqMYXg0K9c0LPNWC9pkXmggApp8nygYLsQwScwAgfgBhGV0aDKQtTA_KgEAAAD__________4JpZIJ2NIJpcISLosQxiXNlY3AyNTZrMaEDBJj7_dLFACaxBfaI8KZTh_SSJUjhyAyfshimvSqo22WDdWRwgiMo",
|
||||
// EF Team
|
||||
"enr:-Ku4QHqVeJ8PPICcWk1vSn_XcSkjOkNiTg6Fmii5j6vUQgvzMc9L1goFnLKgXqBJspJjIsB91LTOleFmyWWrFVATGngBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhAMRHkWJc2VjcDI1NmsxoQKLVXFOhp2uX6jeT0DvvDpPcU8FWMjQdR4wMuORMhpX24N1ZHCCIyg",
|
||||
"enr:-Ku4QG-2_Md3sZIAUebGYT6g0SMskIml77l6yR-M_JXc-UdNHCmHQeOiMLbylPejyJsdAPsTHJyjJB2sYGDLe0dn8uYBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhBLY-NyJc2VjcDI1NmsxoQORcM6e19T1T9gi7jxEZjk_sjVLGFscUNqAY9obgZaxbIN1ZHCCIyg",
|
||||
@ -404,26 +320,28 @@ fn default_boot_nodes() {
|
||||
"enr:-LK4QKWrXTpV9T78hNG6s8AM6IO4XH9kFT91uZtFg1GcsJ6dKovDOr1jtAAFPnS2lvNltkOGA9k29BUN7lFh_sjuc9QBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhANAdd-Jc2VjcDI1NmsxoQLQa6ai7y9PMN5hpLe5HmiJSlYzMuzP7ZhwRiwHvqNXdoN0Y3CCI4yDdWRwgiOM"
|
||||
];
|
||||
|
||||
CommandLineTest::new().run().with_config(|config| {
|
||||
// Lighthouse Team (Sigma Prime)
|
||||
assert_eq!(config.network.boot_nodes_enr[0].to_base64(), mainnet[0]);
|
||||
assert_eq!(config.network.boot_nodes_enr[1].to_base64(), mainnet[1]);
|
||||
// EF Team
|
||||
assert_eq!(config.network.boot_nodes_enr[2].to_base64(), mainnet[2]);
|
||||
assert_eq!(config.network.boot_nodes_enr[3].to_base64(), mainnet[3]);
|
||||
assert_eq!(config.network.boot_nodes_enr[4].to_base64(), mainnet[4]);
|
||||
assert_eq!(config.network.boot_nodes_enr[5].to_base64(), mainnet[5]);
|
||||
// Teku team (Consensys)
|
||||
assert_eq!(config.network.boot_nodes_enr[6].to_base64(), mainnet[6]);
|
||||
assert_eq!(config.network.boot_nodes_enr[7].to_base64(), mainnet[7]);
|
||||
// Prysm team (Prysmatic Labs)
|
||||
assert_eq!(config.network.boot_nodes_enr[8].to_base64(), mainnet[8]);
|
||||
assert_eq!(config.network.boot_nodes_enr[9].to_base64(), mainnet[9]);
|
||||
assert_eq!(config.network.boot_nodes_enr[10].to_base64(), mainnet[10]);
|
||||
// Nimbus team
|
||||
assert_eq!(config.network.boot_nodes_enr[11].to_base64(), mainnet[11]);
|
||||
assert_eq!(config.network.boot_nodes_enr[12].to_base64(), mainnet[12]);
|
||||
});
|
||||
CommandLineTest::new()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
// Lighthouse Team (Sigma Prime)
|
||||
assert_eq!(config.network.boot_nodes_enr[0].to_base64(), mainnet[0]);
|
||||
assert_eq!(config.network.boot_nodes_enr[1].to_base64(), mainnet[1]);
|
||||
// EF Team
|
||||
assert_eq!(config.network.boot_nodes_enr[2].to_base64(), mainnet[2]);
|
||||
assert_eq!(config.network.boot_nodes_enr[3].to_base64(), mainnet[3]);
|
||||
assert_eq!(config.network.boot_nodes_enr[4].to_base64(), mainnet[4]);
|
||||
assert_eq!(config.network.boot_nodes_enr[5].to_base64(), mainnet[5]);
|
||||
// Teku team (Consensys)
|
||||
assert_eq!(config.network.boot_nodes_enr[6].to_base64(), mainnet[6]);
|
||||
assert_eq!(config.network.boot_nodes_enr[7].to_base64(), mainnet[7]);
|
||||
// Prysm team (Prysmatic Labs)
|
||||
assert_eq!(config.network.boot_nodes_enr[8].to_base64(), mainnet[8]);
|
||||
assert_eq!(config.network.boot_nodes_enr[9].to_base64(), mainnet[9]);
|
||||
assert_eq!(config.network.boot_nodes_enr[10].to_base64(), mainnet[10]);
|
||||
// Nimbus team
|
||||
assert_eq!(config.network.boot_nodes_enr[11].to_base64(), mainnet[11]);
|
||||
assert_eq!(config.network.boot_nodes_enr[12].to_base64(), mainnet[12]);
|
||||
});
|
||||
}
|
||||
#[test]
|
||||
fn boot_nodes_flag() {
|
||||
@ -432,7 +350,7 @@ fn boot_nodes_flag() {
|
||||
let enr: Vec<&str> = nodes.split(',').collect();
|
||||
CommandLineTest::new()
|
||||
.flag("boot-nodes", Some(nodes))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.network.boot_nodes_enr[0].to_base64(), enr[0]);
|
||||
assert_eq!(config.network.boot_nodes_enr[1].to_base64(), enr[1]);
|
||||
@ -445,7 +363,7 @@ fn boot_nodes_multiaddr_flag() {
|
||||
let multiaddr: Vec<&str> = nodes.split(',').collect();
|
||||
CommandLineTest::new()
|
||||
.flag("boot-nodes", Some(nodes))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(
|
||||
config.network.boot_nodes_multiaddr[0].to_string(),
|
||||
@ -461,16 +379,18 @@ fn boot_nodes_multiaddr_flag() {
|
||||
fn private_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("private", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.network.private));
|
||||
}
|
||||
#[test]
|
||||
fn zero_ports_flag() {
|
||||
CommandLineTest::new().run().with_config(|config| {
|
||||
assert_eq!(config.network.enr_address, None);
|
||||
assert_eq!(config.http_api.listen_port, 0);
|
||||
assert_eq!(config.http_metrics.listen_port, 0);
|
||||
});
|
||||
CommandLineTest::new()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.network.enr_address, None);
|
||||
assert_eq!(config.http_api.listen_port, 0);
|
||||
assert_eq!(config.http_metrics.listen_port, 0);
|
||||
});
|
||||
}
|
||||
|
||||
// Tests for ENR flags.
|
||||
@ -479,7 +399,7 @@ fn enr_udp_port_flags() {
|
||||
let port = unused_port("udp").expect("Unable to find unused port.");
|
||||
CommandLineTest::new()
|
||||
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.network.enr_udp_port, Some(port)));
|
||||
}
|
||||
#[test]
|
||||
@ -487,7 +407,7 @@ fn enr_tcp_port_flags() {
|
||||
let port = unused_port("tcp").expect("Unable to find unused port.");
|
||||
CommandLineTest::new()
|
||||
.flag("enr-tcp-port", Some(port.to_string().as_str()))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.network.enr_tcp_port, Some(port)));
|
||||
}
|
||||
#[test]
|
||||
@ -500,7 +420,7 @@ fn enr_match_flag() {
|
||||
.flag("listen-address", Some("127.0.0.2"))
|
||||
.flag("discovery-port", Some(port1.to_string().as_str()))
|
||||
.flag("port", Some(port2.to_string().as_str()))
|
||||
.run_with_no_zero_port()
|
||||
.run()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.network.listen_address, addr);
|
||||
assert_eq!(config.network.enr_address, Some(addr));
|
||||
@ -515,7 +435,7 @@ fn enr_address_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("enr-address", Some("192.167.1.1"))
|
||||
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.network.enr_address, Some(addr));
|
||||
assert_eq!(config.network.enr_udp_port, Some(port));
|
||||
@ -529,7 +449,7 @@ fn enr_address_dns_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("enr-address", Some("localhost"))
|
||||
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert!(
|
||||
config.network.enr_address == Some(addr)
|
||||
@ -542,7 +462,7 @@ fn enr_address_dns_flag() {
|
||||
fn disable_enr_auto_update_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("disable-enr-auto-update", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.network.discv5_config.enr_update));
|
||||
}
|
||||
|
||||
@ -551,7 +471,7 @@ fn disable_enr_auto_update_flag() {
|
||||
fn http_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("http", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.http_api.enabled));
|
||||
}
|
||||
#[test]
|
||||
@ -559,7 +479,7 @@ fn http_address_flag() {
|
||||
let addr = "127.0.0.99".parse::<Ipv4Addr>().unwrap();
|
||||
CommandLineTest::new()
|
||||
.flag("http-address", Some("127.0.0.99"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.http_api.listen_addr, addr));
|
||||
}
|
||||
#[test]
|
||||
@ -569,14 +489,14 @@ fn http_port_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("http-port", Some(port1.to_string().as_str()))
|
||||
.flag("port", Some(port2.to_string().as_str()))
|
||||
.run_with_no_zero_port()
|
||||
.run()
|
||||
.with_config(|config| assert_eq!(config.http_api.listen_port, port1));
|
||||
}
|
||||
#[test]
|
||||
fn http_allow_origin_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("http-allow-origin", Some("127.0.0.99"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.http_api.allow_origin, Some("127.0.0.99".to_string()));
|
||||
});
|
||||
@ -585,7 +505,7 @@ fn http_allow_origin_flag() {
|
||||
fn http_allow_origin_all_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("http-allow-origin", Some("*"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.http_api.allow_origin, Some("*".to_string())));
|
||||
}
|
||||
#[test]
|
||||
@ -601,7 +521,7 @@ fn http_tls_flags() {
|
||||
"http-tls-key",
|
||||
dir.path().join("private.key").as_os_str().to_str(),
|
||||
)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
let tls_config = config
|
||||
.http_api
|
||||
@ -618,7 +538,7 @@ fn http_tls_flags() {
|
||||
fn metrics_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("metrics", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert!(config.http_metrics.enabled);
|
||||
assert!(config.network.metrics_enabled);
|
||||
@ -630,7 +550,7 @@ fn metrics_address_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("metrics", None)
|
||||
.flag("metrics-address", Some("127.0.0.99"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.http_metrics.listen_addr, addr));
|
||||
}
|
||||
#[test]
|
||||
@ -641,7 +561,7 @@ fn metrics_port_flag() {
|
||||
.flag("metrics", None)
|
||||
.flag("metrics-port", Some(port1.to_string().as_str()))
|
||||
.flag("port", Some(port2.to_string().as_str()))
|
||||
.run_with_no_zero_port()
|
||||
.run()
|
||||
.with_config(|config| assert_eq!(config.http_metrics.listen_port, port1));
|
||||
}
|
||||
#[test]
|
||||
@ -649,7 +569,7 @@ fn metrics_allow_origin_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("metrics", None)
|
||||
.flag("metrics-allow-origin", Some("http://localhost:5059"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(
|
||||
config.http_metrics.allow_origin,
|
||||
@ -662,7 +582,7 @@ fn metrics_allow_origin_all_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("metrics", None)
|
||||
.flag("metrics-allow-origin", Some("*"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.http_metrics.allow_origin, Some("*".to_string())));
|
||||
}
|
||||
|
||||
@ -671,7 +591,7 @@ fn metrics_allow_origin_all_flag() {
|
||||
fn validator_monitor_auto_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("validator-monitor-auto", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.validator_monitor_auto));
|
||||
}
|
||||
#[test]
|
||||
@ -679,7 +599,7 @@ fn validator_monitor_pubkeys_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("validator-monitor-pubkeys", Some("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef,\
|
||||
0xbeefdeadbeefdeaddeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.validator_monitor_pubkeys[0].to_string(), "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
|
||||
assert_eq!(config.validator_monitor_pubkeys[1].to_string(), "0xbeefdeadbeefdeaddeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
|
||||
@ -694,7 +614,7 @@ fn validator_monitor_file_flag() {
|
||||
.expect("Unable to write to file");
|
||||
CommandLineTest::new()
|
||||
.flag("validator-monitor-file", dir.path().join("pubkeys.txt").as_os_str().to_str())
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.validator_monitor_pubkeys[0].to_string(), "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
|
||||
assert_eq!(config.validator_monitor_pubkeys[1].to_string(), "0xbeefdeadbeefdeaddeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
|
||||
@ -706,21 +626,21 @@ fn validator_monitor_file_flag() {
|
||||
fn slots_per_restore_point_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("slots-per-restore-point", Some("64"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.store.slots_per_restore_point, 64));
|
||||
}
|
||||
#[test]
|
||||
fn block_cache_size_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("block-cache-size", Some("4"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert_eq!(config.store.block_cache_size, 4_usize));
|
||||
}
|
||||
#[test]
|
||||
fn auto_compact_db_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("auto-compact-db", Some("false"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(!config.store.compact_on_prune));
|
||||
}
|
||||
#[test]
|
||||
@ -728,20 +648,20 @@ fn compact_db_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("auto-compact-db", Some("false"))
|
||||
.flag("compact-db", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.store.compact_on_init));
|
||||
}
|
||||
#[test]
|
||||
fn reconstruct_historic_states_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("reconstruct-historic-states", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(config.chain.reconstruct_historic_states));
|
||||
}
|
||||
#[test]
|
||||
fn no_reconstruct_historic_states_flag() {
|
||||
CommandLineTest::new()
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| assert!(!config.chain.reconstruct_historic_states));
|
||||
}
|
||||
|
||||
@ -751,7 +671,7 @@ fn slasher_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("slasher", None)
|
||||
.flag("slasher-max-db-size", Some("16"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config_and_dir(|config, dir| {
|
||||
if let Some(slasher_config) = &config.slasher {
|
||||
assert_eq!(
|
||||
@ -770,7 +690,7 @@ fn slasher_dir_flag() {
|
||||
.flag("slasher", None)
|
||||
.flag("slasher-dir", dir.path().as_os_str().to_str())
|
||||
.flag("slasher-max-db-size", Some("16"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
if let Some(slasher_config) = &config.slasher {
|
||||
assert_eq!(slasher_config.database_path, dir.path());
|
||||
@ -785,7 +705,7 @@ fn slasher_update_period_flag() {
|
||||
.flag("slasher", None)
|
||||
.flag("slasher-max-db-size", Some("16"))
|
||||
.flag("slasher-update-period", Some("100"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
if let Some(slasher_config) = &config.slasher {
|
||||
assert_eq!(slasher_config.update_period, 100);
|
||||
@ -819,7 +739,7 @@ fn slasher_history_length_flag() {
|
||||
.flag("slasher", None)
|
||||
.flag("slasher-max-db-size", Some("16"))
|
||||
.flag("slasher-history-length", Some("2048"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
if let Some(slasher_config) = &config.slasher {
|
||||
assert_eq!(slasher_config.history_length, 2048);
|
||||
@ -833,7 +753,7 @@ fn slasher_max_db_size_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("slasher", None)
|
||||
.flag("slasher-max-db-size", Some("10"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
let slasher_config = config
|
||||
.slasher
|
||||
@ -848,7 +768,7 @@ fn slasher_chunk_size_flag() {
|
||||
.flag("slasher", None)
|
||||
.flag("slasher-chunk-size", Some("32"))
|
||||
.flag("slasher-max-db-size", Some("16"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
let slasher_config = config
|
||||
.slasher
|
||||
@ -863,7 +783,7 @@ fn slasher_validator_chunk_size_flag() {
|
||||
.flag("slasher", None)
|
||||
.flag("slasher-max-db-size", Some("16"))
|
||||
.flag("slasher-validator-chunk-size", Some("512"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
let slasher_config = config
|
||||
.slasher
|
||||
@ -878,7 +798,7 @@ fn slasher_broadcast_flag() {
|
||||
.flag("slasher", None)
|
||||
.flag("slasher-broadcast", None)
|
||||
.flag("slasher-max-db-size", Some("16"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
let slasher_config = config
|
||||
.slasher
|
||||
@ -891,7 +811,7 @@ fn slasher_broadcast_flag() {
|
||||
pub fn malloc_tuning_flag() {
|
||||
CommandLineTest::new()
|
||||
.flag("disable-malloc-tuning", None)
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
assert!(!config.http_metrics.allocator_metrics_enabled);
|
||||
});
|
||||
@ -902,7 +822,7 @@ fn ensure_panic_on_failed_launch() {
|
||||
CommandLineTest::new()
|
||||
.flag("slasher", None)
|
||||
.flag("slasher-chunk-size", Some("10"))
|
||||
.run()
|
||||
.run_with_zero_port()
|
||||
.with_config(|config| {
|
||||
let slasher_config = config
|
||||
.slasher
|
||||
|
164
lighthouse/tests/boot_node.rs
Normal file
164
lighthouse/tests/boot_node.rs
Normal file
@ -0,0 +1,164 @@
|
||||
use boot_node::config::BootNodeConfigSerialization;
|
||||
|
||||
use crate::exec::{CommandLineTestExec, CompletedTest};
|
||||
use beacon_node::get_eth2_network_config;
|
||||
use clap::ArgMatches;
|
||||
use lighthouse_network::discovery::ENR_FILENAME;
|
||||
use lighthouse_network::Enr;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::net::{Ipv4Addr, UdpSocket};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use tempfile::TempDir;
|
||||
|
||||
const IP_ADDRESS: &str = "192.168.2.108";
|
||||
|
||||
/// Returns the `lighthouse boot_node` command.
|
||||
fn base_cmd() -> Command {
|
||||
let lighthouse_bin = env!("CARGO_BIN_EXE_lighthouse");
|
||||
let path = lighthouse_bin
|
||||
.parse::<PathBuf>()
|
||||
.expect("should parse CARGO_TARGET_DIR");
|
||||
|
||||
let mut cmd = Command::new(path);
|
||||
cmd.arg("boot_node");
|
||||
cmd
|
||||
}
|
||||
|
||||
struct CommandLineTest {
|
||||
cmd: Command,
|
||||
}
|
||||
|
||||
impl CommandLineTest {
|
||||
fn new() -> CommandLineTest {
|
||||
let base_cmd = base_cmd();
|
||||
CommandLineTest { cmd: base_cmd }
|
||||
}
|
||||
|
||||
fn run_with_ip(&mut self) -> CompletedTest<BootNodeConfigSerialization> {
|
||||
self.cmd.arg(IP_ADDRESS);
|
||||
self.run()
|
||||
}
|
||||
}
|
||||
|
||||
impl CommandLineTestExec for CommandLineTest {
|
||||
type Config = BootNodeConfigSerialization;
|
||||
|
||||
fn cmd_mut(&mut self) -> &mut Command {
|
||||
&mut self.cmd
|
||||
}
|
||||
}
|
||||
|
||||
fn unused_port() -> u16 {
|
||||
let socket =
|
||||
UdpSocket::bind("127.0.0.1:0").expect("should create udp socket to find unused port");
|
||||
let local_addr = socket
|
||||
.local_addr()
|
||||
.expect("should read udp socket to find unused port");
|
||||
local_addr.port()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enr_address_arg() {
|
||||
let mut test = CommandLineTest::new();
|
||||
test.run_with_ip().with_config(|config| {
|
||||
assert_eq!(config.local_enr.ip(), Some(IP_ADDRESS.parse().unwrap()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn port_flag() {
|
||||
let port = unused_port();
|
||||
CommandLineTest::new()
|
||||
.flag("port", Some(port.to_string().as_str()))
|
||||
.run_with_ip()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.listen_socket.port(), port);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn listen_address_flag() {
|
||||
let addr = "127.0.0.2".parse::<Ipv4Addr>().unwrap();
|
||||
CommandLineTest::new()
|
||||
.flag("listen-address", Some("127.0.0.2"))
|
||||
.run_with_ip()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.listen_socket.ip(), addr);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boot_nodes_flag() {
|
||||
// Get hardcoded boot-nodes to verify they end up in the config.
|
||||
// Pass empty `ArgMatches` to `get_eth2_network_config` as we want to
|
||||
// receive the default `Eth2NetworkConfig`.
|
||||
let empty_args = ArgMatches::default();
|
||||
let default_enr = get_eth2_network_config(&empty_args)
|
||||
.unwrap()
|
||||
.boot_enr
|
||||
.unwrap();
|
||||
let default_enr: Vec<String> = default_enr.iter().map(|enr| enr.to_base64()).collect();
|
||||
|
||||
// Nodes passed via `--boot-nodes` are added to the local routing table.
|
||||
let extra_nodes = "enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8,enr:-LK4QFOFWca5ABQzxiCRcy37G7wy1K6zD4qMYBSN5ozzanwze_XVvXVhCk9JvF0cHXOBZrHK1E4vU7Gn-a0bHVczoDU6h2F0dG5ldHOIAAAAAAAAAACEZXRoMpA7CIeVAAAgCf__________gmlkgnY0gmlwhNIy-4iJc2VjcDI1NmsxoQJA3AXQJ6M3NpBWtJS3HPtbXG14t7qHjXuIaL6IOz89T4N0Y3CCIyiDdWRwgiMo";
|
||||
let extra_enr: Vec<&str> = extra_nodes.split(",").collect();
|
||||
|
||||
// Construct vector of enr expected in config.
|
||||
let default_enr_str: Vec<&str> = default_enr.iter().map(|s| s.as_str()).collect();
|
||||
let mut expect_enr = Vec::new();
|
||||
expect_enr.extend_from_slice(&default_enr_str);
|
||||
expect_enr.extend_from_slice(&extra_enr);
|
||||
|
||||
CommandLineTest::new()
|
||||
.flag("boot-nodes", Some(extra_nodes))
|
||||
.run_with_ip()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.boot_nodes.len(), expect_enr.len());
|
||||
for (i, enr) in config.boot_nodes.iter().enumerate() {
|
||||
assert_eq!(
|
||||
enr.to_base64(),
|
||||
expect_enr[i],
|
||||
"ENR missmatch at index [{}]",
|
||||
i
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enr_port_flag() {
|
||||
let port = unused_port();
|
||||
CommandLineTest::new()
|
||||
.flag("enr-port", Some(port.to_string().as_str()))
|
||||
.run_with_ip()
|
||||
.with_config(|config| {
|
||||
assert_eq!(config.local_enr.udp(), Some(port));
|
||||
})
|
||||
}
|
||||
|
||||
// TODO add tests for flags `enable-enr-auto-update` and `disable-packet-filter`.
|
||||
//
|
||||
// These options end up in `Discv5Config`, which doesn't support serde (de)serialization.
|
||||
|
||||
#[test]
|
||||
fn network_dir_flag() {
|
||||
// Save enr to temp dir.
|
||||
let enr = Enr::from_str("enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8").unwrap();
|
||||
let tmp_dir = TempDir::new().unwrap();
|
||||
save_enr_to_disk(tmp_dir.path(), &enr).unwrap();
|
||||
|
||||
CommandLineTest::new()
|
||||
.flag("network-dir", Some(tmp_dir.path().to_str().unwrap()))
|
||||
.run()
|
||||
.with_config(|config| assert_eq!(config.local_enr, enr))
|
||||
}
|
||||
|
||||
fn save_enr_to_disk(dir: &Path, enr: &Enr) -> Result<(), String> {
|
||||
let mut file = File::create(dir.join(Path::new(ENR_FILENAME)))
|
||||
.map_err(|e| format!("Could not create ENR file: {:?}", e))?;
|
||||
file.write_all(enr.to_base64().as_bytes())
|
||||
.map_err(|e| format!("Could not write ENR to file: {:?}", e))
|
||||
}
|
113
lighthouse/tests/exec.rs
Normal file
113
lighthouse/tests/exec.rs
Normal file
@ -0,0 +1,113 @@
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde_json::from_reader;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, Output};
|
||||
use std::str::from_utf8;
|
||||
use tempfile::TempDir;
|
||||
|
||||
pub trait CommandLineTestExec {
|
||||
type Config: DeserializeOwned;
|
||||
|
||||
fn cmd_mut(&mut self) -> &mut Command;
|
||||
|
||||
/// Adds a flag with optional value to the command.
|
||||
fn flag(&mut self, flag: &str, value: Option<&str>) -> &mut Self {
|
||||
self.cmd_mut().arg(format!("--{}", flag));
|
||||
if let Some(value) = value {
|
||||
self.cmd_mut().arg(value);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Executes the `Command` returned by `Self::cmd_mut` with temporary data directory, dumps
|
||||
/// the configuration and shuts down immediately.
|
||||
///
|
||||
/// Options `--datadir`, `--dump-config` and `--immediate-shutdown` must not be set on the
|
||||
/// command.
|
||||
fn run(&mut self) -> CompletedTest<Self::Config> {
|
||||
// Setup temp directory.
|
||||
let tmp_dir = TempDir::new().expect("Unable to create temporary directory");
|
||||
let tmp_config_path: PathBuf = tmp_dir.path().join("config.json");
|
||||
|
||||
// Add args --datadir <tmp_dir> --dump-config <tmp_config_path> --immediate-shutdown
|
||||
let cmd = self.cmd_mut();
|
||||
cmd.arg("--datadir")
|
||||
.arg(tmp_dir.path().as_os_str())
|
||||
.arg(format!("--{}", "--dump-config"))
|
||||
.arg(tmp_config_path.as_os_str())
|
||||
.arg("--immediate-shutdown");
|
||||
|
||||
// Run the command.
|
||||
let output = output_result(cmd);
|
||||
if let Err(e) = output {
|
||||
panic!("{:?}", e);
|
||||
}
|
||||
|
||||
// Grab the config.
|
||||
let config_file = File::open(tmp_config_path).expect("Unable to open dumped config");
|
||||
let config: Self::Config = from_reader(config_file).expect("Unable to deserialize config");
|
||||
|
||||
CompletedTest::new(config, tmp_dir)
|
||||
}
|
||||
|
||||
/// Executes the `Command` returned by `Self::cmd_mut` dumps the configuration and
|
||||
/// shuts down immediately.
|
||||
///
|
||||
/// Options `--dump-config` and `--immediate-shutdown` must not be set on the command.
|
||||
fn run_with_no_datadir(&mut self) -> CompletedTest<Self::Config> {
|
||||
// Setup temp directory.
|
||||
let tmp_dir = TempDir::new().expect("Unable to create temporary directory");
|
||||
let tmp_config_path: PathBuf = tmp_dir.path().join("config.json");
|
||||
|
||||
// Add args --datadir <tmp_dir> --dump-config <tmp_config_path> --immediate-shutdown
|
||||
let cmd = self.cmd_mut();
|
||||
cmd.arg(format!("--{}", "--dump-config"))
|
||||
.arg(tmp_config_path.as_os_str())
|
||||
.arg("--immediate-shutdown");
|
||||
|
||||
// Run the command.
|
||||
let output = output_result(cmd);
|
||||
if let Err(e) = output {
|
||||
panic!("{:?}", e);
|
||||
}
|
||||
|
||||
// Grab the config.
|
||||
let config_file = File::open(tmp_config_path).expect("Unable to open dumped config");
|
||||
let config: Self::Config = from_reader(config_file).expect("Unable to deserialize config");
|
||||
|
||||
CompletedTest::new(config, tmp_dir)
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes a `Command`, returning a `Result` based upon the success exit code of the command.
|
||||
fn output_result(cmd: &mut Command) -> Result<Output, String> {
|
||||
let output = cmd.output().expect("should run command");
|
||||
|
||||
if output.status.success() {
|
||||
Ok(output)
|
||||
} else {
|
||||
Err(from_utf8(&output.stderr)
|
||||
.expect("stderr is not utf8")
|
||||
.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CompletedTest<C> {
|
||||
config: C,
|
||||
dir: TempDir,
|
||||
}
|
||||
|
||||
impl<C> CompletedTest<C> {
|
||||
fn new(config: C, dir: TempDir) -> Self {
|
||||
CompletedTest { config, dir }
|
||||
}
|
||||
|
||||
pub fn with_config<F: Fn(&C)>(self, func: F) {
|
||||
func(&self.config);
|
||||
}
|
||||
|
||||
pub fn with_config_and_dir<F: Fn(&C, &TempDir)>(self, func: F) {
|
||||
func(&self.config, &self.dir);
|
||||
}
|
||||
}
|
@ -2,4 +2,6 @@
|
||||
|
||||
mod account_manager;
|
||||
mod beacon_node;
|
||||
mod boot_node;
|
||||
mod exec;
|
||||
mod validator_client;
|
||||
|
@ -1,22 +1,16 @@
|
||||
use validator_client::Config;
|
||||
|
||||
use crate::exec::CommandLineTestExec;
|
||||
use bls::{Keypair, PublicKeyBytes};
|
||||
use serde_json::from_reader;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, Output};
|
||||
use std::str::from_utf8;
|
||||
use std::process::Command;
|
||||
use std::string::ToString;
|
||||
use tempfile::TempDir;
|
||||
|
||||
const VALIDATOR_CMD: &str = "validator_client";
|
||||
const CONFIG_NAME: &str = "vc_dump.json";
|
||||
const DUMP_CONFIG_CMD: &str = "dump-config";
|
||||
const IMMEDIATE_SHUTDOWN_CMD: &str = "immediate-shutdown";
|
||||
|
||||
/// Returns the `lighthouse validator_client --immediate-shutdown` command.
|
||||
/// Returns the `lighthouse validator_client` command.
|
||||
fn base_cmd() -> Command {
|
||||
let lighthouse_bin = env!("CARGO_BIN_EXE_lighthouse");
|
||||
let path = lighthouse_bin
|
||||
@ -24,25 +18,10 @@ fn base_cmd() -> Command {
|
||||
.expect("should parse CARGO_TARGET_DIR");
|
||||
|
||||
let mut cmd = Command::new(path);
|
||||
cmd.arg(VALIDATOR_CMD)
|
||||
.arg(format!("--{}", IMMEDIATE_SHUTDOWN_CMD));
|
||||
|
||||
cmd.arg("validator_client");
|
||||
cmd
|
||||
}
|
||||
|
||||
/// Executes a `Command`, returning a `Result` based upon the success exit code of the command.
|
||||
fn output_result(cmd: &mut Command) -> Result<Output, String> {
|
||||
let output = cmd.output().expect("should run command");
|
||||
|
||||
if output.status.success() {
|
||||
Ok(output)
|
||||
} else {
|
||||
Err(from_utf8(&output.stderr)
|
||||
.expect("stderr is not utf8")
|
||||
.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper around `Command` for easier Command Line Testing.
|
||||
struct CommandLineTest {
|
||||
cmd: Command,
|
||||
@ -52,76 +31,13 @@ impl CommandLineTest {
|
||||
let base_cmd = base_cmd();
|
||||
CommandLineTest { cmd: base_cmd }
|
||||
}
|
||||
|
||||
fn flag(mut self, flag: &str, value: Option<&str>) -> Self {
|
||||
// Build the command by adding the flag and any values.
|
||||
self.cmd.arg(format!("--{}", flag));
|
||||
if let Some(value) = value {
|
||||
self.cmd.arg(value);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn run(&mut self) -> CompletedTest {
|
||||
// Setup temp directories.
|
||||
let tmp_dir = TempDir::new().expect("Unable to create temporary directory");
|
||||
let tmp_path: PathBuf = tmp_dir.path().join(CONFIG_NAME);
|
||||
|
||||
// Add --datadir <temp_dir> --dump-config <temp_path> to cmd.
|
||||
self.cmd
|
||||
.arg("--datadir")
|
||||
.arg(tmp_dir.path().as_os_str())
|
||||
.arg(format!("--{}", DUMP_CONFIG_CMD))
|
||||
.arg(tmp_path.as_os_str());
|
||||
|
||||
// Run the command.
|
||||
let _output = output_result(&mut self.cmd).expect("Unable to run command");
|
||||
|
||||
// Grab the config.
|
||||
let config: Config =
|
||||
from_reader(File::open(tmp_path).expect("Unable to open dumped config"))
|
||||
.expect("Unable to deserialize to ClientConfig");
|
||||
CompletedTest {
|
||||
config,
|
||||
dir: tmp_dir,
|
||||
}
|
||||
}
|
||||
|
||||
// In order to test custom validator and secrets directory flags,
|
||||
// datadir cannot be defined.
|
||||
fn run_with_no_datadir(&mut self) -> CompletedTest {
|
||||
// Setup temp directories
|
||||
let tmp_dir = TempDir::new().expect("Unable to create temporary directory");
|
||||
let tmp_path: PathBuf = tmp_dir.path().join(CONFIG_NAME);
|
||||
|
||||
// Add --dump-config <temp_path> to cmd.
|
||||
self.cmd
|
||||
.arg(format!("--{}", DUMP_CONFIG_CMD))
|
||||
.arg(tmp_path.as_os_str());
|
||||
|
||||
// Run the command.
|
||||
let _output = output_result(&mut self.cmd).expect("Unable to run command");
|
||||
|
||||
// Grab the config.
|
||||
let config: Config =
|
||||
from_reader(File::open(tmp_path).expect("Unable to open dumped config"))
|
||||
.expect("Unable to deserialize to ClientConfig");
|
||||
CompletedTest {
|
||||
config,
|
||||
dir: tmp_dir,
|
||||
}
|
||||
}
|
||||
}
|
||||
struct CompletedTest {
|
||||
config: Config,
|
||||
dir: TempDir,
|
||||
}
|
||||
impl CompletedTest {
|
||||
fn with_config<F: Fn(&Config)>(self, func: F) {
|
||||
func(&self.config);
|
||||
}
|
||||
fn with_config_and_dir<F: Fn(&Config, &TempDir)>(self, func: F) {
|
||||
func(&self.config, &self.dir);
|
||||
|
||||
impl CommandLineTestExec for CommandLineTest {
|
||||
type Config = Config;
|
||||
|
||||
fn cmd_mut(&mut self) -> &mut Command {
|
||||
&mut self.cmd
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user