wasm-micro-runtime/tests/unit/libc-builtin/libc_builtin_test.cc

1413 lines
46 KiB
C++
Raw Normal View History

2024-06-04 03:24:27 +00:00
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "func_types.h"
#include "test_helper.h"
#include "wasm_export.h"
#include "gtest/gtest.h"
#include <limits.h>
#include "../interpreter/wasm.h"
void *func_ptr;
#define CALL_FUNC(name, ...) \
((name##_func_type)get_func(#name))(dummy_exec_env.get(), ##__VA_ARGS__)
extern "C" {
extern uint32_t
get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
extern bool
wasm_native_lookup_libc_builtin_global(const char *module_name,
const char *global_name,
WASMGlobalImport *global);
}
class LibcBuiltinTest : public testing::Test
{
protected:
// You should make the members protected s.t. they can be
// accessed from sub-classes.
// virtual void SetUp() will be called before each test is run. You
// should define it if you need to initialize the varaibles.
// Otherwise, this can be skipped.
virtual void SetUp()
{
n_native_symbols = get_libc_builtin_export_apis(&native_symbols);
}
// virtual void TearDown() will be called after each test is run.
// You should define it if there is cleanup work to do. Otherwise,
// you don't have to provide it.
//
virtual void TearDown() {}
public:
WAMRRuntimeRAII<512 * 1024> runtime;
DummyExecEnv dummy_exec_env;
static NativeSymbol *native_symbols;
static uint32_t n_native_symbols;
static void *get_func(const char *name)
{
int32_t i;
for (i = 0; i < n_native_symbols; i++) {
if (strcmp(native_symbols[i].symbol, name) == 0) {
return native_symbols[i].func_ptr;
}
}
return NULL;
}
};
NativeSymbol *LibcBuiltinTest::native_symbols;
uint32_t LibcBuiltinTest::n_native_symbols;
static const char very_long_string[] =
R"(2mwa9vxDhuuvO47XePZvc4DAMdR8dzgKrmRNAM3qVoedFhG7GYyhlC4JiuSdrw8G
7vrPoCLGlVlGwMw7ATDL3bA5Filds8krTxS7h8ioq6CY4UmKl1zjHlmnOYRO3Wmp
ylp21RrG8LzfHFerFyKFxA1GB93OuTFcasO2n9uQljCx8h5KRolbvjdHVnado4B6
3zNV990V7T7LIJHwZKb0RGg0fFo4GQd6Mfdl6aD3UlpKBIxjbonyeaQBY7hPZB8R
J1JV5iw2PWB2BJEGoGhTvlc0a9FxmeqWIjpnU3yNEg2lD3NjZU627pTFcoAy5GCz
wDyF5QzcvtAgWBR95kRpDtV21CRyQ6HteorX1aHemoMYWOLIvX52stUTAnOImMD8
tIw6xwkOZx5fs3x9m540pPnRDiihLn2XuQ1PLPwA6orWOGm3dBKthqsycTqaIl0L
0gpycKbVYFHmakfgEyP9fyMziLT11B6EPzomHQAYgTVUdDl9u63P6sQCeaPwAYsY
gus28uK9YYjpXgOOziG8ocBddvids1iLJLdbiAqKyHaVY4IBLVWU3F74tKGF7TeI
DGAfvpzHls19VM9bKReBfCmDgbib7mCpYEFAQCmu5my0C8QrJlUoOgiljIO0x3sH
ByNf4k9OfhzYi1V4cvDnMELVrk0fyZWmIxDvig7nfzI57OltT28pughPBlLxTn8X
xyMNVYn1dD6Wpp7sqOBjxWGWmdrjleyin0iQ05UbfioHazvLKHtDfm5P2WwVejm6)";
TEST_F(LibcBuiltinTest, puts)
{
char ll_string[2048];
/* Capture the stdout */
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(puts, "Hello Wrold"), strlen("Hello Wrold\n"));
EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold\n");
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(puts, "c"), strlen("c\n"));
EXPECT_EQ(testing::internal::GetCapturedStdout(), "c\n");
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(puts, very_long_string), strlen(very_long_string) + 1);
EXPECT_EQ(testing::internal::GetCapturedStdout(),
std::string(very_long_string) + "\n");
memset(ll_string, 0xAA, sizeof(ll_string));
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(puts, ll_string), strlen(ll_string) + 1);
EXPECT_EQ(testing::internal::GetCapturedStdout(),
std::string(ll_string) + "\n");
}
TEST_F(LibcBuiltinTest, printf)
{
WAMRVaList empty_va_list(dummy_exec_env.get());
/* Capture the stdout */
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", empty_va_list.get()),
strlen("Hello Wrold"));
EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold");
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(printf, "c", empty_va_list.get()), strlen("c"));
EXPECT_EQ(testing::internal::GetCapturedStdout(), "c");
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(printf, very_long_string, empty_va_list.get()),
strlen(very_long_string));
EXPECT_EQ(testing::internal::GetCapturedStdout(), very_long_string);
/* type */
{
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
va_list.add(20); //%d 20
va_list.add(65); //%i 65
va_list.add(10); //%O 12
va_list.add(10); //%u 10
va_list.add(255); //%x ff
va_list.add(255); //%X FF
va_list.add(3.14); //%f 3.14
va_list.add(3.14); //%F 3.14
va_list.add(0.000001); //%e 1.000000e-06
va_list.add(0.000001); //%E 1.000000E-06
va_list.add(0.000001); //%g 1e-06
va_list.add(0.000001); //%G 1E-06
va_list.add("Hello World"); //%s Hello World
testing::internal::CaptureStdout();
/* clang-format off */
EXPECT_EQ(CALL_FUNC(printf, "%d, %i, %o, %u, %x, %X, %f, %F, %e, %E, %g, %G, %s", va_list.get()), 97);
EXPECT_EQ(testing::internal::GetCapturedStdout(),
"20, 65, 12, 10, ff, FF, 3.140000, 3.140000, 1.000000e-06, 1.000000E-06, 1e-06, 1E-06, Hello World");
/* clang-format on */
}
/* %c */
{
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
va_list.add('C'); //%c C
// va_list.add("Hello"); //%p
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(printf, "%c", va_list.get()), 1);
EXPECT_EQ(testing::internal::GetCapturedStdout(), "C");
}
/* %p */
{
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
va_list.add("Hello");
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(printf, "%p", va_list.get()), 7);
EXPECT_EQ(testing::internal::GetCapturedStdout(), "0x200a8");
}
{
/* clang-format off */
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
va_list.add(20); //%td
va_list.add(20); //%zd
va_list.add(20); //%ld
va_list.add(20L); //%jd
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(printf, "%td, %zd, %ld, %jd", va_list.get()), 14);
EXPECT_EQ(testing::internal::GetCapturedStdout(),
"20, 20, 20, 20");
/* clang-format on */
}
/* %% */
{
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
EXPECT_TRUE(CALL_FUNC(printf, "%%", va_list.get()));
}
/* %n */
{
/* Construct a va_list to call printf */
WAMRVaList empty_va_list(dummy_exec_env.get());
/* Capture the stdout */
testing::internal::CaptureStdout();
CALL_FUNC(printf, "0123%n", empty_va_list.get());
EXPECT_EQ(testing::internal::GetCapturedStdout(), "0123");
}
/* flag */
{
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
/*%-*/
va_list.add(20); //%-d 20
va_list.add(20); //%d 20
/*%+*/
va_list.add(20); //%+d +20
va_list.add(-20); //%+d -20
/*% */
va_list.add(20); //% d 20
va_list.add(-20); //% d -20
/*%#*/
va_list.add(20); //%#o 024
va_list.add(255); //%#x 0xff
va_list.add(255); //%#X 0xFF
va_list.add(3.14); //%#.f 3.
va_list.add(3.14); //%#.lf 3.
va_list.add(3.14); //%#.e 3.e+00
va_list.add(3.14); //%#.E 3.E+00
va_list.add(3.14); //%#.g 3.
va_list.add(3.14); //%#.G 3.
va_list.add(20); //%#.a %a
va_list.add(20); //%#.A %A
/*%0*/
va_list.add(20); //%03d 020
testing::internal::CaptureStdout();
/* clang-format off */
EXPECT_EQ(CALL_FUNC(printf, "%-d, %d, %+d, %+d, % d, % d, %#o, %#x, %#X, %#.f, %#.lf, %#.e, %#.E, %#.g, %#.G, %#.a, %#.A, %03d", va_list.get()), 88);
EXPECT_EQ(testing::internal::GetCapturedStdout(),
"20, 20, +20, -20, 20, -20, 024, 0xff, 0XFF, 3., 3., 3.e+00, 3.E+00, 3., 3., %a, %A, 020");
/* clang-format on */
}
/* precision */
{
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
va_list.add(20); //%d 20
va_list.add(20); //%.1d 20
va_list.add(20); //%.2d 20
va_list.add(20); //%.3d 020
va_list.add(20); //%.4d 0020
va_list.add(20); //%.5d 00020
va_list.add(20); //%.6d 000020
va_list.add(20); //%.7d 0000020
va_list.add(20); //%.8d 00000020
va_list.add(20); //%.9d 000000020
testing::internal::CaptureStdout();
/* clang-format off */
EXPECT_EQ(CALL_FUNC(printf, "%d, %.1d, %.2d, %.3d, %.4d, %.5d, %.6d, %.7d, %.8d, %.9d", va_list.get()), 66);
EXPECT_EQ(testing::internal::GetCapturedStdout(),
"20, 20, 20, 020, 0020, 00020, 000020, 0000020, 00000020, 000000020");
/* clang-format on */
}
/*length*/
{
/* clang-format off */
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
va_list.add(0x7F); //%hhd 127 -char
va_list.add(0xFF); //%hhu.1d 255 -unsiged char
va_list.add(0x7FFF); //%hd 32767 -sing short int
va_list.add(0xFFFF); //%hu 65535 -unsiged short
va_list.add(0x7FFFFFFF); //%ld 2147483647 - sing long
va_list.add(0xFFFFFFFF); //%lu 4294967295 -unsigned long
va_list.add(0x7FFFFFFFFFFFFFFF); //%lld 9223372036854775807 sing long long
va_list.add(0xFFFFFFFFFFFFFFFF);//%llu 18446744073709551615 unsiged long long
testing::internal::CaptureStdout();
EXPECT_EQ(CALL_FUNC(printf, "%hhd, %hhu, %hd, %hu, %ld, %lu, %lld, %llu", va_list.get()), 89);
EXPECT_EQ(testing::internal::GetCapturedStdout(),
"127, 255, 32767, 65535, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615");
/* clang-format on */
}
EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", 0), 0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", NULL), 0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", (char *)-1), 0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
EXPECT_EQ(CALL_FUNC(printf, (char *)-1, (char *)-1), 0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
}
TEST_F(LibcBuiltinTest, sprintf)
{
const char *buf;
const char *str = "Hello Wrold";
const char *str_sig = "c";
const char *str_f = "20, 3.140000, Hello World";
const char *str_long = "eqwewerwerqwer34were"; // test ok
// const char *str_long = "TDSFGAWE%#$TERFQ@$%$@!%$@!RS!$#@$%"
// "WAWAAEWAFSDNGFUTKNZDAERQWYNZREWGHAH";
// //fail
WAMRVaList empty_va_list(dummy_exec_env.get());
AppData buf_app{ dummy_exec_env.get(), buf };
AppData str_app{ dummy_exec_env.get(), str };
AppData str_sig_app{ dummy_exec_env.get(), str_sig };
AppData str_long_app{ dummy_exec_env.get(), str_long };
EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
(char *)str_app.get_native_addr(), 0),
0);
EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
(char *)str_app.get_native_addr(), NULL),
0);
EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
(char *)str_app.get_native_addr(), (char *)-1),
0);
EXPECT_FALSE(CALL_FUNC(sprintf, (char *)-1,
(char *)str_app.get_native_addr(),
empty_va_list.get()));
EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
(char *)str_app.get_native_addr(), empty_va_list.get()),
strlen(str));
EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(),
str_app.get_native_addr(), strlen(str)),
0);
EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
(char *)str_sig_app.get_native_addr(),
empty_va_list.get()),
strlen(str_sig));
EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(),
str_sig_app.get_native_addr(), strlen(str_sig)),
0);
EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
(char *)str_long_app.get_native_addr(),
empty_va_list.get()),
strlen(str_long));
EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(),
str_long_app.get_native_addr(), strlen(str_long)),
0);
{
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
va_list.add(20);
va_list.add(3.14);
va_list.add("Hello World");
/* This is like printf("%d, %f, %s", 20, 3.14, "Hello World") */
EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
"%d, %f, %s", va_list.get()),
25);
EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), str_f, 25), 0);
}
}
TEST_F(LibcBuiltinTest, snprintf)
{
char buf[1024];
char buf1[10];
WAMRVaList empty_va_list(dummy_exec_env.get());
EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", 0),
0);
EXPECT_EQ(
CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", NULL),
0);
EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold",
(char *)-1),
0);
EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold",
empty_va_list.get()),
strlen("Hello Wrold"));
EXPECT_EQ(CALL_FUNC(memcmp, buf, "Hello Wrold", strlen("Hello Wrold")), 0);
EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen(very_long_string),
very_long_string, empty_va_list.get()),
strlen(very_long_string));
{
/* Construct a va_list to call printf */
WAMRVaList va_list(dummy_exec_env.get());
va_list.add(20);
va_list.add(3.14);
va_list.add("Hello World");
EXPECT_EQ(CALL_FUNC(snprintf, buf, 25, "%d, %f, %s", va_list.get()),
25);
}
}
TEST_F(LibcBuiltinTest, putchar)
{
char ch;
for (ch = 'a'; ch <= 'z'; ch++)
EXPECT_EQ(CALL_FUNC(putchar, ch), 1);
for (ch = '0'; ch <= '9'; ch++)
EXPECT_EQ(CALL_FUNC(putchar, ch), 1);
for (ch = 0; ch < 127; ch++)
EXPECT_EQ(CALL_FUNC(putchar, ch), 1);
}
TEST_F(LibcBuiltinTest, strdup)
{
const char *src = "Hello World!";
AppData src_app{ dummy_exec_env.get(), src };
/* exception */
EXPECT_EQ(CALL_FUNC(strdup, NULL), 0);
EXPECT_GE(CALL_FUNC(strdup, (char *)src_app.get_native_addr()), 0);
}
TEST_F(LibcBuiltinTest, _strdup)
{
const char *src = "Hello World!";
AppData src_app{ dummy_exec_env.get(), src };
/* exception */
EXPECT_EQ(CALL_FUNC(_strdup, NULL), 0);
EXPECT_GE(CALL_FUNC(_strdup, (char *)src_app.get_native_addr()), 0);
}
TEST_F(LibcBuiltinTest, memcmp)
{
const char *a = "aBcDeF";
const char *b = "AbCdEf";
const char *c = "aacdef";
const char *d = "aBcDeF";
AppData a_app{ dummy_exec_env.get(), a };
AppData b_app{ dummy_exec_env.get(), b };
AppData c_app{ dummy_exec_env.get(), c };
AppData d_app{ dummy_exec_env.get(), d };
/* exception */
EXPECT_EQ(CALL_FUNC(memcmp, (void *)-1, d_app.get_native_addr(), 0), 0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
/* size = 0 */
EXPECT_EQ(
CALL_FUNC(memcmp, a_app.get_native_addr(), d_app.get_native_addr(), 0),
0);
// /* s1>s2 */
EXPECT_GT(CALL_FUNC(memcmp, a_app.get_native_addr(),
b_app.get_native_addr(), strlen(a)),
0);
// /* s1<s2 */
EXPECT_LT(CALL_FUNC(memcmp, a_app.get_native_addr(),
c_app.get_native_addr(), strlen(a)),
0);
// /* s1=s2 */
EXPECT_EQ(CALL_FUNC(memcmp, a_app.get_native_addr(),
d_app.get_native_addr(), strlen(a)),
0);
}
TEST_F(LibcBuiltinTest, memcpy)
{
const char *src = "Hell World";
char *dest;
AppData src_app{ dummy_exec_env.get(), src };
AppData dest_app{ dummy_exec_env.get(), dest };
/* exception */
EXPECT_EQ(CALL_FUNC(memcpy, (void *)-1, src_app.get_native_addr(), 0), 0);
EXPECT_EQ(CALL_FUNC(memcpy, dest_app.get_native_addr(),
src_app.get_native_addr(), 0),
dest_app.get_app_addr());
EXPECT_EQ(CALL_FUNC(memcpy, (void *)-1, src_app.get_native_addr(), 10), 0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
CALL_FUNC(memcpy, dest_app.get_native_addr(), src_app.get_native_addr(),
strlen(src));
EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(),
src_app.get_native_addr(), strlen(src)),
0);
}
TEST_F(LibcBuiltinTest, memmove)
{
const char *src = "Hell World";
char *dest;
AppData src_app{ dummy_exec_env.get(), src };
AppData dest_app{ dummy_exec_env.get(), dest };
/* exception */
EXPECT_EQ(CALL_FUNC(memmove, (void *)-1, dest_app.get_native_addr(), 0), 0);
EXPECT_EQ(CALL_FUNC(memmove, dest_app.get_native_addr(),
src_app.get_native_addr(), 0),
dest_app.get_app_addr());
EXPECT_EQ(CALL_FUNC(memmove, (void *)-1, dest_app.get_native_addr(), 10),
0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
CALL_FUNC(memmove, dest_app.get_native_addr(), src_app.get_native_addr(),
strlen(src));
EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(),
src_app.get_native_addr(), strlen(src)),
0);
}
TEST_F(LibcBuiltinTest, memset)
{
const char *src = "Hello World!";
AppData src_app{ dummy_exec_env.get(), src };
/* exception */
EXPECT_EQ(CALL_FUNC(memset, (void *)-1, 1, strlen(src)), 0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
EXPECT_EQ(CALL_FUNC(memcmp, src_app.get_native_addr(), "Hello World!",
strlen(src)),
0);
EXPECT_GE(CALL_FUNC(memset, src_app.get_native_addr(), '\0', strlen(src)),
0);
EXPECT_EQ(CALL_FUNC(memcmp, src_app.get_native_addr(),
"\0\0\0\0\0\0\0\0\0\0\0\0", strlen(src)),
0);
}
TEST_F(LibcBuiltinTest, strchr)
{
const char *src = "Hell World";
unsigned int ch_existent = 'o';
unsigned int ch_non_existent = '$';
AppData src_app{ dummy_exec_env.get(), src };
EXPECT_EQ(
CALL_FUNC(strchr, (char *)src_app.get_native_addr(), ch_non_existent),
0);
EXPECT_GE(CALL_FUNC(strchr, (char *)src_app.get_native_addr(), ch_existent),
0);
}
TEST_F(LibcBuiltinTest, strcmp)
{
const char *a = "Hello World!";
const char *b = "hello World!";
const char *c = "Hello World!";
AppData a_app{ dummy_exec_env.get(), a };
AppData b_app{ dummy_exec_env.get(), b };
AppData c_app{ dummy_exec_env.get(), c };
/*s1>s2*/
EXPECT_GT(CALL_FUNC(strcmp, (char *)b_app.get_native_addr(),
(char *)a_app.get_native_addr()),
0);
/*s1<s2*/
EXPECT_LT(CALL_FUNC(strcmp, (char *)a_app.get_native_addr(),
(char *)b_app.get_native_addr()),
0);
/*s1=s2*/
EXPECT_EQ(CALL_FUNC(strcmp, (char *)a_app.get_native_addr(),
(char *)c_app.get_native_addr()),
0);
}
TEST_F(LibcBuiltinTest, strncmp)
{
const char *a = "Hello World!";
const char *b = "hello World!";
const char *c = "Hello World!";
AppData a_app{ dummy_exec_env.get(), a };
AppData b_app{ dummy_exec_env.get(), b };
AppData c_app{ dummy_exec_env.get(), c };
/* exception */
EXPECT_EQ(CALL_FUNC(strncmp, (char *)-1, (char *)a_app.get_native_addr(),
strlen(a)),
0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
/* size = 0 */
EXPECT_EQ(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
(char *)c_app.get_native_addr(), 0),
0);
/*s1>s2*/
EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(),
(char *)a_app.get_native_addr(), strlen(a)),
0);
/*s1<s2*/
EXPECT_LT(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
(char *)b_app.get_native_addr(), strlen(a)),
0);
/*s1=s2*/
EXPECT_EQ(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
(char *)c_app.get_native_addr(), strlen(a)),
0);
/*s1>s2*/
EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(),
(char *)a_app.get_native_addr(), 3),
0);
/*s1<s2*/
EXPECT_LT(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
(char *)b_app.get_native_addr(), 3),
0);
/*s1=s2*/
EXPECT_EQ(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
(char *)c_app.get_native_addr(), 3),
0);
}
TEST_F(LibcBuiltinTest, strcpy)
{
char *src = (char *)"Hello World!";
char *dest;
AppData src_app{ dummy_exec_env.get(), src };
AppData dest_app{ dummy_exec_env.get(), dest };
/* exception */
EXPECT_EQ(CALL_FUNC(strcpy, (char *)-1, (char *)src_app.get_native_addr()),
0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
EXPECT_GE(CALL_FUNC(strcpy, (char *)dest_app.get_native_addr(),
(char *)src_app.get_native_addr()),
0);
EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(),
(char *)src_app.get_native_addr(), strlen(src)),
0);
}
TEST_F(LibcBuiltinTest, strncpy)
{
char *src = (char *)"Hello World!";
char *dest;
AppData src_app{ dummy_exec_env.get(), src };
AppData dest_app{ dummy_exec_env.get(), dest };
/* exception */
EXPECT_EQ(CALL_FUNC(strncpy, (char *)-1, (char *)src_app.get_native_addr(),
strlen(src)),
0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
EXPECT_GE(CALL_FUNC(strncpy, (char *)dest_app.get_native_addr(),
(char *)src_app.get_native_addr(), strlen(src)),
0);
EXPECT_EQ(CALL_FUNC(memcmp, (char *)dest_app.get_native_addr(),
(char *)src_app.get_native_addr(), strlen(src)),
0);
EXPECT_GE(CALL_FUNC(strncpy, (char *)dest_app.get_native_addr(),
(char *)src_app.get_native_addr(), 3),
0);
EXPECT_EQ(CALL_FUNC(memcmp, (char *)dest_app.get_native_addr(),
(char *)src_app.get_native_addr(), 3),
0);
}
TEST_F(LibcBuiltinTest, strlen)
{
const char *src = "Hello World!";
AppData src_app{ dummy_exec_env.get(), src };
EXPECT_EQ(CALL_FUNC(strlen, (char *)src_app.get_native_addr()), 12);
}
TEST_F(LibcBuiltinTest, malloc)
{
EXPECT_GT(CALL_FUNC(malloc, 0), 0);
EXPECT_GT(CALL_FUNC(malloc, 100), 0);
EXPECT_EQ(CALL_FUNC(malloc, 0xFFFFFFFF), 0);
}
TEST_F(LibcBuiltinTest, calloc)
{
/* nmemb = 1 size=0xffffffff total_size >= UINT32_MAX */
EXPECT_EQ(CALL_FUNC(calloc, 1, 0xffffffff), 0);
/* nmemb = 1 size=0xffffffff-1 total_size >= UINT32_MAX-1 */
EXPECT_EQ(CALL_FUNC(calloc, 1, (0xffffffff - 1)), 0);
/* nmemb = 1 size = 0 total_size = 0 */
/* According to Linux man page:
If nmemb or size is 0, then calloc() returns either NULL, or a unique
pointer value that can later be successfully passed to free() */
EXPECT_GE(CALL_FUNC(calloc, 1, 0), 0);
/* nmemb = 10 size = 1024 total_size < UINT32_MAX */
EXPECT_GT(CALL_FUNC(calloc, 10, 1024), 0);
}
TEST_F(LibcBuiltinTest, realloc)
{
unsigned int ptr = 0;
// ptr = 0;
// EXPECT_EQ(CALL_FUNC(realloc, ptr, 1024), 0);
// ptr = 1;
// EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0);
// ptr = 3;
// EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0);
/* If ptr is NULL, then the call is equivalent to malloc(size), for all
* values of size */
ptr = CALL_FUNC(realloc, ptr, 1024);
EXPECT_EQ(ptr, ptr);
EXPECT_EQ(CALL_FUNC(realloc, ptr, 10), ptr);
EXPECT_EQ(CALL_FUNC(realloc, ptr, 15), ptr);
ptr = CALL_FUNC(realloc, ptr, 2048);
EXPECT_EQ(ptr, ptr);
/* If size is equal to zero, and ptr is not NULL, then
the call is equivalent to free(ptr) */
CALL_FUNC(realloc, ptr, 0);
}
TEST_F(LibcBuiltinTest, free)
{
const char *src;
const char *s = "Hello World!";
AppMemory src_mem{ dummy_exec_env.get(), 15 };
AppData s_app{ dummy_exec_env.get(), s };
CALL_FUNC(free, (char *)0xFFFFFFFF);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
CALL_FUNC(free, (char *)-1);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
CALL_FUNC(free, NULL);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
memset((char *)src_mem.get_native_addr(), '\0', 15);
strcpy((char *)src_mem.get_native_addr(), (char *)s_app.get_native_addr());
EXPECT_EQ(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(),
s_app.get_native_addr(), 15),
0);
/* free */
CALL_FUNC(free, (char *)src_mem.get_native_addr());
EXPECT_NE(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(),
s_app.get_native_addr(), 15),
0);
}
TEST_F(LibcBuiltinTest, atoi)
{
char *src = (char *)"123";
char *src1 = (char *)"-123";
AppData src_app{ dummy_exec_env.get(), src };
AppData src1_app{ dummy_exec_env.get(), src1 };
EXPECT_EQ(CALL_FUNC(atoi, (char *)src_app.get_native_addr()), 123);
EXPECT_EQ(CALL_FUNC(atoi, (char *)src1_app.get_native_addr()), -123);
}
TEST_F(LibcBuiltinTest, exit)
{
CALL_FUNC(exit, 3);
EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.exit(3)");
dummy_exec_env.clear_exception();
}
TEST_F(LibcBuiltinTest, strtol)
{
char str[20] = "20";
char str1[20] = "-20";
char buffer[20] = "0x31";
char buffer1[20] = "10379cend$3";
char *ptr;
AppData src_app{ dummy_exec_env.get(), str };
AppData src1_app{ dummy_exec_env.get(), str1 };
AppData buffer_app{ dummy_exec_env.get(), buffer };
AppData buffer1_app{ dummy_exec_env.get(), buffer1 };
AppMemory ptr_app{ dummy_exec_env.get(), 20 };
CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
CALL_FUNC(strtol, (char *)src_app.get_native_addr(), &ptr, 10);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 2), 0);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 8), 0);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10),
0);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 16),
0);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 32),
0);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 2),
0);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 8),
16);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 10),
20);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 16),
32);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 32),
64);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 2),
0);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 8),
-16);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 10),
-20);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 16),
-32);
EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 32),
-64);
EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 0),
49);
EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 16),
49);
EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 10),
0);
EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer1_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 10),
10379);
// EXPECT_STREQ((char *)ptr_app.get_native_addr(), "cend$3");
uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr();
EXPECT_GT(str_app_addr, 0);
char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr);
EXPECT_NE(str_native_addr, nullptr);
EXPECT_STREQ(str_native_addr, "cend$3");
}
TEST_F(LibcBuiltinTest, strtoul)
{
char str[20] = "20";
char buffer[20] = "0x31";
char buffer1[20] = "10379cend$3";
char *ptr;
AppData src_app{ dummy_exec_env.get(), str };
AppData buffer_app{ dummy_exec_env.get(), buffer };
AppData buffer1_app{ dummy_exec_env.get(), buffer1 };
AppMemory ptr_app{ dummy_exec_env.get(), 20 };
CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), &ptr, 10);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 2),
0);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 8),
0);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10),
0);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 16),
0);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 32),
0);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 2),
0);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 8),
16);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 10),
20);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 16),
32);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 32),
64);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 0),
49);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 16),
49);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 10),
0);
EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer1_app.get_native_addr(),
(char **)ptr_app.get_native_addr(), 10),
10379);
uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr();
EXPECT_GT(str_app_addr, 0);
char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr);
EXPECT_NE(str_native_addr, nullptr);
EXPECT_STREQ(str_native_addr, "cend$3");
}
TEST_F(LibcBuiltinTest, memchr)
{
const char src[] = "Hello World.";
char ch = 'o';
AppData src_app{ dummy_exec_env.get(), src };
/* exception */
EXPECT_EQ(CALL_FUNC(memchr, (char *)-1, ch, strlen(src)), 0);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: out of bounds memory access");
dummy_exec_env.clear_exception();
EXPECT_GE(CALL_FUNC(memchr, src_app.get_native_addr(), ch, strlen(src)), 0);
}
TEST_F(LibcBuiltinTest, strncasecmp)
{
const char *src1 = "Hello World.";
const char *src2 = "hel";
const char *src3 = "HELLO WORLD.";
AppData src1_app{ dummy_exec_env.get(), src1 };
AppData src2_app{ dummy_exec_env.get(), src2 };
AppData src3_app{ dummy_exec_env.get(), src3 };
EXPECT_GT(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(),
(char *)src2_app.get_native_addr(), 4),
0);
EXPECT_LT(CALL_FUNC(strncasecmp, (char *)src2_app.get_native_addr(),
(char *)src1_app.get_native_addr(), 4),
0);
EXPECT_EQ(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(),
(char *)src3_app.get_native_addr(), strlen(src1)),
0);
}
TEST_F(LibcBuiltinTest, strspn)
{
const char *src1 = "Hello world!";
const char *src2 = "abcd";
const char *src3 = "l";
const char *src4 = "Hell";
const char *src5 = "Helo";
AppData src1_app{ dummy_exec_env.get(), src1 };
AppData src2_app{ dummy_exec_env.get(), src2 };
AppData src3_app{ dummy_exec_env.get(), src3 };
AppData src4_app{ dummy_exec_env.get(), src4 };
AppData src5_app{ dummy_exec_env.get(), src5 };
EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(),
(char *)src2_app.get_native_addr()),
0);
EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(),
(char *)src3_app.get_native_addr()),
0);
EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(),
(char *)src4_app.get_native_addr()),
4);
EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(),
(char *)src5_app.get_native_addr()),
5);
}
TEST_F(LibcBuiltinTest, strcspn)
{
const char *src1 = "Hello world!";
const char *src2 = ".?";
const char *src3 = "llo";
const char *src4 = "http://www.baidu.com/";
const char *src5 = "?.,:\"\'-!";
AppData src1_app{ dummy_exec_env.get(), src1 };
AppData src2_app{ dummy_exec_env.get(), src2 };
AppData src3_app{ dummy_exec_env.get(), src3 };
AppData src4_app{ dummy_exec_env.get(), src4 };
AppData src5_app{ dummy_exec_env.get(), src5 };
EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(),
(char *)src2_app.get_native_addr()),
12);
EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(),
(char *)src3_app.get_native_addr()),
2);
EXPECT_EQ(CALL_FUNC(strcspn, (char *)src4_app.get_native_addr(),
(char *)src5_app.get_native_addr()),
4);
}
TEST_F(LibcBuiltinTest, strstr)
{
const char *src1 = "Hello world!";
const char *src2 = "abcd";
const char *src3 = "Hello";
const char *src4 = "H";
const char *src5 = "llo";
AppData src1_app{ dummy_exec_env.get(), src1 };
AppData src2_app{ dummy_exec_env.get(), src2 };
AppData src3_app{ dummy_exec_env.get(), src3 };
AppData src4_app{ dummy_exec_env.get(), src4 };
AppData src5_app{ dummy_exec_env.get(), src5 };
EXPECT_EQ(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(),
(char *)src2_app.get_native_addr()),
0);
EXPECT_EQ(CALL_FUNC(strstr, (char *)src3_app.get_native_addr(),
(char *)src1_app.get_native_addr()),
0);
EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(),
(char *)src4_app.get_native_addr()),
0);
EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(),
(char *)src5_app.get_native_addr()),
0);
}
TEST_F(LibcBuiltinTest, isupper)
{
EXPECT_FALSE(CALL_FUNC(isupper, 'a'));
EXPECT_FALSE(CALL_FUNC(isupper, 97));
EXPECT_FALSE(CALL_FUNC(isupper, '0'));
EXPECT_FALSE(CALL_FUNC(isupper, '.'));
EXPECT_TRUE(CALL_FUNC(isupper, 'A'));
EXPECT_TRUE(CALL_FUNC(isupper, 65));
}
TEST_F(LibcBuiltinTest, isalpha)
{
EXPECT_FALSE(CALL_FUNC(isalpha, '0'));
EXPECT_FALSE(CALL_FUNC(isalpha, 0));
EXPECT_FALSE(CALL_FUNC(isalpha, '?'));
EXPECT_TRUE(CALL_FUNC(isalpha, 'A'));
EXPECT_TRUE(CALL_FUNC(isalpha, 'a'));
}
TEST_F(LibcBuiltinTest, isspace)
{
EXPECT_FALSE(CALL_FUNC(isspace, '0'));
EXPECT_FALSE(CALL_FUNC(isspace, 0));
EXPECT_FALSE(CALL_FUNC(isspace, '?'));
EXPECT_TRUE(CALL_FUNC(isspace, ' '));
EXPECT_TRUE(CALL_FUNC(isspace, '\t'));
EXPECT_TRUE(CALL_FUNC(isspace, '\n'));
EXPECT_TRUE(CALL_FUNC(isspace, '\v'));
EXPECT_TRUE(CALL_FUNC(isspace, '\f'));
EXPECT_TRUE(CALL_FUNC(isspace, '\r'));
}
TEST_F(LibcBuiltinTest, isgraph)
{
/* ASCII 0x00-0x20 */
EXPECT_FALSE(CALL_FUNC(isgraph, 0x00));
EXPECT_FALSE(CALL_FUNC(isgraph, 0x20));
/* ASCII 0x7F */
EXPECT_FALSE(CALL_FUNC(isgraph, 0x7F));
EXPECT_FALSE(CALL_FUNC(isgraph, 0x80));
/* ASCII 0x21-0x7E */
EXPECT_TRUE(CALL_FUNC(isgraph, 0x21));
EXPECT_TRUE(CALL_FUNC(isgraph, 0x7E));
}
TEST_F(LibcBuiltinTest, isprint)
{
/* ASCII 0x00-0x1F */
EXPECT_FALSE(CALL_FUNC(isprint, 0x00));
EXPECT_FALSE(CALL_FUNC(isprint, 0x1F));
/* ASCII 0x7F */
EXPECT_FALSE(CALL_FUNC(isprint, 0x7F));
EXPECT_FALSE(CALL_FUNC(isprint, 0x80));
/* ASCII 0x20-0x7E */
EXPECT_TRUE(CALL_FUNC(isprint, 0x20));
EXPECT_TRUE(CALL_FUNC(isprint, 0x7E));
}
TEST_F(LibcBuiltinTest, isdigit)
{
/* ASCII 0x00-0x2F */
EXPECT_FALSE(CALL_FUNC(isdigit, 0x00));
EXPECT_FALSE(CALL_FUNC(isdigit, 0x2F));
/* ASCII 0x3A-0x7F */
EXPECT_FALSE(CALL_FUNC(isdigit, 0x3A));
EXPECT_FALSE(CALL_FUNC(isdigit, 0x7F));
/* ASCII 0x30-0x39 */
EXPECT_TRUE(CALL_FUNC(isdigit, 0x30));
EXPECT_TRUE(CALL_FUNC(isdigit, 0x39));
}
TEST_F(LibcBuiltinTest, isxdigit)
{
char str[] = "-FFEE";
char str1[] = "FFEE";
EXPECT_FALSE(CALL_FUNC(isxdigit, str[0]));
EXPECT_TRUE(CALL_FUNC(isxdigit, str1[0]));
/* ASCII 0x00-0x2F */
EXPECT_FALSE(CALL_FUNC(isxdigit, 0x00));
EXPECT_FALSE(CALL_FUNC(isxdigit, 0x2F));
/* ASCII 0x3A-0x40 */
EXPECT_FALSE(CALL_FUNC(isxdigit, 0x3A));
EXPECT_FALSE(CALL_FUNC(isxdigit, 0x40));
/* ASCII 0x49-0x60 */
EXPECT_FALSE(CALL_FUNC(isxdigit, 0x49));
EXPECT_FALSE(CALL_FUNC(isxdigit, 0x60));
/* ASCII 0x67-0x7F */
EXPECT_FALSE(CALL_FUNC(isxdigit, 0x67));
EXPECT_FALSE(CALL_FUNC(isxdigit, 0x7F));
/* ASCII 0x30-0x39 */
EXPECT_TRUE(CALL_FUNC(isxdigit, 0x30));
EXPECT_TRUE(CALL_FUNC(isxdigit, 0x39));
/* ASCII 0x41-0x46 */
EXPECT_TRUE(CALL_FUNC(isxdigit, 0x41));
EXPECT_TRUE(CALL_FUNC(isxdigit, 0x46));
/* ASCII 0x61-0x66 */
EXPECT_TRUE(CALL_FUNC(isxdigit, 0x61));
EXPECT_TRUE(CALL_FUNC(isxdigit, 0x66));
}
TEST_F(LibcBuiltinTest, tolower)
{
char src[] = "aBcDeFgH12345;!#$";
char dest[sizeof(src)];
int i;
for (i = 0; i < sizeof(src); i++) {
dest[i] = CALL_FUNC(tolower, (src[i]));
}
EXPECT_STREQ(dest, "abcdefgh12345;!#$");
}
TEST_F(LibcBuiltinTest, toupper)
{
char src[] = "aBcDeFgH12345;!#$";
char dest[sizeof(src)];
int i;
for (i = 0; i < sizeof(src); i++) {
dest[i] = CALL_FUNC(toupper, (src[i]));
}
EXPECT_STREQ(dest, "ABCDEFGH12345;!#$");
}
TEST_F(LibcBuiltinTest, isalnum)
{
char src[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678"
"9!\"#$%&'()*+,-./:;<=>?@[^_'{|}~";
int i;
int isalnum_cnt = 0;
for (i = 0; i < sizeof(src); i++) {
if (CALL_FUNC(isalnum, (src[i])))
isalnum_cnt++;
}
EXPECT_EQ(isalnum_cnt, 62);
}
TEST_F(LibcBuiltinTest, emscripten_memcpy_big)
{
const char *src = "Hell World";
char *dest;
AppData src_app{ dummy_exec_env.get(), src };
AppData dest_app{ dummy_exec_env.get(), dest };
/* exception */
EXPECT_EQ(CALL_FUNC(emscripten_memcpy_big, (void *)-1,
src_app.get_native_addr(), 0),
0);
CALL_FUNC(emscripten_memcpy_big, dest_app.get_native_addr(),
src_app.get_native_addr(), strlen(src));
EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(),
src_app.get_native_addr(), strlen(src)),
0);
}
TEST_F(LibcBuiltinTest, abort)
{
CALL_FUNC(abort, 33);
EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.abort(33)");
dummy_exec_env.clear_exception();
}
TEST_F(LibcBuiltinTest, abortStackOverflow)
{
CALL_FUNC(abortStackOverflow, 33);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: env.abortStackOverflow(33)");
dummy_exec_env.clear_exception();
}
TEST_F(LibcBuiltinTest, nullFunc_X)
{
CALL_FUNC(nullFunc_X, 33);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: env.nullFunc_X(33)");
dummy_exec_env.clear_exception();
}
TEST_F(LibcBuiltinTest, __cxa_allocate_exception)
{
EXPECT_NE(CALL_FUNC(__cxa_allocate_exception, 0x0), 0x0);
EXPECT_EQ(CALL_FUNC(__cxa_allocate_exception, 0xFFFF), 0x0);
}
TEST_F(LibcBuiltinTest, __cxa_begin_catch)
{
/* 无函数原型 */
}
TEST_F(LibcBuiltinTest, __cxa_throw)
{
void *excepton;
void *tinfo;
CALL_FUNC(__cxa_throw, excepton, tinfo, 1);
EXPECT_STREQ(dummy_exec_env.get_exception(),
"Exception: exception thrown by stdc++");
dummy_exec_env.clear_exception();
}
struct timespec_app app;
TEST_F(LibcBuiltinTest, clock_gettime)
{
struct timespec_app *tsapp;
tsapp = &app;
AppMemory tsapp_app{ dummy_exec_env.get(), sizeof(struct timespec_app) };
/* exception */
EXPECT_EQ(CALL_FUNC(clock_gettime, 0, (struct timespec_app *)-1), -1);
EXPECT_EQ(CALL_FUNC(clock_gettime, 100, NULL), -1);
EXPECT_EQ(CALL_FUNC(clock_gettime, 100, 0), -1);
EXPECT_EQ(CALL_FUNC(clock_gettime, 10,
(struct timespec_app *)tsapp_app.get_native_addr()),
0);
}
TEST_F(LibcBuiltinTest, clock)
{
EXPECT_GE(CALL_FUNC(clock), 0);
}
WASMGlobalImport glb;
TEST_F(LibcBuiltinTest, wasm_native_lookup_libc_builtin_global)
{
const char *module_name = "module name";
const char *global_name = "global name";
const char *module_name1 = "global";
const char *global_name1 = "NaN";
const char *global_name2 = "Infinity";
WASMGlobalImport *global = &glb;
EXPECT_FALSE(
wasm_native_lookup_libc_builtin_global(NULL, global_name, global));
EXPECT_FALSE(
wasm_native_lookup_libc_builtin_global(module_name, NULL, global));
EXPECT_FALSE(
wasm_native_lookup_libc_builtin_global(module_name, global_name, NULL));
EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name,
global_name, global));
EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name,
global_name1, global));
EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1,
global_name1, global));
EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1,
global_name2, global));
}