Skip to content

Commit

Permalink
tests: add functional tests for builtin functions
Browse files Browse the repository at this point in the history
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
  • Loading branch information
jow- committed Feb 3, 2022
1 parent d5003fd commit 7edad5c
Show file tree
Hide file tree
Showing 50 changed files with 4,180 additions and 0 deletions.
27 changes: 27 additions & 0 deletions tests/custom/03_stdlib/01_chr
@@ -0,0 +1,27 @@
The `chr()` function converts each given numeric value into a character
and returns the resulting string, e.g. passing 97, 98 and 99 will yield
the string `abc`.

Negative numeric values and values which cannot be converted to integers
are treated as `0`, values larger than `255` are capped to `255`.

The resulting string will have the same length as the amount of arguments
passed to the `chr()` function.

-- Testcase --
{%
printf("%.J\n", [
chr(),
chr(97, 98, 99),
chr(-1, false, null, [], {}, "0x41", 66.5, 1000)
]);
%}
-- End --

-- Expect stdout --
[
"",
"abc",
"\u0000\u0000\u0000\u0000\u0000AB\u00ff"
]
-- End --
49 changes: 49 additions & 0 deletions tests/custom/03_stdlib/02_die
@@ -0,0 +1,49 @@
The `die()` function triggers a user defined runtime exception when invoked,
using the given value as exception message.

The given message value is converted to a string internally if it is not a
string already. If no message argument is given or if the message argument
is `null`, the default message is `Died`.

The function does not return.

-- Testcase --
{%
print("Before invoking die()\n");

die("An exception!");

print("After invoking die()\n");
%}
-- End --

-- Expect stdout --
Before invoking die()
-- End --

-- Expect stderr --
An exception!
In line 4, byte 21:

` die("An exception!");`
Near here -------------^


-- End --


-- Testcase --
{%
die();
%}
-- End --

-- Expect stderr --
Died
In line 2, byte 6:

` die();`
^-- Near here


-- End --
38 changes: 38 additions & 0 deletions tests/custom/03_stdlib/03_exists
@@ -0,0 +1,38 @@
The `exists()` function checks the existence of the given key within the
given object. If the object contains the given key, `true` is returned,
otherwise `false`.

If the object argument is not an object, `false` is returned as well.

The key argument is converted to a string in case it is not one already.

-- Testcase --
{%
let obj = {
"foo": true,
"bar": false,
"false": null,
"123": "a number"
};

printf("%.J\n", [
exists(true, "test"),
exists(obj, "doesnotexists"),
exists(obj, "foo"),
exists(obj, "bar"),
exists(obj, !true),
exists(obj, 123)
]);
%}
-- End --

-- Expect stdout --
[
false,
false,
true,
true,
true,
true
]
-- End --
36 changes: 36 additions & 0 deletions tests/custom/03_stdlib/04_exit
@@ -0,0 +1,36 @@
The `exit()` function terminates the running program with the given exit
code or 0 in case no argument is given or if the argument cannot be
converted to an integer.

The function does not return.

-- Testcase --
{%
print("Before invoking exit()\n");

exit();

print("After invoking exit()\n");
%}
-- End --

-- Expect stdout --
Before invoking exit()
-- End --

-- Expect exitcode --
0
-- End --


Passing a code argument overrides the default "0" value.

-- Testcase --
{%
exit(123)
%}
-- End --

-- Expect exitcode --
123
-- End --
30 changes: 30 additions & 0 deletions tests/custom/03_stdlib/05_getenv
@@ -0,0 +1,30 @@
The `getenv()` function returns the value of the given environment variable
or `null` if either the given variable does not exist or if the given name
argument is not a string.

-- Testcase --
{%
printf("%.J\n", [
getenv("TEST_VARIABLE"),
getenv("EMPTY_VARIABLE"),
getenv("THIS_LIKELY_DOES_NOT_EXIST"),
getenv(123),
getenv(null)
]);
%}
-- End --

-- Vars --
TEST_VARIABLE=Test Value
EMPTY_VARIABLE=
-- End --

