Skip to content

Commit

Permalink
Merge pull request #37 from jow-/stdlib-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jow- committed Feb 3, 2022
2 parents 3878da8 + 7edad5c commit 5bd764a
Show file tree
Hide file tree
Showing 55 changed files with 4,263 additions and 31 deletions.
63 changes: 46 additions & 17 deletions lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -927,9 +927,18 @@ uc_split(uc_vm_t *vm, size_t nargs)
if (res == REG_NOMATCH)
break;

ucv_array_push(arr, ucv_string_new_length(splitstr, pmatch.rm_so));
if (pmatch.rm_so != pmatch.rm_eo) {
ucv_array_push(arr, ucv_string_new_length(splitstr, pmatch.rm_so));
splitstr += pmatch.rm_eo;
}
else if (*splitstr) {
ucv_array_push(arr, ucv_string_new_length(splitstr, 1));
splitstr++;
}
else {
goto out;
}

splitstr += pmatch.rm_eo;
eflags |= REG_NOTBOL;
}

Expand All @@ -956,6 +965,7 @@ uc_split(uc_vm_t *vm, size_t nargs)
return NULL;
}

out:
return arr;
}

Expand Down Expand Up @@ -1794,7 +1804,13 @@ uc_match(uc_vm_t *vm, size_t nargs)

ucv_array_push(rv, m);

p += pmatch[0].rm_eo;
if (pmatch[0].rm_so != pmatch[0].rm_eo)
p += pmatch[0].rm_eo;
else if (*p)
p++;
else
break;

eflags |= REG_NOTBOL;
}
else {
Expand Down Expand Up @@ -1959,7 +1975,12 @@ uc_replace(uc_vm_t *vm, size_t nargs)
uc_replace_str(vm, replace, p, pmatch, ARRAY_SIZE(pmatch), resbuf);
}

p += pmatch[0].rm_eo;
if (pmatch[0].rm_so != pmatch[0].rm_eo)
p += pmatch[0].rm_eo;
else if (*p)
ucv_stringbuf_addstr(resbuf, p++, 1);
else
break;

if (re->global)
eflags |= REG_NOTBOL;
Expand All @@ -1973,8 +1994,10 @@ uc_replace(uc_vm_t *vm, size_t nargs)
pt = uc_cast_string(vm, &pattern, &pt_freeable);
pl = strlen(pt);

for (l = p = sb; *p; p++) {
if (!strncmp(p, pt, pl)) {
l = p = sb;

while (true) {
if (pl == 0 || !strncmp(p, pt, pl)) {
ucv_stringbuf_addstr(resbuf, l, p - l);

pmatch[0].rm_so = p - l;
Expand All @@ -1997,9 +2020,17 @@ uc_replace(uc_vm_t *vm, size_t nargs)
uc_replace_str(vm, replace, l, pmatch, 1, resbuf);
}

l = p + pl;
p += pl - 1;
if (pl) {
l = p + pl;
p += pl - 1;
}
else {
l = p;
}
}

if (!*p++)
break;
}

ucv_stringbuf_addstr(resbuf, l, strlen(l));
Expand All @@ -2017,10 +2048,10 @@ uc_replace(uc_vm_t *vm, size_t nargs)
static uc_value_t *
uc_json(uc_vm_t *vm, size_t nargs)
{
uc_value_t *rv, *src = uc_fn_arg(0);
uc_value_t *rv = NULL, *src = uc_fn_arg(0);
struct json_tokener *tok = NULL;
enum json_tokener_error err;
json_object *jso;
json_object *jso = NULL;
const char *str;
size_t len;

Expand All @@ -2042,32 +2073,30 @@ uc_json(uc_vm_t *vm, size_t nargs)
err = json_tokener_get_error(tok);

if (err == json_tokener_continue) {
json_object_put(jso);
uc_vm_raise_exception(vm, EXCEPTION_SYNTAX,
"Unexpected end of string in JSON data");

return NULL;
goto out;
}
else if (err != json_tokener_success) {
json_object_put(jso);
uc_vm_raise_exception(vm, EXCEPTION_SYNTAX,
"Failed to parse JSON string: %s",
json_tokener_error_desc(err));

return NULL;
goto out;
}
else if (json_tokener_get_parse_end(tok) < len) {
json_object_put(jso);
uc_vm_raise_exception(vm, EXCEPTION_SYNTAX,
"Trailing garbage after JSON data");

return NULL;
goto out;
}

json_tokener_free(tok);

rv = ucv_from_json(vm, jso);

out:
json_tokener_free(tok);
json_object_put(jso);

return rv;
Expand Down
2 changes: 1 addition & 1 deletion source.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ uc_source_put(uc_source_t *source)
uc_source_type_t
uc_source_type_test(uc_source_t *source)
{
union { char s[sizeof(uint32_t)]; uint32_t n; } buf;
union { char s[sizeof(uint32_t)]; uint32_t n; } buf = { 0 };
uc_source_type_t type = UC_SOURCE_TYPE_PLAIN;
FILE *fp = source->fp;
size_t rlen;
Expand Down
27 changes: 27 additions & 0 deletions tests/custom/03_stdlib/01_chr
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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 --

0 comments on commit 5bd764a

Please sign in to comment.