mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
FEATURE: More ergonomic syntax for asserts.
This commit is contained in:
parent
b87d75c5c7
commit
a7a32d56b2
@ -16,15 +16,15 @@ let list = [1, 2, 3];
|
|||||||
let list2 = list;
|
let list2 = list;
|
||||||
let list3 = [1, 2];
|
let list3 = [1, 2];
|
||||||
|
|
||||||
assert "one == one";
|
assert |one == one|;
|
||||||
assert "one == one";
|
assert |one == one|;
|
||||||
assert "one >= one";
|
assert |one >= one|;
|
||||||
assert "two > one";
|
assert |two > one|;
|
||||||
assert "two >= two";
|
assert |two >= two|;
|
||||||
assert "tpl1 == tpl2";
|
assert |tpl1 == tpl2|;
|
||||||
assert "tpl1 != tpl3";
|
assert |tpl1 != tpl3|;
|
||||||
assert "list == list2";
|
assert |list == list2|;
|
||||||
assert "list != list3";
|
assert |list != list3|;
|
||||||
|
|
||||||
// Deep Comparisons
|
// Deep Comparisons
|
||||||
let tpl4 = {
|
let tpl4 = {
|
||||||
@ -40,17 +40,17 @@ let less = {
|
|||||||
foo = "bar"
|
foo = "bar"
|
||||||
};
|
};
|
||||||
|
|
||||||
assert "tpl4.inner == copy.inner";
|
assert |tpl4.inner == copy.inner|;
|
||||||
assert "tpl4.inner.fld == copy.inner.fld";
|
assert |tpl4.inner.fld == copy.inner.fld|;
|
||||||
assert "tpl4.lst == copy.lst";
|
assert |tpl4.lst == copy.lst|;
|
||||||
assert "tpl4.foo == copy.foo";
|
assert |tpl4.foo == copy.foo|;
|
||||||
assert "tpl4 == copy";
|
assert |tpl4 == copy|;
|
||||||
assert "tpl4 != extra";
|
assert |tpl4 != extra|;
|
||||||
assert "tpl4 != less";
|
assert |tpl4 != less|;
|
||||||
|
|
||||||
// Expression comparisons
|
// Expression comparisons
|
||||||
assert "2 == 1+1";
|
assert |2 == 1+1|;
|
||||||
assert "(1+1) == 2";
|
assert |(1+1) == 2|;
|
||||||
assert "(1+1) == (1+1)";
|
assert |(1+1) == (1+1)|;
|
||||||
let want = "foo";
|
let want = "foo";
|
||||||
assert "select want, 1, { foo=2, } == 2";
|
assert |select want, 1, { foo=2, } == 2|;
|
@ -2,4 +2,4 @@ let empty = NULL;
|
|||||||
let tpl = {
|
let tpl = {
|
||||||
foo = NULL,
|
foo = NULL,
|
||||||
};
|
};
|
||||||
assert "tpl.foo == empty";
|
assert |tpl.foo == empty|;
|
@ -13,10 +13,10 @@ let cplxmacro = macro(argint, argstr, argfloat) => {
|
|||||||
let simpleresult = simplemacro(1, 2, 3);
|
let simpleresult = simplemacro(1, 2, 3);
|
||||||
let cplxresult = cplxmacro(1, "We", 3.0);
|
let cplxresult = cplxmacro(1, "We", 3.0);
|
||||||
|
|
||||||
assert "simpleresult.field1 == 1";
|
assert |simpleresult.field1 == 1|;
|
||||||
assert "simpleresult.field2 == 2";
|
assert |simpleresult.field2 == 2|;
|
||||||
assert "simpleresult.field3 == 3";
|
assert |simpleresult.field3 == 3|;
|
||||||
|
|
||||||
assert "cplxresult.field1 == 2";
|
assert |cplxresult.field1 == 2|;
|
||||||
assert "cplxresult.field2 == \"We are here\"";
|
assert |cplxresult.field2 == "We are here"|;
|
||||||
assert "cplxresult.field3 == 2.0";
|
assert |cplxresult.field3 == 2.0|;
|
@ -1,7 +1,7 @@
|
|||||||
assert "2 * 2 + 1 == 5";
|
assert |2 * 2 + 1 == 5|;
|
||||||
assert "2 + 2 * 3 == 8";
|
assert |2 + 2 * 3 == 8|;
|
||||||
assert "2 * (2 + 1) == 6";
|
assert |2 * (2 + 1) == 6|;
|
||||||
assert "2 * 2 + 1 > 4";
|
assert |2 * 2 + 1 > 4|;
|
||||||
assert "2 * 2 + 1 > 6";
|
assert |2 * 2 + 1 > 6|;
|
||||||
assert "2 * 2 + 1 >= 5";
|
assert |2 * 2 + 1 >= 5|;
|
||||||
assert "2 * 2 + 1 <= 5";
|
assert |2 * 2 + 1 <= 5|;
|
@ -10,10 +10,10 @@ let testmacro = macro(arg) => {
|
|||||||
output = arg,
|
output = arg,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert "list.0 == 1";
|
assert |list.0 == 1|;
|
||||||
assert "list.1 == 2";
|
assert |list.1 == 2|;
|
||||||
assert "list.3 == 4";
|
assert |list.3 == 4|;
|
||||||
assert "tuple.field1 == 1";
|
assert |tuple.field1 == 1|;
|
||||||
assert "tuple.field2 == 3";
|
assert |tuple.field2 == 3|;
|
||||||
assert "tuple.deeplist.0 == \"foo\"";
|
assert |tuple.deeplist.0 == "foo"|;
|
||||||
assert "tuple.deeplist.1 == \"bar\"";
|
assert |tuple.deeplist.1 == "bar"|;
|
@ -71,6 +71,7 @@ pub enum TokenType {
|
|||||||
WS,
|
WS,
|
||||||
COMMENT,
|
COMMENT,
|
||||||
QUOTED,
|
QUOTED,
|
||||||
|
PIPEQUOTE,
|
||||||
DIGIT,
|
DIGIT,
|
||||||
BAREWORD,
|
BAREWORD,
|
||||||
PUNCT,
|
PUNCT,
|
||||||
|
18
src/lib.rs
18
src/lib.rs
@ -409,23 +409,15 @@
|
|||||||
//!
|
//!
|
||||||
//! The assert statement defines an expression that must evaluate to either true or false. Assert statements are noops except
|
//! The assert statement defines an expression that must evaluate to either true or false. Assert statements are noops except
|
||||||
//! during a validation compile. They give you a way to assert certains properties about your data and can be used as a form
|
//! during a validation compile. They give you a way to assert certains properties about your data and can be used as a form
|
||||||
//! of unit testting for your configurations. It starts with the assert keyword followed by a quoted string that is
|
//! of unit testing for your configurations. It starts with the assert keyword followed by a valid boolean ucg expression
|
||||||
//! itself a valid boolean ucg expression.
|
//! delimited by `|` characters.
|
||||||
//!
|
//!
|
||||||
//! ```ucg
|
//! ```ucg
|
||||||
//! assert "host == \"www.example.com\"";
|
//! assert host == "www.example.com";
|
||||||
//! assert "select qa, 443, {
|
//! assert |select qa, 443, {
|
||||||
//! qa = 80,
|
//! qa = 80,
|
||||||
//! prod = 443,
|
//! prod = 443,
|
||||||
//! } == 443";
|
//! } == 443|;
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! It is a little bit awkward for strings since you have to escape their quotes. But you can work around it by
|
|
||||||
//! by storing the expectations in variables first and referencing them in the assert statement.
|
|
||||||
//!
|
|
||||||
//! ```ucg
|
|
||||||
//! let expected_host = "www.example.com";
|
|
||||||
//! assert "host == expected_host";
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! When _test.ucg files are run in a validation run then ucg will output a log of all the assertions
|
//! When _test.ucg files are run in a validation run then ucg will output a log of all the assertions
|
||||||
|
@ -838,7 +838,7 @@ named!(assert_statement<TokenIter, Statement, error::Error>,
|
|||||||
error::Error::new(
|
error::Error::new(
|
||||||
"Invalid syntax for assert",
|
"Invalid syntax for assert",
|
||||||
error::ErrorType::ParseError, pos)),
|
error::ErrorType::ParseError, pos)),
|
||||||
match_type!(STR)) >>
|
match_type!(PIPEQUOTE)) >>
|
||||||
punct!(";") >>
|
punct!(";") >>
|
||||||
(Statement::Assert(tok.clone()))
|
(Statement::Assert(tok.clone()))
|
||||||
)
|
)
|
||||||
|
@ -309,6 +309,20 @@ fn test_out_statement_parse() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_assert_statement_parse() {
|
||||||
|
assert_error!(out_statement("assert"));
|
||||||
|
assert_error!(out_statement("assert |"));
|
||||||
|
assert_error!(out_statement("assert |foo"));
|
||||||
|
assert_parse!(
|
||||||
|
assert_statement("assert |foo|;"),
|
||||||
|
Statement::Assert(Token {
|
||||||
|
pos: Position { line: 1, column: 8 },
|
||||||
|
fragment: "foo".to_string(),
|
||||||
|
typ: TokenType::PIPEQUOTE
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_expression_statement_parse() {
|
fn test_expression_statement_parse() {
|
||||||
assert_error!(expression_statement("foo"));
|
assert_error!(expression_statement("foo"));
|
||||||
|
@ -73,6 +73,20 @@ named!(strtok( Span ) -> Token,
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
named!(pipequotetok( Span ) -> Token,
|
||||||
|
do_parse!(
|
||||||
|
span: position!() >>
|
||||||
|
tag!("|") >>
|
||||||
|
frag: take_until!("|") >>
|
||||||
|
tag!("|") >>
|
||||||
|
(Token{
|
||||||
|
typ: TokenType::PIPEQUOTE,
|
||||||
|
pos: Position::from(span),
|
||||||
|
fragment: frag.fragment.to_string(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
named!(barewordtok( Span ) -> Token,
|
named!(barewordtok( Span ) -> Token,
|
||||||
do_parse!(
|
do_parse!(
|
||||||
span: position!() >>
|
span: position!() >>
|
||||||
@ -336,6 +350,7 @@ named!(whitespace( Span ) -> Token,
|
|||||||
named!(token( Span ) -> Token,
|
named!(token( Span ) -> Token,
|
||||||
alt!(
|
alt!(
|
||||||
strtok |
|
strtok |
|
||||||
|
pipequotetok |
|
||||||
emptytok | // This must come before the barewordtok
|
emptytok | // This must come before the barewordtok
|
||||||
digittok |
|
digittok |
|
||||||
commatok |
|
commatok |
|
||||||
@ -475,6 +490,14 @@ macro_rules! match_type {
|
|||||||
match_type!($i, STR => token_clone)
|
match_type!($i, STR => token_clone)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
($i:expr,PIPEQUOTE => $h:expr) => {
|
||||||
|
match_type!($i, TokenType::PIPEQUOTE, "Not a Pipe Quoted String", $h)
|
||||||
|
};
|
||||||
|
|
||||||
|
($i:expr,PIPEQUOTE) => {
|
||||||
|
match_type!($i, PIPEQUOTE => token_clone)
|
||||||
|
};
|
||||||
|
|
||||||
($i:expr,DIGIT => $h:expr) => {
|
($i:expr,DIGIT => $h:expr) => {
|
||||||
match_type!($i, TokenType::DIGIT, "Not a DIGIT", $h)
|
match_type!($i, TokenType::DIGIT, "Not a DIGIT", $h)
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,16 @@ fn test_escape_quoted() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pipe_quoted() {
|
||||||
|
let result = pipequotetok(LocatedSpan::new("|foo|"));
|
||||||
|
assert!(result.is_done(), format!("result {:?} is not ok", result));
|
||||||
|
if let nom::IResult::Done(_, tok) = result {
|
||||||
|
assert_eq!(tok.fragment, "foo".to_string());
|
||||||
|
assert_eq!(tok.typ, TokenType::PIPEQUOTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_string_with_escaping() {
|
fn test_string_with_escaping() {
|
||||||
let result = strtok(LocatedSpan::new("\"foo \\\\ \\\"bar\""));
|
let result = strtok(LocatedSpan::new("\"foo \\\\ \\\"bar\""));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user