2022-07-04 11:13:58 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2022 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.
|
|
|
|
*/
|
|
|
|
|
2022-12-29 09:22:35 +00:00
|
|
|
#include "ecmascript/base/locale_helper.h"
|
2022-07-04 11:13:58 +00:00
|
|
|
#include "ecmascript/js_number_format.h"
|
|
|
|
#include "ecmascript/napi/jsnapi_helper.h"
|
|
|
|
#include "ecmascript/tests/test_helper.h"
|
|
|
|
|
|
|
|
using namespace panda::ecmascript;
|
|
|
|
|
|
|
|
namespace panda::test {
|
|
|
|
class JSNumberFormatTest : public testing::Test {
|
|
|
|
public:
|
|
|
|
static void SetUpTestCase()
|
|
|
|
{
|
|
|
|
GTEST_LOG_(INFO) << "SetUpTestCase";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TearDownTestCase()
|
|
|
|
{
|
|
|
|
GTEST_LOG_(INFO) << "TearDownCase";
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetUp() override
|
|
|
|
{
|
|
|
|
JSRuntimeOptions options;
|
|
|
|
#if PANDA_TARGET_LINUX
|
|
|
|
// for consistency requirement, use ohos_icu4j/data/icudt67l.dat as icu-data-path
|
|
|
|
options.SetIcuDataPath(ICU_PATH);
|
|
|
|
#endif
|
|
|
|
options.SetEnableForceGC(true);
|
|
|
|
instance = JSNApi::CreateEcmaVM(options);
|
|
|
|
instance->SetEnableForceGC(true);
|
|
|
|
ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
|
|
|
|
thread = instance->GetJSThread();
|
|
|
|
scope = new EcmaHandleScope(thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TearDown() override
|
|
|
|
{
|
|
|
|
TestHelper::DestroyEcmaVMWithScope(instance, scope);
|
|
|
|
}
|
|
|
|
|
|
|
|
EcmaVM *instance {nullptr};
|
|
|
|
ecmascript::EcmaHandleScope *scope {nullptr};
|
|
|
|
JSThread *thread {nullptr};
|
|
|
|
};
|
|
|
|
|
2022-07-05 08:49:21 +00:00
|
|
|
/**
|
|
|
|
* @tc.name: GetIcuCallTarget
|
|
|
|
* @tc.desc: Call "NewJSIntlIcuData" function Set IcuCallTarget,check whether the IcuCallTarget through
|
|
|
|
* "GetIcuCallTarget" function is within expectations then call "formatInt" function format
|
|
|
|
* Int type data and check the returned value is within expectations.
|
|
|
|
* @tc.type: FUNC
|
|
|
|
* @tc.require:
|
|
|
|
*/
|
2022-07-04 11:13:58 +00:00
|
|
|
HWTEST_F_L0(JSNumberFormatTest, GetIcuCallTarget)
|
|
|
|
{
|
|
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
|
|
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
|
|
|
|
|
|
|
JSHandle<JSTaggedValue> ctor = env->GetNumberFormatFunction();
|
|
|
|
JSHandle<JSNumberFormat> numberFormat =
|
|
|
|
JSHandle<JSNumberFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
|
|
|
|
|
|
|
|
icu::Locale icuLocale("en", "US");
|
|
|
|
icu::number::LocalizedNumberFormatter icuNumberFormatter =
|
|
|
|
icu::number::NumberFormatter::withLocale(icuLocale).roundingMode(UNUM_ROUND_HALFUP);
|
|
|
|
// Set IcuCallTarget
|
|
|
|
factory->NewJSIntlIcuData(numberFormat, icuNumberFormatter, JSNumberFormat::FreeIcuNumberformat);
|
|
|
|
icu::number::LocalizedNumberFormatter *resultIcuNumberFormatter = numberFormat->GetIcuCallTarget();
|
|
|
|
EXPECT_TRUE(resultIcuNumberFormatter != nullptr);
|
|
|
|
// Use IcuCallTarget format Int
|
|
|
|
int64_t value = -123456;
|
|
|
|
UErrorCode status = U_ZERO_ERROR;
|
|
|
|
icu::number::FormattedNumber formattedNumber = resultIcuNumberFormatter->formatInt(value, status);
|
|
|
|
icu::UnicodeString result = formattedNumber.toString(status);
|
2022-12-29 09:22:35 +00:00
|
|
|
JSHandle<EcmaString> stringValue = base::LocaleHelper::UStringToString(thread, result);
|
2022-08-24 11:25:56 +00:00
|
|
|
EXPECT_STREQ("-123,456", EcmaStringAccessor(stringValue).ToCString().c_str());
|
2022-07-04 11:13:58 +00:00
|
|
|
}
|
|
|
|
|
2022-07-05 08:49:21 +00:00
|
|
|
/**
|
|
|
|
* @tc.name: InitializeNumberFormat
|
|
|
|
* @tc.desc: Call "InitializeNumberFormat" function Initialize NumberFormat,and check whether the properties of
|
|
|
|
* the object is within expectations.
|
|
|
|
* @tc.type: FUNC
|
|
|
|
* @tc.require:
|
|
|
|
*/
|
2022-07-04 11:13:58 +00:00
|
|
|
HWTEST_F_L0(JSNumberFormatTest, InitializeNumberFormat)
|
|
|
|
{
|
|
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
|
|
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
|
|
|
|
|
|
|
JSHandle<JSTaggedValue> ctor = env->GetNumberFormatFunction();
|
|
|
|
JSHandle<JSNumberFormat> numberFormat =
|
|
|
|
JSHandle<JSNumberFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
|
2022-07-05 08:49:21 +00:00
|
|
|
EXPECT_TRUE(*numberFormat != nullptr);
|
2022-07-04 11:13:58 +00:00
|
|
|
|
|
|
|
JSHandle<JSTaggedValue> locales(factory->NewFromASCII("zh-Hans-CN"));
|
|
|
|
JSHandle<JSTaggedValue> undefinedOptions(thread, JSTaggedValue::Undefined());
|
|
|
|
JSNumberFormat::InitializeNumberFormat(thread, numberFormat, locales, undefinedOptions);
|
|
|
|
// Initialize attribute comparison
|
|
|
|
EXPECT_TRUE(numberFormat->GetNumberingSystem().IsUndefined());
|
|
|
|
JSHandle<EcmaString> localeStr(thread, numberFormat->GetLocale().GetTaggedObject());
|
2022-08-24 11:25:56 +00:00
|
|
|
EXPECT_STREQ("zh-Hans-CN", EcmaStringAccessor(localeStr).ToCString().c_str());
|
2022-07-04 11:13:58 +00:00
|
|
|
EXPECT_EQ(NotationOption::STANDARD, numberFormat->GetNotation());
|
|
|
|
EXPECT_EQ(CompactDisplayOption::SHORT, numberFormat->GetCompactDisplay());
|
|
|
|
EXPECT_EQ(SignDisplayOption::AUTO, numberFormat->GetSignDisplay());
|
|
|
|
EXPECT_EQ(CurrencyDisplayOption::SYMBOL, numberFormat->GetCurrencyDisplay());
|
|
|
|
EXPECT_EQ(CurrencySignOption::STANDARD, numberFormat->GetCurrencySign());
|
|
|
|
EXPECT_EQ(UnitDisplayOption::SHORT, numberFormat->GetUnitDisplay());
|
|
|
|
EXPECT_EQ(numberFormat->GetMinimumIntegerDigits().GetInt(), 1); // 1 : 1 default minimum integer
|
|
|
|
EXPECT_EQ(numberFormat->GetMinimumFractionDigits().GetInt(), 0); // 0 : 0 default minimum fraction
|
|
|
|
EXPECT_EQ(numberFormat->GetMaximumFractionDigits().GetInt(), 3); // 1 : 1 default maximum fraction
|
|
|
|
EXPECT_EQ(numberFormat->GetMinimumSignificantDigits().GetInt(), 0); // 0 : 0 default minimum sigfraction
|
|
|
|
EXPECT_EQ(numberFormat->GetMaximumSignificantDigits().GetInt(), 0); // 0 : 0 default maximum sigfraction
|
|
|
|
EXPECT_TRUE(numberFormat->GetUseGrouping().IsTrue());
|
|
|
|
EXPECT_TRUE(numberFormat->GetBoundFormat().IsUndefined());
|
|
|
|
EXPECT_TRUE(numberFormat->GetUnit().IsUndefined());
|
|
|
|
EXPECT_TRUE(numberFormat->GetCurrency().IsUndefined());
|
|
|
|
}
|
|
|
|
|
2022-07-05 08:49:21 +00:00
|
|
|
/**
|
|
|
|
* @tc.name: CurrencyDigits
|
|
|
|
* @tc.desc: If the ISO 4217 currency contains currency as an alphabetic code, return the minor unit value
|
|
|
|
* corresponding to the currency from the list
|
|
|
|
* @tc.type: FUNC
|
|
|
|
* @tc.require:
|
|
|
|
*/
|
2022-07-04 11:13:58 +00:00
|
|
|
HWTEST_F_L0(JSNumberFormatTest, CurrencyDigits)
|
|
|
|
{
|
2022-07-05 08:49:21 +00:00
|
|
|
// Alphabetic code:USD
|
2022-07-04 11:13:58 +00:00
|
|
|
icu::UnicodeString usdCurrency("USD");
|
|
|
|
// 2 : 2 fraction digits
|
|
|
|
EXPECT_EQ(JSNumberFormat::CurrencyDigits(usdCurrency), 2);
|
2022-07-05 08:49:21 +00:00
|
|
|
// Alphabetic code:EUR
|
2022-07-04 11:13:58 +00:00
|
|
|
icu::UnicodeString eurCurrency("EUR");
|
|
|
|
// 2 : 2 fraction digits
|
|
|
|
EXPECT_EQ(JSNumberFormat::CurrencyDigits(eurCurrency), 2);
|
2022-07-05 08:49:21 +00:00
|
|
|
// Alphabetic code:CHF
|
2022-07-04 11:13:58 +00:00
|
|
|
icu::UnicodeString numberCurrency("CHF");
|
|
|
|
// 2 : 2 fraction digits
|
|
|
|
EXPECT_EQ(JSNumberFormat::CurrencyDigits(numberCurrency), 2);
|
|
|
|
}
|
|
|
|
|
2022-07-05 08:49:21 +00:00
|
|
|
/**
|
|
|
|
* @tc.name: FormatNumeric
|
|
|
|
* @tc.desc: Call "InitializeNumberFormat" function Initialize NumberFormat,Set the sytle attribute of the object to
|
|
|
|
* decimal,construct a bigint type data,and the object calls the FormatNumeric method to interpret the bigint
|
|
|
|
* type data into the corresponding decimal, and check whether the decimal meets the expectation.
|
|
|
|
* @tc.type: FUNC
|
|
|
|
* @tc.require:
|
|
|
|
*/
|
2022-07-04 11:13:58 +00:00
|
|
|
HWTEST_F_L0(JSNumberFormatTest, FormatNumeric)
|
|
|
|
{
|
|
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
|
|
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
|
|
|
auto globalConst = thread->GlobalConstants();
|
|
|
|
|
|
|
|
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
|
|
|
|
JSHandle<JSTaggedValue> ctor = env->GetNumberFormatFunction();
|
|
|
|
JSHandle<JSNumberFormat> numberFormat =
|
|
|
|
JSHandle<JSNumberFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
|
|
|
|
|
|
|
|
JSHandle<JSTaggedValue> styleKey = globalConst->GetHandledStyleString();
|
|
|
|
JSHandle<JSTaggedValue> styleValue(factory->NewFromASCII("decimal"));
|
|
|
|
JSHandle<JSTaggedValue> localeString(factory->NewFromASCII("en-US"));
|
|
|
|
JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
|
|
|
|
JSObject::SetProperty(thread, optionsObj, styleKey, styleValue);
|
|
|
|
JSNumberFormat::InitializeNumberFormat(thread, numberFormat, localeString, JSHandle<JSTaggedValue>(optionsObj));
|
|
|
|
// format BigInt
|
|
|
|
JSHandle<JSTaggedValue> number(thread, JSTaggedValue(123456789));
|
|
|
|
JSHandle<BigInt> jsBigInt(thread, BigInt::NumberToBigInt(thread, number));
|
|
|
|
JSHandle<JSTaggedValue> formatResult =
|
|
|
|
JSNumberFormat::FormatNumeric(thread, numberFormat, jsBigInt.GetTaggedValue());
|
|
|
|
|
|
|
|
JSHandle<EcmaString> resultEcmaStr(thread, formatResult.GetTaggedValue());
|
2022-08-24 11:25:56 +00:00
|
|
|
EXPECT_STREQ("123,456,789", EcmaStringAccessor(resultEcmaStr).ToCString().c_str());
|
2022-07-04 11:13:58 +00:00
|
|
|
}
|
|
|
|
|
2022-07-05 08:49:21 +00:00
|
|
|
/**
|
|
|
|
* @tc.name: UnwrapNumberFormat
|
|
|
|
* @tc.desc: Construct an object,If it is a numberformat object,it will be returned.If it is an object of other types
|
|
|
|
* and inherits the numberformat object, it will get value from the fallbacksymbol key and return.
|
|
|
|
* @tc.type: FUNC
|
|
|
|
* @tc.require:
|
|
|
|
*/
|
2022-07-04 11:13:58 +00:00
|
|
|
HWTEST_F_L0(JSNumberFormatTest, UnwrapNumberFormat)
|
|
|
|
{
|
|
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
|
|
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
|
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
|
|
|
|
|
|
JSHandle<JSTaggedValue> numberFormatFunc = env->GetNumberFormatFunction();
|
2022-07-05 08:49:21 +00:00
|
|
|
JSHandle<JSTaggedValue> numberFormat(
|
|
|
|
factory->NewJSObjectByConstructor(JSHandle<JSFunction>(numberFormatFunc), numberFormatFunc));
|
|
|
|
|
2022-07-04 11:13:58 +00:00
|
|
|
Local<FunctionRef> numberFormatLocal = JSNApiHelper::ToLocal<FunctionRef>(numberFormatFunc);
|
|
|
|
JSHandle<JSTaggedValue> disPlayNamesFunc = env->GetDisplayNamesFunction();
|
|
|
|
Local<FunctionRef> disPlayNamesLocal = JSNApiHelper::ToLocal<FunctionRef>(disPlayNamesFunc);
|
2022-07-05 08:49:21 +00:00
|
|
|
// displaynames Inherit numberformat
|
2022-07-04 11:13:58 +00:00
|
|
|
disPlayNamesLocal->Inherit(vm, numberFormatLocal);
|
|
|
|
JSHandle<JSTaggedValue> disPlayNamesHandle = JSNApiHelper::ToJSHandle(disPlayNamesLocal);
|
|
|
|
JSHandle<JSTaggedValue> disPlayNamesObj(
|
|
|
|
factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(disPlayNamesHandle), disPlayNamesHandle));
|
2022-07-05 08:49:21 +00:00
|
|
|
// object has no Instance
|
2022-07-04 11:13:58 +00:00
|
|
|
JSHandle<JSTaggedValue> unwrapNumberFormat1 = JSNumberFormat::UnwrapNumberFormat(thread, numberFormat);
|
|
|
|
EXPECT_TRUE(JSTaggedValue::SameValue(numberFormat, unwrapNumberFormat1));
|
2022-07-05 08:49:21 +00:00
|
|
|
// object has Instance
|
2022-07-04 11:13:58 +00:00
|
|
|
JSHandle<JSTaggedValue> unwrapNumberFormat2 = JSNumberFormat::UnwrapNumberFormat(thread, disPlayNamesObj);
|
|
|
|
EXPECT_TRUE(unwrapNumberFormat2->IsUndefined());
|
|
|
|
}
|
|
|
|
} // namespace panda::test
|