-- Expect stdout --
[
"Test Value",
"",
null,
null,
null
]
-- End --
113 changes: 113 additions & 0 deletions tests/custom/03_stdlib/06_filter
@@ -0,0 +1,113 @@
The `filter()` function filters the given array by invoking the specified
callback for each item of the input array and only keeping items for which
the callback returned a truish value.

Returns the filtered copy of the input array, maintaining the original order
of items. The input array is not modified.

Returns `null` if the first argument is not an array.

-- Testcase --
{%
let numbers = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];

printf("%.J\n",
filter(numbers, function(n) {
return (n % 2) == 0;
})
);
%}
-- End --

-- Expect stdout --
[
0,
2,
4,
6,
8
]
-- End --


Supplying an invalid callback will trigger an exception.

-- Testcase --
{%
filter([1, 2, 3], "not_a_function")
%}
-- End --

-- Expect stderr --
Type error: left-hand side is not a function
In line 2, byte 36:

` filter([1, 2, 3], "not_a_function")`
Near here ----------------------------^


-- End --


Supplying an invalid array will yield `null`.

-- Testcase --
{%
printf("%.J\n", filter("not_an_array", function(i) { return i > 3 }));
%}
-- End --

-- Expect stdout --
null
-- End --


The callback is invoked with three argument for each item, the current item
value, the index position of the item and the input array being mapped.

-- Testcase --
{%
let words = [ "foo", "bar", "baz", "qrx" ];

print(join("\n",
filter(words, function(word, idx, src) {
printf("word=%s, idx=%d, src=%J\n", word, idx, src);

return true;
})
), "\n");
%}
-- End --

-- Expect stdout --
word=foo, idx=0, src=[ "foo", "bar", "baz", "qrx" ]
word=bar, idx=1, src=[ "foo", "bar", "baz", "qrx" ]
word=baz, idx=2, src=[ "foo", "bar", "baz", "qrx" ]
word=qrx, idx=3, src=[ "foo", "bar", "baz", "qrx" ]
foo
bar
baz
qrx
-- End --


Exceptions in the callback terminate the filter process and are
propagated to the calling context.

-- Testcase --
{%
filter([ 1, 2, 3 ], function() { die() });
%}
-- End --

-- Expect stderr --
Died
In [anonymous function](), line 2, byte 39:
called from function filter ([C])
called from anonymous function ([stdin]:2:42)

` filter([ 1, 2, 3 ], function() { die() });`
Near here -------------------------------^


-- End --
33 changes: 33 additions & 0 deletions tests/custom/03_stdlib/07_hex
@@ -0,0 +1,33 @@
The `hex()` function converts the given hexadecimal string into a signed
integer value and returns the resulting number.

Returns `NaN` if the given argument is not a string, an empty string or
a string containing non-hexadecimal digits.

-- Testcase --
{%
printf("%.J\n", [
hex(),
hex(false),
hex(123),
hex(""),
hex("invalid"),
hex("deaf"),
hex("0x1000"),
hex("ffffffffffffffff")
]);
%}
-- End --

-- Expect stdout --
[
"NaN",
"NaN",
"NaN",
"NaN",
"NaN",
57007,
4096,
9223372036854775807
]
-- End --
42 changes: 42 additions & 0 deletions tests/custom/03_stdlib/08_int
@@ -0,0 +1,42 @@
The `int()` function converts the given value into a signed integer
value and returns the resulting number.

Returns `NaN` if the given argument is not convertible into a number.

Returns `NaN` if the conversion result is out of range.

-- Testcase --
{%
printf("%.J\n", [
int(),
int(false),
int(123),
int(456.789),
int(""),
int("invalid"),
int("deaf"),
int("0x1000"),
int("0xffffffffffffffff"),
int("0177"),
int("+145"),
int("-96")
]);
%}
-- End --

-- Expect stdout --
[
0,
0,
123,
456,
0,
"NaN",
"NaN",
4096,
"NaN",
127,
"NaN",
-96
]
-- End --

0 comments on commit 7edad5c

Please sign in to comment.