• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/js_displaynames.h"
17 
18 #include "ecmascript/intl/locale_helper.h"
19 #include "ecmascript/tests/test_helper.h"
20 
21 using namespace panda;
22 using namespace panda::ecmascript;
23 
24 namespace panda::test {
25 class JSDisplayNamesTest : public testing::Test {
26 public:
SetUpTestCase()27     static void SetUpTestCase()
28     {
29         GTEST_LOG_(INFO) << "SetUpTestCase";
30     }
31 
TearDownTestCase()32     static void TearDownTestCase()
33     {
34         GTEST_LOG_(INFO) << "TearDownCase";
35     }
36 
SetUp()37     void SetUp() override
38     {
39         JSRuntimeOptions options;
40 #if PANDA_TARGET_LINUX
41         // for consistency requirement, use ohos_icu4j/data/icudt67l.dat as icu-data-path
42         options.SetIcuDataPath(ICU_PATH);
43 #endif
44         options.SetEnableForceGC(true);
45         instance = JSNApi::CreateEcmaVM(options);
46         instance->SetEnableForceGC(true);
47         ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
48         thread = instance->GetJSThread();
49         scope = new EcmaHandleScope(thread);
50     }
51 
TearDown()52     void TearDown() override
53     {
54         TestHelper::DestroyEcmaVMWithScope(instance, scope);
55     }
56 
57     EcmaVM *instance {nullptr};
58     EcmaHandleScope *scope {nullptr};
59     JSThread *thread {nullptr};
60 };
61 
62 /**
63  * @tc.name: GetIcuLocaleDisplayNames
64  * @tc.desc: Call "SetIcuLocaleDisplayNames" function Set IcuLocale DisplayNames,check whether the IcuLocale
65  *           DisplayNames through "GetIcuLocaleDisplayNames" function is within expectations then call "getLocale"
66  *           function display locale and check the locale is within expectations.
67  * @tc.type: FUNC
68  * @tc.require:
69  */
HWTEST_F_L0(JSDisplayNamesTest,GetIcuLocaleDisplayNames)70 HWTEST_F_L0(JSDisplayNamesTest, GetIcuLocaleDisplayNames)
71 {
72     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
73     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
74 
75     JSHandle<JSTaggedValue> ctor = env->GetDisplayNamesFunction();
76     JSHandle<JSDisplayNames> displayNames =
77         JSHandle<JSDisplayNames>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
78 
79     icu::Locale icuLocale("en");
80     UDisplayContext display_context[] = {UDISPCTX_LENGTH_SHORT};
81     icu::LocaleDisplayNames* iculocaledisplaynames =
82         icu::LocaleDisplayNames::createInstance(icuLocale, display_context, 1);
83     EXPECT_TRUE(iculocaledisplaynames != nullptr);
84     JSDisplayNames::SetIcuLocaleDisplayNames(
85         thread, displayNames, iculocaledisplaynames, JSDisplayNames::FreeIcuLocaleDisplayNames);
86     icu::LocaleDisplayNames *resultIculocaledisplaynames = displayNames->GetIcuLocaleDisplayNames();
87     EXPECT_TRUE(iculocaledisplaynames == resultIculocaledisplaynames);
88     JSHandle<EcmaString> localeStr =
89         intl::LocaleHelper::ToLanguageTag(thread, resultIculocaledisplaynames->getLocale());
90     EXPECT_STREQ(EcmaStringAccessor(localeStr).ToCString().c_str(), "en");
91 }
92 
93 /**
94  * @tc.name: GetAvailableLocales
95  * @tc.desc: Call function "GetAvailableLocales" to obtain the available locale from the ICU library and
96  *           check whether the obtained locale is empty.
97  * @tc.type: FUNC
98  * @tc.require:
99  */
HWTEST_F_L0(JSDisplayNamesTest,GetAvailableLocales)100 HWTEST_F_L0(JSDisplayNamesTest, GetAvailableLocales)
101 {
102     JSHandle<TaggedArray> displayLocale = JSDisplayNames::GetAvailableLocales(thread);
103     uint32_t localeLen = displayLocale->GetLength();
104     EXPECT_NE(localeLen, 0U);
105 
106     for (uint32_t i = 0; i < localeLen; i++) {
107         EXPECT_FALSE(displayLocale->Get(i).IsHole());
108     }
109 }
110 
SetOptionProperties(JSThread * thread,JSHandle<JSObject> & optionsObj,std::map<std::string,std::string> & displayOptions)111 void SetOptionProperties(JSThread *thread, JSHandle<JSObject> &optionsObj,
112                          std::map<std::string, std::string> &displayOptions)
113 {
114     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
115     auto globalConst = thread->GlobalConstants();
116     // display options keys
117     JSHandle<JSTaggedValue> styleKey = globalConst->GetHandledStyleString();
118     JSHandle<JSTaggedValue> typeKey = globalConst->GetHandledTypeString();
119     JSHandle<JSTaggedValue> fallBackKey = globalConst->GetHandledFallbackString();
120     // display options value
121     JSHandle<JSTaggedValue> styleValue(factory->NewFromASCII(displayOptions["style"].c_str()));
122     JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII(displayOptions["type"].c_str()));
123     JSHandle<JSTaggedValue> fallBackValue(factory->NewFromASCII(displayOptions["fallback"].c_str()));
124     JSObject::SetProperty(thread, optionsObj, styleKey, styleValue);
125     JSObject::SetProperty(thread, optionsObj, typeKey, typeValue);
126     JSObject::SetProperty(thread, optionsObj, fallBackKey, fallBackValue);
127 }
128 
129 /**
130  * @tc.name: InitializeDisplayNames
131  * @tc.desc: Call function "InitializeDisplayNames" to initialize the jsdisplaynames class object and check whether the
132  *           properties of the object is within expectations.
133  * @tc.type: FUNC
134  * @tc.require:
135  */
HWTEST_F_L0(JSDisplayNamesTest,InitializeDisplayNames)136 HWTEST_F_L0(JSDisplayNamesTest, InitializeDisplayNames)
137 {
138     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
139     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
140 
141     JSHandle<JSTaggedValue> ctor = env->GetDisplayNamesFunction();
142     JSHandle<JSDisplayNames> displayNames =
143         JSHandle<JSDisplayNames>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
144     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
145     JSHandle<JSObject> displayOptions = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
146     JSHandle<JSTaggedValue> localeStr(factory->NewFromASCII("en-US"));
147     // options is empty
148     JSDisplayNames::InitializeDisplayNames(thread, displayNames, localeStr, JSHandle<JSTaggedValue>(displayOptions));
149     // Default attribute value and type is undefiend throw a expection
150     EXPECT_EQ(displayNames->GetStyle(), StyOption::LONG);
151     EXPECT_EQ(displayNames->GetType(), TypednsOption::EXCEPTION);
152     EXPECT_EQ(displayNames->GetFallback(), FallbackOption::EXCEPTION);
153     EXPECT_TRUE(thread->HasPendingException());
154     thread->ClearException();
155     // options of the key and value
156     std::map<std::string, std::string> displayOptionsProperty {
157         { "style", "short" },
158         { "type", "script" },
159         { "fallback", "none" },
160     };
161     SetOptionProperties(thread, displayOptions, displayOptionsProperty);
162     // options is not empty
163     JSDisplayNames::InitializeDisplayNames(thread, displayNames, localeStr, JSHandle<JSTaggedValue>(displayOptions));
164     JSHandle<EcmaString> setlocale(thread, displayNames->GetLocale());
165     EXPECT_EQ(displayNames->GetStyle(), StyOption::SHORT);
166     EXPECT_EQ(displayNames->GetType(), TypednsOption::SCRIPT);
167     EXPECT_EQ(displayNames->GetFallback(), FallbackOption::NONE);
168     EXPECT_STREQ(EcmaStringAccessor(setlocale).ToCString().c_str(), "en-US");
169     EXPECT_TRUE(displayNames->GetIcuLocaleDisplayNames() != nullptr);
170 }
171 
172 /**
173  * @tc.name: CanonicalCodeForDisplayNames
174  * @tc.desc: Display the language region and script of the locale according to the display configuration of
175  *           different regions.
176  * @tc.type: FUNC
177  * @tc.require:
178  */
HWTEST_F_L0(JSDisplayNamesTest,CanonicalCodeForDisplayNames)179 HWTEST_F_L0(JSDisplayNamesTest, CanonicalCodeForDisplayNames)
180 {
181     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
182     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
183 
184     JSHandle<JSTaggedValue> ctor = env->GetDisplayNamesFunction();
185     JSHandle<JSDisplayNames> displayNames =
186         JSHandle<JSDisplayNames>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
187     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
188     JSHandle<JSObject> displayOptions = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
189     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("zh-Hant"));
190     // test UDISPCTX_LENGTH_SHORT
191     std::map<std::string, std::string> displayOptionsProperty {
192         { "style", "narrow" },
193         { "type", "script" },
194         { "fallback", "none" },
195     };
196     SetOptionProperties(thread, displayOptions, displayOptionsProperty);
197     JSHandle<JSDisplayNames> initDisplayNames =
198         JSDisplayNames::InitializeDisplayNames(thread, displayNames, locale, JSHandle<JSTaggedValue>(displayOptions));
199     // CanonicalCode for script
200     JSHandle<EcmaString> code = factory->NewFromASCII("Kana");
201     JSHandle<EcmaString> resultDisplay =
202         JSDisplayNames::CanonicalCodeForDisplayNames(thread, initDisplayNames, initDisplayNames->GetType(), code);
203     EXPECT_STREQ(EcmaStringAccessor(resultDisplay).ToCString().c_str(), "片假名");
204     // CanonicalCode for languege
205     code = factory->NewFromASCII("fr");
206     initDisplayNames->SetType(TypednsOption::LANGUAGE);
207     resultDisplay =
208         JSDisplayNames::CanonicalCodeForDisplayNames(thread, initDisplayNames, initDisplayNames->GetType(), code);
209     EXPECT_STREQ(EcmaStringAccessor(resultDisplay).ToCString().c_str(), "法文");
210     // CanonicalCode for region
211     code = factory->NewFromASCII("US");
212     initDisplayNames->SetType(TypednsOption::REGION);
213     resultDisplay =
214         JSDisplayNames::CanonicalCodeForDisplayNames(thread, initDisplayNames, initDisplayNames->GetType(), code);
215     EXPECT_STREQ(EcmaStringAccessor(resultDisplay).ToCString().c_str(), "美國");
216 }
217 
218 /**
219  * @tc.name: ResolvedOptions
220  * @tc.desc: Call function "InitializeDisplayNames" to initialize the jsdisplaynames class object and Copy the
221  *           properties of jsdisplaynames class to a new object.
222  * @tc.type: FUNC
223  * @tc.require:
224  */
HWTEST_F_L0(JSDisplayNamesTest,ResolvedOptions)225 HWTEST_F_L0(JSDisplayNamesTest, ResolvedOptions)
226 {
227     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
228     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
229     auto globalConst = thread->GlobalConstants();
230     JSHandle<JSTaggedValue> localeKey = globalConst->GetHandledLocaleString();
231     JSHandle<JSTaggedValue> styleKey = globalConst->GetHandledStyleString();
232     JSHandle<JSTaggedValue> typeKey = globalConst->GetHandledTypeString();
233     JSHandle<JSTaggedValue> fallBackKey = globalConst->GetHandledFallbackString();
234 
235     JSHandle<JSTaggedValue> ctor = env->GetDisplayNamesFunction();
236     JSHandle<JSDisplayNames> displayNames =
237         JSHandle<JSDisplayNames>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
238     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
239     JSHandle<JSObject> displayOptions = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
240     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("zh-Hant"));
241 
242     std::map<std::string, std::string> displayOptionsProperty {
243         { "style", "short" },
244         { "type", "region" },
245         { "fallback", "code" },
246     };
247     JSHandle<JSTaggedValue> styleValue(factory->NewFromASCII(displayOptionsProperty["style"].c_str()));
248     JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII(displayOptionsProperty["type"].c_str()));
249     JSHandle<JSTaggedValue> fallBackValue(factory->NewFromASCII(displayOptionsProperty["fallback"].c_str()));
250     SetOptionProperties(thread, displayOptions, displayOptionsProperty);
251     JSHandle<JSDisplayNames> initDisplayNames =
252         JSDisplayNames::InitializeDisplayNames(thread, displayNames, locale, JSHandle<JSTaggedValue>(displayOptions));
253 
254     JSDisplayNames::ResolvedOptions(thread, initDisplayNames, displayOptions);
255     EXPECT_EQ(JSTaggedValue::SameValue(
256         JSObject::GetProperty(thread, displayOptions, styleKey).GetValue(), styleValue), true);
257     EXPECT_EQ(JSTaggedValue::SameValue(
258         JSObject::GetProperty(thread, displayOptions, localeKey).GetValue(), locale), true);
259     EXPECT_EQ(JSTaggedValue::SameValue(
260         JSObject::GetProperty(thread, displayOptions, fallBackKey).GetValue(), fallBackValue), true);
261     EXPECT_EQ(JSTaggedValue::SameValue(
262         JSObject::GetProperty(thread, displayOptions, typeKey).GetValue(), typeValue), true);
263 }
264 }  // namespace panda::test
265