Increase test coverage.
This commit is contained in:
parent
936960ee3a
commit
bd9a314baa
@ -50,6 +50,7 @@ pub trait GetFunctionContext: Context {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
/// A context that returns `None` for each identifier.
|
/// A context that returns `None` for each identifier.
|
||||||
|
#[derive(Debug, Default)]
|
||||||
pub struct EmptyContext;
|
pub struct EmptyContext;
|
||||||
|
|
||||||
impl Context for EmptyContext {
|
impl Context for EmptyContext {
|
||||||
@ -150,20 +151,19 @@ macro_rules! context_map {
|
|||||||
|
|
||||||
// The user has to specify a literal 'Function::new' in order to create a function
|
// The user has to specify a literal 'Function::new' in order to create a function
|
||||||
( ($ctx:expr) $k:expr => Function::new($($v:tt)*) , $($tt:tt)*) => {{
|
( ($ctx:expr) $k:expr => Function::new($($v:tt)*) , $($tt:tt)*) => {{
|
||||||
$ctx.set_function($k.into(), $crate::Function::new($($v)*))
|
$crate::ContextWithMutableFunctions::set_function($ctx, $k.into(), $crate::Function::new($($v)*))
|
||||||
.and($crate::context_map!(($ctx) $($tt)*))
|
.and($crate::context_map!(($ctx) $($tt)*))
|
||||||
}};
|
}};
|
||||||
// add a value, and chain the eventual error with the ones in the next values
|
// add a value, and chain the eventual error with the ones in the next values
|
||||||
( ($ctx:expr) $k:expr => $v:expr , $($tt:tt)*) => {{
|
( ($ctx:expr) $k:expr => $v:expr , $($tt:tt)*) => {{
|
||||||
$ctx.set_value($k.into(), $v.into())
|
$crate::ContextWithMutableVariables::set_value($ctx, $k.into(), $v.into())
|
||||||
.and($crate::context_map!(($ctx) $($tt)*))
|
.and($crate::context_map!(($ctx) $($tt)*))
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// Create a context, then recurse to add the values in it
|
// Create a context, then recurse to add the values in it
|
||||||
( $($tt:tt)* ) => {{
|
( $($tt:tt)* ) => {{
|
||||||
use $crate::Context;
|
|
||||||
let mut context = $crate::HashMapContext::new();
|
let mut context = $crate::HashMapContext::new();
|
||||||
$crate::context_map!((context) $($tt)*)
|
$crate::context_map!((&mut context) $($tt)*)
|
||||||
.map(|_| context)
|
.map(|_| context)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
@ -517,6 +517,7 @@ pub use crate::{
|
|||||||
operator::Operator,
|
operator::Operator,
|
||||||
tree::Node,
|
tree::Node,
|
||||||
value::{value_type::ValueType, EmptyType, FloatType, IntType, TupleType, Value, EMPTY_VALUE},
|
value::{value_type::ValueType, EmptyType, FloatType, IntType, TupleType, Value, EMPTY_VALUE},
|
||||||
|
token::PartialToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod context;
|
mod context;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![cfg(not(tarpaulin_include))]
|
||||||
|
|
||||||
use std::fmt::{Display, Error, Formatter};
|
use std::fmt::{Display, Error, Formatter};
|
||||||
|
|
||||||
use crate::operator::*;
|
use crate::operator::*;
|
||||||
|
@ -53,22 +53,38 @@ pub enum Token {
|
|||||||
String(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A partial token is an input character whose meaning depends on the characters around it.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum PartialToken {
|
pub enum PartialToken {
|
||||||
|
/// A partial token that unambiguously maps to a single token.
|
||||||
Token(Token),
|
Token(Token),
|
||||||
|
/// A partial token that is a literal.
|
||||||
Literal(String),
|
Literal(String),
|
||||||
|
/// A plus character '+'.
|
||||||
Plus,
|
Plus,
|
||||||
|
/// A minus character '-'.
|
||||||
Minus,
|
Minus,
|
||||||
|
/// A star character '*'.
|
||||||
Star,
|
Star,
|
||||||
|
/// A slash character '/'.
|
||||||
Slash,
|
Slash,
|
||||||
|
/// A percent character '%'.
|
||||||
Percent,
|
Percent,
|
||||||
|
/// A hat character '^'.
|
||||||
Hat,
|
Hat,
|
||||||
|
/// A whitespace character, e.g. ' '.
|
||||||
Whitespace,
|
Whitespace,
|
||||||
|
/// An equal-to character '='.
|
||||||
Eq,
|
Eq,
|
||||||
|
/// An exclamation mark character '!'.
|
||||||
ExclamationMark,
|
ExclamationMark,
|
||||||
|
/// A greater-than character '>'.
|
||||||
Gt,
|
Gt,
|
||||||
|
/// A lower-than character '<'.
|
||||||
Lt,
|
Lt,
|
||||||
|
/// An ampersand character '&'.
|
||||||
Ampersand,
|
Ampersand,
|
||||||
|
/// A vertical bar character '|'.
|
||||||
VerticalBar,
|
VerticalBar,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
extern crate evalexpr;
|
|
||||||
|
|
||||||
use evalexpr::{error::*, *};
|
use evalexpr::{error::*, *};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -764,3 +762,45 @@ fn test_type_errors_in_binary_operators() {
|
|||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_context() {
|
||||||
|
let context = EmptyContext;
|
||||||
|
assert_eq!(context.get_value("abc"), None);
|
||||||
|
assert_eq!(context.call_function("abc", &Value::Empty), Err(EvalexprError::FunctionIdentifierNotFound("abc".to_owned())));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_hashmap_context_type_safety() {
|
||||||
|
let mut context = context_map! {"a" => 5, "b" => 5.0}.unwrap();
|
||||||
|
assert_eq!(eval_with_context_mut("a = 4", &mut context), Ok(Value::Empty));
|
||||||
|
assert_eq!(eval_with_context_mut("a = 4.0", &mut context), Err(EvalexprError::ExpectedInt {actual: Value::Float(4.0)}));
|
||||||
|
assert_eq!(eval_with_context_mut("a += 4.0", &mut context), Err(EvalexprError::ExpectedInt {actual: Value::Float(8.0)}));
|
||||||
|
assert_eq!(eval_with_context_mut("a -= 4.0", &mut context), Err(EvalexprError::ExpectedInt {actual: Value::Float(0.0)}));
|
||||||
|
assert_eq!(eval_with_context_mut("a *= 4.0", &mut context), Err(EvalexprError::ExpectedInt {actual: Value::Float(16.0)}));
|
||||||
|
assert_eq!(eval_with_context_mut("a /= 4.0", &mut context), Err(EvalexprError::ExpectedInt {actual: Value::Float(1.0)}));
|
||||||
|
assert_eq!(eval_with_context_mut("a %= 4.0", &mut context), Err(EvalexprError::ExpectedInt {actual: Value::Float(0.0)}));
|
||||||
|
assert_eq!(eval_with_context_mut("a ^= 4.0", &mut context), Err(EvalexprError::ExpectedInt {actual: Value::Float(256.0)}));
|
||||||
|
|
||||||
|
assert_eq!(eval_with_context_mut("b = 4.0", &mut context), Ok(Value::Empty));
|
||||||
|
assert_eq!(eval_with_context_mut("b = 4", &mut context), Err(EvalexprError::ExpectedFloat {actual: Value::Int(4)}));
|
||||||
|
assert_eq!(eval_with_context_mut("b += 4", &mut context), Ok(Value::Empty));
|
||||||
|
assert_eq!(eval_with_context_mut("b -= 4", &mut context), Ok(Value::Empty));
|
||||||
|
assert_eq!(eval_with_context_mut("b *= 4", &mut context), Ok(Value::Empty));
|
||||||
|
assert_eq!(eval_with_context_mut("b /= 4", &mut context), Ok(Value::Empty));
|
||||||
|
assert_eq!(eval_with_context_mut("b %= 4", &mut context), Ok(Value::Empty));
|
||||||
|
assert_eq!(eval_with_context_mut("b ^= 4", &mut context), Ok(Value::Empty));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_error_constructors() {
|
||||||
|
assert_eq!(eval("a = true + \"4\""), Err(EvalexprError::ExpectedNumberOrString { actual: Value::Boolean(true) }));
|
||||||
|
assert_eq!(eval("a = true && \"4\""), Err(EvalexprError::ExpectedBoolean { actual: Value::from("4") }));
|
||||||
|
assert_eq!(eval_tuple("4"), Err(EvalexprError::ExpectedTuple { actual: Value::Int(4) }));
|
||||||
|
assert_eq!(Value::Tuple(vec![Value::Int(4), Value::Int(5)]).as_fixed_len_tuple(3), Err(EvalexprError::ExpectedFixedLenTuple { expected_len: 3, actual: Value::Tuple(vec![Value::Int(4), Value::Int(5)]) }));
|
||||||
|
assert_eq!(eval_empty("4"), Err(EvalexprError::ExpectedEmpty {actual: Value::Int(4)}));
|
||||||
|
assert_eq!(eval("&"), Err(EvalexprError::UnmatchedPartialToken { first: PartialToken::Ampersand, second: None }));
|
||||||
|
|
||||||
|
assert_eq!(expect_function_argument_amount(2, 2), Ok(()));
|
||||||
|
assert_eq!(expect_function_argument_amount(2, 3), Err(EvalexprError::WrongFunctionArgumentAmount { expected: 3, actual: 2 }));
|
||||||
|
}
|
@ -12,3 +12,10 @@ fn test_serde() {
|
|||||||
assert_eq!(manual_tree.eval(), serde_tree.eval());
|
assert_eq!(manual_tree.eval(), serde_tree.eval());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serde_errors() {
|
||||||
|
assert_eq!(ron::de::from_str::<Node>("[\"5==5\"]"), Err(ron::de::Error::Parser(ron::de::ParseError::ExpectedString, ron::de::Position{col:1,line:1})));
|
||||||
|
assert_eq!(ron::de::from_str::<Node>("\"&\""), Err(ron::de::Error::Message("Found a partial token '&' that should be followed by another partial token.".to_owned())));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user