arkcompiler_ets_runtime/ecmascript/tests/locale_helper_test.cpp
zhujie81 4f1af05245 Internationalized module isolation scheme (function isolation)
Isolation intl function code

https://e.gitee.com/open_harmony/dashboard?issue=I6F2WR

Signed-off-by: zhujie81 <zhujie81@huawei.com>
2023-03-13 14:52:07 +08:00

352 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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.
*/
#include "ecmascript/intl/locale_helper.h"
#include "ecmascript/ecma_string.h"
#include "ecmascript/global_env.h"
#include "ecmascript/js_collator.h"
#include "ecmascript/tests/test_helper.h"
using namespace panda::ecmascript;
using namespace panda::ecmascript::base;
using LocaleHelper = panda::ecmascript::intl::LocaleHelper;
namespace panda::test {
class LocaleHelperTest : 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 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};
};
/**
* @tc.name: UStringToString
* @tc.desc: Call "UStringToString" function Convert UnicodeString to string(Utf16).
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F_L0(LocaleHelperTest, UStringToString)
{
icu::UnicodeString unicodeString1("GMT-12:00"); // times
JSHandle<EcmaString> ecmaString = LocaleHelper::UStringToString(thread, unicodeString1);
EXPECT_STREQ("GMT-12:00", EcmaStringAccessor(ecmaString).ToCString().c_str());
icu::UnicodeString unicodeString2("周日16:00:00周五23:00:00"); // date
ecmaString = LocaleHelper::UStringToString(thread, unicodeString2);
EXPECT_STREQ("周日16:00:00周五23:00:00", EcmaStringAccessor(ecmaString).ToCString().c_str());
icu::UnicodeString unicodeString3("$654K"); // money
ecmaString = LocaleHelper::UStringToString(thread, unicodeString3);
EXPECT_STREQ("$654K", EcmaStringAccessor(ecmaString).ToCString().c_str());
icu::UnicodeString unicodeString4("1 minute ago"); // moment
ecmaString = LocaleHelper::UStringToString(thread, unicodeString4, 0, 2);
EXPECT_STREQ("1 ", EcmaStringAccessor(ecmaString).ToCString().c_str());
}
/**
* @tc.name: CanonicalizeLocaleList
* @tc.desc: Create a list of locales and canonicalize the locales in the list through "CanonicalizeUnicodeLocaleId"
* function.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F_L0(LocaleHelperTest, CanonicalizeLocaleList)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> ctor = env->GetLocaleFunction();
JSHandle<JSLocale> jsLocale =
JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
// Set IcuLocale
icu::Locale icuLocale("fr", "Latn", "Fr");
factory->NewJSIntlIcuData(jsLocale, icuLocale, JSLocale::FreeIcuLocale);
// test locale is jslocale
JSHandle<TaggedArray> localeArr = LocaleHelper::CanonicalizeLocaleList(thread, JSHandle<JSTaggedValue>(jsLocale));
EXPECT_EQ(localeArr->GetLength(), 1U);
JSHandle<EcmaString> handleEcmaStr(thread, localeArr->Get(0));
EXPECT_STREQ("fr-Latn-FR", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
// test locale is object
JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
JSHandle<JSTaggedValue> localeObj(thread, arr);
JSHandle<JSTaggedValue> localeStr1(factory->NewFromASCII("EN-us"));
PropertyDescriptor desc1(thread, localeStr1, true, true, true);
JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1"));
JSArray::DefineOwnProperty(thread, JSHandle<JSObject>(localeObj), key1, desc1);
JSHandle<JSTaggedValue> localeStr2(factory->NewFromASCII("en-GB"));
PropertyDescriptor desc2(thread, localeStr2, true, true, true);
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("2"));
JSArray::DefineOwnProperty(thread, JSHandle<JSObject>(localeObj), key2, desc2);
// check canonicalized string
localeArr = LocaleHelper::CanonicalizeLocaleList(thread, localeObj);
EXPECT_EQ(localeArr->GetLength(), 2U);
JSHandle<EcmaString> resultEcmaStr1(thread, localeArr->Get(0));
EXPECT_STREQ("en-US", EcmaStringAccessor(resultEcmaStr1).ToCString().c_str());
JSHandle<EcmaString> resultEcmaStr2(thread, localeArr->Get(1));
EXPECT_STREQ("en-GB", EcmaStringAccessor(resultEcmaStr2).ToCString().c_str());
}
/**
* @tc.name: CanonicalizeUnicodeLocaleId
* @tc.desc: Call "CanonicalizeUnicodeLocaleId" function canonicalize locale(Language-Tag),The English case of language,
* region and script is fixed.the language is lowercase.the beginning of region is uppercase, and the script
* is lowercase.if locale string is IsUtf16,return empty string.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F_L0(LocaleHelperTest, CanonicalizeUnicodeLocaleId)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<EcmaString> locale = factory-> NewFromStdString("en-Us");
JSHandle<EcmaString> canonicalizeLocaleId = LocaleHelper::CanonicalizeUnicodeLocaleId(thread, locale);
EXPECT_STREQ("en-US", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
locale = factory-> NewFromStdString("kO-kore-kr");
canonicalizeLocaleId = LocaleHelper::CanonicalizeUnicodeLocaleId(thread, locale);
EXPECT_STREQ("ko-Kore-KR", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
locale = factory-> NewFromStdString("id-u-co-pinyin-de-ID");
canonicalizeLocaleId = LocaleHelper::CanonicalizeUnicodeLocaleId(thread, locale);
EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
// invalid locale
uint16_t localeArr[] = {0x122, 0x104, 0x45, 0x72, 0x97, 0x110, 0x115, 0x45, 0x67, 0x78}; // zh-Hans-CN
uint32_t localeArrLength = sizeof(localeArr) / sizeof(localeArr[0]);
locale = factory->NewFromUtf16(localeArr, localeArrLength);
canonicalizeLocaleId = LocaleHelper::CanonicalizeUnicodeLocaleId(thread, locale);
JSHandle<EcmaString> emptyString = factory->GetEmptyString();
EXPECT_EQ(EcmaStringAccessor::Compare(instance, canonicalizeLocaleId, emptyString), 0);
}
/**
* @tc.name: ToLanguageTag
* @tc.desc: call "ToLanguageTag" function Convert ICU Locale into language tag.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F_L0(LocaleHelperTest, ToLanguageTag)
{
icu::Locale icuLocale1("en", "Latn", "US", "collation=phonebk;currency=euro");
JSHandle<EcmaString> languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale1);
EXPECT_STREQ("en-Latn-US-u-co-phonebk-cu-euro", EcmaStringAccessor(languageTag).ToCString().c_str());
icu::Locale icuLocale2("zh", "Hans", "CN", "collation=phonebk;kn=true");
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale2);
EXPECT_STREQ("zh-Hans-CN-u-co-phonebk-kn", EcmaStringAccessor(languageTag).ToCString().c_str());
icu::Locale icuLocale3("ja", "Jpan", "JP", "collation=phonebk;co=yes");
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale3);
EXPECT_STREQ("ja-Jpan-JP-u-co", EcmaStringAccessor(languageTag).ToCString().c_str());
icu::Locale icuLocale4("z", "CN"); // language is fault
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale4);
EXPECT_STREQ("und-CN", EcmaStringAccessor(languageTag).ToCString().c_str());
icu::Locale icuLocale5("zh", "c"); // script is fault
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale5);
EXPECT_STREQ("zh-x-lvariant-c", EcmaStringAccessor(languageTag).ToCString().c_str());
icu::Locale icuLocale6("en", "Latn", "E"); // region is fault
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale6);
EXPECT_STREQ("en-Latn-x-lvariant-e", EcmaStringAccessor(languageTag).ToCString().c_str());
icu::Locale icuLocale7("en", "Latn", "EG", "kf=yes"); // key value is fault
languageTag = LocaleHelper::ToLanguageTag(thread, icuLocale7);
EXPECT_STREQ("en-Latn-EG-u-kf", EcmaStringAccessor(languageTag).ToCString().c_str());
}
/**
* @tc.name: IsStructurallyValidLanguageTag
* @tc.desc: Call "IsStructurallyValidLanguageTag" function check Language-Tag is valid structurally.If the tag contains
* the correct language, region, script and extension, return true otherwise, return false.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F_L0(LocaleHelperTest, IsStructurallyValidLanguageTag)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
// number-language
JSHandle<EcmaString> handleEcmaStr = factory->NewFromStdString("123-de");
EXPECT_FALSE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
// only language(zh)
handleEcmaStr = factory-> NewFromStdString("zh");
EXPECT_TRUE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
// only language and script, region
handleEcmaStr = factory-> NewFromStdString("zh-Hans-Cn");
EXPECT_TRUE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
handleEcmaStr = factory-> NewFromStdString("ja-JP-u-ca-japanese");
EXPECT_TRUE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
handleEcmaStr = factory-> NewFromStdString("语言脚本地区");
EXPECT_FALSE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
handleEcmaStr = factory-> NewFromStdString("e-US");
EXPECT_FALSE(LocaleHelper::IsStructurallyValidLanguageTag(handleEcmaStr));
}
/**
* @tc.name: ConvertToStdString
* @tc.desc: Convert char* type to std string,check whether the returned string through "ConvertToStdString"
* function is within expectations.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F_L0(LocaleHelperTest, ConvertToStdString)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<EcmaString> handleEcmaStr = factory-> NewFromStdString("一二三四");
std::string stdString = LocaleHelper::ConvertToStdString(handleEcmaStr);
EXPECT_STREQ(stdString.c_str(), "一二三四");
handleEcmaStr = factory-> NewFromStdString("#%!\0@$");
stdString = LocaleHelper::ConvertToStdString(handleEcmaStr);
EXPECT_STREQ(stdString.c_str(), "#%!\0@$");
handleEcmaStr = factory-> NewFromStdString("123456");
stdString = LocaleHelper::ConvertToStdString(handleEcmaStr);
EXPECT_STREQ(stdString.c_str(), "123456");
handleEcmaStr = factory-> NewFromStdString("zhde");
stdString = LocaleHelper::ConvertToStdString(handleEcmaStr);
EXPECT_STREQ(stdString.c_str(), "zhde");
}
/**
* @tc.name: HandleLocaleExtension
* @tc.desc: Find position of subtag "x" or "u" in Locale through "HandleLocaleExtension" function.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F_L0(LocaleHelperTest, HandleLocaleExtension)
{
std::string result = "en-Latn-US-u-ca-gregory-co-compat";
size_t start = 0;
size_t extensionEnd = 0;
LocaleHelper::HandleLocaleExtension(start, extensionEnd, result, result.size());
EXPECT_EQ(extensionEnd, 10U); // the position of "u"
// private extension("x")
result = "de-zh-x-co-phonebk-nu-kali";
start = 0;
extensionEnd = 0;
LocaleHelper::HandleLocaleExtension(start, extensionEnd, result, result.size());
EXPECT_EQ(extensionEnd, 5U); // the position of "x"
}
/**
* @tc.name: HandleLocale
* @tc.desc: Call "HandleLocale" function handle locale,if Locale has subtag "u" ignore it.If Locale has
* both subtag "x" and "u","x" is in front of "u","u" does not ignore,"x" is after "u","u" ignores.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F_L0(LocaleHelperTest, HandleLocale)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
// no "u" or "x"
JSHandle<EcmaString> localeString = factory->NewFromASCII("en-Latn-US");
LocaleHelper::ParsedLocale parsedResult = LocaleHelper::HandleLocale(localeString);
EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US");
// only "x"
localeString = factory->NewFromASCII("zh-CN-x-ca-pinyin");
parsedResult = LocaleHelper::HandleLocale(localeString);
EXPECT_STREQ(parsedResult.base.c_str(), "zh-CN-x-ca-pinyin");
// only "u"
localeString = factory->NewFromASCII("ko-Kore-KR-u-co-phonebk");
parsedResult = LocaleHelper::HandleLocale(localeString);
EXPECT_STREQ(parsedResult.base.c_str(), "ko-Kore-KR");
// both "x" and "u"
localeString = factory->NewFromASCII("en-Latn-US-u-x-co-phonebk-kn-true");
parsedResult = LocaleHelper::HandleLocale(localeString);
EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US-x-co-phonebk-kn-true");
localeString = factory->NewFromASCII("en-Latn-US-x-u-ca-pinyin-co-compat");
parsedResult = LocaleHelper::HandleLocale(localeString);
EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US-x-u-ca-pinyin-co-compat");
}
/**
* @tc.name: BestAvailableLocale
* @tc.desc: Match the best Locale and return from available locale through "BestAvailableLocale" function.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F_L0(LocaleHelperTest, BestAvailableLocale)
{
const char *path = JSCollator::uIcuDataColl.c_str();
// available locales in uIcuDataColl
std::vector<std::string> icuDataAvailableLocales =
LocaleHelper::GetAvailableLocales(thread, nullptr, path);
// available locales(calendar)
std::vector<std::string> calendarAvailableLocales =
LocaleHelper::GetAvailableLocales(thread, "calendar", nullptr);
// available locales(NumberElements)
std::vector<std::string> numberAvailableLocales =
LocaleHelper::GetAvailableLocales(thread, "NumberElements", nullptr);
// "ar-001" is found
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "ar-001").c_str(), "ar-001");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "ar-001").c_str(), "ar-001");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "ar-001").c_str(), "ar-001");
// "agq-CM" is not found in uIcuDataColl
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "agq-CM").c_str(), "");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "agq-CM").c_str(), "agq-CM");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "agq-CM").c_str(), "agq-CM");
// language(und)-region(CN)
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "und-CN").c_str(), "");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "und-CN").c_str(), "");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "und-CN").c_str(), "");
// language(en)-region(001)
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "en-001").c_str(), "en-001");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "en-001").c_str(), "en-001");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "en-001").c_str(), "en-001");
// language(en)-script(Hans)-region(US)
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(icuDataAvailableLocales, "en-Hans-US").c_str(), "en");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(calendarAvailableLocales, "en-Hans-US").c_str(), "en");
EXPECT_STREQ(LocaleHelper::BestAvailableLocale(numberAvailableLocales, "en-Hans-US").c_str(), "en");
}
} // namespace panda::test