From 4558ada580d812b8189f3fe341fa4c9eab5f5bf7 Mon Sep 17 00:00:00 2001 From: Dan Witte Date: Fri, 25 Sep 2009 09:48:13 -0700 Subject: [PATCH] Add int8/int64 tests and simplify error propagation. b=513783, r=jorendorff --- js/ctypes/Function.cpp | 95 ++++++------- js/ctypes/Function.h | 4 +- js/ctypes/Library.cpp | 30 ++-- js/ctypes/Library.h | 2 +- js/ctypes/tests/jsctypes-test.cpp | 88 ++++++++---- js/ctypes/tests/jsctypes-test.h | 62 +++------ js/ctypes/tests/unit/test_jsctypes.js.in | 166 ++++++++++++++++------- 7 files changed, 262 insertions(+), 185 deletions(-) diff --git a/js/ctypes/Function.cpp b/js/ctypes/Function.cpp index 4d8cecaab7e..d170f05a5b1 100644 --- a/js/ctypes/Function.cpp +++ b/js/ctypes/Function.cpp @@ -124,16 +124,16 @@ ToSource(JSContext* cx, jsval vp) return "<>"; } -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(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(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& 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 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; } diff --git a/js/ctypes/Function.h b/js/ctypes/Function.h index 7b4e6c88d68..1e575d0dd15 100644 --- a/js/ctypes/Function.h +++ b/js/ctypes/Function.h @@ -95,12 +95,12 @@ public: Function(); - nsresult Init(JSContext* aContext, Library* aLibrary, PRFuncPtr aFunc, PRUint16 aCallType, jsval aResultType, const nsTArray& aArgTypes); + bool Init(JSContext* aContext, Library* aLibrary, PRFuncPtr aFunc, PRUint16 aCallType, jsval aResultType, const nsTArray& 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 diff --git a/js/ctypes/Library.cpp b/js/ctypes/Library.cpp index bd5e6027003..4d944006904 100644 --- a/js/ctypes/Library.cpp +++ b/js/ctypes/Library.cpp @@ -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 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 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; } } diff --git a/js/ctypes/Library.h b/js/ctypes/Library.h index 128ea484265..9df8b89fc69 100644 --- a/js/ctypes/Library.h +++ b/js/ctypes/Library.h @@ -61,7 +61,7 @@ public: Library(); - PRBool IsOpen() { return mLibrary != nsnull; } + bool IsOpen() { return mLibrary != nsnull; } private: ~Library(); diff --git a/js/ctypes/tests/jsctypes-test.cpp b/js/ctypes/tests/jsctypes-test.cpp index 34db5f11ad3..6194196c3cf 100644 --- a/js/ctypes/tests/jsctypes-test.cpp +++ b/js/ctypes/tests/jsctypes-test.cpp @@ -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)); } diff --git a/js/ctypes/tests/jsctypes-test.h b/js/ctypes/tests/jsctypes-test.h index 861d18154f3..7e1f8108067 100644 --- a/js/ctypes/tests/jsctypes-test.h +++ b/js/ctypes/tests/jsctypes-test.h @@ -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); } + diff --git a/js/ctypes/tests/unit/test_jsctypes.js.in b/js/ctypes/tests/unit/test_jsctypes.js.in index cc2f774db99..669d9970111 100644 --- a/js/ctypes/tests/unit/test_jsctypes.js.in +++ b/js/ctypes/tests/unit/test_jsctypes.js.in @@ -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); }