Add int8/int64 tests and simplify error propagation. b=513783, r=jorendorff

This commit is contained in:
Dan Witte 2009-09-25 09:48:13 -07:00
Родитель 02e66e18b9
Коммит 4558ada580
7 изменённых файлов: 262 добавлений и 185 удалений

Просмотреть файл

@ -124,16 +124,16 @@ ToSource(JSContext* cx, jsval vp)
return "<<error converting value to string>>";
}
static nsresult
static bool
TypeError(JSContext* cx, const char* expected, jsval actual)
{
const char* src = ToSource(cx, actual);
JS_ReportErrorNumber(cx, GetErrorMessage, NULL,
CTYPESMSG_TYPE_ERROR, expected, src);
return NS_ERROR_FAILURE;
return false;
}
static nsresult
static bool
GetABI(PRUint16 aCallType, ffi_abi& aResult)
{
// determine the ABI from the subset of those available on the
@ -142,24 +142,24 @@ GetABI(PRUint16 aCallType, ffi_abi& aResult)
switch (aCallType) {
case nsIForeignLibrary::DEFAULT:
aResult = FFI_DEFAULT_ABI;
return NS_OK;
return true;
#if defined(XP_WIN32)
case nsIForeignLibrary::STDCALL:
aResult = FFI_STDCALL;
return NS_OK;
return true;
#endif
default:
return NS_ERROR_INVALID_ARG;
return false;
}
}
static nsresult
static bool
PrepareType(JSContext* aContext, jsval aType, Type& aResult)
{
// for now, the only types we accept are integer values.
if (!JSVAL_IS_INT(aType)) {
JS_ReportError(aContext, "Invalid type specification");
return NS_ERROR_FAILURE;
return false;
}
PRInt32 type = JSVAL_TO_INT(aType);
@ -205,15 +205,15 @@ PrepareType(JSContext* aContext, jsval aType, Type& aResult)
break;
default:
JS_ReportError(aContext, "Invalid type specification");
return NS_ERROR_NOT_IMPLEMENTED;
return false;
}
aResult.mType = type;
return NS_OK;
return true;
}
static nsresult
static bool
PrepareValue(JSContext* aContext, const Type& aType, jsval aValue, Value& aResult)
{
jsdouble d;
@ -330,10 +330,10 @@ PrepareValue(JSContext* aContext, const Type& aType, jsval aValue, Value& aResul
break;
default:
NS_NOTREACHED("invalid type");
return NS_ERROR_FAILURE;
return false;
}
return NS_OK;
return true;
}
static void
@ -384,7 +384,7 @@ PrepareReturnValue(const Type& aType, Value& aResult)
}
}
static nsresult
static bool
ConvertReturnValue(JSContext* aContext,
const Type& aResultType,
const Value& aResultValue,
@ -405,12 +405,12 @@ ConvertReturnValue(JSContext* aContext,
break;
case nsIForeignLibrary::INT32:
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mInt32), aValue))
return NS_ERROR_OUT_OF_MEMORY;
return false;
break;
case nsIForeignLibrary::INT64:
// Implicit conversion with loss of bits. :-[
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mInt64), aValue))
return NS_ERROR_OUT_OF_MEMORY;
return false;
break;
case nsIForeignLibrary::UINT8:
*aValue = INT_TO_JSVAL(aResultValue.mValue.mUint8);
@ -420,20 +420,20 @@ ConvertReturnValue(JSContext* aContext,
break;
case nsIForeignLibrary::UINT32:
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mUint32), aValue))
return NS_ERROR_OUT_OF_MEMORY;
return false;
break;
case nsIForeignLibrary::UINT64:
// Implicit conversion with loss of bits. :-[
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mUint64), aValue))
return NS_ERROR_OUT_OF_MEMORY;
return false;
break;
case nsIForeignLibrary::FLOAT:
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mFloat), aValue))
return NS_ERROR_OUT_OF_MEMORY;
return false;
break;
case nsIForeignLibrary::DOUBLE:
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mDouble), aValue))
return NS_ERROR_OUT_OF_MEMORY;
return false;
break;
case nsIForeignLibrary::STRING: {
if (!aResultValue.mValue.mPointer) {
@ -443,7 +443,7 @@ ConvertReturnValue(JSContext* aContext,
JSString *jsstring = JS_NewStringCopyZ(aContext,
reinterpret_cast<const char*>(aResultValue.mValue.mPointer));
if (!jsstring)
return NS_ERROR_OUT_OF_MEMORY;
return false;
*aValue = STRING_TO_JSVAL(jsstring);
}
@ -457,7 +457,7 @@ ConvertReturnValue(JSContext* aContext,
JSString *jsstring = JS_NewUCStringCopyZ(aContext,
reinterpret_cast<const jschar*>(aResultValue.mValue.mPointer));
if (!jsstring)
return NS_ERROR_OUT_OF_MEMORY;
return false;
*aValue = STRING_TO_JSVAL(jsstring);
}
@ -465,10 +465,10 @@ ConvertReturnValue(JSContext* aContext,
}
default:
NS_NOTREACHED("invalid type");
return NS_ERROR_FAILURE;
return false;
}
return NS_OK;
return true;
}
/*******************************************************************************
@ -486,7 +486,7 @@ Function::~Function()
{
}
nsresult
bool
Function::Init(JSContext* aContext,
Library* aLibrary,
PRFuncPtr aFunc,
@ -494,31 +494,28 @@ Function::Init(JSContext* aContext,
jsval aResultType,
const nsTArray<jsval>& aArgTypes)
{
nsresult rv;
mLibrary = aLibrary;
mFunc = aFunc;
// determine the ABI
rv = GetABI(aCallType, mCallType);
if (NS_FAILED(rv)) {
if (!GetABI(aCallType, mCallType)) {
JS_ReportError(aContext, "Invalid ABI specification");
return rv;
return false;
}
// prepare the result type
rv = PrepareType(aContext, aResultType, mResultType);
NS_ENSURE_SUCCESS(rv, rv);
if (!PrepareType(aContext, aResultType, mResultType))
return false;
// prepare the argument types
for (PRUint32 i = 0; i < aArgTypes.Length(); ++i) {
rv = PrepareType(aContext, aArgTypes[i], *mArgTypes.AppendElement());
NS_ENSURE_SUCCESS(rv, rv);
if (!PrepareType(aContext, aArgTypes[i], *mArgTypes.AppendElement()))
return false;
// disallow void argument types
if (mArgTypes[i].mType == nsIForeignLibrary::VOID) {
JS_ReportError(aContext, "Cannot have void argument type");
return NS_ERROR_INVALID_ARG;
return false;
}
// ffi_prep_cif requires an array of ffi_types; prepare it separately.
@ -529,29 +526,27 @@ Function::Init(JSContext* aContext,
&mResultType.mFFIType, mFFITypes.Elements());
switch (status) {
case FFI_OK:
return NS_OK;
return true;
case FFI_BAD_ABI:
JS_ReportError(aContext, "Invalid ABI specification");
return NS_ERROR_INVALID_ARG;
return false;
case FFI_BAD_TYPEDEF:
JS_ReportError(aContext, "Invalid type specification");
return NS_ERROR_INVALID_ARG;
return false;
default:
JS_ReportError(aContext, "Unknown libffi error");
return NS_ERROR_FAILURE;
return false;
}
}
PRBool
bool
Function::Execute(JSContext* aContext, PRUint32 aArgc, jsval* aArgv, jsval* aValue)
{
nsresult rv;
// prepare the values for each argument
nsAutoTArray<Value, 16> values;
for (PRUint32 i = 0; i < mArgTypes.Length(); ++i) {
rv = PrepareValue(aContext, mArgTypes[i], aArgv[i], *values.AppendElement());
if (NS_FAILED(rv)) return PR_FALSE;
if (!PrepareValue(aContext, mArgTypes[i], aArgv[i], *values.AppendElement()))
return false;
}
// create an array of pointers to each value, for passing to ffi_call
@ -573,10 +568,7 @@ Function::Execute(JSContext* aContext, PRUint32 aArgc, jsval* aArgv, jsval* aVal
JS_ResumeRequest(aContext, rc);
// prepare a JS object from the result
rv = ConvertReturnValue(aContext, mResultType, resultValue, aValue);
if (NS_FAILED(rv)) return PR_FALSE;
return PR_TRUE;
return ConvertReturnValue(aContext, mResultType, resultValue, aValue);
}
/*******************************************************************************
@ -602,19 +594,16 @@ Function::Call(nsIXPConnectWrappedNative* wrapper,
if (!mLibrary->IsOpen()) {
JS_ReportError(cx, "Library is not open");
*_retval = PR_FALSE;
return NS_ERROR_FAILURE;
return NS_OK;
}
if (argc != mArgTypes.Length()) {
JS_ReportError(cx, "Number of arguments does not match declaration");
*_retval = PR_FALSE;
return NS_ERROR_FAILURE;
return NS_OK;
}
*_retval = Execute(cx, argc, argv, vp);
if (!*_retval)
return NS_ERROR_FAILURE;
return NS_OK;
}

Просмотреть файл

@ -95,12 +95,12 @@ public:
Function();
nsresult Init(JSContext* aContext, Library* aLibrary, PRFuncPtr aFunc, PRUint16 aCallType, jsval aResultType, const nsTArray<jsval>& aArgTypes);
bool Init(JSContext* aContext, Library* aLibrary, PRFuncPtr aFunc, PRUint16 aCallType, jsval aResultType, const nsTArray<jsval>& aArgTypes);
private:
~Function();
PRBool Execute(JSContext* aContext, PRUint32 aArgc, jsval* aArgv, jsval* aValue);
bool Execute(JSContext* aContext, PRUint32 aArgc, jsval* aArgv, jsval* aValue);
protected:
// reference to the library our function is in

Просмотреть файл

@ -49,31 +49,31 @@
namespace mozilla {
namespace ctypes {
static inline nsresult
static inline bool
jsvalToUint16(JSContext* aContext, jsval aVal, PRUint16& aResult)
{
if (JSVAL_IS_INT(aVal)) {
PRUint32 i = JSVAL_TO_INT(aVal);
if (i <= PR_UINT16_MAX) {
aResult = i;
return NS_OK;
return true;
}
}
JS_ReportError(aContext, "Parameter must be a valid ABI constant");
return NS_ERROR_INVALID_ARG;
return false;
}
static inline nsresult
static inline bool
jsvalToCString(JSContext* aContext, jsval aVal, const char*& aResult)
{
if (JSVAL_IS_STRING(aVal)) {
aResult = JS_GetStringBytes(JSVAL_TO_STRING(aVal));
return NS_OK;
return true;
}
JS_ReportError(aContext, "Parameter must be a string");
return NS_ERROR_INVALID_ARG;
return false;
}
NS_IMPL_ISUPPORTS1(Library, nsIForeignLibrary)
@ -136,16 +136,16 @@ Library::Declare(nsISupports** aResult)
// we always need at least a method name, a call type and a return type
if (argc < 3) {
JS_ReportError(ctx, "Insufficient number of arguments");
return NS_ERROR_INVALID_ARG;
return NS_OK;
}
const char* name;
rv = jsvalToCString(ctx, argv[0], name);
NS_ENSURE_SUCCESS(rv, rv);
if (!jsvalToCString(ctx, argv[0], name))
return NS_OK;
PRUint16 callType;
rv = jsvalToUint16(ctx, argv[1], callType);
NS_ENSURE_SUCCESS(rv, rv);
if (!jsvalToUint16(ctx, argv[1], callType))
return NS_OK;
nsAutoTArray<jsval, 16> argTypes;
for (PRUint32 i = 3; i < argc; ++i) {
@ -155,15 +155,15 @@ Library::Declare(nsISupports** aResult)
PRFuncPtr func = PR_FindFunctionSymbol(mLibrary, name);
if (!func) {
JS_ReportError(ctx, "Couldn't find function symbol in library");
return NS_ERROR_FAILURE;
return NS_OK;
}
nsRefPtr<Function> call = new Function;
rv = call->Init(ctx, this, func, callType, argv[2], argTypes);
NS_ENSURE_SUCCESS(rv, rv);
if (!call->Init(ctx, this, func, callType, argv[2], argTypes))
return NS_OK;
call.forget(aResult);
return rv;
return NS_OK;
}
}

Просмотреть файл

@ -61,7 +61,7 @@ public:
Library();
PRBool IsOpen() { return mLibrary != nsnull; }
bool IsOpen() { return mLibrary != nsnull; }
private:
~Library();

Просмотреть файл

@ -50,38 +50,78 @@ test_v()
return;
}
short
test_s()
PRInt8
test_i8()
{
return 12345;
return 123;
}
short
test_s_s(short number)
PRInt8
test_i8_i8(PRInt8 number)
{
return number;
}
short
test_s_ss(short number1, short number2)
PRInt8
test_i8_i8_sum(PRInt8 number1, PRInt8 number2)
{
return number1 + number2;
}
int
test_i()
PRInt16
test_i16()
{
return 123456789;
return 12345;
}
int
test_i_i(int number)
PRInt16
test_i16_i16(PRInt16 number)
{
return number;
}
int
test_i_ii(int number1, int number2)
PRInt16
test_i16_i16_sum(PRInt16 number1, PRInt16 number2)
{
return number1 + number2;
}
PRInt32
test_i32()
{
return 123456789;
}
PRInt32
test_i32_i32(PRInt32 number)
{
return number;
}
PRInt32
test_i32_i32_sum(PRInt32 number1, PRInt32 number2)
{
return number1 + number2;
}
PRInt64
test_i64()
{
#if defined(WIN32) && !defined(__GNUC__)
return 0x28590a1c921de000i64;
#else
return 0x28590a1c921de000LL;
#endif
}
PRInt64
test_i64_i64(PRInt64 number)
{
return number;
}
PRInt64
test_i64_i64_sum(PRInt64 number1, PRInt64 number2)
{
return number1 + number2;
}
@ -99,7 +139,7 @@ test_f_f(float number)
}
float
test_f_ff(float number1, float number2)
test_f_f_sum(float number1, float number2)
{
return (number1 + number2);
}
@ -107,7 +147,7 @@ test_f_ff(float number1, float number2)
double
test_d()
{
return 123456789.5;
return 1234567890123456789.5;
}
double
@ -117,21 +157,21 @@ test_d_d(double number)
}
double
test_d_dd(double number1, double number2)
test_d_d_sum(double number1, double number2)
{
return (number1 + number2);
}
int
PRInt32
test_ansi_len(const char* string)
{
return int(strlen(string));
return PRInt32(strlen(string));
}
int
PRInt32
test_wide_len(const PRUnichar* string)
{
return int(NS_strlen(string));
return PRInt32(NS_strlen(string));
}
const char *
@ -153,9 +193,9 @@ test_ansi_echo(const char* string)
return (char*)string;
}
int
test_i_if_floor(int number1, float number2)
PRInt32
test_floor(PRInt32 number1, float number2)
{
return int(floor(float(number1) + number2));
return PRInt32(floor(float(number1) + number2));
}

Просмотреть файл

@ -39,62 +39,42 @@
* ***** END LICENSE BLOCK ***** */
#include "nscore.h"
#include "prtypes.h"
NS_EXTERN_C
{
NS_EXPORT void test_v();
NS_EXPORT short test_s();
NS_EXPORT short test_s_s(short);
NS_EXPORT short test_s_ss(short, short);
NS_EXPORT PRInt8 test_i8();
NS_EXPORT PRInt8 test_i8_i8(PRInt8);
NS_EXPORT PRInt8 test_i8_i8_sum(PRInt8, PRInt8);
NS_EXPORT int test_i();
NS_EXPORT int test_i_i(int);
NS_EXPORT int test_i_ii(int, int);
NS_EXPORT PRInt16 test_i16();
NS_EXPORT PRInt16 test_i16_i16(PRInt16);
NS_EXPORT PRInt16 test_i16_i16_sum(PRInt16, PRInt16);
NS_EXPORT PRInt32 test_i32();
NS_EXPORT PRInt32 test_i32_i32(PRInt32);
NS_EXPORT PRInt32 test_i32_i32_sum(PRInt32, PRInt32);
NS_EXPORT PRInt64 test_i64();
NS_EXPORT PRInt64 test_i64_i64(PRInt64);
NS_EXPORT PRInt64 test_i64_i64_sum(PRInt64, PRInt64);
NS_EXPORT float test_f();
NS_EXPORT float test_f_f(float);
NS_EXPORT float test_f_ff(float, float);
NS_EXPORT float test_f_f_sum(float, float);
NS_EXPORT double test_d();
NS_EXPORT double test_d_d(double);
NS_EXPORT double test_d_dd(double, double);
NS_EXPORT double test_d_d_sum(double, double);
NS_EXPORT int test_ansi_len(const char*);
NS_EXPORT int test_wide_len(const PRUnichar*);
NS_EXPORT PRInt32 test_ansi_len(const char*);
NS_EXPORT PRInt32 test_wide_len(const PRUnichar*);
NS_EXPORT const char* test_ansi_ret();
NS_EXPORT const PRUnichar* test_wide_ret();
NS_EXPORT char* test_ansi_echo(const char*);
NS_EXPORT int test_i_if_floor(int, float);
struct POINT {
int x;
int y;
};
struct RECT {
int top;
int left;
int bottom;
int right;
};
struct INNER {
unsigned char i1;
long long int i2;
char i3;
};
struct NESTED {
int n1;
short n2;
INNER inner;
long long int n3;
int n4;
};
NS_EXPORT int test_pt_in_rect(RECT, POINT);
NS_EXPORT int test_nested_struct(NESTED);
NS_EXPORT POINT test_struct_return(RECT);
NS_EXPORT PRInt32 test_floor(PRInt32, float);
}

