* Copyright (c) 2021-2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/builtins/builtins_number.h"
#include <cmath>
#include <iostream>
#include "ecmascript/base/number_helper.h"
#include "ecmascript/base/string_helper.h"
#include "ecmascript/ecma_runtime_call_info.h"
#include "ecmascript/ecma_string.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/global_env.h"
#include "ecmascript/js_function.h"
#include "ecmascript/js_global_object.h"
#include "ecmascript/js_handle.h"
#include "ecmascript/js_primitive_ref.h"
#include "ecmascript/js_tagged_value-inl.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tests/test_helper.h"
using namespace panda::ecmascript;
using namespace panda::ecmascript::builtins;
namespace panda::test {
class BuiltinsNumberTest : public BaseTestWithScope<false> {
};
HWTEST_F_L0(BuiltinsNumberTest, NumberConstructor)
{
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> number(env->GetNumberFunction());
JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*number), 6);
ecmaRuntimeCallInfo->SetFunction(number.GetTaggedValue());
ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(5)));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::NumberConstructor(ecmaRuntimeCallInfo);
TestHelper::TearDownFrame(thread, prev);
JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
ASSERT_TRUE(value.IsECMAObject());
JSPrimitiveRef *ref = JSPrimitiveRef::Cast(value.GetTaggedObject());
ASSERT_EQ(ref->GetValue(thread).GetDouble(), 5.0);
}
HWTEST_F_L0(BuiltinsNumberTest, IsFinite)
{
const double value = -10;
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(value)));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, IsFinite1)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(base::MAX_VALUE));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, IsFinite2)
{
JSHandle<EcmaString> test = thread->GetEcmaVM()->GetFactory()->NewFromASCII("helloworld");
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, test.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, IsFinite3)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(base::NAN_VALUE));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, IsFinite4)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(base::POSITIVE_INFINITY));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, IsFinite5)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Undefined());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, IsFinite6)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Null());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, IsInteger)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(0.1));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::IsInteger(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, IsNaN)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(0.1));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::IsNaN(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, ToString1)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
auto ecmaVM = thread->GetEcmaVM();
JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
JSHandle<JSFunction> numberObject(env->GetNumberFunction());
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
JSHandle<JSPrimitiveRef> number = thread->GetEcmaVM()->GetFactory()->NewJSPrimitiveRef(numberObject, value);
auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo1->SetThis(number.GetTaggedValue());
ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(7.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
JSTaggedValue result1 = BuiltinsNumber::ToString(ecmaRuntimeCallInfo1);
ASSERT_TRUE(result1.IsString());
JSHandle<EcmaString> res1(thread, reinterpret_cast<EcmaString *>(result1.GetRawData()));
JSHandle<EcmaString> correctResult1 = factory->NewFromASCII("234.312256641535441");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res1, *correctResult1));
TestHelper::TearDownFrame(thread, prev);
auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo2->SetThis(JSTaggedValue(15));
ecmaRuntimeCallInfo2->SetCallArg(0, JSTaggedValue(4));
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
JSTaggedValue result2 = BuiltinsNumber::ToString(ecmaRuntimeCallInfo2);
ASSERT_TRUE(result2.IsString());
JSHandle<EcmaString> res2(thread, reinterpret_cast<EcmaString *>(result2.GetRawData()));
JSHandle<EcmaString> correctResult2 = factory->NewFromASCII("33");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res2, *correctResult2));
TestHelper::TearDownFrame(thread, prev);
auto ecmaRuntimeCallInfo3 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo3->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo3->SetThis(JSTaggedValue(5));
ecmaRuntimeCallInfo3->SetCallArg(0, JSTaggedValue(8));
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo3);
JSTaggedValue result3 = BuiltinsNumber::ToString(ecmaRuntimeCallInfo3);
ASSERT_TRUE(result3.IsString());
JSHandle<EcmaString> res3(thread, reinterpret_cast<EcmaString *>(result3.GetRawData()));
JSHandle<EcmaString> correctResult3 = factory->NewFromASCII("5");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res3, *correctResult3));
TestHelper::TearDownFrame(thread, prev);
auto ecmaRuntimeCallInfo4 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo4->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo4->SetThis(JSTaggedValue(0));
ecmaRuntimeCallInfo4->SetCallArg(0, JSTaggedValue(8));
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo4);
JSTaggedValue result4 = BuiltinsNumber::ToString(ecmaRuntimeCallInfo4);
ASSERT_TRUE(result4.IsString());
JSHandle<EcmaString> res4(thread, reinterpret_cast<EcmaString *>(result4.GetRawData()));
JSHandle<EcmaString> correctResult4 = factory->NewFromASCII("0");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res4, *correctResult4));
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, ToString2)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(-50));
ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(35));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
JSTaggedValue result1 = BuiltinsNumber::ToString(ecmaRuntimeCallInfo1);
ASSERT_TRUE(result1.IsString());
JSHandle<EcmaString> res1(thread, reinterpret_cast<EcmaString *>(result1.GetRawData()));
JSHandle<EcmaString> correctResult1 = factory->NewFromASCII("-1f");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res1, *correctResult1));
TestHelper::TearDownFrame(thread, prev);
auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo2->SetThis(JSTaggedValue(2));
ecmaRuntimeCallInfo2->SetCallArg(0, JSTaggedValue(2.5));
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
JSTaggedValue result2 = BuiltinsNumber::ToString(ecmaRuntimeCallInfo2);
ASSERT_TRUE(result2.IsString());
JSHandle<EcmaString> res2(thread, reinterpret_cast<EcmaString *>(result2.GetRawData()));
JSHandle<EcmaString> correctResult2 = factory->NewFromASCII("10");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res2, *correctResult2));
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, IsExponential)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> numberObject(env->GetNumberFunction());
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(5.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::ToExponential(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSHandle<EcmaString> correctResult = factory->NewFromASCII("1.23456e+2");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res, *correctResult));
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, ToFixed)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> numberObject(env->GetNumberFunction());
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(10.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::ToFixed(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSHandle<EcmaString> correctResult = factory->NewFromASCII("123.4560000000");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res, *correctResult));
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, ToFixed1)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> numberObject(env->GetNumberFunction());
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(30.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::ToFixed(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSHandle<EcmaString> correctResult = factory->NewFromASCII("123.456000000000003069544618483633");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res, *correctResult));
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, ToFixed2) {
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
auto ecmaVM = thread->GetEcmaVM();
JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
JSHandle<JSFunction> numberObject(env->GetNumberFunction());
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1e21));
JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
auto ecmaRuntimeCallInfo =
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(20.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::ToFixed(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSHandle<EcmaString> correctResult = factory->NewFromASCII("1e+21");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res, *correctResult));
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, ToPrecision)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> numberObject(env->GetNumberFunction());
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(8.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::ToPrecision(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSHandle<EcmaString> correctResult = factory->NewFromASCII("123.45600");
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *res, *correctResult));
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, parseFloat)
{
JSHandle<EcmaString> param = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0x123");
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, param.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::ParseFloat(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue(static_cast<double>(0)).GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, parseFloat1)
{
JSHandle<EcmaString> param = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0x123xx");
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, param.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::ParseFloat(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue(static_cast<double>(0)).GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, parseInt)
{
const char *number = "0x123";
JSHandle<EcmaString> param = thread->GetEcmaVM()->GetFactory()->NewFromASCII(number);
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, param.GetTaggedValue());
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(16.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsNumber::ParseInt(ecmaRuntimeCallInfo);
ASSERT_EQ(result.GetRawData(), JSTaggedValue(static_cast<int>(291)).GetRawData());
TestHelper::TearDownFrame(thread, prev);
}
HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleFlags)
{
JSHandle<EcmaString> str;
common::Span<const uint8_t> sp;
CVector<uint8_t> buf;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0a");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0b");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0o");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 00x");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 000.4_");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0.4);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0010.s ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 10);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0010e2");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 1000);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0010e+3_0");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 10000);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0x");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_TRUE(std::isnan(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_HEX)));
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0x10 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_HEX), 16);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0x1g");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_HEX + base::IGNORE_TRAILING), 1);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0xh");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_TRUE(std::isnan(
base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_HEX + base::IGNORE_TRAILING)));
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0O");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_TRUE(std::isnan(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_OCTAL)));
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0o10 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_OCTAL), 8);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0o1d");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_OCTAL | base::IGNORE_TRAILING),
1);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0o8");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_TRUE(std::isnan(
base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_OCTAL | base::IGNORE_TRAILING)));
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0b");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_TRUE(std::isnan(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_BINARY)));
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0b10 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_BINARY), 2);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0b1d");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_BINARY | base::IGNORE_TRAILING),
1);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0b2");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_TRUE(std::isnan(
base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_BINARY | base::IGNORE_TRAILING)));
}
HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleRadix)
{
JSHandle<EcmaString> str;
common::Span<const uint8_t> sp;
CVector<uint8_t> buf;
int radix;
radix = 0;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 100);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100.3e2 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 10030);
radix = 1;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0000 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 0);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0001 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_TRUE(std::isnan(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS)));
radix = 2;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 4);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 11 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 3);
radix = 3;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 9);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 21 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 7);
radix = 4;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 16);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 31 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 13);
radix = 8;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 64);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 71 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 57);
radix = 10;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 100);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0020 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 20);
radix = 16;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 256);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 1e ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 30);
radix = 18;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 324);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 1g ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 34);
radix = 25;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 625);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 1g ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 41);
radix = 36;
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 1296);
str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 1z ");
sp = EcmaStringAccessor(str).ToUtf8Span(thread, buf);
ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 71);
}
HWTEST_F_L0(BuiltinsNumberTest, NumberToString)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<EcmaString> res = factory->NewFromASCII("100");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(100)), res), 0);
res = factory->NewFromASCII("11223344");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(11223344)), res), 0);
res = factory->NewFromASCII("1234567890");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(1234567890)), res), 0);
res = factory->NewFromASCII("100");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.0))), res), 0);
res = factory->NewFromASCII("100.5");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.5))), res), 0);
res = factory->NewFromASCII("100.25");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.25))), res), 0);
res = factory->NewFromASCII("100.125");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.125))), res), 0);
res = factory->NewFromASCII("100.6125");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.6125))), res), 0);
res = factory->NewFromASCII("0.0006125");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(0.0006125))), res), 0);
res = factory->NewFromASCII("-0.0006125");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-0.0006125))), res), 0);
res = factory->NewFromASCII("-1234567890.0006125");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-1234567890.0006125))), res), 0);
res = factory->NewFromASCII("1234567890.0006125");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(1234567890.0006125))), res), 0);
res = factory->NewFromASCII("11234567890.000612");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(11234567890.0006125))), res), 0);
}
}