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