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-07-31 23:15:26 -07:00
#![ warn(warnings, missing_docs, trivial_casts, unused_qualifications) ]
2019-08-29 14:46:54 -07:00
#![ forbid(unsafe_code) ]
2020-07-31 23:15:26 -07:00
use color_eyre ::eyre ::Result ;
2020-08-22 16:45:03 -07:00
use std ::{ fs , io ::Write , path ::PathBuf , time ::Duration } ;
use tempdir ::TempDir ;
2020-07-31 23:15:26 -07:00
use zebra_test ::prelude ::* ;
2020-08-22 16:45:03 -07:00
use zebrad ::config ::ZebradConfig ;
pub fn tempdir ( create_config : bool ) -> Result < ( PathBuf , impl Drop ) > {
let dir = TempDir ::new ( " zebrad_tests " ) ? ;
if create_config {
let cache_dir = dir . path ( ) . join ( " state " ) ;
fs ::create_dir ( & cache_dir ) ? ;
let mut config = ZebradConfig ::default ( ) ;
config . state . cache_dir = cache_dir ;
config . state . memory_cache_bytes = 256000000 ;
config . network . listen_addr = " 127.0.0.1:0 " . parse ( ) ? ;
fs ::File ::create ( dir . path ( ) . join ( " zebrad.toml " ) ) ?
. write_all ( toml ::to_string ( & config ) ? . as_bytes ( ) ) ? ;
}
Ok ( ( dir . path ( ) . to_path_buf ( ) , dir ) )
}
2020-07-31 23:15:26 -07:00
2020-08-13 13:31:13 -07:00
pub fn get_child ( args : & [ & str ] , tempdir : & PathBuf ) -> Result < TestChild > {
let mut cmd = test_cmd ( env! ( " CARGO_BIN_EXE_zebrad " ) , & tempdir ) ? ;
Ok ( cmd
. args ( args )
. stdout ( Stdio ::piped ( ) )
. stderr ( Stdio ::piped ( ) )
. spawn2 ( )
. unwrap ( ) )
2020-07-31 23:15:26 -07:00
}
#[ test ]
fn generate_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " generate " ] , & tempdir ) ? ;
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
2020-07-31 23:15:26 -07:00
output . stdout_contains ( r "# Default configuration for zebrad." ) ? ;
Ok ( ( ) )
}
#[ test ]
fn generate_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( false ) ? ;
2020-07-31 23:15:26 -07:00
// unexpected free argument `argument`
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " generate " , " argument " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// unrecognized option `-f`
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " generate " , " -f " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// missing argument to option `-o`
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " generate " , " -o " ] , & tempdir ) ? ;
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
let mut generated_config_path = tempdir . clone ( ) ;
generated_config_path . push ( " zebrad.toml " ) ;
2020-07-31 23:15:26 -07:00
// Valid
2020-08-13 13:31:13 -07:00
let child = get_child (
& [ " generate " , " -o " , generated_config_path . to_str ( ) . unwrap ( ) ] ,
2020-08-14 16:38:32 -07:00
& tempdir ,
2020-08-13 13:31:13 -07:00
) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_success ( ) ? ;
2019-08-29 14:46:54 -07:00
2020-08-13 13:31:13 -07:00
// Check if the temp dir still exist
assert! ( tempdir . exists ( ) ) ;
// Check if the file was created
assert! ( generated_config_path . exists ( ) ) ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
}
#[ test ]
fn help_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " help " ] , & tempdir ) ? ;
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 haves the version
output . stdout_contains ( r "zebrad [0-9].[0-9].[0-9]" ) ? ;
// Make sure we are in help by looking usage string
2020-07-31 23:15:26 -07:00
output . stdout_contains ( r "USAGE:" ) ? ;
Ok ( ( ) )
}
#[ test ]
fn help_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
// The subcommand "argument" wasn't recognized.
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " help " , " argument " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// option `-f` does not accept an argument
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " help " , " -f " ] , & tempdir ) ? ;
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
#[ test ]
2020-07-31 23:15:26 -07:00
fn revhex_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
// Valid
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " revhex " , " 33eeff55 " ] , & tempdir ) ? ;
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
output . stdout_equals ( " 55ffee33 \n " ) ? ;
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 seed_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
2020-08-13 13:31:13 -07:00
let mut child = get_child ( & [ " -v " , " seed " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
// Run the program and kill it at 1 second
std ::thread ::sleep ( Duration ::from_secs ( 1 ) ) ;
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
output . stdout_contains ( r "Starting zebrad in seed mode" ) ? ;
2020-08-04 13:38:39 -07:00
// Make sure the command was killed
assert! ( output . was_killed ( ) ) ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
}
#[ test ]
fn seed_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
// unexpected free argument `argument`
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " seed " , " argument " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// unrecognized option `-f`
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " seed " , " -f " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// unexpected free argument `start`
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " seed " , " start " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
Ok ( ( ) )
}
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-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
2020-08-13 13:31:13 -07:00
let mut child = get_child ( & [ " -v " , " start " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
// Run the program and kill it at 1 second
std ::thread ::sleep ( Duration ::from_secs ( 1 ) ) ;
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
2020-08-20 03:52:15 -07:00
// start is the default mode, so we check for end of line, to distinguish it
// from seed
output . stdout_contains ( r "Starting zebrad$" ) ? ;
2020-07-31 23:15:26 -07:00
2020-08-04 13:38:39 -07:00
// Make sure the command was killed
assert! ( output . was_killed ( ) ) ;
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-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
// Any free argument is valid
2020-08-13 13:31:13 -07:00
let mut child = get_child ( & [ " start " , " argument " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
// Run the program and kill it at 1 second
std ::thread ::sleep ( Duration ::from_secs ( 1 ) ) ;
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
2020-08-04 13:38:39 -07:00
// Make sure the command was killed
assert! ( output . was_killed ( ) ) ;
2020-07-31 23:15:26 -07:00
output . assert_failure ( ) ? ;
// unrecognized option `-f`
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " start " , " -f " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
Ok ( ( ) )
}
#[ test ]
fn app_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
let output = output . assert_success ( ) ? ;
output . stdout_contains ( r "USAGE:" ) ? ;
Ok ( ( ) )
}
#[ test ]
fn version_no_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " version " ] , & tempdir ) ? ;
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
output . stdout_matches ( r "^zebrad [0-9].[0-9].[0-9]-[A-Za-z]*.[0-9]\n$" ) ? ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
}
#[ test ]
fn version_args ( ) -> Result < ( ) > {
zebra_test ::init ( ) ;
2020-08-13 13:31:13 -07:00
let ( tempdir , _guard ) = tempdir ( true ) ? ;
2020-07-31 23:15:26 -07:00
// unexpected free argument `argument`
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " version " , " argument " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
// unrecognized option `-f`
2020-08-13 13:31:13 -07:00
let child = get_child ( & [ " version " , " -f " ] , & tempdir ) ? ;
2020-07-31 23:15:26 -07:00
let output = child . wait_with_output ( ) ? ;
output . assert_failure ( ) ? ;
Ok ( ( ) )
}
#[ test ]
2020-08-20 03:49:38 -07:00
fn valid_generated_config_test ( ) -> Result < ( ) > {
// 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-08-20 03:52:15 -07:00
valid_generated_config ( " start " , r "Starting zebrad$" ) ? ;
2020-08-20 03:49:38 -07:00
valid_generated_config ( " seed " , r "Starting zebrad in seed mode" ) ? ;
Ok ( ( ) )
}
fn valid_generated_config ( command : & str , expected_output : & str ) -> Result < ( ) > {
2020-08-13 13:31:13 -07:00
zebra_test ::init ( ) ;
let ( tempdir , _guard ) = tempdir ( false ) ? ;
// Add a config file name to tempdir path
let mut generated_config_path = tempdir . clone ( ) ;
generated_config_path . push ( " zebrad.toml " ) ;
// Generate configuration in temp dir path
let child = get_child (
& [ " generate " , " -o " , generated_config_path . to_str ( ) . unwrap ( ) ] ,
2020-08-14 16:38:32 -07:00
& tempdir ,
2020-08-13 13:31:13 -07:00
) ? ;
let output = child . wait_with_output ( ) ? ;
output . assert_success ( ) ? ;
// Check if the file was created
assert! ( generated_config_path . exists ( ) ) ;
2020-08-20 03:49:38 -07:00
// Run command using temp dir and kill it at 1 second
2020-08-13 13:31:13 -07:00
let mut child = get_child (
2020-08-20 03:49:38 -07:00
& [ " -c " , generated_config_path . to_str ( ) . unwrap ( ) , command ] ,
2020-08-14 16:38:32 -07:00
& tempdir ,
2020-08-13 13:31:13 -07:00
) ? ;
std ::thread ::sleep ( Duration ::from_secs ( 1 ) ) ;
child . kill ( ) ? ;
let output = child . wait_with_output ( ) ? ;
let output = output . assert_failure ( ) ? ;
2020-08-20 03:49:38 -07:00
output . stdout_contains ( expected_output ) ? ;
2020-08-13 13:31:13 -07:00
2020-08-20 03:39:10 -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.
assert! ( output . was_killed ( ) , " Expected zebrad with generated config to succeed. Are there other acceptance test, zebrad, or zcashd processes running? " ) ;
2020-08-13 13:31:13 -07:00
2020-08-20 03:49:38 -07:00
// Check if the temp dir still exists
2020-08-13 13:31:13 -07:00
assert! ( tempdir . exists ( ) ) ;
2020-08-20 03:49:38 -07:00
// Check if the created config file still exists
2020-08-13 13:31:13 -07:00
assert! ( generated_config_path . exists ( ) ) ;
2020-07-31 23:15:26 -07:00
Ok ( ( ) )
2019-08-29 14:46:54 -07:00
}