zebra/zebrad/tests/common/lightwalletd.rs

390 lines
13 KiB
Rust
Raw Normal View History

//! `lightwalletd`-specific shared code for the `zebrad` acceptance tests.
//!
//! # Warning
//!
//! Test functions in this file will not be run.
//! This file is only for test library code.
use std::{
env,
net::SocketAddr,
path::{Path, PathBuf},
time::Duration,
};
use zebra_test::{
command::{Arguments, TestChild, TestDirExt, NO_MATCHES_REGEX_ITER},
net::random_known_port,
prelude::*,
};
use zebrad::config::ZebradConfig;
use super::{
cached_state::ZEBRA_CACHED_STATE_DIR_VAR,
config::default_test_config,
failure_messages::{
LIGHTWALLETD_EMPTY_ZEBRA_STATE_IGNORE_MESSAGES, LIGHTWALLETD_FAILURE_MESSAGES,
PROCESS_FAILURE_MESSAGES, ZEBRA_FAILURE_MESSAGES,
},
launch::{
ZebradTestDirExt, LIGHTWALLETD_DELAY, LIGHTWALLETD_FULL_SYNC_TIP_DELAY,
LIGHTWALLETD_UPDATE_TIP_DELAY,
},
};
use LightwalletdTestType::*;
add(test): Integration test to send transactions using lightwalletd (#4068) * Export the `zebra_state::Config::db_path` method Make it easier for tests to discover the sub-directory used to store the chain state data. * Generate code for interfacing with lightwalletd Use the `tonic-build` crate to generate Rust code for communicating with lightwalletd using gRPC. The `*.proto` files were obtained from the Zcash lightwalletd repository. * Use `block::Height` instead of `Height` Import the `block` instead to make it slightly clearer. * Add helper function to remove a file if it exists Try to remove it and ignore an error if it says that the file doesn't exist. This will be used later to remove the lock file from a copied chain state directory. * Add helper function to copy chain state dirs Copy an existing chain state directory into a new temporary directory. * Add a `BoxStateService` type alias Make it easier to write and read a boxed version of a state service. * Add a helper function to start the state service Make it easier to specify the state service to use an existing state cache directory. * Import `eyre!` macro at the module level Allow it to be used in different places without having to repeat the imports. * Add `load_tip_height_from_state_directory` helper A function to discover the current chain tip height stored in a state cache. * Add helper function to prepare partial sync. state Loads a partially synchronized cached state directory into a temporary directory that can be used by a zebrad instance, and also returns the chain tip block height of that state. * Add `perform_full_sync_starting_from` helper Runs a zebrad with an existing partially synchronized state, and finishes synchronizing it to the network chain tip. * Add function to load transactions from a block Use a provided state service to load all transactions from a block at a specified height. The state service is a generic type parameter, because `zebra_state::service::ReadStateService` is not exported publicly. Using a generic type parameter also allows the service to be wrapped in layers if needed in the future. * Add `load_transactions_from_block_after` helper A function to load transactions from a block stored in a cached state directory. The cached state must be synchronized to a chain tip higher than the requested height. * Add helper function to load some test transactions Given a partially synchronized chain state, it will extend that chain by performing a full synchronization, and obtain some transactions from one of the newly added blocks. * Update `spawn_zebrad_for_rpc_without_initial_peers` Wait until the mempool is activated. * Add method to start lightwalletd with RPC server Returns the lightwalletd instance and the port that it's listening for RPC connections. The instance can reuse an existing cached lightwalletd state if the `LIGHTWALLETD_DATA_DIR` environment variable is set. * Add a `LightwalletdRpcClient` type alias To make it easier to identify the type generated from the Protobuf files. * Add helper function to connect to lightwalletd Prepare an RPC client to send requests to a lightwalletd instance. * Add a `prepare_send_transaction_request` helper Creates a request message for lightwalletd to send a transaction. * Add test to send transactions using lightwalletd Obtain some valid transactions from future blocks and try to send them to a lightwalletd instance connected to a zebrad instance that hasn't seen those transactions yet. The transactions should be successfully queued in Zebra's mempool. * Make `zebra_directory` parameter generic Allow using a `TempDir` or a `PathBuf`. * Move lightwalletd protobuf files Place them closer to the module directory, so that it's clearer that they specify the RPC protocol for lightwalletd, and not Zebra itself. * Don't use coinbase transactions in the test Coinbase transactions are rejected by the mempool. * Don't remove state lock file It is removed automatically by Zebra when it shuts down, so if it exists it should be reported as a bug. * Force mempool to be enabled in Zebrad instance Speed up the initialization of the Zebrad instance used for lightwalletd to connect to. * Refactor to create `LIGHTWALLETD_DATA_DIR_VAR` Document how the environment variable can be used to speed up the test. * Check for process errors in spawned Zebra instance Enable checking for known process failure messages. * Add `FINISH_PARTIAL_SYNC_TIMEOUT` constant Document why it exists and how the choice of the value affects the test. * Add `LIGHTWALLETD_TEST_TIMEOUT` constant And use it for the Zebrad and the Lightwalletd instances used in the send transaction integration test. * Check `lightwalletd` process for errors Enable checking the lightwalletd process for known failure messages. * Update `tonic` and `prost` dependencies Use the latest version and fix CI failures because `rustfmt` isn't installed in the build environment. * Create `send_transaction_test` module Move the send transaction using lightwalletd test and its helper functions into a new module. * Move `LIGHTWALLETD_TEST_TIMEOUT` constant Place it in the parent `lightwalletd` module. * Move gRPC helper functions and types to `rpc` mod. Make them more accessible so that they can be used by other tests. * Create a `cached_state` module Move the test utility functions related to using a cached Zebra state into the module. * Move `perform_full_sync_starting_from` to `sync` Keep to closer to the synchronization utility functions. * Move Zebra cached state path variable constant Place it in the `cached_state` module. * Skip test if `ZEBRA_TEST_LIGHTWALLETD` is not set Make it part of the set of tests ignored as a whole if no lightwalletd tests should be executed. * Move `spawn_zebrad_for_rpc_without_initial_peers` Place it in the `launch` sub-module. * Rename `rpc` module into `wallet_grpc` Avoid any potential misunderstandings when the name is seen out of context. * Allow duplicate `heck` dependency At least until `structopt` is updated or `zebra-utils` is updated to use `clap` 3. * Fix a deny.toml typo * fix(build): CMake is required by `prost` crate Co-authored-by: teor <teor@riseup.net> Co-authored-by: Gustavo Valverde <gustavo@iterativo.do>
2022-04-27 16:06:11 -07:00
pub mod send_transaction_test;
pub mod wallet_grpc;
/// The name of the env var that enables Zebra lightwalletd integration tests.
/// These tests need a `lightwalletd` binary in the test machine's path.
///
/// We use a constant so that the compiler detects typos.
///
/// # Note
///
/// This environmental variable is used to enable the lightwalletd tests.
/// But the network tests are *disabled* by their environmental variables.
pub const ZEBRA_TEST_LIGHTWALLETD: &str = "ZEBRA_TEST_LIGHTWALLETD";
/// Optional environment variable with the cached state for lightwalletd.
///
/// Required for [`LightwalletdTestType::UpdateCachedState`],
/// so we can test lightwalletd RPC integration with a populated state.
///
/// Can also be used to speed up the [`sending_transactions_using_lightwalletd`] test,
/// by skipping the lightwalletd initial sync.
pub const LIGHTWALLETD_DATA_DIR_VAR: &str = "LIGHTWALLETD_DATA_DIR";
add(test): Integration test to send transactions using lightwalletd (#4068) * Export the `zebra_state::Config::db_path` method Make it easier for tests to discover the sub-directory used to store the chain state data. * Generate code for interfacing with lightwalletd Use the `tonic-build` crate to generate Rust code for communicating with lightwalletd using gRPC. The `*.proto` files were obtained from the Zcash lightwalletd repository. * Use `block::Height` instead of `Height` Import the `block` instead to make it slightly clearer. * Add helper function to remove a file if it exists Try to remove it and ignore an error if it says that the file doesn't exist. This will be used later to remove the lock file from a copied chain state directory. * Add helper function to copy chain state dirs Copy an existing chain state directory into a new temporary directory. * Add a `BoxStateService` type alias Make it easier to write and read a boxed version of a state service. * Add a helper function to start the state service Make it easier to specify the state service to use an existing state cache directory. * Import `eyre!` macro at the module level Allow it to be used in different places without having to repeat the imports. * Add `load_tip_height_from_state_directory` helper A function to discover the current chain tip height stored in a state cache. * Add helper function to prepare partial sync. state Loads a partially synchronized cached state directory into a temporary directory that can be used by a zebrad instance, and also returns the chain tip block height of that state. * Add `perform_full_sync_starting_from` helper Runs a zebrad with an existing partially synchronized state, and finishes synchronizing it to the network chain tip. * Add function to load transactions from a block Use a provided state service to load all transactions from a block at a specified height. The state service is a generic type parameter, because `zebra_state::service::ReadStateService` is not exported publicly. Using a generic type parameter also allows the service to be wrapped in layers if needed in the future. * Add `load_transactions_from_block_after` helper A function to load transactions from a block stored in a cached state directory. The cached state must be synchronized to a chain tip higher than the requested height. * Add helper function to load some test transactions Given a partially synchronized chain state, it will extend that chain by performing a full synchronization, and obtain some transactions from one of the newly added blocks. * Update `spawn_zebrad_for_rpc_without_initial_peers` Wait until the mempool is activated. * Add method to start lightwalletd with RPC server Returns the lightwalletd instance and the port that it's listening for RPC connections. The instance can reuse an existing cached lightwalletd state if the `LIGHTWALLETD_DATA_DIR` environment variable is set. * Add a `LightwalletdRpcClient` type alias To make it easier to identify the type generated from the Protobuf files. * Add helper function to connect to lightwalletd Prepare an RPC client to send requests to a lightwalletd instance. * Add a `prepare_send_transaction_request` helper Creates a request message for lightwalletd to send a transaction. * Add test to send transactions using lightwalletd Obtain some valid transactions from future blocks and try to send them to a lightwalletd instance connected to a zebrad instance that hasn't seen those transactions yet. The transactions should be successfully queued in Zebra's mempool. * Make `zebra_directory` parameter generic Allow using a `TempDir` or a `PathBuf`. * Move lightwalletd protobuf files Place them closer to the module directory, so that it's clearer that they specify the RPC protocol for lightwalletd, and not Zebra itself. * Don't use coinbase transactions in the test Coinbase transactions are rejected by the mempool. * Don't remove state lock file It is removed automatically by Zebra when it shuts down, so if it exists it should be reported as a bug. * Force mempool to be enabled in Zebrad instance Speed up the initialization of the Zebrad instance used for lightwalletd to connect to. * Refactor to create `LIGHTWALLETD_DATA_DIR_VAR` Document how the environment variable can be used to speed up the test. * Check for process errors in spawned Zebra instance Enable checking for known process failure messages. * Add `FINISH_PARTIAL_SYNC_TIMEOUT` constant Document why it exists and how the choice of the value affects the test. * Add `LIGHTWALLETD_TEST_TIMEOUT` constant And use it for the Zebrad and the Lightwalletd instances used in the send transaction integration test. * Check `lightwalletd` process for errors Enable checking the lightwalletd process for known failure messages. * Update `tonic` and `prost` dependencies Use the latest version and fix CI failures because `rustfmt` isn't installed in the build environment. * Create `send_transaction_test` module Move the send transaction using lightwalletd test and its helper functions into a new module. * Move `LIGHTWALLETD_TEST_TIMEOUT` constant Place it in the parent `lightwalletd` module. * Move gRPC helper functions and types to `rpc` mod. Make them more accessible so that they can be used by other tests. * Create a `cached_state` module Move the test utility functions related to using a cached Zebra state into the module. * Move `perform_full_sync_starting_from` to `sync` Keep to closer to the synchronization utility functions. * Move Zebra cached state path variable constant Place it in the `cached_state` module. * Skip test if `ZEBRA_TEST_LIGHTWALLETD` is not set Make it part of the set of tests ignored as a whole if no lightwalletd tests should be executed. * Move `spawn_zebrad_for_rpc_without_initial_peers` Place it in the `launch` sub-module. * Rename `rpc` module into `wallet_grpc` Avoid any potential misunderstandings when the name is seen out of context. * Allow duplicate `heck` dependency At least until `structopt` is updated or `zebra-utils` is updated to use `clap` 3. * Fix a deny.toml typo * fix(build): CMake is required by `prost` crate Co-authored-by: teor <teor@riseup.net> Co-authored-by: Gustavo Valverde <gustavo@iterativo.do>
2022-04-27 16:06:11 -07:00
/// The maximum time that a `lightwalletd` integration test is expected to run.
pub const LIGHTWALLETD_TEST_TIMEOUT: Duration = Duration::from_secs(60 * 60);
/// Should we skip Zebra lightwalletd integration tests?
#[allow(clippy::print_stderr)]
pub fn zebra_skip_lightwalletd_tests() -> bool {
// TODO: check if the lightwalletd binary is in the PATH?
// (this doesn't seem to be implemented in the standard library)
//
// See is_command_available in zebra-test/tests/command.rs for one way to do this.
if env::var_os(ZEBRA_TEST_LIGHTWALLETD).is_none() {
// This message is captured by the test runner, use
// `cargo test -- --nocapture` to see it.
eprintln!(
"Skipped lightwalletd integration test, \
set the 'ZEBRA_TEST_LIGHTWALLETD' environmental variable to run the test",
);
return true;
}
false
}
/// Returns a `zebrad` config with a random known RPC port.
pub fn random_known_rpc_port_config() -> Result<ZebradConfig> {
// [Note on port conflict](#Note on port conflict)
let listen_port = random_known_port();
let listen_ip = "127.0.0.1".parse().expect("hard-coded IP is valid");
let zebra_rpc_listener = SocketAddr::new(listen_ip, listen_port);
// Write a configuration that has the rpc listen_addr option set
// TODO: split this config into another function?
let mut config = default_test_config()?;
config.rpc.listen_addr = Some(zebra_rpc_listener);
Ok(config)
}
/// Extension trait for methods on `tempfile::TempDir` for using it as a test
/// directory for `zebrad`.
pub trait LightWalletdTestDirExt: ZebradTestDirExt
where
Self: AsRef<Path> + Sized,
{
/// Spawn `lightwalletd` with `lightwalletd_state_path`, and `extra_args`,
/// as a child process in this test directory,
/// potentially taking ownership of the tempdir for the duration of the child process.
///
/// By default, launch a working test instance with logging, and avoid port conflicts.
///
/// # Panics
///
/// If there is no lightwalletd config in the test directory.
fn spawn_lightwalletd_child(
self,
lightwalletd_state_path: impl Into<Option<PathBuf>>,
extra_args: Arguments,
) -> Result<TestChild<Self>>;
/// Create a config file and use it for all subsequently spawned `lightwalletd` processes.
/// Returns an error if the config already exists.
///
/// If needed:
/// - recursively create directories for the config
fn with_lightwalletd_config(self, zebra_rpc_listener: SocketAddr) -> Result<Self>;
}
impl<T> LightWalletdTestDirExt for T
where
Self: TestDirExt + AsRef<Path> + Sized,
{
fn spawn_lightwalletd_child(
self,
lightwalletd_state_path: impl Into<Option<PathBuf>>,
extra_args: Arguments,
) -> Result<TestChild<Self>> {
let test_dir = self.as_ref().to_owned();
let default_config_path = test_dir.join("lightwalletd-zcash.conf");
assert!(
default_config_path.exists(),
"lightwalletd requires a config"
);
// By default, launch a working test instance with logging,
// and avoid port conflicts.
change(test): Refactor how extra arguments are handled when spawing lightwalled (#4067) * Join similar imports Avoid the confusion that might cause one to think that they come from different modules or crates. * Create an `Arguments` helper type A type to keep track of a list of arguments for a sub-process. It makes it easier for overriding parameters with new values. * Create an `args!` helper macro Make it simpler to create `Arguments` instances with known values. * Require `Arguments` for `spawn_child` method Change the method to have an `Arguments` parameter, and merge it with some default values before passing them forward. * Use `Arguments` in `spawn_lightwalletd_child` Change the method to use an `Arguments` instance, and merge it with some default options. * Use `Arguments` in `spawn_child_with_command` Require an `Arguments` instance in the `spawn_child_with_command` extension method. Makes it simpler to call from `spawn_child` and `spawn_lightwalletd_child` extension methods. * Test if argument order is preserved Check that when building an `Arguments` instance, the order that the arguments are set is preserved in the generated list of strings. * Refactor test to improve readability Also separates some common code to be reused by later tests. * Test overriding arguments Check to see if overriding arguments behaves as expected, by keeping the argument order when overriding and not introducing duplicates. * Refactor test to improve readability Move out a chunk of code so that the test itself is easier to read and to make that code reusable by a later test. * Test that `Arguments` instances can be merged Merge two `Arguments` instances built from two lists of arguments, and check that the expanded strings preserve order and override rules. * Add Eq derives on Arguments Co-authored-by: teor <teor@riseup.net>
2022-04-19 03:28:52 -07:00
let mut args = Arguments::new();
// the fake zcashd conf we just wrote
let zcash_conf_path = default_config_path
.as_path()
.to_str()
.expect("Path is valid Unicode");
args.set_parameter("--zcash-conf-path", zcash_conf_path);
// the lightwalletd cache directory
if let Some(lightwalletd_state_path) = lightwalletd_state_path.into() {
args.set_parameter(
"--data-dir",
lightwalletd_state_path
.to_str()
.expect("path is valid Unicode"),
);
} else {
let empty_state_path = test_dir.join("lightwalletd_state");
std::fs::create_dir(&empty_state_path)
.expect("unexpected failure creating lightwalletd state sub-directory");
args.set_parameter(
"--data-dir",
empty_state_path.to_str().expect("path is valid Unicode"),
);
}
change(test): Refactor how extra arguments are handled when spawing lightwalled (#4067) * Join similar imports Avoid the confusion that might cause one to think that they come from different modules or crates. * Create an `Arguments` helper type A type to keep track of a list of arguments for a sub-process. It makes it easier for overriding parameters with new values. * Create an `args!` helper macro Make it simpler to create `Arguments` instances with known values. * Require `Arguments` for `spawn_child` method Change the method to have an `Arguments` parameter, and merge it with some default values before passing them forward. * Use `Arguments` in `spawn_lightwalletd_child` Change the method to use an `Arguments` instance, and merge it with some default options. * Use `Arguments` in `spawn_child_with_command` Require an `Arguments` instance in the `spawn_child_with_command` extension method. Makes it simpler to call from `spawn_child` and `spawn_lightwalletd_child` extension methods. * Test if argument order is preserved Check that when building an `Arguments` instance, the order that the arguments are set is preserved in the generated list of strings. * Refactor test to improve readability Also separates some common code to be reused by later tests. * Test overriding arguments Check to see if overriding arguments behaves as expected, by keeping the argument order when overriding and not introducing duplicates. * Refactor test to improve readability Move out a chunk of code so that the test itself is easier to read and to make that code reusable by a later test. * Test that `Arguments` instances can be merged Merge two `Arguments` instances built from two lists of arguments, and check that the expanded strings preserve order and override rules. * Add Eq derives on Arguments Co-authored-by: teor <teor@riseup.net>
2022-04-19 03:28:52 -07:00
// log to standard output
//
// TODO: if lightwalletd needs to run on Windows,
// work out how to log to the terminal on all platforms
args.set_parameter("--log-file", "/dev/stdout");
// let the OS choose a random available wallet client port
args.set_parameter("--grpc-bind-addr", "127.0.0.1:0");
args.set_parameter("--http-bind-addr", "127.0.0.1:0");
// don't require a TLS certificate for the HTTP server
args.set_argument("--no-tls-very-insecure");
// apply user provided arguments
args.merge_with(extra_args);
self.spawn_child_with_command("lightwalletd", args)
}
fn with_lightwalletd_config(self, zebra_rpc_listener: SocketAddr) -> Result<Self> {
use std::fs;
let lightwalletd_config = format!(
"\
rpcbind={}\n\
rpcport={}\n\
",
zebra_rpc_listener.ip(),
zebra_rpc_listener.port(),
);
let dir = self.as_ref();
fs::create_dir_all(dir)?;
let config_file = dir.join("lightwalletd-zcash.conf");
fs::write(config_file, lightwalletd_config.as_bytes())?;
Ok(self)
}
}
/// The type of lightwalletd integration test that we're running.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LightwalletdTestType {
/// Launch with an empty Zebra and lightwalletd state.
LaunchWithEmptyState,
/// Do a full sync from an empty lightwalletd state.
///
/// This test requires a cached Zebra state.
FullSyncFromGenesis {
/// Should the test allow a cached lightwalletd state?
///
/// If `false`, the test fails if the lightwalletd state is populated.
allow_lightwalletd_cached_state: bool,
},
/// Sync to tip from a lightwalletd cached state.
///
/// This test requires a cached Zebra and lightwalletd state.
UpdateCachedState,
}
impl LightwalletdTestType {
/// Does this test need a Zebra cached state?
pub fn needs_zebra_cached_state(&self) -> bool {
match self {
LaunchWithEmptyState => false,
FullSyncFromGenesis { .. } | UpdateCachedState => true,
}
}
/// Does this test need a lightwalletd cached state?
pub fn needs_lightwalletd_cached_state(&self) -> bool {
match self {
LaunchWithEmptyState | FullSyncFromGenesis { .. } => false,
UpdateCachedState => true,
}
}
/// Does this test allow a lightwalletd cached state, even if it is not required?
pub fn allow_lightwalletd_cached_state(&self) -> bool {
match self {
LaunchWithEmptyState => false,
FullSyncFromGenesis {
allow_lightwalletd_cached_state,
} => *allow_lightwalletd_cached_state,
UpdateCachedState => true,
}
}
/// Returns the Zebra state path for this test, if set.
pub fn zebrad_state_path(&self) -> Option<PathBuf> {
match env::var_os(ZEBRA_CACHED_STATE_DIR_VAR) {
Some(path) => Some(path.into()),
None => {
tracing::info!(
"skipped {self:?} lightwalletd test, \
set the {ZEBRA_CACHED_STATE_DIR_VAR:?} environment variable to run the test",
);
None
}
}
}
/// Returns a Zebra config for this test.
///
/// Returns `None` if the test should be skipped,
/// and `Some(Err(_))` if the config could not be created.
pub fn zebrad_config(&self) -> Option<Result<ZebradConfig>> {
if !self.needs_zebra_cached_state() {
return Some(random_known_rpc_port_config());
}
let zebra_state_path = self.zebrad_state_path()?;
let mut config = match random_known_rpc_port_config() {
Ok(config) => config,
Err(error) => return Some(Err(error)),
};
config.sync.lookahead_limit = zebrad::components::sync::DEFAULT_LOOKAHEAD_LIMIT;
config.state.ephemeral = false;
config.state.cache_dir = zebra_state_path;
Some(Ok(config))
}
/// Returns the lightwalletd state path for this test, if set.
pub fn lightwalletd_state_path(&self) -> Option<PathBuf> {
env::var_os(LIGHTWALLETD_DATA_DIR_VAR).map(Into::into)
}
/// Returns the `zebrad` timeout for this test type.
pub fn zebrad_timeout(&self) -> Duration {
match self {
LaunchWithEmptyState => LIGHTWALLETD_DELAY,
FullSyncFromGenesis { .. } | UpdateCachedState => LIGHTWALLETD_UPDATE_TIP_DELAY,
}
}
/// Returns the `lightwalletd` timeout for this test type.
pub fn lightwalletd_timeout(&self) -> Duration {
match self {
LaunchWithEmptyState => LIGHTWALLETD_DELAY,
UpdateCachedState => LIGHTWALLETD_UPDATE_TIP_DELAY,
FullSyncFromGenesis { .. } => LIGHTWALLETD_FULL_SYNC_TIP_DELAY,
}
}
/// Returns Zebra log regexes that indicate the tests have failed,
/// and regexes of any failures that should be ignored.
pub fn zebrad_failure_messages(&self) -> (Vec<String>, Vec<String>) {
let mut zebrad_failure_messages: Vec<String> = ZEBRA_FAILURE_MESSAGES
.iter()
.chain(PROCESS_FAILURE_MESSAGES)
.map(ToString::to_string)
.collect();
if self.needs_zebra_cached_state() {
// Fail if we need a cached Zebra state, but it's empty
zebrad_failure_messages.push("loaded Zebra state cache tip=None".to_string());
}
if *self == LaunchWithEmptyState {
// Fail if we need an empty Zebra state, but it has blocks
zebrad_failure_messages
.push(r"loaded Zebra state cache tip=.*Height\([1-9][0-9]*\)".to_string());
}
let zebrad_ignore_messages = Vec::new();
(zebrad_failure_messages, zebrad_ignore_messages)
}
/// Returns `lightwalletd` log regexes that indicate the tests have failed,
/// and regexes of any failures that should be ignored.
pub fn lightwalletd_failure_messages(&self) -> (Vec<String>, Vec<String>) {
let mut lightwalletd_failure_messages: Vec<String> = LIGHTWALLETD_FAILURE_MESSAGES
.iter()
.chain(PROCESS_FAILURE_MESSAGES)
.map(ToString::to_string)
.collect();
// Zebra state failures
if self.needs_zebra_cached_state() {
// Fail if we need a cached Zebra state, but it's empty
lightwalletd_failure_messages.push("No Chain tip available yet".to_string());
}
// lightwalletd state failures
if self.needs_lightwalletd_cached_state() {
// Fail if we need a cached lightwalletd state, but it isn't near the tip
//
// TODO: fail on `[0-9]{1,6}` when we're using the tip cached state (#4155)
lightwalletd_failure_messages.push("Found [0-9]{1,5} blocks in cache".to_string());
}
if !self.allow_lightwalletd_cached_state() {
// Fail if we need an empty lightwalletd state, but it has blocks
lightwalletd_failure_messages.push("Found [1-9][0-9]* blocks in cache".to_string());
}
let lightwalletd_ignore_messages = if *self == LaunchWithEmptyState {
LIGHTWALLETD_EMPTY_ZEBRA_STATE_IGNORE_MESSAGES.iter()
} else {
NO_MATCHES_REGEX_ITER.iter()
}
.map(ToString::to_string)
.collect();
(lightwalletd_failure_messages, lightwalletd_ignore_messages)
}
}