• 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 #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