mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
FEATURE: Use a better DSL for unit tests.
* Assert now requires a tuple instead of a string containing statements. * We include a helpful ucg based unit testing module. Fixes: #26
This commit is contained in:
parent
f022e71c0c
commit
d989e47706
@ -3,3 +3,4 @@ script:
|
||||
- cargo build --verbose
|
||||
- cargo test --verbose
|
||||
- cargo run -- test integration_tests
|
||||
- cargo run -- test -r std/tests
|
||||
|
15
Makefile
Normal file
15
Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
all: test build
|
||||
|
||||
build:
|
||||
cargo build
|
||||
|
||||
test: unit integration stdlibtest
|
||||
|
||||
unit:
|
||||
cargo test
|
||||
|
||||
integration: unit
|
||||
cargo run -- test -r integration_tests
|
||||
|
||||
stdlibtest: integration
|
||||
cargo run -- test -r std/tests
|
@ -54,24 +54,26 @@ configuration or the results of test assertions.
|
||||
|
||||
### Assert Statements
|
||||
|
||||
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 of unit testing
|
||||
for your configurations. It starts with the `assert` keyword followed by a valid block
|
||||
of UCG statements delimited by `|` characters. The final statement in the block
|
||||
must evaluate to a boolean expression.
|
||||
The assert statement defines an expression that must evaluate to tuple with an
|
||||
ok field that is either true or false and a desc field that is a string. 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 of unit
|
||||
testing for your configurations. It starts with the `assert` keyword followed
|
||||
by a valid ucg expression.
|
||||
|
||||
```
|
||||
assert |
|
||||
host == "www.example.com";
|
||||
|;
|
||||
assert {
|
||||
ok = host == "www.example.com",
|
||||
desc = "Host is www.example.com",
|
||||
};
|
||||
|
||||
assert |
|
||||
select qa, 443, {
|
||||
assert {
|
||||
ok = select qa, 443, {
|
||||
qa = 80,
|
||||
prod = 443,
|
||||
} == 443;
|
||||
|;
|
||||
} == 443,
|
||||
desc = "select default was 443",
|
||||
};
|
||||
```
|
||||
|
||||
Assert statements are only evaluated when running the `ucg test` command. That
|
||||
|
@ -1,17 +1,17 @@
|
||||
assert |macro |;
|
||||
assert |{ foo = hello world}|;
|
||||
assert |{ foo = "hello world"|;
|
||||
assert |{ = }|;
|
||||
assert |"|;
|
||||
assert |=|;
|
||||
assert {macro };
|
||||
assert {{ foo = hello world}};
|
||||
assert {{ foo = "hello world"};
|
||||
assert {{ = }};
|
||||
assert {"};
|
||||
assert {=};
|
||||
|
||||
assert |let |;
|
||||
assert |let foo |;
|
||||
assert |let foo =|;
|
||||
assert |import |;
|
||||
assert |import foo |;
|
||||
assert |out |;
|
||||
assert |out "|;
|
||||
assert |out json|;
|
||||
assert {let };
|
||||
assert {let foo };
|
||||
assert {let foo =};
|
||||
assert {import };
|
||||
assert {import foo };
|
||||
assert {out };
|
||||
assert {out "};
|
||||
assert {out json};
|
||||
|
||||
assert |let env = 1;|;
|
||||
assert {let env = 1;};
|
@ -16,33 +16,42 @@ let list = [1, 2, 3];
|
||||
let list2 = list;
|
||||
let list3 = [1, 2];
|
||||
|
||||
assert |
|
||||
one == one;
|
||||
|;
|
||||
assert |
|
||||
one == one;
|
||||
|;
|
||||
assert |
|
||||
one >= one;
|
||||
|;
|
||||
assert |
|
||||
two > one;
|
||||
|;
|
||||
assert |
|
||||
two >= two;
|
||||
|;
|
||||
assert |
|
||||
tpl1 == tpl2;
|
||||
|;
|
||||
assert |
|
||||
tpl1 != tpl3;
|
||||
|;
|
||||
assert |
|
||||
list == list2;
|
||||
|;
|
||||
assert |
|
||||
list != list3;
|
||||
|;
|
||||
assert {
|
||||
ok = one == one,
|
||||
desc = "one == one",
|
||||
};
|
||||
assert {
|
||||
ok = one == one,
|
||||
desc = "one == one",
|
||||
};
|
||||
assert {
|
||||
ok = one >= one,
|
||||
desc = "one >= one"
|
||||
};
|
||||
assert {
|
||||
ok = two > one,
|
||||
desc = "two > one"
|
||||
};
|
||||
assert {
|
||||
ok = two >= two,
|
||||
desc = "two >= two",
|
||||
};
|
||||
assert {
|
||||
ok = tpl1 == tpl2,
|
||||
desc = "tpl1 == tpl2"
|
||||
};
|
||||
assert {
|
||||
ok = tpl1 != tpl3,
|
||||
desc = "tpl1 != tpl3",
|
||||
};
|
||||
assert {
|
||||
ok = list == list2,
|
||||
desc = "list == list2",
|
||||
};
|
||||
assert {
|
||||
ok = list != list3,
|
||||
desc = "list != list3",
|
||||
};
|
||||
|
||||
// Deep Comparisons
|
||||
let tpl4 = {
|
||||
@ -58,73 +67,105 @@ let less = {
|
||||
foo = "bar"
|
||||
};
|
||||
|
||||
assert |
|
||||
tpl4.inner == copy.inner;
|
||||
|;
|
||||
assert |
|
||||
tpl4.inner.fld == copy.inner.fld;
|
||||
|;
|
||||
assert |
|
||||
tpl4.lst == copy.lst;
|
||||
|;
|
||||
assert |
|
||||
tpl4.foo == copy.foo;
|
||||
|;
|
||||
assert |
|
||||
tpl4 == copy;
|
||||
|;
|
||||
assert |
|
||||
tpl4 != extra;
|
||||
|;
|
||||
assert |
|
||||
tpl4 != less;
|
||||
|;
|
||||
assert {
|
||||
ok = tpl4.inner == copy.inner,
|
||||
desc = "tpl4.inner == copy.inner",
|
||||
};
|
||||
assert {
|
||||
ok = tpl4.inner.fld == copy.inner.fld,
|
||||
desc = "tpl4.inner.fld == copy.inner.fld",
|
||||
};
|
||||
assert {
|
||||
ok = tpl4.lst == copy.lst,
|
||||
desc = "tpl4.lst == copy.lst",
|
||||
};
|
||||
assert {
|
||||
ok = tpl4.foo == copy.foo,
|
||||
desc = "tpl4.foo == copy.foo",
|
||||
};
|
||||
assert {
|
||||
ok = tpl4 == copy,
|
||||
desc = "tpl4 == copy",
|
||||
};
|
||||
assert {
|
||||
ok = tpl4 != extra,
|
||||
desc = "tpl4 != extra",
|
||||
};
|
||||
assert {
|
||||
ok = tpl4 != less,
|
||||
desc = "tpl4 != less",
|
||||
};
|
||||
|
||||
assert |
|
||||
[[1, 2, [3]], 4] == [[1, 2, [3]], 4];
|
||||
|;
|
||||
assert {
|
||||
ok = [[1, 2, [3]], 4] == [[1, 2, [3]], 4],
|
||||
desc = "[[1, 2, [3]], 4] == [[1, 2, [3]], 4]",
|
||||
};
|
||||
|
||||
assert |
|
||||
[[1, 2, [3]], 4] != [[1, 2, [6]], 4];
|
||||
|;
|
||||
assert {
|
||||
ok = [[1, 2, [3]], 4] != [[1, 2, [6]], 4],
|
||||
desc = "[[1, 2, [3]], 4] != [[1, 2, [6]], 4]",
|
||||
};
|
||||
|
||||
// Expression comparisons
|
||||
assert |2 == 1+1;|;
|
||||
assert |(1+1) == 2;|;
|
||||
assert |(1+1) == (1+1);|;
|
||||
assert {
|
||||
ok = 2 == 1+1,
|
||||
desc = "2 == 1+1",
|
||||
};
|
||||
assert {
|
||||
ok = (1+1) == 2,
|
||||
desc = "(1+1) == 2",
|
||||
};
|
||||
assert {
|
||||
ok = (1+1) == (1+1),
|
||||
desc = "(1+1) == (1+1)",
|
||||
};
|
||||
let want = "foo";
|
||||
assert |
|
||||
select want, 1, { foo=2, } == 2;
|
||||
|;
|
||||
assert {
|
||||
ok = select want, 1, { foo=2, } == 2,
|
||||
desc = "select want, 1, { foo=2, } == 2",
|
||||
};
|
||||
|
||||
// Contains comparison operators.
|
||||
assert |
|
||||
"foo" in {
|
||||
assert {
|
||||
ok = "foo" in {
|
||||
foo = "bar",
|
||||
},
|
||||
desc = "\"foo\" in {
|
||||
foo = \"bar\",
|
||||
}
|
||||
",
|
||||
};
|
||||
|;
|
||||
assert |
|
||||
foo in {
|
||||
assert {
|
||||
ok = foo in {
|
||||
foo = "bar",
|
||||
},
|
||||
desc = "foo in {
|
||||
foo = \"bar\",
|
||||
}",
|
||||
};
|
||||
assert {
|
||||
ok = "foo" in ["foo", "bar"],
|
||||
desc = "\"foo\" in [\"foo\", \"bar\"]",
|
||||
};
|
||||
assert {
|
||||
ok = "foo" in ["bar", "foo", "bar"],
|
||||
desc = "\"foo\" in [\"bar\", \"foo\", \"bar\"]",
|
||||
};
|
||||
assert {
|
||||
ok = { foo = 1 } in ["foo", { foo = 1 }],
|
||||
desc = "{ foo = 1 } in [\"foo\", { foo = 1 }]",
|
||||
};
|
||||
assert {
|
||||
ok = true in [ "foo" in {foo = 1}, false ],
|
||||
desc = "true in [ \"foo\" in {foo = 1}, false ]",
|
||||
};
|
||||
|;
|
||||
assert |
|
||||
"foo" in ["foo", "bar"];
|
||||
|;
|
||||
assert |
|
||||
"foo" in ["bar", "foo", "bar"];
|
||||
|;
|
||||
assert |
|
||||
{ foo = 1 } in ["foo", { foo = 1 }];
|
||||
|;
|
||||
assert |
|
||||
true in [ "foo" in {foo = 1}, false ];
|
||||
|;
|
||||
|
||||
assert |
|
||||
"foo" ~ "o+";
|
||||
|;
|
||||
assert {
|
||||
ok = "foo" ~ "o+",
|
||||
desc = "\"foo\" ~ \"o+\""
|
||||
};
|
||||
|
||||
assert |
|
||||
"foo" !~ "bar";
|
||||
|;
|
||||
assert {
|
||||
ok = "foo" !~ "bar",
|
||||
desc = "\"foo\" !~ \"bar\"",
|
||||
};
|
@ -1,6 +1,8 @@
|
||||
assert |
|
||||
"hello " + "world" == "hello world";
|
||||
|;
|
||||
assert |
|
||||
[1, 2, 3] + [4, 5, 6] == [1, 2, 3, 4, 5, 6];
|
||||
|;
|
||||
assert {
|
||||
ok = "hello " + "world" == "hello world",
|
||||
desc = "\"hello \" + \"world\" == \"hello world\"",
|
||||
};
|
||||
assert {
|
||||
ok = [1, 2, 3] + [4, 5, 6] == [1, 2, 3, 4, 5, 6],
|
||||
desc = "[1, 2, 3] + [4, 5, 6] == [1, 2, 3, 4, 5, 6]",
|
||||
};
|
@ -2,6 +2,7 @@ let empty = NULL;
|
||||
let tpl = {
|
||||
foo = NULL,
|
||||
};
|
||||
assert |
|
||||
tpl.foo == empty;
|
||||
|;
|
||||
assert {
|
||||
ok = tpl.foo == empty,
|
||||
desc = "tpl.foo == empty",
|
||||
};
|
@ -1,12 +1,16 @@
|
||||
assert |
|
||||
"hello @" % ("world") == "hello world";
|
||||
|;
|
||||
assert |
|
||||
"1 @ @" % (2, 3) == "1 2 3";
|
||||
|;
|
||||
assert |
|
||||
"@ or @" % (true, false) == "true or false";
|
||||
|;
|
||||
assert |
|
||||
"@" % (NULL) == "NULL";
|
||||
|;
|
||||
assert {
|
||||
ok = "hello @" % ("world") == "hello world",
|
||||
desc = "\"hello @\" % (\"world\") == \"hello world\"",
|
||||
};
|
||||
assert {
|
||||
ok = "1 @ @" % (2, 3) == "1 2 3",
|
||||
desc = "\"1 @ @\" % (2, 3) == \"1 2 3\"",
|
||||
};
|
||||
assert {
|
||||
ok = "@ or @" % (true, false) == "true or false",
|
||||
desc = "\"@ or @\" % (true, false) == \"true or false\"",
|
||||
};
|
||||
assert {
|
||||
ok = "@" % (NULL) == "NULL",
|
||||
desc = "\"@\" % (NULL) == \"NULL\"",
|
||||
};
|
@ -18,48 +18,58 @@ let identity_list_reducer = macro(acc, item) => {
|
||||
result = acc + [item],
|
||||
};
|
||||
|
||||
assert |
|
||||
reduce identity_list_reducer.result [], list1 == list1;
|
||||
|;
|
||||
assert {
|
||||
ok = reduce identity_list_reducer.result [], list1 == list1,
|
||||
desc = "reduce identity_list_reducer.result [], list1 == list1",
|
||||
};
|
||||
|
||||
let nested_list = {
|
||||
list = list1,
|
||||
};
|
||||
|
||||
assert |
|
||||
reduce identity_list_reducer.result [], (nested_list.list) == list1;
|
||||
|;
|
||||
assert {
|
||||
ok = reduce identity_list_reducer.result [], (nested_list.list) == list1,
|
||||
desc = "reduce identity_list_reducer.result [], (nested_list.list) == list1",
|
||||
};
|
||||
|
||||
let list_reducer = macro(acc, item) => {
|
||||
result = acc + item,
|
||||
};
|
||||
|
||||
assert |
|
||||
reduce list_reducer.result 0, list1 == 0 + 1 + 2 + 3 + 4;
|
||||
|;
|
||||
assert {
|
||||
ok = reduce list_reducer.result 0, list1 == 0 + 1 + 2 + 3 + 4,
|
||||
desc = "reduce list_reducer.result 0, list1 == 0 + 1 + 2 + 3 + 4",
|
||||
};
|
||||
|
||||
assert |
|
||||
map mapper.result list1 == [2, 3, 4, 5];
|
||||
|;
|
||||
assert |
|
||||
(map mapper.result [1, 2, 3, 4]) == [2, 3, 4, 5];
|
||||
|;
|
||||
assert |
|
||||
map mapper.result [1, 2, 3, 4] == [2, 3, 4, 5];
|
||||
|;
|
||||
assert {
|
||||
ok = map mapper.result list1 == [2, 3, 4, 5],
|
||||
desc = "map mapper.result list1 == [2, 3, 4, 5]",
|
||||
};
|
||||
assert {
|
||||
ok = (map mapper.result [1, 2, 3, 4]) == [2, 3, 4, 5],
|
||||
desc = "(map mapper.result [1, 2, 3, 4]) == [2, 3, 4, 5]",
|
||||
};
|
||||
assert {
|
||||
ok = map mapper.result [1, 2, 3, 4] == [2, 3, 4, 5],
|
||||
desc = "map mapper.result [1, 2, 3, 4] == [2, 3, 4, 5]",
|
||||
};
|
||||
|
||||
assert |
|
||||
filter filtrator.result list2 == ["foo", "foo"];
|
||||
|;
|
||||
assert |
|
||||
(filter filtrator.result ["foo", "bar", "foo", "bar"]) == ["foo", "foo"];
|
||||
|;
|
||||
assert |
|
||||
filter filtrator.result ["foo", "bar", "foo", "bar"] == ["foo", "foo"];
|
||||
|;
|
||||
assert |
|
||||
filter boolfiltrator.result [1, 2, 3, 4, 5, 6, 7] == [1, 2, 3, 4];
|
||||
|;
|
||||
assert {
|
||||
ok = filter filtrator.result list2 == ["foo", "foo"],
|
||||
desc = "filter filtrator.result list2 == [\"foo\", \"foo\"]",
|
||||
};
|
||||
assert {
|
||||
ok = (filter filtrator.result ["foo", "bar", "foo", "bar"]) == ["foo", "foo"],
|
||||
desc = "(filter filtrator.result [\"foo\", \"bar\", \"foo\", \"bar\"]) == [\"foo\", \"foo\"]",
|
||||
};
|
||||
assert {
|
||||
ok = filter filtrator.result ["foo", "bar", "foo", "bar"] == ["foo", "foo"],
|
||||
desc = "filter filtrator.result [\"foo\", \"bar\", \"foo\", \"bar\"] == [\"foo\", \"foo\"]",
|
||||
};
|
||||
assert {
|
||||
ok = filter boolfiltrator.result [1, 2, 3, 4, 5, 6, 7] == [1, 2, 3, 4],
|
||||
desc = "filter boolfiltrator.result [1, 2, 3, 4, 5, 6, 7] == [1, 2, 3, 4]",
|
||||
};
|
||||
|
||||
// Tuple processing
|
||||
let test_tpl = {
|
||||
@ -71,9 +81,10 @@ let identity_tpl_mapper = macro(name, val) => {
|
||||
result = [name, val],
|
||||
};
|
||||
|
||||
assert |
|
||||
map identity_tpl_mapper.result test_tpl == test_tpl;
|
||||
|;
|
||||
assert {
|
||||
ok = map identity_tpl_mapper.result test_tpl == test_tpl,
|
||||
desc = "map identity_tpl_mapper.result test_tpl == test_tpl",
|
||||
};
|
||||
|
||||
let tpl_mapper = macro(name, val) => {
|
||||
result = select name, [name, val], {
|
||||
@ -82,9 +93,10 @@ let tpl_mapper = macro(name, val) => {
|
||||
},
|
||||
};
|
||||
|
||||
assert |
|
||||
map tpl_mapper.result test_tpl == {foo = "barbar", cute = "pygmy"};
|
||||
|;
|
||||
assert {
|
||||
ok = map tpl_mapper.result test_tpl == {foo = "barbar", cute = "pygmy"},
|
||||
desc = "map tpl_mapper.result test_tpl == {foo = \"barbar\", cute = \"pygmy\"}",
|
||||
};
|
||||
|
||||
let identity_tpl_filter = macro(name, val) => {
|
||||
result = true,
|
||||
@ -95,13 +107,15 @@ let tpl_filter = macro(name, val) => {
|
||||
result = name != "foo",
|
||||
};
|
||||
|
||||
assert |
|
||||
filter identity_tpl_filter.result test_tpl == test_tpl;
|
||||
|;
|
||||
assert {
|
||||
ok = filter identity_tpl_filter.result test_tpl == test_tpl,
|
||||
desc = "filter identity_tpl_filter.result test_tpl == test_tpl",
|
||||
};
|
||||
|
||||
assert |
|
||||
filter tpl_filter.result test_tpl == { quux = "baz" };
|
||||
|;
|
||||
assert {
|
||||
ok = filter tpl_filter.result test_tpl == { quux = "baz" },
|
||||
desc = "filter tpl_filter.result test_tpl == { quux = \"baz\" }",
|
||||
};
|
||||
|
||||
let tpl_reducer = macro(acc, name, val) => {
|
||||
result = acc{
|
||||
@ -110,6 +124,7 @@ let tpl_reducer = macro(acc, name, val) => {
|
||||
},
|
||||
};
|
||||
|
||||
assert |
|
||||
reduce tpl_reducer.result {keys = [], vals = []}, test_tpl == {keys = ["foo", "quux"], vals = ["bar", "baz"]};
|
||||
|;
|
||||
assert {
|
||||
ok = reduce tpl_reducer.result {keys = [], vals = []}, test_tpl == {keys = ["foo", "quux"], vals = ["bar", "baz"]},
|
||||
desc = "reduce tpl_reducer.result {keys = [], vals = []}, test_tpl == {keys = [\"foo\", \"quux\"], vals = [\"bar\", \"baz\"]}",
|
||||
};
|
@ -1,14 +1,17 @@
|
||||
let script = include str "./include_example.sh";
|
||||
assert |
|
||||
script == "#!/usr/bin/env bash
|
||||
echo \"included\"";
|
||||
|;
|
||||
assert {
|
||||
ok = script == "#!/usr/bin/env bash
|
||||
echo \"included\"",
|
||||
desc = "script was successfully included",
|
||||
};
|
||||
let expected = "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvICJpbmNsdWRlZCI=";
|
||||
let base64 = include b64 "./include_example.sh";
|
||||
assert |
|
||||
base64 == expected;
|
||||
|;
|
||||
assert {
|
||||
ok = base64 == expected,
|
||||
desc = "base64 == expected",
|
||||
};
|
||||
let base64safe = include b64urlsafe "./include_example.sh";
|
||||
assert |
|
||||
base64safe == expected;
|
||||
|;
|
||||
assert {
|
||||
ok = base64safe == expected,
|
||||
desc = "base64safe == expected",
|
||||
};
|
@ -2,10 +2,12 @@ let empty_list = [];
|
||||
|
||||
let concatenated = ["foo"] + ["bar"];
|
||||
|
||||
assert |
|
||||
concatenated == ["foo", "bar"];
|
||||
|;
|
||||
assert {
|
||||
ok = concatenated == ["foo", "bar"],
|
||||
desc = "concatenated == [\"foo\", \"bar\"]",
|
||||
};
|
||||
|
||||
assert |
|
||||
concatenated + empty_list == ["foo", "bar"];
|
||||
|;
|
||||
assert {
|
||||
ok = concatenated + empty_list == ["foo", "bar"],
|
||||
desc = "concatenated + empty_list == [\"foo\", \"bar\"]",
|
||||
};
|
@ -19,31 +19,39 @@ let noargresult = noargmacro();
|
||||
let simpleresult = simplemacro(1, 2, 3);
|
||||
let cplxresult = cplxmacro(1, "We", 3.0);
|
||||
|
||||
assert |
|
||||
noargresult.field1 == "value";
|
||||
|;
|
||||
assert |
|
||||
simpleresult.field1 == 1;
|
||||
|;
|
||||
assert |
|
||||
simpleresult.field2 == 2;
|
||||
|;
|
||||
assert |
|
||||
simpleresult.field3 == 3;
|
||||
|;
|
||||
assert {
|
||||
ok = noargresult.field1 == "value",
|
||||
desc = "noargresult.field1 == \"value\"",
|
||||
};
|
||||
assert {
|
||||
ok = simpleresult.field1 == 1,
|
||||
desc = "simpleresult.field1 == 1",
|
||||
};
|
||||
assert {
|
||||
ok = simpleresult.field2 == 2,
|
||||
desc = "simpleresult.field2 == 2",
|
||||
};
|
||||
assert {
|
||||
ok = simpleresult.field3 == 3,
|
||||
desc = "simpleresult.field3 == 3",
|
||||
};
|
||||
|
||||
assert |
|
||||
cplxresult.field1 == 2;
|
||||
|;
|
||||
assert |
|
||||
cplxresult.field2 == "We are here";
|
||||
|;
|
||||
assert |
|
||||
cplxresult.field3 == 2.0;
|
||||
|;
|
||||
assert |
|
||||
cplxresult.boolfield == true;
|
||||
|;
|
||||
assert {
|
||||
ok = cplxresult.field1 == 2,
|
||||
desc = "cplxresult.field1 == 2",
|
||||
};
|
||||
assert {
|
||||
ok = cplxresult.field2 == "We are here",
|
||||
desc = "cplxresult.field2 == \"We are here\"",
|
||||
};
|
||||
assert {
|
||||
ok = cplxresult.field3 == 2.0,
|
||||
desc = "cplxresult.field3 == 2.0",
|
||||
};
|
||||
assert {
|
||||
ok = cplxresult.boolfield == true,
|
||||
desc = "cplxresult.boolfield == true",
|
||||
};
|
||||
|
||||
let macro_tpl_arg = macro(tpl) => {
|
||||
result = tpl.field,
|
||||
@ -53,6 +61,7 @@ let arg_tpl = {
|
||||
field = "value",
|
||||
};
|
||||
|
||||
assert |
|
||||
macro_tpl_arg(arg_tpl).result == arg_tpl.field;
|
||||
|;
|
||||
assert {
|
||||
ok = macro_tpl_arg(arg_tpl).result == arg_tpl.field,
|
||||
desc = "macro_tpl_arg(arg_tpl).result == arg_tpl.field",
|
||||
};
|
@ -11,14 +11,16 @@ let test_simple_mod = module {
|
||||
};
|
||||
|
||||
let simple_mod_instance = test_simple_mod{};
|
||||
assert |
|
||||
simple_mod_instance.value == "value";
|
||||
|;
|
||||
assert {
|
||||
ok = simple_mod_instance.value == "value",
|
||||
desc = "simple_mod_instance.value == \"value\"",
|
||||
};
|
||||
|
||||
let simple_mod_with_args = test_simple_mod{arg = "othervalue"};
|
||||
assert |
|
||||
simple_mod_with_args.value == "othervalue";
|
||||
|;
|
||||
assert {
|
||||
ok = simple_mod_with_args.value == "othervalue",
|
||||
desc = "simple_mod_with_args.value == \"othervalue\"",
|
||||
};
|
||||
|
||||
let embedded_mod = module {
|
||||
deep_value = "None",
|
||||
@ -41,19 +43,23 @@ let embedded_mod = module {
|
||||
|
||||
let embedded_default_params = embedded_mod{};
|
||||
|
||||
assert |
|
||||
embedded_default_params.embedded.value == "None";
|
||||
|;
|
||||
assert {
|
||||
ok = embedded_default_params.embedded.value == "None",
|
||||
desc = "embedded_default_params.embedded.value == \"None\"",
|
||||
};
|
||||
|
||||
assert |
|
||||
embedded_default_params.env_name == "qa";
|
||||
|;
|
||||
assert {
|
||||
ok = embedded_default_params.env_name == "qa",
|
||||
desc = "embedded_default_params.env_name == \"qa\"",
|
||||
};
|
||||
|
||||
let embedded_with_params = embedded_mod{deep_value = "Some"};
|
||||
|
||||
assert |
|
||||
embedded_with_params.embedded.value == "Some";
|
||||
|;
|
||||
assert |
|
||||
embedded_mod{dep_value="Some"}.embedded_def{}.value == "None";
|
||||
|;
|
||||
assert {
|
||||
ok = embedded_with_params.embedded.value == "Some",
|
||||
desc = "embedded_with_params.embedded.value == \"Some\"",
|
||||
};
|
||||
assert {
|
||||
ok = embedded_mod{dep_value="Some"}.embedded_def{}.value == "None",
|
||||
desc = "embedded_mod{dep_value=\"Some\"}.embedded_def{}.value == \"None\"",
|
||||
};
|
@ -1,42 +1,54 @@
|
||||
assert |
|
||||
2 * 2 + 1 == 5;
|
||||
|;
|
||||
assert |
|
||||
2 + 2 * 3 == 8;
|
||||
|;
|
||||
assert |
|
||||
2 * (2 + 1) == 6;
|
||||
|;
|
||||
assert |
|
||||
2 * 2 + 1 > 4;
|
||||
|;
|
||||
assert |
|
||||
2 * 2 + 1 < 6;
|
||||
|;
|
||||
assert |
|
||||
2 * 2 + 1 >= 5;
|
||||
|;
|
||||
assert |
|
||||
2 * 2 + 1 <= 5;
|
||||
|;
|
||||
assert |
|
||||
2 / 2 == 1;
|
||||
|;
|
||||
assert |
|
||||
2 - 1 == 1;
|
||||
|;
|
||||
assert |
|
||||
1 + 1 + 1 + 1 == 4;
|
||||
|;
|
||||
assert |
|
||||
1 + 1 + 2 * 2 + 1 + 1 == 1 + 1 + (2 * 2) + 1 + 1;
|
||||
|;
|
||||
assert {
|
||||
ok = 2 * 2 + 1 == 5,
|
||||
desc = "2 * 2 + 1 == 5",
|
||||
};
|
||||
assert {
|
||||
ok = 2 + 2 * 3 == 8,
|
||||
desc = "2 + 2 * 3 == 8",
|
||||
};
|
||||
assert {
|
||||
ok = 2 * (2 + 1) == 6,
|
||||
desc = "2 * (2 + 1) == 6",
|
||||
};
|
||||
assert {
|
||||
ok = 2 * 2 + 1 > 4,
|
||||
desc = "2 * 2 + 1 > 4",
|
||||
};
|
||||
assert {
|
||||
ok = 2 * 2 + 1 < 6,
|
||||
desc = "2 * 2 + 1 < 6",
|
||||
};
|
||||
assert {
|
||||
ok = 2 * 2 + 1 >= 5,
|
||||
desc = "2 * 2 + 1 >= 5",
|
||||
};
|
||||
assert {
|
||||
ok = 2 * 2 + 1 <= 5,
|
||||
desc = "2 * 2 + 1 <= 5",
|
||||
};
|
||||
assert {
|
||||
ok = 2 / 2 == 1,
|
||||
desc = "2 / 2 == 1",
|
||||
};
|
||||
assert {
|
||||
ok = 2 - 1 == 1,
|
||||
desc = "2 - 1 == 1",
|
||||
};
|
||||
assert {
|
||||
ok = 1 + 1 + 1 + 1 == 4,
|
||||
desc = "1 + 1 + 1 + 1 == 4",
|
||||
};
|
||||
assert {
|
||||
ok = 1 + 1 + 2 * 2 + 1 + 1 == 1 + 1 + (2 * 2) + 1 + 1,
|
||||
desc = "1 + 1 + 2 * 2 + 1 + 1 == 1 + 1 + (2 * 2) + 1 + 1",
|
||||
};
|
||||
let tpl = {
|
||||
one = {
|
||||
two = 12,
|
||||
},
|
||||
};
|
||||
|
||||
assert |
|
||||
1 + tpl.one.two * 2 + 3 == 28;
|
||||
|;
|
||||
assert {
|
||||
ok = 1 + tpl.one.two * 2 + 3 == 28,
|
||||
desc = "1 + tpl.one.two * 2 + 3 == 28",
|
||||
};
|
@ -11,12 +11,14 @@ let defaultgot = select badwant, "OOPS", {
|
||||
door2 = "you lose",
|
||||
};
|
||||
|
||||
assert |
|
||||
got == "grand prize";
|
||||
|;
|
||||
assert |
|
||||
defaultgot == "OOPS";
|
||||
|;
|
||||
assert {
|
||||
ok = got == "grand prize",
|
||||
desc = "got == \"grand prize\"",
|
||||
};
|
||||
assert {
|
||||
ok = defaultgot == "OOPS",
|
||||
desc = "defaultgot == \"OOPS\"",
|
||||
};
|
||||
|
||||
// select inside a macro
|
||||
|
||||
@ -29,21 +31,25 @@ let condmacro = macro(arg) => {
|
||||
|
||||
let result = condmacro("opt1");
|
||||
|
||||
assert |
|
||||
condmacro("opt1") == {output = "yay"};
|
||||
|;
|
||||
assert |
|
||||
condmacro("opt2") == {output = "boo"};
|
||||
|;
|
||||
assert |
|
||||
condmacro("invalid") == {output = NULL};
|
||||
|;
|
||||
assert {
|
||||
ok = condmacro("opt1") == {output = "yay"},
|
||||
desc = "condmacro(\"opt1\") == {output = \"yay\"}",
|
||||
};
|
||||
assert {
|
||||
ok = condmacro("opt2") == {output = "boo"},
|
||||
desc = "condmacro(\"opt2\") == {output = \"boo\"}",
|
||||
};
|
||||
assert {
|
||||
ok = condmacro("invalid") == {output = NULL},
|
||||
desc = "condmacro(\"invalid\") == {output = NULL}",
|
||||
};
|
||||
|
||||
let iflike = select true, "default", {
|
||||
true = "I was true",
|
||||
false = "I was false",
|
||||
};
|
||||
|
||||
assert |
|
||||
iflike == "I was true";
|
||||
|;
|
||||
assert {
|
||||
ok = iflike == "I was true",
|
||||
desc = "iflike == \"I was true\"",
|
||||
};
|
@ -10,44 +10,55 @@ let testmacro = macro(arg) => {
|
||||
output = arg,
|
||||
};
|
||||
|
||||
assert |
|
||||
list.0 == 1;
|
||||
|;
|
||||
assert |
|
||||
list.1 == 2;
|
||||
|;
|
||||
assert |
|
||||
list.3 == 4;
|
||||
|;
|
||||
assert |
|
||||
tuple.field1 == 1;
|
||||
|;
|
||||
assert |
|
||||
tuple.field2 == 3;
|
||||
|;
|
||||
assert |
|
||||
tuple.deeplist.0 == "foo";
|
||||
|;
|
||||
assert |
|
||||
tuple.deeplist.1 == "bar";
|
||||
|;
|
||||
assert |
|
||||
{foo = "bar"}.foo == "bar";
|
||||
|;
|
||||
assert |
|
||||
["one", "two", "three"].0 == "one";
|
||||
|;
|
||||
assert {
|
||||
ok = list.0 == 1,
|
||||
desc = "list.0 == 1",
|
||||
};
|
||||
assert {
|
||||
ok = list.1 == 2,
|
||||
desc = "list.1 == 2",
|
||||
};
|
||||
assert {
|
||||
ok = list.3 == 4,
|
||||
desc = "list.3 == 4",
|
||||
};
|
||||
assert {
|
||||
ok = tuple.field1 == 1,
|
||||
desc = "tuple.field1 == 1",
|
||||
};
|
||||
assert {
|
||||
ok = tuple.field2 == 3,
|
||||
desc = "tuple.field2 == 3",
|
||||
};
|
||||
assert {
|
||||
ok = tuple.deeplist.0 == "foo",
|
||||
desc = "tuple.deeplist.0 == \"foo\"",
|
||||
};
|
||||
assert {
|
||||
ok = tuple.deeplist.1 == "bar",
|
||||
desc = "tuple.deeplist.1 == \"bar\"",
|
||||
};
|
||||
assert {
|
||||
ok = {foo = "bar"}.foo == "bar",
|
||||
desc = "{foo = \"bar\"}.foo == \"bar\"",
|
||||
};
|
||||
assert {
|
||||
ok = ["one", "two", "three"].0 == "one",
|
||||
desc = "[\"one\", \"two\", \"three\"].0 == \"one\"",
|
||||
};
|
||||
|
||||
let macro_for_test = macro() => {
|
||||
foo = "bar",
|
||||
};
|
||||
assert |
|
||||
macro_for_test().foo == "bar";
|
||||
|;
|
||||
assert {
|
||||
ok = macro_for_test().foo == "bar",
|
||||
desc = "macro_for_test().foo == \"bar\"",
|
||||
};
|
||||
|
||||
let mymodule = module { foo = "bar" } => {
|
||||
let foo = mod.foo;
|
||||
};
|
||||
assert |
|
||||
mymodule{}.foo == "bar";
|
||||
|;
|
||||
assert {
|
||||
ok = mymodule{}.foo == "bar",
|
||||
desc = "mymodule{}.foo == \"bar\"",
|
||||
};
|
@ -15,33 +15,42 @@ let nestedtpl = {
|
||||
maybe_val = NULL,
|
||||
};
|
||||
|
||||
assert |
|
||||
simpletpl.foo == "bar";
|
||||
|;
|
||||
assert |
|
||||
stringfieldtpl."field 1" == 1;
|
||||
|;
|
||||
assert |
|
||||
nestedtpl.scalar == 1;
|
||||
|;
|
||||
assert |
|
||||
nestedtpl.maybe_val == NULL;
|
||||
|;
|
||||
assert |
|
||||
nestedtpl.inner.field == "value";
|
||||
|;
|
||||
assert |
|
||||
nestedtpl.list.0 == 1;
|
||||
|;
|
||||
assert |
|
||||
nestedtpl.list.1 == 2;
|
||||
|;
|
||||
assert |
|
||||
nestedtpl.list.2 == 3;
|
||||
|;
|
||||
assert |
|
||||
nestedtpl.list.3 == 4;
|
||||
|;
|
||||
assert {
|
||||
ok = simpletpl.foo == "bar",
|
||||
desc = "simpletpl.foo == \"bar\"",
|
||||
};
|
||||
assert {
|
||||
ok = stringfieldtpl."field 1" == 1,
|
||||
desc = "stringfieldtpl.\"field 1\" == 1",
|
||||
};
|
||||
assert {
|
||||
ok = nestedtpl.scalar == 1,
|
||||
desc = "nestedtpl.scalar == 1",
|
||||
};
|
||||
assert {
|
||||
ok = nestedtpl.maybe_val == NULL,
|
||||
desc = "nestedtpl.maybe_val == NULL",
|
||||
};
|
||||
assert {
|
||||
ok = nestedtpl.inner.field == "value",
|
||||
desc = "nestedtpl.inner.field == \"value\"",
|
||||
};
|
||||
assert {
|
||||
ok = nestedtpl.list.0 == 1,
|
||||
desc = "nestedtpl.list.0 == 1",
|
||||
};
|
||||
assert {
|
||||
ok = nestedtpl.list.1 == 2,
|
||||
desc = "nestedtpl.list.1 == 2",
|
||||
};
|
||||
assert {
|
||||
ok = nestedtpl.list.2 == 3,
|
||||
desc = "nestedtpl.list.2 == 3",
|
||||
};
|
||||
assert {
|
||||
ok = nestedtpl.list.3 == 4,
|
||||
desc = "nestedtpl.list.3 == 4",
|
||||
};
|
||||
|
||||
let nestedcopy = nestedtpl{
|
||||
inner = self.inner{
|
||||
@ -62,18 +71,22 @@ let deepnestedcopy = nestedcopy{
|
||||
},
|
||||
};
|
||||
|
||||
assert |
|
||||
nestedcopy.inner.field2 == 2;
|
||||
|;
|
||||
assert |
|
||||
nestedcopy.inner.inner.field3 == "three";
|
||||
|;
|
||||
assert |
|
||||
deepnestedcopy.inner.inner.field4 == 4;
|
||||
|;
|
||||
assert |
|
||||
deepnestedcopy.maybe_val == "some val";
|
||||
|;
|
||||
assert {
|
||||
ok = nestedcopy.inner.field2 == 2,
|
||||
desc = "nestedcopy.inner.field2 == 2",
|
||||
};
|
||||
assert {
|
||||
ok = nestedcopy.inner.inner.field3 == "three",
|
||||
desc = "nestedcopy.inner.inner.field3 == \"three\"",
|
||||
};
|
||||
assert {
|
||||
ok = deepnestedcopy.inner.inner.field4 == 4,
|
||||
desc = "deepnestedcopy.inner.inner.field4 == 4",
|
||||
};
|
||||
assert {
|
||||
ok = deepnestedcopy.maybe_val == "some val",
|
||||
desc = "deepnestedcopy.maybe_val == \"some val\"",
|
||||
};
|
||||
|
||||
let base_maybe = {
|
||||
real = "A real value",
|
||||
@ -83,38 +96,43 @@ let copy_maybe = base_maybe{
|
||||
real = NULL,
|
||||
};
|
||||
|
||||
assert |
|
||||
copy_maybe.real == NULL;
|
||||
|;
|
||||
assert {
|
||||
ok = copy_maybe.real == NULL,
|
||||
desc = "copy_maybe.real == NULL",
|
||||
};
|
||||
|
||||
let quotedself_tpl = {
|
||||
"self" = "myself",
|
||||
};
|
||||
|
||||
assert |
|
||||
quotedself_tpl."self" == "myself";
|
||||
|;
|
||||
assert {
|
||||
ok = quotedself_tpl."self" == "myself",
|
||||
desc = "quotedself_tpl.\"self\" == \"myself\"",
|
||||
};
|
||||
|
||||
let quotedenv_tpl = {
|
||||
"env" = "myenv",
|
||||
};
|
||||
|
||||
assert |
|
||||
quotedenv_tpl."env" == "myenv";
|
||||
|;
|
||||
assert {
|
||||
ok = quotedenv_tpl."env" == "myenv",
|
||||
desc = "quotedenv_tpl.\"env\" == \"myenv\"",
|
||||
};
|
||||
|
||||
let unquotedenv_tpl = {
|
||||
env = "myenv",
|
||||
};
|
||||
|
||||
assert |
|
||||
unquotedenv_tpl."env" == "myenv";
|
||||
|;
|
||||
assert {
|
||||
ok = unquotedenv_tpl."env" == "myenv",
|
||||
desc = "unquotedenv_tpl.\"env\" == \"myenv\"",
|
||||
};
|
||||
|
||||
let unquotedself_tpl = {
|
||||
self = "myself",
|
||||
};
|
||||
|
||||
assert |
|
||||
unquotedself_tpl."self" == "myself";
|
||||
|;
|
||||
assert {
|
||||
ok = unquotedself_tpl."self" == "myself",
|
||||
desc = "unquotedself_tpl.\"self\" == \"myself\"",
|
||||
};
|
||||
|
@ -742,7 +742,7 @@ pub enum Statement {
|
||||
Import(ImportDef),
|
||||
|
||||
// Assert statement
|
||||
Assert(Token),
|
||||
Assert(Expression),
|
||||
|
||||
// Identify an Expression for output.
|
||||
Output(Token, Expression),
|
||||
|
106
src/build/mod.rs
106
src/build/mod.rs
@ -457,7 +457,7 @@ impl<'a> FileBuilder<'a> {
|
||||
fn eval_stmt(&mut self, stmt: &Statement) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||
let child_scope = self.scope.clone();
|
||||
match stmt {
|
||||
&Statement::Assert(ref expr) => self.build_assert(&expr),
|
||||
&Statement::Assert(ref expr) => self.build_assert(&expr, &child_scope),
|
||||
&Statement::Let(ref def) => self.eval_let(def),
|
||||
&Statement::Import(ref def) => self.eval_import(def),
|
||||
&Statement::Expression(ref expr) => self.eval_expr(expr, &child_scope),
|
||||
@ -1360,22 +1360,29 @@ impl<'a> FileBuilder<'a> {
|
||||
};
|
||||
}
|
||||
|
||||
fn build_assert(&mut self, tok: &Token) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||
fn record_assert_result(&mut self, msg: &str, is_success: bool) {
|
||||
let msg = format!("{}\n", msg);
|
||||
self.assert_collector.summary.push_str(&msg);
|
||||
if !is_success {
|
||||
self.assert_collector.failures.push_str(&msg);
|
||||
self.assert_collector.success = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn build_assert(
|
||||
&mut self,
|
||||
expr: &Expression,
|
||||
scope: &Scope,
|
||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||
if !self.validate_mode {
|
||||
// we are not in validate_mode then build_asserts are noops.
|
||||
return Ok(Rc::new(Val::Empty));
|
||||
}
|
||||
let expr = &tok.fragment;
|
||||
let assert_input =
|
||||
OffsetStrIter::new_with_offsets(expr, tok.pos.line - 1, tok.pos.column - 1);
|
||||
let ok = match self.eval_input(assert_input) {
|
||||
let ok = match self.eval_expr(expr, scope) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
// failure!
|
||||
let msg = format!(
|
||||
"NOT OK - '{}' at line: {} column: {}\n\tCompileError: {}\n",
|
||||
expr, tok.pos.line, tok.pos.column, e
|
||||
);
|
||||
let msg = format!("CompileError: {}\n", e);
|
||||
self.assert_collector.summary.push_str(&msg);
|
||||
self.assert_collector.failures.push_str(&msg);
|
||||
self.assert_collector.success = false;
|
||||
@ -1383,34 +1390,69 @@ impl<'a> FileBuilder<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
if let &Val::Boolean(b) = ok.as_ref() {
|
||||
// record the assertion result.
|
||||
if b {
|
||||
// success!
|
||||
match ok.as_ref() {
|
||||
&Val::Tuple(ref fs) => {
|
||||
let ok_field = match find_in_fieldlist("ok", fs) {
|
||||
Some(ref val) => match val.as_ref() {
|
||||
&Val::Boolean(b) => b,
|
||||
_ => {
|
||||
let msg = format!(
|
||||
"OK - '{}' at line: {} column: {}\n",
|
||||
expr, tok.pos.line, tok.pos.column
|
||||
"TYPE FAIL - Expected Boolean field ok in tuple {}, line: {} column: {}",
|
||||
ok.as_ref(), expr.pos().line, expr.pos().column
|
||||
);
|
||||
self.assert_collector.summary.push_str(&msg);
|
||||
} else {
|
||||
// failure!
|
||||
let msg = format!(
|
||||
"NOT OK - '{}' at line: {} column: {}\n",
|
||||
expr, tok.pos.line, tok.pos.column
|
||||
);
|
||||
self.assert_collector.summary.push_str(&msg);
|
||||
self.assert_collector.failures.push_str(&msg);
|
||||
self.assert_collector.success = false;
|
||||
self.record_assert_result(&msg, false);
|
||||
return Ok(Rc::new(Val::Empty));
|
||||
}
|
||||
} else {
|
||||
},
|
||||
None => {
|
||||
let msg = format!(
|
||||
"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);
|
||||
return Ok(Rc::new(Val::Empty));
|
||||
}
|
||||
};
|
||||
let desc = match find_in_fieldlist("desc", fs) {
|
||||
Some(ref val) => match val.as_ref() {
|
||||
Val::Str(ref s) => s.clone(),
|
||||
_ => {
|
||||
let msg = format!(
|
||||
"TYPE FAIL - Expected Boolean field desc in tuple {} line: {} column: {}",
|
||||
ok, expr.pos().line, expr.pos().column
|
||||
);
|
||||
self.record_assert_result(&msg, false);
|
||||
return Ok(Rc::new(Val::Empty));
|
||||
}
|
||||
},
|
||||
None => {
|
||||
let msg = format!(
|
||||
"TYPE FAIL - Expected Boolean field desc in tuple {} line: {} column: {}\n",
|
||||
ok, expr.pos().line, expr.pos().column
|
||||
);
|
||||
self.record_assert_result(&msg, false);
|
||||
return Ok(Rc::new(Val::Empty));
|
||||
}
|
||||
};
|
||||
self.record_assert_result(&desc, ok_field);
|
||||
}
|
||||
&Val::Empty
|
||||
| &Val::Boolean(_)
|
||||
| &Val::Env(_)
|
||||
| &Val::Float(_)
|
||||
| &Val::Int(_)
|
||||
| &Val::Str(_)
|
||||
| &Val::List(_)
|
||||
| &Val::Macro(_)
|
||||
| &Val::Module(_) => {
|
||||
// record an assertion type-failure result.
|
||||
let msg = format!(
|
||||
"TYPE FAIL - '{}' Expected Boolean got {} at line: {} column: {}\n",
|
||||
expr, ok, tok.pos.line, tok.pos.column
|
||||
"TYPE FAIL - Expected tuple with ok and desc fields got {} at line: {} column: {}\n",
|
||||
ok, expr.pos().line, expr.pos().column
|
||||
);
|
||||
self.assert_collector.failures.push_str(&msg);
|
||||
self.assert_collector.success = false;
|
||||
self.assert_collector.summary.push_str(&msg);
|
||||
self.record_assert_result(&msg, false);
|
||||
return Ok(Rc::new(Val::Empty));
|
||||
}
|
||||
}
|
||||
Ok(ok)
|
||||
}
|
||||
|
@ -736,9 +736,9 @@ make_fn!(
|
||||
assert_statement<SliceIter<Token>, Statement>,
|
||||
do_each!(
|
||||
_ => word!("assert"),
|
||||
tok => must!(match_type!(PIPEQUOTE)),
|
||||
expr => must!(expression),
|
||||
_ => must!(punct!(";")),
|
||||
(Statement::Assert(tok.clone()))
|
||||
(Statement::Assert(expr))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -84,20 +84,6 @@ make_fn!(strtok<OffsetStrIter, Token>,
|
||||
)
|
||||
);
|
||||
|
||||
make_fn!(pipequotetok<OffsetStrIter, Token>,
|
||||
do_each!(
|
||||
p => input!(),
|
||||
_ => text_token!("|"),
|
||||
frag => until!(text_token!("|")),
|
||||
_ => text_token!("|"),
|
||||
(Token{
|
||||
typ: TokenType::PIPEQUOTE,
|
||||
pos: Position::from(&p),
|
||||
fragment: frag.to_string(),
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
make_fn!(barewordtok<OffsetStrIter, Token>,
|
||||
do_each!(
|
||||
span => input!(),
|
||||
@ -378,7 +364,6 @@ fn token<'a>(input: OffsetStrIter<'a>) -> Result<OffsetStrIter<'a>, Token> {
|
||||
either!(
|
||||
input,
|
||||
strtok,
|
||||
pipequotetok,
|
||||
emptytok, // This must come before the barewordtok
|
||||
digittok,
|
||||
commatok,
|
||||
@ -528,14 +513,6 @@ macro_rules! match_type {
|
||||
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) => {
|
||||
match_type!($i, TokenType::DIGIT, "Not a DIGIT", $h)
|
||||
};
|
||||
|
@ -74,19 +74,6 @@ fn test_escape_quoted() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pipe_quoted() {
|
||||
let result = pipequotetok(OffsetStrIter::new("|foo|"));
|
||||
assert!(
|
||||
result.is_complete(),
|
||||
format!("result {:?} is not ok", result)
|
||||
);
|
||||
if let Result::Complete(_, tok) = result {
|
||||
assert_eq!(tok.fragment, "foo".to_string());
|
||||
assert_eq!(tok.typ, TokenType::PIPEQUOTE);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_with_escaping() {
|
||||
let result = strtok(OffsetStrIter::new("\"foo \\\\ \\\"bar\""));
|
||||
|
42
std/lists.ucg
Normal file
42
std/lists.ucg
Normal file
@ -0,0 +1,42 @@
|
||||
let str_join = module{
|
||||
sep=" ",
|
||||
list=NULL,
|
||||
} => {
|
||||
let joiner = macro(acc, item) => {
|
||||
result = select (acc.out == ""), NULL, {
|
||||
true = acc{
|
||||
out="@@" % (acc.out,item),
|
||||
},
|
||||
false = acc{
|
||||
out="@@@" % (acc.out, acc.sep, item),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let result = (reduce joiner.result {sep=mod.sep, out=""}, (mod.list)).out;
|
||||
};
|
||||
|
||||
let len = module{
|
||||
list = NULL,
|
||||
} => {
|
||||
let counter = macro(acc, item) => {
|
||||
result = acc + 1,
|
||||
};
|
||||
|
||||
let result = reduce counter.result 0, (mod.list);
|
||||
};
|
||||
|
||||
let enumerate = module{
|
||||
start = 0,
|
||||
step = 1,
|
||||
list = NULL,
|
||||
} => {
|
||||
let reducer = macro(acc, item) => {
|
||||
result = acc{count = acc.count + acc.step, list=acc.list + [[acc.count, item]]},
|
||||
};
|
||||
|
||||
let acc = {count=mod.start, list=[], step=mod.step};
|
||||
|
||||
let enumerated = reduce reducer.result acc, (mod.list);
|
||||
let result = enumerated.list;
|
||||
};
|
88
std/testing.ucg
Normal file
88
std/testing.ucg
Normal file
@ -0,0 +1,88 @@
|
||||
// A module with helper test assertions for ucg tests.
|
||||
// Each contained module will output a struct with
|
||||
// ok and desc fields.
|
||||
//
|
||||
// ok will be a boolean.
|
||||
// desc will be a descriptive message.
|
||||
let asserts = module{
|
||||
// allows you to specify a a prefix for messages.
|
||||
ok_prefix = "OK - ",
|
||||
// specify the prefix to add when the condition is not true.
|
||||
not_prefix = "NOT ",
|
||||
// A default description to use for messages.
|
||||
default_description = "TODO description",
|
||||
} => {
|
||||
|
||||
// Test that a value is true.
|
||||
let ok = module{
|
||||
ok_prefix = mod.ok_prefix,
|
||||
not_prefix = mod.not_prefix,
|
||||
// test value expected to be true for success.
|
||||
test=false,
|
||||
// descriptive message to use in output.
|
||||
desc=mod.default_description,
|
||||
} => {
|
||||
let ok = mod.test;
|
||||
|
||||
let desc = select ok, "NOT OK - ", {
|
||||
true = "@@" % (mod.ok_prefix, mod.desc),
|
||||
false = "@@@" % (mod.not_prefix, mod.ok_prefix, mod.desc),
|
||||
};
|
||||
};
|
||||
|
||||
// Test that a value is not true.
|
||||
let not_ok = module{
|
||||
ok_prefix = mod.ok_prefix,
|
||||
not_prefix = mod.not_prefix,
|
||||
// Test value expected to to be false for success.
|
||||
test=true,
|
||||
// descriptive message to use in output.
|
||||
desc=mod.default_description,
|
||||
} => {
|
||||
let ok = mod.test != true;
|
||||
|
||||
let desc_prefix = select ok, "", {
|
||||
true = "@@" % (mod.ok_prefix, mod.desc),
|
||||
false = "@@@" % (mod.not_prefix, mod.ok_prefix, mod.desc),
|
||||
};
|
||||
|
||||
let desc = select (mod.desc == ""), "", {
|
||||
true = "@ not succcessful" % (desc_prefix),
|
||||
false = "@" % (desc_prefix),
|
||||
};
|
||||
};
|
||||
|
||||
// Asserts that two values are equal. Does deep equal comparisons.
|
||||
let equal = module{
|
||||
ok_prefix = mod.ok_prefix,
|
||||
not_prefix = mod.not_prefix,
|
||||
// Left value for deep equal comparison.
|
||||
left=NULL,
|
||||
// right value for deep equal comparison.
|
||||
right=NULL,
|
||||
} => {
|
||||
let ok = mod.left == mod.right;
|
||||
|
||||
let desc = select ok, "", {
|
||||
true = "@@ == @" % (mod.ok_prefix, mod.left, mod.right),
|
||||
false = "@@@ != @" % (mod.not_prefix, mod.ok_prefix, mod.left, mod.right),
|
||||
};
|
||||
};
|
||||
|
||||
// Asserts that two values are not equal. Does deep equal comparisons.
|
||||
let not_equal = module{
|
||||
ok_prefix = mod.ok_prefix,
|
||||
not_prefix = mod.not_prefix,
|
||||
// Left value for deep equal comparison.
|
||||
left=NULL,
|
||||
// right value for deep equal comparison.
|
||||
right=NULL,
|
||||
} => {
|
||||
let ok = mod.left != mod.right;
|
||||
|
||||
let desc = select ok, "", {
|
||||
true = "@@ != @" % (mod.ok_prefix, mod.left, mod.right),
|
||||
false = "@@@ == @" % (mod.not_prefix, mod.ok_prefix, mod.left, mod.right),
|
||||
};
|
||||
};
|
||||
};
|
35
std/tests/lists_test.ucg
Normal file
35
std/tests/lists_test.ucg
Normal file
@ -0,0 +1,35 @@
|
||||
import "../lists.ucg" as list;
|
||||
import "../testing.ucg" as t;
|
||||
|
||||
let list_to_join = [1, 2, 3];
|
||||
|
||||
let asserts = t.asserts{};
|
||||
|
||||
assert asserts.equal{
|
||||
left=list.str_join{sep=",", list=list_to_join}.result,
|
||||
right="1,2,3"
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
left=list.len{list=[0, 1, 2, 3]}.result,
|
||||
right=4,
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
left=list.enumerate{list=["foo", "bar"]}.result,
|
||||
right=[[0, "foo"], [1, "bar"]],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
left=list.enumerate{start=1, list=["foo", "bar"]}.result,
|
||||
right=[[1, "foo"], [2, "bar"]],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
left=list.enumerate{
|
||||
start=1,
|
||||
step=2,
|
||||
list=["foo", "bar"]
|
||||
}.result,
|
||||
right=[[1, "foo"], [3, "bar"]],
|
||||
};
|
69
std/tests/testing_test.ucg
Normal file
69
std/tests/testing_test.ucg
Normal file
@ -0,0 +1,69 @@
|
||||
import "../testing.ucg" as t;
|
||||
|
||||
let asserts = t.asserts{};
|
||||
|
||||
let not_equal_result = asserts.not_equal{
|
||||
left=1,
|
||||
right=2,
|
||||
};
|
||||
assert not_equal_result;
|
||||
assert asserts.equal{
|
||||
left=not_equal_result.desc,
|
||||
right="OK - 1 != 2",
|
||||
};
|
||||
|
||||
let bad_not_equal_result = asserts.not_equal{
|
||||
left=1,
|
||||
right=1,
|
||||
};
|
||||
assert asserts.not_ok{test=bad_not_equal_result.ok};
|
||||
assert asserts.equal{
|
||||
left=bad_not_equal_result.desc,
|
||||
right="NOT OK - 1 == 1",
|
||||
};
|
||||
|
||||
|
||||
let equal_result = asserts.equal{
|
||||
left=1,
|
||||
right=1,
|
||||
};
|
||||
assert equal_result;
|
||||
assert asserts.equal{
|
||||
left=equal_result.desc,
|
||||
right="OK - 1 == 1",
|
||||
};
|
||||
|
||||
let bad_equal_result = asserts.equal{
|
||||
left=1,
|
||||
right=2,
|
||||
};
|
||||
assert asserts.equal{
|
||||
left=bad_equal_result.desc,
|
||||
right="NOT OK - 1 != 2",
|
||||
};
|
||||
|
||||
let ok_result = asserts.ok{
|
||||
test=true,
|
||||
};
|
||||
assert ok_result;
|
||||
assert asserts.equal{
|
||||
left=ok_result.desc,
|
||||
right="OK - TODO description",
|
||||
};
|
||||
|
||||
let bad_ok_result = t.asserts.ok{
|
||||
test=false,
|
||||
};
|
||||
assert asserts.equal{
|
||||
left=bad_ok_result.desc,
|
||||
right="NOT OK - TODO description",
|
||||
};
|
||||
|
||||
let not_ok_result = asserts.not_ok{
|
||||
test=false,
|
||||
};
|
||||
assert not_ok_result;
|
||||
assert asserts.equal{
|
||||
left=not_ok_result.desc,
|
||||
right="OK - TODO description",
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user