DUK_LOCAL void duk__selftest_types(void) { if (!(sizeof(duk_int8_t) == 1 && sizeof(duk_uint8_t) == 1 && sizeof(duk_int16_t) == 2 && sizeof(duk_uint16_t) == 2 && sizeof(duk_int32_t) == 4 && sizeof(duk_uint32_t) == 4)) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int{8,16,32}_t size"); } #if defined(DUK_USE_64BIT_OPS) if (!(sizeof(duk_int64_t) == 8 && sizeof(duk_uint64_t) == 8)) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int64_t size"); } #endif if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) { /* Some internal code now assumes that all duk_uint_t values * can be expressed with a duk_size_t. */ DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_size_t is smaller than duk_uint_t"); } if (!(sizeof(duk_int_t) >= 4)) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_int_t is not 32 bits"); } }
DUK_LOCAL void duk__selftest_cast_double_to_uint(void) { /* * https://github.com/svaarala/duktape/issues/127#issuecomment-77863473 */ duk_double_t d1, d2; duk_small_uint_t u; duk_double_t d1v, d2v; duk_small_uint_t uv; d1 = 1.0; u = (duk_small_uint_t) d1; d2 = (duk_double_t) u; if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to uint cast failed"); } /* Same test with volatiles */ d1v = 1.0; uv = (duk_small_uint_t) d1v; d2v = (duk_double_t) uv; if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to uint cast failed"); } }
DUK_LOCAL void duk__selftest_struct_align(void) { #if defined(DUK_USE_ALIGN_4) if ((sizeof(duk_hbuffer_fixed) % 4) != 0) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 4"); } #elif defined(DUK_USE_ALIGN_8) if ((sizeof(duk_hbuffer_fixed) % 8) != 0) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 8"); } #else /* no check */ #endif }
DUK_LOCAL void duk__selftest_twos_complement(void) { volatile int test; test = -1; if (((duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: two's complement arithmetic"); } }
DUK_LOCAL void duk__selftest_packed_tval(void) { #if defined(DUK_USE_PACKED_TVAL) if (sizeof(void *) > 4) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: packed duk_tval in use but sizeof(void *) > 4"); } #endif }
DUK_LOCAL void duk__selftest_bswap_macros(void) { duk_uint32_t x32; duk_uint16_t x16; duk_double_union du; duk_double_t du_diff; x16 = 0xbeefUL; x16 = DUK_BSWAP16(x16); if (x16 != (duk_uint16_t) 0xefbeUL) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP16"); } x32 = 0xdeadbeefUL; x32 = DUK_BSWAP32(x32); if (x32 != (duk_uint32_t) 0xefbeaddeUL) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP32"); } /* >>> struct.unpack('>d', '4000112233445566'.decode('hex')) * (2.008366013071895,) */ du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22; du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66; DUK_DBLUNION_BSWAP(&du); du_diff = du.d - 2.008366013071895; #if 0 DUK_FPRINTF(DUK_STDERR, "du_diff: %lg\n", (double) du_diff); #endif if (du_diff > 1e-15) { /* Allow very small lenience because some compilers won't parse * exact IEEE double constants (happened in matrix testing with * Linux gcc-4.8 -m32 at least). */ #if 0 DUK_FPRINTF(DUK_STDERR, "Result of DUK_DBLUNION_BSWAP: %02x %02x %02x %02x %02x %02x %02x %02x\n", (unsigned int) du.uc[0], (unsigned int) du.uc[1], (unsigned int) du.uc[2], (unsigned int) du.uc[3], (unsigned int) du.uc[4], (unsigned int) du.uc[5], (unsigned int) du.uc[6], (unsigned int) du.uc[7]); #endif DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_DBLUNION_BSWAP"); } }
DUK_LOCAL void duk__selftest_twos_complement(void) { volatile int test; test = -1; /* Note that byte order doesn't affect this test: all bytes in * 'test' will be 0xFF for two's complement. */ if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: two's complement arithmetic"); } }
DUK_INTERNAL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg) { DUK_UNREF(ctx); #ifdef DUK_USE_FILE_IO DUK_FPRINTF(DUK_STDERR, "FATAL %ld: %s\n", (long) code, (const char *) (msg ? msg : "null")); DUK_FFLUSH(DUK_STDERR); #else /* omit print */ #endif DUK_D(DUK_DPRINT("default fatal handler called, code %ld -> calling DUK_PANIC()", (long) code)); DUK_PANIC(code, msg); DUK_UNREACHABLE(); }
DUK_LOCAL void duk__selftest_byte_order(void) { duk__test_u32_union u1; duk__test_double_union u2; /* * >>> struct.pack('>d', 102030405060).encode('hex') * '4237c17c6dc40000' */ #if defined(DUK_USE_INTEGER_LE) u1.c[0] = 0xef; u1.c[1] = 0xbe; u1.c[2] = 0xad; u1.c[3] = 0xde; #elif defined(DUK_USE_INTEGER_ME) #error integer mixed endian not supported now #elif defined(DUK_USE_INTEGER_BE) u1.c[0] = 0xde; u1.c[1] = 0xad; u1.c[2] = 0xbe; u1.c[3] = 0xef; #else #error unknown integer endianness #endif #if defined(DUK_USE_DOUBLE_LE) u2.c[0] = 0x00; u2.c[1] = 0x00; u2.c[2] = 0xc4; u2.c[3] = 0x6d; u2.c[4] = 0x7c; u2.c[5] = 0xc1; u2.c[6] = 0x37; u2.c[7] = 0x42; #elif defined(DUK_USE_DOUBLE_ME) u2.c[0] = 0x7c; u2.c[1] = 0xc1; u2.c[2] = 0x37; u2.c[3] = 0x42; u2.c[4] = 0x00; u2.c[5] = 0x00; u2.c[6] = 0xc4; u2.c[7] = 0x6d; #elif defined(DUK_USE_DOUBLE_BE) u2.c[0] = 0x42; u2.c[1] = 0x37; u2.c[2] = 0xc1; u2.c[3] = 0x7c; u2.c[4] = 0x6d; u2.c[5] = 0xc4; u2.c[6] = 0x00; u2.c[7] = 0x00; #else #error unknown double endianness #endif if (u1.i != (duk_uint32_t) 0xdeadbeefUL) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_uint32_t byte order"); } if (u2.d != (double) 102030405060.0) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double byte order"); } }
DUK_LOCAL void duk__selftest_64bit_arithmetic(void) { #if defined(DUK_USE_64BIT_OPS) volatile duk_int64_t i; volatile duk_double_t d; /* Catch a double-to-int64 cast issue encountered in practice. */ d = 2147483648.0; i = (duk_int64_t) d; if (i != 0x80000000LL) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: casting 2147483648.0 to duk_int64_t failed"); } #else /* nop */ #endif }
DUK_LOCAL void duk__selftest_cast_double_to_uint32(void) { /* * This test fails on an exotic ARM target; double-to-uint * cast is incorrectly clamped to -signed- int highest value. * * https://github.com/svaarala/duktape/issues/336 */ duk_double_t dv; duk_uint32_t uv; dv = 3735928559.0; /* 0xdeadbeef in decimal */ uv = (duk_uint32_t) dv; if (uv != 0xdeadbeefUL) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_uint32_t cast failed"); } }
DUK_LOCAL void duk__selftest_double_union_size(void) { if (sizeof(duk__test_double_union) != 8) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: invalid union size"); } }
static void duk_selftest_union_size(void) { if (sizeof(duk_test_union) != 8) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: invalid union size"); } }