Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add float type and test cases for float and double type. #187

Merged
merged 12 commits into from
Nov 25, 2017
Merged
1 change: 1 addition & 0 deletions core/idl_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

struct IDLBoolean final : public IDLBaseHelper<bool> {};
struct IDLByte final : public IDLBaseHelper<int8_t> {};
struct IDLFloat final : public IDLBaseHelper<float> {};
struct IDLDouble final : public IDLBaseHelper<double> {};
struct IDLLongLong final : public IDLBaseHelper<int64_t> {};
struct IDLLong final : public IDLBaseHelper<int32_t> {};
Expand Down
1 change: 1 addition & 0 deletions core/js_type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ JS_TYPE_TRAITS_NUMBER(int32_t);
JS_TYPE_TRAITS_NUMBER(uint32_t);
JS_TYPE_TRAITS_NUMBER(int64_t);
JS_TYPE_TRAITS_NUMBER(uint64_t);
JS_TYPE_TRAITS_NUMBER(float);
JS_TYPE_TRAITS_NUMBER(double);

JS_TYPE_TRAITS_BOOLEAN(bool);
Expand Down
19 changes: 19 additions & 0 deletions core/native_type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ struct NativeTypeTraits<IDLByte> : public NativeTypeTraitsBase<IDLByte> {
}
};

// The double type is a floating point numeric type that corresponds to the set
// of finite double-precision 64 bit IEEE 754 floating point numbers.
template <>
struct NativeTypeTraits<IDLFloat> : public NativeTypeTraitsBase<IDLFloat> {
static float NativeValue(const Napi::Env& env, const Napi::Value& js_value) {
if (!js_value.IsNumber()) {
Napi::TypeError::New(env, "It's an invalid number.")
.ThrowAsJavaScriptException();
return 0.0f;
}

return js_value.ToNumber().FloatValue();
}

static bool IsTypeEquals(const Napi::Value& js_value) {
return js_value.IsNumber();
}
};

// The double type is a floating point numeric type that corresponds to the set
// of finite double-precision 64 bit IEEE 754 floating point numbers.
template <>
Expand Down
77 changes: 70 additions & 7 deletions test/interface_basic_types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ test('Test for IDL \'long long\' type', async () => {
// TypeScript's range.

expect(test_interface.longLongMethod(0)).toBe(0);
for (var i = Number.MIN_SAFE_INTEGER; i < Number.MAX_SAFE_INTEGER;
for (let i = Number.MIN_SAFE_INTEGER; i < Number.MAX_SAFE_INTEGER;
i += Math.floor(Math.random() * Number.MAX_SAFE_INTEGER / 1000)) {
expect(test_interface.longLongMethod(i)).toBe(i);
}
Expand Down Expand Up @@ -133,30 +133,93 @@ test('Test for IDL \'unsigned long long\' type', async () => {
// So we are not able to do overflow test and so on.

expect(test_interface.unsignedLongLongMethod(0)).toBe(0);
for (var i = 1; i < Number.MAX_SAFE_INTEGER;
for (let i = 1; i < Number.MAX_SAFE_INTEGER;
i += Math.floor(Math.random() * Number.MAX_SAFE_INTEGER / 1000)) {
expect(test_interface.unsignedLongLongMethod(i)).toBe(i);
}
expect(test_interface.unsignedLongLongMethod(-1) != -1).toBe(true);
});

test('Test for IDL \'float\' type', async () => {
let test_interface = new bacardi.TestInterface();

// The float type is a floating point numeric type that corresponds to the set
// of finite single-precision 32 bit IEEE 754 floating point numbers.

expect(test_interface.floatMethod(0.0)).toBe(0.0);

const base = 1 / 2;
const precision = 23;
for (let test_case = 0; test_case < 100; test_case++) {
// for fraction part
// create a random number that has 23 bits precision
let fraction = 1; // set the biggest bit.
for (let i = 1; i < precision; i++) {
if (Math.random() > 0.5)
fraction += base ** i;
}
fraction += base ** precision // set the smallest bit

// for exponent part
// test all value of exponent part
// because exponent value -127 is used to express 0
// so this must start from -126.
for (let i = -126; i <= 127; i++) {
let float_value = fraction * (2 ** i);
expect(test_interface.floatMethod(float_value)).toBe(float_value);
}

// these two cases are beyond the range of floating-point
let float_value = fraction * (2 ** -127);
expect(test_interface.floatMethod(float_value) != float_value).toBe(true);
float_value = fraction * (2 ** 128);
expect(test_interface.floatMethod(float_value) != float_value).toBe(true);
}

let float_min = 2 ** (-149);
;
expect(test_interface.floatMethod(float_min)).toBe(float_min);
// the value beyond the range of exponent
expect(test_interface.floatMethod(float_min / 2) != float_min / 2).toBe(true);
expect(test_interface.floatMethod(float_min / 2) != float_min / 2).toBe(true);
});

test('Test for IDL \'double\' type', async () => {
let test_interface = new bacardi.TestInterface();

// The double type is a floating point numeric type that corresponds to the
// set of finite double-precision 64 bit IEEE 754 floating point numbers.

expect(test_interface.doubleMethod(0.123456789012345))
.toBe(0.123456789012345);

// FIXME(zino): We should test for comparing single-precision floating point.

// FIXME(zino): We should check whether the type is restricted or
// unrestricted.
const base = 1 / 2;
const precision = 52;
for (let test_case = 0; test_case < 100; test_case++) {
// for fraction part
// create a random number that has 52 bits precision
let fraction = 1; // set the biggest bit.
for (let i = 1; i < precision; i++) {
if (Math.random() > 0.5)
fraction += base ** i;
}
fraction += base ** precision; // set the smallest bit

// for exponent part
// test all value of exponent part
// because exponent value -1022 is used to express 0
// so this must start from -1022.
for (let i = -1022; i <= 1023; i += Math.ceil(Math.random() * 100)) {
let double_value = fraction * (2 ** i);
expect(test_interface.doubleMethod(double_value)).toBe(double_value);
}
// Note that the range of double and the range of number in typescript is
// the same, so we can not test the value out of the range.
});

test('Test for IDL \'string\' type', async () => {
let test_interface = new bacardi.TestInterface();

// The string type is not exact matching WebIDL spec but it will convert
// UTF8 string in platform side.
expect(test_interface.stringMethod('Hello World!')).toBe('Hello World!');
Expand Down
4 changes: 4 additions & 0 deletions test/test_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ uint64_t TestInterface::UnsignedLongLongMethod(uint64_t number) {
return number;
}

float TestInterface::FloatMethod(float number) {
return number;
}

double TestInterface::DoubleMethod(double number) {
return number;
}
Expand Down
1 change: 1 addition & 0 deletions test/test_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class TestInterface {
uint16_t UnsignedShortMethod(uint16_t number);
uint32_t UnsignedLongMethod(uint32_t number);
uint64_t UnsignedLongLongMethod(uint64_t number);
float FloatMethod(float number);
double DoubleMethod(double number);
const std::string StringMethod(const std::string& string);

Expand Down
1 change: 1 addition & 0 deletions test/test_interface.idl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface TestInterface {
unsigned short unsignedShortMethod(unsigned short number);
unsigned long unsignedLongMethod(unsigned long number);
unsigned long long unsignedLongLongMethod(unsigned long long number);
float floatMethod(float number);
double doubleMethod(double number);
string stringMethod(string string);

Expand Down