summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2023-01-23 11:36:31 +0100
committerJo-Philipp Wich <jo@mein.io>2023-01-23 11:36:31 +0100
commitf1be0d725735fd8dd489494b00e954a93223f722 (patch)
tree2a433e6506d6cd3a61bf75f4829de46f22c9a9af
parent48a6eac1da1584ea784fd7d53f761baa87ae84d2 (diff)
types: fix array unshift operations and add test coverage
- Fix `ucv_array_unshift()` improperly rejecting operation on empty arrays - Fix `uc_unshift()` improperly reversing maintaining argument order - Add missing test coverage for `push()`, `pop()`, `unshift()` and `shift()` array operations. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--lib.c6
-rw-r--r--tests/custom/03_stdlib/65_push52
-rw-r--r--tests/custom/03_stdlib/66_unshift52
-rw-r--r--tests/custom/03_stdlib/67_pop37
-rw-r--r--tests/custom/03_stdlib/68_shift37
-rw-r--r--types.c2
6 files changed, 182 insertions, 4 deletions
diff --git a/lib.c b/lib.c
index 0366a13..a0a1b9b 100644
--- a/lib.c
+++ b/lib.c
@@ -464,18 +464,18 @@ static uc_value_t *
uc_unshift(uc_vm_t *vm, size_t nargs)
{
uc_value_t *arr = uc_fn_arg(0);
- uc_value_t *item = NULL;
+ uc_value_t *item;
size_t i;
if (!assert_mutable_array(vm, arr))
return NULL;
for (i = 1; i < nargs; i++) {
- item = uc_fn_arg(i);
+ item = uc_fn_arg(nargs - i);
ucv_array_unshift(arr, ucv_get(item));
}
- return ucv_get(item);
+ return (nargs > 1) ? ucv_get(uc_fn_arg(nargs - 1)) : NULL;
}
static uc_value_t *
diff --git a/tests/custom/03_stdlib/65_push b/tests/custom/03_stdlib/65_push
new file mode 100644
index 0000000..c6707dd
--- /dev/null
+++ b/tests/custom/03_stdlib/65_push
@@ -0,0 +1,52 @@
+The `push()` function appends the given argument(s) to the end of the given array
+while maintaining their order.
+
+Returns the last pushed value.
+
+Returns `null` if the given destination argment is not an array.
+
+Throws a type exception if the given array is immuatable.
+
+-- Testcase --
+{%
+ let arr = [];
+
+ printf("%.J\n", [
+ // push one element
+ push(arr, 123),
+
+ // push multiple elements
+ push(arr, 1, 2, 3),
+
+ // push null values
+ push(arr, null, null, 4),
+
+ // push no-op
+ push(arr),
+
+ // push with invalid destination
+ push({}, 1, 2, 3)
+ ]);
+
+ printf("%.J\n", arr);
+%}
+-- End --
+
+-- Expect stdout --
+[
+ 123,
+ 3,
+ 4,
+ null,
+ null
+]
+[
+ 123,
+ 1,
+ 2,
+ 3,
+ null,
+ null,
+ 4
+]
+-- End --
diff --git a/tests/custom/03_stdlib/66_unshift b/tests/custom/03_stdlib/66_unshift
new file mode 100644
index 0000000..9771661
--- /dev/null
+++ b/tests/custom/03_stdlib/66_unshift
@@ -0,0 +1,52 @@
+The `unshift()` function places the given argument(s) at the begin of the
+given array while maintaining their order.
+
+Returns the last added value.
+
+Returns `null` if the given destination argment is not an array.
+
+Throws a type exception if the given array is immuatable.
+
+-- Testcase --
+{%
+ let arr = [];
+
+ printf("%.J\n", [
+ // add one element
+ unshift(arr, 123),
+
+ // add multiple elements
+ unshift(arr, 1, 2, 3),
+
+ // add null values
+ unshift(arr, null, null, 4),
+
+ // no-op
+ unshift(arr),
+
+ // invalid destination
+ unshift({}, 1, 2, 3)
+ ]);
+
+ printf("%.J\n", arr);
+%}
+-- End --
+
+-- Expect stdout --
+[
+ 123,
+ 3,
+ 4,
+ null,
+ null
+]
+[
+ null,
+ null,
+ 4,
+ 1,
+ 2,
+ 3,
+ 123
+]
+-- End --
diff --git a/tests/custom/03_stdlib/67_pop b/tests/custom/03_stdlib/67_pop
new file mode 100644
index 0000000..1af11fa
--- /dev/null
+++ b/tests/custom/03_stdlib/67_pop
@@ -0,0 +1,37 @@
+The `pop()` function removes the last element of the given source array.
+
+Returns the removed value.
+
+Returns `null` if the given source argment is not an array.
+
+Throws a type exception if the given array is immuatable.
+
+-- Testcase --
+{%
+ let arr = [ 1, null, 3 ];
+
+ printf("%.J\n", [
+ // remove one element
+ pop(arr),
+
+ // remove a null element
+ pop(arr),
+
+ // invalid source
+ pop({ test: true })
+ ]);
+
+ printf("%.J\n", arr);
+%}
+-- End --
+
+-- Expect stdout --
+[
+ 3,
+ null,
+ null
+]
+[
+ 1
+]
+-- End --
diff --git a/tests/custom/03_stdlib/68_shift b/tests/custom/03_stdlib/68_shift
new file mode 100644
index 0000000..7b0df89
--- /dev/null
+++ b/tests/custom/03_stdlib/68_shift
@@ -0,0 +1,37 @@
+The `shift()` function removes the first element of the given source array.
+
+Returns the removed value.
+
+Returns `null` if the given source argment is not an array.
+
+Throws a type exception if the given array is immuatable.
+
+-- Testcase --
+{%
+ let arr = [ 1, null, 3 ];
+
+ printf("%.J\n", [
+ // remove one element
+ shift(arr),
+
+ // remove a null element
+ shift(arr),
+
+ // invalid source
+ shift({ test: true })
+ ]);
+
+ printf("%.J\n", arr);
+%}
+-- End --
+
+-- Expect stdout --
+[
+ 1,
+ null,
+ null
+]
+[
+ 3
+]
+-- End --
diff --git a/types.c b/types.c
index cde2221..321392e 100644
--- a/types.c
+++ b/types.c
@@ -772,7 +772,7 @@ ucv_array_unshift(uc_value_t *uv, uc_value_t *item)
uc_array_t *array = (uc_array_t *)uv;
size_t i;
- if (ucv_type(uv) != UC_ARRAY || array->count == 0)
+ if (ucv_type(uv) != UC_ARRAY)
return NULL;
array->count++;