Просмотреть файл

@ -77,8 +77,10 @@ function run_test()
var library = ctypes.open(libfile);
run_void_tests(library);
run_short_tests(library);
run_int_tests(library);
run_int8_tests(library);
run_int16_tests(library);
run_int32_tests(library);
run_int64_tests(library);
run_float_tests(library);
run_double_tests(library);
run_string_tests(library);
@ -95,18 +97,50 @@ function run_void_tests(library) {
do_check_eq(test_v(), undefined);
}
function run_short_tests(library) {
var test_s = library.declare("test_s", Types.DEFAULT, Types.INT16);
do_check_eq(test_s(), 12345);
function run_int8_tests(library) {
var test_i8 = library.declare("test_i8", Types.DEFAULT, Types.INT8);
do_check_eq(test_i8(), 123);
var test_s_s = library.declare("test_s_s", Types.DEFAULT, Types.INT16, Types.INT16);
do_check_eq(test_s_s(5), 5);
do_check_eq(test_s_s(0), 0);
do_check_eq(test_s_s(0x7fff), 0x7fff);
do_check_eq(test_s_s(-0x8000), -0x8000);
do_check_eq(1/test_s_s(-0), 1/0); // that is, test_s_s(-0) is +0
do_check_eq(test_s_s(true), 1);
do_check_eq(test_s_s(false), 0);
var test_i8_i8 = library.declare("test_i8_i8", Types.DEFAULT, Types.INT8, Types.INT8);
do_check_eq(test_i8_i8(5), 5);
do_check_eq(test_i8_i8(0), 0);
do_check_eq(test_i8_i8(0x7f), 0x7f);
do_check_eq(test_i8_i8(-0x80), -0x80);
do_check_eq(1/test_i8_i8(-0), 1/0); // that is, test_i8_i8(-0) is +0
do_check_eq(test_i8_i8(true), 1);
do_check_eq(test_i8_i8(false), 0);
// don't convert anything else to an int8
var vals = [0x80, -0x81, 0x100000000, Infinity, -Infinity, NaN,
null, undefined, "", "0", {}, [], new Number(16),
{toString: function () { return 7; }},
{valueOf: function () { return 7; }}];
for (var i = 0; i < vals.length; i++)
do_check_throws(function () { test_i8_i8(vals[i]); }, TypeError);
var test_i8_i8_sum = library.declare("test_i8_i8_sum", Types.DEFAULT, Types.INT8, Types.INT8, Types.INT8);
do_check_eq(test_i8_i8_sum(5, 5), 10);
// test the range of unsigned. (we can reuse the signed C function
// here, since it's binary-compatible.)
var test_ui8_ui8 = library.declare("test_i8_i8", Types.DEFAULT, Types.UINT8, Types.UINT8);
do_check_eq(test_ui8_ui8(0xff), 0xff);
do_check_throws(function () { test_ui8_ui8(0x100); }, TypeError);
do_check_throws(function () { test_ui8_ui8(-1); }, TypeError);
}
function run_int16_tests(library) {
var test_i16 = library.declare("test_i16", Types.DEFAULT, Types.INT16);
do_check_eq(test_i16(), 12345);
var test_i16_i16 = library.declare("test_i16_i16", Types.DEFAULT, Types.INT16, Types.INT16);
do_check_eq(test_i16_i16(5), 5);
do_check_eq(test_i16_i16(0), 0);
do_check_eq(test_i16_i16(0x7fff), 0x7fff);
do_check_eq(test_i16_i16(-0x8000), -0x8000);
do_check_eq(1/test_i16_i16(-0), 1/0); // that is, test_i16_i16(-0) is +0
do_check_eq(test_i16_i16(true), 1);
do_check_eq(test_i16_i16(false), 0);
// don't convert anything else to an int16
var vals = [0x8000, -0x8001, 0x100000000, Infinity, -Infinity, NaN,
@ -114,49 +148,83 @@ function run_short_tests(library) {
{toString: function () { return 7; }},
{valueOf: function () { return 7; }}];
for (var i = 0; i < vals.length; i++)
do_check_throws(function () { test_s_s(vals[i]); }, TypeError);
do_check_throws(function () { test_i16_i16(vals[i]); }, TypeError);
var test_s_ss = library.declare("test_s_ss", Types.DEFAULT, Types.INT16, Types.INT16, Types.INT16);
do_check_eq(test_s_ss(5, 5), 10);
var test_i16_i16_sum = library.declare("test_i16_i16_sum", Types.DEFAULT, Types.INT16, Types.INT16, Types.INT16);
do_check_eq(test_i16_i16_sum(5, 5), 10);
// test the range of unsigned. (we can reuse the signed C function
// here, since it's binary-compatible.)
var test_us_us = library.declare("test_s_s", Types.DEFAULT, Types.UINT16, Types.UINT16);
do_check_eq(test_us_us(0xffff), 0xffff);
do_check_throws(function () { test_us_us(0x10000); }, TypeError);
do_check_throws(function () { test_us_us(-1); }, TypeError);
var test_ui16_ui16 = library.declare("test_i16_i16", Types.DEFAULT, Types.UINT16, Types.UINT16);
do_check_eq(test_ui16_ui16(0xffff), 0xffff);
do_check_throws(function () { test_ui16_ui16(0x10000); }, TypeError);
do_check_throws(function () { test_ui16_ui16(-1); }, TypeError);
}
function run_int_tests(library) {
var test_i = library.declare("test_i", Types.DEFAULT, Types.INT32);
do_check_eq(test_i(), 123456789);
function run_int32_tests(library) {
var test_i32 = library.declare("test_i32", Types.DEFAULT, Types.INT32);
do_check_eq(test_i32(), 123456789);
var test_i_i = library.declare("test_i_i", Types.DEFAULT, Types.INT32, Types.INT32);
do_check_eq(test_i_i(5), 5);
do_check_eq(test_i_i(0), 0);
do_check_eq(test_i_i(0x7fffffff), 0x7fffffff);
do_check_eq(test_i_i(-0x80000000), -0x80000000);
do_check_eq(1/test_i_i(-0), 1/0); // that is, test_i_i(-0) is +0
do_check_eq(test_i_i(true), 1);
do_check_eq(test_i_i(false), 0);
var test_i32_i32 = library.declare("test_i32_i32", Types.DEFAULT, Types.INT32, Types.INT32);
do_check_eq(test_i32_i32(5), 5);
do_check_eq(test_i32_i32(0), 0);
do_check_eq(test_i32_i32(0x7fffffff), 0x7fffffff);
do_check_eq(test_i32_i32(-0x80000000), -0x80000000);
do_check_eq(1/test_i32_i32(-0), 1/0); // that is, test_i32_i32(-0) is +0
do_check_eq(test_i32_i32(true), 1);
do_check_eq(test_i32_i32(false), 0);
// don't convert anything else to an int
// don't convert anything else to an int32
var vals = [0x80000000, -0x80000001, Infinity, -Infinity, NaN,
null, undefined, "", "0", {}, [], new Number(16),
{toString: function () { return 7; }},
{valueOf: function () { return 7; }}];
for (var i = 0; i < vals.length; i++)
do_check_throws(function () { test_i_i(vals[i]); }, TypeError);
do_check_throws(function () { test_i32_i32(vals[i]); }, TypeError);
var test_i_ii = library.declare("test_i_ii", Types.DEFAULT, Types.INT32, Types.INT32, Types.INT32);
do_check_eq(test_i_ii(5, 5), 10);
var test_i32_i32_sum = library.declare("test_i32_i32_sum", Types.DEFAULT, Types.INT32, Types.INT32, Types.INT32);
do_check_eq(test_i32_i32_sum(5, 5), 10);
// test the range of unsigned. (we can reuse the signed C function
// here, since it's binary-compatible.)
var test_ui_ui = library.declare("test_i_i", Types.DEFAULT, Types.UINT32, Types.UINT32);
do_check_eq(test_ui_ui(0xffffffff), 0xffffffff);
do_check_throws(function () { test_ui_ui(0x100000000); }, TypeError);
do_check_throws(function () { test_ui_ui(-1); }, TypeError);
var test_ui32_ui32 = library.declare("test_i32_i32", Types.DEFAULT, Types.UINT32, Types.UINT32);
do_check_eq(test_ui32_ui32(0xffffffff), 0xffffffff);
do_check_throws(function () { test_ui32_ui32(0x100000000); }, TypeError);
do_check_throws(function () { test_ui32_ui32(-1); }, TypeError);
}
function run_int64_tests(library) {
var test_i64 = library.declare("test_i64", Types.DEFAULT, Types.INT64);
// JS represents 64 bit ints as doubles, so we have to be careful how many
// significant digits we use
do_check_eq(test_i64(), 0x28590a1c921de000);
var test_i64_i64 = library.declare("test_i64_i64", Types.DEFAULT, Types.INT64, Types.INT64);
do_check_eq(test_i64_i64(5), 5);
do_check_eq(test_i64_i64(0), 0);
do_check_eq(test_i64_i64(0x7ffffffffffffc00), 0x7ffffffffffffc00);
do_check_eq(test_i64_i64(-0x8000000000000000), -0x8000000000000000);
do_check_eq(1/test_i64_i64(-0), 1/0); // that is, test_i64_i64(-0) is +0
do_check_eq(test_i64_i64(true), 1);
do_check_eq(test_i64_i64(false), 0);
// don't convert anything else to an int64
var vals = [0x8000000000000000, -0x8000000000001000, Infinity, -Infinity, NaN,
null, undefined, "", "0", {}, [], new Number(16),
{toString: function () { return 7; }},
{valueOf: function () { return 7; }}];
for (var i = 0; i < vals.length; i++)
do_check_throws(function () { test_i64_i64(vals[i]); }, TypeError);
var test_i64_i64_sum = library.declare("test_i64_i64_sum", Types.DEFAULT, Types.INT64, Types.INT64, Types.INT64);
do_check_eq(test_i64_i64_sum(5, 5), 10);
// test the range of unsigned. (we can reuse the signed C function
// here, since it's binary-compatible.)
var test_ui64_ui64 = library.declare("test_i64_i64", Types.DEFAULT, Types.UINT64, Types.UINT64);
do_check_eq(test_ui64_ui64(0xfffffffffffff800), 0xfffffffffffff800);
do_check_throws(function () { test_ui64_ui64(0x10000000000000000); }, TypeError);
do_check_throws(function () { test_ui64_ui64(-1); }, TypeError);
}
function run_float_tests(library) {
@ -181,14 +249,14 @@ function run_float_tests(library) {
for (var i = 0; i < vals.length; i++)
do_check_throws(function () { test_f_f(vals[i]); }, TypeError);
var test_f_ff = library.declare("test_f_ff", Types.DEFAULT, Types.FLOAT, Types.FLOAT, Types.FLOAT);
do_check_eq(test_f_ff(5, 5), 10);
do_check_eq(test_f_ff(5.5, 5.5), 11);
var test_f_f_sum = library.declare("test_f_f_sum", Types.DEFAULT, Types.FLOAT, Types.FLOAT, Types.FLOAT);
do_check_eq(test_f_f_sum(5, 5), 10);
do_check_eq(test_f_f_sum(5.5, 5.5), 11);
}
function run_double_tests(library) {
var test_d = library.declare("test_d", Types.DEFAULT, Types.DOUBLE);
do_check_eq(test_d(), 123456789.5);
do_check_eq(test_d(), 1234567890123456789.5);
var test_d_d = library.declare("test_d_d", Types.DEFAULT, Types.DOUBLE, Types.DOUBLE);
do_check_eq(test_d_d(5), 5);
@ -205,9 +273,9 @@ function run_double_tests(library) {
for (var i = 0; i < vals.length; i++)
do_check_throws(function () { test_d_d(vals[i]); }, TypeError);
var test_d_dd = library.declare("test_d_dd", Types.DEFAULT, Types.DOUBLE, Types.DOUBLE, Types.DOUBLE);
do_check_eq(test_d_dd(5, 5), 10);
do_check_eq(test_d_dd(5.5, 5.5), 11);
var test_d_d_sum = library.declare("test_d_d_sum", Types.DEFAULT, Types.DOUBLE, Types.DOUBLE, Types.DOUBLE);
do_check_eq(test_d_d_sum(5, 5), 10);
do_check_eq(test_d_d_sum(5.5, 5.5), 11);
}
function run_string_tests(library) {
@ -235,8 +303,8 @@ function run_string_tests(library) {
}
function run_mixed_tests(library) {
var test_i_if_floor = library.declare("test_i_if_floor", Types.DEFAULT, Types.INT32, Types.INT32, Types.FLOAT);
do_check_eq(test_i_if_floor(5, 5.5), 10);
do_check_throws(function() { test_i_if_floor(5.5, 5); }, TypeError);
var test_floor = library.declare("test_floor", Types.DEFAULT, Types.INT32, Types.INT32, Types.FLOAT);
do_check_eq(test_floor(5, 5.5), 10);
do_check_throws(function() { test_floor(5.5, 5); }, TypeError);
}