mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
FIX: Better error reporting.
Also adds some testing functions to check build failures. Begins to address Issue #34
This commit is contained in:
parent
39f7afa8fc
commit
2068063a5b
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1,6 +1,6 @@
|
||||
[[package]]
|
||||
name = "abortable_parser"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -443,7 +443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "ucg"
|
||||
version = "0.5.1"
|
||||
dependencies = [
|
||||
"abortable_parser 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"abortable_parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bencher 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -549,7 +549,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum abortable_parser 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "685d99bbca3566d6b7f34b09d68039089ce4a36226f6f99f61ed8495850e3213"
|
||||
"checksum abortable_parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1b5820556138ca74cc120d93d6724fbbdf4c8e130e640333d589a3f7ae747e4"
|
||||
"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
|
||||
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
|
||||
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
||||
|
@ -19,7 +19,7 @@ include = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
abortable_parser = "~0.2.2"
|
||||
abortable_parser = "~0.2.3"
|
||||
clap = "~2.26.0"
|
||||
serde_json = "~1.0.9"
|
||||
simple-error = "0.1"
|
||||
|
@ -15,6 +15,8 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use super::assets::MemoryCache;
|
||||
use super::FileBuilder;
|
||||
|
||||
@ -29,6 +31,39 @@ fn assert_build(input: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_build_failure(input: &str, expect: Vec<Regex>) {
|
||||
let i_paths = Vec::new();
|
||||
let cache = MemoryCache::new();
|
||||
let mut b = FileBuilder::new("<Eval>", &i_paths, Rc::new(RefCell::new(cache)));
|
||||
b.enable_validate_mode();
|
||||
let err = b.eval_string(input);
|
||||
match err {
|
||||
Ok(_) => {
|
||||
for r in expect.iter() {
|
||||
if !b.assert_collector.success {
|
||||
if let None = r.find(&b.assert_collector.failures) {
|
||||
panic!(
|
||||
"[{}] was not found in Assertion Failures:\n{}",
|
||||
r, b.assert_collector.failures
|
||||
);
|
||||
}
|
||||
} else {
|
||||
panic!("Building input Did not panic!");
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ref err) => {
|
||||
for r in expect.iter() {
|
||||
let stack_trace = format!("{}", err);
|
||||
// Look for each expect to match the string.
|
||||
if let None = r.find(&stack_trace) {
|
||||
panic!("[{}] was not found in stacktrace:\n{}", r, stack_trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuples() {
|
||||
assert_build(include_str!("../../integration_tests/tuple_test.ucg"));
|
||||
@ -119,3 +154,73 @@ fn test_declarative_failures_are_caused_by_msg() {
|
||||
fn test_declarative_failures_can_with_format_expr() {
|
||||
assert_build("fail \"@ is a failure!\" % (1);");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assert_just_keyword_compile_failures() {
|
||||
assert_build_failure(
|
||||
"assert ",
|
||||
vec![
|
||||
Regex::new(r"line: 1, column: 1").unwrap(),
|
||||
Regex::new(r"Expected Tuple \{ok=<bool>, desc=<str>\}: at <eval> line: 1, column: 8")
|
||||
.unwrap(),
|
||||
Regex::new(r"Expected Expression: at <eval> line: 1, column: 8").unwrap(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assert_partial_tuple_compile_failures() {
|
||||
assert_build_failure(
|
||||
"assert {",
|
||||
vec![
|
||||
Regex::new(r"line: 1, column: 1").unwrap(),
|
||||
Regex::new(r"Expected Tuple \{ok=<bool>, desc=<str>\}: at <eval> line: 1, column: 8")
|
||||
.unwrap(),
|
||||
Regex::new(r"Expected \(\}\) Instead is \(\): at <eval> line: 1, column: 9").unwrap(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assert_partial_tuple_missing_ok_compile_failures() {
|
||||
assert_build_failure(
|
||||
"assert {};",
|
||||
vec![
|
||||
Regex::new(r"0 - NOT OK: TYPE FAIL - Expected Boolean field ok in tuple \{").unwrap(),
|
||||
Regex::new(r"line: 1, column: 8").unwrap(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assert_partial_tuple_bad_ok_compile_failures() {
|
||||
assert_build_failure(
|
||||
"assert { ok = 1, };",
|
||||
vec![
|
||||
Regex::new(r"0 - NOT OK: TYPE FAIL - Expected Boolean field ok in tuple \{").unwrap(),
|
||||
Regex::new(r"line: 1, column: 8").unwrap(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assert_partial_tuple_missing_desc_compile_failures() {
|
||||
assert_build_failure(
|
||||
"assert { ok=true, };",
|
||||
vec![
|
||||
Regex::new(r"0 - NOT OK: TYPE FAIL - Expected String field desc in tuple \{").unwrap(),
|
||||
Regex::new(r"line: 1, column: 8").unwrap(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assert_partial_tuple_bad_desc_compile_failures() {
|
||||
assert_build_failure(
|
||||
"assert { ok=true, desc = 1 };",
|
||||
vec![
|
||||
Regex::new(r"0 - NOT OK: TYPE FAIL - Expected String field desc in tuple \{").unwrap(),
|
||||
Regex::new(r"line: 1, column: 8").unwrap(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -1535,7 +1535,7 @@ impl<'a> FileBuilder<'a> {
|
||||
&Val::Boolean(b) => b,
|
||||
_ => {
|
||||
let msg = format!(
|
||||
"TYPE FAIL - Expected Boolean field ok in tuple {}, line: {} column: {}",
|
||||
"TYPE FAIL - Expected Boolean field ok in tuple {}, line: {}, column: {}",
|
||||
ok.as_ref(), expr.pos().line, expr.pos().column
|
||||
);
|
||||
self.record_assert_result(&msg, false);
|
||||
@ -1544,7 +1544,7 @@ impl<'a> FileBuilder<'a> {
|
||||
},
|
||||
None => {
|
||||
let msg = format!(
|
||||
"TYPE FAIL - Expected Boolean field ok in tuple {}, line: {} column: {}",
|
||||
"TYPE FAIL - Expected Boolean field ok in tuple {}, line: {}, column: {}",
|
||||
ok.as_ref(), expr.pos().line, expr.pos().column
|
||||
);
|
||||
self.record_assert_result(&msg, false);
|
||||
@ -1556,7 +1556,7 @@ impl<'a> FileBuilder<'a> {
|
||||
Val::Str(ref s) => s.clone(),
|
||||
_ => {
|
||||
let msg = format!(
|
||||
"TYPE FAIL - Expected Boolean field desc in tuple {} line: {} column: {}",
|
||||
"TYPE FAIL - Expected String field desc in tuple {} line: {}, column: {}",
|
||||
ok, expr.pos().line, expr.pos().column
|
||||
);
|
||||
self.record_assert_result(&msg, false);
|
||||
@ -1565,7 +1565,7 @@ impl<'a> FileBuilder<'a> {
|
||||
},
|
||||
None => {
|
||||
let msg = format!(
|
||||
"TYPE FAIL - Expected Boolean field desc in tuple {} line: {} column: {}\n",
|
||||
"TYPE FAIL - Expected String field desc in tuple {} line: {}, column: {}\n",
|
||||
ok, expr.pos().line, expr.pos().column
|
||||
);
|
||||
self.record_assert_result(&msg, false);
|
||||
|
@ -81,7 +81,7 @@ impl BuildError {
|
||||
};
|
||||
write!(
|
||||
w,
|
||||
"{} at {} line: {} column: {}\nCaused By:\n\t{} ",
|
||||
"{} at {} line: {}, column: {}\nCaused By:\n\t{} ",
|
||||
self.err_type, file, self.pos.line, self.pos.column, self.msg
|
||||
)?;
|
||||
Ok(())
|
||||
|
@ -100,13 +100,17 @@ impl<'a> Positioned for OffsetStrIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> InputIter for OffsetStrIter<'a> {}
|
||||
impl<'a> InputIter for OffsetStrIter<'a> {
|
||||
fn curr(&self) -> Self::Item {
|
||||
self.clone().peek_next().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SliceIter<'a, Token>> for Position {
|
||||
fn from(source: &'a SliceIter<'a, Token>) -> Self {
|
||||
match source.peek_next() {
|
||||
Some(t) => t.pos.clone(),
|
||||
None => Position::new(0, 0, 0),
|
||||
None => source.curr().pos.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -733,7 +733,7 @@ fn expression(input: SliceIter<Token>) -> ParseResult<Expression> {
|
||||
let _input = input.clone();
|
||||
match trace_parse!(_input, op_expression) {
|
||||
Result::Incomplete(i) => Result::Incomplete(i),
|
||||
Result::Fail(_) => trace_parse!(input, non_op_expression),
|
||||
Result::Fail(_) => trace_parse!(input, wrap_err!(non_op_expression, "Expected Expression")),
|
||||
Result::Abort(e) => Result::Abort(e),
|
||||
Result::Complete(rest, expr) => Result::Complete(rest, expr),
|
||||
}
|
||||
@ -782,7 +782,7 @@ make_fn!(
|
||||
assert_statement<SliceIter<Token>, Statement>,
|
||||
do_each!(
|
||||
_ => word!("assert"),
|
||||
expr => must!(expression),
|
||||
expr => wrap_err!(must!(expression), "Expected Tuple {ok=<bool>, desc=<str>}"),
|
||||
_ => must!(punct!(";")),
|
||||
(Statement::Assert(expr))
|
||||
)
|
||||
|
@ -630,7 +630,7 @@ macro_rules! match_token {
|
||||
} else {
|
||||
Result::Fail(Error::new(
|
||||
format!("Expected {} Instead is ({})", $msg, tok.fragment),
|
||||
Box::new(i_),
|
||||
Box::new($i.clone()),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user