zebra/zebrad/tests/common/lightwalletd.rs

273 lines
9.4 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},
};
use tempfile::TempDir;
use zebra_chain::parameters::Network::{self, *};
use zebra_test::{
args,
command::{Arguments, TestDirExt},
net::random_known_port,
prelude::*,
};
use super::{config::testdir, launch::ZebradTestDirExt, test_type::TestType};
#[cfg(feature = "lightwalletd-grpc-tests")]
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;
#[cfg(feature = "lightwalletd-grpc-tests")]
pub mod sync;
#[cfg(feature = "lightwalletd-grpc-tests")]
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 wallet_grpc;
#[cfg(feature = "lightwalletd-grpc-tests")]
pub mod wallet_grpc_test;
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 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 [`TestType::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: &str = "LIGHTWALLETD_DATA_DIR";
/// 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/src/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
}
/// Spawns a lightwalletd instance on `network`, connected to `zebrad_rpc_address`,
/// with its gRPC server functionality enabled.
///
/// Expects cached state based on the `test_type`. Use the `LIGHTWALLETD_DATA_DIR`
/// environmental variable to provide an initial state to the lightwalletd instance.
///
/// Returns:
/// - `Ok(Some(lightwalletd, lightwalletd_rpc_port))` on success,
/// - `Ok(None)` if the test doesn't have the required network or cached state, and
/// - `Err(_)` if spawning lightwalletd fails.
#[tracing::instrument]
pub fn spawn_lightwalletd_for_rpc<S: AsRef<str> + std::fmt::Debug>(
network: Network,
test_name: S,
test_type: TestType,
zebrad_rpc_address: SocketAddr,
) -> Result<Option<(TestChild<TempDir>, u16)>> {
assert_eq!(network, Mainnet, "this test only supports Mainnet for now");
let test_name = test_name.as_ref();
// Skip the test unless the user specifically asked for it
if !can_spawn_lightwalletd_for_rpc(test_name, test_type) {
return Ok(None);
}
let lightwalletd_state_path = test_type.lightwalletd_state_path(test_name);
let lightwalletd_dir = testdir()?.with_lightwalletd_config(zebrad_rpc_address)?;
let lightwalletd_rpc_port = random_known_port();
let lightwalletd_rpc_address = format!("127.0.0.1:{lightwalletd_rpc_port}");
let arguments = args!["--grpc-bind-addr": lightwalletd_rpc_address];
let (lightwalletd_failure_messages, lightwalletd_ignore_messages) =
test_type.lightwalletd_failure_messages();
let mut lightwalletd = lightwalletd_dir
.spawn_lightwalletd_child(lightwalletd_state_path, arguments)?
.with_timeout(test_type.lightwalletd_timeout())
.with_failure_regex_iter(lightwalletd_failure_messages, lightwalletd_ignore_messages);
// Wait until `lightwalletd` has launched.
// This log happens very quickly, so it is ok to block for a short while here.
lightwalletd.expect_stdout_line_matches(regex::escape("Starting gRPC server"))?;
Ok(Some((lightwalletd, lightwalletd_rpc_port)))
}
/// Returns `true` if a lightwalletd test for `test_type` has everything it needs to run.
#[tracing::instrument]
pub fn can_spawn_lightwalletd_for_rpc<S: AsRef<str> + std::fmt::Debug>(
test_name: S,
test_type: TestType,
) -> bool {
if zebra_test::net::zebra_skip_network_tests() {
return false;
}
// Skip the test unless the user specifically asked for it
//
// TODO: pass test_type to zebra_skip_lightwalletd_tests() and check for lightwalletd launch in there
if test_type.launches_lightwalletd() && zebra_skip_lightwalletd_tests() {
return false;
}
let lightwalletd_state_path = test_type.lightwalletd_state_path(test_name);
if test_type.needs_lightwalletd_cached_state() && lightwalletd_state_path.is_none() {
return false;
}
true
}
/// Extension trait for methods on `tempfile::TempDir` for using it as a test
change(ci): Generate mainnet checkpoints in CI (#6550) * Add extra test type modes to support zebra-checkpoints * Add Mainnet and Testnet zebra-checkpoints test harnesses * Add zebra-checkpoints to test docker images * Add zebra-checkpoints test entrypoints * Add Mainnet CI workflow for zebra-checkpoints * Enable zebra-checkpoints feature in the test image * Use the same features for (almost) all the docker tests * Make workflow features match Docker features * Add a feature note * Add a zebra-checkpoints test feature to zebrad * Remove the "no cached state" testnet code * Log a startup message to standard error when launching zebra-checkpoints * Rename tests to avoid partial name conflicts * Fix log formatting * Add sentry feature to experimental docker image build * Explain what ENTRYPOINT_FEATURES is used for * Use the correct zebra-checkpoints path * Silence zebrad logs while generating checkpoints * Fix zebra-checkpoints log handling * Re-enable waiting for zebrad to fully sync * Add documentation for how to run these tests individually * Start generating checkpoints from the last compiled-in checkpoint * Fix clippy lints * Revert changes to TestType * Wait for all the checkpoints before finishing * Add more stderr debugging to zebra-checkpoints * Fix an outdated module comment * Add a workaround for zebra-checkpoints launch/run issues * Use temp dir and log what it is * Log extra metadata about the zebra-checkpoints binary * Add note about unstable feature -Z bindeps * Temporarily make the test run faster and with debug info * Log the original test command name when showing stdout and stderr * Try zebra-checkpoints in the system path first, then the cargo path * Fix slow thread close bug in dual process test harness * If the logs are shown, don't say they are hidden * Run `zebra-checkpoints --help` to work out what's going on in CI * Build `zebra-utils` binaries for `zebrad` integration tests * Revert temporary debugging changes * Revert changes that were moved to another PR
2023-04-26 21:39:43 -07:00
/// directory for `lightwalletd`.
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,
{
#[allow(clippy::unwrap_in_result)]
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;
// zcash/lightwalletd requires rpcuser and rpcpassword, or a zcashd cookie file
// But when a lightwalletd with this config is used by Zebra,
// Zebra ignores any authentication and provides access regardless.
let lightwalletd_config = format!(
"\
rpcbind={}\n\
rpcport={}\n\
rpcuser=xxxxx
rpcpassword=xxxxx
",
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)
}
}