mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
2b18f03b2b
It's mostly useless, but aren't we all. Also added benchmarks to make sure I didn't mess anything up. And one or two tiny but unrelated fixes. --------- Signed-off-by: Anders Eknert <anders.eknert@apple.com> Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com> Co-authored-by: Stephan Renatus <stephan.renatus@gmail.com>
3871 lines
179 KiB
C
3871 lines
179 KiB
C
#include <ctype.h>
|
|
|
|
#include "aggregates.h"
|
|
#include "arithmetic.h"
|
|
#include "array.h"
|
|
#include "bits-builtins.h"
|
|
#include "cidr.h"
|
|
#include "conversions.h"
|
|
#include "encoding.h"
|
|
#include "glob.h"
|
|
#include "graphs.h"
|
|
#include "json.h"
|
|
#include "malloc.h"
|
|
#include "memoize.h"
|
|
#include "mpd.h"
|
|
#include "numbers.h"
|
|
#include "object.h"
|
|
#include "regex.h"
|
|
#include "set.h"
|
|
#include "str.h"
|
|
#include "strings.h"
|
|
#include "test.h"
|
|
#include "types.h"
|
|
#include "template-string.h"
|
|
|
|
// NOTE(sr): we've removed the float number representation, so this helper
|
|
// is to make our tests less annoying:
|
|
#define opa_number_float(f) opa_number_ref(#f, sizeof(#f))
|
|
|
|
void reset_heap(void)
|
|
{
|
|
// This will leak memory!!
|
|
// TODO: How should we safely reset it if we don't know the original starting ptr?
|
|
opa_heap_ptr_set(opa_heap_top_get());
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_malloc)
|
|
void test_opa_malloc(void)
|
|
{
|
|
opa_malloc_init_test();
|
|
|
|
reset_heap();
|
|
|
|
// NOTE(tsandall): These numbers are not particularly important. They're
|
|
// sized to cause opa_malloc to call grow.memory. The tester initializes
|
|
// memory with 2 pages so we allocate ~4 pages of memory here.
|
|
const int N = 256;
|
|
const int S = 1024;
|
|
|
|
for(int i = 0; i < N; i++)
|
|
{
|
|
char *buf = opa_malloc(S);
|
|
|
|
for(int x = 0; x < S; x++)
|
|
{
|
|
buf[x] = x % 255;
|
|
}
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_malloc_min_size)
|
|
void test_opa_malloc_min_size(void)
|
|
{
|
|
reset_heap();
|
|
|
|
// Ensure that allocations less than the minimum size
|
|
// are creating blocks large enough to be re-used by
|
|
// the minimum size.
|
|
void *too_small = opa_malloc(2);
|
|
test("allocated min block", too_small != NULL);
|
|
|
|
void *barrier = opa_malloc(0);
|
|
|
|
opa_free(too_small);
|
|
|
|
test("new free block", opa_heap_free_blocks() == 1);
|
|
|
|
void *min_sized = opa_malloc(4);
|
|
test("reused block", opa_heap_free_blocks() == 0);
|
|
opa_free(min_sized);
|
|
opa_free(barrier);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_malloc_split_threshold_small_block)
|
|
void test_opa_malloc_split_threshold_small_block(void)
|
|
{
|
|
reset_heap();
|
|
|
|
// Ensure that free blocks larger than the requested
|
|
// allocation, but too small to leave a sufficiently
|
|
// sized remainder, are left intact.
|
|
size_t heap_block_size = 12;
|
|
void *too_small = opa_malloc(2 * 128 + heap_block_size - 1);
|
|
test("allocated too_small block", too_small != NULL);
|
|
|
|
void *barrier = opa_malloc(256);
|
|
|
|
opa_free(too_small);
|
|
|
|
test("new small free block", opa_heap_free_blocks() == 1);
|
|
|
|
// Expect the smaller allocation to use the bigger block
|
|
// without splitting.
|
|
void *new = opa_malloc(128);
|
|
test("unable to split block", opa_heap_free_blocks() == 0);
|
|
opa_free(new);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_malloc_split_threshold_big_block)
|
|
void test_opa_malloc_split_threshold_big_block(void)
|
|
{
|
|
reset_heap();
|
|
|
|
// Ensure that free blocks large enough to be split are split up
|
|
// until they are too small: have space almost to allocate three
|
|
// separate 128 blocks.
|
|
size_t heap_block_size = 12;
|
|
void *splittable = opa_malloc(3 * 128 + 2 * heap_block_size - 1);
|
|
test("allocated splittable block", splittable != NULL);
|
|
|
|
void *barrier = opa_malloc(128);
|
|
|
|
opa_free(splittable);
|
|
test("new large free block", opa_heap_free_blocks() == 1);
|
|
|
|
// Expect to be able to get multiple blocks out of the new free one without
|
|
// new allocations.
|
|
unsigned int high = opa_heap_ptr_get();
|
|
|
|
void *split1 = opa_malloc(128);
|
|
void *split2 = opa_malloc(128); // Too big to split remaining bytes, should take oversized block.
|
|
|
|
test("heap ptr", high == opa_heap_ptr_get());
|
|
test("remaining free blocks", opa_heap_free_blocks() == 0);
|
|
|
|
opa_free(split1);
|
|
opa_free(split2);
|
|
opa_free(barrier);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_free)
|
|
void test_opa_free(void)
|
|
{
|
|
reset_heap();
|
|
|
|
|
|
// check the heap shrinks with a single malloc and free.
|
|
|
|
size_t blocks = opa_heap_free_blocks();
|
|
opa_free(opa_malloc(0));
|
|
|
|
test("free blocks", blocks == 0 && opa_heap_free_blocks() == 1);
|
|
|
|
// check the double malloc, followed with frees in identical order
|
|
// results in eventual heap shrinking.
|
|
|
|
void *p1 = opa_malloc(0);
|
|
void *p2 = opa_malloc(0);
|
|
test("free blocks", opa_heap_free_blocks() == 0);
|
|
|
|
opa_free(p1);
|
|
test("free blocks", opa_heap_free_blocks() == 1);
|
|
|
|
opa_free(p2);
|
|
test("free blocks", opa_heap_free_blocks() == 2);
|
|
|
|
// check the double malloc, followed with frees in reverse order
|
|
// results in gradual heap shrinking.
|
|
|
|
p1 = opa_malloc(0);
|
|
p2 = opa_malloc(0);
|
|
test("free blocks", opa_heap_free_blocks() == 0);
|
|
|
|
opa_free(p2);
|
|
test("free blocks", opa_heap_free_blocks() == 1);
|
|
|
|
opa_free(p1);
|
|
test("free blocks", opa_heap_free_blocks() == 2);
|
|
|
|
// check the free re-use (without splitting).
|
|
|
|
p1 = opa_malloc(1);
|
|
p2 = opa_malloc(1);
|
|
|
|
opa_free(p1);
|
|
test("free blocks", opa_heap_free_blocks() == 1);
|
|
|
|
p1 = opa_malloc(1);
|
|
test("free blocks", opa_heap_free_blocks() == 0);
|
|
|
|
opa_free(p2);
|
|
opa_free(p1);
|
|
test("free blocks", opa_heap_free_blocks() == 2);
|
|
|
|
// check the free re-use (with splitting).
|
|
|
|
p1 = opa_malloc(512);
|
|
p2 = opa_malloc(512);
|
|
|
|
opa_free(p1);
|
|
test("free blocks", opa_heap_free_blocks() == 3);
|
|
// 2 small, 1 large
|
|
|
|
p1 = opa_malloc(128);
|
|
test("free blocks", opa_heap_free_blocks() == 3);
|
|
// 2 small, 1 large (split p1)
|
|
|
|
opa_free(p2);
|
|
test("free blocks", opa_heap_free_blocks() == 3);
|
|
// 2 small, 1 large (merged end-p1, p2)
|
|
|
|
opa_free(p1);
|
|
test("free blocks", opa_heap_free_blocks() == 3);
|
|
// 2 small, 1 large (merged start-p1,end-p1+p2)
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_heap_blocks_stash)
|
|
void test_opa_heap_blocks_stash(void)
|
|
{
|
|
reset_heap();
|
|
|
|
unsigned int base = opa_heap_ptr_get();
|
|
void *p1;
|
|
void *p2;
|
|
|
|
// check basic save / restore
|
|
p1 = opa_malloc(128);
|
|
p2 = opa_malloc(128);
|
|
opa_free(p1);
|
|
test("free blocks", opa_heap_free_blocks() == 1);
|
|
opa_heap_blocks_stash();
|
|
test("free blocks", opa_heap_free_blocks() == 0);
|
|
opa_heap_blocks_restore();
|
|
test("free blocks", opa_heap_free_blocks() == 1);
|
|
opa_free(p2);
|
|
test("free blocks", opa_heap_free_blocks() == 1);
|
|
// 1 merged block remaining
|
|
|
|
// check opa_heap_stash_clear()
|
|
p1 = opa_malloc(128);
|
|
p2 = opa_malloc(128);
|
|
opa_free(p1);
|
|
opa_heap_blocks_stash();
|
|
opa_heap_stash_clear();
|
|
opa_heap_blocks_restore();
|
|
test("free blocks", opa_heap_free_blocks() == 0);
|
|
opa_heap_ptr_set(base); // p2 is dangling, but we'll discard it
|
|
}
|
|
|
|
#define MAX_TEST_BLOCKS 100
|
|
static void *sort_blocks[MAX_TEST_BLOCKS];
|
|
unsigned int prng_state = 1;
|
|
#define AX 65537
|
|
#define CX 123
|
|
|
|
/* Use a pseudo-random number generator to ensure test repeatability */
|
|
static void prng_seed(unsigned int n)
|
|
{
|
|
prng_state = n;
|
|
}
|
|
|
|
static unsigned int prng(unsigned int max)
|
|
{
|
|
unsigned int v = (prng_state * AX + CX) % max;
|
|
prng_state = v;
|
|
return v;
|
|
}
|
|
|
|
static void test_opa_block_sort(unsigned int nblocks)
|
|
{
|
|
int i, j;
|
|
void *h;
|
|
|
|
test("valid nblocks", nblocks <= MAX_TEST_BLOCKS);
|
|
|
|
reset_heap();
|
|
|
|
/* Allocate N blocks */
|
|
for (i = 0; i < nblocks; i++) {
|
|
sort_blocks[i] = opa_malloc(128);
|
|
test("available blocks", sort_blocks[i] != NULL);
|
|
}
|
|
|
|
/* Randomize the blocks */
|
|
prng_seed(nblocks);
|
|
for (i = 0; i < nblocks; i++)
|
|
{
|
|
j = prng(nblocks - i) + i;
|
|
h = sort_blocks[i];
|
|
sort_blocks[i] = sort_blocks[j];
|
|
sort_blocks[j] = h;
|
|
}
|
|
|
|
/* Bulk free all the blocks */
|
|
for (i = 0; i < nblocks; i++)
|
|
opa_free_bulk(sort_blocks[i]);
|
|
|
|
/* This will abort when compiled with DEBUG if order is violated */
|
|
opa_free_bulk_commit();
|
|
|
|
test("total heap blocks", opa_heap_free_blocks() == 1);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_block_sorting)
|
|
void test_opa_block_sorting(void)
|
|
{
|
|
test_opa_block_sort(1);
|
|
test_opa_block_sort(2);
|
|
test_opa_block_sort(3);
|
|
test_opa_block_sort(4);
|
|
test_opa_block_sort(10);
|
|
test_opa_block_sort(30);
|
|
test_opa_block_sort(100);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_free_bulk)
|
|
void test_opa_free_bulk(void)
|
|
{
|
|
reset_heap();
|
|
|
|
void *p1;
|
|
void *p2;
|
|
void *p3;
|
|
void *p4;
|
|
|
|
p1 = opa_malloc(128);
|
|
p2 = opa_malloc(128);
|
|
p3 = opa_malloc(128);
|
|
p4 = opa_malloc(128);
|
|
|
|
opa_free_bulk(p1);
|
|
opa_free_bulk(p3);
|
|
|
|
// blocks are on the bulk freelist and won't be reclaimed
|
|
// until the next malloc().
|
|
test("free blocks", opa_heap_free_blocks() == 0);
|
|
p1 = opa_malloc(128);
|
|
test("free blocks", opa_heap_free_blocks() == 1);
|
|
|
|
// now free them all and allocate 1. Check others aggregated
|
|
opa_free_bulk(p1);
|
|
opa_free_bulk(p2);
|
|
opa_free_bulk(p4);
|
|
|
|
p1 = opa_malloc(128);
|
|
test("free blocks", opa_heap_free_blocks() == 1);
|
|
opa_free(p1);
|
|
test("free blocks", opa_heap_free_blocks() == 1);
|
|
|
|
// Check that small blocks are released to the heap immediately
|
|
p1 = opa_malloc(32);
|
|
opa_free_bulk(p1);
|
|
test("free blocks", opa_heap_free_blocks() == 2);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_memoize)
|
|
void test_opa_memoize(void)
|
|
{
|
|
opa_memoize_init();
|
|
|
|
opa_memoize_insert(100, opa_number_int(1));
|
|
opa_memoize_insert(200, opa_number_int(2));
|
|
opa_value *a = opa_memoize_get(100);
|
|
opa_value *b = opa_memoize_get(200);
|
|
opa_memoize_push();
|
|
opa_value *c = opa_memoize_get(100);
|
|
opa_value *d = opa_memoize_get(200);
|
|
opa_memoize_insert(100, opa_number_int(3));
|
|
opa_memoize_pop();
|
|
opa_value *e = opa_memoize_get(100);
|
|
|
|
opa_value *exp_a = opa_number_int(1);
|
|
opa_value *exp_b = opa_number_int(2);
|
|
opa_value *exp_c = NULL;
|
|
opa_value *exp_d = NULL;
|
|
opa_value *exp_e = opa_number_int(1);
|
|
|
|
test("insert-a", opa_value_compare(a, exp_a) == 0);
|
|
test("insert-b", opa_value_compare(b, exp_b) == 0);
|
|
test("get-a-after-push", opa_value_compare(c, exp_c) == 0);
|
|
test("get-b-after-push", opa_value_compare(d, exp_d) == 0);
|
|
test("get-a-after-pop", opa_value_compare(e, exp_e) == 0);
|
|
}
|
|
|
|
// NOTE(sr): These tests are run in order. If they weren't, every test that
|
|
// depends on mpd's state being initialized would have to call `opa_mpd_init`
|
|
// first. When the Wasm module is used, the `Start` function (`_initialize`,
|
|
// emitted from the Wasm compiler) takes care of that.
|
|
WASM_EXPORT(test_opa_mpd)
|
|
void test_opa_mpd(void)
|
|
{
|
|
// NOTE(sr): This call also initializes mpd_one, which is used under the
|
|
// hood for `qadd_one`.
|
|
opa_mpd_init();
|
|
opa_value *zero = opa_number_int(0);
|
|
opa_value *two = opa_bf_to_number(qadd_one(qadd_one(opa_number_to_bf(zero))));
|
|
test("0+1+1 is 2", opa_value_compare(opa_number_int(2), two) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_strlen)
|
|
void test_opa_strlen(void)
|
|
{
|
|
test("empty", opa_strlen("") == 0);
|
|
test("non-empty", opa_strlen("1234") == 4);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_strncmp)
|
|
void test_opa_strncmp(void)
|
|
{
|
|
test("empty", opa_strncmp("", "", 0) == 0);
|
|
test("equal", opa_strncmp("1234", "1234", 4) == 0);
|
|
test("less than", opa_strncmp("1234", "1243", 4) < 0);
|
|
test("greater than", opa_strncmp("1243", "1234", 4) > 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_strcmp)
|
|
void test_opa_strcmp(void)
|
|
{
|
|
test("empty", opa_strcmp("", "") == 0);
|
|
test("equal", opa_strcmp("abcd", "abcd") == 0);
|
|
test("less than", opa_strcmp("1234", "1243") < 0);
|
|
test("greater than", opa_strcmp("1243", "1234") > 0);
|
|
test("shorter", opa_strcmp("123", "1234") < 0);
|
|
test("longer", opa_strcmp("1234", "123") > 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_itoa)
|
|
void test_opa_itoa(void)
|
|
{
|
|
char buf[sizeof(long long)*8+1];
|
|
|
|
test("itoa", opa_strcmp(opa_itoa(0, buf, 10), "0") == 0);
|
|
test("itoa", opa_strcmp(opa_itoa(-128, buf, 10), "-128") == 0);
|
|
test("itoa", opa_strcmp(opa_itoa(127, buf, 10), "127") == 0);
|
|
test("itoa", opa_strcmp(opa_itoa(0x7FFFFFFFFFFFFFFF, buf, 10), "9223372036854775807") == 0);
|
|
test("itoa", opa_strcmp(opa_itoa(0x8000000000000001, buf, 10), "-9223372036854775807") == 0);
|
|
test("itoa", opa_strcmp(opa_itoa(0xFFFFFFFFFFFFFFFF, buf, 10), "-1") == 0);
|
|
|
|
test("itoa/base2", opa_strcmp(opa_itoa(0, buf, 2), "0") == 0);
|
|
test("itoa/base2", opa_strcmp(opa_itoa(-128, buf, 2), "-10000000") == 0);
|
|
test("itoa/base2", opa_strcmp(opa_itoa(127, buf, 2), "1111111") == 0);
|
|
test("itoa/base2", opa_strcmp(opa_itoa(0x7FFFFFFFFFFFFFFF, buf, 2), "111111111111111111111111111111111111111111111111111111111111111") == 0);
|
|
test("itoa/base2", opa_strcmp(opa_itoa(0x8000000000000001, buf, 2), "-111111111111111111111111111111111111111111111111111111111111111") == 0);
|
|
test("itoa/base2", opa_strcmp(opa_itoa(0xFFFFFFFFFFFFFFFF, buf, 2), "-1") == 0);
|
|
|
|
test("itoa/base16", opa_strcmp(opa_itoa(0, buf, 16), "0") == 0);
|
|
test("itoa/base16", opa_strcmp(opa_itoa(-128, buf, 16), "-80") == 0);
|
|
test("itoa/base16", opa_strcmp(opa_itoa(127, buf, 16), "7f") == 0);
|
|
test("itoa/base16", opa_strcmp(opa_itoa(0x7FFFFFFFFFFFFFFF, buf,16), "7fffffffffffffff") == 0);
|
|
test("itoa/base16", opa_strcmp(opa_itoa(0x8000000000000001, buf, 16), "-7fffffffffffffff") == 0);
|
|
test("itoa/base16", opa_strcmp(opa_itoa(0xFFFFFFFFFFFFFFFF, buf, 16), "-1") == 0);
|
|
}
|
|
|
|
|
|
int crunch_opa_atoi64(const char *str, long long exp, int exp_rc)
|
|
{
|
|
long long result;
|
|
int rc;
|
|
|
|
if ((rc = opa_atoi64(str, opa_strlen(str), &result)) != exp_rc)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return exp_rc != 0 || result == exp;
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_atoi64)
|
|
void test_opa_atoi64(void)
|
|
{
|
|
test("integer", crunch_opa_atoi64("127", 127, 0));
|
|
test("negative integer", crunch_opa_atoi64("-128", -128, 0));
|
|
test("non integer", crunch_opa_atoi64("-128.3", 0, -2));
|
|
test("empty", crunch_opa_atoi64("", 0, -1));
|
|
}
|
|
|
|
int crunch_opa_atof64(const char *str, double exp, int exp_rc)
|
|
{
|
|
double result;
|
|
int rc;
|
|
|
|
if ((rc = opa_atof64(str, opa_strlen(str), &result)) != exp_rc)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return exp_rc != 0 || result == exp;
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_atof64)
|
|
void test_opa_atof64(void)
|
|
{
|
|
test("empty", crunch_opa_atof64("", 0, -1));
|
|
test("bad integer", crunch_opa_atof64("1234-6", 0, -2));
|
|
test("bad fraction", crunch_opa_atof64("1234.5-6", 0, -2));
|
|
test("bad exponent", crunch_opa_atof64("1234.5e6-", 0, -2));
|
|
test("bad exponent", crunch_opa_atof64("12345e6-", 0, -2));
|
|
test("integer", crunch_opa_atof64("127", 127, 0));
|
|
test("negative integer", crunch_opa_atof64("-128", -128, 0));
|
|
test("fraction", crunch_opa_atof64("16.7", 16.7, 0));
|
|
test("exponent", crunch_opa_atof64("6e7", 6e7, 0));
|
|
}
|
|
|
|
WASM_EXPORT(test_memchr)
|
|
void test_memchr(void)
|
|
{
|
|
char s[] = { 1, 2, 2, 3 };
|
|
|
|
test("memchr", memchr(s, 2, 1) == NULL);
|
|
test("memchr", memchr(s, 2, sizeof(s)) == &s[1]);
|
|
test("memchr", memchr(s, 4, sizeof(s)) == NULL);
|
|
}
|
|
|
|
WASM_EXPORT(test_memcmp)
|
|
void test_memcmp(void)
|
|
{
|
|
char a[] = { 1, 2, 3, 4 }, b[] = { 1, 2, 3, 3 };
|
|
|
|
test("memcmp", memcmp(a, b, 3) == 0);
|
|
test("memcmp", memcmp(a, b, 4) == 1);
|
|
test("memcmp", memcmp(b, a, 4) == -1);
|
|
}
|
|
|
|
WASM_EXPORT(test_memcpy)
|
|
void test_memcpy(void)
|
|
{
|
|
char dest[] = { 1, 2, 3, 4 }, src[] = { 9, 8, 7 };
|
|
char expected[] = { 9, 8, 3, 4 };
|
|
memcpy(dest, src, 2);
|
|
|
|
test("memcpy", memcmp(dest, expected, sizeof(expected)) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_memset)
|
|
void test_memset(void)
|
|
{
|
|
char s[] = { 9, 8, 7, 6 };
|
|
char expected[] = { 1, 1, 1, 6 };
|
|
memset(s, 1, 3);
|
|
|
|
test("memset", memcmp(s, expected, sizeof(expected)) == 0);
|
|
}
|
|
|
|
int lex_crunch(const char *s)
|
|
{
|
|
opa_json_lex ctx;
|
|
opa_json_lex_init(s, opa_strlen(s), &ctx);
|
|
return opa_json_lex_read(&ctx);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_lex_tokens)
|
|
void test_opa_lex_tokens(void)
|
|
{
|
|
test("empty", lex_crunch("") == OPA_JSON_TOKEN_EOF);
|
|
test("space", lex_crunch(" ") == OPA_JSON_TOKEN_EOF);
|
|
test("tab", lex_crunch("\t") == OPA_JSON_TOKEN_EOF);
|
|
test("newline", lex_crunch("\n") == OPA_JSON_TOKEN_EOF);
|
|
test("carriage return", lex_crunch("\r") == OPA_JSON_TOKEN_EOF);
|
|
test("null", lex_crunch("null") == OPA_JSON_TOKEN_NULL);
|
|
test("true", lex_crunch("true") == OPA_JSON_TOKEN_TRUE);
|
|
test("false", lex_crunch("false") == OPA_JSON_TOKEN_FALSE);
|
|
|
|
test("bad unicode", lex_crunch("\" \\uabcx \"") == OPA_JSON_TOKEN_ERROR); // not hex
|
|
test("escape not closed", lex_crunch("\"a\\\"") == OPA_JSON_TOKEN_ERROR); // unmatched escape
|
|
test("bad escape character", lex_crunch("\"\\Q\"") == OPA_JSON_TOKEN_ERROR); // invalid escape character Q
|
|
test("object start", lex_crunch(" { ") == OPA_JSON_TOKEN_OBJECT_START);
|
|
test("object end", lex_crunch(" } ") == OPA_JSON_TOKEN_OBJECT_END);
|
|
test("array start", lex_crunch(" [ ") == OPA_JSON_TOKEN_ARRAY_START);
|
|
test("array end", lex_crunch(" ] ") == OPA_JSON_TOKEN_ARRAY_END);
|
|
test("element separator", lex_crunch(" , ") == OPA_JSON_TOKEN_COMMA);
|
|
test("item separator", lex_crunch(" : ") == OPA_JSON_TOKEN_COLON);
|
|
}
|
|
|
|
int lex_buffer_crunch(const char *s, const char *exp, int token)
|
|
{
|
|
opa_json_lex ctx;
|
|
opa_json_lex_init(s, opa_strlen(s), &ctx);
|
|
|
|
if (opa_json_lex_read(&ctx) != token)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
size_t exp_len = opa_strlen(exp);
|
|
size_t buf_len = ctx.buf_end - ctx.buf;
|
|
|
|
if (exp_len != buf_len)
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (opa_strncmp(ctx.buf, exp, buf_len) != 0)
|
|
{
|
|
return -3;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define test_lex_buffer(note, s, exp, token) test(note, (lex_buffer_crunch(s, exp, token) == 0))
|
|
|
|
WASM_EXPORT(test_opa_lex_buffer)
|
|
void test_opa_lex_buffer(void)
|
|
{
|
|
test_lex_buffer("zero", "0", "0", OPA_JSON_TOKEN_NUMBER);
|
|
test_lex_buffer("signed zero", "-0", "-0", OPA_JSON_TOKEN_NUMBER);
|
|
test_lex_buffer("integers", "1234567890", "1234567890", OPA_JSON_TOKEN_NUMBER);
|
|
test_lex_buffer("signed integers", "-1234567890", "-1234567890", OPA_JSON_TOKEN_NUMBER);
|
|
test_lex_buffer("floats", "0.1234567890", "0.1234567890", OPA_JSON_TOKEN_NUMBER);
|
|
test_lex_buffer("signed floats", "-0.1234567890", "-0.1234567890", OPA_JSON_TOKEN_NUMBER);
|
|
test_lex_buffer("exponents", "-0.1234567890e0", "-0.1234567890e0", OPA_JSON_TOKEN_NUMBER);
|
|
test_lex_buffer("exponents", "-0.1234567890E+1000", "-0.1234567890E+1000", OPA_JSON_TOKEN_NUMBER);
|
|
test_lex_buffer("exponents", "-0.1234567890E-1000", "-0.1234567890E-1000", OPA_JSON_TOKEN_NUMBER);
|
|
test_lex_buffer("empty string", "\"\"", "", OPA_JSON_TOKEN_STRING);
|
|
test_lex_buffer("escaped buffer", "\"a\\\"b\"", "a\\\"b", OPA_JSON_TOKEN_STRING_ESCAPED);
|
|
test_lex_buffer("escaped quote", "\"\\\"\"", "\\\"", OPA_JSON_TOKEN_STRING_ESCAPED);
|
|
test_lex_buffer("escaped reverse solidus", "\"\\\\\"", "\\\\", OPA_JSON_TOKEN_STRING_ESCAPED);
|
|
test_lex_buffer("escaped solidus", "\"\\/\"", "\\/", OPA_JSON_TOKEN_STRING_ESCAPED);
|
|
test_lex_buffer("escaped backspace", "\"\\b\"", "\\b", OPA_JSON_TOKEN_STRING_ESCAPED);
|
|
test_lex_buffer("escaped feed forward", "\"\\f\"", "\\f", OPA_JSON_TOKEN_STRING_ESCAPED);
|
|
test_lex_buffer("escaped line feed", "\"\\n\"", "\\n", OPA_JSON_TOKEN_STRING_ESCAPED);
|
|
test_lex_buffer("escaped carriage return", "\"\\r\"", "\\r", OPA_JSON_TOKEN_STRING_ESCAPED);
|
|
test_lex_buffer("escaped tab", "\"\\t\"", "\\t", OPA_JSON_TOKEN_STRING_ESCAPED);
|
|
test_lex_buffer("plain", "\"abcdefg\"", "abcdefg", OPA_JSON_TOKEN_STRING);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_compare)
|
|
void test_opa_value_compare(void)
|
|
{
|
|
test("none", opa_value_compare(NULL, NULL) == 0);
|
|
test("none/some", opa_value_compare(NULL, opa_null()) < 0);
|
|
test("some/none", opa_value_compare(opa_null(), NULL) > 0);
|
|
test("null", opa_value_compare(opa_null(), opa_null()) == 0);
|
|
test("null/boolean", opa_value_compare(opa_boolean(true), opa_null()) > 0);
|
|
test("true/true", opa_value_compare(opa_boolean(true), opa_boolean(true)) == 0);
|
|
test("true/false", opa_value_compare(opa_boolean(true), opa_boolean(false)) > 0);
|
|
test("false/true", opa_value_compare(opa_boolean(false), opa_boolean(true)) < 0);
|
|
test("false/false", opa_value_compare(opa_boolean(false), opa_boolean(false)) == 0);
|
|
test("number/boolean", opa_value_compare(opa_number_int(100), opa_boolean(true)) > 0);
|
|
test("integers", opa_value_compare(opa_number_int(100), opa_number_int(99)) > 0);
|
|
test("integers", opa_value_compare(opa_number_int(100), opa_number_int(101)) < 0);
|
|
test("integers", opa_value_compare(opa_number_int(100), opa_number_int(100)) == 0);
|
|
test("integers", opa_value_compare(opa_number_int(-100), opa_number_int(100)) < 0);
|
|
test("integers", opa_value_compare(opa_number_int(-100), opa_number_int(-101)) > 0);
|
|
test("integer/float", opa_value_compare(opa_number_int(100), opa_number_float(100.1)) < 0);
|
|
test("floats", opa_value_compare(opa_number_float(100.2), opa_number_float(100.1)) > 0);
|
|
test("floats", opa_value_compare(opa_number_float(100.2), opa_number_float(100.3)) < 0);
|
|
test("floats", opa_value_compare(opa_number_float(100.3), opa_number_float(100.3)) == 0);
|
|
test("string/number", opa_value_compare(opa_string_terminated("foo"), opa_number_float(100)) > 0);
|
|
test("strings", opa_value_compare(opa_string_terminated("foo"), opa_string_terminated("foo")) == 0);
|
|
test("strings", opa_value_compare(opa_string_terminated("foo"), opa_string_terminated("bar")) > 0);
|
|
test("strings", opa_value_compare(opa_string_terminated("bar"), opa_string_terminated("baz")) < 0);
|
|
test("strings", opa_value_compare(opa_string_terminated("foobar"), opa_string_terminated("foo")) > 0);
|
|
test("strings", opa_value_compare(opa_string_terminated("foo"), opa_string_terminated("foobar")) < 0);
|
|
|
|
opa_array_t *arr1 = opa_cast_array(opa_array());
|
|
opa_array_append(arr1, opa_number_int(1));
|
|
opa_array_append(arr1, opa_number_int(2));
|
|
opa_array_append(arr1, opa_number_int(3));
|
|
|
|
opa_array_t *arr2 = opa_cast_array(opa_array());
|
|
opa_array_append(arr2, opa_number_int(1));
|
|
opa_array_append(arr2, opa_number_int(3));
|
|
opa_array_append(arr2, opa_number_int(2));
|
|
|
|
opa_array_t *arr3 = opa_cast_array(opa_array());
|
|
opa_array_append(arr2, opa_number_int(1));
|
|
opa_array_append(arr2, opa_number_int(3));
|
|
|
|
opa_value *v1, *v2, *v3;
|
|
v1 = &arr1->hdr;
|
|
v2 = &arr2->hdr;
|
|
v3 = &arr3->hdr;
|
|
|
|
test("array/string", opa_value_compare(v1, opa_string_terminated("a")) > 0);
|
|
test("arrays", opa_value_compare(v1, v1) == 0);
|
|
test("arrays", opa_value_compare(v1, v2) < 0);
|
|
test("arrays", opa_value_compare(v2, v1) > 0);
|
|
test("arrays", opa_value_compare(v3, v2) < 0);
|
|
test("arrays", opa_value_compare(v2, v3) > 0);
|
|
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj1, opa_string_terminated("b"), opa_number_int(2));
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj2, opa_string_terminated("b"), opa_number_int(3));
|
|
|
|
opa_object_t *obj3 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj3, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj3, opa_string_terminated("c"), opa_number_int(3));
|
|
|
|
opa_object_t *obj4 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj4, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj4, opa_string_terminated("b"), opa_number_int(2));
|
|
opa_object_insert(obj4, opa_string_terminated("c"), opa_number_int(3));
|
|
|
|
v1 = &obj1->hdr;
|
|
v2 = &obj2->hdr;
|
|
v3 = &obj3->hdr;
|
|
opa_value *v4 = &obj4->hdr;
|
|
|
|
test("object/array", opa_value_compare(v1, opa_array()) > 0);
|
|
test("objects", opa_value_compare(v1, v1) == 0);
|
|
test("objects", opa_value_compare(v1, v2) < 0);
|
|
test("objects", opa_value_compare(v2, v3) < 0);
|
|
test("objects", opa_value_compare(v4, v1) > 0);
|
|
test("objects", opa_value_compare(v4, v2) < 0);
|
|
|
|
opa_set_t *set1 = opa_cast_set(opa_set());
|
|
opa_set_add(set1, opa_string_terminated("a"));
|
|
opa_set_add(set1, opa_string_terminated("b"));
|
|
|
|
opa_set_t *set2 = opa_cast_set(opa_set());
|
|
opa_set_add(set2, opa_string_terminated("a"));
|
|
opa_set_add(set2, opa_string_terminated("c"));
|
|
|
|
opa_set_t *set3 = opa_cast_set(opa_set());
|
|
opa_set_add(set3, opa_string_terminated("a"));
|
|
opa_set_add(set3, opa_string_terminated("b"));
|
|
opa_set_add(set3, opa_string_terminated("c"));
|
|
|
|
v1 = &set1->hdr;
|
|
v2 = &set2->hdr;
|
|
v3 = &set3->hdr;
|
|
|
|
test("set/object", opa_value_compare(v1, opa_object()) > 0);
|
|
test("sets", opa_value_compare(v1, v1) == 0);
|
|
test("sets", opa_value_compare(v1, v2) < 0);
|
|
test("sets", opa_value_compare(v2, v3) > 0); // because c > b
|
|
test("sets", opa_value_compare(v3, v1) > 0);
|
|
}
|
|
|
|
int parse_crunch(const char *s, opa_value *exp)
|
|
{
|
|
opa_value *ret = opa_json_parse(s, opa_strlen(s));
|
|
if (ret == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
return opa_value_compare(exp, ret) == 0;
|
|
}
|
|
|
|
int value_parse_crunch(const char *s, opa_value *exp)
|
|
{
|
|
opa_value *ret = opa_value_parse(s, opa_strlen(s));
|
|
if (ret == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
return opa_value_compare(exp, ret) == 0;
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_json_parse_scalar)
|
|
void test_opa_json_parse_scalar(void)
|
|
{
|
|
test("null", parse_crunch("null", opa_null()));
|
|
test("true", parse_crunch("true", opa_boolean(true)));
|
|
test("false", parse_crunch("false", opa_boolean(false)));
|
|
test("strings", parse_crunch("\"hello\"", opa_string_terminated("hello")));
|
|
test("strings: escaped quote", parse_crunch("\"a\\\"b\"", opa_string_terminated("a\"b")));
|
|
test("strings: escaped reverse solidus", parse_crunch("\"a\\\\b\"", opa_string_terminated("a\\b")));
|
|
test("strings: escaped solidus", parse_crunch("\"a\\/b\"", opa_string_terminated("a/b")));
|
|
test("strings: escaped backspace", parse_crunch("\"a\\bb\"", opa_string_terminated("a\bb")));
|
|
test("strings: escaped feed forward", parse_crunch("\"a\\fb\"", opa_string_terminated("a\fb")));
|
|
test("strings: escaped line feed", parse_crunch("\"a\\nb\"", opa_string_terminated("a\nb")));
|
|
test("strings: escaped carriage return", parse_crunch("\"a\\rb\"", opa_string_terminated("a\rb")));
|
|
test("strings: escaped tab", parse_crunch("\"a\\tb\"", opa_string_terminated("a\tb")));
|
|
test("strings: utf-8 2 bytes", parse_crunch("\"\xc2\xa2\"", opa_string_terminated("\xc2\xa2")));
|
|
test("strings: utf-8 3 bytes", parse_crunch("\"\xe0\xb8\x81\"", opa_string_terminated("\xe0\xb8\x81")));
|
|
test("strings: utf-8 3 bytes", parse_crunch("\"\xe2\x82\xac\"", opa_string_terminated("\xe2\x82\xac")));
|
|
test("strings: utf-8 3 bytes", parse_crunch("\"\xed\x9e\xb0\"", opa_string_terminated("\xed\x9e\xb0")));
|
|
test("strings: utf-8 3 bytes", parse_crunch("\"\xef\xa4\x80\"", opa_string_terminated("\xef\xa4\x80")));
|
|
test("strings: utf-8 4 bytes", parse_crunch("\"\xf0\x90\x8d\x88\"", opa_string_terminated("\xf0\x90\x8d\x88")));
|
|
test("strings: utf-8 4 bytes", parse_crunch("\"\xf3\xa0\x80\x81\"", opa_string_terminated("\xf3\xa0\x80\x81")));
|
|
test("strings: utf-8 4 bytes", parse_crunch("\"\xf4\x80\x80\x80\"", opa_string_terminated("\xf4\x80\x80\x80")));
|
|
test("strings: utf-16 no surrogate pair", parse_crunch("\" \\u20AC \"", opa_string_terminated(" \xe2\x82\xac ")));
|
|
test("strings: utf-16 surrogate pair", parse_crunch("\" \\ud801\\udc37 \"", opa_string_terminated(" \xf0\x90\x90\xb7 ")));
|
|
test("integers", parse_crunch("0", opa_number_int(0)));
|
|
test("integers", parse_crunch("123456789", opa_number_int(123456789)));
|
|
test("signed integers", parse_crunch("-0", opa_number_int(0)));
|
|
test("signed integers", parse_crunch("-123456789", opa_number_int(-123456789)));
|
|
test("floats", parse_crunch("16.7", opa_number_float(16.7)));
|
|
test("signed floats", parse_crunch("-16.7", opa_number_float(-16.7)));
|
|
test("exponents", parse_crunch("6e7", opa_number_float(6e7)));
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_json_max_str_len)
|
|
void test_opa_json_max_str_len(void)
|
|
{
|
|
test("max str len: a char", opa_json_max_string_len("a", 1) == 1);
|
|
test("max str len: chars", opa_json_max_string_len("ab", 2) == 2);
|
|
test("max str len: single char escape", opa_json_max_string_len("ab\nd", 4) == 4);
|
|
test("max str len: 2 byte utf-8", opa_json_max_string_len("\xc2\xa2", 2) == 2);
|
|
test("max str len: 3 byte utf-8", opa_json_max_string_len("\xe0\xb8\x81", 3) == 3);
|
|
test("max str len: 4 byte utf-8", opa_json_max_string_len("\xf0\x90\x8d\x88", 4) == 4);
|
|
test("max str len: utf-16 no surrogate pair", opa_json_max_string_len(" \\u20AC ", 8) == 6);
|
|
test("max str len: utf-16 surrogate pair", opa_json_max_string_len(" \\ud801\\udc37 ", 14) == 6);
|
|
}
|
|
|
|
opa_array_t *fixture_array1(void)
|
|
{
|
|
opa_array_t *arr = opa_cast_array(opa_array());
|
|
opa_array_append(arr, opa_number_int(1));
|
|
opa_array_append(arr, opa_number_int(2));
|
|
opa_array_append(arr, opa_number_int(3));
|
|
opa_array_append(arr, opa_number_int(4));
|
|
return arr;
|
|
}
|
|
|
|
opa_array_t *fixture_array2(void)
|
|
{
|
|
opa_array_t *arr1 = opa_cast_array(opa_array());
|
|
opa_array_append(arr1, opa_number_int(1));
|
|
opa_array_append(arr1, opa_number_int(2));
|
|
opa_array_append(arr1, opa_number_int(3));
|
|
opa_array_append(arr1, opa_number_int(4));
|
|
|
|
opa_array_t *arr2 = opa_cast_array(opa_array());
|
|
opa_array_append(arr2, opa_number_int(5));
|
|
opa_array_append(arr2, opa_number_int(6));
|
|
opa_array_append(arr2, opa_number_int(7));
|
|
opa_array_append(arr2, opa_number_int(8));
|
|
|
|
opa_array_t *arr = opa_cast_array(opa_array());
|
|
opa_array_append(arr, &arr1->hdr);
|
|
opa_array_append(arr, &arr2->hdr);
|
|
|
|
return arr;
|
|
}
|
|
|
|
opa_object_t *fixture_object1(void)
|
|
{
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj, opa_string_terminated("b"), opa_number_int(2));
|
|
return obj;
|
|
}
|
|
|
|
opa_object_t *fixture_object2(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("c"), opa_number_int(1));
|
|
opa_object_insert(obj1, opa_string_terminated("d"), opa_number_int(2));
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("e"), opa_number_int(3));
|
|
opa_object_insert(obj2, opa_string_terminated("f"), opa_number_int(4));
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), &obj1->hdr);
|
|
opa_object_insert(obj, opa_string_terminated("b"), &obj2->hdr);
|
|
return obj;
|
|
}
|
|
|
|
opa_set_t *fixture_set1(void)
|
|
{
|
|
opa_set_t *set = opa_cast_set(opa_set());
|
|
opa_set_add(set, opa_string_terminated("a"));
|
|
opa_set_add(set, opa_string_terminated("b"));
|
|
return set;
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_length)
|
|
void test_opa_value_length(void)
|
|
{
|
|
opa_array_t *arr = fixture_array1();
|
|
opa_object_t *obj = fixture_object1();
|
|
opa_set_t *set = fixture_set1();
|
|
|
|
test("arrays", opa_value_length(&arr->hdr) == 4);
|
|
test("objects", opa_value_length(&obj->hdr) == 2);
|
|
test("sets", opa_value_length(&set->hdr) == 2);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_get_array)
|
|
void test_opa_value_get_array(void)
|
|
{
|
|
opa_array_t *arr = fixture_array1();
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
opa_value *result = opa_value_get(&arr->hdr, opa_number_int(i));
|
|
|
|
if (result == NULL)
|
|
{
|
|
test_fatal("array get failed");
|
|
}
|
|
|
|
if (opa_value_compare(result, opa_number_int(i + 1)) != 0)
|
|
{
|
|
test_fatal("array get returned bad value");
|
|
}
|
|
}
|
|
|
|
opa_value *result = opa_value_get(&arr->hdr, opa_string_terminated("foo"));
|
|
|
|
if (result != NULL)
|
|
{
|
|
test_fatal("array get returned unexpected result");
|
|
}
|
|
|
|
result = opa_value_get(&arr->hdr, opa_number_float(3.14));
|
|
|
|
if (result != NULL)
|
|
{
|
|
test_fatal("array get returned unexpected result");
|
|
}
|
|
|
|
result = opa_value_get(&arr->hdr, opa_number_int(-1));
|
|
|
|
if (result != NULL)
|
|
{
|
|
test_fatal("array get returned unexpected result");
|
|
}
|
|
|
|
result = opa_value_get(&arr->hdr, opa_number_int(4));
|
|
|
|
if (result != NULL)
|
|
{
|
|
test_fatal("array get returned unexpected result");
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_array_sort)
|
|
void test_opa_array_sort(void)
|
|
{
|
|
opa_array_t *arr = opa_cast_array(opa_array());
|
|
|
|
opa_array_append(arr, opa_number_int(4));
|
|
opa_array_append(arr, opa_number_int(3));
|
|
opa_array_append(arr, opa_number_int(2));
|
|
opa_array_append(arr, opa_number_int(1));
|
|
|
|
opa_array_sort(arr, opa_value_compare);
|
|
|
|
// iterate through the array to verify both the indices and values.
|
|
|
|
opa_value *res = opa_array();
|
|
opa_value *exp = &fixture_array1()->hdr;
|
|
|
|
for (opa_value *prev = NULL, *curr = NULL; (curr = opa_value_iter(&arr->hdr, prev)) != NULL; prev = curr)
|
|
{
|
|
opa_array_append(opa_cast_array(res), opa_value_get(&arr->hdr, curr));
|
|
}
|
|
|
|
if (opa_value_compare(res, exp) != 0)
|
|
{
|
|
test_fatal("array sort returned unexpected result");
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_get_object)
|
|
void test_opa_value_get_object(void)
|
|
{
|
|
opa_object_t *obj = fixture_object1();
|
|
|
|
const char *keys[2] = {
|
|
"a",
|
|
"b",
|
|
};
|
|
|
|
long long values[2] = {
|
|
1,
|
|
2,
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(keys) / sizeof(const char *); i++)
|
|
{
|
|
opa_value *result = opa_value_get(&obj->hdr, opa_string_terminated(keys[i]));
|
|
|
|
if (result == NULL)
|
|
{
|
|
test_fatal("object get failed");
|
|
}
|
|
|
|
if (opa_value_compare(result, opa_number_int(values[i])) != 0)
|
|
{
|
|
test_fatal("object get returned bad value");
|
|
}
|
|
}
|
|
|
|
opa_value *result = opa_value_get(&obj->hdr, opa_string_terminated("non-existent"));
|
|
|
|
if (result != NULL)
|
|
{
|
|
test_fatal("object get returned unexpected result");
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_json_parse_composites)
|
|
void test_opa_json_parse_composites(void)
|
|
{
|
|
|
|
opa_value *empty_arr = opa_array();
|
|
|
|
test("empty array", parse_crunch("[]", empty_arr));
|
|
test("array", parse_crunch("[1,2,3,4]", &fixture_array1()->hdr));
|
|
test("array nested", parse_crunch("[[1,2,3,4],[5,6,7,8]]", &fixture_array2()->hdr));
|
|
|
|
opa_value *empty_obj = opa_object();
|
|
|
|
test("empty object", parse_crunch("{}", empty_obj));
|
|
test("object", parse_crunch("{\"a\": 1, \"b\": 2}", &fixture_object1()->hdr));
|
|
test("object nested", parse_crunch("{\"a\": {\"c\": 1, \"d\": 2}, \"b\": {\"e\": 3, \"f\": 4}}", &fixture_object2()->hdr));
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_parse)
|
|
void test_opa_value_parse(void)
|
|
{
|
|
opa_set_t *set = opa_cast_set(opa_set());
|
|
opa_set_add(set, opa_number_int(1));
|
|
|
|
test("set of one", value_parse_crunch("{1}", &set->hdr));
|
|
test("set of one - dupes", value_parse_crunch("{1,1}", &set->hdr));
|
|
|
|
opa_set_add(set, opa_number_int(2));
|
|
opa_set_add(set, opa_number_int(3));
|
|
|
|
test("set multiple", value_parse_crunch("{1,2,3}", &set->hdr));
|
|
|
|
opa_value *empty_set = opa_set();
|
|
|
|
test("empty", value_parse_crunch("set()", empty_set));
|
|
test("empty whitespace", value_parse_crunch("set( )", empty_set));
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_free)
|
|
void test_opa_value_free(void)
|
|
{
|
|
char *s;
|
|
opa_value *ret;
|
|
int i;
|
|
|
|
reset_heap();
|
|
unsigned int base;
|
|
|
|
// This is tricky because some of these dynamic allocations
|
|
// leave memory in the heap because the blocks they allocate
|
|
// come from different lists. If they don't get freed in
|
|
// reverse order of allocation, the heap pointer won't go
|
|
// down. Some of these objects don't free the sub-objects
|
|
// in reverse order of allocation.
|
|
//
|
|
// However, what we can do is
|
|
// * do a small number of parse/free combinations to prime the heap
|
|
// * grab the new heap pointer
|
|
// * do a few more parse/free cycles checking each time that the
|
|
// pointer doesn't increase.
|
|
//
|
|
// This isn't perfect because for larger, variable-sized blocks
|
|
// order of allocation matters and can lead to the heap bumping
|
|
// up a bit although this would stabalize in the long run. But
|
|
// to a void this, keep the value elements (strings, numbers, ...)
|
|
// small to keep the allocations in the fixed-sized block regions.
|
|
|
|
// Null test
|
|
s = "null";
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
base = opa_heap_ptr_get();
|
|
for (i = 0; i < 5; i++) {
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
test("heap ptr", base == opa_heap_ptr_get());
|
|
}
|
|
|
|
// Boolean test
|
|
s = "true";
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
base = opa_heap_ptr_get();
|
|
for (i = 0; i < 5; i++) {
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
test("heap ptr", base == opa_heap_ptr_get());
|
|
}
|
|
|
|
// Integer test
|
|
s = "0";
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
base = opa_heap_ptr_get();
|
|
for (i = 0; i < 5; i++) {
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
test("heap ptr", base == opa_heap_ptr_get());
|
|
}
|
|
|
|
// String test
|
|
s = "\"hello\"";
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
base = opa_heap_ptr_get();
|
|
for (i = 0; i < 5; i++) {
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
test("heap ptr", base == opa_heap_ptr_get());
|
|
}
|
|
|
|
// Array test
|
|
s = "[\"a\", \"b\", \"c\"]";
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
base = opa_heap_ptr_get();
|
|
for (i = 0; i < 5; i++) {
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
test("heap ptr", base == opa_heap_ptr_get());
|
|
}
|
|
|
|
// Object test
|
|
s = "{\"a\": 1, \"b\": 2}";
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
base = opa_heap_ptr_get();
|
|
for (i = 0; i < 5; i++) {
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
test("heap ptr", base == opa_heap_ptr_get());
|
|
}
|
|
|
|
// Set test
|
|
//
|
|
// The bucket sizes seem to be just enough to mix elements,
|
|
// buckets and set objects. This makes one parse/free
|
|
// cycle insufficient to stabalize the heap. So do two
|
|
// instead before validating that the heap will no longer
|
|
// increase.
|
|
s = "{\"a\", \"b\", \"c\"}";
|
|
for (i = 0; i < 2; i++) {
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
}
|
|
base = opa_heap_ptr_get();
|
|
for (i = 0; i < 5; i++) {
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
test("heap ptr", base == opa_heap_ptr_get());
|
|
}
|
|
|
|
// Compound object / array test
|
|
s = "{[1,2],[3,4]}";
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
base = opa_heap_ptr_get();
|
|
for (i = 0; i < 5; i++) {
|
|
ret = opa_value_parse(s, opa_strlen(s));
|
|
test("parse", ret != NULL);
|
|
opa_value_free(ret);
|
|
test("heap ptr", base == opa_heap_ptr_get());
|
|
}
|
|
}
|
|
|
|
|
|
WASM_EXPORT(test_opa_json_parse_memory_ownership)
|
|
void test_opa_json_parse_memory_ownership(void)
|
|
{
|
|
char s[] = "[1,\"a\"]";
|
|
|
|
opa_value *result = opa_json_parse(s, sizeof(s));
|
|
|
|
opa_value *exp = opa_array();
|
|
opa_array_t *arr = opa_cast_array(exp);
|
|
opa_array_append(arr, opa_number_int(1));
|
|
opa_array_append(arr, opa_string("a", 1));
|
|
|
|
test("expected value", opa_value_compare(result, exp) == 0);
|
|
|
|
for (int i = 0; i < sizeof(s); i++)
|
|
{
|
|
s[i] = 0;
|
|
}
|
|
|
|
test("expected value after overwriting buffer", opa_value_compare(result, exp) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_object_insert)
|
|
void test_opa_object_insert(void)
|
|
{
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
|
|
opa_object_insert(obj, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj, opa_string_terminated("b"), opa_number_int(2));
|
|
opa_object_insert(obj, opa_string_terminated("a"), opa_number_int(3));
|
|
|
|
opa_value *v1 = opa_value_get(&obj->hdr, opa_string_terminated("a"));
|
|
|
|
if (opa_value_compare(v1, opa_number_int(3)) != 0)
|
|
{
|
|
test_fatal("object insert did not replace value")
|
|
}
|
|
|
|
opa_object_insert(obj, opa_string_terminated("b"), opa_number_int(4));
|
|
|
|
opa_value *v2 = opa_value_get(&obj->hdr, opa_string_terminated("b"));
|
|
|
|
if (opa_value_compare(v2, opa_number_int(4)) != 0)
|
|
{
|
|
test_fatal("object insert did not replace value")
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_object_growth)
|
|
void test_opa_object_growth(void)
|
|
{
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), opa_string_terminated("1"));
|
|
opa_object_insert(obj, opa_string_terminated("b"), opa_string_terminated("2"));
|
|
opa_object_insert(obj, opa_string_terminated("c"), opa_string_terminated("3"));
|
|
opa_object_insert(obj, opa_string_terminated("d"), opa_string_terminated("4"));
|
|
opa_object_insert(obj, opa_string_terminated("e"), opa_string_terminated("5"));
|
|
opa_object_insert(obj, opa_string_terminated("e"), opa_string_terminated("5'"));
|
|
|
|
if (obj->len != 5)
|
|
{
|
|
test_fatal("object is missing key-value pairs")
|
|
}
|
|
|
|
if (obj->n != 8)
|
|
{
|
|
test_fatal("object capacity did double")
|
|
}
|
|
|
|
opa_object_insert(obj, opa_string_terminated("f"), opa_string_terminated("6"));
|
|
|
|
if (obj->len != 6)
|
|
{
|
|
test_fatal("object is missing key-value pairs")
|
|
}
|
|
|
|
if (obj->n != 16)
|
|
{
|
|
test_fatal("object capacity did not double")
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_set_add_and_get)
|
|
void test_opa_set_add_and_get(void)
|
|
{
|
|
opa_set_t *set = fixture_set1();
|
|
opa_set_add(set, opa_string_terminated("a"));
|
|
|
|
opa_set_t *cpy = fixture_set1();
|
|
|
|
if (opa_value_compare(&set->hdr, &cpy->hdr) != 0)
|
|
{
|
|
test_fatal("set was modified by add with duplicate element");
|
|
}
|
|
|
|
opa_set_add(set, opa_string_terminated("c"));
|
|
|
|
if (opa_value_compare(&set->hdr, &cpy->hdr) <= 0)
|
|
{
|
|
test_fatal("set should be greater than cpy")
|
|
}
|
|
|
|
if (opa_value_get(&set->hdr, opa_string_terminated("c")) == NULL)
|
|
{
|
|
test_fatal("set should contain string term c")
|
|
}
|
|
|
|
opa_set_t *order = opa_cast_set(opa_set());
|
|
opa_set_add(order, opa_string_terminated("b"));
|
|
opa_set_add(order, opa_string_terminated("c"));
|
|
opa_set_add(order, opa_string_terminated("a"));
|
|
|
|
if (opa_value_compare(&set->hdr, &order->hdr) != 0)
|
|
{
|
|
test_fatal("sets should be equal")
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_set_growth)
|
|
void test_opa_set_growth(void)
|
|
{
|
|
opa_set_t *set = opa_cast_set(opa_set());
|
|
opa_set_add(set, opa_string_terminated("a"));
|
|
opa_set_add(set, opa_string_terminated("b"));
|
|
opa_set_add(set, opa_string_terminated("c"));
|
|
opa_set_add(set, opa_string_terminated("d"));
|
|
opa_set_add(set, opa_string_terminated("e"));
|
|
opa_set_add(set, opa_string_terminated("e"));
|
|
|
|
if (set->len != 5)
|
|
{
|
|
test_fatal("set is missing elements")
|
|
}
|
|
|
|
if (set->n != 8)
|
|
{
|
|
test_fatal("set capacity did double")
|
|
}
|
|
|
|
opa_set_add(set, opa_string_terminated("f"));
|
|
|
|
if (set->len != 6)
|
|
{
|
|
test_fatal("set is missing elements")
|
|
}
|
|
|
|
if (set->n != 16)
|
|
{
|
|
test_fatal("set capacity did not double")
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_iter_object)
|
|
void test_opa_value_iter_object(void)
|
|
{
|
|
opa_object_t *obj = fixture_object1();
|
|
|
|
opa_value *k1 = opa_value_iter(&obj->hdr, NULL);
|
|
opa_value *k2 = opa_value_iter(&obj->hdr, k1);
|
|
opa_value *k3 = opa_value_iter(&obj->hdr, k2);
|
|
|
|
opa_value *exp1 = opa_string_terminated("b");
|
|
opa_value *exp2 = opa_string_terminated("a");
|
|
opa_value *exp3 = NULL;
|
|
|
|
if (opa_value_compare(k1, exp1) != 0)
|
|
{
|
|
test_fatal("object iter start did not return expected value");
|
|
}
|
|
|
|
if (opa_value_compare(k2, exp2) != 0)
|
|
{
|
|
test_fatal("object iter second did not return expected value");
|
|
}
|
|
|
|
if (opa_value_compare(k3, exp3) != 0)
|
|
{
|
|
test_fatal("object iter third did not return expected value");
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_iter_array)
|
|
void test_opa_value_iter_array(void)
|
|
{
|
|
opa_array_t *arr = opa_cast_array(opa_array());
|
|
|
|
opa_array_append(arr, opa_number_int(1));
|
|
opa_array_append(arr, opa_number_int(2));
|
|
|
|
opa_value *k1 = opa_value_iter(&arr->hdr, NULL);
|
|
opa_value *k2 = opa_value_iter(&arr->hdr, k1);
|
|
opa_value *k3 = opa_value_iter(&arr->hdr, k2);
|
|
|
|
opa_value *exp1 = opa_number_int(0);
|
|
opa_value *exp2 = opa_number_int(1);
|
|
opa_value *exp3 = NULL;
|
|
|
|
if (opa_value_compare(k1, exp1) != 0)
|
|
{
|
|
test_fatal("array iter start did not return expected value");
|
|
}
|
|
|
|
if (opa_value_compare(k2, exp2) != 0)
|
|
{
|
|
test_fatal("array iter second did not return expected value");
|
|
}
|
|
|
|
if (opa_value_compare(k3, exp3) != 0)
|
|
{
|
|
test_fatal("array iter third did not return expected value");
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_iter_set)
|
|
void test_opa_value_iter_set(void)
|
|
{
|
|
opa_set_t *set = opa_cast_set(opa_set());
|
|
|
|
opa_set_add(set, opa_number_int(1));
|
|
opa_set_add(set, opa_number_int(2));
|
|
|
|
opa_value *v1 = opa_value_iter(&set->hdr, NULL);
|
|
opa_value *v2 = opa_value_iter(&set->hdr, v1);
|
|
opa_value *v3 = opa_value_iter(&set->hdr, v2);
|
|
|
|
opa_value *exp1 = opa_number_int(1);
|
|
opa_value *exp2 = opa_number_int(2);
|
|
opa_value *exp3 = NULL;
|
|
|
|
if (opa_value_compare(v1, exp1) != 0)
|
|
{
|
|
test_fatal("set iter did not return expected value");
|
|
}
|
|
|
|
if (opa_value_compare(v2, exp2) != 0)
|
|
{
|
|
test_fatal("set iter second did not return expected value");
|
|
}
|
|
|
|
if (opa_value_compare(v3, exp3) != 0)
|
|
{
|
|
test_fatal("set iter third did not return expected value");
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_merge_scalars)
|
|
void test_opa_value_merge_scalars(void)
|
|
{
|
|
opa_value *result = opa_value_merge(opa_number_int(1), opa_string_terminated("foo"));
|
|
|
|
if (result == NULL)
|
|
{
|
|
test_fatal("merge of two scalars failed");
|
|
}
|
|
else if (opa_value_compare(result, opa_number_int(1)) != 0)
|
|
{
|
|
test_fatal("scalar merge returned unexpected result");
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_merge_first_operand_null)
|
|
void test_opa_value_merge_first_operand_null(void)
|
|
{
|
|
test_str_eq("second operand string returns string", "\"foo\"", opa_json_dump(opa_value_merge(NULL, opa_string_terminated("foo"))));
|
|
test_str_eq("second operand object returns object", "{}", opa_json_dump(opa_value_merge(NULL, opa_object())));
|
|
test_str_eq("second operand number returns number", "1", opa_json_dump(opa_value_merge(NULL, opa_number_int(1))));
|
|
test_str_eq("second operand array returns array", "[]", opa_json_dump(opa_value_merge(NULL, opa_array())));
|
|
test_str_eq("second operand set returns set", "set()", opa_value_dump(opa_value_merge(NULL, opa_set())));
|
|
test_str_eq("second operand null returns null", "null", opa_json_dump(opa_value_merge(NULL, opa_null())));
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_merge_simple)
|
|
void test_opa_value_merge_simple(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
|
|
opa_object_insert(obj1, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj2, opa_string_terminated("b"), opa_number_int(2));
|
|
|
|
opa_object_t *exp1 = opa_cast_object(opa_object());
|
|
opa_object_insert(exp1, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(exp1, opa_string_terminated("b"), opa_number_int(2));
|
|
|
|
opa_value *result = opa_value_merge(&obj1->hdr, &obj2->hdr);
|
|
|
|
if (result == NULL)
|
|
{
|
|
test_fatal("object merge failed");
|
|
}
|
|
else if (opa_value_compare(result, &exp1->hdr) != 0)
|
|
{
|
|
test_fatal("object merge returned unexpected result");
|
|
}
|
|
}
|
|
|
|
|
|
WASM_EXPORT(test_opa_value_merge_nested)
|
|
void test_opa_value_merge_nested(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_t *obj1a = opa_cast_object(opa_object());
|
|
|
|
opa_object_insert(obj1a, opa_string_terminated("b"), opa_number_int(1));
|
|
opa_object_insert(obj1, opa_string_terminated("a"), &obj1a->hdr);
|
|
opa_object_insert(obj1, opa_string_terminated("c"), opa_number_int(2));
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_t *obj2a = opa_cast_object(opa_object());
|
|
|
|
opa_object_insert(obj2a, opa_string_terminated("d"), opa_number_int(3));
|
|
opa_object_insert(obj2, opa_string_terminated("a"), &obj2a->hdr);
|
|
opa_object_insert(obj2, opa_string_terminated("e"), opa_number_int(4));
|
|
|
|
opa_object_t *exp1 = opa_cast_object(opa_object());
|
|
opa_object_t *exp1a = opa_cast_object(opa_object());
|
|
|
|
opa_object_insert(exp1a, opa_string_terminated("b"), opa_number_int(1));
|
|
opa_object_insert(exp1a, opa_string_terminated("d"), opa_number_int(3));
|
|
opa_object_insert(exp1, opa_string_terminated("a"), &exp1a->hdr);
|
|
opa_object_insert(exp1, opa_string_terminated("c"), opa_number_int(2));
|
|
opa_object_insert(exp1, opa_string_terminated("e"), opa_number_int(4));
|
|
|
|
opa_value *result = opa_value_merge(&obj1->hdr, &obj2->hdr);
|
|
|
|
if (result == NULL)
|
|
{
|
|
test_fatal("object merge failed");
|
|
}
|
|
else if (opa_value_compare(&exp1->hdr, result) != 0)
|
|
{
|
|
test_fatal("object merge returned unexpected result");
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_shallow_copy)
|
|
void test_opa_value_shallow_copy(void)
|
|
{
|
|
// construct a value that has one of each type
|
|
char str[] = "{\"a\": [1, true, null, 2.5]}";
|
|
opa_value *obj = opa_json_parse(str, sizeof(str));
|
|
opa_set_t *set = opa_cast_set(opa_set());
|
|
opa_set_add(set, obj);
|
|
|
|
opa_value *cpy = opa_value_shallow_copy(&set->hdr);
|
|
|
|
if (opa_value_compare(cpy, &set->hdr) != 0)
|
|
{
|
|
test_fatal("expected original and shallow copy to be equal");
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_json_dump)
|
|
void test_opa_json_dump(void)
|
|
{
|
|
test("null", opa_strcmp(opa_json_dump(opa_null()), "null") == 0);
|
|
test("false", opa_strcmp(opa_json_dump(opa_boolean(false)), "false") == 0);
|
|
test("true", opa_strcmp(opa_json_dump(opa_boolean(true)), "true") == 0);
|
|
test("strings", opa_strcmp(opa_json_dump(opa_string_terminated("hello\"world")), "\"hello\\\"world\"") == 0);
|
|
test("strings utf-8", opa_strcmp(opa_json_dump(opa_string_terminated("\xed\xba\xad")), "\"\xed\xba\xad\"") == 0);
|
|
test("numbers", opa_strcmp(opa_json_dump(opa_number_int(127)), "127") == 0);
|
|
|
|
test_str_eq("numbers/float", "12345.678", opa_json_dump(opa_number_float(12345.678)));
|
|
test_str_eq("numbers/float", "10.5", opa_json_dump(opa_number_float(10.5)));
|
|
|
|
opa_value *arr = opa_array();
|
|
test("arrays", opa_strcmp(opa_json_dump(arr), "[]") == 0);
|
|
|
|
opa_array_append(opa_cast_array(arr), opa_string_terminated("hello"));
|
|
test("arrays", opa_strcmp(opa_json_dump(arr), "[\"hello\"]") == 0);
|
|
|
|
opa_array_append(opa_cast_array(arr), opa_string_terminated("world"));
|
|
test("arrays", opa_strcmp(opa_json_dump(arr), "[\"hello\",\"world\"]") == 0);
|
|
|
|
opa_value *set = opa_set();
|
|
test("sets", opa_strcmp(opa_json_dump(set), "[]") == 0);
|
|
|
|
opa_set_add(opa_cast_set(set), opa_string_terminated("hello"));
|
|
test("sets", opa_strcmp(opa_json_dump(set), "[\"hello\"]") == 0);
|
|
|
|
opa_set_add(opa_cast_set(set), opa_string_terminated("world"));
|
|
test("sets", opa_strcmp(opa_json_dump(set), "[\"hello\",\"world\"]") == 0);
|
|
|
|
opa_value *obj = opa_object();
|
|
test("objects", opa_strcmp(opa_json_dump(obj), "{}") == 0);
|
|
|
|
opa_object_insert(opa_cast_object(obj), opa_string_terminated("k1"), opa_string_terminated("v1"));
|
|
test("objects", opa_strcmp(opa_json_dump(obj), "{\"k1\":\"v1\"}") == 0);
|
|
|
|
opa_object_insert(opa_cast_object(obj), opa_string_terminated("k2"), opa_string_terminated("v2"));
|
|
test("objects", opa_strcmp(opa_json_dump(obj), "{\"k1\":\"v1\",\"k2\":\"v2\"}") == 0);
|
|
|
|
opa_value *terminators = opa_array();
|
|
opa_array_append(opa_cast_array(terminators), opa_boolean(true));
|
|
opa_array_append(opa_cast_array(terminators), opa_boolean(false));
|
|
opa_array_append(opa_cast_array(terminators), opa_null());
|
|
|
|
test("bool/null terminators", opa_strcmp(opa_json_dump(terminators), "[true,false,null]") == 0);
|
|
|
|
opa_value *non_string_keys = opa_object();
|
|
opa_array_t *arrk = opa_cast_array(opa_array());
|
|
opa_array_append(arrk, opa_number_int(1));
|
|
opa_object_insert(opa_cast_object(non_string_keys), &arrk->hdr, opa_number_int(1));
|
|
test_str_eq("objects/non string keys", opa_json_dump(non_string_keys), "{\"[1]\":1}");
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_dump)
|
|
void test_opa_value_dump(void)
|
|
{
|
|
test("empty sets", opa_strcmp(opa_value_dump(opa_set()), "set()") == 0);
|
|
|
|
opa_set_t *set = opa_cast_set(opa_set());
|
|
opa_set_add(set, opa_number_int(1));
|
|
|
|
test("sets of one", opa_strcmp(opa_value_dump(&set->hdr), "{1}") == 0);
|
|
|
|
opa_set_add(set, opa_number_int(2));
|
|
test("sets", opa_strcmp(opa_value_dump(&set->hdr), "{1, 2}") == 0);
|
|
|
|
opa_value *non_string_keys = opa_object();
|
|
opa_array_t *arrk = opa_cast_array(opa_array());
|
|
opa_array_append(arrk, opa_number_int(1));
|
|
opa_object_insert(opa_cast_object(non_string_keys), &arrk->hdr, opa_number_int(1));
|
|
test_str_eq("objects/non string keys", "{[1]: 1}", opa_value_dump(non_string_keys));
|
|
}
|
|
|
|
WASM_EXPORT(test_arithmetic)
|
|
void test_arithmetic(void)
|
|
{
|
|
long long i = 0;
|
|
|
|
test("abs +1", opa_number_try_int(opa_cast_number(opa_arith_abs(opa_number_int(1))), &i) == 0 && i == 1);
|
|
test("abs -1", opa_number_try_int(opa_cast_number(opa_arith_abs(opa_number_int(-1))), &i) == 0 && i == 1);
|
|
test("abs 1.5 (float)", opa_number_as_float(opa_cast_number(opa_arith_abs(opa_number_float(1.5)))) == 1.5);
|
|
test("abs -1.5 (float)", opa_number_as_float(opa_cast_number(opa_arith_abs(opa_number_float(-1.5)))) == 1.5);
|
|
test("abs 1.5 (ref)", opa_number_as_float(opa_cast_number(opa_arith_abs(opa_number_ref("1.5", 3)))) == 1.5);
|
|
test("abs -1.5 (ref)", opa_number_as_float(opa_cast_number(opa_arith_abs(opa_number_ref("-1.5", 4)))) == 1.5);
|
|
test("round 1", opa_number_try_int(opa_cast_number(opa_arith_round(opa_number_int(1))), &i) == 0 && i == 1);
|
|
test("round -1", opa_number_try_int(opa_cast_number(opa_arith_round(opa_number_int(-1))), &i) == 0 && i == -1);
|
|
test("round 1.4 (float)", opa_number_as_float(opa_cast_number(opa_arith_round(opa_number_float(1.4)))) == 1);
|
|
test("round -1.4 (float)", opa_number_as_float(opa_cast_number(opa_arith_round(opa_number_float(-1.4)))) == -1);
|
|
test("round 1.5 (float)", opa_number_as_float(opa_cast_number(opa_arith_round(opa_number_float(1.5)))) == 2);
|
|
test("round -1.5 (float)", opa_number_as_float(opa_cast_number(opa_arith_round(opa_number_float(-1.5)))) == -2);
|
|
test("round 2.5 (float)", opa_number_as_float(opa_cast_number(opa_arith_round(opa_number_float(2.5)))) == 3);
|
|
test("round -2.5 (float)", opa_number_as_float(opa_cast_number(opa_arith_round(opa_number_float(-2.5)))) == -3);
|
|
test("ceil 1", opa_number_as_float(opa_cast_number(opa_arith_ceil(opa_number_int(1)))) == 1);
|
|
test("ceil 1.01 (float)", opa_number_as_float(opa_cast_number(opa_arith_ceil(opa_number_float(1.01)))) == 2);
|
|
test("ceil -1.99999 (float)", opa_number_as_float(opa_cast_number(opa_arith_ceil(opa_number_float(-1.99999)))) == -1);
|
|
test("floor 1", opa_number_as_float(opa_cast_number(opa_arith_floor(opa_number_int(1)))) == 1);
|
|
test("floor 1.01 (float)", opa_number_as_float(opa_cast_number(opa_arith_floor(opa_number_float(1.01)))) == 1);
|
|
test("floor -1.99999 (float)", opa_number_as_float(opa_cast_number(opa_arith_floor(opa_number_float(-1.99999)))) == -2);
|
|
test("plus 1+2", opa_number_as_float(opa_cast_number(opa_arith_plus(opa_number_float(1), opa_number_float(2)))) == 3);
|
|
test("minus 3-2", opa_number_as_float(opa_cast_number(opa_arith_minus(opa_number_float(3), opa_number_float(2)))) == 1);
|
|
|
|
opa_set_t *s1 = opa_cast_set(opa_set());
|
|
opa_set_add(s1, opa_number_int(0));
|
|
opa_set_add(s1, opa_number_int(1));
|
|
opa_set_add(s1, opa_number_int(2));
|
|
|
|
opa_set_t *s2 = opa_cast_set(opa_set());
|
|
opa_set_add(s2, opa_number_int(0));
|
|
opa_set_add(s2, opa_number_int(2));
|
|
|
|
opa_set_t *s3 = opa_cast_set(opa_arith_minus(&s1->hdr, &s2->hdr));
|
|
test("minus set", s3->len == 1 && opa_set_get(s3, opa_number_int(1)) != NULL);
|
|
test("multiply 3*2", opa_number_as_float(opa_cast_number(opa_arith_multiply(opa_number_float(3), opa_number_float(2)))) == 6);
|
|
test("divide 3/2", opa_number_as_float(opa_cast_number(opa_arith_divide(opa_number_float(3), opa_number_float(2)))) == 1.5);
|
|
test("divide 3/0", opa_arith_divide(opa_number_float(3), opa_number_float(0)) == NULL);
|
|
test("remainder 5 % 2", opa_number_as_float(opa_cast_number(opa_arith_rem(opa_number_float(5), opa_number_float(2)))) == 1);
|
|
test("remainder 1.1 % 1", opa_arith_rem(opa_number_float(1.1), opa_number_float(1)) == NULL);
|
|
test("remainder 1 % 1.1", opa_arith_rem(opa_number_float(1), opa_number_float(1.1)) == NULL);
|
|
test("remainder 1 % 0", opa_arith_rem(opa_number_float(1), opa_number_float(0)) == NULL);
|
|
}
|
|
|
|
WASM_EXPORT(test_set_diff)
|
|
void test_set_diff(void)
|
|
{
|
|
// test_arithmetic covers the diff.
|
|
}
|
|
|
|
WASM_EXPORT(test_set_intersection_union)
|
|
void test_set_intersection_union(void)
|
|
{
|
|
opa_set_t *s1 = opa_cast_set(opa_set());
|
|
opa_set_add(s1, opa_number_int(0));
|
|
opa_set_add(s1, opa_number_int(1));
|
|
opa_set_add(s1, opa_number_int(2));
|
|
|
|
opa_set_t *s2 = opa_cast_set(opa_set());
|
|
opa_set_add(s2, opa_number_int(0));
|
|
opa_set_add(s2, opa_number_int(1));
|
|
|
|
opa_set_t *r = opa_cast_set(opa_set_intersection(&s1->hdr, &s2->hdr));
|
|
test("set/intersection", r->len == 2 && opa_set_get(r, opa_number_int(0)) != NULL && opa_set_get(r, opa_number_int(1)) != NULL);
|
|
|
|
r = opa_cast_set(opa_set_union(&s1->hdr, &s2->hdr));
|
|
test("set/union", r->len == 3 &&
|
|
opa_set_get(r, opa_number_int(0)) != NULL &&
|
|
opa_set_get(r, opa_number_int(1)) != NULL &&
|
|
opa_set_get(r, opa_number_int(2)) != NULL);
|
|
}
|
|
|
|
|
|
WASM_EXPORT(test_sets_intersection_union)
|
|
void test_sets_intersection_union(void)
|
|
{
|
|
opa_set_t *s1 = opa_cast_set(opa_set());
|
|
opa_set_add(s1, opa_number_int(0));
|
|
opa_set_add(s1, opa_number_int(1));
|
|
opa_set_add(s1, opa_number_int(2));
|
|
|
|
opa_set_t *s2 = opa_cast_set(opa_set());
|
|
opa_set_add(s2, opa_number_int(0));
|
|
opa_set_add(s2, opa_number_int(1));
|
|
|
|
opa_set_t *s3 = opa_cast_set(opa_set());
|
|
opa_set_add(s3, opa_number_int(0));
|
|
|
|
opa_set_t *sets = opa_cast_set(opa_set());
|
|
opa_set_add(sets, &s1->hdr);
|
|
opa_set_add(sets, &s2->hdr);
|
|
opa_set_add(sets, &s3->hdr);
|
|
|
|
opa_set_t *r = opa_cast_set(opa_sets_intersection(&sets->hdr));
|
|
test("sets/intersection", r->len == 1 && opa_set_get(r, opa_number_int(0)) != NULL);
|
|
|
|
r = opa_cast_set(opa_sets_union(&sets->hdr));
|
|
test("sets/union", r->len == 3 &&
|
|
opa_set_get(r, opa_number_int(0)) != NULL &&
|
|
opa_set_get(r, opa_number_int(1)) != NULL &&
|
|
opa_set_get(r, opa_number_int(2)) != NULL);
|
|
}
|
|
|
|
WASM_EXPORT(test_array)
|
|
void test_array(void)
|
|
{
|
|
opa_array_t *arr1 = opa_cast_array(opa_array());
|
|
opa_array_append(arr1, opa_number_int(0));
|
|
opa_array_append(arr1, opa_number_int(1));
|
|
|
|
opa_array_t *arr2 = opa_cast_array(opa_array());
|
|
opa_array_append(arr2, opa_number_int(2));
|
|
opa_array_append(arr2, opa_number_int(3));
|
|
|
|
opa_array_t *r = opa_cast_array(opa_array_concat(&arr1->hdr, &arr2->hdr));
|
|
|
|
test("array_concat", r->len == 4 &&
|
|
opa_value_compare(r->elems[0].v, opa_number_int(0)) == 0 &&
|
|
opa_value_compare(r->elems[1].v, opa_number_int(1)) == 0 &&
|
|
opa_value_compare(r->elems[2].v, opa_number_int(2)) == 0 &&
|
|
opa_value_compare(r->elems[3].v, opa_number_int(3)) == 0);
|
|
|
|
r = opa_cast_array(opa_array_slice(&r->hdr, opa_number_int(1), opa_number_int(3)));
|
|
|
|
test("array_slice", r->len == 2 &&
|
|
opa_value_compare(r->elems[0].v, opa_number_int(1)) == 0 &&
|
|
opa_value_compare(r->elems[1].v, opa_number_int(2)) == 0);
|
|
|
|
opa_array_t *arr3 = opa_cast_array(opa_array());
|
|
opa_array_append(arr3, opa_number_int(0));
|
|
opa_array_append(arr3, opa_number_int(1));
|
|
opa_array_append(arr3, opa_number_int(2));
|
|
|
|
r = opa_cast_array(opa_array_reverse(&arr3->hdr));
|
|
test("array_reverse", r->len == 3 &&
|
|
opa_value_compare(r->elems[0].v, opa_number_int(2)) == 0 &&
|
|
opa_value_compare(r->elems[1].v, opa_number_int(1)) == 0 &&
|
|
opa_value_compare(r->elems[2].v, opa_number_int(0)) == 0);
|
|
|
|
// array.flatten [[0,1], [2,3], 4] -> [0,1,2,3,4]
|
|
opa_array_t *sub1 = opa_cast_array(opa_array());
|
|
opa_array_append(sub1, opa_number_int(0));
|
|
opa_array_append(sub1, opa_number_int(1));
|
|
|
|
opa_array_t *sub2 = opa_cast_array(opa_array());
|
|
opa_array_append(sub2, opa_number_int(2));
|
|
opa_array_append(sub2, opa_number_int(3));
|
|
|
|
opa_array_t *nested = opa_cast_array(opa_array());
|
|
opa_array_append(nested, &sub1->hdr);
|
|
opa_array_append(nested, &sub2->hdr);
|
|
opa_array_append(nested, opa_number_int(4));
|
|
|
|
r = opa_cast_array(opa_array_flatten(&nested->hdr));
|
|
test("array_flatten", r->len == 5 &&
|
|
opa_value_compare(r->elems[0].v, opa_number_int(0)) == 0 &&
|
|
opa_value_compare(r->elems[1].v, opa_number_int(1)) == 0 &&
|
|
opa_value_compare(r->elems[2].v, opa_number_int(2)) == 0 &&
|
|
opa_value_compare(r->elems[3].v, opa_number_int(3)) == 0 &&
|
|
opa_value_compare(r->elems[4].v, opa_number_int(4)) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_types)
|
|
void test_types(void)
|
|
{
|
|
test("is_number", opa_value_compare(opa_types_is_number(opa_number_int(0)), opa_boolean(true)) == 0);
|
|
test("is_number", opa_value_compare(opa_types_is_number(opa_null()), opa_boolean(false)) == 0);
|
|
test("is_string", opa_value_compare(opa_types_is_string(opa_string("a", 1)), opa_boolean(true)) == 0);
|
|
test("is_string", opa_value_compare(opa_types_is_string(opa_null()), opa_boolean(false)) == 0);
|
|
test("is_boolean", opa_value_compare(opa_types_is_boolean(opa_boolean(true)), opa_boolean(true)) == 0);
|
|
test("is_boolean", opa_value_compare(opa_types_is_boolean(opa_null()), opa_boolean(false)) == 0);
|
|
test("is_array", opa_value_compare(opa_types_is_array(opa_array()), opa_boolean(true)) == 0);
|
|
test("is_array", opa_value_compare(opa_types_is_array(opa_null()), opa_boolean(false)) == 0);
|
|
test("is_set", opa_value_compare(opa_types_is_set(opa_set()), opa_boolean(true)) == 0);
|
|
test("is_set", opa_value_compare(opa_types_is_set(opa_null()), opa_boolean(false)) == 0);
|
|
test("is_object", opa_value_compare(opa_types_is_object(opa_object()), opa_boolean(true)) == 0);
|
|
test("is_object", opa_value_compare(opa_types_is_object(opa_null()), opa_boolean(false)) == 0);
|
|
test("is_null", opa_value_compare(opa_types_is_null(opa_null()), opa_boolean(true)) == 0);
|
|
test("is_null", opa_value_compare(opa_types_is_null(opa_number_int(0)), opa_boolean(false)) == 0);
|
|
|
|
test("name/null", opa_value_compare(opa_types_name(opa_null()), opa_string("null", 4)) == 0);
|
|
test("name/boolean", opa_value_compare(opa_types_name(opa_boolean(true)), opa_string("boolean", 7)) == 0);
|
|
test("name/number", opa_value_compare(opa_types_name(opa_number_int(0)), opa_string("number", 6)) == 0);
|
|
test("name/string", opa_value_compare(opa_types_name(opa_string("a", 1)), opa_string("string", 6)) == 0);
|
|
test("name/array", opa_value_compare(opa_types_name(opa_array()), opa_string("array", 5)) == 0);
|
|
test("name/object", opa_value_compare(opa_types_name(opa_object()), opa_string("object", 6)) == 0);
|
|
test("name/set", opa_value_compare(opa_types_name(opa_set()), opa_string("set", 3)) == 0);
|
|
}
|
|
|
|
static opa_value *number(const char *s)
|
|
{
|
|
size_t n = strlen(s);
|
|
uint8_t sign = MPD_POS;
|
|
size_t pos = 2;
|
|
|
|
if (s[0] == '-')
|
|
{
|
|
sign = MPD_NEG;
|
|
pos = 3;
|
|
}
|
|
|
|
int digits = n - pos;
|
|
uint16_t rdata[digits];
|
|
|
|
for (int i = 0; i < digits; i++)
|
|
{
|
|
int c = s[pos+i] & 0xff;
|
|
if (isdigit(c))
|
|
{
|
|
c -= '0';
|
|
} else if (isalpha(c)) {
|
|
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
|
}
|
|
|
|
rdata[digits - i - 1] = c;
|
|
}
|
|
|
|
uint32_t status = 0;
|
|
mpd_t *r = mpd_qnew();
|
|
mpd_qimport_u16(r, &rdata[0], digits, sign, 16, mpd_max_ctx(), &status);
|
|
return opa_bf_to_number(r);
|
|
}
|
|
|
|
WASM_EXPORT(test_bits)
|
|
void test_bits(void)
|
|
{
|
|
// tests from https://golang.org/src/math/big/int_test.go L1193
|
|
|
|
struct and_or_xor_test
|
|
{
|
|
const char *x;
|
|
const char *y;
|
|
const char *and;
|
|
const char *or;
|
|
const char *xor;
|
|
};
|
|
|
|
struct and_or_xor_test tests1[] = {
|
|
{"0x00", "0x00", "0x00", "0x00", "0x00"},
|
|
{"0x00", "0x01", "0x00", "0x01", "0x01"},
|
|
{"0x01", "0x00", "0x00", "0x01", "0x01"},
|
|
{"-0x01", "0x00", "0x00", "-0x01", "-0x01"},
|
|
{"-0xaf", "-0x50", "-0xf0", "-0x0f", "0xe1"},
|
|
{"0x00", "-0x01", "0x00", "-0x01", "-0x01"},
|
|
{"0x01", "0x01", "0x01", "0x01", "0x00"},
|
|
{"-0x01", "-0x01", "-0x01", "-0x01", "0x00"},
|
|
{"0x07", "0x08", "0x00", "0x0f", "0x0f"},
|
|
{"0x05", "0x0f", "0x05", "0x0f", "0x0a"},
|
|
{"0xff", "-0x0a", "0xf6", "-0x01", "-0xf7"},
|
|
{"0x013ff6", "0x9a4e", "0x1a46", "0x01bffe", "0x01a5b8"},
|
|
{"-0x013ff6", "0x9a4e", "0x800a", "-0x0125b2", "-0x01a5bc"},
|
|
{"-0x013ff6", "-0x9a4e", "-0x01bffe", "-0x1a46", "0x01a5b8"},
|
|
{
|
|
"0x1000009dc6e3d9822cba04129bcbe3401",
|
|
"0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
|
|
"0x1000001186210100001000009048c2001",
|
|
"0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
|
|
"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
|
|
},
|
|
{
|
|
"0x1000009dc6e3d9822cba04129bcbe3401",
|
|
"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
|
|
"0x8c40c2d8822caa04120b8321401",
|
|
"-0xb9bd7d543685789d57ca918e82229142459020483cd2014001fd",
|
|
"-0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fe",
|
|
},
|
|
{
|
|
"-0x1000009dc6e3d9822cba04129bcbe3401",
|
|
"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
|
|
"-0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
|
|
"-0x1000001186210100001000009048c2001",
|
|
"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
|
|
},
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(tests1)/sizeof(tests1[0]); i++) {
|
|
test("and", opa_value_compare(number(tests1[i].and), opa_bits_and(number(tests1[i].x), number(tests1[i].y))) == 0);
|
|
test("or", opa_value_compare(number(tests1[i].or), opa_bits_or(number(tests1[i].x), number(tests1[i].y))) == 0);
|
|
test("xor", opa_value_compare(number(tests1[i].xor), opa_bits_xor(number(tests1[i].x), number(tests1[i].y))) == 0);
|
|
}
|
|
|
|
// tests from https://golang.org/src/math/big/int_test.go L1496
|
|
|
|
struct negate_test
|
|
{
|
|
const char *input;
|
|
const char *output;
|
|
};
|
|
|
|
struct negate_test tests2[] = {
|
|
{"0", "-1"},
|
|
{"1", "-2"},
|
|
{"7", "-8"},
|
|
{"0", "-1"},
|
|
{"-81910", "81909"},
|
|
{
|
|
"298472983472983471903246121093472394872319615612417471234712061",
|
|
"-298472983472983471903246121093472394872319615612417471234712062",
|
|
},
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(tests2)/sizeof(tests2[0]); i++) {
|
|
test("negate", opa_value_compare(opa_number_ref(tests2[i].output, strlen(tests2[i].output)),
|
|
opa_bits_negate(opa_number_ref(tests2[i].input, strlen(tests2[i].input)))) == 0);
|
|
test("negate", opa_value_compare(opa_number_ref(tests2[i].input, strlen(tests2[i].input)),
|
|
opa_bits_negate(opa_number_ref(tests2[i].output, strlen(tests2[i].output)))) == 0);
|
|
}
|
|
|
|
// tests from https://golang.org/src/math/big/int_test.go L883
|
|
|
|
struct shift_test
|
|
{
|
|
const char *input;
|
|
int shift;
|
|
const char *output;
|
|
};
|
|
|
|
struct shift_test tests3[] = {
|
|
{"0", 0, "0"},
|
|
{"-0", 0, "0"},
|
|
{"0", 1, "0"},
|
|
{"0", 2, "0"},
|
|
{"1", 0, "1"},
|
|
{"1", 1, "0"},
|
|
{"1", 2, "0"},
|
|
{"2", 0, "2"},
|
|
{"2", 1, "1"},
|
|
{"-1", 0, "-1"},
|
|
{"-1", 1, "-1"},
|
|
{"-1", 10, "-1"},
|
|
{"-100", 2, "-25"},
|
|
{"-100", 3, "-13"},
|
|
{"-100", 100, "-1"},
|
|
{"4294967296", 0, "4294967296"},
|
|
{"4294967296", 1, "2147483648"},
|
|
{"4294967296", 2, "1073741824"},
|
|
{"18446744073709551616", 0, "18446744073709551616"},
|
|
{"18446744073709551616", 1, "9223372036854775808"},
|
|
{"18446744073709551616", 2, "4611686018427387904"},
|
|
{"18446744073709551616", 64, "1"},
|
|
{"340282366920938463463374607431768211456", 64, "18446744073709551616"},
|
|
{"340282366920938463463374607431768211456", 128, "1"},
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(tests3)/sizeof(tests3[0]); i++) {
|
|
test("right shift", opa_value_compare(opa_number_ref(tests3[i].output, strlen(tests3[i].output)),
|
|
opa_bits_shiftright(opa_number_ref(tests3[i].input, strlen(tests3[i].input)),
|
|
opa_number_int(tests3[i].shift))) == 0);
|
|
};
|
|
|
|
// tests from https://golang.org/src/math/big/int_test.go L940
|
|
|
|
struct shift_test tests4[] = {
|
|
{"0", 0, "0"},
|
|
{"0", 1, "0"},
|
|
{"0", 2, "0"},
|
|
{"1", 0, "1"},
|
|
{"1", 1, "2"},
|
|
{"1", 2, "4"},
|
|
{"2", 0, "2"},
|
|
{"2", 1, "4"},
|
|
{"2", 2, "8"},
|
|
{"-87", 1, "-174"},
|
|
{"4294967296", 0, "4294967296"},
|
|
{"4294967296", 1, "8589934592"},
|
|
{"4294967296", 2, "17179869184"},
|
|
{"18446744073709551616", 0, "18446744073709551616"},
|
|
{"9223372036854775808", 1, "18446744073709551616"},
|
|
{"4611686018427387904", 2, "18446744073709551616"},
|
|
{"1", 64, "18446744073709551616"},
|
|
{"18446744073709551616", 64, "340282366920938463463374607431768211456"},
|
|
{"1", 128, "340282366920938463463374607431768211456"},
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(tests4)/sizeof(tests4[0]); i++) {
|
|
test("left shift", opa_value_compare(opa_number_ref(tests4[i].output, strlen(tests4[i].output)),
|
|
opa_bits_shiftleft(opa_number_ref(tests4[i].input, strlen(tests4[i].input)),
|
|
opa_number_int(tests4[i].shift))) == 0);
|
|
};
|
|
}
|
|
|
|
WASM_EXPORT(test_aggregates)
|
|
void test_aggregates(void)
|
|
{
|
|
opa_array_t *arr = opa_cast_array(opa_array());
|
|
opa_array_append(arr, opa_number_int(2));
|
|
opa_array_append(arr, opa_number_int(1));
|
|
opa_array_append(arr, opa_number_int(4));
|
|
|
|
opa_array_t *arr_sorted = opa_cast_array(opa_array());
|
|
opa_array_append(arr_sorted, opa_number_int(1));
|
|
opa_array_append(arr_sorted, opa_number_int(2));
|
|
opa_array_append(arr_sorted, opa_number_int(4));
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("b"), opa_number_int(2));
|
|
opa_object_insert(obj, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj, opa_string_terminated("c"), opa_number_int(4));
|
|
|
|
opa_set_t *set = opa_cast_set(opa_set());
|
|
opa_set_add(set, opa_number_int(2));
|
|
opa_set_add(set, opa_number_int(1));
|
|
opa_set_add(set, opa_number_int(4));
|
|
|
|
test("count/string", opa_value_compare(opa_agg_count(opa_string("foo", 3)), opa_number_int(3)) == 0);
|
|
test("count/unicode string", opa_value_compare(opa_agg_count(opa_string("\xC3\xA5\xC3\xA4\xC3\xB6", 6)), opa_number_int(3)) == 0);
|
|
test("count/array", opa_value_compare(opa_agg_count(&arr->hdr), opa_number_int(3)) == 0);
|
|
test("count/object", opa_value_compare(opa_agg_count(&obj->hdr), opa_number_int(3)) == 0);
|
|
test("count/set", opa_value_compare(opa_agg_count(&set->hdr), opa_number_int(3)) == 0);
|
|
|
|
test("sum/array", opa_value_compare(opa_agg_sum(&arr->hdr), opa_number_int(7)) == 0);
|
|
test("sum/set", opa_value_compare(opa_agg_sum(&set->hdr), opa_number_int(7)) == 0);
|
|
|
|
test("product/array", opa_value_compare(opa_agg_product(&arr->hdr), opa_number_int(8)) == 0);
|
|
test("product/set", opa_value_compare(opa_agg_product(&set->hdr), opa_number_int(8)) == 0);
|
|
|
|
test("max/array", opa_value_compare(opa_agg_max(&arr->hdr), opa_number_int(4)) == 0);
|
|
test("max/set", opa_value_compare(opa_agg_max(&set->hdr), opa_number_int(4)) == 0);
|
|
|
|
test("min/array", opa_value_compare(opa_agg_min(&arr->hdr), opa_number_int(1)) == 0);
|
|
test("min/set", opa_value_compare(opa_agg_min(&set->hdr), opa_number_int(1)) == 0);
|
|
|
|
test("sort/array", opa_value_compare(opa_agg_sort(&arr->hdr), &arr_sorted->hdr) == 0);
|
|
test("sort/set", opa_value_compare(opa_agg_sort(&set->hdr), &arr_sorted->hdr) == 0);
|
|
|
|
opa_array_t *arr_trues = opa_cast_array(opa_array());
|
|
opa_array_append(arr_trues, opa_boolean(true));
|
|
opa_array_append(arr_trues, opa_boolean(true));
|
|
|
|
opa_array_t *arr_mixed = opa_cast_array(opa_array());
|
|
opa_array_append(arr_mixed, opa_boolean(true));
|
|
opa_array_append(arr_mixed, opa_boolean(false));
|
|
|
|
opa_array_t *arr_falses = opa_cast_array(opa_array());
|
|
opa_array_append(arr_falses, opa_boolean(false));
|
|
opa_array_append(arr_falses, opa_boolean(false));
|
|
|
|
test("all/array trues", opa_value_compare(opa_agg_all(&arr_trues->hdr), opa_boolean(true)) == 0);
|
|
test("all/array mixed", opa_value_compare(opa_agg_all(&arr_mixed->hdr), opa_boolean(false)) == 0);
|
|
test("all/array falses", opa_value_compare(opa_agg_all(&arr_falses->hdr), opa_boolean(false)) == 0);
|
|
test("any/array trues", opa_value_compare(opa_agg_any(&arr_trues->hdr), opa_boolean(true)) == 0);
|
|
test("any/array mixed", opa_value_compare(opa_agg_any(&arr_mixed->hdr), opa_boolean(true)) == 0);
|
|
test("any/array falses", opa_value_compare(opa_agg_any(&arr_falses->hdr), opa_boolean(false)) == 0);
|
|
|
|
opa_set_t *set_trues = opa_cast_set(opa_set());
|
|
opa_set_add(set_trues, opa_boolean(true));
|
|
opa_set_add(set_trues, opa_boolean(true));
|
|
|
|
opa_set_t *set_mixed = opa_cast_set(opa_set());
|
|
opa_set_add(set_mixed, opa_boolean(true));
|
|
opa_set_add(set_mixed, opa_boolean(false));
|
|
|
|
opa_set_t *set_falses = opa_cast_set(opa_set());
|
|
opa_set_add(set_falses, opa_boolean(false));
|
|
opa_set_add(set_falses, opa_boolean(false));
|
|
|
|
test("all/set trues", opa_value_compare(opa_agg_all(&set_trues->hdr), opa_boolean(true)) == 0);
|
|
test("all/set mixed", opa_value_compare(opa_agg_all(&set_mixed->hdr), opa_boolean(false)) == 0);
|
|
test("all/set falses", opa_value_compare(opa_agg_all(&set_falses->hdr), opa_boolean(false)) == 0);
|
|
test("any/set trues", opa_value_compare(opa_agg_any(&set_trues->hdr), opa_boolean(true)) == 0);
|
|
test("any/set mixed", opa_value_compare(opa_agg_any(&set_mixed->hdr), opa_boolean(true)) == 0);
|
|
test("any/set falses", opa_value_compare(opa_agg_any(&set_falses->hdr), opa_boolean(false)) == 0);
|
|
|
|
opa_set_t *set_foo_bar = opa_cast_set(opa_set());
|
|
opa_set_add(set_foo_bar, opa_string_terminated("foo"));
|
|
opa_set_add(set_foo_bar, opa_string_terminated("bar"));
|
|
|
|
test("member3/set key==val found", opa_value_compare(builtin_member3(opa_string_terminated("foo"), opa_string_terminated("foo"), &set_foo_bar->hdr), opa_boolean(true)) == 0);
|
|
test("member3/set key==val not found", opa_value_compare(builtin_member3(opa_string_terminated("baz"), opa_string_terminated("baz"), &set_foo_bar->hdr), opa_boolean(false)) == 0);
|
|
test("member3/set key!=val", opa_value_compare(builtin_member3(opa_string_terminated("foo"), opa_string_terminated("bar"), &set_foo_bar->hdr), opa_boolean(false)) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_base64)
|
|
void test_base64(void)
|
|
{
|
|
test("base64/is_valid", opa_value_compare(opa_base64_is_valid(opa_string_terminated("YWJjMTIzIT8kKiYoKSctPUB+")), opa_boolean(true)) == 0);
|
|
test("base64/encode", opa_value_compare(opa_base64_encode(opa_string_terminated("abc123!?$*&()'-=@~")), opa_string_terminated("YWJjMTIzIT8kKiYoKSctPUB+")) == 0);
|
|
test("base64/encode", opa_value_compare(opa_base64_encode(opa_string_terminated("This is a long string that should not be split to many lines")),
|
|
opa_string_terminated("VGhpcyBpcyBhIGxvbmcgc3RyaW5nIHRoYXQgc2hvdWxkIG5vdCBiZSBzcGxpdCB0byBtYW55IGxpbmVz")) == 0);
|
|
test("base64/decode", opa_value_compare(opa_base64_decode(opa_string_terminated("YWJjMTIzIT8kKiYoKSctPUB+")), opa_string_terminated("abc123!?$*&()'-=@~")) == 0);
|
|
test("base64/decode", opa_value_compare(opa_base64_decode(opa_string_terminated("VGhpcyBpcyBhIGxvbmcgc3RyaW5nIHRoYXQgc2hvdWxkIG5vdCBiZSBzcGxpdCB0byBtYW55IGxpbmVz")),
|
|
opa_string_terminated("This is a long string that should not be split to many lines")) == 0);
|
|
test("base64/decode", opa_value_compare(opa_base64_decode(opa_string_terminated("VGhpcyBpcyBhIGxvbmcgc3RyaW5nIHRoYXQgY2FuIGJlIHBhcnNlZCBldmVuIGlmIHNwbGl0IHRv\nIG1hbnkgbGluZXM=")),
|
|
opa_string_terminated("This is a long string that can be parsed even if split to many lines")) == 0);
|
|
test("base64/url_encode", opa_value_compare(opa_base64_url_encode(opa_string_terminated("abc123!?$*&()'-=@~")), opa_string_terminated("YWJjMTIzIT8kKiYoKSctPUB-")) == 0);
|
|
test("base64/url_decode", opa_value_compare(opa_base64_url_decode(opa_string_terminated("YWJjMTIzIT8kKiYoKSctPUB-")), opa_string_terminated("abc123!?$*&()'-=@~")) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_json)
|
|
void test_json(void)
|
|
{
|
|
test("json/marshal", opa_value_compare(opa_json_marshal(opa_string_terminated("string")), opa_string_terminated("\"string\"")) == 0);
|
|
test("json/unmarshal", opa_value_compare(opa_json_unmarshal(opa_string_terminated("\"string\"")), opa_string_terminated("string")) == 0);
|
|
test("json/is_valid_true", opa_cast_boolean(opa_json_is_valid(opa_string_terminated("\"string\"")))->v);
|
|
test("json/is_valid_false", !opa_cast_boolean(opa_json_is_valid(opa_string_terminated("\"string")))->v);
|
|
}
|
|
|
|
WASM_EXPORT(test_object)
|
|
void test_object(void)
|
|
{
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj, opa_string_terminated("b"), opa_number_int(2));
|
|
opa_object_insert(obj, opa_string_terminated("c"), opa_number_int(3));
|
|
|
|
test("object/get (key found)", opa_value_compare(builtin_object_get(&obj->hdr, opa_string_terminated("a"), opa_number_int(2)), opa_number_int(1)) == 0);
|
|
test("object/get (string key not found)", opa_value_compare(builtin_object_get(&obj->hdr, opa_string_terminated("d"), opa_number_int(2)), opa_number_int(2)) == 0);
|
|
test("object/get (integer key not found)", opa_value_compare(builtin_object_get(&obj->hdr, opa_number_int(1), opa_number_int(2)), opa_number_int(2)) == 0);
|
|
test("object/get (boolean default value)", opa_value_compare(builtin_object_get(&obj->hdr, opa_number_int(1), opa_boolean(true)), opa_boolean(true)) == 0);
|
|
test("object/get (non-object operand)", opa_value_compare(builtin_object_get(opa_string_terminated("a"), opa_number_int(1), opa_boolean(true)), NULL) == 0);
|
|
|
|
opa_object_t *obj_keys = opa_cast_object(opa_object());
|
|
opa_object_insert(obj_keys, opa_string_terminated("a"), opa_number_int(0));
|
|
opa_object_insert(obj_keys, opa_string_terminated("c"), opa_number_int(0));
|
|
|
|
opa_object_t *expected = opa_cast_object(opa_object());
|
|
opa_object_insert(expected, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(expected, opa_string_terminated("c"), opa_number_int(3));
|
|
test("object/filter (object keys)", opa_value_compare(builtin_object_filter(&obj->hdr, &obj_keys->hdr), &expected->hdr) == 0);
|
|
|
|
opa_set_t *set_keys = opa_cast_set(opa_set());
|
|
opa_set_add(set_keys, opa_string_terminated("a"));
|
|
opa_set_add(set_keys, opa_string_terminated("c"));
|
|
test("object/filter (set keys)", opa_value_compare(builtin_object_filter(&obj->hdr, &set_keys->hdr), &expected->hdr) == 0);
|
|
|
|
opa_array_t *arr_keys = opa_cast_array(opa_array());
|
|
opa_array_append(arr_keys, opa_string_terminated("a"));
|
|
opa_array_append(arr_keys, opa_string_terminated("c"));
|
|
test("object/filter (array keys)", opa_value_compare(builtin_object_filter(&obj->hdr, &arr_keys->hdr), &expected->hdr) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_object_keys)
|
|
void test_object_keys(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj1, opa_string_terminated("b"), opa_number_int(2));
|
|
opa_object_insert(obj1, opa_string_terminated("c"), opa_number_int(3));
|
|
|
|
opa_set_t *expected_keys1 = opa_cast_set(opa_set());
|
|
opa_set_add(expected_keys1, opa_string_terminated("a"));
|
|
opa_set_add(expected_keys1, opa_string_terminated("b"));
|
|
opa_set_add(expected_keys1, opa_string_terminated("c"));
|
|
|
|
test("object/keys (string keys)", opa_value_compare(builtin_object_keys(&obj1->hdr), &expected_keys1->hdr) == 0);
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_number_int(1), opa_number_int(2));
|
|
opa_object_insert(obj2, opa_number_int(3), opa_number_int(4));
|
|
|
|
opa_set_t *expected_keys2 = opa_cast_set(opa_set());
|
|
opa_set_add(expected_keys2, opa_number_int(1));
|
|
opa_set_add(expected_keys2, opa_number_int(3));
|
|
|
|
test("object/keys (number keys)", opa_value_compare(builtin_object_keys(&obj2->hdr), &expected_keys2->hdr) == 0);
|
|
|
|
opa_set_t *set_key = opa_cast_set(opa_set());
|
|
opa_set_add(set_key, opa_number_int(1));
|
|
opa_set_add(set_key, opa_number_int(2));
|
|
|
|
opa_object_t *obj3 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj3, &set_key->hdr, opa_number_int(1));
|
|
|
|
opa_set_t *expected_keys3 = opa_cast_set(opa_set());
|
|
opa_set_add(expected_keys3, &set_key->hdr);
|
|
|
|
test("object/keys (set keys)", opa_value_compare(builtin_object_keys(&obj3->hdr), &expected_keys3->hdr) == 0);
|
|
|
|
opa_object_t *object_key = opa_cast_object(opa_object());
|
|
opa_object_insert(object_key, opa_string_terminated("a"), opa_number_int(1));
|
|
|
|
opa_object_t *obj4 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj4, &object_key->hdr, opa_number_int(1));
|
|
|
|
opa_set_t *expected_keys4 = opa_cast_set(opa_set());
|
|
opa_set_add(expected_keys4, &object_key->hdr);
|
|
|
|
test("object/keys (object keys)", opa_value_compare(builtin_object_keys(&obj4->hdr), &expected_keys4->hdr) == 0);
|
|
|
|
opa_array_t *array_key = opa_cast_array(opa_array());
|
|
opa_array_append(array_key, opa_number_int(1));
|
|
opa_array_append(array_key, opa_number_int(2));
|
|
|
|
opa_object_t *obj5 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj5, &array_key->hdr, opa_number_int(1));
|
|
|
|
opa_set_t *expected_keys5 = opa_cast_set(opa_set());
|
|
opa_set_add(expected_keys5, &array_key->hdr);
|
|
|
|
test("object/keys (array keys)", opa_value_compare(builtin_object_keys(&obj5->hdr), &expected_keys5->hdr) == 0);
|
|
|
|
opa_object_t *obj6 = opa_cast_object(opa_object());
|
|
opa_set_t *expected_keys6 = opa_cast_set(opa_set());
|
|
test("object/keys (empty)", opa_value_compare(builtin_object_keys(&obj6->hdr), &expected_keys6->hdr) == 0);
|
|
|
|
test("object/keys (null on non-object)", opa_value_compare(builtin_object_keys(opa_number_int(3)), NULL) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_object_remove)
|
|
void test_object_remove(void)
|
|
{
|
|
opa_object_t *o = opa_cast_object(opa_object());
|
|
opa_object_insert(o, opa_string_terminated("c"), opa_number_int(3));
|
|
|
|
// input -> {"a": 1, "b": {"c": 3}}
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj1, opa_string_terminated("b"), &o->hdr);
|
|
|
|
opa_set_t *set_keys1 = opa_cast_set(opa_set());
|
|
opa_set_add(set_keys1, opa_string_terminated("a"));
|
|
|
|
opa_object_t *expected1 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected1, opa_string_terminated("b"), &o->hdr);
|
|
test("object/remove (base)", opa_value_compare(builtin_object_remove(&obj1->hdr, &set_keys1->hdr), &expected1->hdr) == 0);
|
|
|
|
// input -> {"a": 1, "b": {"c": 3}, "d": 4}
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(obj2, opa_string_terminated("b"), &o->hdr);
|
|
opa_object_insert(obj2, opa_string_terminated("d"), opa_number_int(4));
|
|
|
|
opa_set_t *set_keys2 = opa_cast_set(opa_set());
|
|
opa_set_add(set_keys2, opa_string_terminated("b"));
|
|
opa_set_add(set_keys2, opa_string_terminated("d"));
|
|
|
|
opa_object_t *expected2 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected2, opa_string_terminated("a"), opa_number_int(1));
|
|
test("object/remove (multiple keys set)", opa_value_compare(builtin_object_remove(&obj2->hdr, &set_keys2->hdr), &expected2->hdr) == 0);
|
|
|
|
opa_array_t *arr_keys = opa_cast_array(opa_array());
|
|
opa_array_append(arr_keys, opa_string_terminated("b"));
|
|
opa_array_append(arr_keys, opa_string_terminated("d"));
|
|
test("object/remove (multiple keys array)", opa_value_compare(builtin_object_remove(&obj2->hdr, &arr_keys->hdr), &expected2->hdr) == 0);
|
|
|
|
opa_object_t *obj_keys = opa_cast_object(opa_object());
|
|
opa_object_insert(obj_keys, opa_string_terminated("b"), opa_number_int(1));
|
|
opa_object_insert(obj_keys, opa_string_terminated("d"), opa_string_terminated(""));
|
|
test("object/remove (multiple keys object)", opa_value_compare(builtin_object_remove(&obj2->hdr, &obj_keys->hdr), &expected2->hdr) == 0);
|
|
|
|
// input -> {"a": {"b": {"c": 3}}, "x": 123}
|
|
opa_object_t *o2 = opa_cast_object(opa_object());
|
|
opa_object_insert(o2, opa_string_terminated("b"), &o->hdr);
|
|
|
|
opa_object_t *obj3 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj3, opa_string_terminated("a"), &o2->hdr);
|
|
opa_object_insert(obj3, opa_string_terminated("x"), opa_number_int(123));
|
|
|
|
opa_object_t *o_keys1 = opa_cast_object(opa_object());
|
|
opa_object_insert(o_keys1, opa_string_terminated("foo"), opa_string_terminated("bar"));
|
|
|
|
opa_object_t *o_keys2 = opa_cast_object(opa_object());
|
|
opa_object_insert(o_keys2, opa_string_terminated("b"), &o_keys1->hdr);
|
|
|
|
opa_object_t *obj_keys2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj_keys2, opa_string_terminated("a"), &o_keys2->hdr);
|
|
|
|
opa_object_t *expected3 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected3, opa_string_terminated("x"), opa_number_int(123));
|
|
test("object/remove (multiple keys object nested)", opa_value_compare(builtin_object_remove(&obj3->hdr, &obj_keys2->hdr), &expected3->hdr) == 0);
|
|
|
|
test("object/remove (empty object)", opa_value_compare(builtin_object_remove(opa_object(), &obj_keys2->hdr), opa_object()) == 0);
|
|
|
|
test("object/remove (empty keys set)", opa_value_compare(builtin_object_remove(&obj3->hdr, opa_set()), &obj3->hdr) == 0);
|
|
|
|
test("object/remove (empty keys array)", opa_value_compare(builtin_object_remove(&obj3->hdr, opa_array()), &obj3->hdr) == 0);
|
|
|
|
test("object/remove (empty keys object)", opa_value_compare(builtin_object_remove(&obj3->hdr, opa_object()), &obj3->hdr) == 0);
|
|
|
|
test("object/remove (non-object first operand)", opa_value_compare(builtin_object_remove(opa_string_terminated("a"), opa_object()), NULL) == 0);
|
|
|
|
opa_set_t *set_keys3 = opa_cast_set(opa_set());
|
|
opa_set_add(set_keys3, opa_string_terminated("foo"));
|
|
test("object/remove (key does not exist)", opa_value_compare(builtin_object_remove(&obj3->hdr, &set_keys3->hdr), &obj3->hdr) == 0);
|
|
|
|
test("object/remove (second operand not object/set/array)", opa_value_compare(builtin_object_remove(&obj3->hdr, opa_string_terminated("a")), NULL) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_object_union)
|
|
void test_object_union(void)
|
|
{
|
|
test("object/union (both empty)", opa_value_compare(builtin_object_union(opa_object(), opa_object()), opa_object()) == 0);
|
|
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("a"), opa_number_int(1));
|
|
test("object/union (left empty)", opa_value_compare(builtin_object_union(opa_object(), &obj1->hdr), &obj1->hdr) == 0);
|
|
|
|
test("object/union (right empty)", opa_value_compare(builtin_object_union(&obj1->hdr, opa_object()), &obj1->hdr) == 0);
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("b"), opa_number_int(2));
|
|
|
|
opa_object_t *expected1 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected1, opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(expected1, opa_string_terminated("b"), opa_number_int(2));
|
|
|
|
test("object/union (base)", opa_value_compare(builtin_object_union(&obj1->hdr, &obj2->hdr), &expected1->hdr) == 0);
|
|
|
|
opa_object_t *o = opa_cast_object(opa_object());
|
|
opa_object_insert(o, opa_string_terminated("c"), opa_number_int(3));
|
|
opa_object_t *o2 = opa_cast_object(opa_object());
|
|
opa_object_insert(o2, opa_string_terminated("b"), &o->hdr);
|
|
opa_object_t *obj3 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj3, opa_string_terminated("a"), &o2->hdr);
|
|
|
|
opa_object_t *expected2 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected2, opa_string_terminated("a"),&o2->hdr);
|
|
opa_object_insert(expected2, opa_string_terminated("b"), opa_number_int(2));
|
|
|
|
test("object/union (nested)", opa_value_compare(builtin_object_union(&obj3->hdr, &obj2->hdr), &expected2->hdr) == 0);
|
|
test("object/union (nested reverse)", opa_value_compare(builtin_object_union(&obj2->hdr, &obj3->hdr), &expected2->hdr) == 0);
|
|
|
|
opa_object_t *obj4 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj4, opa_string_terminated("a"), opa_number_int(2));
|
|
|
|
test("object/union (conflict simple)", opa_value_compare(builtin_object_union(&obj1->hdr, &obj4->hdr), &obj4->hdr) == 0);
|
|
|
|
opa_object_insert(obj3, opa_string_terminated("d"), opa_number_int(7));
|
|
|
|
test("object/union (conflict nested and extra field)", opa_value_compare(builtin_object_union(&obj1->hdr, &obj3->hdr), &obj3->hdr) == 0);
|
|
|
|
// Operand 1 -> {"a": {"b": {"c": 1}}, "e": 1}
|
|
opa_object_t *o3 = opa_cast_object(opa_object());
|
|
opa_object_insert(o3, opa_string_terminated("c"), opa_number_int(1));
|
|
opa_object_t *o4 = opa_cast_object(opa_object());
|
|
opa_object_insert(o4, opa_string_terminated("b"), &o3->hdr);
|
|
opa_object_t *obj5 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj5, opa_string_terminated("a"), &o4->hdr);
|
|
opa_object_insert(obj5, opa_string_terminated("e"), opa_number_int(1));
|
|
|
|
// Operand 2 -> {"a": {"b": "foo", "b1": "bar"}, "d": 7, "e": 17}
|
|
opa_object_t *o5 = opa_cast_object(opa_object());
|
|
opa_object_insert(o5, opa_string_terminated("b"), opa_string_terminated("foo"));
|
|
opa_object_insert(o5, opa_string_terminated("b1"), opa_string_terminated("bar"));
|
|
opa_object_t *obj6 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj6, opa_string_terminated("a"), &o5->hdr);
|
|
opa_object_insert(obj6, opa_string_terminated("d"), opa_number_int(7));
|
|
opa_object_insert(obj6, opa_string_terminated("e"), opa_number_int(17));
|
|
|
|
// Expected -> {"a": {"b": "foo", "b1": "bar"}, "d": 7, "e": 17}
|
|
opa_object_t *o6 = opa_cast_object(opa_object());
|
|
opa_object_insert(o6, opa_string_terminated("b"), opa_string_terminated("foo"));
|
|
opa_object_insert(o6, opa_string_terminated("b1"), opa_string_terminated("bar"));
|
|
opa_object_t *expected3 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected3, opa_string_terminated("a"), &o6->hdr);
|
|
opa_object_insert(expected3, opa_string_terminated("d"), opa_number_int(7));
|
|
opa_object_insert(expected3, opa_string_terminated("e"), opa_number_int(17));
|
|
|
|
test("object/union (conflict multiple-1)", opa_value_compare(builtin_object_union(&obj5->hdr, &obj6->hdr), &expected3->hdr) == 0);
|
|
|
|
// Operand 1 -> {"a": {"b": {"c": 1, "d": 2}}, "e": 1}
|
|
opa_object_t *o7 = opa_cast_object(opa_object());
|
|
opa_object_insert(o7, opa_string_terminated("c"), opa_number_int(1));
|
|
opa_object_insert(o7, opa_string_terminated("d"), opa_number_int(2));
|
|
opa_object_t *o8 = opa_cast_object(opa_object());
|
|
opa_object_insert(o8, opa_string_terminated("b"), &o7->hdr);
|
|
opa_object_t *obj7 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj7, opa_string_terminated("a"), &o8->hdr);
|
|
opa_object_insert(obj7, opa_string_terminated("e"), opa_number_int(1));
|
|
|
|
// Operand 2 -> {"a": {"b": {"c": "foo"}, "b1": "bar"}, "d": 7, "e": 17}
|
|
opa_object_t *o9 = opa_cast_object(opa_object());
|
|
opa_object_insert(o9, opa_string_terminated("c"), opa_string_terminated("foo"));
|
|
opa_object_t *o10 = opa_cast_object(opa_object());
|
|
opa_object_insert(o10, opa_string_terminated("b"), &o9->hdr);
|
|
opa_object_insert(o10, opa_string_terminated("b1"), opa_string_terminated("bar"));
|
|
opa_object_t *obj8 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj8, opa_string_terminated("a"), &o10->hdr);
|
|
opa_object_insert(obj8, opa_string_terminated("d"), opa_number_int(7));
|
|
opa_object_insert(obj8, opa_string_terminated("e"), opa_number_int(17));
|
|
|
|
// Expected -> {"a": {"b": {"c": "foo", "d": 2}, "b1": "bar"}, "d": 7, "e": 17}
|
|
opa_object_t *o11 = opa_cast_object(opa_object());
|
|
opa_object_insert(o11, opa_string_terminated("c"), opa_string_terminated("foo"));
|
|
opa_object_insert(o11, opa_string_terminated("d"), opa_number_int(2));
|
|
opa_object_t *o12 = opa_cast_object(opa_object());
|
|
opa_object_insert(o12, opa_string_terminated("b"), &o11->hdr);
|
|
opa_object_insert(o12, opa_string_terminated("b1"), opa_string_terminated("bar"));
|
|
opa_object_t *expected4 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected4, opa_string_terminated("a"), &o12->hdr);
|
|
opa_object_insert(expected4, opa_string_terminated("d"), opa_number_int(7));
|
|
opa_object_insert(expected4, opa_string_terminated("e"), opa_number_int(17));
|
|
|
|
test("object/union (conflict multiple-2)", opa_value_compare(builtin_object_union(&obj7->hdr, &obj8->hdr), &expected4->hdr) == 0);
|
|
|
|
opa_object_t *obj9 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj9, opa_string_terminated("a"), opa_string_terminated("foo"));
|
|
opa_object_insert(obj9, opa_string_terminated("b"), opa_string_terminated("bar"));
|
|
|
|
opa_object_t *obj10 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj10, opa_string_terminated("a"), opa_string_terminated("baz"));
|
|
|
|
opa_object_t *expected5 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected5, opa_string_terminated("a"), opa_string_terminated("baz"));
|
|
opa_object_insert(expected5, opa_string_terminated("b"), opa_string_terminated("bar"));
|
|
|
|
test("object/union (conflict multiple-3)", opa_value_compare(builtin_object_union(&obj9->hdr, &obj10->hdr), &expected5->hdr) == 0);
|
|
|
|
test("object/union (non-object first operand)", opa_value_compare(builtin_object_union(opa_string_terminated("a"), opa_object()), NULL) == 0);
|
|
|
|
test("object/union (non-object second operand)", opa_value_compare(builtin_object_union(opa_object(), opa_string_terminated("a")), NULL) == 0);
|
|
}
|
|
|
|
opa_object_t *json_test_fixture_object1(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("c"), opa_number_int(7));
|
|
opa_object_insert(obj1, opa_string_terminated("d"), opa_number_int(8));
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("b"), &obj1->hdr);
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), &obj2->hdr);
|
|
opa_object_insert(obj, opa_string_terminated("e"), opa_number_int(9));
|
|
return obj;
|
|
}
|
|
|
|
opa_object_t *json_test_fixture_object2(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("c"), opa_number_int(7));
|
|
opa_object_insert(obj1, opa_string_terminated("d"), opa_number_int(8));
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("b"), &obj1->hdr);
|
|
opa_object_insert(obj2, opa_string_terminated("e"), opa_number_int(9));
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), &obj2->hdr);
|
|
|
|
return obj;
|
|
}
|
|
|
|
opa_object_t *json_test_fixture_object3(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("b"), opa_number_int(7));
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), &obj1->hdr);
|
|
opa_object_insert(obj, opa_string_terminated("c"), opa_number_int(1));
|
|
|
|
return obj;
|
|
}
|
|
|
|
opa_object_t *json_test_fixture_object4(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("b"), opa_number_int(7));
|
|
opa_object_insert(obj1, opa_string_terminated("c"), opa_number_int(8));
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("d"), opa_number_int(9));
|
|
|
|
opa_array_t *arr1 = opa_cast_array(opa_array());
|
|
opa_array_append(arr1, &obj1->hdr);
|
|
opa_array_append(arr1, &obj2->hdr);
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), &arr1->hdr);
|
|
|
|
return obj;
|
|
}
|
|
|
|
opa_object_t *json_test_fixture_object5(void)
|
|
{
|
|
opa_array_t *arr1 = opa_cast_array(opa_array());
|
|
opa_array_append(arr1, opa_string_terminated("b"));
|
|
opa_array_append(arr1, opa_string_terminated("c"));
|
|
opa_array_append(arr1, opa_string_terminated("d"));
|
|
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("1"), &arr1->hdr);
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("x"), opa_string_terminated("y"));
|
|
|
|
opa_array_t *arr2 = opa_cast_array(opa_array());
|
|
opa_array_append(arr2, &obj1->hdr);
|
|
opa_array_append(arr2, &obj2->hdr);
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), &arr2->hdr);
|
|
|
|
return obj;
|
|
}
|
|
|
|
opa_object_t *json_test_fixture_object6(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("c"), opa_number_int(7));
|
|
opa_object_insert(obj1, opa_string_terminated("d"), opa_number_int(8));
|
|
opa_object_insert(obj1, opa_string_terminated("x"), opa_number_int(0));
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("b"), &obj1->hdr);
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), &obj2->hdr);
|
|
opa_object_insert(obj, opa_string_terminated("e"), opa_number_int(9));
|
|
return obj;
|
|
}
|
|
|
|
opa_object_t *json_remove_get_exp_object1(void)
|
|
{
|
|
opa_array_t *arr1 = opa_cast_array(opa_array());
|
|
opa_array_append(arr1, opa_string_terminated("b"));
|
|
opa_array_append(arr1, opa_string_terminated("c"));
|
|
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("1"), &arr1->hdr);
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("x"), opa_string_terminated("y"));
|
|
|
|
opa_array_t *arr2 = opa_cast_array(opa_array());
|
|
opa_array_append(arr2, &obj1->hdr);
|
|
opa_array_append(arr2, &obj2->hdr);
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), &arr2->hdr);
|
|
|
|
return obj;
|
|
}
|
|
|
|
opa_object_t *json_remove_get_exp_object2(void)
|
|
{
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("x"), opa_number_int(0));
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("b"), &obj1->hdr);
|
|
|
|
opa_object_t *obj = opa_cast_object(opa_object());
|
|
opa_object_insert(obj, opa_string_terminated("a"), &obj2->hdr);
|
|
opa_object_insert(obj, opa_string_terminated("e"), opa_number_int(9));
|
|
return obj;
|
|
}
|
|
|
|
WASM_EXPORT(test_json_remove)
|
|
void test_json_remove(void)
|
|
{
|
|
opa_object_t *obj1 = json_test_fixture_object1();
|
|
|
|
opa_set_t *set_paths1 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths1, opa_string_terminated("a/b/c"));
|
|
|
|
opa_object_t *o1 = opa_cast_object(opa_object());
|
|
opa_object_insert(o1, opa_string_terminated("d"), opa_number_int(8));
|
|
opa_object_t *o2 = opa_cast_object(opa_object());
|
|
opa_object_insert(o2, opa_string_terminated("b"), &o1->hdr);
|
|
|
|
opa_object_t *expected1 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected1, opa_string_terminated("a"), &o2->hdr);
|
|
opa_object_insert(expected1, opa_string_terminated("e"), opa_number_int(9));
|
|
|
|
test("jsonremove/base", opa_value_compare(builtin_json_remove(&obj1->hdr, &set_paths1->hdr), &expected1->hdr) == 0);
|
|
|
|
opa_set_add(set_paths1, opa_string_terminated("e"));
|
|
|
|
opa_object_t *expected2 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected2, opa_string_terminated("a"), &o2->hdr);
|
|
|
|
test("jsonremove/multiple roots", opa_value_compare(builtin_json_remove(&obj1->hdr, &set_paths1->hdr), &expected2->hdr) == 0);
|
|
|
|
opa_array_t *array_paths1 = opa_cast_array(opa_array());
|
|
opa_array_append(array_paths1, opa_string_terminated("a/b/c"));
|
|
opa_array_append(array_paths1, opa_string_terminated("e"));
|
|
|
|
test("jsonremove/multiple roots array", opa_value_compare(builtin_json_remove(&obj1->hdr, &array_paths1->hdr), &expected2->hdr) == 0);
|
|
|
|
opa_object_t *obj2 = json_test_fixture_object2();
|
|
|
|
opa_set_t *set_paths2 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths2, opa_string_terminated("a/b/c"));
|
|
opa_set_add(set_paths2, opa_string_terminated("a/e"));
|
|
|
|
test("jsonremove/shared roots", opa_value_compare(builtin_json_remove(&obj2->hdr, &set_paths2->hdr), &expected2->hdr) == 0);
|
|
|
|
opa_object_t *obj3 = json_test_fixture_object3();
|
|
opa_set_t *set_paths3 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths3, opa_string_terminated("a"));
|
|
opa_set_add(set_paths3, opa_string_terminated("a/b"));
|
|
|
|
opa_object_t *expected3 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected3, opa_string_terminated("c"), opa_number_int(1));
|
|
|
|
test("jsonremove/conflict", opa_value_compare(builtin_json_remove(&obj3->hdr, &set_paths3->hdr), &expected3->hdr) == 0);
|
|
|
|
opa_object_t *obj4 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj4, opa_string_terminated("a"), opa_number_int(7));
|
|
|
|
test("jsonremove/empty list", opa_value_compare(builtin_json_remove(&obj4->hdr, opa_set()), &obj4->hdr) == 0);
|
|
|
|
test("jsonremove/empty object", opa_value_compare(builtin_json_remove(opa_object(), &set_paths3->hdr), opa_object()) == 0);
|
|
|
|
opa_object_t *obj5 = json_test_fixture_object1();
|
|
|
|
opa_set_t *set_paths4 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths4, opa_string_terminated("a"));
|
|
opa_set_add(set_paths4, opa_string_terminated("e"));
|
|
|
|
test("jsonremove/delete all", opa_value_compare(builtin_json_remove(&obj5->hdr, &set_paths4->hdr), opa_object()) == 0);
|
|
|
|
opa_object_t *obj6 = json_test_fixture_object4();
|
|
|
|
opa_set_t *set_paths5 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths5, opa_string_terminated("a/0/b"));
|
|
opa_set_add(set_paths5, opa_string_terminated("a/1"));
|
|
|
|
opa_object_t *o3 = opa_cast_object(opa_object());
|
|
opa_object_insert(o3, opa_string_terminated("c"), opa_number_int(8));
|
|
opa_array_t *a3 = opa_cast_array(opa_array());
|
|
opa_array_append(a3, &o3->hdr);
|
|
opa_object_t *expected4 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected4, opa_string_terminated("a"), &a3->hdr);
|
|
|
|
test("jsonremove/arrays", opa_value_compare(builtin_json_remove(&obj6->hdr, &set_paths5->hdr), &expected4->hdr) == 0);
|
|
|
|
opa_object_t *obj7 = json_test_fixture_object5();
|
|
|
|
opa_set_t *set_paths6 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths6, opa_string_terminated("a/0/1/2"));
|
|
|
|
opa_object_t *expected5 = json_remove_get_exp_object1();
|
|
|
|
test("jsonremove/object with number keys", opa_value_compare(builtin_json_remove(&obj7->hdr, &set_paths6->hdr), &expected5->hdr) == 0);
|
|
|
|
opa_object_t *obj8 = json_test_fixture_object1();
|
|
|
|
opa_array_t *a4 = opa_cast_array(opa_array());
|
|
opa_array_append(a4, opa_string_terminated("a"));
|
|
opa_array_append(a4, opa_string_terminated("b"));
|
|
opa_array_append(a4, opa_string_terminated("c"));
|
|
|
|
opa_array_t *a5 = opa_cast_array(opa_array());
|
|
opa_array_append(a5, opa_string_terminated("e"));
|
|
|
|
opa_set_t *set_paths7 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths7, &a4->hdr);
|
|
opa_set_add(set_paths7, &a5->hdr);
|
|
|
|
test("jsonremove/arrays of roots", opa_value_compare(builtin_json_remove(&obj8->hdr, &set_paths7->hdr), &expected2->hdr) == 0);
|
|
|
|
opa_object_t *obj9 = json_test_fixture_object6();
|
|
|
|
opa_set_t *set_paths8 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths8, opa_string_terminated("a/b/d"));
|
|
opa_set_add(set_paths8, &a4->hdr);
|
|
|
|
opa_object_t *expected6 = json_remove_get_exp_object2();
|
|
|
|
test("jsonremove/mixed root types", opa_value_compare(builtin_json_remove(&obj9->hdr, &set_paths8->hdr), &expected6->hdr) == 0);
|
|
|
|
test("jsonremove/error (invalid first operand - string)", opa_value_compare(builtin_json_remove(opa_string_terminated("a"), opa_set()), NULL) == 0);
|
|
|
|
test("jsonremove/error (invalid first operand - number)", opa_value_compare(builtin_json_remove(opa_number_int(22), opa_set()), NULL) == 0);
|
|
|
|
test("jsonremove/error (invalid first operand - boolean)", opa_value_compare(builtin_json_remove(opa_boolean(true), opa_set()), NULL) == 0);
|
|
|
|
test("jsonremove/error (invalid first operand - array)", opa_value_compare(builtin_json_remove(opa_array(), opa_set()), NULL) == 0);
|
|
|
|
test("jsonremove/error (invalid second operand - string)", opa_value_compare(builtin_json_remove(opa_object(), opa_string_terminated("a")), NULL) == 0);
|
|
|
|
test("jsonremove/error (invalid second operand - number)", opa_value_compare(builtin_json_remove(opa_object(), opa_number_int(22)), NULL) == 0);
|
|
|
|
test("jsonremove/error (invalid second operand - boolean)", opa_value_compare(builtin_json_remove(opa_object(), opa_boolean(true)), NULL) == 0);
|
|
|
|
test("jsonremove/error (invalid second operand - object)", opa_value_compare(builtin_json_remove(opa_object(), opa_object()), NULL) == 0);
|
|
|
|
opa_set_t *set_paths9 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths9, opa_number_int(1));
|
|
opa_set_add(set_paths9, opa_string_terminated("a"));
|
|
|
|
test("jsonremove/error invalid paths type set with numbers", opa_value_compare(builtin_json_remove(opa_object(), &set_paths9->hdr), NULL) == 0);
|
|
|
|
opa_set_t *set_paths10 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths10, opa_string_terminated("a"));
|
|
opa_set_add(set_paths10, &obj9->hdr);
|
|
|
|
test("jsonremove/error invalid paths type set with objects", opa_value_compare(builtin_json_remove(opa_object(), &set_paths10->hdr), NULL) == 0);
|
|
|
|
opa_array_t *array_paths2 = opa_cast_array(opa_array());
|
|
opa_array_append(array_paths2, opa_string_terminated("a"));
|
|
opa_array_append(array_paths2, opa_number_int(1));
|
|
opa_array_append(array_paths2, opa_number_int(2));
|
|
|
|
test("jsonremove/error invalid paths type array with numbers", opa_value_compare(builtin_json_remove(opa_object(), &array_paths2->hdr), NULL) == 0);
|
|
|
|
opa_array_t *array_paths3 = opa_cast_array(opa_array());
|
|
opa_array_append(array_paths3, opa_string_terminated("a"));
|
|
opa_array_append(array_paths3, opa_object());
|
|
|
|
test("jsonremove/error invalid paths type array with objects", opa_value_compare(builtin_json_remove(opa_object(), &array_paths3->hdr), NULL) == 0);
|
|
|
|
opa_set_t *set_paths11 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths11, opa_string_terminated("a/b"));
|
|
opa_set_add(set_paths11, opa_string_terminated("e"));
|
|
|
|
opa_object_t *expected7 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected7, opa_string_terminated("a"), opa_object());
|
|
|
|
test("jsonremove/delete last in object", opa_value_compare(builtin_json_remove(&obj5->hdr, &set_paths11->hdr), &expected7->hdr) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_json_filter)
|
|
void test_json_filter(void)
|
|
{
|
|
opa_object_t *obj1 = json_test_fixture_object1();
|
|
|
|
opa_set_t *set_paths1 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths1, opa_string_terminated("a/b/c"));
|
|
|
|
opa_object_t *o1 = opa_cast_object(opa_object());
|
|
opa_object_insert(o1, opa_string_terminated("c"), opa_number_int(7));
|
|
opa_object_t *o2 = opa_cast_object(opa_object());
|
|
opa_object_insert(o2, opa_string_terminated("b"), &o1->hdr);
|
|
|
|
opa_object_t *expected1 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected1, opa_string_terminated("a"), &o2->hdr);
|
|
|
|
test("jsonfilter/base", opa_value_compare(builtin_json_filter(&obj1->hdr, &set_paths1->hdr), &expected1->hdr) == 0);
|
|
|
|
opa_set_add(set_paths1, opa_string_terminated("e"));
|
|
opa_object_insert(expected1, opa_string_terminated("e"), opa_number_int(9));
|
|
|
|
test("jsonfilter/multiple roots", opa_value_compare(builtin_json_filter(&obj1->hdr, &set_paths1->hdr), &expected1->hdr) == 0);
|
|
|
|
opa_array_t *array_paths1 = opa_cast_array(opa_array());
|
|
opa_array_append(array_paths1, opa_string_terminated("a/b/c"));
|
|
opa_array_append(array_paths1, opa_string_terminated("e"));
|
|
|
|
test("jsonfilter/multiple roots array", opa_value_compare(builtin_json_filter(&obj1->hdr, &array_paths1->hdr), &expected1->hdr) == 0);
|
|
|
|
opa_object_t *obj2 = json_test_fixture_object2();
|
|
|
|
opa_set_t *set_paths2 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths2, opa_string_terminated("a/b/c"));
|
|
opa_set_add(set_paths2, opa_string_terminated("a/e"));
|
|
|
|
opa_object_t *o3 = opa_cast_object(opa_object());
|
|
opa_object_insert(o3, opa_string_terminated("b"), &o1->hdr);
|
|
opa_object_insert(o3, opa_string_terminated("e"), opa_number_int(9));
|
|
|
|
opa_object_t *expected2 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected2, opa_string_terminated("a"), &o3->hdr);
|
|
|
|
test("jsonfilter/shared roots", opa_value_compare(builtin_json_filter(&obj2->hdr, &set_paths2->hdr), &expected2->hdr) == 0);
|
|
|
|
opa_object_t *o4 = opa_cast_object(opa_object());
|
|
opa_object_insert(o4, opa_string_terminated("b"), opa_number_int(7));
|
|
|
|
opa_object_t *obj3 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj3, opa_string_terminated("a"), &o4->hdr);
|
|
|
|
opa_set_t *set_paths3 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths3, opa_string_terminated("a"));
|
|
opa_set_add(set_paths3, opa_string_terminated("a/b"));
|
|
|
|
test("jsonfilter/conflict", opa_value_compare(builtin_json_filter(&obj3->hdr, &set_paths3->hdr), &obj3->hdr) == 0);
|
|
|
|
test("jsonfilter/empty list", opa_value_compare(builtin_json_filter(&obj3->hdr, opa_set()), opa_object()) == 0);
|
|
|
|
test("jsonfilter/empty object", opa_value_compare(builtin_json_filter(opa_object(), &set_paths3->hdr), opa_object()) == 0);
|
|
|
|
opa_object_t *obj4 = json_test_fixture_object4();
|
|
opa_set_t *set_paths4 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths4, opa_string_terminated("a/0/b"));
|
|
opa_set_add(set_paths4, opa_string_terminated("a/1"));
|
|
|
|
opa_object_t *o5 = opa_cast_object(opa_object());
|
|
opa_object_insert(o5, opa_string_terminated("b"), opa_number_int(7));
|
|
|
|
opa_object_t *o6 = opa_cast_object(opa_object());
|
|
opa_object_insert(o6, opa_string_terminated("d"), opa_number_int(9));
|
|
|
|
opa_array_t *a1 = opa_cast_array(opa_array());
|
|
opa_array_append(a1, &o5->hdr);
|
|
opa_array_append(a1, &o6->hdr);
|
|
|
|
opa_object_t *expected3 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected3, opa_string_terminated("a"), &a1->hdr);
|
|
|
|
test("jsonfilter/arrays", opa_value_compare(builtin_json_filter(&obj4->hdr, &set_paths4->hdr), &expected3->hdr) == 0);
|
|
|
|
opa_object_t *obj5 = json_test_fixture_object5();
|
|
opa_set_t *set_paths5 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths5, opa_string_terminated("a/0/1/2"));
|
|
|
|
opa_array_t *a2 = opa_cast_array(opa_array());
|
|
opa_array_append(a2, opa_string_terminated("d"));
|
|
|
|
opa_object_t *o7 = opa_cast_object(opa_object());
|
|
opa_object_insert(o7, opa_string_terminated("1"), &a2->hdr);
|
|
|
|
opa_array_t *a3 = opa_cast_array(opa_array());
|
|
opa_array_append(a3, &o7->hdr);
|
|
|
|
opa_object_t *expected4 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected4, opa_string_terminated("a"), &a3->hdr);
|
|
|
|
test("jsonfilter/object with number keys", opa_value_compare(builtin_json_filter(&obj5->hdr, &set_paths5->hdr), &expected4->hdr) == 0);
|
|
|
|
opa_array_t *a4 = opa_cast_array(opa_array());
|
|
opa_array_append(a4, opa_string_terminated("a"));
|
|
opa_array_append(a4, opa_string_terminated("b"));
|
|
opa_array_append(a4, opa_string_terminated("c"));
|
|
|
|
opa_array_t *a5 = opa_cast_array(opa_array());
|
|
opa_array_append(a5, opa_string_terminated("e"));
|
|
|
|
opa_set_t *set_paths6 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths6, &a4->hdr);
|
|
opa_set_add(set_paths6, &a5->hdr);
|
|
|
|
test("jsonfilter/arrays of roots", opa_value_compare(builtin_json_filter(&obj1->hdr, &set_paths6->hdr), &expected1->hdr) == 0);
|
|
|
|
opa_object_t *obj6 = json_test_fixture_object6();
|
|
|
|
opa_set_t *set_paths7 = opa_cast_set(opa_set());
|
|
opa_set_add(set_paths7, opa_string_terminated("a/b/d"));
|
|
opa_set_add(set_paths7, &a4->hdr);
|
|
|
|
opa_object_t *o8 = opa_cast_object(opa_object());
|
|
opa_object_insert(o8, opa_string_terminated("c"), opa_number_int(7));
|
|
opa_object_insert(o8, opa_string_terminated("d"), opa_number_int(8));
|
|
|
|
opa_object_t *o9 = opa_cast_object(opa_object());
|
|
opa_object_insert(o9, opa_string_terminated("b"), &o8->hdr);
|
|
|
|
opa_object_t *expected5 = opa_cast_object(opa_object());
|
|
opa_object_insert(expected5, opa_string_terminated("a"), &o9->hdr);
|
|
|
|
test("jsonfilter/mixed root types", opa_value_compare(builtin_json_filter(&obj6->hdr, &set_paths7->hdr), &expected5->hdr) == 0);
|
|
|
|
test("jsonfilter/error (invalid first operand - string)", opa_value_compare(builtin_json_filter(opa_string_terminated("a"), opa_set()), NULL) == 0);
|
|
|
|
test("jsonfilter/error (invalid first operand - number)", opa_value_compare(builtin_json_filter(opa_number_int(22), opa_set()), NULL) == 0);
|
|
|
|
test("jsonfilter/error (invalid first operand - boolean)", opa_value_compare(builtin_json_filter(opa_boolean(true), opa_set()), NULL) == 0);
|
|
|
|
test("jsonfilter/error (invalid first operand - array)", opa_value_compare(builtin_json_filter(opa_array(), opa_set()), NULL) == 0);
|
|
|
|
test("jsonfilter/error (invalid second operand - string)", opa_value_compare(builtin_json_filter(opa_object(), opa_string_terminated("a")), NULL) == 0);
|
|
|
|
test("jsonfilter/error (invalid second operand - number)", opa_value_compare(builtin_json_filter(opa_object(), opa_number_int(22)), NULL) == 0);
|
|
|
|
test("jsonfilter/error (invalid second operand - boolean)", opa_value_compare(builtin_json_filter(opa_object(), opa_boolean(true)), NULL) == 0);
|
|
|
|
test("jsonfilter/error (invalid second operand - object)", opa_value_compare(builtin_json_filter(opa_object(), opa_object()), NULL) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_builtin_graph_reachable)
|
|
void test_builtin_graph_reachable(void)
|
|
{
|
|
|
|
test("reachable/malformed graph", opa_value_compare(builtin_graph_reachable(opa_set(), opa_set()), NULL) == 0);
|
|
|
|
opa_object_t *graph1 = opa_cast_object(opa_object());
|
|
opa_set_t *initial1 = opa_cast_set(opa_set());
|
|
opa_set_add(initial1, opa_string_terminated("a"));
|
|
|
|
test("reachable/empty", opa_value_compare(builtin_graph_reachable(&graph1->hdr, &initial1->hdr), opa_set()) == 0);
|
|
|
|
// graph -> {"a": {"b"}, "b": {"c"}, "c": {"a"}}
|
|
opa_set_t *vertex1_1 = opa_cast_set(opa_set());
|
|
opa_set_add(vertex1_1, opa_string_terminated("b"));
|
|
opa_object_insert(graph1, opa_string_terminated("a"), &vertex1_1->hdr);
|
|
|
|
opa_set_t *vertex2_1 = opa_cast_set(opa_set());
|
|
opa_set_add(vertex2_1, opa_string_terminated("c"));
|
|
opa_object_insert(graph1, opa_string_terminated("b"), &vertex2_1->hdr);
|
|
|
|
opa_set_t *vertex3_1 = opa_cast_set(opa_set());
|
|
opa_set_add(vertex3_1, opa_string_terminated("a"));
|
|
opa_object_insert(graph1, opa_string_terminated("c"), &vertex3_1->hdr);
|
|
|
|
opa_set_t *expected1 = opa_cast_set(opa_set());
|
|
opa_set_add(expected1, opa_string_terminated("a"));
|
|
opa_set_add(expected1, opa_string_terminated("b"));
|
|
opa_set_add(expected1, opa_string_terminated("c"));
|
|
|
|
test("reachable/cycle", opa_value_compare(builtin_graph_reachable(&graph1->hdr, &initial1->hdr), &expected1->hdr) == 0);
|
|
|
|
// graph -> {"a": {"b", "c"}, "b": {"d"}, "c": {"d"}, "d": {}, "e": {"f"}, "f": {"e"}, "x": {"x"}}
|
|
opa_object_t *graph2 = opa_cast_object(opa_object());
|
|
opa_set_t *initial2 = opa_cast_set(opa_set());
|
|
opa_set_add(initial2, opa_string_terminated("b"));
|
|
opa_set_add(initial2, opa_string_terminated("e"));
|
|
|
|
opa_set_t *vertex1_2 = opa_cast_set(opa_set());
|
|
opa_set_add(vertex1_2, opa_string_terminated("b"));
|
|
opa_set_add(vertex1_2, opa_string_terminated("c"));
|
|
opa_object_insert(graph2, opa_string_terminated("a"), &vertex1_2->hdr);
|
|
|
|
opa_set_t *vertex2_2 = opa_cast_set(opa_set());
|
|
opa_set_add(vertex2_2, opa_string_terminated("d"));
|
|
opa_object_insert(graph2, opa_string_terminated("b"), &vertex2_2->hdr);
|
|
opa_object_insert(graph2, opa_string_terminated("c"), &vertex2_2->hdr);
|
|
|
|
opa_object_insert(graph2, opa_string_terminated("d"), opa_set());
|
|
|
|
opa_set_t *vertex3_2 = opa_cast_set(opa_set());
|
|
opa_set_add(vertex3_2, opa_string_terminated("f"));
|
|
opa_object_insert(graph2, opa_string_terminated("e"), &vertex3_2->hdr);
|
|
|
|
opa_set_t *vertex4_2 = opa_cast_set(opa_set());
|
|
opa_set_add(vertex4_2, opa_string_terminated("e"));
|
|
opa_object_insert(graph2, opa_string_terminated("f"), &vertex4_2->hdr);
|
|
|
|
opa_set_t *vertex5_2 = opa_cast_set(opa_set());
|
|
opa_set_add(vertex5_2, opa_string_terminated("x"));
|
|
opa_object_insert(graph2, opa_string_terminated("x"), &vertex5_2->hdr);
|
|
|
|
opa_set_t *expected2 = opa_cast_set(opa_set());
|
|
opa_set_add(expected2, opa_string_terminated("b"));
|
|
opa_set_add(expected2, opa_string_terminated("d"));
|
|
opa_set_add(expected2, opa_string_terminated("e"));
|
|
opa_set_add(expected2, opa_string_terminated("f"));
|
|
|
|
test("reachable/components", opa_value_compare(builtin_graph_reachable(&graph2->hdr, &initial2->hdr), &expected2->hdr) == 0);
|
|
|
|
// graph -> {"a": ["b"], "b": ["c"], "c": ["a"]}
|
|
opa_object_t *graph3 = opa_cast_object(opa_object());
|
|
opa_array_t *initial3 = opa_cast_array(opa_array());
|
|
opa_array_append(initial3, opa_string_terminated("a"));
|
|
|
|
opa_array_t *vertex1_3 = opa_cast_array(opa_array());
|
|
opa_array_append(vertex1_3, opa_string_terminated("b"));
|
|
opa_object_insert(graph3, opa_string_terminated("a"), &vertex1_3->hdr);
|
|
|
|
opa_array_t *vertex2_3 = opa_cast_array(opa_array());
|
|
opa_array_append(vertex2_3, opa_string_terminated("c"));
|
|
opa_object_insert(graph3, opa_string_terminated("b"), &vertex2_3->hdr);
|
|
|
|
opa_array_t *vertex3_3 = opa_cast_array(opa_array());
|
|
opa_array_append(vertex3_3, opa_string_terminated("a"));
|
|
opa_object_insert(graph3, opa_string_terminated("c"), &vertex3_3->hdr);
|
|
|
|
opa_set_t *expected3 = opa_cast_set(opa_set());
|
|
opa_set_add(expected3, opa_string_terminated("a"));
|
|
opa_set_add(expected3, opa_string_terminated("b"));
|
|
opa_set_add(expected3, opa_string_terminated("c"));
|
|
|
|
test("reachable/arrays", opa_value_compare(builtin_graph_reachable(&graph3->hdr, &initial3->hdr), &expected3->hdr) == 0);
|
|
|
|
test("reachable/malformed initial nodes", opa_value_compare(builtin_graph_reachable(&graph3->hdr, opa_string_terminated("foo")), NULL) == 0);
|
|
|
|
// graph -> {"a": null}
|
|
opa_object_t *graph4 = opa_cast_object(opa_object());
|
|
opa_object_insert(graph4, opa_string_terminated("a"), opa_null());
|
|
|
|
opa_set_t *expected4 = opa_cast_set(opa_set());
|
|
opa_set_add(expected4, opa_string_terminated("a"));
|
|
|
|
test("reachable/null edge", opa_value_compare(builtin_graph_reachable(&graph4->hdr, &initial3->hdr), &expected4->hdr) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_strings)
|
|
void test_strings(void)
|
|
{
|
|
opa_array_t *any_prefix_match_string_arr_1 = opa_cast_array(opa_array());
|
|
opa_array_append(any_prefix_match_string_arr_1, opa_string_terminated("a/b/c"));
|
|
opa_array_append(any_prefix_match_string_arr_1, opa_string_terminated("e/f/g"));
|
|
|
|
opa_array_t *any_prefix_match_prefixes_arr_11 = opa_cast_array(opa_array());
|
|
opa_array_append(any_prefix_match_prefixes_arr_11, opa_string_terminated("g/b"));
|
|
opa_array_append(any_prefix_match_prefixes_arr_11, opa_string_terminated("a/"));
|
|
|
|
opa_array_t *any_prefix_match_prefixes_arr_12 = opa_cast_array(opa_array());
|
|
opa_array_append(any_prefix_match_prefixes_arr_12, opa_string_terminated("g/b"));
|
|
opa_array_append(any_prefix_match_prefixes_arr_12, opa_string_terminated("b/"));
|
|
|
|
opa_array_t *any_prefix_match_string_arr_2 = opa_cast_array(opa_array());
|
|
opa_array_t *any_prefix_match_prefixes_arr_2 = opa_cast_array(opa_array());
|
|
|
|
opa_set_t *any_prefix_match_string_set_1 = opa_cast_set(opa_set());
|
|
opa_set_add(any_prefix_match_string_set_1, opa_string_terminated("a/b/c"));
|
|
opa_set_add(any_prefix_match_string_set_1, opa_string_terminated("e/f/g"));
|
|
|
|
opa_set_t *any_prefix_match_prefixes_set_11 = opa_cast_set(opa_set());
|
|
opa_set_add(any_prefix_match_prefixes_set_11, opa_string_terminated("g/b"));
|
|
opa_set_add(any_prefix_match_prefixes_set_11, opa_string_terminated("a/"));
|
|
|
|
opa_set_t *any_prefix_match_prefixes_set_12 = opa_cast_set(opa_set());
|
|
opa_set_add(any_prefix_match_prefixes_set_12, opa_string_terminated("g/b"));
|
|
opa_set_add(any_prefix_match_prefixes_set_12, opa_string_terminated("b/"));
|
|
|
|
opa_set_t *any_prefix_match_string_set_2 = opa_cast_set(opa_set());
|
|
opa_set_t *any_prefix_match_prefixes_set_2 = opa_cast_set(opa_set());
|
|
|
|
test("any_prefix_match/__", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated(""), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("any_prefix_match/_a", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated(""), opa_string_terminated("a")), opa_boolean(false)) == 0);
|
|
test("any_prefix_match/a_", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("a"), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("any_prefix_match/aa", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("a"), opa_string_terminated("a")), opa_boolean(true)) == 0);
|
|
test("any_prefix_match/ab", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("a"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("any_prefix_match/aab", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("a"), opa_string_terminated("ab")), opa_boolean(false)) == 0);
|
|
test("any_prefix_match/aba", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("ab"), opa_string_terminated("a")), opa_boolean(true)) == 0);
|
|
test("any_prefix_match/aab", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("aa"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("any_prefix_match/abab", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("ab"), opa_string_terminated("ab")), opa_boolean(true)) == 0);
|
|
test("any_prefix_match/abaa", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("ab"), opa_string_terminated("aa")), opa_boolean(false)) == 0);
|
|
test("any_prefix_match/abcab", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("abc"), opa_string_terminated("ab")), opa_boolean(true)) == 0);
|
|
test("any_prefix_match/abcac", opa_value_compare(opa_strings_any_prefix_match(opa_string_terminated("abc"), opa_string_terminated("ac")), opa_boolean(false)) == 0);
|
|
test("any_prefix_match/arr11", opa_value_compare(opa_strings_any_prefix_match(&any_prefix_match_string_arr_1->hdr, &any_prefix_match_prefixes_arr_11->hdr), opa_boolean(true)) == 0);
|
|
test("any_prefix_match/arr12", opa_value_compare(opa_strings_any_prefix_match(&any_prefix_match_string_arr_1->hdr, &any_prefix_match_prefixes_arr_12->hdr), opa_boolean(false)) == 0);
|
|
test("any_prefix_match/arr2", opa_value_compare(opa_strings_any_prefix_match(&any_prefix_match_string_arr_2->hdr, &any_prefix_match_prefixes_arr_2->hdr), opa_boolean(false)) == 0);
|
|
test("any_prefix_match/set11", opa_value_compare(opa_strings_any_prefix_match(&any_prefix_match_string_set_1->hdr, &any_prefix_match_prefixes_set_11->hdr), opa_boolean(true)) == 0);
|
|
test("any_prefix_match/set12", opa_value_compare(opa_strings_any_prefix_match(&any_prefix_match_string_set_1->hdr, &any_prefix_match_prefixes_set_12->hdr), opa_boolean(false)) == 0);
|
|
test("any_prefix_match/set2", opa_value_compare(opa_strings_any_prefix_match(&any_prefix_match_string_set_2->hdr, &any_prefix_match_prefixes_set_2->hdr), opa_boolean(false)) == 0);
|
|
|
|
opa_array_t *any_suffix_match_string_arr_1 = opa_cast_array(opa_array());
|
|
opa_array_append(any_suffix_match_string_arr_1, opa_string_terminated("a/b/c"));
|
|
opa_array_append(any_suffix_match_string_arr_1, opa_string_terminated("e/f/g"));
|
|
|
|
opa_array_t *any_suffix_match_suffixes_arr_11 = opa_cast_array(opa_array());
|
|
opa_array_append(any_suffix_match_suffixes_arr_11, opa_string_terminated("g/b"));
|
|
opa_array_append(any_suffix_match_suffixes_arr_11, opa_string_terminated("/c"));
|
|
|
|
opa_array_t *any_suffix_match_suffixes_arr_12 = opa_cast_array(opa_array());
|
|
opa_array_append(any_suffix_match_suffixes_arr_12, opa_string_terminated("g/b"));
|
|
opa_array_append(any_suffix_match_suffixes_arr_12, opa_string_terminated("/b"));
|
|
|
|
opa_array_t *any_suffix_match_string_arr_2 = opa_cast_array(opa_array());
|
|
opa_array_t *any_suffix_match_suffixes_arr_2 = opa_cast_array(opa_array());
|
|
|
|
opa_set_t *any_suffix_match_string_set_1 = opa_cast_set(opa_set());
|
|
opa_set_add(any_suffix_match_string_set_1, opa_string_terminated("a/b/c"));
|
|
opa_set_add(any_suffix_match_string_set_1, opa_string_terminated("e/f/g"));
|
|
|
|
opa_set_t *any_suffix_match_suffixes_set_11 = opa_cast_set(opa_set());
|
|
opa_set_add(any_suffix_match_suffixes_set_11, opa_string_terminated("g/b"));
|
|
opa_set_add(any_suffix_match_suffixes_set_11, opa_string_terminated("/c"));
|
|
|
|
opa_set_t *any_suffix_match_suffixes_set_12 = opa_cast_set(opa_set());
|
|
opa_set_add(any_suffix_match_suffixes_set_12, opa_string_terminated("g/b"));
|
|
opa_set_add(any_suffix_match_suffixes_set_12, opa_string_terminated("/b"));
|
|
|
|
opa_set_t *any_suffix_match_string_set_2 = opa_cast_set(opa_set());
|
|
opa_set_t *any_suffix_match_suffixes_set_2 = opa_cast_set(opa_set());
|
|
|
|
test("any_suffix_match/__", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated(""), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("any_suffix_match/_a", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated(""), opa_string_terminated("a")), opa_boolean(false)) == 0);
|
|
test("any_suffix_match/a_", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("a"), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("any_suffix_match/aa", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("a"), opa_string_terminated("a")), opa_boolean(true)) == 0);
|
|
test("any_suffix_match/ab", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("a"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("any_suffix_match/aab", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("a"), opa_string_terminated("ab")), opa_boolean(false)) == 0);
|
|
test("any_suffix_match/abb", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("ab"), opa_string_terminated("b")), opa_boolean(true)) == 0);
|
|
test("any_suffix_match/aab", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("aa"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("any_suffix_match/abab", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("ab"), opa_string_terminated("ab")), opa_boolean(true)) == 0);
|
|
test("any_suffix_match/abaa", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("ab"), opa_string_terminated("aa")), opa_boolean(false)) == 0);
|
|
test("any_suffix_match/abcbc", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("abc"), opa_string_terminated("bc")), opa_boolean(true)) == 0);
|
|
test("any_suffix_match/abcbd", opa_value_compare(opa_strings_any_suffix_match(opa_string_terminated("abc"), opa_string_terminated("bd")), opa_boolean(false)) == 0);
|
|
test("any_suffix_match/arr11", opa_value_compare(opa_strings_any_suffix_match(&any_suffix_match_string_arr_1->hdr, &any_suffix_match_suffixes_arr_11->hdr), opa_boolean(true)) == 0);
|
|
test("any_suffix_match/arr12", opa_value_compare(opa_strings_any_suffix_match(&any_suffix_match_string_arr_1->hdr, &any_suffix_match_suffixes_arr_12->hdr), opa_boolean(false)) == 0);
|
|
test("any_suffix_match/arr2", opa_value_compare(opa_strings_any_suffix_match(&any_suffix_match_string_arr_2->hdr, &any_suffix_match_suffixes_arr_2->hdr), opa_boolean(false)) == 0);
|
|
test("any_suffix_match/set11", opa_value_compare(opa_strings_any_suffix_match(&any_suffix_match_string_set_1->hdr, &any_suffix_match_suffixes_set_11->hdr), opa_boolean(true)) == 0);
|
|
test("any_suffix_match/set12", opa_value_compare(opa_strings_any_suffix_match(&any_suffix_match_string_set_1->hdr, &any_suffix_match_suffixes_set_12->hdr), opa_boolean(false)) == 0);
|
|
test("any_suffix_match/set2", opa_value_compare(opa_strings_any_suffix_match(&any_suffix_match_string_set_2->hdr, &any_suffix_match_suffixes_set_2->hdr), opa_boolean(false)) == 0);
|
|
|
|
opa_value *join = opa_string_terminated("--");
|
|
|
|
opa_array_t *arr0 = opa_cast_array(opa_array());
|
|
|
|
opa_array_t *arr1 = opa_cast_array(opa_array());
|
|
opa_array_append(arr1, opa_string_terminated("foo"));
|
|
|
|
opa_array_t *arr2 = opa_cast_array(opa_array());
|
|
opa_array_append(arr2, opa_string_terminated("foo"));
|
|
opa_array_append(arr2, opa_string_terminated("bar"));
|
|
|
|
opa_set_t *set0 = opa_cast_set(opa_set());
|
|
|
|
opa_set_t *set1 = opa_cast_set(opa_set());
|
|
opa_set_add(set1, opa_string_terminated("foo"));
|
|
|
|
opa_set_t *set2 = opa_cast_set(opa_set());
|
|
opa_set_add(set2, opa_string_terminated("foo"));
|
|
opa_set_add(set2, opa_string_terminated("bar"));
|
|
|
|
test("concat/array0", opa_value_compare(opa_strings_concat(join, &arr0->hdr), opa_string_terminated("")) == 0);
|
|
test("concat/array1", opa_value_compare(opa_strings_concat(join, &arr1->hdr), opa_string_terminated("foo")) == 0);
|
|
test("concat/array2", opa_value_compare(opa_strings_concat(join, &arr2->hdr), opa_string_terminated("foo--bar")) == 0);
|
|
test("concat/set0", opa_value_compare(opa_strings_concat(join, &set0->hdr), opa_string_terminated("")) == 0);
|
|
test("concat/set1", opa_value_compare(opa_strings_concat(join, &set1->hdr), opa_string_terminated("foo")) == 0);
|
|
test("concat/set2", opa_value_compare(opa_strings_concat(join, &set2->hdr), opa_string_terminated("bar--foo")) == 0);
|
|
|
|
test("contains/__", opa_value_compare(opa_strings_contains(opa_string_terminated(""), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("contains/_a", opa_value_compare(opa_strings_contains(opa_string_terminated(""), opa_string_terminated("a")), opa_boolean(false)) == 0);
|
|
test("contains/a_", opa_value_compare(opa_strings_contains(opa_string_terminated("a"), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("contains/aa", opa_value_compare(opa_strings_contains(opa_string_terminated("a"), opa_string_terminated("a")), opa_boolean(true)) == 0);
|
|
test("contains/ab", opa_value_compare(opa_strings_contains(opa_string_terminated("a"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("contains/aab", opa_value_compare(opa_strings_contains(opa_string_terminated("a"), opa_string_terminated("ab")), opa_boolean(false)) == 0);
|
|
test("contains/abb", opa_value_compare(opa_strings_contains(opa_string_terminated("ab"), opa_string_terminated("b")), opa_boolean(true)) == 0);
|
|
test("contains/aab", opa_value_compare(opa_strings_contains(opa_string_terminated("aa"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("contains/abab", opa_value_compare(opa_strings_contains(opa_string_terminated("ab"), opa_string_terminated("ab")), opa_boolean(true)) == 0);
|
|
test("contains/abaa", opa_value_compare(opa_strings_contains(opa_string_terminated("ab"), opa_string_terminated("aa")), opa_boolean(false)) == 0);
|
|
test("contains/abcbc", opa_value_compare(opa_strings_contains(opa_string_terminated("abc"), opa_string_terminated("bc")), opa_boolean(true)) == 0);
|
|
test("contains/abcbd", opa_value_compare(opa_strings_contains(opa_string_terminated("abc"), opa_string_terminated("bd")), opa_boolean(false)) == 0);
|
|
|
|
test("endswith/__", opa_value_compare(opa_strings_endswith(opa_string_terminated(""), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("endswith/_a", opa_value_compare(opa_strings_endswith(opa_string_terminated(""), opa_string_terminated("a")), opa_boolean(false)) == 0);
|
|
test("endswith/a_", opa_value_compare(opa_strings_endswith(opa_string_terminated("a"), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("endswith/aa", opa_value_compare(opa_strings_endswith(opa_string_terminated("a"), opa_string_terminated("a")), opa_boolean(true)) == 0);
|
|
test("endswith/ab", opa_value_compare(opa_strings_endswith(opa_string_terminated("a"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("endswith/aab", opa_value_compare(opa_strings_endswith(opa_string_terminated("a"), opa_string_terminated("ab")), opa_boolean(false)) == 0);
|
|
test("endswith/abb", opa_value_compare(opa_strings_endswith(opa_string_terminated("ab"), opa_string_terminated("b")), opa_boolean(true)) == 0);
|
|
test("endswith/aab", opa_value_compare(opa_strings_endswith(opa_string_terminated("aa"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("endswith/abab", opa_value_compare(opa_strings_endswith(opa_string_terminated("ab"), opa_string_terminated("ab")), opa_boolean(true)) == 0);
|
|
test("endswith/abaa", opa_value_compare(opa_strings_endswith(opa_string_terminated("ab"), opa_string_terminated("aa")), opa_boolean(false)) == 0);
|
|
test("endswith/abcbc", opa_value_compare(opa_strings_endswith(opa_string_terminated("abc"), opa_string_terminated("bc")), opa_boolean(true)) == 0);
|
|
test("endswith/abcbd", opa_value_compare(opa_strings_endswith(opa_string_terminated("abc"), opa_string_terminated("bd")), opa_boolean(false)) == 0);
|
|
|
|
test("format_int/2_0", opa_value_compare(opa_strings_format_int(opa_number_float(0), opa_number_int(2)), opa_string_terminated("0")) == 0);
|
|
test("format_int/2_1", opa_value_compare(opa_strings_format_int(opa_number_float(1), opa_number_int(2)), opa_string_terminated("1")) == 0);
|
|
test("format_int/2_-1", opa_value_compare(opa_strings_format_int(opa_number_float(-1), opa_number_int(2)), opa_string_terminated("-1")) == 0);
|
|
test("format_int/2_2", opa_value_compare(opa_strings_format_int(opa_number_float(2), opa_number_int(2)), opa_string_terminated("10")) == 0);
|
|
test("format_int/2_7", opa_value_compare(opa_strings_format_int(opa_number_float(7), opa_number_int(2)), opa_string_terminated("111")) == 0);
|
|
test("format_int/8_0", opa_value_compare(opa_strings_format_int(opa_number_float(0), opa_number_int(8)), opa_string_terminated("0")) == 0);
|
|
test("format_int/8_1", opa_value_compare(opa_strings_format_int(opa_number_float(1), opa_number_int(8)), opa_string_terminated("1")) == 0);
|
|
test("format_int/8_-1", opa_value_compare(opa_strings_format_int(opa_number_float(-1), opa_number_int(8)), opa_string_terminated("-1")) == 0);
|
|
test("format_int/8_8", opa_value_compare(opa_strings_format_int(opa_number_float(8), opa_number_int(8)), opa_string_terminated("10")) == 0);
|
|
test("format_int/8_9", opa_value_compare(opa_strings_format_int(opa_number_float(9), opa_number_int(8)), opa_string_terminated("11")) == 0);
|
|
test("format_int/10_0", opa_value_compare(opa_strings_format_int(opa_number_float(0), opa_number_int(10)), opa_string_terminated("0")) == 0);
|
|
test("format_int/10_1", opa_value_compare(opa_strings_format_int(opa_number_float(1), opa_number_int(10)), opa_string_terminated("1")) == 0);
|
|
test("format_int/10_-1", opa_value_compare(opa_strings_format_int(opa_number_float(-1), opa_number_int(10)), opa_string_terminated("-1")) == 0);
|
|
test("format_int/10_10", opa_value_compare(opa_strings_format_int(opa_number_float(10), opa_number_int(10)), opa_string_terminated("10")) == 0);
|
|
test("format_int/10_11", opa_value_compare(opa_strings_format_int(opa_number_float(11), opa_number_int(10)), opa_string_terminated("11")) == 0);
|
|
test("format_int/16_0", opa_value_compare(opa_strings_format_int(opa_number_float(0), opa_number_int(16)), opa_string_terminated("0")) == 0);
|
|
test("format_int/16_1", opa_value_compare(opa_strings_format_int(opa_number_float(1), opa_number_int(16)), opa_string_terminated("1")) == 0);
|
|
test("format_int/16_-1", opa_value_compare(opa_strings_format_int(opa_number_float(-1), opa_number_int(16)), opa_string_terminated("-1")) == 0);
|
|
test("format_int/16_15.5", opa_value_compare(opa_strings_format_int(opa_number_float(15.5), opa_number_int(16)), opa_string_terminated("f")) == 0);
|
|
test("format_int/16_-15.5", opa_value_compare(opa_strings_format_int(opa_number_float(-15.5), opa_number_int(16)), opa_string_terminated("-f")) == 0);
|
|
test("format_int/16_16", opa_value_compare(opa_strings_format_int(opa_number_float(16), opa_number_int(16)), opa_string_terminated("10")) == 0);
|
|
test("format_int/16_31", opa_value_compare(opa_strings_format_int(opa_number_float(31), opa_number_int(16)), opa_string_terminated("1f")) == 0);
|
|
|
|
test("indexof/__", opa_value_compare(opa_strings_indexof(opa_string_terminated(""), opa_string_terminated("")), opa_number_int(0)) == 0);
|
|
test("indexof/_a", opa_value_compare(opa_strings_indexof(opa_string_terminated(""), opa_string_terminated("a")), opa_number_int(-1)) == 0);
|
|
test("indexof/a_", opa_value_compare(opa_strings_indexof(opa_string_terminated("a"), opa_string_terminated("")), opa_number_int(0)) == 0);
|
|
test("indexof/aa", opa_value_compare(opa_strings_indexof(opa_string_terminated("a"), opa_string_terminated("a")), opa_number_int(0)) == 0);
|
|
test("indexof/ab", opa_value_compare(opa_strings_indexof(opa_string_terminated("a"), opa_string_terminated("b")), opa_number_int(-1)) == 0);
|
|
test("indexof/aab", opa_value_compare(opa_strings_indexof(opa_string_terminated("a"), opa_string_terminated("ab")), opa_number_int(-1)) == 0);
|
|
test("indexof/abb", opa_value_compare(opa_strings_indexof(opa_string_terminated("ab"), opa_string_terminated("b")), opa_number_int(1)) == 0);
|
|
test("indexof/aab", opa_value_compare(opa_strings_indexof(opa_string_terminated("aa"), opa_string_terminated("b")), opa_number_int(-1)) == 0);
|
|
test("indexof/abab", opa_value_compare(opa_strings_indexof(opa_string_terminated("ab"), opa_string_terminated("ab")), opa_number_int(0)) == 0);
|
|
test("indexof/abaa", opa_value_compare(opa_strings_indexof(opa_string_terminated("ab"), opa_string_terminated("aa")), opa_number_int(-1)) == 0);
|
|
test("indexof/abcbc", opa_value_compare(opa_strings_indexof(opa_string_terminated("abc"), opa_string_terminated("bc")), opa_number_int(1)) == 0);
|
|
test("indexof/abcbd", opa_value_compare(opa_strings_indexof(opa_string_terminated("abc"), opa_string_terminated("bd")), opa_number_int(-1)) == 0);
|
|
test("indexof/unicode", opa_value_compare(opa_strings_indexof(opa_string_terminated("\xC3\xA5\xC3\xA4\xC3\xB6"), opa_string_terminated("\xC3\xB6")), opa_number_int(2)) == 0);
|
|
|
|
test("replace/___", opa_value_compare(opa_strings_replace(opa_string_terminated(""), opa_string_terminated(""), opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
test("replace/_ab", opa_value_compare(opa_strings_replace(opa_string_terminated(""), opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("")) == 0);
|
|
test("replace/aab", opa_value_compare(opa_strings_replace(opa_string_terminated("a"), opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("b")) == 0);
|
|
test("replace/cab", opa_value_compare(opa_strings_replace(opa_string_terminated("c"), opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("c")) == 0);
|
|
test("replace/aaab", opa_value_compare(opa_strings_replace(opa_string_terminated("aa"), opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("bb")) == 0);
|
|
test("replace/acaab", opa_value_compare(opa_strings_replace(opa_string_terminated("aca"), opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("bcb")) == 0);
|
|
test("replace/acaabd", opa_value_compare(opa_strings_replace(opa_string_terminated("aca"), opa_string_terminated("a"), opa_string_terminated("bd")), opa_string_terminated("bdcbd")) == 0);
|
|
test("replace/cacab", opa_value_compare(opa_strings_replace(opa_string_terminated("cac"), opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("cbc")) == 0);
|
|
test("replace/cacabd", opa_value_compare(opa_strings_replace(opa_string_terminated("cac"), opa_string_terminated("a"), opa_string_terminated("bd")), opa_string_terminated("cbdc")) == 0);
|
|
|
|
test("reverse/abc", opa_value_compare(opa_strings_reverse(opa_string_terminated("abc")), opa_string_terminated("cba")) == 0);
|
|
test("reverse/unicode", opa_value_compare(opa_strings_reverse(opa_string_terminated("1😀𝛾")), opa_string_terminated("𝛾😀1"))== 0);
|
|
test("reverse/___", opa_value_compare(opa_strings_reverse(opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("a"), opa_string_terminated("b"));
|
|
opa_object_insert(obj2, opa_string_terminated("c"), opa_string_terminated("d"));
|
|
|
|
test("replace_n/empty", opa_value_compare(opa_strings_replace_n(opa_object(), opa_string_terminated("a")), opa_string_terminated("a")) == 0);
|
|
test("replace_n/two", opa_value_compare(opa_strings_replace_n(&obj2->hdr, opa_string_terminated("ac")), opa_string_terminated("bd")) == 0);
|
|
|
|
opa_array_t *arr2b = opa_cast_array(opa_array());
|
|
opa_array_append(arr2b, opa_string_terminated(""));
|
|
opa_array_append(arr2b, opa_string_terminated("foo"));
|
|
|
|
opa_array_t *arr2c = opa_cast_array(opa_array());
|
|
opa_array_append(arr2c, opa_string_terminated("foo"));
|
|
opa_array_append(arr2c, opa_string_terminated(""));
|
|
|
|
opa_array_t *arr3 = opa_cast_array(opa_array());
|
|
opa_array_append(arr3, opa_string_terminated("foo"));
|
|
opa_array_append(arr3, opa_string_terminated("bar"));
|
|
opa_array_append(arr3, opa_string_terminated("baz"));
|
|
|
|
test("split/one", opa_value_compare(opa_strings_split(opa_string_terminated("foo"), opa_string_terminated(",")), &arr1->hdr) == 0);
|
|
test("split/two_a", opa_value_compare(opa_strings_split(opa_string_terminated("foo,bar"), opa_string_terminated(",")), &arr2->hdr) == 0);
|
|
test("split/two_b", opa_value_compare(opa_strings_split(opa_string_terminated(",,foo"), opa_string_terminated(",,")), &arr2b->hdr) == 0);
|
|
test("split/two_c", opa_value_compare(opa_strings_split(opa_string_terminated("foo,,"), opa_string_terminated(",,")), &arr2c->hdr) == 0);
|
|
test("split/three", opa_value_compare(opa_strings_split(opa_string_terminated("foo,,bar,,baz"), opa_string_terminated(",,")), &arr3->hdr) == 0);
|
|
|
|
opa_array_t *arr4 = opa_cast_array(opa_array());
|
|
opa_array_append(arr4, opa_string_terminated("f"));
|
|
opa_array_append(arr4, opa_string_terminated("o"));
|
|
opa_array_append(arr4, opa_string_terminated("o"));
|
|
|
|
opa_array_t *arr5 = opa_cast_array(opa_array());
|
|
opa_array_append(arr5, opa_string_terminated("f"));
|
|
opa_array_append(arr5, opa_string_terminated("\xE2\x82\xAC")); // euro symbol
|
|
opa_array_append(arr5, opa_string_terminated("o"));
|
|
|
|
test("split/ascii", opa_value_compare(opa_strings_split(opa_string_terminated("foo"), opa_string_terminated("")), &arr4->hdr) == 0);
|
|
test("split/utf8", opa_value_compare(opa_strings_split(opa_string_terminated("f\xE2\x82\xACo"), opa_string_terminated("")), &arr5->hdr) == 0);
|
|
|
|
opa_array_t *arr6 = opa_cast_array(opa_array());
|
|
opa_array_append(arr6, opa_string_terminated(""));
|
|
test("split/empty", opa_value_compare(opa_strings_split(opa_string_terminated(""), opa_string_terminated(",")), &arr6->hdr) == 0);
|
|
|
|
test("startswith/__", opa_value_compare(opa_strings_startswith(opa_string_terminated(""), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("startswith/_a", opa_value_compare(opa_strings_startswith(opa_string_terminated(""), opa_string_terminated("a")), opa_boolean(false)) == 0);
|
|
test("startswith/a_", opa_value_compare(opa_strings_startswith(opa_string_terminated("a"), opa_string_terminated("")), opa_boolean(true)) == 0);
|
|
test("startswith/aa", opa_value_compare(opa_strings_startswith(opa_string_terminated("a"), opa_string_terminated("a")), opa_boolean(true)) == 0);
|
|
test("startswith/ab", opa_value_compare(opa_strings_startswith(opa_string_terminated("a"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("startswith/aab", opa_value_compare(opa_strings_startswith(opa_string_terminated("a"), opa_string_terminated("ab")), opa_boolean(false)) == 0);
|
|
test("startswith/aba", opa_value_compare(opa_strings_startswith(opa_string_terminated("ab"), opa_string_terminated("a")), opa_boolean(true)) == 0);
|
|
test("startswith/aab", opa_value_compare(opa_strings_startswith(opa_string_terminated("aa"), opa_string_terminated("b")), opa_boolean(false)) == 0);
|
|
test("startswith/abab", opa_value_compare(opa_strings_startswith(opa_string_terminated("ab"), opa_string_terminated("ab")), opa_boolean(true)) == 0);
|
|
test("startswith/abaa", opa_value_compare(opa_strings_startswith(opa_string_terminated("ab"), opa_string_terminated("aa")), opa_boolean(false)) == 0);
|
|
test("startswith/abcab", opa_value_compare(opa_strings_startswith(opa_string_terminated("abc"), opa_string_terminated("ab")), opa_boolean(true)) == 0);
|
|
test("startswith/abcac", opa_value_compare(opa_strings_startswith(opa_string_terminated("abc"), opa_string_terminated("ac")), opa_boolean(false)) == 0);
|
|
|
|
test("substring/_00", opa_value_compare(opa_strings_substring(opa_string_terminated(""), opa_number_int(0), opa_number_int(0)), opa_string_terminated("")) == 0);
|
|
test("substring/_0-1", opa_value_compare(opa_strings_substring(opa_string_terminated(""), opa_number_int(0), opa_number_int(-1)), opa_string_terminated("")) == 0);
|
|
test("substring/_10", opa_value_compare(opa_strings_substring(opa_string_terminated(""), opa_number_int(1), opa_number_int(0)), opa_string_terminated("")) == 0);
|
|
test("substring/_1-1", opa_value_compare(opa_strings_substring(opa_string_terminated(""), opa_number_int(1), opa_number_int(-1)), opa_string_terminated("")) == 0);
|
|
test("substring/abc1-1", opa_value_compare(opa_strings_substring(opa_string_terminated("abc"), opa_number_int(1), opa_number_int(-1)), opa_string_terminated("bc")) == 0);
|
|
test("substring/abc10", opa_value_compare(opa_strings_substring(opa_string_terminated("abc"), opa_number_int(1), opa_number_int(0)), opa_string_terminated("")) == 0);
|
|
test("substring/abc11", opa_value_compare(opa_strings_substring(opa_string_terminated("abc"), opa_number_int(1), opa_number_int(1)), opa_string_terminated("b")) == 0);
|
|
test("substring/abc12", opa_value_compare(opa_strings_substring(opa_string_terminated("abc"), opa_number_int(1), opa_number_int(2)), opa_string_terminated("bc")) == 0);
|
|
test("substring/abc41", opa_value_compare(opa_strings_substring(opa_string_terminated("abc"), opa_number_int(4), opa_number_int(1)), opa_string_terminated("")) == 0);
|
|
test("substring/unicode", opa_value_compare(opa_strings_substring(opa_string_terminated("\xC3\xA5\xC3\xA4\xC3\xB6\x7A"), opa_number_int(1), opa_number_int(1)), opa_string_terminated("\xC3\xA4")) == 0);
|
|
test("substring/unicode", opa_value_compare(opa_strings_substring(opa_string_terminated("\xC3\xA5\xC3\xA4\xC3\xB6\x7A"), opa_number_int(1), opa_number_int(2)), opa_string_terminated("\xC3\xA4\xC3\xB6")) == 0);
|
|
test("substring/unicode", opa_value_compare(opa_strings_substring(opa_string_terminated("\xC3\xA5\xC3\xA4\xC3\xB6\x7A"), opa_number_int(2), opa_number_int(-1)), opa_string_terminated("\xC3\xB6\x7A")) == 0);
|
|
|
|
test("trim/__", opa_value_compare(opa_strings_trim(opa_string_terminated(""), opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
test("trim/abcba", opa_value_compare(opa_strings_trim(opa_string_terminated("abc"), opa_string_terminated("ba")), opa_string_terminated("c")) == 0);
|
|
|
|
test("trim_left/__", opa_value_compare(opa_strings_trim_left(opa_string_terminated(""), opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
test("trim_left/_a", opa_value_compare(opa_strings_trim_left(opa_string_terminated(""), opa_string_terminated("a")), opa_string_terminated("")) == 0);
|
|
test("trim_left/a_", opa_value_compare(opa_strings_trim_left(opa_string_terminated("a"), opa_string_terminated("")), opa_string_terminated("a")) == 0);
|
|
test("trim_left/aa", opa_value_compare(opa_strings_trim_left(opa_string_terminated("a"), opa_string_terminated("a")), opa_string_terminated("")) == 0);
|
|
test("trim_left/ab", opa_value_compare(opa_strings_trim_left(opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("a")) == 0);
|
|
test("trim_left/aba", opa_value_compare(opa_strings_trim_left(opa_string_terminated("ab"), opa_string_terminated("a")), opa_string_terminated("b")) == 0);
|
|
test("trim_left/abcba", opa_value_compare(opa_strings_trim_left(opa_string_terminated("abc"), opa_string_terminated("ba")), opa_string_terminated("c")) == 0);
|
|
test("trim_left/aeuro dceuro ", opa_value_compare(opa_strings_trim_left(opa_string_terminated("a\xE2\x82\xAC d"), opa_string_terminated("ca\xE2\x82\xAC ")), opa_string_terminated("d")) == 0);
|
|
|
|
test("trim_prefix/__", opa_value_compare(opa_strings_trim_prefix(opa_string_terminated(""), opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
test("trim_prefix/_a", opa_value_compare(opa_strings_trim_prefix(opa_string_terminated(""), opa_string_terminated("a")), opa_string_terminated("")) == 0);
|
|
test("trim_prefix/a_", opa_value_compare(opa_strings_trim_prefix(opa_string_terminated("a"), opa_string_terminated("")), opa_string_terminated("a")) == 0);
|
|
test("trim_prefix/aa", opa_value_compare(opa_strings_trim_prefix(opa_string_terminated("a"), opa_string_terminated("a")), opa_string_terminated("")) == 0);
|
|
test("trim_prefix/ab", opa_value_compare(opa_strings_trim_prefix(opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("a")) == 0);
|
|
test("trim_prefix/aba", opa_value_compare(opa_strings_trim_prefix(opa_string_terminated("ab"), opa_string_terminated("a")), opa_string_terminated("b")) == 0);
|
|
|
|
test("trim_right/__", opa_value_compare(opa_strings_trim_right(opa_string_terminated(""), opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
test("trim_right/_a", opa_value_compare(opa_strings_trim_right(opa_string_terminated(""), opa_string_terminated("a")), opa_string_terminated("")) == 0);
|
|
test("trim_right/a_", opa_value_compare(opa_strings_trim_right(opa_string_terminated("a"), opa_string_terminated("")), opa_string_terminated("a")) == 0);
|
|
test("trim_right/aa", opa_value_compare(opa_strings_trim_right(opa_string_terminated("a"), opa_string_terminated("a")), opa_string_terminated("")) == 0);
|
|
test("trim_right/ab", opa_value_compare(opa_strings_trim_right(opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("a")) == 0);
|
|
test("trim_right/abb", opa_value_compare(opa_strings_trim_right(opa_string_terminated("ab"), opa_string_terminated("b")), opa_string_terminated("a")) == 0);
|
|
test("trim_right/abccb", opa_value_compare(opa_strings_trim_right(opa_string_terminated("abc"), opa_string_terminated("cb")), opa_string_terminated("a")) == 0);
|
|
test("trim_right/daeuro ceuro ", opa_value_compare(opa_strings_trim_right(opa_string_terminated("da\xE2\x82\xAC "), opa_string_terminated("ca\xE2\x82\xAC ")), opa_string_terminated("d")) == 0);
|
|
|
|
test("trim_suffix/__", opa_value_compare(opa_strings_trim_suffix(opa_string_terminated(""), opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
test("trim_suffix/_a", opa_value_compare(opa_strings_trim_suffix(opa_string_terminated(""), opa_string_terminated("a")), opa_string_terminated("")) == 0);
|
|
test("trim_suffix/a_", opa_value_compare(opa_strings_trim_suffix(opa_string_terminated("a"), opa_string_terminated("")), opa_string_terminated("a")) == 0);
|
|
test("trim_suffix/aa", opa_value_compare(opa_strings_trim_suffix(opa_string_terminated("a"), opa_string_terminated("a")), opa_string_terminated("")) == 0);
|
|
test("trim_suffix/ab", opa_value_compare(opa_strings_trim_suffix(opa_string_terminated("a"), opa_string_terminated("b")), opa_string_terminated("a")) == 0);
|
|
test("trim_suffix/abb", opa_value_compare(opa_strings_trim_suffix(opa_string_terminated("ab"), opa_string_terminated("b")), opa_string_terminated("a")) == 0);
|
|
|
|
test("trim_space/_", opa_value_compare(opa_strings_trim_space(opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
test("trim_space/a", opa_value_compare(opa_strings_trim_space(opa_string_terminated("a")), opa_string_terminated("a")) == 0);
|
|
test("trim_space/_a", opa_value_compare(opa_strings_trim_space(opa_string_terminated(" a")), opa_string_terminated("a")) == 0);
|
|
test("trim_space/a_", opa_value_compare(opa_strings_trim_space(opa_string_terminated("a ")), opa_string_terminated("a")) == 0);
|
|
test("trim_space/_a_", opa_value_compare(opa_strings_trim_space(opa_string_terminated(" a ")), opa_string_terminated("a")) == 0);
|
|
test("trim_space/______a_b_c______", opa_value_compare(opa_strings_trim_space(opa_string_terminated("\t\n\v\f\r a b c \r\f\v\n\t")), opa_string_terminated("a b c")) == 0);
|
|
test("trim_space/euro", opa_value_compare(opa_strings_trim_space(opa_string_terminated("\xE2\x82\xAC")), opa_string_terminated("\xE2\x82\xAC")) == 0);
|
|
test("trim_space/_euro_", opa_value_compare(opa_strings_trim_space(opa_string_terminated(" \xE2\x82\xAC ")), opa_string_terminated("\xE2\x82\xAC")) == 0);
|
|
test("trim_space/a_euro_", opa_value_compare(opa_strings_trim_space(opa_string_terminated("a \xE2\x82\xAC ")), opa_string_terminated("a \xE2\x82\xAC")) == 0);
|
|
test("trim_space/_euro_a", opa_value_compare(opa_strings_trim_space(opa_string_terminated(" \xE2\x82\xAC a")), opa_string_terminated("\xE2\x82\xAC a")) == 0);
|
|
test("trim_space/ogham_a", opa_value_compare(opa_strings_trim_space(opa_string_terminated("\xe1\x9a\x80 a")), opa_string_terminated("a")) == 0);
|
|
test("trim_space/oghamenspace_a", opa_value_compare(opa_strings_trim_space(opa_string_terminated("\xe1\x9a\x80\xe2\x80\x82 a")), opa_string_terminated("a")) == 0);
|
|
test("trim_space/a_oghamenspace_a", opa_value_compare(opa_strings_trim_space(opa_string_terminated("a \xe1\x9a\x80\xe2\x80\x82")), opa_string_terminated("a")) == 0);
|
|
|
|
test("lower/_", opa_value_compare(opa_strings_lower(opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
test("lower/a", opa_value_compare(opa_strings_lower(opa_string_terminated("a")), opa_string_terminated("a")) == 0);
|
|
test("lower/A", opa_value_compare(opa_strings_lower(opa_string_terminated("A")), opa_string_terminated("a")) == 0);
|
|
test("lower/AbCd", opa_value_compare(opa_strings_lower(opa_string_terminated("AbCd")), opa_string_terminated("abcd")) == 0);
|
|
test("lower/utf-8", opa_value_compare(opa_strings_lower(opa_string_terminated("\xc4\x80")), opa_string_terminated("\xc4\x81")) == 0);
|
|
test("lower/utf-8", opa_value_compare(opa_strings_lower(opa_string_terminated("\xc9\x83")), opa_string_terminated("\xc6\x80")) == 0);
|
|
|
|
test("upper/_", opa_value_compare(opa_strings_upper(opa_string_terminated("")), opa_string_terminated("")) == 0);
|
|
test("upper/a", opa_value_compare(opa_strings_upper(opa_string_terminated("a")), opa_string_terminated("A")) == 0);
|
|
test("upper/A", opa_value_compare(opa_strings_upper(opa_string_terminated("A")), opa_string_terminated("A")) == 0);
|
|
test("upper/AbCd", opa_value_compare(opa_strings_upper(opa_string_terminated("AbCd")), opa_string_terminated("ABCD")) == 0);
|
|
test("upper/utf-8", opa_value_compare(opa_strings_upper(opa_string_terminated("\xc4\x81")), opa_string_terminated("\xc4\x80")) == 0);
|
|
test("upper/utf-8", opa_value_compare(opa_strings_upper(opa_string_terminated("\xc6\x80")), opa_string_terminated("\xc9\x83")) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_numbers_range)
|
|
void test_numbers_range(void)
|
|
{
|
|
opa_value *a = opa_number_int(10);
|
|
opa_value *b = opa_number_int(12);
|
|
|
|
opa_value *exp = opa_array();
|
|
opa_array_t *arr = opa_cast_array(exp);
|
|
opa_array_append(arr, opa_number_int(10));
|
|
opa_array_append(arr, opa_number_int(11));
|
|
opa_array_append(arr, opa_number_int(12));
|
|
|
|
test("number.range/ascending", opa_value_compare(opa_numbers_range(a, b), exp) == 0);
|
|
|
|
opa_value *reversed = opa_array();
|
|
arr = opa_cast_array(reversed);
|
|
opa_array_append(arr, opa_number_int(12));
|
|
opa_array_append(arr, opa_number_int(11));
|
|
opa_array_append(arr, opa_number_int(10));
|
|
|
|
test("numbers.range/descending", opa_value_compare(opa_numbers_range(b, a), reversed) == 0);
|
|
test("numbers.range/bad operand", opa_numbers_range(opa_string_terminated("foo"), opa_number_int(10)) == NULL);
|
|
test("numbers.range/bad operand", opa_numbers_range(opa_number_int(10), opa_string_terminated("foo")) == NULL);
|
|
}
|
|
|
|
WASM_EXPORT(test_to_number)
|
|
void test_to_number(void)
|
|
{
|
|
test("to_number/null", opa_value_compare(opa_to_number(opa_null()), opa_number_int(0)) == 0);
|
|
test("to_number/false", opa_value_compare(opa_to_number(opa_boolean(false)), opa_number_int(0)) == 0);
|
|
test("to_number/true", opa_value_compare(opa_to_number(opa_boolean(true)), opa_number_int(1)) == 0);
|
|
test("to_number/nop", opa_value_compare(opa_to_number(opa_number_int(1)), opa_number_int(1)) == 0);
|
|
test("to_number/integer", opa_value_compare(opa_to_number(opa_string_terminated("10")), opa_number_int(10)) == 0);
|
|
test("to_number/float", opa_value_compare(opa_to_number(opa_string_terminated("3.5")), opa_number_float(3.5)) == 0);
|
|
test("to_number/bad string", opa_to_number(opa_string_terminated("deadbeef")) == NULL);
|
|
test("to_number/bad value", opa_to_number(opa_array()) == NULL);
|
|
}
|
|
|
|
WASM_EXPORT(test_cidr_contains)
|
|
void test_cidr_contains(void)
|
|
{
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("10.0.0.0/8"), opa_string_terminated("10.1.0.0/24")), opa_boolean(true)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("172.17.0.0/24"), opa_string_terminated("172.17.0.0/16")), opa_boolean(false)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("10.0.0.0/8"), opa_string_terminated("192.168.1.0/24")), opa_boolean(false)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("10.0.0.0/8"), opa_string_terminated("10.1.1.1/32")), opa_boolean(true)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("2001:4860:4860::8888/32"), opa_string_terminated("2001:4860:4860:1234::8888/40")), opa_boolean(true)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("2001:4860:4860::8888/32"), opa_string_terminated("2001:4860:4860:1234:5678:1234:5678:8888/128")), opa_boolean(true)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("2001:4860::/96"), opa_string_terminated("2001:4860::/32")), opa_boolean(false)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("2001:4860::/32"), opa_string_terminated("fd1e:5bfe:8af3:9ddc::/64")), opa_boolean(false)) == 0);
|
|
test("cidr/contains", opa_cidr_contains(opa_string_terminated("not-a-cidr"), opa_string_terminated("192.168.1.67")) == NULL);
|
|
test("cidr/contains", opa_cidr_contains(opa_string_terminated("192.168.1.0/28"), opa_string_terminated("not-a-cidr")) == NULL);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("10.0.0.0/8"), opa_string_terminated("10.1.2.3")), opa_boolean(true)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_contains(opa_string_terminated("10.0.0.0/8"), opa_string_terminated("192.168.1.1")), opa_boolean(false)) == 0);
|
|
|
|
test("cidr/contains", opa_value_compare(opa_cidr_intersects(opa_string_terminated("192.168.1.0/25"), opa_string_terminated("192.168.1.64/25")), opa_boolean(true)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_intersects(opa_string_terminated("192.168.1.0/24"), opa_string_terminated("192.168.2.0/24")), opa_boolean(false)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_intersects(opa_string_terminated("fd1e:5bfe:8af3:9ddc::/64"), opa_string_terminated("fd1e:5bfe:8af3:9ddc:1111::/72")), opa_boolean(true)) == 0);
|
|
test("cidr/contains", opa_value_compare(opa_cidr_intersects(opa_string_terminated("fd1e:5bfe:8af3:9ddc::/64"), opa_string_terminated("2001:4860:4860::8888/32")), opa_boolean(false)) == 0);
|
|
test("cidr/contains", opa_cidr_intersects(opa_string_terminated("not-a-cidr"), opa_string_terminated("192.168.1.0/24")) == NULL);
|
|
test("cidr/contains", opa_cidr_intersects(opa_string_terminated("192.168.1.0/28"), opa_string_terminated("not-a-cidr")) == NULL);
|
|
}
|
|
|
|
opa_value *__new_value_path(int sz, ...)
|
|
{
|
|
va_list ap;
|
|
opa_value *path = opa_array();
|
|
|
|
va_start(ap, sz);
|
|
|
|
for (int i = 0; i < sz; i++)
|
|
{
|
|
const char* p = va_arg(ap, const char*);
|
|
opa_array_append(opa_cast_array(path), opa_string_terminated(p));
|
|
}
|
|
|
|
va_end(ap);
|
|
|
|
return path;
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_add_path)
|
|
void test_opa_value_add_path() {
|
|
opa_value *data = opa_object();
|
|
opa_value *update = opa_object();
|
|
opa_value *path;
|
|
opa_errc rc;
|
|
|
|
opa_object_insert(opa_cast_object(update), opa_string_terminated("a"), opa_number_int(1));
|
|
|
|
rc = opa_value_add_path(data, opa_array(), update);
|
|
test_errc_eq("empty_path_rc", OPA_ERR_INVALID_PATH, rc);
|
|
|
|
// Setup base document
|
|
data = opa_object();
|
|
opa_object_insert(opa_cast_object(data), opa_string_terminated("b"), opa_number_int(2));
|
|
opa_object_insert(opa_cast_object(data), opa_string_terminated("c"), opa_number_int(3));
|
|
opa_object_insert(opa_cast_object(data), opa_string_terminated("d"), opa_number_int(4));
|
|
|
|
// Upsert into existing object path
|
|
update = opa_object();
|
|
opa_object_insert(opa_cast_object(update), opa_string_terminated("x"), opa_number_int(5));
|
|
|
|
path = __new_value_path(1, "b");
|
|
rc = opa_value_add_path(data, path, update);
|
|
test_errc_eq("overwrite_sub_path_rc", OPA_ERR_OK, rc);
|
|
test_str_eq("overwrite_sub_path", "{\"d\":4,\"c\":3,\"b\":{\"x\":5}}", opa_json_dump(data))
|
|
|
|
// Upsert w/ creating nested path
|
|
update = opa_object();
|
|
opa_object_insert(opa_cast_object(update), opa_string_terminated("foo"), opa_number_int(123));
|
|
|
|
path = __new_value_path(5, "b", "y", "z", "p", "q");
|
|
rc = opa_value_add_path(data, path, update);
|
|
test_errc_eq("mkdir_rc", OPA_ERR_OK, rc);
|
|
char *exp = "{\"d\":4,\"c\":3,\"b\":{\"y\":{\"z\":{\"p\":{\"q\":{\"foo\":123}}}},\"x\":5}}";
|
|
test_str_eq("mkdir", exp, opa_json_dump(data));
|
|
|
|
// NULL path
|
|
update = opa_object();
|
|
rc = opa_value_add_path(update, NULL, opa_object());
|
|
test_errc_eq("null_path_rc", OPA_ERR_INVALID_PATH, rc);
|
|
test_str_eq("null_path_unchanged", exp, opa_json_dump(data));
|
|
|
|
// non-array path types
|
|
rc = opa_value_add_path(update, opa_string_terminated("foo"), opa_object());
|
|
test_errc_eq("invalid_string_path_rc", OPA_ERR_INVALID_PATH, rc);
|
|
test_str_eq("invalid_string_path_unchanged", exp, opa_json_dump(data));
|
|
|
|
rc = opa_value_add_path(update, opa_number_int(1), opa_object());
|
|
test_errc_eq("invalid_number_path_rc", OPA_ERR_INVALID_PATH, rc);
|
|
test_str_eq("invalid_number_path_unchanged", exp, opa_json_dump(data));
|
|
|
|
rc = opa_value_add_path(update, opa_set(), opa_object());
|
|
test_errc_eq("invalid_set_path_rc", OPA_ERR_INVALID_PATH, rc);
|
|
test_str_eq("invalid_set_path_unchanged", exp, opa_json_dump(data));
|
|
|
|
// invalid nested object type
|
|
opa_value *base = opa_object();
|
|
opa_value *invalid_node = opa_set();
|
|
opa_set_add(opa_cast_set(invalid_node), opa_string_terminated("y"));
|
|
opa_object_insert(opa_cast_object(base), opa_string_terminated("x"), invalid_node);
|
|
|
|
exp = "{\"x\":[\"y\"]}";
|
|
path = __new_value_path(3, "x", "y", "z");
|
|
|
|
rc = opa_value_add_path(base, path, opa_object());
|
|
test_errc_eq("invalid_nested_object_in_path_rc", OPA_ERR_INVALID_TYPE, rc);
|
|
test_str_eq("invalid_nested_object_in_path_unchanged", exp, opa_json_dump(base));
|
|
|
|
// invalid nested object type leaf
|
|
base = opa_object();
|
|
opa_object_insert(opa_cast_object(base), opa_string_terminated("x"), opa_number_int(5));
|
|
exp = "{\"x\":5}";
|
|
path = __new_value_path(3, "x", "y", "z");
|
|
|
|
rc = opa_value_add_path(base, path, opa_object());
|
|
test_errc_eq("invalid_nested_object_at_path_end_rc", OPA_ERR_INVALID_TYPE, rc);
|
|
test_str_eq("invalid_nested_object_at_path_end_unchanged", exp, opa_json_dump(base));
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_object_delete)
|
|
void test_opa_object_delete(void)
|
|
{
|
|
opa_value *data = opa_object();
|
|
|
|
opa_object_insert(opa_cast_object(data), opa_string_terminated("a"), opa_number_int(1));
|
|
opa_object_insert(opa_cast_object(data), opa_string_terminated("b"), opa_number_int(2));
|
|
opa_object_insert(opa_cast_object(data), opa_string_terminated("c"), opa_number_int(3));
|
|
|
|
opa_object_remove(opa_cast_object(data), opa_string_terminated("a"), false);
|
|
test_str_eq("remove_key", "{\"c\":3,\"b\":2}", opa_json_dump(data));
|
|
|
|
opa_object_remove(opa_cast_object(data), opa_string_terminated("bad key"), false);
|
|
test_str_eq("remove_unknown_key", "{\"c\":3,\"b\":2}", opa_json_dump(data));
|
|
|
|
opa_object_remove(opa_cast_object(data), opa_string_terminated("b"), false);
|
|
opa_object_remove(opa_cast_object(data), opa_string_terminated("c"), false);
|
|
test_str_eq("remove_all_keys", "{}", opa_json_dump(data));
|
|
|
|
opa_object_remove(opa_cast_object(data), opa_string_terminated("bad key"), false);
|
|
test_str_eq("remove_on_empty_obj", "{}", opa_json_dump(data));
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_value_remove_path)
|
|
void test_opa_value_remove_path(void)
|
|
{
|
|
opa_value *path;
|
|
opa_errc rc;
|
|
|
|
char *raw = "{\"a\":{\"b\":{\"c\":{\"d\":123}}},\"x\":[1,{\"y\":{\"z\":{}}}]}";
|
|
opa_value *data = opa_json_parse(raw, strlen(raw));
|
|
|
|
path = opa_array();
|
|
rc = opa_value_remove_path(data, path);
|
|
test_errc_eq("empty_path", OPA_ERR_INVALID_PATH, rc);
|
|
|
|
// Reset back to full data doc
|
|
data = opa_json_parse(raw, strlen(raw));
|
|
|
|
path = __new_value_path(1, "foo");
|
|
rc = opa_value_remove_path(data, path);
|
|
test_errc_eq("path_doesnt_exist_rc", OPA_ERR_OK, rc);
|
|
test_str_eq("path_doesnt_exist", raw, opa_json_dump(data));
|
|
|
|
path = __new_value_path(3, "a", "b", "foo");
|
|
rc = opa_value_remove_path(data, path);
|
|
test_errc_eq("path_doesnt_exist_nested_rc", OPA_ERR_OK, rc);
|
|
test_str_eq("path_doesnt_exist_nested", raw, opa_json_dump(data));
|
|
|
|
path = __new_value_path(4, "a", "b", "c", "d");
|
|
rc = opa_value_remove_path(data, path);
|
|
test_errc_eq("leaf_rc", OPA_ERR_OK, rc);
|
|
test_str_eq("leaf", "{\"a\":{\"b\":{\"c\":{}}},\"x\":[1,{\"y\":{\"z\":{}}}]}", opa_json_dump(data));
|
|
|
|
path = __new_value_path(2, "a", "b");
|
|
rc = opa_value_remove_path(data, path);
|
|
test_errc_eq("branch_rc", OPA_ERR_OK, rc);
|
|
test_str_eq("branch", "{\"a\":{},\"x\":[1,{\"y\":{\"z\":{}}}]}", opa_json_dump(data));
|
|
|
|
path = __new_value_path(1, "a");
|
|
rc = opa_value_remove_path(data, path);
|
|
test_errc_eq("branch_root_rc", OPA_ERR_OK, rc);
|
|
test_str_eq("branch_root", "{\"x\":[1,{\"y\":{\"z\":{}}}]}", opa_json_dump(data));
|
|
|
|
path = __new_value_path(3, "x", "1", "y");
|
|
rc = opa_value_remove_path(data, path);
|
|
test_errc_eq("invalid_array_path_rc", OPA_ERR_OK, rc);
|
|
test_str_eq("invalid_array_path", "{\"x\":[1,{\"y\":{\"z\":{}}}]}", opa_json_dump(data));
|
|
|
|
path = opa_array();
|
|
opa_array_append(opa_cast_array(path), opa_string_terminated("x"));
|
|
opa_array_append(opa_cast_array(path), opa_number_int(1));
|
|
opa_array_append(opa_cast_array(path), opa_string_terminated("y"));
|
|
rc = opa_value_remove_path(data, path);
|
|
test_errc_eq("invalid_array_path_rc", OPA_ERR_INVALID_PATH, rc);
|
|
test_str_eq("array_index_path", "{\"x\":[1,{\"y\":{\"z\":{}}}]}", opa_json_dump(data));
|
|
|
|
rc = opa_value_remove_path(opa_object(), NULL);
|
|
test_errc_eq("null_path_rc", OPA_ERR_INVALID_PATH, rc);
|
|
test_str_eq("array_index_path", "{\"x\":[1,{\"y\":{\"z\":{}}}]}", opa_json_dump(data));
|
|
}
|
|
|
|
#define ARGS_N(...) ((int)(sizeof((int[]){ __VA_ARGS__ })/sizeof(int)))
|
|
#define BUILD(N, ...) build(N, ARGS_N(__VA_ARGS__), __VA_ARGS__)
|
|
|
|
typedef struct {
|
|
int length;
|
|
int *positions;
|
|
} sequence;
|
|
|
|
typedef struct {
|
|
int n;
|
|
sequence *sequences;
|
|
} sequences;
|
|
|
|
static sequences* build(int n, int args, ...)
|
|
{
|
|
va_list valist;
|
|
va_start(valist, args);
|
|
|
|
sequences *s = malloc(sizeof(sequences));
|
|
s->n = n;
|
|
s->sequences = malloc(n * sizeof(sequence));
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
int run_length = args / n;
|
|
|
|
int *positions = s->sequences[i].positions = malloc(sizeof(int) * run_length);
|
|
int j = 0;
|
|
for (; j < run_length; j++)
|
|
{
|
|
positions[j] = va_arg(valist, int);
|
|
}
|
|
s->sequences[i].length = j;
|
|
}
|
|
|
|
va_end(valist);
|
|
return s;
|
|
}
|
|
|
|
static void test_submatch_string(const char *s, sequence *seq, opa_value *result)
|
|
{
|
|
for (int i = 0; i < seq->length; i += 2)
|
|
{
|
|
int start = seq->positions[i];
|
|
int end = seq->positions[i+1];
|
|
|
|
opa_string_t *match = opa_cast_string(opa_value_get(result, opa_number_int(i/2)));
|
|
test("regex/find_all_string_submatch", opa_strncmp(&s[start], match->v, end-start) == 0);
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_regex)
|
|
void test_regex(void)
|
|
{
|
|
test("regex/is_valid", opa_value_compare(opa_regex_is_valid(opa_string_terminated(".*")), opa_boolean(true)) == 0);
|
|
test("regex/is_valid_non_string", opa_value_compare(opa_regex_is_valid(opa_number_int(123)), opa_boolean(false)) == 0);
|
|
|
|
typedef struct {
|
|
const char *pat;
|
|
const char *text;
|
|
sequences *sequences;
|
|
} testcase;
|
|
|
|
// golang find test cases from https://golang.org/src/regexp/find_test.go
|
|
testcase tests[] = {
|
|
{"", "", BUILD(1, 0, 0)},
|
|
{"^abcdefg", "abcdefg", BUILD(1, 0, 7)},
|
|
{"a+", "baaab", BUILD(1, 1, 4)},
|
|
{"abcd..", "abcdef", BUILD(1, 0, 6)},
|
|
{"a", "a", BUILD(1, 0, 1)},
|
|
{"x", "y", NULL},
|
|
{"b", "abc", BUILD(1, 1, 2)},
|
|
{".", "a", BUILD(1, 0, 1)},
|
|
{".*", "abcdef", BUILD(1, 0, 6)},
|
|
{"^a", "abcde", BUILD(1, 0, 1)},
|
|
{"^", "abcde", BUILD(1, 0, 0)},
|
|
{"$", "abcde", BUILD(1, 5, 5)},
|
|
{"^abcd$", "abcd", BUILD(1, 0, 4)},
|
|
{"^bcd'", "abcdef", NULL},
|
|
{"^abcd$", "abcde", NULL},
|
|
{"a+", "baaab", BUILD(1, 1, 4)},
|
|
{"a*", "baaab", BUILD(3, 0, 0, 1, 4, 5, 5)},
|
|
{"[a-z]+", "abcd", BUILD(1, 0, 4)},
|
|
{"[^a-z]+", "ab1234cd", BUILD(1, 2, 6)},
|
|
{"[a\\-\\]z]+", "az]-bcz", BUILD(2, 0, 4, 6, 7)},
|
|
{"[^\\n]+", "abcd\n", BUILD(1, 0, 4)},
|
|
{"[日本語]+", "日本語日本語", BUILD(1, 0, 18)},
|
|
{"日本語+", "日本語", BUILD(1, 0, 9)},
|
|
{"日本語+", "日本語語語語", BUILD(1, 0, 18)},
|
|
{"()", "", BUILD(1, 0, 0, 0, 0)},
|
|
{"(a)", "a", BUILD(1, 0, 1, 0, 1)},
|
|
{"(.)(.)", "日a", BUILD(1, 0, 4, 0, 3, 3, 4)},
|
|
{"(.*)", "", BUILD(1, 0, 0, 0, 0)},
|
|
{"(.*)", "abcd", BUILD(1, 0, 4, 0, 4)},
|
|
{"(..)(..)", "abcd", BUILD(1, 0, 4, 0, 2, 2, 4)},
|
|
{"(([^xyz]*)(d))", "abcd", BUILD(1, 0, 4, 0, 4, 0, 3, 3, 4)},
|
|
{"((a|b|c)*(d))", "abcd", BUILD(1, 0, 4, 0, 4, 2, 3, 3, 4)},
|
|
{"(((a|b|c)*)(d))", "abcd", BUILD(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)},
|
|
{"\\a\\f\\n\\r\\t\\v", "\a\f\n\r\t\v", BUILD(1, 0, 6)},
|
|
{"[\\a\\f\\n\\r\\t\\v]+", "\a\f\n\r\t\v", BUILD(1, 0, 6)},
|
|
|
|
{"a*(|(b))c*", "aacc", BUILD(1, 0, 4, 2, 2, -1, -1)},
|
|
{"(.*).*", "ab", BUILD(1, 0, 2, 0, 2)},
|
|
{"[.]", ".", BUILD(1, 0, 1)},
|
|
{"/$", "/abc/", BUILD(1, 4, 5)},
|
|
{"/$", "/abc", NULL},
|
|
|
|
// multiple matches
|
|
{".", "abc", BUILD(3, 0, 1, 1, 2, 2, 3)},
|
|
{"(.)", "abc", BUILD(3, 0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 2, 3)},
|
|
{".(.)", "abcd", BUILD(2, 0, 2, 1, 2, 2, 4, 3, 4)},
|
|
{"ab*", "abbaab", BUILD(3, 0, 3, 3, 4, 4, 6)},
|
|
{"a(b*)", "abbaab", BUILD(3, 0, 3, 1, 3, 3, 4, 4, 4, 4, 6, 5, 6)},
|
|
|
|
// fixed bugs
|
|
{"ab$", "cab", BUILD(1, 1, 3)},
|
|
{"axxb$", "axxcb", NULL},
|
|
{"data", "daXY data", BUILD(1, 5, 9)},
|
|
{"da(.)a$", "daXY data", BUILD(1, 5, 9, 7, 8)},
|
|
{"zx+", "zzx", BUILD(1, 1, 3)},
|
|
{"ab$", "abcab", BUILD(1, 3, 5)},
|
|
{"(aa)*$", "a", BUILD(1, 1, 1, -1, -1)},
|
|
{"(?:.|(?:.a))", "", NULL},
|
|
{"(?:A(?:A|a))", "Aa", BUILD(1, 0, 2)},
|
|
{"(?:A|(?:A|a))", "a", BUILD(1, 0, 1)},
|
|
{"(a){0}", "", BUILD(1, 0, 0, -1, -1)},
|
|
{"(?-s)(?:(?:^).)", "\n", NULL},
|
|
{"(?s)(?:(?:^).)", "\n", BUILD(1, 0, 1)},
|
|
{"(?:(?:^).)", "\n", NULL},
|
|
{"\\b", "x", BUILD(2, 0, 0, 1, 1)},
|
|
{"\\b", "xx", BUILD(2, 0, 0, 2, 2)},
|
|
{"\\b", "x y", BUILD(4, 0, 0, 1, 1, 2, 2, 3, 3)},
|
|
{"\\b", "xx yy", BUILD(4, 0, 0, 2, 2, 3, 3, 5, 5)},
|
|
{"\\B", "x", NULL},
|
|
{"\\B", "xx", BUILD(1, 1, 1)},
|
|
{"\\B", "x y", NULL},
|
|
{"\\B", "xx yy", BUILD(2, 1, 1, 4, 4)},
|
|
|
|
// RE2 tests
|
|
{"[^\\S\\s]", "abcd", NULL},
|
|
{"[^\\S[:space:]]", "abcd", NULL},
|
|
{"[^\\D\\d]", "abcd", NULL},
|
|
{"[^\\D[:digit:]]", "abcd", NULL},
|
|
{"(?i)\\W", "x", NULL},
|
|
{"(?i)\\W", "k", NULL},
|
|
{"(?i)\\W", "s", NULL},
|
|
|
|
// long set of matches (longer than startSize)
|
|
{
|
|
".",
|
|
"qwertyuiopasdfghjklzxcvbnm1234567890",
|
|
BUILD(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
|
|
10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
|
|
20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
|
|
30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36),
|
|
},
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(tests) / sizeof(testcase); i++)
|
|
{
|
|
test("regex/match", opa_value_compare(opa_regex_match(opa_string_terminated(tests[i].pat), opa_string_terminated(tests[i].text)), opa_boolean(tests[i].sequences != NULL)) == 0);
|
|
}
|
|
|
|
for (int i = 0; i < sizeof(tests) / sizeof(testcase); i++)
|
|
{
|
|
opa_value *result = opa_regex_find_all_string_submatch(opa_string_terminated(tests[i].pat), opa_string_terminated(tests[i].text), opa_number_int(-1));
|
|
opa_array_t *arr = opa_cast_array(result);
|
|
|
|
if (tests[i].sequences == NULL)
|
|
{
|
|
test("regex/find_all_string_submatch (len)", arr->len == 0);
|
|
continue;
|
|
}
|
|
|
|
test("regex/find_all_string_submatch (len)", arr->len == tests[i].sequences->n);
|
|
for (int j = 0; j < tests[i].sequences->n; j++)
|
|
{
|
|
test_submatch_string(tests[i].text, &tests[i].sequences->sequences[j], opa_value_get(result, opa_number_int(j)));
|
|
}
|
|
}
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_lookup)
|
|
void test_opa_lookup(void)
|
|
{
|
|
opa_array_t *path1 = opa_cast_array(opa_array());
|
|
opa_array_append(path1, opa_string_terminated("foo"));
|
|
opa_array_append(path1, opa_string_terminated("bar"));
|
|
opa_array_append(path1, opa_string_terminated("baz"));
|
|
|
|
opa_object_t *mock_mapping = opa_cast_object(opa_object());
|
|
opa_object_t *obj1 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj1, opa_string_terminated("baz"), opa_number_int(1));
|
|
opa_object_t *obj2 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj2, opa_string_terminated("bar"), &obj1->hdr);
|
|
opa_object_insert(mock_mapping, opa_string_terminated("foo"), &obj2->hdr);
|
|
|
|
opa_value *empty_mapping = opa_object();
|
|
|
|
opa_object_t *smaller_mapping = opa_cast_object(opa_object());
|
|
opa_object_t *obj3 = opa_cast_object(opa_object());
|
|
opa_object_insert(obj3, opa_string_terminated("bar"), opa_number_int(2));
|
|
opa_object_insert(smaller_mapping, opa_string_terminated("foo"), &obj3->hdr);
|
|
|
|
test("opa_lookup/hit", opa_lookup(&mock_mapping->hdr, &path1->hdr) == 1);
|
|
test("opa_lookup/miss", opa_lookup(empty_mapping, &path1->hdr) == 0);
|
|
test("opa_lookup/miss/less", opa_lookup(&smaller_mapping->hdr, &path1->hdr) == 0);
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_mapping_init)
|
|
void test_opa_mapping_init(void)
|
|
{
|
|
opa_string_t *s = opa_cast_string(opa_string_terminated("{\"foo\": {\"bar\": 123}}"));
|
|
opa_mapping_init(s->v, s->len);
|
|
|
|
opa_array_t *path1 = opa_cast_array(opa_array());
|
|
opa_array_append(path1, opa_string_terminated("foo"));
|
|
opa_array_append(path1, opa_string_terminated("bar"));
|
|
test("opa_mapping_init/opa_lookup_works", opa_mapping_lookup(&path1->hdr) == 123);
|
|
}
|
|
|
|
opa_value *template_expression_value(opa_value *v) {
|
|
opa_set_t *s = opa_cast_set(opa_set());
|
|
|
|
if (v != NULL) {
|
|
opa_set_add(s, v);
|
|
}
|
|
|
|
return &s->hdr;
|
|
}
|
|
|
|
WASM_EXPORT(test_opa_template_string)
|
|
void test_opa_template_string(void)
|
|
{
|
|
// empty
|
|
opa_value *arg = opa_array();
|
|
opa_array_t *arr = opa_cast_array(arg);
|
|
|
|
opa_value *res = opa_template_string(arg);
|
|
test_str_eq("empty", "", opa_cast_string(res)->v);
|
|
opa_array_free(arr, true, false);
|
|
|
|
// simple
|
|
arg = opa_array();
|
|
arr = opa_cast_array(arg);
|
|
opa_array_append(arr, opa_string_terminated("foo"));
|
|
|
|
res = opa_template_string(arg);
|
|
test_str_eq("simple", "foo", opa_cast_string(res)->v);
|
|
opa_array_free(arr, true, false);
|
|
|
|
// undefined
|
|
arg = opa_array();
|
|
arr = opa_cast_array(arg);
|
|
opa_array_append(arr, opa_set()); // empty set indicates undefined value
|
|
|
|
res = opa_template_string(arg);
|
|
test_str_eq("undefined", "<undefined>", opa_cast_string(res)->v);
|
|
opa_array_free(arr, true, false);
|
|
|
|
// primitives
|
|
arg = opa_array();
|
|
arr = opa_cast_array(arg);
|
|
opa_array_append(arr, opa_string_terminated("foo "));
|
|
opa_array_append(arr, opa_null());
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, opa_boolean(true));
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, opa_boolean(false));
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, opa_number_int(42));
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, opa_number_float(4.2));
|
|
|
|
res = opa_template_string(arg);
|
|
test_str_eq("primitives", "foo null true false 42 4.2", opa_cast_string(res)->v);
|
|
opa_array_free(arr, true, false);
|
|
|
|
// template-expressions, primitives
|
|
arg = opa_array();
|
|
arr = opa_cast_array(arg);
|
|
opa_array_append(arr, opa_string_terminated("foo "));
|
|
opa_array_append(arr, template_expression_value(opa_string_terminated("bar ")));
|
|
opa_array_append(arr, template_expression_value(opa_boolean(true)));
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, template_expression_value(opa_boolean(false)));
|
|
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, template_expression_value(opa_null()));
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, template_expression_value(opa_number_int(42)));
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, template_expression_value(opa_number_ref("4.2", 3)));
|
|
|
|
res = opa_template_string(arg);
|
|
test_str_eq("template-expressions, primitives", "foo bar true false null 42 4.2", opa_cast_string(res)->v);
|
|
opa_array_free(arr, true, false);
|
|
|
|
// template-expressions, collections
|
|
arg = opa_array();
|
|
arr = opa_cast_array(arg);
|
|
opa_array_append(arr, template_expression_value(opa_array()));
|
|
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_t *arrExpr = opa_cast_array(opa_array());
|
|
opa_array_append(arrExpr, opa_boolean(true));
|
|
opa_array_append(arrExpr, opa_string_terminated("foo"));
|
|
opa_array_append(arr, template_expression_value(&arrExpr->hdr));
|
|
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, template_expression_value(opa_set()));
|
|
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_set_t *setExpr = opa_cast_set(opa_set());
|
|
opa_set_add(setExpr, opa_boolean(false));
|
|
opa_array_append(arr, template_expression_value(&setExpr->hdr));
|
|
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_array_append(arr, template_expression_value(opa_object()));
|
|
|
|
opa_array_append(arr, opa_string_terminated(" "));
|
|
opa_object_t *objExpr = opa_cast_object(opa_object());
|
|
opa_object_insert(objExpr, opa_string_terminated("foo"), opa_boolean(true));
|
|
opa_object_insert(objExpr, opa_number_int(42), opa_null());
|
|
opa_array_append(arr, template_expression_value(&objExpr->hdr));
|
|
|
|
res = opa_template_string(arg);
|
|
test_str_eq("template-expressions, collections", "[] [true, \"foo\"] set() {false} {} {\"foo\": true, 42: null}", opa_cast_string(res)->v);
|
|
opa_array_free(arr, true, false);
|
|
}
|