Paul Pan
a471519ff7
1. add basic dl_call support 2. re-organize code structure 3. fix `wasm_runtime_call_wasm` error handler 4. update examples
178 lines
5.4 KiB
C++
178 lines
5.4 KiB
C++
#include <gtest/gtest.h>
|
|
#include <dlfcn.h>
|
|
|
|
extern "C" {
|
|
#include "utils/defs.h"
|
|
#include "wrt/lib/dl.h"
|
|
#include "wasm_exec_env.h"
|
|
|
|
extern bool signature_check(const char *signature, int *arg_count, bool *has_ret);
|
|
}
|
|
|
|
DLContext dl_context;
|
|
WASMExecEnv exec_env;
|
|
|
|
void init() {
|
|
dl_context.mem.malloc = malloc;
|
|
dl_context.mem.free = free;
|
|
dl_context.symTable = nullptr;
|
|
memset(dl_context.hnd, 0, sizeof(dl_context.hnd));
|
|
memset(dl_context.sym, 0, sizeof(dl_context.sym));
|
|
exec_env.attachment = &dl_context;
|
|
}
|
|
|
|
#define check_symbol_consistency(sym, postfix) \
|
|
do { \
|
|
ASSERT_GT((sym), 0); \
|
|
ASSERT_LT((sym), DL_MAX_SYMBOLS); \
|
|
ASSERT_NE(dl_context.sym[(sym)-1].symbol, nullptr); \
|
|
ASSERT_NE(dl_context.sym[(sym)-1].cif, nullptr); \
|
|
ASSERT_GT(dl_context.sym[(sym)-1].backref, 0); \
|
|
unsigned ref##postfix = dl_context.sym[(sym)-1].backref; \
|
|
ASSERT_GT(ref##postfix, 0); \
|
|
ASSERT_LE(ref##postfix, DL_MAX_HANDLES); \
|
|
ASSERT_NE(dl_context.hnd[ref##postfix - 1].handle, nullptr); \
|
|
} while (0)
|
|
|
|
#define check_hnd_empty(postfix) \
|
|
do { \
|
|
for (auto &hnd##postfix : dl_context.hnd) { \
|
|
ASSERT_EQ(hnd##postfix.handle, nullptr); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define check_sym_empty(postfix) \
|
|
do { \
|
|
for (auto &sym##postfix : dl_context.sym) { \
|
|
ASSERT_EQ(sym##postfix.symbol, nullptr); \
|
|
ASSERT_EQ(sym##postfix.cif, nullptr); \
|
|
ASSERT_EQ(sym##postfix.backref, 0); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define check_empty(postfix) \
|
|
do { \
|
|
check_sym_empty(postfix); \
|
|
check_hnd_empty(postfix); \
|
|
} while (0)
|
|
|
|
TEST(DLTest, InitAndFree) {
|
|
// use valgrind !
|
|
auto *context = (DLContext *)malloc(sizeof(DLContext));
|
|
ASSERT_NE(context, nullptr);
|
|
context->mem.malloc = malloc;
|
|
context->mem.free = free;
|
|
dl_init(context);
|
|
|
|
EXPECT_NE(context->symTable, nullptr);
|
|
for (auto &hnd : context->hnd) {
|
|
EXPECT_EQ(hnd.handle, nullptr);
|
|
}
|
|
for (auto &sym : context->sym) {
|
|
EXPECT_EQ(sym.symbol, nullptr);
|
|
EXPECT_EQ(sym.cif, nullptr);
|
|
EXPECT_EQ(sym.backref, 0);
|
|
}
|
|
|
|
dl_free(context);
|
|
free(context);
|
|
}
|
|
|
|
TEST(DLTest, OpenAndClose) {
|
|
init();
|
|
|
|
int handle = dl_open(&exec_env, "./SimpleLib.so", RTLD_LAZY);
|
|
ASSERT_GT(handle, 0);
|
|
int result = dl_close(&exec_env, handle);
|
|
ASSERT_EQ(result, WRT_OK);
|
|
check_empty(0);
|
|
|
|
handle = dl_open(&exec_env, "not_exists", RTLD_LAZY);
|
|
ASSERT_EQ(handle, WRT_ERROR);
|
|
check_empty(1);
|
|
|
|
handle = dl_open(&exec_env, "", RTLD_LAZY);
|
|
ASSERT_EQ(handle, WRT_ERROR);
|
|
check_empty(2);
|
|
|
|
handle = dl_open(&exec_env, nullptr, RTLD_LAZY);
|
|
ASSERT_EQ(handle, WRT_ERROR);
|
|
check_empty(3);
|
|
}
|
|
|
|
TEST(DLTest, ManyOpen) {
|
|
init();
|
|
|
|
int handles[DL_MAX_HANDLES];
|
|
for (int &handle : handles) {
|
|
handle = dl_open(&exec_env, "./SimpleLib.so", RTLD_LAZY);
|
|
ASSERT_GT(handle, 0);
|
|
}
|
|
|
|
{
|
|
int handle = dl_open(&exec_env, "./SimpleLib.so", RTLD_LAZY);
|
|
ASSERT_EQ(handle, WRT_ERROR);
|
|
}
|
|
|
|
for (int handle : handles) {
|
|
int result = dl_close(&exec_env, handle);
|
|
ASSERT_EQ(result, WRT_OK);
|
|
}
|
|
|
|
check_empty(0);
|
|
}
|
|
|
|
TEST(DLTest, SignatureCheck) {
|
|
typedef struct {
|
|
const char *test;
|
|
bool result;
|
|
int arg_count;
|
|
bool has_ret;
|
|
} Case;
|
|
|
|
const static Case cases[] = {
|
|
{"", false, 0, false}, {"()", true, 0, false}, {"(i)", true, 1, false},
|
|
{"()i", true, 0, true}, {"(x)", false, 0, false}, {"()x", false, 0, false},
|
|
{"(i)f", true, 1, true}, {"(i)x", false, 0, false}, {"(x)f", false, 0, false},
|
|
{"i", false, 0, false}, {"i()", false, 0, false}, {"i(i)", false, 0, false},
|
|
{"(i)()", false, 0, false}, {"(ii", false, 0, false}, {"(iiffdd)l", true, 6, true},
|
|
{"(ffddii)ll", false, 0, false}, {"()ii", false, 0, false}, {"(i", false, 0, false},
|
|
{"(i(i))i", false, 0, false}, {"i)i", false, 0, false}, {"((i)i", false, 0, false},
|
|
{"(i))i", false, 0, false}, {"())", false, 0, false}};
|
|
|
|
for (const auto &cur_case : cases) {
|
|
int arg_count = 0;
|
|
bool has_ret = false;
|
|
bool ok = signature_check(cur_case.test, &arg_count, &has_ret);
|
|
|
|
EXPECT_EQ(ok, cur_case.result);
|
|
if (ok) {
|
|
EXPECT_EQ(arg_count, cur_case.arg_count);
|
|
EXPECT_EQ(has_ret, cur_case.has_ret);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST(DLTest, GetCloseSym) {
|
|
init();
|
|
|
|
int hnd = dl_open(&exec_env, "./SimpleLib.so", RTLD_LAZY);
|
|
{
|
|
int sym = dl_sym(&exec_env, hnd, "fib_fast", "(i)i");
|
|
check_symbol_consistency(sym, 0);
|
|
}
|
|
|
|
{
|
|
int sym = dl_sym(&exec_env, hnd, "fib_fast", "(v)i");
|
|
ASSERT_EQ(sym, WRT_ERROR);
|
|
}
|
|
|
|
{
|
|
dl_close_sym(&exec_env, hnd, 1);
|
|
check_sym_empty(0);
|
|
}
|
|
|
|
dl_close(&exec_env, hnd);
|
|
check_empty(0);
|
|
}
|