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 build --verbose
|
||||||
- cargo test --verbose
|
- cargo test --verbose
|
||||||
- cargo run -- test integration_tests
|
- 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
|
### Assert Statements
|
||||||
|
|
||||||
The assert statement defines an expression that must evaluate to either true or false.
|
The assert statement defines an expression that must evaluate to tuple with an
|
||||||
Assert statements are noops except during a validation compile. They give you a way to
|
ok field that is either true or false and a desc field that is a string. Assert
|
||||||
assert certains properties about your data and can be used as a form of unit testing
|
statements are noops except during a validation compile. They give you a way to
|
||||||
for your configurations. It starts with the `assert` keyword followed by a valid block
|
assert certains properties about your data and can be used as a form of unit
|
||||||
of UCG statements delimited by `|` characters. The final statement in the block
|
testing for your configurations. It starts with the `assert` keyword followed
|
||||||
must evaluate to a boolean expression.
|
by a valid ucg expression.
|
||||||
|
|
||||||
```
|
```
|
||||||
assert |
|
assert {
|
||||||
host == "www.example.com";
|
ok = host == "www.example.com",
|
||||||
|;
|
desc = "Host is www.example.com",
|
||||||
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
select qa, 443, {
|
ok = select qa, 443, {
|
||||||
qa = 80,
|
qa = 80,
|
||||||
prod = 443,
|
prod = 443,
|
||||||
} == 443;
|
} == 443,
|
||||||
|;
|
desc = "select default was 443",
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Assert statements are only evaluated when running the `ucg test` command. That
|
Assert statements are only evaluated when running the `ucg test` command. That
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
assert |macro |;
|
assert {macro };
|
||||||
assert |{ foo = hello world}|;
|
assert {{ foo = hello world}};
|
||||||
assert |{ foo = "hello world"|;
|
assert {{ foo = "hello world"};
|
||||||
assert |{ = }|;
|
assert {{ = }};
|
||||||
assert |"|;
|
assert {"};
|
||||||
assert |=|;
|
assert {=};
|
||||||
|
|
||||||
assert |let |;
|
assert {let };
|
||||||
assert |let foo |;
|
assert {let foo };
|
||||||
assert |let foo =|;
|
assert {let foo =};
|
||||||
assert |import |;
|
assert {import };
|
||||||
assert |import foo |;
|
assert {import foo };
|
||||||
assert |out |;
|
assert {out };
|
||||||
assert |out "|;
|
assert {out "};
|
||||||
assert |out json|;
|
assert {out json};
|
||||||
|
|
||||||
assert |let env = 1;|;
|
assert {let env = 1;};
|
@ -16,33 +16,42 @@ let list = [1, 2, 3];
|
|||||||
let list2 = list;
|
let list2 = list;
|
||||||
let list3 = [1, 2];
|
let list3 = [1, 2];
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
one == one;
|
ok = one == one,
|
||||||
|;
|
desc = "one == one",
|
||||||
assert |
|
};
|
||||||
one == one;
|
assert {
|
||||||
|;
|
ok = one == one,
|
||||||
assert |
|
desc = "one == one",
|
||||||
one >= one;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = one >= one,
|
||||||
two > one;
|
desc = "one >= one"
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
two >= two;
|
ok = two > one,
|
||||||
|;
|
desc = "two > one"
|
||||||
assert |
|
};
|
||||||
tpl1 == tpl2;
|
assert {
|
||||||
|;
|
ok = two >= two,
|
||||||
assert |
|
desc = "two >= two",
|
||||||
tpl1 != tpl3;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = tpl1 == tpl2,
|
||||||
list == list2;
|
desc = "tpl1 == tpl2"
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
list != list3;
|
ok = tpl1 != tpl3,
|
||||||
|;
|
desc = "tpl1 != tpl3",
|
||||||
|
};
|
||||||
|
assert {
|
||||||
|
ok = list == list2,
|
||||||
|
desc = "list == list2",
|
||||||
|
};
|
||||||
|
assert {
|
||||||
|
ok = list != list3,
|
||||||
|
desc = "list != list3",
|
||||||
|
};
|
||||||
|
|
||||||
// Deep Comparisons
|
// Deep Comparisons
|
||||||
let tpl4 = {
|
let tpl4 = {
|
||||||
@ -58,73 +67,105 @@ let less = {
|
|||||||
foo = "bar"
|
foo = "bar"
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
tpl4.inner == copy.inner;
|
ok = tpl4.inner == copy.inner,
|
||||||
|;
|
desc = "tpl4.inner == copy.inner",
|
||||||
assert |
|
};
|
||||||
tpl4.inner.fld == copy.inner.fld;
|
assert {
|
||||||
|;
|
ok = tpl4.inner.fld == copy.inner.fld,
|
||||||
assert |
|
desc = "tpl4.inner.fld == copy.inner.fld",
|
||||||
tpl4.lst == copy.lst;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = tpl4.lst == copy.lst,
|
||||||
tpl4.foo == copy.foo;
|
desc = "tpl4.lst == copy.lst",
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
tpl4 == copy;
|
ok = tpl4.foo == copy.foo,
|
||||||
|;
|
desc = "tpl4.foo == copy.foo",
|
||||||
assert |
|
};
|
||||||
tpl4 != extra;
|
assert {
|
||||||
|;
|
ok = tpl4 == copy,
|
||||||
assert |
|
desc = "tpl4 == copy",
|
||||||
tpl4 != less;
|
};
|
||||||
|;
|
assert {
|
||||||
|
ok = tpl4 != extra,
|
||||||
|
desc = "tpl4 != extra",
|
||||||
|
};
|
||||||
|
assert {
|
||||||
|
ok = tpl4 != less,
|
||||||
|
desc = "tpl4 != less",
|
||||||
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
[[1, 2, [3]], 4] == [[1, 2, [3]], 4];
|
ok = [[1, 2, [3]], 4] == [[1, 2, [3]], 4],
|
||||||
|;
|
desc = "[[1, 2, [3]], 4] == [[1, 2, [3]], 4]",
|
||||||
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
[[1, 2, [3]], 4] != [[1, 2, [6]], 4];
|
ok = [[1, 2, [3]], 4] != [[1, 2, [6]], 4],
|
||||||
|;
|
desc = "[[1, 2, [3]], 4] != [[1, 2, [6]], 4]",
|
||||||
|
};
|
||||||
|
|
||||||
// Expression comparisons
|
// Expression comparisons
|
||||||
assert |2 == 1+1;|;
|
assert {
|
||||||
assert |(1+1) == 2;|;
|
ok = 2 == 1+1,
|
||||||
assert |(1+1) == (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";
|
let want = "foo";
|
||||||
assert |
|
assert {
|
||||||
select want, 1, { foo=2, } == 2;
|
ok = select want, 1, { foo=2, } == 2,
|
||||||
|;
|
desc = "select want, 1, { foo=2, } == 2",
|
||||||
|
};
|
||||||
|
|
||||||
// Contains comparison operators.
|
// Contains comparison operators.
|
||||||
assert |
|
assert {
|
||||||
"foo" in {
|
ok = "foo" in {
|
||||||
foo = "bar",
|
foo = "bar",
|
||||||
};
|
},
|
||||||
|;
|
desc = "\"foo\" in {
|
||||||
assert |
|
foo = \"bar\",
|
||||||
foo in {
|
}
|
||||||
|
",
|
||||||
|
};
|
||||||
|
assert {
|
||||||
|
ok = foo in {
|
||||||
foo = "bar",
|
foo = "bar",
|
||||||
};
|
},
|
||||||
|;
|
desc = "foo in {
|
||||||
assert |
|
foo = \"bar\",
|
||||||
"foo" in ["foo", "bar"];
|
}",
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
"foo" in ["bar", "foo", "bar"];
|
ok = "foo" in ["foo", "bar"],
|
||||||
|;
|
desc = "\"foo\" in [\"foo\", \"bar\"]",
|
||||||
assert |
|
};
|
||||||
{ foo = 1 } in ["foo", { foo = 1 }];
|
assert {
|
||||||
|;
|
ok = "foo" in ["bar", "foo", "bar"],
|
||||||
assert |
|
desc = "\"foo\" in [\"bar\", \"foo\", \"bar\"]",
|
||||||
true in [ "foo" in {foo = 1}, false ];
|
};
|
||||||
|;
|
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 |
|
assert {
|
||||||
"foo" ~ "o+";
|
ok = "foo" ~ "o+",
|
||||||
|;
|
desc = "\"foo\" ~ \"o+\""
|
||||||
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
"foo" !~ "bar";
|
ok = "foo" !~ "bar",
|
||||||
|;
|
desc = "\"foo\" !~ \"bar\"",
|
||||||
|
};
|
@ -1,6 +1,8 @@
|
|||||||
assert |
|
assert {
|
||||||
"hello " + "world" == "hello world";
|
ok = "hello " + "world" == "hello world",
|
||||||
|;
|
desc = "\"hello \" + \"world\" == \"hello world\"",
|
||||||
assert |
|
};
|
||||||
[1, 2, 3] + [4, 5, 6] == [1, 2, 3, 4, 5, 6];
|
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 = {
|
let tpl = {
|
||||||
foo = NULL,
|
foo = NULL,
|
||||||
};
|
};
|
||||||
assert |
|
assert {
|
||||||
tpl.foo == empty;
|
ok = tpl.foo == empty,
|
||||||
|;
|
desc = "tpl.foo == empty",
|
||||||
|
};
|
@ -1,12 +1,16 @@
|
|||||||
assert |
|
assert {
|
||||||
"hello @" % ("world") == "hello world";
|
ok = "hello @" % ("world") == "hello world",
|
||||||
|;
|
desc = "\"hello @\" % (\"world\") == \"hello world\"",
|
||||||
assert |
|
};
|
||||||
"1 @ @" % (2, 3) == "1 2 3";
|
assert {
|
||||||
|;
|
ok = "1 @ @" % (2, 3) == "1 2 3",
|
||||||
assert |
|
desc = "\"1 @ @\" % (2, 3) == \"1 2 3\"",
|
||||||
"@ or @" % (true, false) == "true or false";
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = "@ or @" % (true, false) == "true or false",
|
||||||
"@" % (NULL) == "NULL";
|
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],
|
result = acc + [item],
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
reduce identity_list_reducer.result [], list1 == list1;
|
ok = reduce identity_list_reducer.result [], list1 == list1,
|
||||||
|;
|
desc = "reduce identity_list_reducer.result [], list1 == list1",
|
||||||
|
};
|
||||||
|
|
||||||
let nested_list = {
|
let nested_list = {
|
||||||
list = list1,
|
list = list1,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
reduce identity_list_reducer.result [], (nested_list.list) == list1;
|
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) => {
|
let list_reducer = macro(acc, item) => {
|
||||||
result = acc + item,
|
result = acc + item,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
reduce list_reducer.result 0, list1 == 0 + 1 + 2 + 3 + 4;
|
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 |
|
assert {
|
||||||
map mapper.result list1 == [2, 3, 4, 5];
|
ok = map mapper.result list1 == [2, 3, 4, 5],
|
||||||
|;
|
desc = "map mapper.result list1 == [2, 3, 4, 5]",
|
||||||
assert |
|
};
|
||||||
(map mapper.result [1, 2, 3, 4]) == [2, 3, 4, 5];
|
assert {
|
||||||
|;
|
ok = (map mapper.result [1, 2, 3, 4]) == [2, 3, 4, 5],
|
||||||
assert |
|
desc = "(map mapper.result [1, 2, 3, 4]) == [2, 3, 4, 5]",
|
||||||
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 |
|
assert {
|
||||||
filter filtrator.result list2 == ["foo", "foo"];
|
ok = filter filtrator.result list2 == ["foo", "foo"],
|
||||||
|;
|
desc = "filter filtrator.result list2 == [\"foo\", \"foo\"]",
|
||||||
assert |
|
};
|
||||||
(filter filtrator.result ["foo", "bar", "foo", "bar"]) == ["foo", "foo"];
|
assert {
|
||||||
|;
|
ok = (filter filtrator.result ["foo", "bar", "foo", "bar"]) == ["foo", "foo"],
|
||||||
assert |
|
desc = "(filter filtrator.result [\"foo\", \"bar\", \"foo\", \"bar\"]) == [\"foo\", \"foo\"]",
|
||||||
filter filtrator.result ["foo", "bar", "foo", "bar"] == ["foo", "foo"];
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = filter filtrator.result ["foo", "bar", "foo", "bar"] == ["foo", "foo"],
|
||||||
filter boolfiltrator.result [1, 2, 3, 4, 5, 6, 7] == [1, 2, 3, 4];
|
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
|
// Tuple processing
|
||||||
let test_tpl = {
|
let test_tpl = {
|
||||||
@ -71,9 +81,10 @@ let identity_tpl_mapper = macro(name, val) => {
|
|||||||
result = [name, val],
|
result = [name, val],
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
map identity_tpl_mapper.result test_tpl == test_tpl;
|
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) => {
|
let tpl_mapper = macro(name, val) => {
|
||||||
result = select name, [name, val], {
|
result = select name, [name, val], {
|
||||||
@ -82,9 +93,10 @@ let tpl_mapper = macro(name, val) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
map tpl_mapper.result test_tpl == {foo = "barbar", cute = "pygmy"};
|
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) => {
|
let identity_tpl_filter = macro(name, val) => {
|
||||||
result = true,
|
result = true,
|
||||||
@ -95,13 +107,15 @@ let tpl_filter = macro(name, val) => {
|
|||||||
result = name != "foo",
|
result = name != "foo",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
filter identity_tpl_filter.result test_tpl == test_tpl;
|
ok = filter identity_tpl_filter.result test_tpl == test_tpl,
|
||||||
|;
|
desc = "filter identity_tpl_filter.result test_tpl == test_tpl",
|
||||||
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
filter tpl_filter.result test_tpl == { quux = "baz" };
|
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) => {
|
let tpl_reducer = macro(acc, name, val) => {
|
||||||
result = acc{
|
result = acc{
|
||||||
@ -110,6 +124,7 @@ let tpl_reducer = macro(acc, name, val) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
reduce tpl_reducer.result {keys = [], vals = []}, test_tpl == {keys = ["foo", "quux"], vals = ["bar", "baz"]};
|
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";
|
let script = include str "./include_example.sh";
|
||||||
assert |
|
assert {
|
||||||
script == "#!/usr/bin/env bash
|
ok = script == "#!/usr/bin/env bash
|
||||||
echo \"included\"";
|
echo \"included\"",
|
||||||
|;
|
desc = "script was successfully included",
|
||||||
|
};
|
||||||
let expected = "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvICJpbmNsdWRlZCI=";
|
let expected = "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvICJpbmNsdWRlZCI=";
|
||||||
let base64 = include b64 "./include_example.sh";
|
let base64 = include b64 "./include_example.sh";
|
||||||
assert |
|
assert {
|
||||||
base64 == expected;
|
ok = base64 == expected,
|
||||||
|;
|
desc = "base64 == expected",
|
||||||
|
};
|
||||||
let base64safe = include b64urlsafe "./include_example.sh";
|
let base64safe = include b64urlsafe "./include_example.sh";
|
||||||
assert |
|
assert {
|
||||||
base64safe == expected;
|
ok = base64safe == expected,
|
||||||
|;
|
desc = "base64safe == expected",
|
||||||
|
};
|
@ -2,10 +2,12 @@ let empty_list = [];
|
|||||||
|
|
||||||
let concatenated = ["foo"] + ["bar"];
|
let concatenated = ["foo"] + ["bar"];
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
concatenated == ["foo", "bar"];
|
ok = concatenated == ["foo", "bar"],
|
||||||
|;
|
desc = "concatenated == [\"foo\", \"bar\"]",
|
||||||
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
concatenated + empty_list == ["foo", "bar"];
|
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 simpleresult = simplemacro(1, 2, 3);
|
||||||
let cplxresult = cplxmacro(1, "We", 3.0);
|
let cplxresult = cplxmacro(1, "We", 3.0);
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
noargresult.field1 == "value";
|
ok = noargresult.field1 == "value",
|
||||||
|;
|
desc = "noargresult.field1 == \"value\"",
|
||||||
assert |
|
};
|
||||||
simpleresult.field1 == 1;
|
assert {
|
||||||
|;
|
ok = simpleresult.field1 == 1,
|
||||||
assert |
|
desc = "simpleresult.field1 == 1",
|
||||||
simpleresult.field2 == 2;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = simpleresult.field2 == 2,
|
||||||
simpleresult.field3 == 3;
|
desc = "simpleresult.field2 == 2",
|
||||||
|;
|
};
|
||||||
|
assert {
|
||||||
|
ok = simpleresult.field3 == 3,
|
||||||
|
desc = "simpleresult.field3 == 3",
|
||||||
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
cplxresult.field1 == 2;
|
ok = cplxresult.field1 == 2,
|
||||||
|;
|
desc = "cplxresult.field1 == 2",
|
||||||
assert |
|
};
|
||||||
cplxresult.field2 == "We are here";
|
assert {
|
||||||
|;
|
ok = cplxresult.field2 == "We are here",
|
||||||
assert |
|
desc = "cplxresult.field2 == \"We are here\"",
|
||||||
cplxresult.field3 == 2.0;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = cplxresult.field3 == 2.0,
|
||||||
cplxresult.boolfield == true;
|
desc = "cplxresult.field3 == 2.0",
|
||||||
|;
|
};
|
||||||
|
assert {
|
||||||
|
ok = cplxresult.boolfield == true,
|
||||||
|
desc = "cplxresult.boolfield == true",
|
||||||
|
};
|
||||||
|
|
||||||
let macro_tpl_arg = macro(tpl) => {
|
let macro_tpl_arg = macro(tpl) => {
|
||||||
result = tpl.field,
|
result = tpl.field,
|
||||||
@ -53,6 +61,7 @@ let arg_tpl = {
|
|||||||
field = "value",
|
field = "value",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
macro_tpl_arg(arg_tpl).result == arg_tpl.field;
|
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{};
|
let simple_mod_instance = test_simple_mod{};
|
||||||
assert |
|
assert {
|
||||||
simple_mod_instance.value == "value";
|
ok = simple_mod_instance.value == "value",
|
||||||
|;
|
desc = "simple_mod_instance.value == \"value\"",
|
||||||
|
};
|
||||||
|
|
||||||
let simple_mod_with_args = test_simple_mod{arg = "othervalue"};
|
let simple_mod_with_args = test_simple_mod{arg = "othervalue"};
|
||||||
assert |
|
assert {
|
||||||
simple_mod_with_args.value == "othervalue";
|
ok = simple_mod_with_args.value == "othervalue",
|
||||||
|;
|
desc = "simple_mod_with_args.value == \"othervalue\"",
|
||||||
|
};
|
||||||
|
|
||||||
let embedded_mod = module {
|
let embedded_mod = module {
|
||||||
deep_value = "None",
|
deep_value = "None",
|
||||||
@ -41,19 +43,23 @@ let embedded_mod = module {
|
|||||||
|
|
||||||
let embedded_default_params = embedded_mod{};
|
let embedded_default_params = embedded_mod{};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
embedded_default_params.embedded.value == "None";
|
ok = embedded_default_params.embedded.value == "None",
|
||||||
|;
|
desc = "embedded_default_params.embedded.value == \"None\"",
|
||||||
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
embedded_default_params.env_name == "qa";
|
ok = embedded_default_params.env_name == "qa",
|
||||||
|;
|
desc = "embedded_default_params.env_name == \"qa\"",
|
||||||
|
};
|
||||||
|
|
||||||
let embedded_with_params = embedded_mod{deep_value = "Some"};
|
let embedded_with_params = embedded_mod{deep_value = "Some"};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
embedded_with_params.embedded.value == "Some";
|
ok = embedded_with_params.embedded.value == "Some",
|
||||||
|;
|
desc = "embedded_with_params.embedded.value == \"Some\"",
|
||||||
assert |
|
};
|
||||||
embedded_mod{dep_value="Some"}.embedded_def{}.value == "None";
|
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 |
|
assert {
|
||||||
2 * 2 + 1 == 5;
|
ok = 2 * 2 + 1 == 5,
|
||||||
|;
|
desc = "2 * 2 + 1 == 5",
|
||||||
assert |
|
};
|
||||||
2 + 2 * 3 == 8;
|
assert {
|
||||||
|;
|
ok = 2 + 2 * 3 == 8,
|
||||||
assert |
|
desc = "2 + 2 * 3 == 8",
|
||||||
2 * (2 + 1) == 6;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = 2 * (2 + 1) == 6,
|
||||||
2 * 2 + 1 > 4;
|
desc = "2 * (2 + 1) == 6",
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
2 * 2 + 1 < 6;
|
ok = 2 * 2 + 1 > 4,
|
||||||
|;
|
desc = "2 * 2 + 1 > 4",
|
||||||
assert |
|
};
|
||||||
2 * 2 + 1 >= 5;
|
assert {
|
||||||
|;
|
ok = 2 * 2 + 1 < 6,
|
||||||
assert |
|
desc = "2 * 2 + 1 < 6",
|
||||||
2 * 2 + 1 <= 5;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = 2 * 2 + 1 >= 5,
|
||||||
2 / 2 == 1;
|
desc = "2 * 2 + 1 >= 5",
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
2 - 1 == 1;
|
ok = 2 * 2 + 1 <= 5,
|
||||||
|;
|
desc = "2 * 2 + 1 <= 5",
|
||||||
assert |
|
};
|
||||||
1 + 1 + 1 + 1 == 4;
|
assert {
|
||||||
|;
|
ok = 2 / 2 == 1,
|
||||||
assert |
|
desc = "2 / 2 == 1",
|
||||||
1 + 1 + 2 * 2 + 1 + 1 == 1 + 1 + (2 * 2) + 1 + 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 = {
|
let tpl = {
|
||||||
one = {
|
one = {
|
||||||
two = 12,
|
two = 12,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
1 + tpl.one.two * 2 + 3 == 28;
|
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",
|
door2 = "you lose",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
got == "grand prize";
|
ok = got == "grand prize",
|
||||||
|;
|
desc = "got == \"grand prize\"",
|
||||||
assert |
|
};
|
||||||
defaultgot == "OOPS";
|
assert {
|
||||||
|;
|
ok = defaultgot == "OOPS",
|
||||||
|
desc = "defaultgot == \"OOPS\"",
|
||||||
|
};
|
||||||
|
|
||||||
// select inside a macro
|
// select inside a macro
|
||||||
|
|
||||||
@ -29,21 +31,25 @@ let condmacro = macro(arg) => {
|
|||||||
|
|
||||||
let result = condmacro("opt1");
|
let result = condmacro("opt1");
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
condmacro("opt1") == {output = "yay"};
|
ok = condmacro("opt1") == {output = "yay"},
|
||||||
|;
|
desc = "condmacro(\"opt1\") == {output = \"yay\"}",
|
||||||
assert |
|
};
|
||||||
condmacro("opt2") == {output = "boo"};
|
assert {
|
||||||
|;
|
ok = condmacro("opt2") == {output = "boo"},
|
||||||
assert |
|
desc = "condmacro(\"opt2\") == {output = \"boo\"}",
|
||||||
condmacro("invalid") == {output = NULL};
|
};
|
||||||
|;
|
assert {
|
||||||
|
ok = condmacro("invalid") == {output = NULL},
|
||||||
|
desc = "condmacro(\"invalid\") == {output = NULL}",
|
||||||
|
};
|
||||||
|
|
||||||
let iflike = select true, "default", {
|
let iflike = select true, "default", {
|
||||||
true = "I was true",
|
true = "I was true",
|
||||||
false = "I was false",
|
false = "I was false",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
iflike == "I was true";
|
ok = iflike == "I was true",
|
||||||
|;
|
desc = "iflike == \"I was true\"",
|
||||||
|
};
|
@ -10,44 +10,55 @@ let testmacro = macro(arg) => {
|
|||||||
output = arg,
|
output = arg,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
list.0 == 1;
|
ok = list.0 == 1,
|
||||||
|;
|
desc = "list.0 == 1",
|
||||||
assert |
|
};
|
||||||
list.1 == 2;
|
assert {
|
||||||
|;
|
ok = list.1 == 2,
|
||||||
assert |
|
desc = "list.1 == 2",
|
||||||
list.3 == 4;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = list.3 == 4,
|
||||||
tuple.field1 == 1;
|
desc = "list.3 == 4",
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
tuple.field2 == 3;
|
ok = tuple.field1 == 1,
|
||||||
|;
|
desc = "tuple.field1 == 1",
|
||||||
assert |
|
};
|
||||||
tuple.deeplist.0 == "foo";
|
assert {
|
||||||
|;
|
ok = tuple.field2 == 3,
|
||||||
assert |
|
desc = "tuple.field2 == 3",
|
||||||
tuple.deeplist.1 == "bar";
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = tuple.deeplist.0 == "foo",
|
||||||
{foo = "bar"}.foo == "bar";
|
desc = "tuple.deeplist.0 == \"foo\"",
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
["one", "two", "three"].0 == "one";
|
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() => {
|
let macro_for_test = macro() => {
|
||||||
foo = "bar",
|
foo = "bar",
|
||||||
};
|
};
|
||||||
assert |
|
assert {
|
||||||
macro_for_test().foo == "bar";
|
ok = macro_for_test().foo == "bar",
|
||||||
|;
|
desc = "macro_for_test().foo == \"bar\"",
|
||||||
|
};
|
||||||
|
|
||||||
let mymodule = module { foo = "bar" } => {
|
let mymodule = module { foo = "bar" } => {
|
||||||
let foo = mod.foo;
|
let foo = mod.foo;
|
||||||
};
|
};
|
||||||
assert |
|
assert {
|
||||||
mymodule{}.foo == "bar";
|
ok = mymodule{}.foo == "bar",
|
||||||
|;
|
desc = "mymodule{}.foo == \"bar\"",
|
||||||
|
};
|
@ -15,33 +15,42 @@ let nestedtpl = {
|
|||||||
maybe_val = NULL,
|
maybe_val = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
simpletpl.foo == "bar";
|
ok = simpletpl.foo == "bar",
|
||||||
|;
|
desc = "simpletpl.foo == \"bar\"",
|
||||||
assert |
|
};
|
||||||
stringfieldtpl."field 1" == 1;
|
assert {
|
||||||
|;
|
ok = stringfieldtpl."field 1" == 1,
|
||||||
assert |
|
desc = "stringfieldtpl.\"field 1\" == 1",
|
||||||
nestedtpl.scalar == 1;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = nestedtpl.scalar == 1,
|
||||||
nestedtpl.maybe_val == NULL;
|
desc = "nestedtpl.scalar == 1",
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
nestedtpl.inner.field == "value";
|
ok = nestedtpl.maybe_val == NULL,
|
||||||
|;
|
desc = "nestedtpl.maybe_val == NULL",
|
||||||
assert |
|
};
|
||||||
nestedtpl.list.0 == 1;
|
assert {
|
||||||
|;
|
ok = nestedtpl.inner.field == "value",
|
||||||
assert |
|
desc = "nestedtpl.inner.field == \"value\"",
|
||||||
nestedtpl.list.1 == 2;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = nestedtpl.list.0 == 1,
|
||||||
nestedtpl.list.2 == 3;
|
desc = "nestedtpl.list.0 == 1",
|
||||||
|;
|
};
|
||||||
assert |
|
assert {
|
||||||
nestedtpl.list.3 == 4;
|
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{
|
let nestedcopy = nestedtpl{
|
||||||
inner = self.inner{
|
inner = self.inner{
|
||||||
@ -62,18 +71,22 @@ let deepnestedcopy = nestedcopy{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
nestedcopy.inner.field2 == 2;
|
ok = nestedcopy.inner.field2 == 2,
|
||||||
|;
|
desc = "nestedcopy.inner.field2 == 2",
|
||||||
assert |
|
};
|
||||||
nestedcopy.inner.inner.field3 == "three";
|
assert {
|
||||||
|;
|
ok = nestedcopy.inner.inner.field3 == "three",
|
||||||
assert |
|
desc = "nestedcopy.inner.inner.field3 == \"three\"",
|
||||||
deepnestedcopy.inner.inner.field4 == 4;
|
};
|
||||||
|;
|
assert {
|
||||||
assert |
|
ok = deepnestedcopy.inner.inner.field4 == 4,
|
||||||
deepnestedcopy.maybe_val == "some val";
|
desc = "deepnestedcopy.inner.inner.field4 == 4",
|
||||||
|;
|
};
|
||||||
|
assert {
|
||||||
|
ok = deepnestedcopy.maybe_val == "some val",
|
||||||
|
desc = "deepnestedcopy.maybe_val == \"some val\"",
|
||||||
|
};
|
||||||
|
|
||||||
let base_maybe = {
|
let base_maybe = {
|
||||||
real = "A real value",
|
real = "A real value",
|
||||||
@ -83,38 +96,43 @@ let copy_maybe = base_maybe{
|
|||||||
real = NULL,
|
real = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
copy_maybe.real == NULL;
|
ok = copy_maybe.real == NULL,
|
||||||
|;
|
desc = "copy_maybe.real == NULL",
|
||||||
|
};
|
||||||
|
|
||||||
let quotedself_tpl = {
|
let quotedself_tpl = {
|
||||||
"self" = "myself",
|
"self" = "myself",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
quotedself_tpl."self" == "myself";
|
ok = quotedself_tpl."self" == "myself",
|
||||||
|;
|
desc = "quotedself_tpl.\"self\" == \"myself\"",
|
||||||
|
};
|
||||||
|
|
||||||
let quotedenv_tpl = {
|
let quotedenv_tpl = {
|
||||||
"env" = "myenv",
|
"env" = "myenv",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
quotedenv_tpl."env" == "myenv";
|
ok = quotedenv_tpl."env" == "myenv",
|
||||||
|;
|
desc = "quotedenv_tpl.\"env\" == \"myenv\"",
|
||||||
|
};
|
||||||
|
|
||||||
let unquotedenv_tpl = {
|
let unquotedenv_tpl = {
|
||||||
env = "myenv",
|
env = "myenv",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
unquotedenv_tpl."env" == "myenv";
|
ok = unquotedenv_tpl."env" == "myenv",
|
||||||
|;
|
desc = "unquotedenv_tpl.\"env\" == \"myenv\"",
|
||||||
|
};
|
||||||
|
|
||||||
let unquotedself_tpl = {
|
let unquotedself_tpl = {
|
||||||
self = "myself",
|
self = "myself",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert |
|
assert {
|
||||||
unquotedself_tpl."self" == "myself";
|
ok = unquotedself_tpl."self" == "myself",
|
||||||
|;
|
desc = "unquotedself_tpl.\"self\" == \"myself\"",
|
||||||
|
};
|
||||||
|
@ -742,7 +742,7 @@ pub enum Statement {
|
|||||||
Import(ImportDef),
|
Import(ImportDef),
|
||||||
|
|
||||||
// Assert statement
|
// Assert statement
|
||||||
Assert(Token),
|
Assert(Expression),
|
||||||
|
|
||||||
// Identify an Expression for output.
|
// Identify an Expression for output.
|
||||||
Output(Token, Expression),
|
Output(Token, Expression),
|
||||||
|
116
src/build/mod.rs
116
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>> {
|
fn eval_stmt(&mut self, stmt: &Statement) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
let child_scope = self.scope.clone();
|
let child_scope = self.scope.clone();
|
||||||
match stmt {
|
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::Let(ref def) => self.eval_let(def),
|
||||||
&Statement::Import(ref def) => self.eval_import(def),
|
&Statement::Import(ref def) => self.eval_import(def),
|
||||||
&Statement::Expression(ref expr) => self.eval_expr(expr, &child_scope),
|
&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 {
|
if !self.validate_mode {
|
||||||
// we are not in validate_mode then build_asserts are noops.
|
// we are not in validate_mode then build_asserts are noops.
|
||||||
return Ok(Rc::new(Val::Empty));
|
return Ok(Rc::new(Val::Empty));
|
||||||
}
|
}
|
||||||
let expr = &tok.fragment;
|
let ok = match self.eval_expr(expr, scope) {
|
||||||
let assert_input =
|
|
||||||
OffsetStrIter::new_with_offsets(expr, tok.pos.line - 1, tok.pos.column - 1);
|
|
||||||
let ok = match self.eval_input(assert_input) {
|
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// failure!
|
// failure!
|
||||||
let msg = format!(
|
let msg = format!("CompileError: {}\n", e);
|
||||||
"NOT OK - '{}' at line: {} column: {}\n\tCompileError: {}\n",
|
|
||||||
expr, tok.pos.line, tok.pos.column, e
|
|
||||||
);
|
|
||||||
self.assert_collector.summary.push_str(&msg);
|
self.assert_collector.summary.push_str(&msg);
|
||||||
self.assert_collector.failures.push_str(&msg);
|
self.assert_collector.failures.push_str(&msg);
|
||||||
self.assert_collector.success = false;
|
self.assert_collector.success = false;
|
||||||
@ -1383,34 +1390,69 @@ impl<'a> FileBuilder<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let &Val::Boolean(b) = ok.as_ref() {
|
match ok.as_ref() {
|
||||||
// record the assertion result.
|
&Val::Tuple(ref fs) => {
|
||||||
if b {
|
let ok_field = match find_in_fieldlist("ok", fs) {
|
||||||
// success!
|
Some(ref val) => match val.as_ref() {
|
||||||
let msg = format!(
|
&Val::Boolean(b) => b,
|
||||||
"OK - '{}' at line: {} column: {}\n",
|
_ => {
|
||||||
expr, tok.pos.line, tok.pos.column
|
let msg = format!(
|
||||||
);
|
"TYPE FAIL - Expected Boolean field ok in tuple {}, line: {} column: {}",
|
||||||
self.assert_collector.summary.push_str(&msg);
|
ok.as_ref(), expr.pos().line, expr.pos().column
|
||||||
} else {
|
);
|
||||||
// failure!
|
self.record_assert_result(&msg, false);
|
||||||
let msg = format!(
|
return Ok(Rc::new(Val::Empty));
|
||||||
"NOT OK - '{}' at line: {} column: {}\n",
|
}
|
||||||
expr, tok.pos.line, tok.pos.column
|
},
|
||||||
);
|
None => {
|
||||||
self.assert_collector.summary.push_str(&msg);
|
let msg = format!(
|
||||||
self.assert_collector.failures.push_str(&msg);
|
"TYPE FAIL - Expected Boolean field ok in tuple {}, line: {} column: {}",
|
||||||
self.assert_collector.success = false;
|
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 tuple with ok and desc fields got {} at line: {} column: {}\n",
|
||||||
|
ok, expr.pos().line, expr.pos().column
|
||||||
|
);
|
||||||
|
self.record_assert_result(&msg, false);
|
||||||
|
return Ok(Rc::new(Val::Empty));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// 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
|
|
||||||
);
|
|
||||||
self.assert_collector.failures.push_str(&msg);
|
|
||||||
self.assert_collector.success = false;
|
|
||||||
self.assert_collector.summary.push_str(&msg);
|
|
||||||
}
|
}
|
||||||
Ok(ok)
|
Ok(ok)
|
||||||
}
|
}
|
||||||
|
@ -736,9 +736,9 @@ make_fn!(
|
|||||||
assert_statement<SliceIter<Token>, Statement>,
|
assert_statement<SliceIter<Token>, Statement>,
|
||||||
do_each!(
|
do_each!(
|
||||||
_ => word!("assert"),
|
_ => word!("assert"),
|
||||||
tok => must!(match_type!(PIPEQUOTE)),
|
expr => must!(expression),
|
||||||
_ => must!(punct!(";")),
|
_ => 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>,
|
make_fn!(barewordtok<OffsetStrIter, Token>,
|
||||||
do_each!(
|
do_each!(
|
||||||
span => input!(),
|
span => input!(),
|
||||||
@ -378,7 +364,6 @@ fn token<'a>(input: OffsetStrIter<'a>) -> Result<OffsetStrIter<'a>, Token> {
|
|||||||
either!(
|
either!(
|
||||||
input,
|
input,
|
||||||
strtok,
|
strtok,
|
||||||
pipequotetok,
|
|
||||||
emptytok, // This must come before the barewordtok
|
emptytok, // This must come before the barewordtok
|
||||||
digittok,
|
digittok,
|
||||||
commatok,
|
commatok,
|
||||||
@ -528,14 +513,6 @@ 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)
|
||||||
};
|
};
|
||||||
|
@ -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]
|
#[test]
|
||||||
fn test_string_with_escaping() {
|
fn test_string_with_escaping() {
|
||||||
let result = strtok(OffsetStrIter::new("\"foo \\\\ \\\"bar\""));
|
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