moves EntryPoint to submodule and adds a test
This commit is contained in:
parent
6927d83b24
commit
f06f245ece
|
@ -1,25 +1,22 @@
|
||||||
//! Zebrad Abscissa Application
|
//! Zebrad Abscissa Application
|
||||||
|
|
||||||
use std::{fmt::Write as _, io::Write as _, path::PathBuf, process};
|
mod entry_point;
|
||||||
|
use self::entry_point::EntryPoint;
|
||||||
|
|
||||||
|
use std::{fmt::Write as _, io::Write as _, process};
|
||||||
|
|
||||||
use abscissa_core::{
|
use abscissa_core::{
|
||||||
application::{self, fatal_error, AppCell},
|
application::{self, fatal_error, AppCell},
|
||||||
command::{Command, Usage},
|
|
||||||
config::{self, Configurable},
|
config::{self, Configurable},
|
||||||
status_err,
|
status_err,
|
||||||
terminal::{component::Terminal, stderr, stdout, ColorChoice},
|
terminal::{component::Terminal, stderr, stdout, ColorChoice},
|
||||||
Application, Component, FrameworkError, Options, Runnable, Shutdown, StandardPaths,
|
Application, Component, FrameworkError, Shutdown, StandardPaths, Version,
|
||||||
Version,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use zebra_network::constants::PORT_IN_USE_ERROR;
|
use zebra_network::constants::PORT_IN_USE_ERROR;
|
||||||
use zebra_state::constants::{DATABASE_FORMAT_VERSION, LOCK_FILE_ERROR};
|
use zebra_state::constants::{DATABASE_FORMAT_VERSION, LOCK_FILE_ERROR};
|
||||||
|
|
||||||
use crate::{
|
use crate::{commands::ZebradCmd, components::tracing::Tracing, config::ZebradConfig};
|
||||||
commands::{StartCmd, ZebradCmd},
|
|
||||||
components::tracing::Tracing,
|
|
||||||
config::ZebradConfig,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Application state
|
/// Application state
|
||||||
pub static APPLICATION: AppCell<ZebradApp> = AppCell::new();
|
pub static APPLICATION: AppCell<ZebradApp> = AppCell::new();
|
||||||
|
@ -43,98 +40,6 @@ pub fn app_config() -> config::Reader<ZebradApp> {
|
||||||
config::Reader::new(&APPLICATION)
|
config::Reader::new(&APPLICATION)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Toplevel entrypoint command.
|
|
||||||
///
|
|
||||||
/// Handles obtaining toplevel help as well as verbosity settings.
|
|
||||||
#[derive(Debug, Options)]
|
|
||||||
pub struct EntryPoint {
|
|
||||||
#[options(help = "tracing filters which override the zebrad.toml config")]
|
|
||||||
filters: Vec<String>,
|
|
||||||
|
|
||||||
/// Path to the configuration file
|
|
||||||
#[options(short = "c", help = "path to configuration file")]
|
|
||||||
pub config: Option<PathBuf>,
|
|
||||||
|
|
||||||
/// Obtain help about the current command
|
|
||||||
#[options(short = "h", help = "print help message")]
|
|
||||||
pub help: bool,
|
|
||||||
|
|
||||||
/// Increase verbosity setting
|
|
||||||
#[options(short = "v", help = "be verbose")]
|
|
||||||
pub verbose: bool,
|
|
||||||
|
|
||||||
/// Subcommand to execute.
|
|
||||||
///
|
|
||||||
/// The `command` option will delegate option parsing to the command type,
|
|
||||||
/// starting at the first free argument. Defaults to start.
|
|
||||||
#[options(command, default_expr = "Some(ZebradCmd::Start(StartCmd::default()))")]
|
|
||||||
pub command: Option<ZebradCmd>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EntryPoint {
|
|
||||||
/// Borrow the underlying command type or print usage info and exit
|
|
||||||
fn command(&self) -> &ZebradCmd {
|
|
||||||
self.command
|
|
||||||
.as_ref()
|
|
||||||
.expect("Some(ZebradCmd::Start(StartCmd::default()) as default value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Runnable for EntryPoint {
|
|
||||||
fn run(&self) {
|
|
||||||
self.command().run()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for EntryPoint {
|
|
||||||
/// Name of this program as a string
|
|
||||||
fn name() -> &'static str {
|
|
||||||
ZebradCmd::name()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Description of this program
|
|
||||||
fn description() -> &'static str {
|
|
||||||
ZebradCmd::description()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Version of this program
|
|
||||||
fn version() -> &'static str {
|
|
||||||
ZebradCmd::version()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Authors of this program
|
|
||||||
fn authors() -> &'static str {
|
|
||||||
ZebradCmd::authors()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get usage information for a particular subcommand (if available)
|
|
||||||
fn subcommand_usage(command: &str) -> Option<Usage> {
|
|
||||||
ZebradCmd::subcommand_usage(command)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Configurable<ZebradConfig> for EntryPoint {
|
|
||||||
/// Path to the command's configuration file
|
|
||||||
fn config_path(&self) -> Option<PathBuf> {
|
|
||||||
match &self.config {
|
|
||||||
// Use explicit `-c`/`--config` argument if passed
|
|
||||||
Some(cfg) => Some(cfg.clone()),
|
|
||||||
|
|
||||||
// Otherwise defer to the toplevel command's config path logic
|
|
||||||
None => self.command.as_ref().and_then(|cmd| cmd.config_path()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process the configuration after it has been loaded, potentially
|
|
||||||
/// modifying it or returning an error if options are incompatible
|
|
||||||
fn process_config(&self, config: ZebradConfig) -> Result<ZebradConfig, FrameworkError> {
|
|
||||||
match &self.command {
|
|
||||||
Some(cmd) => cmd.process_config(config),
|
|
||||||
None => Ok(config),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the zebrad version for this build, in SemVer 2.0 format.
|
/// Returns the zebrad version for this build, in SemVer 2.0 format.
|
||||||
///
|
///
|
||||||
/// Includes the git commit and the number of commits since the last version
|
/// Includes the git commit and the number of commits since the last version
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
//! Zebrad EntryPoint
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
commands::{StartCmd, ZebradCmd},
|
||||||
|
config::ZebradConfig,
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use abscissa_core::{
|
||||||
|
command::{Command, Usage},
|
||||||
|
config::Configurable,
|
||||||
|
FrameworkError, Options, Runnable,
|
||||||
|
};
|
||||||
|
|
||||||
|
// (See https://docs.rs/abscissa_core/0.5.2/src/abscissa_core/command/entrypoint.rs.html)
|
||||||
|
/// Toplevel entrypoint command.
|
||||||
|
///
|
||||||
|
/// Handles obtaining toplevel help as well as verbosity settings.
|
||||||
|
#[derive(Debug, Options)]
|
||||||
|
pub struct EntryPoint {
|
||||||
|
/// Path to the configuration file
|
||||||
|
#[options(short = "c", help = "path to configuration file")]
|
||||||
|
pub config: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// Obtain help about the current command
|
||||||
|
#[options(short = "h", help = "print help message")]
|
||||||
|
pub help: bool,
|
||||||
|
|
||||||
|
/// Increase verbosity setting
|
||||||
|
#[options(short = "v", help = "be verbose")]
|
||||||
|
pub verbose: bool,
|
||||||
|
|
||||||
|
/// Subcommand to execute.
|
||||||
|
///
|
||||||
|
/// The `command` option will delegate option parsing to the command type,
|
||||||
|
/// starting at the first free argument. Defaults to start.
|
||||||
|
#[options(command, default_expr = "Some(ZebradCmd::Start(StartCmd::default()))")]
|
||||||
|
pub command: Option<ZebradCmd>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntryPoint {
|
||||||
|
/// Borrow the underlying command type or print usage info and exit
|
||||||
|
fn command(&self) -> &ZebradCmd {
|
||||||
|
self.command
|
||||||
|
.as_ref()
|
||||||
|
.expect("Some(ZebradCmd::Start(StartCmd::default()) as default value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Runnable for EntryPoint {
|
||||||
|
fn run(&self) {
|
||||||
|
self.command().run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for EntryPoint {
|
||||||
|
/// Name of this program as a string
|
||||||
|
fn name() -> &'static str {
|
||||||
|
ZebradCmd::name()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Description of this program
|
||||||
|
fn description() -> &'static str {
|
||||||
|
ZebradCmd::description()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Version of this program
|
||||||
|
fn version() -> &'static str {
|
||||||
|
ZebradCmd::version()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Authors of this program
|
||||||
|
fn authors() -> &'static str {
|
||||||
|
ZebradCmd::authors()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get usage information for a particular subcommand (if available)
|
||||||
|
fn subcommand_usage(command: &str) -> Option<Usage> {
|
||||||
|
ZebradCmd::subcommand_usage(command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Configurable<ZebradConfig> for EntryPoint {
|
||||||
|
/// Path to the command's configuration file
|
||||||
|
fn config_path(&self) -> Option<PathBuf> {
|
||||||
|
match &self.config {
|
||||||
|
// Use explicit `-c`/`--config` argument if passed
|
||||||
|
Some(cfg) => Some(cfg.clone()),
|
||||||
|
|
||||||
|
// Otherwise defer to the toplevel command's config path logic
|
||||||
|
None => self.command.as_ref().and_then(|cmd| cmd.config_path()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process the configuration after it has been loaded, potentially
|
||||||
|
/// modifying it or returning an error if options are incompatible
|
||||||
|
fn process_config(&self, config: ZebradConfig) -> Result<ZebradConfig, FrameworkError> {
|
||||||
|
match &self.command {
|
||||||
|
Some(cmd) => cmd.process_config(config),
|
||||||
|
None => Ok(config),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -501,6 +501,37 @@ fn config_test() -> Result<()> {
|
||||||
// Check that an older stored configuration we have for Zebra works
|
// Check that an older stored configuration we have for Zebra works
|
||||||
stored_config_works()?;
|
stored_config_works()?;
|
||||||
|
|
||||||
|
// Runs `zebrad` serially to avoid potential port conflicts
|
||||||
|
app_no_args()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that `zebrad` runs the start command with no args
|
||||||
|
fn app_no_args() -> Result<()> {
|
||||||
|
let _init_guard = zebra_test::init();
|
||||||
|
|
||||||
|
// start caches state, so run one of the start tests with persistent state
|
||||||
|
let testdir = testdir()?.with_config(&mut persistent_test_config()?)?;
|
||||||
|
|
||||||
|
let mut child = testdir.spawn_child(args![])?;
|
||||||
|
|
||||||
|
// Run the program and kill it after a few seconds
|
||||||
|
std::thread::sleep(LAUNCH_DELAY);
|
||||||
|
child.kill()?;
|
||||||
|
|
||||||
|
let output = child.wait_with_output()?;
|
||||||
|
let output = output.assert_failure()?;
|
||||||
|
|
||||||
|
output.stdout_line_contains("Starting zebrad")?;
|
||||||
|
|
||||||
|
// 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")?;
|
||||||
|
|
||||||
|
// Make sure the command was killed
|
||||||
|
output.assert_was_killed()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue