|
|
@ -4,13 +4,13 @@ use std::fmt; |
|
|
|
use loggers::Logger;
|
|
|
|
use symbols::Symbol;
|
|
|
|
|
|
|
|
#[derive(Debug,PartialEq)]
|
|
|
|
pub enum SymbolRunError<E: Error> {
|
|
|
|
Symbol(E),
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum SymbolRunError {
|
|
|
|
Symbol(Box<Error>),
|
|
|
|
ExecuteDidNotReach(())
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: Error> Error for SymbolRunError<E> {
|
|
|
|
impl Error for SymbolRunError {
|
|
|
|
fn description(&self) -> &str {
|
|
|
|
match self {
|
|
|
|
&SymbolRunError::Symbol(_) => "Symbol execution error",
|
|
|
@ -19,13 +19,13 @@ impl<E: Error> Error for SymbolRunError<E> { |
|
|
|
}
|
|
|
|
fn cause(&self) -> Option<&Error> {
|
|
|
|
match self {
|
|
|
|
&SymbolRunError::Symbol(ref e) => Some(e),
|
|
|
|
&SymbolRunError::Symbol(ref e) => Some(&**e),
|
|
|
|
&SymbolRunError::ExecuteDidNotReach(_) => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: Error> fmt::Display for SymbolRunError<E> {
|
|
|
|
impl fmt::Display for SymbolRunError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
&SymbolRunError::Symbol(ref e) => write!(f, "{}", e),
|
|
|
@ -34,22 +34,14 @@ impl<E: Error> fmt::Display for SymbolRunError<E> { |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: Error> From<E> for SymbolRunError<E> {
|
|
|
|
fn from(err: E) -> SymbolRunError<E> {
|
|
|
|
SymbolRunError::Symbol(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait SymbolRunner {
|
|
|
|
fn run_symbol<S: ?Sized + Symbol + fmt::Display>(&self, logger: &mut Logger, symbol: &S) -> Result<(), SymbolRunError<S::Error>>
|
|
|
|
where S::Error: Error;
|
|
|
|
fn run_symbol<S: ?Sized + Symbol + fmt::Display>(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box<Error>>;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct InitializingSymbolRunner;
|
|
|
|
|
|
|
|
impl SymbolRunner for InitializingSymbolRunner {
|
|
|
|
fn run_symbol<S: ?Sized + Symbol + fmt::Display>(&self, logger: &mut Logger, symbol: &S) -> Result<(), SymbolRunError<S::Error>>
|
|
|
|
where S::Error: Error
|
|
|
|
fn run_symbol<S: ?Sized + Symbol + fmt::Display>(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box<Error>>
|
|
|
|
{
|
|
|
|
let target_reached = try!(symbol.target_reached());
|
|
|
|
if target_reached {
|
|
|
@ -61,7 +53,7 @@ impl SymbolRunner for InitializingSymbolRunner { |
|
|
|
let target_reached = try!(symbol.target_reached());
|
|
|
|
logger.debug(format!("Symbol reports target_reached: {:?} (should be true)", target_reached).as_str());
|
|
|
|
if !target_reached {
|
|
|
|
return Err(SymbolRunError::ExecuteDidNotReach(()));
|
|
|
|
return Err(Box::new(SymbolRunError::ExecuteDidNotReach(())));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
@ -71,8 +63,7 @@ impl SymbolRunner for InitializingSymbolRunner { |
|
|
|
pub struct DrySymbolRunner;
|
|
|
|
|
|
|
|
impl SymbolRunner for DrySymbolRunner {
|
|
|
|
fn run_symbol<S: ?Sized + Symbol + fmt::Display>(&self, logger: &mut Logger, symbol: &S) -> Result<(), SymbolRunError<S::Error>>
|
|
|
|
where S::Error: Error
|
|
|
|
fn run_symbol<S: ?Sized + Symbol + fmt::Display>(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box<Error>>
|
|
|
|
{
|
|
|
|
let target_reached = try!(symbol.target_reached());
|
|
|
|
logger.debug(format!("Symbol reports target_reached: {:?}", target_reached).as_str());
|
|
|
@ -95,7 +86,6 @@ mod test { |
|
|
|
use symbols::Symbol;
|
|
|
|
use schema::SymbolRunner;
|
|
|
|
use schema::InitializingSymbolRunner;
|
|
|
|
use schema::SymbolRunError;
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
enum DummySymbolError {
|
|
|
@ -114,34 +104,29 @@ mod test { |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct DummySymbol {
|
|
|
|
_target_reacheds: Vec<Result<bool, DummySymbolError>>,
|
|
|
|
_cur_target_reached: RefCell<usize>,
|
|
|
|
_execute: Result<(), DummySymbolError>,
|
|
|
|
struct DummySymbol<'a> {
|
|
|
|
_execute: &'a Fn() -> Result<(), Box<Error>>,
|
|
|
|
_target_reached: &'a Fn() -> Result<bool, Box<Error>>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Symbol for DummySymbol {
|
|
|
|
type Error = DummySymbolError;
|
|
|
|
fn target_reached(&self) -> Result<bool, Self::Error> {
|
|
|
|
let mut cur = self._cur_target_reached.borrow_mut();
|
|
|
|
let ret = self._target_reacheds[*cur].clone();
|
|
|
|
*cur = *cur + 1;
|
|
|
|
ret
|
|
|
|
impl<'a> Symbol for DummySymbol<'a> {
|
|
|
|
fn target_reached(&self) -> Result<bool, Box<Error>> {
|
|
|
|
(self._target_reached)()
|
|
|
|
}
|
|
|
|
fn execute(&self) -> Result<(), Box<Error>> {
|
|
|
|
(self._execute)()
|
|
|
|
}
|
|
|
|
fn execute(&self) -> Result<(), Self::Error> { self._execute.clone() }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for DummySymbol {
|
|
|
|
impl<'a> fmt::Display for DummySymbol<'a> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "Dummy symbol")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DummySymbol {
|
|
|
|
fn new(target_reached: Vec<Result<bool, DummySymbolError>>,
|
|
|
|
execute: Result<(), DummySymbolError>) -> DummySymbol {
|
|
|
|
DummySymbol { _target_reacheds: target_reached, _cur_target_reached: RefCell::new(0), _execute: execute }
|
|
|
|
impl<'a> DummySymbol<'a> {
|
|
|
|
fn new(target_reached: &'a Fn() -> Result<bool, Box<Error>>, execute: &'a Fn() -> Result<(), Box<Error>>) -> DummySymbol<'a> {
|
|
|
|
DummySymbol { _target_reached: target_reached, _execute: execute }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
@ -166,36 +151,37 @@ mod test { |
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn nothing_needed_to_be_done() {
|
|
|
|
let result: Result<(), SymbolRunError<DummySymbolError>> = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(vec![Ok(true)], Ok(())) );
|
|
|
|
assert_eq!(
|
|
|
|
result,
|
|
|
|
Ok(())
|
|
|
|
);
|
|
|
|
let result = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(&|| Ok(true), &|| Ok(())) );
|
|
|
|
assert!(result.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn everything_is_ok() {
|
|
|
|
let result: Result<(), SymbolRunError<DummySymbolError>> = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(vec![Ok(false), Ok(true)], Ok(())) );
|
|
|
|
assert_eq!(
|
|
|
|
result,
|
|
|
|
Ok(())
|
|
|
|
);
|
|
|
|
let first = RefCell::new(true);
|
|
|
|
let result = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(&|| {
|
|
|
|
let mut _first = first.borrow_mut();
|
|
|
|
Ok(if *_first {
|
|
|
|
*_first = false;
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
})
|
|
|
|
}, &|| Ok(())) );
|
|
|
|
assert!(result.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn executing_did_not_change_state() {
|
|
|
|
let result: Result<(), SymbolRunError<DummySymbolError>> = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(vec![Ok(false), Ok(false)], Ok(())));
|
|
|
|
let result = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(&|| Ok(false), &|| Ok(())));
|
|
|
|
assert_eq!(
|
|
|
|
result,
|
|
|
|
Err(SymbolRunError::ExecuteDidNotReach(()))
|
|
|
|
result.unwrap_err().description(),
|
|
|
|
"Target not reached after executing symbol"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn executing_did_not_work() {
|
|
|
|
assert_eq!(
|
|
|
|
InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(vec![Ok(false)], Err(DummySymbolError::Error(()))) ),
|
|
|
|
Err(SymbolRunError::Symbol(DummySymbolError::Error(())))
|
|
|
|
);
|
|
|
|
let err = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(&|| Ok(false), &|| Err(Box::new(DummySymbolError::Error(()))) )).unwrap_err();
|
|
|
|
assert_eq!(err.description(), "Description");
|
|
|
|
}
|
|
|
|
}
|