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 BaseTestWithScope<true> {
26 };
27
JSDisplayNamesCreateWithOptionTest(JSThread *thread, JSHandle<JSTaggedValue> &locale, JSHandle<JSTaggedValue> &typeValue)28 static JSTaggedValue JSDisplayNamesCreateWithOptionTest(JSThread *thread, JSHandle<JSTaggedValue> &locale,
29 JSHandle<JSTaggedValue> &typeValue)
30 {
31 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
32 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
33 JSHandle<JSFunction> newTarget(env->GetDisplayNamesFunction());
34 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
35 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
36
37 JSHandle<JSTaggedValue> typeKey = thread->GlobalConstants()->GetHandledTypeString();
38 JSObject::SetProperty(thread, optionsObj, typeKey, typeValue);
39
40 JSHandle<JSTaggedValue> localesString = locale;
41 std::vector<JSTaggedValue> args{localesString.GetTaggedValue(), optionsObj.GetTaggedValue()};
42 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, newTarget, args, 8);
43
44 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
45 JSTaggedValue result = BuiltinsDisplayNames::DisplayNamesConstructor(ecmaRuntimeCallInfo);
46 TestHelper::TearDownFrame(thread, prev);
47
48 EXPECT_TRUE(result.IsJSDisplayNames());
49 return result;
50 }
51
52 // new DisplayNames(locales, options)
HWTEST_F_L0(BuiltinsDisplayNamesTest, DisplayNamesConstructor)53 HWTEST_F_L0(BuiltinsDisplayNamesTest, DisplayNamesConstructor)
54 {
55 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
56 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
57 JSHandle<JSFunction> newTarget(env->GetDisplayNamesFunction());
58 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
59
60 JSHandle<JSTaggedValue> typeKey = thread->GlobalConstants()->GetHandledTypeString();
61 JSHandle<JSTaggedValue> styleKey = thread->GlobalConstants()->GetHandledStyleString();
62 JSHandle<JSTaggedValue> fallbackKey = thread->GlobalConstants()->GetHandledFallbackString();
63
64 JSHandle<JSTaggedValue> localeString(factory->NewFromASCII("en"));
65 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("language"));
66 JSHandle<JSTaggedValue> styleValue(factory->NewFromASCII("narrow"));
67 JSHandle<JSTaggedValue> fallbackValue(factory->NewFromASCII("code"));
68
69 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
70 JSObject::SetProperty(thread, optionsObj, typeKey, typeValue);
71 JSObject::SetProperty(thread, optionsObj, styleKey, styleValue);
72 JSObject::SetProperty(thread, optionsObj, fallbackKey, fallbackValue);
73
74 std::vector<JSTaggedValue> args{localeString.GetTaggedValue(), optionsObj.GetTaggedValue()};
75 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, newTarget, args, 8);
76
77 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
78 JSTaggedValue result = BuiltinsDisplayNames::DisplayNamesConstructor(ecmaRuntimeCallInfo);
79 TestHelper::TearDownFrame(thread, prev);
80 EXPECT_TRUE(result.IsJSDisplayNames());
81 }
82
83 // Of(fr, type(language))
HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_001)84 HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_001)
85 {
86 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
87 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
88 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("language"));
89 JSHandle<JSDisplayNames> jsDisplayNames =
90 JSHandle<JSDisplayNames>(thread, JSDisplayNamesCreateWithOptionTest(thread, locale, typeValue));
91
92 JSHandle<JSTaggedValue> stringValue(factory->NewFromASCII("fr"));
93 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
94 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
95 ecmaRuntimeCallInfo->SetThis(jsDisplayNames.GetTaggedValue());
96 ecmaRuntimeCallInfo->SetCallArg(0, stringValue.GetTaggedValue());
97
98 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
99 JSTaggedValue result = BuiltinsDisplayNames::Of(ecmaRuntimeCallInfo);
100 TestHelper::TearDownFrame(thread, prev);
101
102 EXPECT_TRUE(result.IsString());
103 JSHandle<EcmaString> handleEcmaStr(thread, result);
104 EXPECT_STREQ("French", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
105 }
106
107 // Of(419, type(region))
HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_002)108 HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_002)
109 {
110 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
111 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
112 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("region"));
113 JSHandle<JSDisplayNames> jsDisplayNames =
114 JSHandle<JSDisplayNames>(thread, JSDisplayNamesCreateWithOptionTest(thread, locale, typeValue));
115
116 JSHandle<JSTaggedValue> stringValue(factory->NewFromASCII("419"));
117 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
118 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
119 ecmaRuntimeCallInfo->SetThis(jsDisplayNames.GetTaggedValue());
120 ecmaRuntimeCallInfo->SetCallArg(0, stringValue.GetTaggedValue());
121
122 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
123 JSTaggedValue result = BuiltinsDisplayNames::Of(ecmaRuntimeCallInfo);
124 TestHelper::TearDownFrame(thread, prev);
125
126 EXPECT_TRUE(result.IsString());
127 JSHandle<EcmaString> handleEcmaStr(thread, result);
128 EXPECT_STREQ("Latin America", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
129 }
130
131 // Of(EUR, type(currency))
HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_003)132 HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_003)
133 {
134 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
135 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
136 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("currency"));
137 JSHandle<JSDisplayNames> jsDisplayNames =
138 JSHandle<JSDisplayNames>(thread, JSDisplayNamesCreateWithOptionTest(thread, locale, typeValue));
139
140 JSHandle<JSTaggedValue> stringValue(factory->NewFromASCII("EUR"));
141 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
142 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
143 ecmaRuntimeCallInfo->SetThis(jsDisplayNames.GetTaggedValue());
144 ecmaRuntimeCallInfo->SetCallArg(0, stringValue.GetTaggedValue());
145
146 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
147 JSTaggedValue result = BuiltinsDisplayNames::Of(ecmaRuntimeCallInfo);
148 TestHelper::TearDownFrame(thread, prev);
149
150 EXPECT_TRUE(result.IsString());
151 JSHandle<EcmaString> handleEcmaStr(thread, result);
152 EXPECT_STREQ("Euro", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
153 }
154
155 // Of(Code Cover)
HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_004)156 HWTEST_F_L0(BuiltinsDisplayNamesTest, Of_004)
157 {
158 // IsNotJSDisplayNames
159 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
160 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
161 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
162 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Undefined());
163
164 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
165 JSTaggedValue result = BuiltinsDisplayNames::Of(ecmaRuntimeCallInfo);
166 TestHelper::TearDownFrame(thread, prev);
167 EXPECT_TRUE(thread->HasPendingException());
168 EXPECT_EQ(result, JSTaggedValue::Exception());
169 thread->ClearException();
170 }
171
172 // SupportedLocalesOf("best fit")
HWTEST_F_L0(BuiltinsDisplayNamesTest, SupportedLocalesOf_001)173 HWTEST_F_L0(BuiltinsDisplayNamesTest, SupportedLocalesOf_001)
174 {
175 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
176 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("id-u-co-pinyin-de-ID"));
177
178 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
179 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
180 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
181 ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
182 // set the tag is default value
183 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
184
185 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
186 JSTaggedValue resultArr = BuiltinsDisplayNames::SupportedLocalesOf(ecmaRuntimeCallInfo);
187 TestHelper::TearDownFrame(thread, prev);
188
189 JSHandle<JSArray> resultHandle(thread, resultArr);
190 JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
191 EXPECT_EQ(elements->GetLength(), 1U);
192 JSHandle<EcmaString> handleEcmaStr(thread, elements->Get(0));
193 EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
194 }
195
196 // SupportedLocalesOf("look up")
HWTEST_F_L0(BuiltinsDisplayNamesTest, SupportedLocalesOf_002)197 HWTEST_F_L0(BuiltinsDisplayNamesTest, SupportedLocalesOf_002)
198 {
199 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
200 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
201 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
202
203 JSHandle<JSTaggedValue> localeMatcherKey = thread->GlobalConstants()->GetHandledLocaleMatcherString();
204 JSHandle<JSTaggedValue> localeMatcherValue(factory->NewFromASCII("lookup"));
205 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
206 JSObject::SetProperty(thread, optionsObj, localeMatcherKey, localeMatcherValue);
207 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("de-DE-u-co-phonebk"));
208
209 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
210 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
211 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
212 ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
213 ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
214
215 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
216 JSTaggedValue resultArr = BuiltinsDisplayNames::SupportedLocalesOf(ecmaRuntimeCallInfo);
217 TestHelper::TearDownFrame(thread, prev);
218
219 JSHandle<JSArray> resultHandle(thread, resultArr);
220 JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
221 EXPECT_EQ(elements->GetLength(), 1U);
222 JSHandle<EcmaString> handleEcmaStr(thread, elements->Get(0));
223 EXPECT_STREQ("de-DE-u-co-phonebk", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
224 }
225
HWTEST_F_L0(BuiltinsDisplayNamesTest, ResolvedOptions)226 HWTEST_F_L0(BuiltinsDisplayNamesTest, ResolvedOptions)
227 {
228 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
229 auto globalConst = thread->GlobalConstants();
230 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("de-DE"));
231 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("currency"));
232 JSHandle<JSDisplayNames> jsDisplayNames =
233 JSHandle<JSDisplayNames>(thread, JSDisplayNamesCreateWithOptionTest(
234 thread, locale, typeValue));
235 std::vector<JSTaggedValue> args{};
236 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 4, jsDisplayNames.GetTaggedValue());
237
238 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
239 JSTaggedValue result = BuiltinsDisplayNames::ResolvedOptions(ecmaRuntimeCallInfo);
240 TestHelper::TearDownFrame(thread, prev);
241
242 JSHandle<JSTaggedValue> resultObj =
243 JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<JSTaggedType>(result.GetRawData())));
244 // judge whether the properties of the object are the same as those of jsdatetimeformat tag
245 JSHandle<JSTaggedValue> localeKey = globalConst->GetHandledLocaleString();
246 JSHandle<JSTaggedValue> localeValue(factory->NewFromASCII("de-DE"));
247 EXPECT_EQ(JSTaggedValue::SameValue(
248 JSObject::GetProperty(thread, resultObj, localeKey).GetValue(), localeValue), true);
249 JSHandle<JSTaggedValue> typeKey = globalConst->GetHandledTypeString();
250 EXPECT_EQ(JSTaggedValue::SameValue(
251 JSObject::GetProperty(thread, resultObj, typeKey).GetValue(), typeValue), true);
252 }
253 }
254