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