Skip to content

Commit

Permalink
Add float type and test cases for float and double type. (#187)
Browse files Browse the repository at this point in the history
This patch includes the implementation of `float` type
and extensive test cases for `float` and `double` type.
- implementation of `float` type and its test interface.
- test cases for `float` and `double` type.
   
ISSUE=#182
  • Loading branch information
usefulhyun authored and romandev committed Nov 25, 2017
1 parent e848669 commit d47d88f
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 7 deletions.
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

0 comments on commit d47d88f

Please sign in to comment.