blob: 897872b4ee076200626a703e9edad2da1c10bf9a [file] [edit]
#include <assert.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wasm-rt.h"
#include "wasm-rt-impl.h"
int g_tests_run;
int g_tests_passed;
static void run_spec_tests(void);
static void error(const char* file, int line, const char* format, ...) {
va_list args;
va_start(args, format);
fprintf(stderr, "%s:%d: assertion failed: ", file, line);
vfprintf(stderr, format, args);
va_end(args);
}
#define ASSERT_TRAP(f) \
do { \
g_tests_run++; \
if (wasm_rt_impl_try() != 0) { \
g_tests_passed++; \
} else { \
(void)(f); \
error(__FILE__, __LINE__, "expected " #f " to trap.\n"); \
} \
} while (0)
#define ASSERT_EXHAUSTION(f) \
do { \
g_tests_run++; \
wasm_rt_trap_t code = wasm_rt_impl_try(); \
switch (code) { \
case WASM_RT_TRAP_NONE: \
(void)(f); \
error(__FILE__, __LINE__, "expected " #f " to trap.\n"); \
break; \
case WASM_RT_TRAP_EXHAUSTION: \
g_tests_passed++; \
break; \
default: \
error(__FILE__, __LINE__, \
"expected " #f \
" to trap due to exhaustion, got trap code %d.\n", \
code); \
break; \
} \
} while (0)
#define ASSERT_RETURN(f) \
do { \
g_tests_run++; \
if (wasm_rt_impl_try() != 0) { \
error(__FILE__, __LINE__, #f " trapped.\n"); \
} else { \
f; \
g_tests_passed++; \
} \
} while (0)
#define ASSERT_RETURN_T(type, fmt, f, expected) \
do { \
g_tests_run++; \
if (wasm_rt_impl_try() != 0) { \
error(__FILE__, __LINE__, #f " trapped.\n"); \
} else { \
type actual = f; \
if (is_equal_##type(actual, expected)) { \
g_tests_passed++; \
} else { \
error(__FILE__, __LINE__, \
"in " #f ": expected %" fmt ", got %" fmt ".\n", expected, \
actual); \
} \
} \
} while (0)
#define ASSERT_RETURN_NAN_T(type, itype, fmt, f, kind) \
do { \
g_tests_run++; \
if (wasm_rt_impl_try() != 0) { \
error(__FILE__, __LINE__, #f " trapped.\n"); \
} else { \
type actual = f; \
itype iactual; \
memcpy(&iactual, &actual, sizeof(iactual)); \
if (is_##kind##_nan_##type(iactual)) { \
g_tests_passed++; \
} else { \
error(__FILE__, __LINE__, \
"in " #f ": expected result to be a " #kind " nan, got 0x%" fmt \
".\n", \
iactual); \
} \
} \
} while (0)
#define ASSERT_RETURN_I32(f, expected) ASSERT_RETURN_T(u32, "u", f, expected)
#define ASSERT_RETURN_I64(f, expected) ASSERT_RETURN_T(u64, PRIu64, f, expected)
#define ASSERT_RETURN_F32(f, expected) ASSERT_RETURN_T(f32, ".9g", f, expected)
#define ASSERT_RETURN_F64(f, expected) ASSERT_RETURN_T(f64, ".17g", f, expected)
#define ASSERT_RETURN_CANONICAL_NAN_F32(f) \
ASSERT_RETURN_NAN_T(f32, u32, "08x", f, canonical)
#define ASSERT_RETURN_CANONICAL_NAN_F64(f) \
ASSERT_RETURN_NAN_T(f64, u64, "016x", f, canonical)
#define ASSERT_RETURN_ARITHMETIC_NAN_F32(f) \
ASSERT_RETURN_NAN_T(f32, u32, "08x", f, arithmetic)
#define ASSERT_RETURN_ARITHMETIC_NAN_F64(f) \
ASSERT_RETURN_NAN_T(f64, u64, "016x", f, arithmetic)
static bool is_equal_u32(u32 x, u32 y) {
return x == y;
}
static bool is_equal_u64(u64 x, u64 y) {
return x == y;
}
static bool is_equal_f32(f32 x, f32 y) {
u32 ux, uy;
memcpy(&ux, &x, sizeof(ux));
memcpy(&uy, &y, sizeof(uy));
return ux == uy;
}
static bool is_equal_f64(f64 x, f64 y) {
u64 ux, uy;
memcpy(&ux, &x, sizeof(ux));
memcpy(&uy, &y, sizeof(uy));
return ux == uy;
}
static f32 make_nan_f32(u32 x) {
x |= 0x7f800000;
f32 res;
memcpy(&res, &x, sizeof(res));
return res;
}
static f64 make_nan_f64(u64 x) {
x |= 0x7ff0000000000000;
f64 res;
memcpy(&res, &x, sizeof(res));
return res;
}
static bool is_canonical_nan_f32(u32 x) {
return (x & 0x7fffffff) == 0x7fc00000;
}
static bool is_canonical_nan_f64(u64 x) {
return (x & 0x7fffffffffffffff) == 0x7ff8000000000000;
}
static bool is_arithmetic_nan_f32(u32 x) {
return (x & 0x7fc00000) == 0x7fc00000;
}
static bool is_arithmetic_nan_f64(u64 x) {
return (x & 0x7ff8000000000000) == 0x7ff8000000000000;
}
/*
* spectest implementations
*/
static void spectest_print(void) {
printf("spectest.print()\n");
}
static void spectest_print_i32(uint32_t i) {
printf("spectest.print_i32(%d)\n", i);
}
static void spectest_print_f32(float f) {
printf("spectest.print_f32(%g)\n", f);
}
static void spectest_print_i32_f32(uint32_t i, float f) {
printf("spectest.print_i32_f32(%d %g)\n", i, f);
}
static void spectest_print_f64(double d) {
printf("spectest.print_f64(%g)\n", d);
}
static void spectest_print_f64_f64(double d1, double d2) {
printf("spectest.print_f64_f64(%g %g)\n", d1, d2);
}
static wasm_rt_table_t spectest_table;
static wasm_rt_memory_t spectest_memory;
static uint32_t spectest_global_i32 = 666;
void (*Z_spectestZ_printZ_vv)(void) = &spectest_print;
void (*Z_spectestZ_print_i32Z_vi)(uint32_t) = &spectest_print_i32;
void (*Z_spectestZ_print_f32Z_vf)(float) = &spectest_print_f32;
void (*Z_spectestZ_print_i32_f32Z_vif)(uint32_t,
float) = &spectest_print_i32_f32;
void (*Z_spectestZ_print_f64Z_vd)(double) = &spectest_print_f64;
void (*Z_spectestZ_print_f64_f64Z_vdd)(double,
double) = &spectest_print_f64_f64;
wasm_rt_table_t* Z_spectestZ_table = &spectest_table;
wasm_rt_memory_t* Z_spectestZ_memory = &spectest_memory;
uint32_t* Z_spectestZ_global_i32Z_i = &spectest_global_i32;
static void init_spectest_module(void) {
wasm_rt_allocate_memory(&spectest_memory, 1, 2);
wasm_rt_allocate_table(&spectest_table, 10, 20);
}
int main(int argc, char** argv) {
init_spectest_module();
run_spec_tests();
printf("%u/%u tests passed.\n", g_tests_passed, g_tests_run);
return g_tests_passed != g_tests_run;
}