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/builtins/builtins_displaynames.h"
17
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_displaynames.h"
20 #include "ecmascript/tests/test_helper.h"
21
22 using namespace panda::ecmascript;
23 using namespace panda::ecmascript::builtins;
24 namespace panda::test {
25 class BuiltinsDisplayNamesTest : 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
JSDisplayNamesCreateWithOptionTest(JSThread * thread,JSHandle<JSTaggedValue> & locale,JSHandle<JSTaggedValue> & typeValue)62 static JSTaggedValue JSDisplayNamesCreateWithOptionTest(JSThread *thread, JSHandle<JSTaggedValue> &locale,
63 JSHandle<JSTaggedValue> &typeValue)
64 {
65 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
66 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
67 JSHandle<JSFunction> newTarget(env->GetDisplayNamesFunction());
68 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
69 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
70
71 JSHandle<JSTaggedValue> typeKey = thread->GlobalConstants()->GetHandledTypeString();
72 JSObject::SetProperty(thread, optionsObj, typeKey, typeValue);
73
74 JSHandle<JSTaggedValue> localesString = locale;
75 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
76 ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
77 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
78 ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
79 ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
80
81 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
82 JSTaggedValue result = BuiltinsDisplayNames::DisplayNamesConstructor(ecmaRuntimeCallInfo);
83 TestHelper::TearDownFrame(thread, prev);
84
85 EXPECT_TRUE(result.IsJSDisplayNames());
86 return result;
87 }
88
89 // new DisplayNames(locales, options)
HWTEST_F_L0(BuiltinsDisplayNamesTest,DisplayNamesConstructor)90 HWTEST_F_L0(BuiltinsDisplayNamesTest, DisplayNamesConstructor)
91 {
92 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
93 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
94 JSHandle<JSFunction> newTarget(env->GetDisplayNamesFunction());
95 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
96
97 JSHandle<JSTaggedValue> typeKey = thread->GlobalConstants()->GetHandledTypeString();
98 JSHandle<JSTaggedValue> styleKey = thread->GlobalConstants()->GetHandledStyleString();
99 JSHandle<JSTaggedValue> fallbackKey = thread->GlobalConstants()->GetHandledFallbackString();
100
101 JSHandle<JSTaggedValue> localeString(factory->NewFromASCII("en"));
102 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("language"));
103 JSHandle<JSTaggedValue> styleValue(factory->NewFromASCII("narrow"));
104 JSHandle<JSTaggedValue> fallbackValue(factory->NewFromASCII("code"));
105
106 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
107 JSObject::SetProperty(thread, optionsObj, typeKey, typeValue);
108 JSObject::SetProperty(thread, optionsObj, styleKey, styleValue);
109 JSObject::SetProperty(thread, optionsObj, fallbackKey, fallbackValue);
110
111 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
112 ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
113 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
114 ecmaRuntimeCallInfo->SetCallArg(0, localeString.GetTaggedValue());
115 ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
116
117 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
118 JSTaggedValue result = BuiltinsDisplayNames::DisplayNamesConstructor(ecmaRuntimeCallInfo);
119 TestHelper::TearDownFrame(thread, prev);
120 EXPECT_TRUE(result.IsJSDisplayNames());
121 }
122
123 // Of(fr, type(language))
HWTEST_F_L0(BuiltinsDisplayNamesTest,Of_001)124 HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_001)
125 {
126 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
127 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
128 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("language"));
129 JSHandle<JSDisplayNames> jsDisplayNames =
130 JSHandle<JSDisplayNames>(thread, JSDisplayNamesCreateWithOptionTest(thread, locale, typeValue));
131
132 JSHandle<JSTaggedValue> stringValue(factory->NewFromASCII("fr"));
133 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
134 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
135 ecmaRuntimeCallInfo->SetThis(jsDisplayNames.GetTaggedValue());
136 ecmaRuntimeCallInfo->SetCallArg(0, stringValue.GetTaggedValue());
137
138 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
139 JSTaggedValue result = BuiltinsDisplayNames::Of(ecmaRuntimeCallInfo);
140 TestHelper::TearDownFrame(thread, prev);
141
142 EXPECT_TRUE(result.IsString());
143 JSHandle<EcmaString> handleEcmaStr(thread, result);
144 EXPECT_STREQ("French", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
145 }
146
147 // Of(419, type(region))
HWTEST_F_L0(BuiltinsDisplayNamesTest,Of_002)148 HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_002)
149 {
150 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
151 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
152 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("region"));
153 JSHandle<JSDisplayNames> jsDisplayNames =
154 JSHandle<JSDisplayNames>(thread, JSDisplayNamesCreateWithOptionTest(thread, locale, typeValue));
155
156 JSHandle<JSTaggedValue> stringValue(factory->NewFromASCII("419"));
157 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
158 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
159 ecmaRuntimeCallInfo->SetThis(jsDisplayNames.GetTaggedValue());
160 ecmaRuntimeCallInfo->SetCallArg(0, stringValue.GetTaggedValue());
161
162 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
163 JSTaggedValue result = BuiltinsDisplayNames::Of(ecmaRuntimeCallInfo);
164 TestHelper::TearDownFrame(thread, prev);
165
166 EXPECT_TRUE(result.IsString());
167 JSHandle<EcmaString> handleEcmaStr(thread, result);
168 EXPECT_STREQ("Latin America", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
169 }
170
171 // Of(EUR, type(currency))
HWTEST_F_L0(BuiltinsDisplayNamesTest,Of_003)172 HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_003)
173 {
174 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
175 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
176 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("currency"));
177 JSHandle<JSDisplayNames> jsDisplayNames =
178 JSHandle<JSDisplayNames>(thread, JSDisplayNamesCreateWithOptionTest(thread, locale, typeValue));
179
180 JSHandle<JSTaggedValue> stringValue(factory->NewFromASCII("EUR"));
181 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
182 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
183 ecmaRuntimeCallInfo->SetThis(jsDisplayNames.GetTaggedValue());
184 ecmaRuntimeCallInfo->SetCallArg(0, stringValue.GetTaggedValue());
185
186 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
187 JSTaggedValue result = BuiltinsDisplayNames::Of(ecmaRuntimeCallInfo);
188 TestHelper::TearDownFrame(thread, prev);
189
190 EXPECT_TRUE(result.IsString());
191 JSHandle<EcmaString> handleEcmaStr(thread, result);
192 EXPECT_STREQ("Euro", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
193 }
194
195 // Of(Code Cover)
HWTEST_F_L0(BuiltinsDisplayNamesTest,Of_004)196 HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_004)
197 {
198 // IsNotJSDisplayNames
199 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
200 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
201 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
202 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Undefined());
203
204 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
205 JSTaggedValue result = BuiltinsDisplayNames::Of(ecmaRuntimeCallInfo);
206 TestHelper::TearDownFrame(thread, prev);
207 EXPECT_TRUE(thread->HasPendingException());
208 EXPECT_EQ(result, JSTaggedValue::Exception());
209 thread->ClearException();
210 }
211
212 // SupportedLocalesOf("best fit")
HWTEST_F_L0(BuiltinsDisplayNamesTest,SupportedLocalesOf_001)213 HWTEST_F_L0(BuiltinsDisplayNamesTest, SupportedLocalesOf_001)
214 {
215 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
216 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("id-u-co-pinyin-de-ID"));
217
218 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
219 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
220 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
221 ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
222 // set the tag is default value
223 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
224
225 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
226 JSTaggedValue resultArr = BuiltinsDisplayNames::SupportedLocalesOf(ecmaRuntimeCallInfo);
227 TestHelper::TearDownFrame(thread, prev);
228
229 JSHandle<JSArray> resultHandle(thread, resultArr);
230 JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
231 EXPECT_EQ(elements->GetLength(), 1U);
232 JSHandle<EcmaString> handleEcmaStr(thread, elements->Get(0));
233 EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
234 }
235
236 // SupportedLocalesOf("look up")
HWTEST_F_L0(BuiltinsDisplayNamesTest,SupportedLocalesOf_002)237 HWTEST_F_L0(BuiltinsDisplayNamesTest, SupportedLocalesOf_002)
238 {
239 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
240 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
241 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
242
243 JSHandle<JSTaggedValue> localeMatcherKey = thread->GlobalConstants()->GetHandledLocaleMatcherString();
244 JSHandle<JSTaggedValue> localeMatcherValue(factory->NewFromASCII("lookup"));
245 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
246 JSObject::SetProperty(thread, optionsObj, localeMatcherKey, localeMatcherValue);
247 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("de-DE-u-co-phonebk"));
248
249 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
250 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
251 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
252 ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
253 ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
254
255 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
256 JSTaggedValue resultArr = BuiltinsDisplayNames::SupportedLocalesOf(ecmaRuntimeCallInfo);
257 TestHelper::TearDownFrame(thread, prev);
258
259 JSHandle<JSArray> resultHandle(thread, resultArr);
260 JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
261 EXPECT_EQ(elements->GetLength(), 1U);
262 JSHandle<EcmaString> handleEcmaStr(thread, elements->Get(0));
263 EXPECT_STREQ("de-DE-u-co-phonebk", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
264 }
265
HWTEST_F_L0(BuiltinsDisplayNamesTest,ResolvedOptions)266 HWTEST_F_L0(BuiltinsDisplayNamesTest, ResolvedOptions)
267 {
268 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
269 auto globalConst = thread->GlobalConstants();
270 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("de-DE"));
271 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("currency"));
272 JSHandle<JSDisplayNames> jsDisplayNames =
273 JSHandle<JSDisplayNames>(thread, JSDisplayNamesCreateWithOptionTest(
274 thread, locale, typeValue));
275 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
276 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
277 ecmaRuntimeCallInfo->SetThis(jsDisplayNames.GetTaggedValue());
278
279 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
280 JSTaggedValue result = BuiltinsDisplayNames::ResolvedOptions(ecmaRuntimeCallInfo);
281 TestHelper::TearDownFrame(thread, prev);
282
283 JSHandle<JSTaggedValue> resultObj =
284 JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<JSTaggedType>(result.GetRawData())));
285 // judge whether the properties of the object are the same as those of jsdatetimeformat tag
286 JSHandle<JSTaggedValue> localeKey = globalConst->GetHandledLocaleString();
287 JSHandle<JSTaggedValue> localeValue(factory->NewFromASCII("de-DE"));
288 EXPECT_EQ(JSTaggedValue::SameValue(
289 JSObject::GetProperty(thread, resultObj, localeKey).GetValue(), localeValue), true);
290 JSHandle<JSTaggedValue> typeKey = globalConst->GetHandledTypeString();
291 EXPECT_EQ(JSTaggedValue::SameValue(
292 JSObject::GetProperty(thread, resultObj, typeKey).GetValue(), typeValue), true);
293 }
294 }
295