Skip to content

Commit

Permalink
refactored ServerBootstrapper
Browse files Browse the repository at this point in the history
Extracted command and settings builder
  • Loading branch information
dkijania committed Jul 9, 2020
1 parent ef5f915 commit 27a1887
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 77 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions vit-servicing-station-tests/Cargo.toml
Expand Up @@ -25,6 +25,7 @@ askama_shared = "0.8"
vit-servicing-station-lib = {path= "../vit-servicing-station-lib"}
lazy_static = "1.4"
rand = "0.7"
predicates = { version = "1.0", default-features = false, features = ["difference"] }

#diesel doesn't have an way to create empty db
#rustqlite is used for that purpose
Expand Down
77 changes: 0 additions & 77 deletions vit-servicing-station-tests/src/common/startup/server.rs

This file was deleted.

66 changes: 66 additions & 0 deletions vit-servicing-station-tests/src/common/startup/server/bootstrap.rs
@@ -0,0 +1,66 @@
use std::process::Stdio;
use thiserror::Error;

use super::{BootstrapCommandBuilder, ServerSettingsBuilder};
use crate::common::{paths::BLOCK0_BIN, server::Server};

pub struct ServerBootstrapper {
settings_builder: ServerSettingsBuilder,
}

impl ServerBootstrapper {
pub fn new() -> Self {
let mut settings_builder: ServerSettingsBuilder = Default::default();
settings_builder
.with_random_localhost_address()
.with_block0_path(BLOCK0_BIN.to_string());

Self { settings_builder }
}

pub fn with_localhost_address(&mut self, port: u32) -> &mut Self {
self.settings_builder.with_localhost_address(port);
self
}

pub fn with_db_path<S: Into<String>>(&mut self, db_url: S) -> &mut Self {
self.settings_builder.with_db_path(db_url.into());
self
}

pub fn with_block0_path<S: Into<String>>(&mut self, block0_path: S) -> &mut Self {
self.settings_builder.with_block0_path(block0_path.into());
self
}

pub fn start(&self) -> Result<Server, ServerBootstrapperError> {
let settings = self.settings_builder.build();

let mut command_builder: BootstrapCommandBuilder = Default::default();

let mut command = command_builder
.address(&settings.address.to_string())
.db_url(&settings.db_url)
.block0_path(&settings.block0_path)
.build();

let child = command.stdout(Stdio::inherit()).spawn()?;

std::thread::sleep(std::time::Duration::from_secs(1));
Ok(Server::new(child, settings))
}
}

impl Default for ServerBootstrapper {
fn default() -> Self {
Self::new()
}
}

