forked from bellard/quickjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
38a3707
commit 6159d5d
Showing
2 changed files
with
249 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |