2020-07-31 23:15:26 -07:00
//! Acceptance test: runs zebrad as a subprocess and asserts its
2019-08-29 14:46:54 -07:00
//! output for given argument combinations matches what is expected.
2020-09-07 17:05:23 -07:00
//!
2021-06-28 18:20:32 -07:00
//! ## Note on port conflict
2021-01-29 04:36:33 -08:00
//!
2020-09-07 17:05:23 -07:00
//! If the test child has a cache or port conflict with another test, or a
//! running zebrad or zcashd, then it will panic. But the acceptance tests
//! expect it to run until it is killed.
//!
//! If these conflicts cause test failures:
//! - run the tests in an isolated environment,
//! - run zebrad on a custom cache path and port,
//! - run zcashd on a custom port.
2021-06-28 18:20:32 -07:00
//!
//! ## Failures due to Configured Network Interfaces or Network Connectivity
//!
//! If your test environment does not have any IPv6 interfaces configured, skip IPv6 tests
//! by setting the `ZEBRA_SKIP_IPV6_TESTS` environmental variable.
//!
//! If it does not have any IPv4 interfaces, IPv4 localhost is not on `127.0.0.1`,
//! or you have poor network connectivity,
//! skip all the network tests by setting the `ZEBRA_SKIP_NETWORK_TESTS` environmental variable.
2022-06-15 01:05:02 -07:00
//!
//! ## Large/full sync tests
//!
//! This file has sync tests that are marked as ignored because they take too much time to run.
//! Some of them require environment variables or directories to be present:
//!
//! - `FULL_SYNC_MAINNET_TIMEOUT_MINUTES` env variable: The total number of minutes we
//! will allow this test to run or give up. Value for the Mainnet full sync tests.
//! - `FULL_SYNC_TESTNET_TIMEOUT_MINUTES` env variable: The total number of minutes we
//! will allow this test to run or give up. Value for the Testnet ful sync tests.
//! - `/zebrad-cache` directory: For some sync tests, this needs to be created in
//! the file system, the created directory should have write permissions.
//!
//! Here are some examples on how to run each of the tests:
//!
//! ```console
//! $ cargo test sync_large_checkpoints_mainnet -- --ignored --nocapture
//!
//! $ cargo test sync_large_checkpoints_mempool_mainnet -- --ignored --nocapture
//!
//! $ sudo mkdir /zebrad-cache
//! $ sudo chmod 777 /zebrad-cache
//! $ export FULL_SYNC_MAINNET_TIMEOUT_MINUTES=600
//! $ cargo test full_sync_mainnet -- --ignored --nocapture
//!
//! $ sudo mkdir /zebrad-cache
//! $ sudo chmod 777 /zebrad-cache
//! $ export FULL_SYNC_TESTNET_TIMEOUT_MINUTES=600
//! $ cargo test full_sync_testnet -- --ignored --nocapture
//! ```
//!
//! Please refer to the documentation of each test for more information.
//!
//! ## Lightwalletd tests
//!
//! The lightwalletd software is an interface service that uses zebrad or zcashd RPC methods to serve wallets or other applications with blockchain content in an efficient manner.
//! There are several versions of lightwalled in the form of different forks. The original
//! repo is <https://github.com/zcash/lightwalletd> but Zecwallet Lite uses a custom fork: <https://github.com/adityapk00/lightwalletd>.
//! The custom fork from adityapk00 is the one Zebra use for this tests:
//!
//! Zebra lightwalletd tests are not all marked as ignored but none will run unless
//! at least the `ZEBRA_TEST_LIGHTWALLETD` environment variable is present:
//!
//! - `ZEBRA_TEST_LIGHTWALLETD` env variable: Needs to be present to run any of the lightwalletd tests.
//! - `ZEBRA_CACHED_STATE_DIR` env var: The path to a zebra blockchain database.
//! - `LIGHTWALLETD_DATA_DIR` env variable. The path to a lightwalletd database.
//! - `--features lightwalletd-grpc-tests` cargo flag. The flag given to cargo to build the source code of the running test.
//!
//! Here are some examples of running each test:
//!
//! ```console
//! $ export ZEBRA_TEST_LIGHTWALLETD=true
//! $ cargo test lightwalletd_integration -- --nocapture
//!
//! $ export ZEBRA_TEST_LIGHTWALLETD=true
//! $ export ZEBRA_CACHED_STATE_DIR="/path/to/zebra/chain"
//! $ export LIGHTWALLETD_DATA_DIR="/path/to/lightwalletd/database"
//! $ cargo test lightwalletd_update_sync -- --nocapture
//!
//! $ export ZEBRA_TEST_LIGHTWALLETD=true
//! $ export ZEBRA_CACHED_STATE_DIR="/path/to/zebra/chain"
//! $ cargo test lightwalletd_full_sync -- --ignored --nocapture
//!
//! $ export ZEBRA_TEST_LIGHTWALLETD=true
//! $ cargo test lightwalletd_test_suite -- --ignored --nocapture
//!
//! $ export ZEBRA_TEST_LIGHTWALLETD=true
//! $ export ZEBRA_CACHED_STATE_DIR="/path/to/zebra/chain"
//! $ cargo test fully_synced_rpc_test -- --ignored --nocapture
//!
//! $ export ZEBRA_TEST_LIGHTWALLETD=true
//! $ export ZEBRA_CACHED_STATE_DIR="/path/to/zebra/chain"
//! $ export LIGHTWALLETD_DATA_DIR="/path/to/lightwalletd/database"
//! $ cargo test sending_transactions_using_lightwalletd --features lightwalletd-grpc-tests -- --ignored --nocapture
//!
//! $ export ZEBRA_TEST_LIGHTWALLETD=true
//! $ export ZEBRA_CACHED_STATE_DIR="/path/to/zebra/chain"
//! $ export LIGHTWALLETD_DATA_DIR="/path/to/lightwalletd/database"
//! $ cargo test lightwalletd_wallet_grpc_tests --features lightwalletd-grpc-tests -- --ignored --nocapture
//! ```
//!
//! Please refer to the documentation of each test for more information.
2020-07-31 23:15:26 -07:00
2022-06-27 17:36:36 -07:00
use std ::{ collections ::HashSet , env , fs , path ::PathBuf , time ::Duration } ;
2022-03-18 09:02:22 -07:00
2021-06-03 19:28:43 -07:00
use color_eyre ::{
2022-06-27 17:36:36 -07:00
eyre ::{ eyre , Result , WrapErr } ,
2021-06-03 19:28:43 -07:00
Help ,
} ;
2020-09-11 13:39:39 -07:00
2020-10-27 02:25:29 -07:00
use zebra_chain ::{
2022-04-27 16:06:11 -07:00
block ,
2021-06-17 17:05:28 -07:00
parameters ::Network ::{ self , * } ,
2020-10-27 02:25:29 -07:00
} ;
2021-01-29 04:36:33 -08:00
use zebra_network ::constants ::PORT_IN_USE_ERROR ;
use zebra_state ::constants ::LOCK_FILE_ERROR ;
2020-10-27 02:25:29 -07:00
2022-04-29 12:56:11 -07:00
use zebra_test ::{ args , command ::ContextFrom , net ::random_known_port , prelude ::* } ;
2022-03-18 09:02:22 -07:00
mod common ;
use common ::{
check ::{ is_zebrad_version , EphemeralCheck , EphemeralConfig } ,
2022-06-26 17:07:37 -07:00
config ::{ default_test_config , persistent_test_config , stored_config_path , testdir } ,
2022-04-27 16:06:11 -07:00
launch ::{
spawn_zebrad_for_rpc_without_initial_peers , ZebradTestDirExt , BETWEEN_NODES_DELAY ,
2022-04-29 12:56:11 -07:00
LAUNCH_DELAY ,
2022-04-27 16:06:11 -07:00
} ,
2022-03-18 09:02:22 -07:00
lightwalletd ::{
random_known_rpc_port_config , zebra_skip_lightwalletd_tests , LightWalletdTestDirExt ,
2022-04-29 12:56:11 -07:00
LightwalletdTestType ::{ self , * } ,
2022-03-18 09:02:22 -07:00
} ,
sync ::{
create_cached_database_height , sync_until , MempoolBehavior , LARGE_CHECKPOINT_TEST_HEIGHT ,
LARGE_CHECKPOINT_TIMEOUT , MEDIUM_CHECKPOINT_TEST_HEIGHT , STOP_AT_HEIGHT_REGEX ,
2022-06-30 08:14:30 -07:00
STOP_ON_LOAD_TIMEOUT , SYNC_FINISHED_REGEX , TINY_CHECKPOINT_TEST_HEIGHT ,
TINY_CHECKPOINT_TIMEOUT ,
2022-03-18 09:02:22 -07:00
} ,
} ;
2020-07-31 23:15:26 -07:00
#[ test ]
fn generate_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2020-09-11 13:39:39 -07:00
let child = testdir ( ) ?
2021-01-13 22:59:06 -08:00
. with_config ( & mut default_test_config ( ) ? ) ?
2022-04-19 03:28:52 -07:00
. spawn_child ( args! [ " generate " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
let output = output . assert_success ( ) ? ;
2020-08-10 12:50:48 -07:00
// First line
2021-06-03 19:28:43 -07:00
output . stdout_line_contains ( " # Default configuration for zebrad " ) ? ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
}
#[ test ]
fn generate_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2020-09-11 13:39:39 -07:00
let testdir = testdir ( ) ? ;
let testdir = & testdir ;
2020-07-31 23:15:26 -07:00
// unexpected free argument `argument`
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " generate " , " argument " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// unrecognized option `-f`
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " generate " , " -f " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// missing argument to option `-o`
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " generate " , " -o " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
2020-08-13 13:31:13 -07:00
// Add a config file name to tempdir path
2020-09-11 13:39:39 -07:00
let generated_config_path = testdir . path ( ) . join ( " zebrad.toml " ) ;
2020-08-13 13:31:13 -07:00
2020-07-31 23:15:26 -07:00
// Valid
2020-09-11 13:39:39 -07:00
let child =
2022-04-19 03:28:52 -07:00
testdir . spawn_child ( args! [ " generate " , " -o " : generated_config_path . to_str ( ) . unwrap ( ) ] ) ? ;
2020-08-13 13:31:13 -07:00
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
2020-09-01 12:39:04 -07:00
let output = output . assert_success ( ) ? ;
2019-08-29 14:46:54 -07:00
2021-01-11 18:26:08 -08:00
assert_with_context! (
testdir . path ( ) . exists ( ) ,
& output ,
" test temp directory not found "
) ;
assert_with_context! (
generated_config_path . exists ( ) ,
& output ,
" generated config file not found "
) ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
}
#[ test ]
fn help_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2021-01-13 22:59:06 -08:00
let testdir = testdir ( ) ? . with_config ( & mut default_test_config ( ) ? ) ? ;
2020-07-31 23:15:26 -07:00
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " help " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
let output = output . assert_success ( ) ? ;
2021-06-03 19:28:43 -07:00
// The first line should have the version
output . any_output_line (
is_zebrad_version ,
& output . output . stdout ,
" stdout " ,
" a valid zebrad semantic version " ,
) ? ;
2020-08-10 12:50:48 -07:00
// Make sure we are in help by looking usage string
2021-06-03 19:28:43 -07:00
output . stdout_line_contains ( " USAGE: " ) ? ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
}
#[ test ]
fn help_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2020-09-11 13:39:39 -07:00
let testdir = testdir ( ) ? ;
let testdir = & testdir ;
2020-07-31 23:15:26 -07:00
// The subcommand "argument" wasn't recognized.
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " help " , " argument " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// option `-f` does not accept an argument
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " help " , " -f " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
Ok ( ( ) )
}
2019-08-29 14:46:54 -07:00
2020-08-19 14:48:22 -07:00
#[ test ]
2020-07-31 23:15:26 -07:00
fn start_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2020-08-31 01:32:55 -07:00
// start caches state, so run one of the start tests with persistent state
2021-01-13 22:59:06 -08:00
let testdir = testdir ( ) ? . with_config ( & mut persistent_test_config ( ) ? ) ? ;
2020-07-31 23:15:26 -07:00
2022-04-19 03:28:52 -07:00
let mut child = testdir . spawn_child ( args! [ " -v " , " start " ] ) ? ;
2020-07-31 23:15:26 -07:00
2020-12-15 01:02:30 -08:00
// Run the program and kill it after a few seconds
std ::thread ::sleep ( LAUNCH_DELAY ) ;
2020-07-31 23:15:26 -07:00
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
2021-06-03 19:28:43 -07:00
output . stdout_line_contains ( " Starting zebrad " ) ? ;
2020-07-31 23:15:26 -07:00
2021-06-28 22:03:51 -07:00
// Make sure the command passed the legacy chain check
output . stdout_line_contains ( " starting legacy chain check " ) ? ;
output . stdout_line_contains ( " no legacy chain found " ) ? ;
2020-08-04 13:38:39 -07:00
// Make sure the command was killed
2020-09-01 12:39:04 -07:00
output . assert_was_killed ( ) ? ;
2020-08-04 13:38:39 -07:00
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
}
2020-08-19 14:48:22 -07:00
#[ test ]
2020-07-31 23:15:26 -07:00
fn start_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2021-01-13 22:59:06 -08:00
let testdir = testdir ( ) ? . with_config ( & mut default_test_config ( ) ? ) ? ;
2020-09-11 13:39:39 -07:00
let testdir = & testdir ;
2020-07-31 23:15:26 -07:00
2022-04-19 03:28:52 -07:00
let mut child = testdir . spawn_child ( args! [ " start " ] ) ? ;
2020-12-15 01:02:30 -08:00
// Run the program and kill it after a few seconds
std ::thread ::sleep ( LAUNCH_DELAY ) ;
2020-07-31 23:15:26 -07:00
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
2020-08-04 13:38:39 -07:00
// Make sure the command was killed
2020-09-01 12:39:04 -07:00
output . assert_was_killed ( ) ? ;
2020-08-04 13:38:39 -07:00
2020-07-31 23:15:26 -07:00
output . assert_failure ( ) ? ;
// unrecognized option `-f`
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " start " , " -f " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
Ok ( ( ) )
}
2020-08-31 01:32:55 -07:00
#[ test ]
fn persistent_mode ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2021-01-13 22:59:06 -08:00
let testdir = testdir ( ) ? . with_config ( & mut persistent_test_config ( ) ? ) ? ;
2020-09-11 13:39:39 -07:00
let testdir = & testdir ;
2020-08-31 01:32:55 -07:00
2022-04-19 03:28:52 -07:00
let mut child = testdir . spawn_child ( args! [ " -v " , " start " ] ) ? ;
2020-08-31 01:32:55 -07:00
2020-12-15 01:02:30 -08:00
// Run the program and kill it after a few seconds
std ::thread ::sleep ( LAUNCH_DELAY ) ;
2020-08-31 01:32:55 -07:00
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
// Make sure the command was killed
2020-09-01 12:39:04 -07:00
output . assert_was_killed ( ) ? ;
2020-08-31 01:32:55 -07:00
2020-09-11 13:39:39 -07:00
let cache_dir = testdir . path ( ) . join ( " state " ) ;
2021-01-11 18:26:08 -08:00
assert_with_context! (
cache_dir . read_dir ( ) ? . count ( ) > 0 ,
& output ,
" state directory empty despite persistent state config "
) ;
2020-08-31 01:32:55 -07:00
Ok ( ( ) )
}
2021-01-11 18:26:08 -08:00
#[ test ]
fn ephemeral_existing_directory ( ) -> Result < ( ) > {
ephemeral ( EphemeralConfig ::Default , EphemeralCheck ::ExistingDirectory )
}
2020-08-31 01:32:55 -07:00
2021-01-11 18:26:08 -08:00
#[ test ]
fn ephemeral_missing_directory ( ) -> Result < ( ) > {
ephemeral ( EphemeralConfig ::Default , EphemeralCheck ::MissingDirectory )
}
2020-08-31 01:32:55 -07:00
2021-01-11 18:26:08 -08:00
#[ test ]
fn misconfigured_ephemeral_existing_directory ( ) -> Result < ( ) > {
ephemeral (
EphemeralConfig ::MisconfiguredCacheDir ,
EphemeralCheck ::ExistingDirectory ,
)
2020-08-31 01:32:55 -07:00
}
#[ test ]
2021-01-11 18:26:08 -08:00
fn misconfigured_ephemeral_missing_directory ( ) -> Result < ( ) > {
ephemeral (
EphemeralConfig ::MisconfiguredCacheDir ,
EphemeralCheck ::MissingDirectory ,
)
}
2020-08-31 01:32:55 -07:00
2021-01-11 18:26:08 -08:00
fn ephemeral ( cache_dir_config : EphemeralConfig , cache_dir_check : EphemeralCheck ) -> Result < ( ) > {
use std ::io ::ErrorKind ;
zebra_test ::init ( ) ;
2020-08-31 01:32:55 -07:00
2020-08-31 12:43:43 -07:00
let mut config = default_test_config ( ) ? ;
2022-01-14 07:11:23 -08:00
let run_dir = testdir ( ) ? ;
2020-08-31 12:43:43 -07:00
2021-01-11 18:26:08 -08:00
let ignored_cache_dir = run_dir . path ( ) . join ( " state " ) ;
if cache_dir_config = = EphemeralConfig ::MisconfiguredCacheDir {
// Write a configuration that sets both the cache_dir and ephemeral options
config . state . cache_dir = ignored_cache_dir . clone ( ) ;
}
if cache_dir_check = = EphemeralCheck ::ExistingDirectory {
// We set the cache_dir config to a newly created empty temp directory,
// then make sure that it is empty after the test
fs ::create_dir ( & ignored_cache_dir ) ? ;
}
2020-08-31 01:32:55 -07:00
2021-01-11 18:26:08 -08:00
let mut child = run_dir
. path ( )
2021-01-13 22:59:06 -08:00
. with_config ( & mut config ) ?
2022-04-19 03:28:52 -07:00
. spawn_child ( args! [ " start " ] ) ? ;
2020-12-15 01:02:30 -08:00
// Run the program and kill it after a few seconds
std ::thread ::sleep ( LAUNCH_DELAY ) ;
2020-08-31 01:32:55 -07:00
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
// Make sure the command was killed
2020-09-01 12:39:04 -07:00
output . assert_was_killed ( ) ? ;
2020-08-31 01:32:55 -07:00
2021-01-11 18:26:08 -08:00
let expected_run_dir_file_names = match cache_dir_check {
// we created the state directory, so it should still exist
EphemeralCheck ::ExistingDirectory = > {
assert_with_context! (
ignored_cache_dir
. read_dir ( )
. expect ( " ignored_cache_dir should still exist " )
. count ( )
= = 0 ,
& output ,
" ignored_cache_dir not empty for ephemeral {:?} {:?}: {:?} " ,
cache_dir_config ,
cache_dir_check ,
ignored_cache_dir . read_dir ( ) . unwrap ( ) . collect ::< Vec < _ > > ( )
) ;
[ " state " , " zebrad.toml " ] . iter ( )
}
// we didn't create the state directory, so it should not exist
EphemeralCheck ::MissingDirectory = > {
assert_with_context! (
ignored_cache_dir
. read_dir ( )
. expect_err ( " ignored_cache_dir should not exist " )
. kind ( )
= = ErrorKind ::NotFound ,
& output ,
" unexpected creation of ignored_cache_dir for ephemeral {:?} {:?}: the cache dir exists and contains these files: {:?} " ,
cache_dir_config ,
cache_dir_check ,
ignored_cache_dir . read_dir ( ) . unwrap ( ) . collect ::< Vec < _ > > ( )
) ;
[ " zebrad.toml " ] . iter ( )
}
} ;
let expected_run_dir_file_names = expected_run_dir_file_names . map ( Into ::into ) . collect ( ) ;
let run_dir_file_names = run_dir
. path ( )
. read_dir ( )
. expect ( " run_dir should still exist " )
. map ( | dir_entry | dir_entry . expect ( " run_dir is readable " ) . file_name ( ) )
// ignore directory list order, because it can vary based on the OS and filesystem
. collect ::< HashSet < _ > > ( ) ;
2020-09-11 13:39:39 -07:00
assert_with_context! (
2021-01-11 18:26:08 -08:00
run_dir_file_names = = expected_run_dir_file_names ,
& output ,
" run_dir not empty for ephemeral {:?} {:?}: expected {:?}, actual: {:?} " ,
cache_dir_config ,
cache_dir_check ,
expected_run_dir_file_names ,
run_dir_file_names
2020-09-11 13:39:39 -07:00
) ;
2020-08-31 01:32:55 -07:00
Ok ( ( ) )
}
2020-07-31 23:15:26 -07:00
#[ test ]
fn app_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2021-01-13 22:59:06 -08:00
let testdir = testdir ( ) ? . with_config ( & mut default_test_config ( ) ? ) ? ;
2020-07-31 23:15:26 -07:00
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
let output = output . assert_success ( ) ? ;
2021-06-03 19:28:43 -07:00
output . stdout_line_contains ( " USAGE: " ) ? ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
}
#[ test ]
fn version_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2021-01-13 22:59:06 -08:00
let testdir = testdir ( ) ? . with_config ( & mut default_test_config ( ) ? ) ? ;
2020-07-31 23:15:26 -07:00
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " version " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
let output = output . assert_success ( ) ? ;
2021-06-03 19:28:43 -07:00
// The output should only contain the version
output . output_check (
is_zebrad_version ,
& output . output . stdout ,
" stdout " ,
" a valid zebrad semantic version " ,
) ? ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
}
#[ test ]
fn version_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2021-01-13 22:59:06 -08:00
let testdir = testdir ( ) ? . with_config ( & mut default_test_config ( ) ? ) ? ;
2020-09-11 13:39:39 -07:00
let testdir = & testdir ;
2020-07-31 23:15:26 -07:00
// unexpected free argument `argument`
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " version " , " argument " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// unrecognized option `-f`
2022-04-19 03:28:52 -07:00
let child = testdir . spawn_child ( args! [ " version " , " -f " ] ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
Ok ( ( ) )
}
2022-06-27 17:36:36 -07:00
/// Run config tests that use the default ports and paths.
///
/// Unlike the other tests, these tests can not be run in parallel, because
/// they use the generated config. So parallel execution can cause port and
/// cache conflicts.
2020-07-31 23:15:26 -07:00
#[ test ]
2022-06-27 17:36:36 -07:00
fn config_test ( ) -> Result < ( ) > {
2021-06-03 19:28:43 -07:00
valid_generated_config ( " start " , " Starting zebrad " ) ? ;
2020-08-20 03:49:38 -07:00
2022-06-27 17:36:36 -07:00
// Check what happens when Zebra parses an invalid config
invalid_generated_config ( ) ? ;
// Check that an older stored configuration we have for Zebra works
2022-06-26 17:07:37 -07:00
stored_config_works ( ) ? ;
2020-08-20 03:49:38 -07:00
Ok ( ( ) )
}
2022-06-27 17:36:36 -07:00
/// Test that `zebrad start` can parse the output from `zebrad generate`.
2021-06-03 19:28:43 -07:00
fn valid_generated_config ( command : & str , expect_stdout_line_contains : & str ) -> Result < ( ) > {
2020-08-13 13:31:13 -07:00
zebra_test ::init ( ) ;
2020-11-09 16:29:25 -08:00
2020-09-11 13:39:39 -07:00
let testdir = testdir ( ) ? ;
let testdir = & testdir ;
2020-08-13 13:31:13 -07:00
// Add a config file name to tempdir path
2020-09-11 13:39:39 -07:00
let generated_config_path = testdir . path ( ) . join ( " zebrad.toml " ) ;
2020-08-13 13:31:13 -07:00
// Generate configuration in temp dir path
2020-09-11 13:39:39 -07:00
let child =
2022-04-19 03:28:52 -07:00
testdir . spawn_child ( args! [ " generate " , " -o " : generated_config_path . to_str ( ) . unwrap ( ) ] ) ? ;
2020-08-13 13:31:13 -07:00
let output = child . wait_with_output ( ) ? ;
2020-09-01 12:39:04 -07:00
let output = output . assert_success ( ) ? ;
2020-08-13 13:31:13 -07:00
2021-01-11 18:26:08 -08:00
assert_with_context! (
generated_config_path . exists ( ) ,
& output ,
" generated config file not found "
) ;
2020-08-13 13:31:13 -07:00
2020-12-15 01:02:30 -08:00
// Run command using temp dir and kill it after a few seconds
2022-04-19 03:28:52 -07:00
let mut child = testdir . spawn_child ( args! [ command ] ) ? ;
2020-12-15 01:02:30 -08:00
std ::thread ::sleep ( LAUNCH_DELAY ) ;
2020-08-13 13:31:13 -07:00
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
2021-06-03 19:28:43 -07:00
output . stdout_line_contains ( expect_stdout_line_contains ) ? ;
2020-08-13 13:31:13 -07:00
2020-09-07 17:05:23 -07:00
// [Note on port conflict](#Note on port conflict)
output . assert_was_killed ( ) . wrap_err ( " Possible port or cache conflict. Are there other acceptance test, zebrad, or zcashd processes running? " ) ? ;
2020-08-13 13:31:13 -07:00
2021-01-11 18:26:08 -08:00
assert_with_context! (
testdir . path ( ) . exists ( ) ,
& output ,
" test temp directory not found "
) ;
assert_with_context! (
generated_config_path . exists ( ) ,
& output ,
" generated config file not found "
) ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
2019-08-29 14:46:54 -07:00
}
2020-09-07 17:05:23 -07:00
2022-06-27 17:36:36 -07:00
/// Checks that Zebra prints an informative message when it cannot parse the
/// config file.
fn invalid_generated_config ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
let testdir = & testdir ( ) ? ;
// Add a config file name to tempdir path.
let config_path = testdir . path ( ) . join ( " zebrad.toml " ) ;
// Generate a valid config file in the temp dir.
let child = testdir . spawn_child ( args! [ " generate " , " -o " : config_path . to_str ( ) . unwrap ( ) ] ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_success ( ) ? ;
assert_with_context! (
config_path . exists ( ) ,
& output ,
" generated config file not found "
) ;
// Load the valid config file that Zebra generated.
let mut config_file = fs ::read_to_string ( config_path . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
// Let's now alter the config file so that it contains a deprecated format
// of `mempool.eviction_memory_time`.
config_file = config_file
. lines ( )
// Remove the valid `eviction_memory_time` key/value pair from the
// config.
. filter ( | line | ! line . contains ( " eviction_memory_time " ) )
. map ( | line | line . to_owned ( ) + " \n " )
. collect ( ) ;
// Append the `eviction_memory_time` key/value pair in a deprecated format.
config_file + = r "
[ mempool . eviction_memory_time ]
nanos = 0
secs = 3600
" ;
// Write the altered config file so that Zebra can pick it up.
fs ::write ( config_path . to_str ( ) . unwrap ( ) , config_file . as_bytes ( ) )
. expect ( " Could not write the altered config file. " ) ;
// Run Zebra in a temp dir so that it loads the config.
let mut child = testdir . spawn_child ( args! [ " start " ] ) ? ;
// Return an error if Zebra is running for more than two seconds.
//
// Since the config is invalid, Zebra should terminate instantly after its
// start. Two seconds should be sufficient for Zebra to read the config file
// and terminate.
std ::thread ::sleep ( Duration ::from_secs ( 2 ) ) ;
if child . is_running ( ) {
child . kill ( ) ? ;
return Err ( eyre! ( " Zebra should not be running anymore. " ) ) ;
}
let output = child . wait_with_output ( ) ? ;
// Check that Zebra produced an informative message.
output . stderr_contains ( " Zebra could not parse the provided config file. This might mean you are using a deprecated format of the file. " ) ? ;
Ok ( ( ) )
}
/// Test that an older `zebrad.toml` can still be parsed by the latest `zebrad`.
2022-06-26 17:07:37 -07:00
fn stored_config_works ( ) -> Result < ( ) > {
let stored_config_path = stored_config_path ( ) ;
let run_dir = testdir ( ) ? ;
// run zebra with stored config
let mut child =
run_dir . spawn_child ( args! [ " -c " , stored_config_path . to_str ( ) . unwrap ( ) , " start " ] ) ? ;
// zebra was able to start with the stored config
child . expect_stdout_line_matches ( " Starting zebrad " . to_string ( ) ) ? ;
// finish
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
// [Note on port conflict](#Note on port conflict)
output
. assert_was_killed ( )
. wrap_err ( " Possible port conflict. Are there other acceptance tests running? " ) ? ;
Ok ( ( ) )
}
2020-10-09 16:50:33 -07:00
/// Test if `zebrad` can sync the first checkpoint on mainnet.
///
2020-10-20 02:45:27 -07:00
/// The first checkpoint contains a single genesis block.
2020-09-11 13:39:39 -07:00
#[ test ]
2020-09-08 18:59:24 -07:00
fn sync_one_checkpoint_mainnet ( ) -> Result < ( ) > {
2020-10-20 02:45:27 -07:00
sync_until (
2021-10-21 05:30:11 -07:00
TINY_CHECKPOINT_TEST_HEIGHT ,
2020-10-20 02:45:27 -07:00
Mainnet ,
2020-10-27 02:25:29 -07:00
STOP_AT_HEIGHT_REGEX ,
2021-10-21 05:30:11 -07:00
TINY_CHECKPOINT_TIMEOUT ,
2020-10-27 02:25:29 -07:00
None ,
2022-02-15 15:46:20 -08:00
MempoolBehavior ::ShouldNotActivate ,
2022-02-22 18:20:52 -08:00
// checkpoint sync is irrelevant here - all tested checkpoints are mandatory
true ,
true ,
2020-10-20 02:45:27 -07:00
)
2020-10-27 02:25:29 -07:00
. map ( | _tempdir | ( ) )
2020-09-08 18:59:24 -07:00
}
2020-10-09 16:50:33 -07:00
/// Test if `zebrad` can sync the first checkpoint on testnet.
///
2020-10-20 02:45:27 -07:00
/// The first checkpoint contains a single genesis block.
2022-06-13 13:13:30 -07:00
// TODO: disabled because testnet is not currently reliable
// #[test]
#[ allow(dead_code) ]
2020-09-08 18:59:24 -07:00
fn sync_one_checkpoint_testnet ( ) -> Result < ( ) > {
2020-10-20 02:45:27 -07:00
sync_until (
2021-10-21 05:30:11 -07:00
TINY_CHECKPOINT_TEST_HEIGHT ,
2020-10-20 02:45:27 -07:00
Testnet ,
2020-10-27 02:25:29 -07:00
STOP_AT_HEIGHT_REGEX ,
2021-10-21 05:30:11 -07:00
TINY_CHECKPOINT_TIMEOUT ,
2020-10-27 02:25:29 -07:00
None ,
2022-02-15 15:46:20 -08:00
MempoolBehavior ::ShouldNotActivate ,
2022-02-22 18:20:52 -08:00
// checkpoint sync is irrelevant here - all tested checkpoints are mandatory
true ,
true ,
2020-10-20 02:45:27 -07:00
)
2020-10-27 02:25:29 -07:00
. map ( | _tempdir | ( ) )
2020-09-08 18:59:24 -07:00
}
2020-10-27 02:25:29 -07:00
/// Test if `zebrad` can sync the first checkpoint, restart, and stop on load.
#[ test ]
fn restart_stop_at_height ( ) -> Result < ( ) > {
2021-06-15 15:48:09 -07:00
zebra_test ::init ( ) ;
2021-10-21 05:30:11 -07:00
restart_stop_at_height_for_network ( Network ::Mainnet , TINY_CHECKPOINT_TEST_HEIGHT ) ? ;
2022-06-13 13:13:30 -07:00
// TODO: disabled because testnet is not currently reliable
// restart_stop_at_height_for_network(Network::Testnet, TINY_CHECKPOINT_TEST_HEIGHT)?;
2021-06-15 15:48:09 -07:00
Ok ( ( ) )
}
2022-04-27 16:06:11 -07:00
fn restart_stop_at_height_for_network ( network : Network , height : block ::Height ) -> Result < ( ) > {
2020-10-27 02:25:29 -07:00
let reuse_tempdir = sync_until (
2021-06-15 15:48:09 -07:00
height ,
network ,
2020-10-27 02:25:29 -07:00
STOP_AT_HEIGHT_REGEX ,
2021-10-21 05:30:11 -07:00
TINY_CHECKPOINT_TIMEOUT ,
2020-10-27 02:25:29 -07:00
None ,
2022-02-15 15:46:20 -08:00
MempoolBehavior ::ShouldNotActivate ,
2022-02-22 18:20:52 -08:00
// checkpoint sync is irrelevant here - all tested checkpoints are mandatory
true ,
true ,
2020-10-27 02:25:29 -07:00
) ? ;
2021-04-07 02:25:31 -07:00
// if stopping corrupts the rocksdb database, zebrad might hang or crash here
2021-04-07 02:23:48 -07:00
// if stopping does not write the rocksdb database to disk, Zebra will
// sync, rather than stopping immediately at the configured height
2020-10-27 02:25:29 -07:00
sync_until (
2021-06-15 15:48:09 -07:00
height ,
network ,
2020-11-12 17:37:52 -08:00
" state is already at the configured height " ,
2020-10-27 02:25:29 -07:00
STOP_ON_LOAD_TIMEOUT ,
2021-10-13 08:04:49 -07:00
reuse_tempdir ,
2022-02-15 15:46:20 -08:00
MempoolBehavior ::ShouldNotActivate ,
2022-02-22 18:20:52 -08:00
// checkpoint sync is irrelevant here - all tested checkpoints are mandatory
true ,
false ,
2020-10-27 02:25:29 -07:00
) ? ;
Ok ( ( ) )
}
2021-10-13 08:04:49 -07:00
/// Test if `zebrad` can activate the mempool on mainnet.
/// Debug activation happens after committing the genesis block.
#[ test ]
fn activate_mempool_mainnet ( ) -> Result < ( ) > {
sync_until (
2022-04-27 16:06:11 -07:00
block ::Height ( TINY_CHECKPOINT_TEST_HEIGHT . 0 + 1 ) ,
2021-10-13 08:04:49 -07:00
Mainnet ,
STOP_AT_HEIGHT_REGEX ,
2021-10-21 05:30:11 -07:00
TINY_CHECKPOINT_TIMEOUT ,
2021-10-13 08:04:49 -07:00
None ,
2022-02-15 15:46:20 -08:00
MempoolBehavior ::ForceActivationAt ( TINY_CHECKPOINT_TEST_HEIGHT ) ,
2022-02-22 18:20:52 -08:00
// checkpoint sync is irrelevant here - all tested checkpoints are mandatory
true ,
true ,
2021-10-13 08:04:49 -07:00
)
. map ( | _tempdir | ( ) )
}
2020-10-27 02:25:29 -07:00
/// Test if `zebrad` can sync some larger checkpoints on mainnet.
2020-10-20 02:53:28 -07:00
///
2020-10-20 02:55:11 -07:00
/// This test might fail or timeout on slow or unreliable networks,
/// so we don't run it by default. It also takes a lot longer than
/// our 10 second target time for default tests.
2020-10-20 02:53:28 -07:00
#[ test ]
2020-10-20 02:55:11 -07:00
#[ ignore ]
2020-10-27 02:25:29 -07:00
fn sync_large_checkpoints_mainnet ( ) -> Result < ( ) > {
let reuse_tempdir = sync_until (
LARGE_CHECKPOINT_TEST_HEIGHT ,
Mainnet ,
STOP_AT_HEIGHT_REGEX ,
LARGE_CHECKPOINT_TIMEOUT ,
None ,
2022-02-15 15:46:20 -08:00
MempoolBehavior ::ShouldNotActivate ,
2022-02-22 18:20:52 -08:00
// checkpoint sync is irrelevant here - all tested checkpoints are mandatory
true ,
true ,
2020-10-27 02:25:29 -07:00
) ? ;
// if this sync fails, see the failure notes in `restart_stop_at_height`
2020-10-20 02:53:28 -07:00
sync_until (
2020-10-27 02:25:29 -07:00
( LARGE_CHECKPOINT_TEST_HEIGHT - 1 ) . unwrap ( ) ,
2020-10-20 02:53:28 -07:00
Mainnet ,
2020-10-27 02:25:29 -07:00
" previous state height is greater than the stop height " ,
STOP_ON_LOAD_TIMEOUT ,
2021-10-13 08:04:49 -07:00
reuse_tempdir ,
2022-02-15 15:46:20 -08:00
MempoolBehavior ::ShouldNotActivate ,
2022-02-22 18:20:52 -08:00
// checkpoint sync is irrelevant here - all tested checkpoints are mandatory
true ,
false ,
2020-10-27 02:25:29 -07:00
) ? ;
Ok ( ( ) )
2020-10-20 02:53:28 -07:00
}
2021-10-21 05:30:11 -07:00
// TODO: We had `sync_large_checkpoints_testnet` and `sync_large_checkpoints_mempool_testnet`,
// but they were removed because the testnet is unreliable (#1222).
// We should re-add them after we have more testnet instances (#1791).
2020-10-20 02:53:28 -07:00
2021-10-14 19:27:50 -07:00
/// Test if `zebrad` can run side by side with the mempool.
2021-10-21 05:30:11 -07:00
/// This is done by running the mempool and syncing some checkpoints.
2021-10-14 19:27:50 -07:00
#[ test ]
2021-10-21 05:30:11 -07:00
#[ ignore ]
fn sync_large_checkpoints_mempool_mainnet ( ) -> Result < ( ) > {
2021-10-14 19:27:50 -07:00
sync_until (
2021-10-21 05:30:11 -07:00
MEDIUM_CHECKPOINT_TEST_HEIGHT ,
2021-10-14 19:27:50 -07:00
Mainnet ,
STOP_AT_HEIGHT_REGEX ,
LARGE_CHECKPOINT_TIMEOUT ,
None ,
2022-02-15 15:46:20 -08:00
MempoolBehavior ::ForceActivationAt ( TINY_CHECKPOINT_TEST_HEIGHT ) ,
2022-02-22 18:20:52 -08:00
// checkpoint sync is irrelevant here - all tested checkpoints are mandatory
true ,
true ,
2021-10-14 19:27:50 -07:00
)
. map ( | _tempdir | ( ) )
}
2020-10-29 18:00:02 -07:00
fn create_cached_database ( network : Network ) -> Result < ( ) > {
2021-06-17 17:05:28 -07:00
let height = network . mandatory_checkpoint_height ( ) ;
2022-03-02 00:53:00 -08:00
let checkpoint_stop_regex = format! ( " {} .*CommitFinalized request " , STOP_AT_HEIGHT_REGEX ) ;
2021-12-14 13:43:07 -08:00
create_cached_database_height (
network ,
height ,
2022-05-05 02:25:46 -07:00
// We don't need the ZK parameters, we're only using checkpoints
2021-12-14 13:43:07 -08:00
true ,
2022-02-22 18:20:52 -08:00
// Use checkpoints to increase sync performance while caching the database
true ,
2022-03-02 00:53:00 -08:00
// Check that we're still using checkpoints when we finish the cached sync
& checkpoint_stop_regex ,
2021-12-14 13:43:07 -08:00
)
2020-10-29 18:00:02 -07:00
}
2020-10-28 12:34:43 -07:00
2021-06-17 17:05:28 -07:00
fn sync_past_mandatory_checkpoint ( network : Network ) -> Result < ( ) > {
let height = network . mandatory_checkpoint_height ( ) + 1200 ;
2022-03-02 00:53:00 -08:00
let full_validation_stop_regex =
format! ( " {} .*best non-finalized chain root " , STOP_AT_HEIGHT_REGEX ) ;
2021-07-09 05:47:09 -07:00
create_cached_database_height (
network ,
height . unwrap ( ) ,
2022-05-05 02:25:46 -07:00
// We need the ZK parameters for full validation
2021-12-14 13:43:07 -08:00
false ,
2022-02-22 18:20:52 -08:00
// Test full validation by turning checkpoints off
false ,
2022-05-05 02:25:46 -07:00
// Check that we're doing full validation when we finish the cached sync
2022-03-02 00:53:00 -08:00
& full_validation_stop_regex ,
2021-07-09 05:47:09 -07:00
)
2020-10-29 18:00:02 -07:00
}
2020-10-28 12:34:43 -07:00
2022-05-05 02:25:46 -07:00
/// Sync `network` until the chain tip is reached, or a timeout elapses.
///
/// The timeout is specified using an environment variable, with the name configured by the
/// `timeout_argument_name` parameter. The value of the environment variable must the number of
/// minutes specified as an integer.
2022-06-15 01:05:02 -07:00
#[ allow(clippy::print_stderr) ]
2022-05-05 02:25:46 -07:00
fn full_sync_test ( network : Network , timeout_argument_name : & str ) -> Result < ( ) > {
let timeout_argument : Option < u64 > = env ::var ( timeout_argument_name )
. ok ( )
. and_then ( | timeout_string | timeout_string . parse ( ) . ok ( ) ) ;
// # TODO
//
// Replace hard-coded values in create_cached_database_height with:
// - the timeout in the environmental variable
// - the path from ZEBRA_CACHED_STATE_DIR
if let Some ( _timeout_minutes ) = timeout_argument {
create_cached_database_height (
network ,
// Just keep going until we reach the chain tip
block ::Height ::MAX ,
// We need the ZK parameters for full validation
false ,
// Use the checkpoints to sync quickly, then do full validation until the chain tip
true ,
// Finish when we reach the chain tip
2022-06-30 08:14:30 -07:00
SYNC_FINISHED_REGEX ,
2022-05-05 02:25:46 -07:00
)
} else {
2022-06-15 01:05:02 -07:00
eprintln! (
" Skipped full sync test for {}, \
set the { :? } environmental variable to run the test " ,
network , timeout_argument_name ,
2022-05-05 02:25:46 -07:00
) ;
Ok ( ( ) )
}
}
2020-10-30 12:45:26 -07:00
// These tests are ignored because they're too long running to run during our
// traditional CI, and they depend on persistent state that cannot be made
// available in github actions or google cloud build. Instead we run these tests
// directly in a vm we spin up on google compute engine, where we can mount
2022-05-05 02:25:46 -07:00
// drives populated by the sync_to_mandatory_checkpoint tests, snapshot those drives,
// and then use them to more quickly run the sync_past_mandatory_checkpoint tests.
2020-10-30 12:45:26 -07:00
2021-06-17 17:05:28 -07:00
/// Sync up to the mandatory checkpoint height on mainnet and stop.
2021-06-03 15:48:40 -07:00
#[ allow(dead_code) ]
2021-06-17 17:05:28 -07:00
#[ cfg_attr(feature = " test_sync_to_mandatory_checkpoint_mainnet " , test) ]
2022-05-05 02:25:46 -07:00
fn sync_to_mandatory_checkpoint_mainnet ( ) -> Result < ( ) > {
2020-10-29 18:00:02 -07:00
zebra_test ::init ( ) ;
let network = Mainnet ;
2022-05-05 02:25:46 -07:00
create_cached_database ( network )
2020-10-29 18:00:02 -07:00
}
2020-12-19 15:06:18 -08:00
2021-06-17 17:05:28 -07:00
/// Sync to the mandatory checkpoint height testnet and stop.
2021-06-03 15:48:40 -07:00
#[ allow(dead_code) ]
2021-06-17 17:05:28 -07:00
#[ cfg_attr(feature = " test_sync_to_mandatory_checkpoint_testnet " , test) ]
2022-05-05 02:25:46 -07:00
fn sync_to_mandatory_checkpoint_testnet ( ) -> Result < ( ) > {
2020-10-29 18:00:02 -07:00
zebra_test ::init ( ) ;
let network = Testnet ;
2022-05-05 02:25:46 -07:00
create_cached_database ( network )
2020-10-29 18:00:02 -07:00
}
2020-10-28 12:34:43 -07:00
2021-06-17 17:05:28 -07:00
/// Test syncing 1200 blocks (3 checkpoints) past the mandatory checkpoint on mainnet.
2020-11-22 21:12:12 -08:00
///
2021-06-17 17:05:28 -07:00
/// This assumes that the config'd state is already synced at or near the mandatory checkpoint
/// activation on mainnet. If the state has already synced past the mandatory checkpoint
2020-11-22 21:12:12 -08:00
/// activation by 1200 blocks, it will fail.
2021-06-03 15:48:40 -07:00
#[ allow(dead_code) ]
2021-06-17 17:05:28 -07:00
#[ cfg_attr(feature = " test_sync_past_mandatory_checkpoint_mainnet " , test) ]
2022-05-05 02:25:46 -07:00
fn sync_past_mandatory_checkpoint_mainnet ( ) -> Result < ( ) > {
2020-10-29 18:00:02 -07:00
zebra_test ::init ( ) ;
let network = Mainnet ;
2022-05-05 02:25:46 -07:00
sync_past_mandatory_checkpoint ( network )
2020-10-29 18:00:02 -07:00
}
2021-06-17 17:05:28 -07:00
/// Test syncing 1200 blocks (3 checkpoints) past the mandatory checkpoint on testnet.
2020-11-22 21:12:12 -08:00
///
2021-06-17 17:05:28 -07:00
/// This assumes that the config'd state is already synced at or near the mandatory checkpoint
/// activation on testnet. If the state has already synced past the mandatory checkpoint
2020-11-22 21:12:12 -08:00
/// activation by 1200 blocks, it will fail.
2021-06-03 15:48:40 -07:00
#[ allow(dead_code) ]
2021-06-17 17:05:28 -07:00
#[ cfg_attr(feature = " test_sync_past_mandatory_checkpoint_testnet " , test) ]
2022-05-05 02:25:46 -07:00
fn sync_past_mandatory_checkpoint_testnet ( ) -> Result < ( ) > {
2020-10-29 18:00:02 -07:00
zebra_test ::init ( ) ;
let network = Testnet ;
2022-05-05 02:25:46 -07:00
sync_past_mandatory_checkpoint ( network )
}
/// Test if `zebrad` can fully sync the chain on mainnet.
///
/// This test takes a long time to run, so we don't run it by default. This test is only executed
/// if there is an environment variable named `FULL_SYNC_MAINNET_TIMEOUT_MINUTES` set with the number
/// of minutes to wait for synchronization to complete before considering that the test failed.
#[ test ]
#[ ignore ]
fn full_sync_mainnet ( ) -> Result < ( ) > {
// TODO: add "ZEBRA" at the start of this env var, to avoid clashes
full_sync_test ( Mainnet , " FULL_SYNC_MAINNET_TIMEOUT_MINUTES " )
}
/// Test if `zebrad` can fully sync the chain on testnet.
///
/// This test takes a long time to run, so we don't run it by default. This test is only executed
/// if there is an environment variable named `FULL_SYNC_TESTNET_TIMEOUT_MINUTES` set with the number
/// of minutes to wait for synchronization to complete before considering that the test failed.
#[ test ]
#[ ignore ]
fn full_sync_testnet ( ) -> Result < ( ) > {
// TODO: add "ZEBRA" at the start of this env var, to avoid clashes
full_sync_test ( Testnet , " FULL_SYNC_TESTNET_TIMEOUT_MINUTES " )
2020-10-28 12:34:43 -07:00
}
2022-06-16 12:56:40 -07:00
#[ cfg(feature = " prometheus " ) ]
2020-09-07 17:05:23 -07:00
#[ tokio::test ]
async fn metrics_endpoint ( ) -> Result < ( ) > {
2020-12-14 23:33:37 -08:00
use hyper ::Client ;
2020-09-07 17:05:23 -07:00
zebra_test ::init ( ) ;
// [Note on port conflict](#Note on port conflict)
2020-12-17 17:32:33 -08:00
let port = random_known_port ( ) ;
2020-12-14 23:33:37 -08:00
let endpoint = format! ( " 127.0.0.1: {} " , port ) ;
let url = format! ( " http:// {} " , endpoint ) ;
2020-09-07 17:05:23 -07:00
// Write a configuration that has metrics endpoint_addr set
let mut config = default_test_config ( ) ? ;
config . metrics . endpoint_addr = Some ( endpoint . parse ( ) . unwrap ( ) ) ;
2022-01-14 07:11:23 -08:00
let dir = testdir ( ) ? . with_config ( & mut config ) ? ;
2022-04-19 03:28:52 -07:00
let child = dir . spawn_child ( args! [ " start " ] ) ? ;
2020-09-07 17:05:23 -07:00
2020-12-15 01:02:30 -08:00
// Run `zebrad` for a few seconds before testing the endpoint
// Since we're an async function, we have to use a sleep future, not thread sleep.
tokio ::time ::sleep ( LAUNCH_DELAY ) . await ;
2020-09-07 17:05:23 -07:00
// Create an http client
let client = Client ::new ( ) ;
// Test metrics endpoint
2021-02-18 12:46:27 -08:00
let res = client . get ( url . try_into ( ) . expect ( " url is valid " ) ) . await ;
let ( res , child ) = child . kill_on_error ( res ) ? ;
2020-09-07 17:05:23 -07:00
assert! ( res . status ( ) . is_success ( ) ) ;
2021-02-18 12:46:27 -08:00
let body = hyper ::body ::to_bytes ( res ) . await ;
let ( body , mut child ) = child . kill_on_error ( body ) ? ;
2020-09-07 17:05:23 -07:00
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
2021-06-03 19:28:43 -07:00
output . any_output_line_contains (
2021-11-02 11:46:57 -07:00
" # TYPE zebrad_build_info counter " ,
2021-06-03 19:28:43 -07:00
& body ,
" metrics exporter response " ,
" the metrics response header " ,
) ? ;
std ::str ::from_utf8 ( & body ) . expect ( " unexpected invalid UTF-8 in metrics exporter response " ) ;
2020-09-07 17:05:23 -07:00
// Make sure metrics was started
2021-06-03 19:28:43 -07:00
output . stdout_line_contains ( format! ( " Opened metrics endpoint at {} " , endpoint ) . as_str ( ) ) ? ;
2020-09-07 17:05:23 -07:00
// [Note on port conflict](#Note on port conflict)
output
. assert_was_killed ( )
. wrap_err ( " Possible port conflict. Are there other acceptance tests running? " ) ? ;
Ok ( ( ) )
}
2022-06-16 12:56:40 -07:00
#[ cfg(feature = " filter-reload " ) ]
2020-09-07 17:05:23 -07:00
#[ tokio::test ]
async fn tracing_endpoint ( ) -> Result < ( ) > {
2020-12-14 23:33:37 -08:00
use hyper ::{ Body , Client , Request } ;
2020-09-07 17:05:23 -07:00
zebra_test ::init ( ) ;
// [Note on port conflict](#Note on port conflict)
2020-12-17 17:32:33 -08:00
let port = random_known_port ( ) ;
2020-12-14 23:33:37 -08:00
let endpoint = format! ( " 127.0.0.1: {} " , port ) ;
let url_default = format! ( " http:// {} " , endpoint ) ;
let url_filter = format! ( " {} /filter " , url_default ) ;
2020-09-07 17:05:23 -07:00
// Write a configuration that has tracing endpoint_addr option set
let mut config = default_test_config ( ) ? ;
config . tracing . endpoint_addr = Some ( endpoint . parse ( ) . unwrap ( ) ) ;
2022-01-14 07:11:23 -08:00
let dir = testdir ( ) ? . with_config ( & mut config ) ? ;
2022-04-19 03:28:52 -07:00
let child = dir . spawn_child ( args! [ " start " ] ) ? ;
2020-09-07 17:05:23 -07:00
2020-12-15 01:02:30 -08:00
// Run `zebrad` for a few seconds before testing the endpoint
// Since we're an async function, we have to use a sleep future, not thread sleep.
tokio ::time ::sleep ( LAUNCH_DELAY ) . await ;
2020-09-07 17:05:23 -07:00
// Create an http client
let client = Client ::new ( ) ;
// Test tracing endpoint
2020-12-14 23:33:37 -08:00
let res = client
. get ( url_default . try_into ( ) . expect ( " url_default is valid " ) )
2021-02-18 12:46:27 -08:00
. await ;
let ( res , child ) = child . kill_on_error ( res ) ? ;
2020-09-07 17:05:23 -07:00
assert! ( res . status ( ) . is_success ( ) ) ;
2021-02-18 12:46:27 -08:00
let body = hyper ::body ::to_bytes ( res ) . await ;
let ( body , child ) = child . kill_on_error ( body ) ? ;
2020-09-07 17:05:23 -07:00
// Set a filter and make sure it was changed
2020-12-14 23:33:37 -08:00
let request = Request ::post ( url_filter . clone ( ) )
2020-09-07 17:05:23 -07:00
. body ( Body ::from ( " zebrad=debug " ) )
. unwrap ( ) ;
2021-02-18 12:46:27 -08:00
let post = client . request ( request ) . await ;
let ( _post , child ) = child . kill_on_error ( post ) ? ;
2020-09-07 17:05:23 -07:00
2020-12-14 23:33:37 -08:00
let tracing_res = client
. get ( url_filter . try_into ( ) . expect ( " url_filter is valid " ) )
2021-02-18 12:46:27 -08:00
. await ;
let ( tracing_res , child ) = child . kill_on_error ( tracing_res ) ? ;
2020-09-07 17:05:23 -07:00
assert! ( tracing_res . status ( ) . is_success ( ) ) ;
2021-02-18 12:46:27 -08:00
let tracing_body = hyper ::body ::to_bytes ( tracing_res ) . await ;
let ( tracing_body , mut child ) = child . kill_on_error ( tracing_body ) ? ;
2020-09-07 17:05:23 -07:00
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
// Make sure tracing endpoint was started
2021-06-03 19:28:43 -07:00
output . stdout_line_contains ( format! ( " Opened tracing endpoint at {} " , endpoint ) . as_str ( ) ) ? ;
2021-06-03 15:48:40 -07:00
// TODO: Match some trace level messages from output
2020-09-07 17:05:23 -07:00
2021-06-03 19:28:43 -07:00
// Make sure the endpoint header is correct
// The header is split over two lines. But we don't want to require line
// breaks at a specific word, so we run two checks for different substrings.
output . any_output_line_contains (
" HTTP endpoint allows dynamic control of the filter " ,
& body ,
" tracing filter endpoint response " ,
" the tracing response header " ,
) ? ;
output . any_output_line_contains (
" tracing events " ,
& body ,
" tracing filter endpoint response " ,
" the tracing response header " ,
) ? ;
std ::str ::from_utf8 ( & body ) . expect ( " unexpected invalid UTF-8 in tracing filter response " ) ;
// Make sure endpoint requests change the filter
output . any_output_line_contains (
" zebrad=debug " ,
& tracing_body ,
" tracing filter endpoint response " ,
" the modified tracing filter " ,
) ? ;
std ::str ::from_utf8 ( & tracing_body )
. expect ( " unexpected invalid UTF-8 in modified tracing filter response " ) ;
2020-09-07 17:05:23 -07:00
// [Note on port conflict](#Note on port conflict)
output
. assert_was_killed ( )
. wrap_err ( " Possible port conflict. Are there other acceptance tests running? " ) ? ;
Ok ( ( ) )
}
2021-01-29 04:36:33 -08:00
2022-03-02 16:39:47 -08:00
#[ tokio::test ]
async fn rpc_endpoint ( ) -> Result < ( ) > {
use hyper ::{ body ::to_bytes , Body , Client , Method , Request } ;
use serde_json ::Value ;
zebra_test ::init ( ) ;
if zebra_test ::net ::zebra_skip_network_tests ( ) {
return Ok ( ( ) ) ;
}
// Write a configuration that has RPC listen_addr set
2022-03-18 09:02:22 -07:00
// [Note on port conflict](#Note on port conflict)
let mut config = random_known_rpc_port_config ( ) ? ;
let url = format! ( " http:// {} " , config . rpc . listen_addr . unwrap ( ) ) ;
2022-03-02 16:39:47 -08:00
let dir = testdir ( ) ? . with_config ( & mut config ) ? ;
2022-04-19 03:28:52 -07:00
let mut child = dir . spawn_child ( args! [ " start " ] ) ? ;
2022-03-02 16:39:47 -08:00
// Wait until port is open.
2022-03-18 09:02:22 -07:00
child . expect_stdout_line_matches (
format! ( " Opened RPC endpoint at {} " , config . rpc . listen_addr . unwrap ( ) ) . as_str ( ) ,
) ? ;
2022-03-02 16:39:47 -08:00
// Create an http client
let client = Client ::new ( ) ;
// Create a request to call `getinfo` RPC method
let req = Request ::builder ( )
. method ( Method ::POST )
. uri ( url )
. header ( " content-type " , " application/json " )
. body ( Body ::from (
r # "{"jsonrpc":"1.0","method":"getinfo","params":[],"id":123}"# ,
) ) ? ;
// Make the call to the RPC endpoint
let res = client . request ( req ) . await ? ;
// Test rpc endpoint response
assert! ( res . status ( ) . is_success ( ) ) ;
let body = to_bytes ( res ) . await ;
let ( body , mut child ) = child . kill_on_error ( body ) ? ;
let parsed : Value = serde_json ::from_slice ( & body ) ? ;
// Check that we have at least 4 characters in the `build` field.
let build = parsed [ " result " ] [ " build " ] . as_str ( ) . unwrap ( ) ;
assert! ( build . len ( ) > 4 , " Got {} " , build ) ;
// Check that the `subversion` field has "Zebra" in it.
let subversion = parsed [ " result " ] [ " subversion " ] . as_str ( ) . unwrap ( ) ;
assert! ( subversion . contains ( " Zebra " ) , " Got {} " , subversion ) ;
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
// [Note on port conflict](#Note on port conflict)
output
. assert_was_killed ( )
. wrap_err ( " Possible port conflict. Are there other acceptance tests running? " ) ? ;
Ok ( ( ) )
}
2022-02-23 03:52:30 -08:00
2022-04-29 12:56:11 -07:00
/// Make sure `lightwalletd` works with Zebra, when both their states are empty.
2022-03-25 05:25:31 -07:00
///
2022-04-29 12:56:11 -07:00
/// This test only runs when the `ZEBRA_TEST_LIGHTWALLETD` env var is set.
2022-03-25 05:25:31 -07:00
///
2022-04-29 12:56:11 -07:00
/// This test doesn't work on Windows, so it is always skipped on that platform.
#[ test ]
#[ cfg(not(target_os = " windows " )) ]
fn lightwalletd_integration ( ) -> Result < ( ) > {
lightwalletd_integration_test ( LaunchWithEmptyState )
}
2022-03-22 18:34:37 -07:00
2022-07-25 15:13:25 -07:00
/// Make sure `zebrad` can sync from peers, but don't actually launch `lightwalletd`.
2022-03-25 05:25:31 -07:00
///
2022-07-25 15:13:25 -07:00
/// This test only runs when the `ZEBRA_CACHED_STATE_DIR` env var is set.
///
/// This test might work on Windows.
#[ test ]
fn zebrad_update_sync ( ) -> Result < ( ) > {
lightwalletd_integration_test ( UpdateZebraCachedStateNoRpc )
}
/// Make sure `lightwalletd` can sync from Zebra, in update sync mode.
2022-03-25 05:25:31 -07:00
///
2022-04-29 12:56:11 -07:00
/// This test only runs when the `ZEBRA_TEST_LIGHTWALLETD`,
/// `ZEBRA_CACHED_STATE_DIR`, and `LIGHTWALLETD_DATA_DIR` env vars are set.
///
/// This test doesn't work on Windows, so it is always skipped on that platform.
#[ test ]
#[ cfg(not(target_os = " windows " )) ]
fn lightwalletd_update_sync ( ) -> Result < ( ) > {
lightwalletd_integration_test ( UpdateCachedState )
}
2022-03-25 05:25:31 -07:00
2022-04-29 12:56:11 -07:00
/// Make sure `lightwalletd` can fully sync from genesis using Zebra.
2022-02-23 03:52:30 -08:00
///
2022-04-29 12:56:11 -07:00
/// This test only runs when the `ZEBRA_TEST_LIGHTWALLETD` and
/// `ZEBRA_CACHED_STATE_DIR` env vars are set.
2022-02-23 20:28:09 -08:00
///
/// This test doesn't work on Windows, so it is always skipped on that platform.
2022-02-23 03:52:30 -08:00
#[ test ]
2022-04-29 12:56:11 -07:00
#[ ignore ]
2022-02-23 03:52:30 -08:00
#[ cfg(not(target_os = " windows " )) ]
2022-04-29 12:56:11 -07:00
fn lightwalletd_full_sync ( ) -> Result < ( ) > {
lightwalletd_integration_test ( FullSyncFromGenesis {
allow_lightwalletd_cached_state : false ,
} )
}
/// Make sure `lightwalletd` can sync from Zebra, in all available modes.
///
/// Runs the tests in this order:
/// - launch lightwalletd with empty states,
2022-06-01 04:36:59 -07:00
/// - if `ZEBRA_CACHED_STATE_DIR` is set:
/// - run a full sync
/// - if `ZEBRA_CACHED_STATE_DIR` and `LIGHTWALLETD_DATA_DIR` are set:
/// - run a quick update sync,
/// - run a send transaction gRPC test,
/// - run read-only gRPC tests.
///
/// The gRPC tests only run when the `lightwalletd-grpc-tests` is on.
2022-04-29 12:56:11 -07:00
///
/// These tests don't work on Windows, so they are always skipped on that platform.
2022-06-01 04:36:59 -07:00
#[ tokio::test ]
2022-04-29 12:56:11 -07:00
#[ ignore ]
#[ cfg(not(target_os = " windows " )) ]
2022-06-01 04:36:59 -07:00
async fn lightwalletd_test_suite ( ) -> Result < ( ) > {
2022-04-29 12:56:11 -07:00
lightwalletd_integration_test ( LaunchWithEmptyState ) ? ;
2022-07-25 15:13:25 -07:00
// Only runs when ZEBRA_CACHED_STATE_DIR is set.
lightwalletd_integration_test ( UpdateZebraCachedStateNoRpc ) ? ;
2022-04-29 12:56:11 -07:00
// Only runs when ZEBRA_CACHED_STATE_DIR is set.
// When manually running the test suite, allow cached state in the full sync test.
lightwalletd_integration_test ( FullSyncFromGenesis {
allow_lightwalletd_cached_state : true ,
} ) ? ;
// Only runs when LIGHTWALLETD_DATA_DIR and ZEBRA_CACHED_STATE_DIR are set
lightwalletd_integration_test ( UpdateCachedState ) ? ;
2022-06-01 04:36:59 -07:00
// Only runs when LIGHTWALLETD_DATA_DIR and ZEBRA_CACHED_STATE_DIR are set,
// and the compile-time gRPC feature is on.
#[ cfg(feature = " lightwalletd-grpc-tests " ) ]
{
common ::lightwalletd ::send_transaction_test ::run ( ) . await ? ;
common ::lightwalletd ::wallet_grpc_test ::run ( ) . await ? ;
}
2022-04-29 12:56:11 -07:00
Ok ( ( ) )
}
/// Run a lightwalletd integration test with a configuration for `test_type`.
///
2022-07-25 15:13:25 -07:00
/// Set `FullSyncFromGenesis { allow_lightwalletd_cached_state: true }` to speed up manual full sync tests.
2022-04-29 12:56:11 -07:00
///
/// The random ports in this test can cause [rare port conflicts.](#Note on port conflict)
fn lightwalletd_integration_test ( test_type : LightwalletdTestType ) -> Result < ( ) > {
2022-02-23 03:52:30 -08:00
zebra_test ::init ( ) ;
2022-03-18 09:02:22 -07:00
// Skip the test unless the user specifically asked for it
2022-07-25 15:13:25 -07:00
//
// 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 ( ) {
2022-02-23 20:28:09 -08:00
return Ok ( ( ) ) ;
}
2022-07-25 15:13:25 -07:00
// TODO: split the zebrad and lightwalletd launches and checks into separate functions?
// Get the zebrad config
2022-02-23 03:52:30 -08:00
2022-04-29 12:56:11 -07:00
// Handle the Zebra state directory based on the test type:
// - LaunchWithEmptyState: ignore the state directory
2022-07-25 15:13:25 -07:00
// - FullSyncFromGenesis, UpdateCachedState, UpdateZebraCachedStateNoRpc:
2022-04-29 12:56:11 -07:00
// skip the test if it is not available, timeout if it is not populated
2022-07-25 15:13:25 -07:00
// Write a configuration that has RPC listen_addr set (if needed).
2022-04-29 12:56:11 -07:00
// If the state path env var is set, use it in the config.
2022-05-04 18:08:27 -07:00
let config = if let Some ( config ) =
test_type . zebrad_config ( " lightwalletd_integration_test " . to_string ( ) )
{
2022-04-29 12:56:11 -07:00
config ?
} else {
return Ok ( ( ) ) ;
} ;
// Handle the lightwalletd state directory based on the test type:
2022-07-25 15:13:25 -07:00
// - LaunchWithEmptyState, UpdateZebraCachedStateNoRpc: ignore the state directory
2022-04-29 12:56:11 -07:00
// - FullSyncFromGenesis: use it if available, timeout if it is already populated
// - UpdateCachedState: skip the test if it is not available, timeout if it is not populated
2022-05-04 18:08:27 -07:00
let lightwalletd_state_path =
test_type . lightwalletd_state_path ( " lightwalletd_integration_test " . to_string ( ) ) ;
2022-02-23 03:52:30 -08:00
2022-04-29 12:56:11 -07:00
if test_type . needs_lightwalletd_cached_state ( ) & & lightwalletd_state_path . is_none ( ) {
return Ok ( ( ) ) ;
}
2022-06-01 04:36:59 -07:00
tracing ::info! (
? test_type ,
? config ,
? lightwalletd_state_path ,
" running lightwalletd & zebrad integration test " ,
) ;
2022-04-29 12:56:11 -07:00
// Get the lists of process failure logs
let ( zebrad_failure_messages , zebrad_ignore_messages ) = test_type . zebrad_failure_messages ( ) ;
// Launch zebrad
let zdir = testdir ( ) ? . with_exact_config ( & config ) ? ;
2022-03-22 18:34:37 -07:00
let mut zebrad = zdir
2022-04-19 03:28:52 -07:00
. spawn_child ( args! [ " start " ] ) ?
2022-04-29 12:56:11 -07:00
. with_timeout ( test_type . zebrad_timeout ( ) )
. with_failure_regex_iter ( zebrad_failure_messages , zebrad_ignore_messages ) ;
if test_type . needs_zebra_cached_state ( ) {
2022-05-31 20:53:51 -07:00
zebrad
. expect_stdout_line_matches ( r "loaded Zebra state cache .*tip.*=.*Height\([0-9]{7}\)" ) ? ;
2022-04-29 12:56:11 -07:00
} else {
// Timeout the test if we're somehow accidentally using a cached state
2022-05-31 20:53:51 -07:00
zebrad . expect_stdout_line_matches ( " loaded Zebra state cache .*tip.*=.*None " ) ? ;
2022-04-29 12:56:11 -07:00
}
2022-02-23 03:52:30 -08:00
2022-07-25 15:13:25 -07:00
// Launch lightwalletd, if needed
let mut lightwalletd = if test_type . launches_lightwalletd ( ) {
// Wait until `zebrad` has opened the RPC endpoint
zebrad . expect_stdout_line_matches ( regex ::escape (
format! ( " Opened RPC endpoint at {} " , config . rpc . listen_addr . unwrap ( ) ) . as_str ( ) ,
) ) ? ;
2022-02-23 03:52:30 -08:00
2022-07-25 15:13:25 -07:00
// Write a fake zcashd configuration that has the rpcbind and rpcport options set
let ldir = testdir ( ) ? ;
let ldir = ldir . with_lightwalletd_config ( config . rpc . listen_addr . unwrap ( ) ) ? ;
2022-04-29 12:56:11 -07:00
2022-07-25 15:13:25 -07:00
let ( lightwalletd_failure_messages , lightwalletd_ignore_messages ) =
test_type . lightwalletd_failure_messages ( ) ;
2022-02-23 03:52:30 -08:00
2022-07-25 15:13:25 -07:00
// Launch the lightwalletd process
let lightwalletd = if test_type = = LaunchWithEmptyState {
ldir . spawn_lightwalletd_child ( None , args! [ ] ) ?
} else {
ldir . spawn_lightwalletd_child ( lightwalletd_state_path , args! [ ] ) ?
} ;
2022-02-23 03:52:30 -08:00
2022-07-25 15:13:25 -07:00
let mut lightwalletd = lightwalletd
. with_timeout ( test_type . lightwalletd_timeout ( ) )
. with_failure_regex_iter ( lightwalletd_failure_messages , lightwalletd_ignore_messages ) ;
2022-02-23 03:52:30 -08:00
2022-07-25 15:13:25 -07:00
// Wait until `lightwalletd` has launched
lightwalletd . expect_stdout_line_matches ( regex ::escape ( " Starting gRPC server " ) ) ? ;
2022-02-23 03:52:30 -08:00
2022-07-25 15:13:25 -07:00
// Check that `lightwalletd` is calling the expected Zebra RPCs
2022-02-23 03:52:30 -08:00
2022-07-25 15:13:25 -07:00
// getblockchaininfo
2022-06-01 04:36:59 -07:00
if test_type . needs_zebra_cached_state ( ) {
2022-07-25 15:13:25 -07:00
lightwalletd . expect_stdout_line_matches (
" Got sapling height 419200 block height [0-9]{7} chain main branchID [0-9a-f]{8} " ,
) ? ;
2022-06-01 04:36:59 -07:00
} else {
2022-07-25 15:13:25 -07:00
// Timeout the test if we're somehow accidentally using a cached state in our temp dir
lightwalletd . expect_stdout_line_matches (
" Got sapling height 419200 block height [0-9]{1,6} chain main branchID 00000000 " ,
) ? ;
}
if test_type . needs_lightwalletd_cached_state ( ) {
lightwalletd . expect_stdout_line_matches ( " Found [0-9]{7} blocks in cache " ) ? ;
} else if ! test_type . allow_lightwalletd_cached_state ( ) {
// Timeout the test if we're somehow accidentally using a cached state in our temp dir
lightwalletd . expect_stdout_line_matches ( " Found 0 blocks in cache " ) ? ;
2022-06-01 04:36:59 -07:00
}
2022-03-03 05:03:06 -08:00
2022-07-25 15:13:25 -07:00
// getblock with the first Sapling block in Zebra's state
//
// zcash/lightwalletd calls getbestblockhash here, but
// adityapk00/lightwalletd calls getblock
//
// The log also depends on what is in Zebra's state:
//
// # Cached Zebra State
//
// lightwalletd ingests blocks into its cache.
//
// # Empty Zebra State
//
// lightwalletd tries to download the Sapling activation block, but it's not in the state.
//
// Until the Sapling activation block has been downloaded,
// lightwalletd will keep retrying getblock.
if ! test_type . allow_lightwalletd_cached_state ( ) {
if test_type . needs_zebra_cached_state ( ) {
lightwalletd . expect_stdout_line_matches (
" ([Aa]dding block to cache)|([Ww]aiting for block) " ,
) ? ;
} else {
lightwalletd . expect_stdout_line_matches ( regex ::escape (
" Waiting for zcashd height to reach Sapling activation height (419200) " ,
) ) ? ;
}
}
Some ( lightwalletd )
} else {
None
} ;
if test_type . needs_zebra_cached_state ( ) {
2022-04-29 12:56:11 -07:00
// Wait for Zebra to sync its cached state to the chain tip
2022-05-31 20:53:51 -07:00
zebrad . expect_stdout_line_matches ( SYNC_FINISHED_REGEX ) ? ;
2022-04-29 12:56:11 -07:00
2022-06-27 12:50:47 -07:00
// Wait for lightwalletd to sync some blocks
2022-07-25 15:13:25 -07:00
if let Some ( ref mut lightwalletd ) = lightwalletd {
lightwalletd
. expect_stdout_line_matches ( " ([Aa]dding block to cache)|([Ww]aiting for block) " ) ? ;
2022-06-27 12:50:47 -07:00
2022-07-25 15:13:25 -07:00
// Wait for lightwalletd to sync to Zebra's tip.
2022-07-07 20:03:07 -07:00
//
2022-07-25 15:13:25 -07:00
// TODO: after the lightwalletd hangs are fixed, fail the test on errors or timeouts
if cfg! ( lightwalletd_hang_fix ) {
lightwalletd . expect_stdout_line_matches ( " [Ww]aiting for block " ) ? ;
} else {
// To work around a hang bug, we run the test until:
// - lightwalletd starts waiting for blocks (best case scenario)
// - lightwalletd syncs to near the tip (workaround, cached state image is usable)
// - the test times out with an error, but we ignore it
// (workaround, cached state might be usable, slow, or might fail other tests)
//
// TODO: update the regex to `1[8-9][0-9]{5}` when mainnet reaches block 1_800_000
let log_result = lightwalletd . expect_stdout_line_matches (
" ([Aa]dding block to cache 1[7-9][0-9]{5})|([Ww]aiting for block) " ,
2022-07-07 20:03:07 -07:00
) ;
2022-07-25 15:13:25 -07:00
if log_result . is_err ( ) {
// This error takes up about 100 lines, and looks like a panic message
tracing ::warn! (
multi_line_error = ? log_result ,
" ignoring a lightwalletd test failure, to work around a lightwalletd hang bug " ,
) ;
}
2022-07-07 20:03:07 -07:00
}
}
2022-04-29 12:56:11 -07:00
// Check Zebra is still at the tip (also clears and prints Zebra's logs)
2022-05-31 20:53:51 -07:00
zebrad . expect_stdout_line_matches ( SYNC_FINISHED_REGEX ) ? ;
2022-04-29 12:56:11 -07:00
// lightwalletd doesn't log anything when we've reached the tip.
// But when it gets near the tip, it starts using the mempool.
2022-06-01 04:36:59 -07:00
//
// adityapk00/lightwalletd logs mempool changes, but zcash/lightwalletd doesn't.
2022-06-27 12:50:47 -07:00
//
// TODO: re-enable this code when lightwalletd hangs are fixed
2022-07-07 20:03:07 -07:00
if cfg! ( lightwalletd_hang_fix ) {
2022-07-25 15:13:25 -07:00
if let Some ( ref mut lightwalletd ) = lightwalletd {
lightwalletd . expect_stdout_line_matches ( regex ::escape (
" Block hash changed, clearing mempool clients " ,
) ) ? ;
lightwalletd
. expect_stdout_line_matches ( regex ::escape ( " Adding new mempool txid " ) ) ? ;
}
2022-06-01 04:36:59 -07:00
}
2022-04-29 12:56:11 -07:00
}
2022-03-11 16:20:17 -08:00
2022-02-23 03:52:30 -08:00
// Cleanup both processes
2022-07-25 15:13:25 -07:00
//
2022-02-23 03:52:30 -08:00
// If the test fails here, see the [note on port conflict](#Note on port conflict)
//
2022-03-03 05:03:06 -08:00
// zcash/lightwalletd exits by itself, but
// adityapk00/lightwalletd keeps on going, so it gets killed by the test harness.
2022-07-25 15:13:25 -07:00
zebrad . kill ( ) ? ;
if let Some ( mut lightwalletd ) = lightwalletd {
lightwalletd . kill ( ) ? ;
let lightwalletd_output = lightwalletd . wait_with_output ( ) ? . assert_failure ( ) ? ;
lightwalletd_output
. assert_was_killed ( )
. wrap_err ( " Possible port conflict. Are there other acceptance tests running? " ) ? ;
}
let zebrad_output = zebrad . wait_with_output ( ) ? . assert_failure ( ) ? ;
2022-03-18 09:02:22 -07:00
2022-02-23 03:52:30 -08:00
zebrad_output
. assert_was_killed ( )
. wrap_err ( " Possible port conflict. Are there other acceptance tests running? " ) ? ;
Ok ( ( ) )
}
2021-01-29 04:36:33 -08:00
/// Test will start 2 zebrad nodes one after the other using the same Zcash listener.
/// It is expected that the first node spawned will get exclusive use of the port.
/// The second node will panic with the Zcash listener conflict hint added in #1535.
#[ test ]
2021-02-15 11:52:30 -08:00
fn zebra_zcash_listener_conflict ( ) -> Result < ( ) > {
2021-01-29 04:36:33 -08:00
zebra_test ::init ( ) ;
// [Note on port conflict](#Note on port conflict)
let port = random_known_port ( ) ;
let listen_addr = format! ( " 127.0.0.1: {} " , port ) ;
// Write a configuration that has our created network listen_addr
let mut config = default_test_config ( ) ? ;
config . network . listen_addr = listen_addr . parse ( ) . unwrap ( ) ;
2022-01-14 07:11:23 -08:00
let dir1 = testdir ( ) ? . with_config ( & mut config ) ? ;
2021-06-03 19:28:43 -07:00
let regex1 = regex ::escape ( & format! (
" Opened Zcash protocol endpoint at {} " ,
listen_addr
) ) ;
2021-01-29 04:36:33 -08:00
// From another folder create a configuration with the same listener.
// `network.listen_addr` will be the same in the 2 nodes.
// (But since the config is ephemeral, they will have different state paths.)
2022-01-14 07:11:23 -08:00
let dir2 = testdir ( ) ? . with_config ( & mut config ) ? ;
2021-01-29 04:36:33 -08:00
check_config_conflict ( dir1 , regex1 . as_str ( ) , dir2 , PORT_IN_USE_ERROR . as_str ( ) ) ? ;
Ok ( ( ) )
}
/// Start 2 zebrad nodes using the same metrics listener port, but different
/// state directories and Zcash listener ports. The first node should get
/// exclusive use of the port. The second node will panic with the Zcash metrics
/// conflict hint added in #1535.
#[ test ]
2022-06-16 12:56:40 -07:00
#[ cfg(feature = " prometheus " ) ]
2021-02-15 11:52:30 -08:00
fn zebra_metrics_conflict ( ) -> Result < ( ) > {
2021-01-29 04:36:33 -08:00
zebra_test ::init ( ) ;
// [Note on port conflict](#Note on port conflict)
let port = random_known_port ( ) ;
let listen_addr = format! ( " 127.0.0.1: {} " , port ) ;
// Write a configuration that has our created metrics endpoint_addr
let mut config = default_test_config ( ) ? ;
config . metrics . endpoint_addr = Some ( listen_addr . parse ( ) . unwrap ( ) ) ;
2022-01-14 07:11:23 -08:00
let dir1 = testdir ( ) ? . with_config ( & mut config ) ? ;
2021-06-03 19:28:43 -07:00
let regex1 = regex ::escape ( & format! ( r "Opened metrics endpoint at {}" , listen_addr ) ) ;
2021-01-29 04:36:33 -08:00
// From another folder create a configuration with the same endpoint.
// `metrics.endpoint_addr` will be the same in the 2 nodes.
// But they will have different Zcash listeners (auto port) and states (ephemeral)
2022-01-14 07:11:23 -08:00
let dir2 = testdir ( ) ? . with_config ( & mut config ) ? ;
2021-01-29 04:36:33 -08:00
check_config_conflict ( dir1 , regex1 . as_str ( ) , dir2 , PORT_IN_USE_ERROR . as_str ( ) ) ? ;
Ok ( ( ) )
}
/// Start 2 zebrad nodes using the same tracing listener port, but different
/// state directories and Zcash listener ports. The first node should get
/// exclusive use of the port. The second node will panic with the Zcash tracing
/// conflict hint added in #1535.
#[ test ]
2022-06-16 12:56:40 -07:00
#[ cfg(feature = " filter-reload " ) ]
2021-02-15 11:52:30 -08:00
fn zebra_tracing_conflict ( ) -> Result < ( ) > {
2021-01-29 04:36:33 -08:00
zebra_test ::init ( ) ;
// [Note on port conflict](#Note on port conflict)
let port = random_known_port ( ) ;
let listen_addr = format! ( " 127.0.0.1: {} " , port ) ;
// Write a configuration that has our created tracing endpoint_addr
let mut config = default_test_config ( ) ? ;
config . tracing . endpoint_addr = Some ( listen_addr . parse ( ) . unwrap ( ) ) ;
2022-01-14 07:11:23 -08:00
let dir1 = testdir ( ) ? . with_config ( & mut config ) ? ;
2021-06-03 19:28:43 -07:00
let regex1 = regex ::escape ( & format! ( r "Opened tracing endpoint at {}" , listen_addr ) ) ;
2021-01-29 04:36:33 -08:00
// From another folder create a configuration with the same endpoint.
// `tracing.endpoint_addr` will be the same in the 2 nodes.
// But they will have different Zcash listeners (auto port) and states (ephemeral)
2022-01-14 07:11:23 -08:00
let dir2 = testdir ( ) ? . with_config ( & mut config ) ? ;
2021-01-29 04:36:33 -08:00
check_config_conflict ( dir1 , regex1 . as_str ( ) , dir2 , PORT_IN_USE_ERROR . as_str ( ) ) ? ;
Ok ( ( ) )
}
2022-03-02 16:39:47 -08:00
/// Start 2 zebrad nodes using the same RPC listener port, but different
/// state directories and Zcash listener ports. The first node should get
/// exclusive use of the port. The second node will panic.
2022-06-14 17:31:18 -07:00
///
/// This test is sometimes unreliable on Windows, and hangs on macOS.
/// We believe this is a CI infrastructure issue, not a platform-specific issue.
2022-03-02 16:39:47 -08:00
#[ test ]
2022-06-14 17:31:18 -07:00
#[ cfg(not(any(target_os = " windows " , target_os = " macos " ))) ]
2022-03-02 16:39:47 -08:00
fn zebra_rpc_conflict ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2022-03-03 23:01:41 -08:00
if zebra_test ::net ::zebra_skip_network_tests ( ) {
return Ok ( ( ) ) ;
}
2022-03-18 09:02:22 -07:00
// Write a configuration that has RPC listen_addr set
2022-03-02 16:39:47 -08:00
// [Note on port conflict](#Note on port conflict)
2022-03-18 09:02:22 -07:00
let mut config = random_known_rpc_port_config ( ) ? ;
2022-03-02 16:39:47 -08:00
let dir1 = testdir ( ) ? . with_config ( & mut config ) ? ;
2022-03-18 09:02:22 -07:00
let regex1 = regex ::escape ( & format! (
r "Opened RPC endpoint at {}" ,
config . rpc . listen_addr . unwrap ( ) ,
) ) ;
2022-03-02 16:39:47 -08:00
// From another folder create a configuration with the same endpoint.
// `rpc.listen_addr` will be the same in the 2 nodes.
// But they will have different Zcash listeners (auto port) and states (ephemeral)
let dir2 = testdir ( ) ? . with_config ( & mut config ) ? ;
check_config_conflict ( dir1 , regex1 . as_str ( ) , dir2 , " Unable to start RPC server " ) ? ;
Ok ( ( ) )
}
2021-01-29 04:36:33 -08:00
/// Start 2 zebrad nodes using the same state directory, but different Zcash
/// listener ports. The first node should get exclusive access to the database.
/// The second node will panic with the Zcash state conflict hint added in #1535.
#[ test ]
2021-02-15 11:52:30 -08:00
fn zebra_state_conflict ( ) -> Result < ( ) > {
2021-01-29 04:36:33 -08:00
zebra_test ::init ( ) ;
// A persistent config has a fixed temp state directory, but asks the OS to
// automatically choose an unused port
let mut config = persistent_test_config ( ) ? ;
2022-01-14 07:11:23 -08:00
let dir_conflict = testdir ( ) ? . with_config ( & mut config ) ? ;
2021-01-29 04:36:33 -08:00
// Windows problems with this match will be worked on at #1654
// We are matching the whole opened path only for unix by now.
2021-06-03 19:28:43 -07:00
let contains = if cfg! ( unix ) {
2021-01-29 04:36:33 -08:00
let mut dir_conflict_full = PathBuf ::new ( ) ;
dir_conflict_full . push ( dir_conflict . path ( ) ) ;
dir_conflict_full . push ( " state " ) ;
dir_conflict_full . push ( format! (
" v{} " ,
zebra_state ::constants ::DATABASE_FORMAT_VERSION
) ) ;
dir_conflict_full . push ( config . network . network . to_string ( ) . to_lowercase ( ) ) ;
format! (
" Opened Zebra state cache at {} " ,
dir_conflict_full . display ( )
)
} else {
String ::from ( " Opened Zebra state cache at " )
} ;
check_config_conflict (
dir_conflict . path ( ) ,
2021-06-03 19:28:43 -07:00
regex ::escape ( & contains ) . as_str ( ) ,
2021-01-29 04:36:33 -08:00
dir_conflict . path ( ) ,
LOCK_FILE_ERROR . as_str ( ) ,
) ? ;
Ok ( ( ) )
}
/// Launch a node in `first_dir`, wait a few seconds, then launch a node in
/// `second_dir`. Check that the first node's stdout contains
/// `first_stdout_regex`, and the second node's stderr contains
/// `second_stderr_regex`.
fn check_config_conflict < T , U > (
first_dir : T ,
first_stdout_regex : & str ,
second_dir : U ,
second_stderr_regex : & str ,
) -> Result < ( ) >
where
T : ZebradTestDirExt ,
U : ZebradTestDirExt ,
{
// Start the first node
2022-04-19 03:28:52 -07:00
let mut node1 = first_dir . spawn_child ( args! [ " start " ] ) ? ;
2021-01-29 04:36:33 -08:00
2022-02-15 07:30:10 -08:00
// Wait until node1 has used the conflicting resource.
node1 . expect_stdout_line_matches ( first_stdout_regex ) ? ;
2021-01-29 04:36:33 -08:00
2022-03-02 16:39:47 -08:00
// Wait a bit before launching the second node.
std ::thread ::sleep ( BETWEEN_NODES_DELAY ) ;
2021-01-29 04:36:33 -08:00
// Spawn the second node
2022-04-19 03:28:52 -07:00
let node2 = second_dir . spawn_child ( args! [ " start " ] ) ;
2021-02-18 12:46:27 -08:00
let ( node2 , mut node1 ) = node1 . kill_on_error ( node2 ) ? ;
2021-01-29 04:36:33 -08:00
// Wait a few seconds and kill first node.
// Second node is terminated by panic, no need to kill.
std ::thread ::sleep ( LAUNCH_DELAY ) ;
2021-02-18 12:46:27 -08:00
let node1_kill_res = node1 . kill ( ) ;
2022-02-15 07:30:10 -08:00
let ( _ , mut node2 ) = node2 . kill_on_error ( node1_kill_res ) ? ;
2021-02-18 12:46:27 -08:00
2021-02-18 22:02:48 -08:00
// node2 should have panicked due to a conflict. Kill it here anyway, so it
// doesn't outlive the test on error.
//
2021-02-19 01:38:18 -08:00
// This code doesn't work on Windows or macOS. It's cleanup code that only
// runs when node2 doesn't panic as expected. So it's ok to skip it.
// See #1781.
#[ cfg(target_os = " linux " ) ]
2021-02-18 15:57:09 -08:00
if node2 . is_running ( ) {
return node2
2021-02-18 22:02:48 -08:00
. kill_on_error ::< ( ) , _ > ( Err ( eyre! (
" conflicted node2 was still running, but the test expected a panic "
) ) )
2022-02-15 07:30:10 -08:00
. context_from ( & mut node1 )
2021-02-18 15:57:09 -08:00
. map ( | _ | ( ) ) ;
}
2022-02-15 07:30:10 -08:00
2021-02-18 15:57:09 -08:00
// Now we're sure both nodes are dead, and we have both their outputs
2022-02-15 07:30:10 -08:00
let output1 = node1 . wait_with_output ( ) . context_from ( & mut node2 ) ? ;
2021-02-18 15:57:09 -08:00
let output2 = node2 . wait_with_output ( ) . context_from ( & output1 ) ? ;
2022-02-15 07:30:10 -08:00
// Make sure the first node was killed, rather than exiting with an error.
2021-02-18 15:57:09 -08:00
output1
. assert_was_killed ( )
. warning ( " Possible port conflict. Are there other acceptance tests running? " )
. context_from ( & output2 ) ? ;
2021-01-29 04:36:33 -08:00
2022-02-15 07:30:10 -08:00
// Make sure node2 has the expected resource conflict.
2021-02-18 15:57:09 -08:00
output2
2021-06-03 19:28:43 -07:00
. stderr_line_matches ( second_stderr_regex )
2021-02-18 15:57:09 -08:00
. context_from ( & output1 ) ? ;
2021-01-29 04:36:33 -08:00
output2
. assert_was_not_killed ( )
2021-02-18 15:57:09 -08:00
. warning ( " Possible port conflict. Are there other acceptance tests running? " )
. context_from ( & output1 ) ? ;
2021-01-29 04:36:33 -08:00
Ok ( ( ) )
}
2022-04-25 22:32:27 -07:00
#[ tokio::test ]
#[ ignore ]
async fn fully_synced_rpc_test ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2022-04-29 12:56:11 -07:00
// We're only using cached Zebra state here, so this test type is the most similar
let test_type = LightwalletdTestType ::FullSyncFromGenesis {
allow_lightwalletd_cached_state : false ,
} ;
// Handle the Zebra state directory
2022-05-04 18:08:27 -07:00
let cached_state_path = test_type . zebrad_state_path ( " fully_synced_rpc_test " . to_string ( ) ) ;
2022-04-29 12:56:11 -07:00
if cached_state_path . is_none ( ) {
return Ok ( ( ) ) ;
2022-04-25 22:32:27 -07:00
} ;
2022-04-29 12:56:11 -07:00
tracing ::info! ( " running fully synced zebrad RPC test " ) ;
2022-04-25 22:32:27 -07:00
let network = Network ::Mainnet ;
2022-05-04 21:44:14 -07:00
let ( _zebrad , zebra_rpc_address ) =
spawn_zebrad_for_rpc_without_initial_peers ( network , cached_state_path . unwrap ( ) , test_type ) ? ;
2022-04-25 22:32:27 -07:00
// Make a getblock test that works only on synced node (high block number).
// The block is before the mandatory checkpoint, so the checkpoint cached state can be used
// if desired.
let client = reqwest ::Client ::new ( ) ;
let res = client
. post ( format! ( " http:// {} " , & zebra_rpc_address . to_string ( ) ) )
// Manually constructed request to avoid encoding it, for simplicity
. body ( r # "{"jsonrpc": "2.0", "method": "getblock", "params": ["1180900", 0], "id":123 }"# )
. header ( " Content-Type " , " application/json " )
. send ( )
. await ?
. text ( )
. await ? ;
// Simple textual check to avoid fully parsing the response, for simplicity
let expected_bytes = zebra_test ::vectors ::MAINNET_BLOCKS
. get ( & 1_180_900 )
. expect ( " test block must exist " ) ;
let expected_hex = hex ::encode ( expected_bytes ) ;
assert! (
res . contains ( & expected_hex ) ,
" response did not contain the desired block: {} " ,
res
) ;
Ok ( ( ) )
}
2022-06-20 17:59:51 -07:00
#[ tokio::test ]
async fn delete_old_databases ( ) -> Result < ( ) > {
use std ::fs ::{ canonicalize , create_dir } ;
zebra_test ::init ( ) ;
let mut config = default_test_config ( ) ? ;
let run_dir = testdir ( ) ? ;
let cache_dir = run_dir . path ( ) . join ( " state " ) ;
// create cache dir
create_dir ( cache_dir . clone ( ) ) ? ;
// create a v1 dir outside cache dir that should not be deleted
let outside_dir = run_dir . path ( ) . join ( " v1 " ) ;
create_dir ( & outside_dir ) ? ;
assert! ( outside_dir . as_path ( ) . exists ( ) ) ;
// create a `v1` dir inside cache dir that should be deleted
let inside_dir = cache_dir . join ( " v1 " ) ;
create_dir ( & inside_dir ) ? ;
let canonicalized_inside_dir = canonicalize ( inside_dir . clone ( ) ) . ok ( ) . unwrap ( ) ;
assert! ( inside_dir . as_path ( ) . exists ( ) ) ;
// modify config with our cache dir and not ephemeral configuration
// (delete old databases function will not run when ephemeral = true)
config . state . cache_dir = cache_dir ;
config . state . ephemeral = false ;
// run zebra with our config
let mut child = run_dir
. with_config ( & mut config ) ?
. spawn_child ( args! [ " start " ] ) ? ;
// delete checker running
child . expect_stdout_line_matches ( " checking for old database versions " . to_string ( ) ) ? ;
// inside dir was deleted
child . expect_stdout_line_matches ( format! (
" deleted outdated state directory deleted_state={:?} " ,
canonicalized_inside_dir
) ) ? ;
assert! ( ! inside_dir . as_path ( ) . exists ( ) ) ;
// deleting old databases task ended
child . expect_stdout_line_matches ( " finished old database version cleanup task " . to_string ( ) ) ? ;
// outside dir was not deleted
assert! ( outside_dir . as_path ( ) . exists ( ) ) ;
// finish
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
// [Note on port conflict](#Note on port conflict)
output
. assert_was_killed ( )
. wrap_err ( " Possible port conflict. Are there other acceptance tests running? " ) ? ;
Ok ( ( ) )
}
2022-04-27 16:06:11 -07:00
/// Test sending transactions using a lightwalletd instance connected to a zebrad instance.
2022-04-25 22:32:27 -07:00
///
2022-04-27 16:06:11 -07:00
/// See [`common::lightwalletd::send_transaction_test`] for more information.
2022-06-01 04:36:59 -07:00
///
/// This test doesn't work on Windows, so it is always skipped on that platform.
2022-05-11 07:06:58 -07:00
#[ cfg(feature = " lightwalletd-grpc-tests " ) ]
2022-04-27 16:06:11 -07:00
#[ tokio::test ]
2022-05-05 22:30:38 -07:00
#[ ignore ]
2022-06-01 04:36:59 -07:00
#[ cfg(not(target_os = " windows " )) ]
2022-04-27 16:06:11 -07:00
async fn sending_transactions_using_lightwalletd ( ) -> Result < ( ) > {
common ::lightwalletd ::send_transaction_test ::run ( ) . await
2022-04-25 22:32:27 -07:00
}
2022-05-03 21:00:46 -07:00
/// Test all the rpc methods a wallet connected to lightwalletd can call.
///
/// See [`common::lightwalletd::wallet_grpc_test`] for more information.
2022-06-01 04:36:59 -07:00
///
/// This test doesn't work on Windows, so it is always skipped on that platform.
2022-05-11 07:06:58 -07:00
#[ cfg(feature = " lightwalletd-grpc-tests " ) ]
2022-05-03 21:00:46 -07:00
#[ tokio::test ]
2022-05-11 07:06:58 -07:00
#[ ignore ]
2022-06-01 04:36:59 -07:00
#[ cfg(not(target_os = " windows " )) ]
2022-05-03 21:00:46 -07:00
async fn lightwalletd_wallet_grpc_tests ( ) -> Result < ( ) > {
common ::lightwalletd ::wallet_grpc_test ::run ( ) . await
}