#[derive(Debug, Error)]
pub enum ServerBootstrapperError {
#[error("cannot spawn process")]
ProcessSpawnError(#[from] std::io::Error),
#[error("cannot find binary (0)")]
CargoError(#[from] assert_cmd::cargo::CargoError),
}
121 changes: 121 additions & 0 deletions vit-servicing-station-tests/src/common/startup/server/command.rs
@@ -0,0 +1,121 @@
use crate::common::startup::get_exe;
use std::{path::PathBuf, process::Command};

/// In order to test robustness of server bootstrapper we need to be able
/// to provide some
pub struct BootstrapCommandBuilder {
exe: PathBuf,
address: Option<String>,
allowed_origins: Option<String>,
block0_path: Option<String>,
cert_file: Option<PathBuf>,
db_url: Option<String>,
in_settings_file: Option<PathBuf>,
max_age_secs: Option<u32>,
out_settings_file: Option<PathBuf>,
priv_key_file: Option<PathBuf>,
}

impl Default for BootstrapCommandBuilder {
fn default() -> Self {
Self::new(get_exe())
}
}

impl BootstrapCommandBuilder {
pub fn new(exe: PathBuf) -> Self {
Self {
exe,
address: None,
allowed_origins: None,
block0_path: None,
cert_file: None,
db_url: None,
in_settings_file: None,
max_age_secs: None,
out_settings_file: None,
priv_key_file: None,
}
}

pub fn address<S: Into<String>>(&mut self, address: S) -> &mut Self {
self.address = Some(address.into());
self
}

pub fn allowed_origins<S: Into<String>>(&mut self, allowed_origins: S) -> &mut Self {
self.allowed_origins = Some(allowed_origins.into());
self
}

pub fn block0_path<S: Into<String>>(&mut self, block0_path: S) -> &mut Self {
self.block0_path = Some(block0_path.into());
self
}

pub fn cert_file(&mut self, cert_file: &PathBuf) -> &mut Self {
self.cert_file = Some(cert_file.clone());
self
}
pub fn db_url<S: Into<String>>(&mut self, db_url: S) -> &mut Self {
self.db_url = Some(db_url.into());
self
}
pub fn in_settings_file(&mut self, in_settings_file: &PathBuf) -> &mut Self {
self.in_settings_file = Some(in_settings_file.clone());
self
}
pub fn max_age_secs(&mut self, max_age_secs: u32) -> &mut Self {
self.max_age_secs = Some(max_age_secs);
self
}
pub fn out_settings_file(&mut self, out_settings_file: &PathBuf) -> &mut Self {
self.out_settings_file = Some(out_settings_file.clone());
self
}
pub fn priv_key_file(&mut self, priv_key_file: &PathBuf) -> &mut Self {
self.priv_key_file = Some(priv_key_file.clone());
self
}

pub fn build(&self) -> Command {
let mut command = Command::new(self.exe.clone());
if let Some(address) = &self.address {
command.arg("--address").arg(address);
}

if let Some(allowed_origins) = &self.allowed_origins {
command.arg("--allowed-origins").arg(allowed_origins);
}

if let Some(block0_path) = &self.block0_path {
command.arg("--block0-path").arg(block0_path);
}

if let Some(cert_file) = &self.cert_file {
command.arg("--cert-file").arg(cert_file.to_str().unwrap());
}
if let Some(db_url) = &self.db_url {
command.arg("--db-url").arg(db_url);
}
if let Some(in_settings_file) = &self.in_settings_file {
command
.arg("--in-settings-file")
.arg(in_settings_file.to_str().unwrap());
}
if let Some(max_age_secs) = &self.max_age_secs {
command.arg("--max-age-secs").arg(max_age_secs.to_string());
}
if let Some(out_settings_file) = &self.out_settings_file {
command
.arg("--out-settings-file")
.arg(out_settings_file.to_str().unwrap());
}
if let Some(priv_key_file) = &self.priv_key_file {
command
.arg("--priv-key-file")
.arg(priv_key_file.to_str().unwrap());
}
command
}
}
7 changes: 7 additions & 0 deletions vit-servicing-station-tests/src/common/startup/server/mod.rs
@@ -0,0 +1,7 @@
mod bootstrap;
mod command;
mod settings;

pub use bootstrap::{ServerBootstrapper, ServerBootstrapperError};
pub use command::BootstrapCommandBuilder;
pub use settings::{dump_settings, ServerSettingsBuilder};
52 changes: 52 additions & 0 deletions vit-servicing-station-tests/src/common/startup/server/settings.rs
@@ -0,0 +1,52 @@
use crate::common::startup::get_available_port;
use assert_fs::{fixture::PathChild, TempDir};
use std::{net::SocketAddr, path::PathBuf};
use vit_servicing_station_lib::server::settings::{dump_settings_to_file, ServiceSettings};

pub struct ServerSettingsBuilder {
settings: ServiceSettings,
}

impl Default for ServerSettingsBuilder {
fn default() -> Self {
Self {
settings: Default::default(),
}
}
}

impl ServerSettingsBuilder {
pub fn with_random_localhost_address(&mut self) -> &mut Self {
self.with_localhost_address(get_available_port());
self
}

pub fn with_localhost_address(&mut self, port: u32) -> &mut Self {
self.settings.address = Self::format_localhost_address(port);
self
}

fn format_localhost_address(port: u32) -> SocketAddr {
format!("127.0.0.1:{}", port).parse().unwrap()
}

pub fn with_db_path<S: Into<String>>(&mut self, db_url: S) -> &mut Self {
self.settings.db_url = db_url.into();
self
}

pub fn with_block0_path<S: Into<String>>(&mut self, block0_path: S) -> &mut Self {
self.settings.block0_path = block0_path.into();
self
}

pub fn build(&self) -> ServiceSettings {
self.settings.clone()
}
}

pub fn dump_settings(temp_dir: &TempDir, settings: &ServiceSettings) -> PathBuf {
let child_path = temp_dir.child("settings.json");
dump_settings_to_file(child_path.path().to_str().unwrap(), settings).unwrap();
child_path.path().into()
}

0 comments on commit 27a1887

Please sign in to comment.