Skip to content

Commit

Permalink
Add C function test for quickjs.c
Browse files Browse the repository at this point in the history
  • Loading branch information
LanderlYoung committed Aug 12, 2024
1 parent 38a3707 commit 6159d5d
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 3 deletions.
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ CONFIG_SHARED_LIBS=y # building shared libraries is supported
endif
endif

PROGS=qjs$(EXE) qjsc$(EXE) run-test262
PROGS=qjs$(EXE) qjsc$(EXE) run-test262 quickjs_test
ifneq ($(CROSS_PREFIX),)
QJSC_CC=gcc
QJSC=./host-qjsc
Expand Down Expand Up @@ -367,12 +367,18 @@ $(OBJDIR)/%.check.o: %.c | $(OBJDIR)
regexp_test: libregexp.c libunicode.c cutils.c
$(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS)

quickjs_test$(EXE): tests/quickjs_test.c $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ tests/quickjs_test.c $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o $(LIBS)

run_quickjs_test: quickjs_test$(EXE)
./quickjs_test$(EXE)

unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h
$(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o

clean:
rm -f repl.c qjscalc.c out.c
rm -f *.a *.o *.d *~ unicode_gen regexp_test fuzz_eval fuzz_compile fuzz_regexp $(PROGS)
rm -f *.a *.o *.d *~ unicode_gen regexp_test fuzz_eval fuzz_compile fuzz_regexp quickjs_test $(PROGS)
rm -f hello.c test_fib.c
rm -f examples/*.so tests/*.so
rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
Expand Down Expand Up @@ -463,7 +469,7 @@ ifdef CONFIG_M32
test: qjs32
endif

test: qjs
test: qjs run_quickjs_test
./qjs tests/test_closure.js
./qjs tests/test_language.js
./qjs --std tests/test_builtin.js
Expand Down
240 changes: 240 additions & 0 deletions tests/quickjs_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/* test quickjs.c internal functions */
#include "../quickjs.c" /* HACK: include c file to access static functions */

static void test_weak_ref(JSRuntime *rt)
{
JSContext *ctx = JS_NewContext(rt);
JSValue obj = JS_NewObject(ctx);
JSValue weak_ref = JS_NewWeakRef(ctx, obj);
JSValue deref;

assert(!JS_IsException(weak_ref));
deref = JS_DerefWeakRef(ctx, weak_ref);
assert(JS_StrictEq(ctx, obj, deref));

JS_FreeValue(ctx, obj);
JS_FreeValue(ctx, deref);

deref = JS_DerefWeakRef(ctx, weak_ref);
assert(JS_IsUndefined(deref));

JS_FreeValue(ctx, weak_ref);
JS_FreeContext(ctx);
}

typedef struct {
JSHashEntry entry;
int key;
int value;
} TestEntry;

static void *__get_key(JSHashMap *_, JSHashEntry *entry)
{
return &container_of(entry, TestEntry, entry)->key;
}

static uint32_t __hash_key(JSHashMap *_, void *key)
{
int k = *(int *)key;
return k * k;
}

static BOOL __key_equals(JSHashMap *_, void *key1, void *key2)
{
return *(int *)key1 == *(int *)key2;
}

#define SIZE 1024
static void test_hash_map(JSRuntime *rt)
{
{ /* add/remove/iterate */
JSHashMap map;
TestEntry e[SIZE];
int i;
assert(!js_hash_map_init(
rt, &map,
JS_HASH_MAP_DEFAULT_SIZE,
JS_HASH_MAP_DEFAULT_LOAD_FACTOR,
JS_HASH_MAP_DEFAULT_SHRINK_FACTOR,
FALSE, __get_key, __hash_key, __key_equals));

for (i = 0; i < SIZE; i++) {
js_hash_map_init_entry(&e[i].entry);
e[i].key = e[i].value = i;
assert(!js_hash_map_add_entry(rt, &map, &e[i].entry));
assert(js_hash_map_size(&map) == i + 1);
}

for (i = 0; i < SIZE; i++) {
JSHashEntry *entry = js_hash_map_find_entry(&map, &i);
assert(entry);
assert(container_of(entry, TestEntry, entry)->key == i);
assert(container_of(entry, TestEntry, entry)->value == i);

js_hash_map_del_entry(rt, &map, entry);
assert(js_hash_map_find_entry(&map, &i) == NULL);
assert(js_hash_map_size(&map) == SIZE - i - 1);
}
js_hash_map_release(rt, &map, NULL, NULL);
assert(js_hash_map_size(&map) == 0);
}

{ /* enlarge/shrink */
JSHashMap map;
TestEntry e[SIZE];
int i;
size_t initial_size = 8;
float load_factor = 0.5;
float shrink_factor = 0.2;

assert(!js_hash_map_init(
rt, &map,
initial_size,
load_factor,
shrink_factor,
FALSE, __get_key, __hash_key, __key_equals));

assert(map.capacity == initial_size);

// enlarege size == 5 == initial_size * load_factor + 1
for(i = 0; i < 4; i++) {
js_hash_map_init_entry(&e[i].entry);
e[i].key = e[i].value = i;
assert(!js_hash_map_add_entry(rt, &map, &e[i].entry));
assert(map.capacity == 8);
}
js_hash_map_init_entry(&e[i].entry);
assert(!js_hash_map_add_entry(rt, &map, &e[i].entry));
assert(map.capacity == 16 /* initial_size * 2 */); /* enlarge */
assert(js_hash_map_size(&map) == 5);

// shrink size == 3.2
js_hash_map_del_entry(rt, &map, &e[0].entry);
assert(map.capacity == 16);
js_hash_map_del_entry(rt, &map, &e[1].entry);
assert(map.capacity == 8); /* shrink */

js_hash_map_release(rt, &map, NULL, NULL);
}

{ /* iterate */
JSHashMap map;
TestEntry e[SIZE];
JSHashEntry *el;
BOOL v[SIZE];
int i;
assert(!js_hash_map_init(
rt, &map,
JS_HASH_MAP_DEFAULT_SIZE,
JS_HASH_MAP_DEFAULT_LOAD_FACTOR,
JS_HASH_MAP_DEFAULT_SHRINK_FACTOR,
FALSE, __get_key, __hash_key, __key_equals));

for (i = 0; i < SIZE; i++) {
js_hash_map_init_entry(&e[i].entry);
e[i].key = e[i].value = i;
assert(!js_hash_map_add_entry(rt, &map, &e[i].entry));
}

for (i = 0; i < SIZE; i++) v[i] = FALSE;
el = NULL;
while ((el = js_hash_map_next_entry(&map, el))) {
TestEntry *te = container_of(el, TestEntry, entry);
assert(!v[te->key]);
v[te->key] = TRUE;
}
for (i = 0; i < SIZE; i++) {
assert(v[i]);
}

js_hash_map_release(rt, &map, NULL, NULL);
}
}

typedef struct {
JSHashEntryLinked entry;
int key;
int value;
} TestEntryLinked;

static TestEntryLinked *__entry(JSHashEntry *entry)
{
return container_of(container_of(entry, JSHashEntryLinked, entry),
TestEntryLinked, entry);
}

static void *__get_key_linked(JSHashMap *_, JSHashEntry *entry)
{
return &__entry(entry)->key;
}

static void test_hash_map_linked(JSRuntime *rt)
{
JSHashMap map;
TestEntryLinked e[SIZE];
JSHashEntry *el;
BOOL v[SIZE];
int i;
assert(!js_hash_map_init(
rt, &map,
JS_HASH_MAP_DEFAULT_SIZE,
JS_HASH_MAP_DEFAULT_LOAD_FACTOR,
JS_HASH_MAP_DEFAULT_SHRINK_FACTOR,
TRUE, __get_key_linked, __hash_key, __key_equals));

for (i = 0; i < SIZE; i++) {
v[i] = FALSE;
js_hash_map_init_entry_linked(&e[i].entry);
e[i].key = e[i].value = i;
assert(!js_hash_map_add_entry(rt, &map, &e[i].entry.entry));
}

i = 0;
el = NULL;
while ((el = js_hash_map_next_entry(&map, el))) {
TestEntryLinked *te = __entry(el);
assert(te->key == i);
i++;
}

{ /* iterate */
JSHashMapIterator it;
js_hash_map_iterator_init(&map, &it);

i = 0;
while ((el = js_hash_map_iterator_next(&map, &it))) {
assert(__entry(el)->key == i);
i++;
}

js_hash_map_iterator_release(&it);
}

{ /* modify during iterate */
JSHashMapIterator it;
js_hash_map_iterator_init(&map, &it);

i = 0;
while ((el = js_hash_map_iterator_next(&map, &it))) {
assert(__entry(el)->key == i);
js_hash_map_del_entry(rt, &map, el);
i++;
assert(js_hash_map_size(&map) == SIZE - i);
}

js_hash_map_iterator_release(&it);
}

js_hash_map_release(rt, &map, NULL, NULL);
}
#undef SIZE


int main() {
JSRuntime *rt = JS_NewRuntime();
test_weak_ref(rt);
test_hash_map(rt);
test_hash_map_linked(rt);
JS_FreeRuntime(rt);
return 0;
}

0 comments on commit 6159d5d

Please sign in to comment.