• 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/builtins/builtins_relative_time_format.h"
17 
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_relative_time_format.h"
20 #include "ecmascript/tests/test_helper.h"
21 
22 using namespace panda::ecmascript;
23 using namespace panda::ecmascript::builtins;
24 
25 namespace panda::test {
26 class BuiltinsRelativeTimeFormatTest : public testing::Test {
27 public:
SetUpTestCase()28     static void SetUpTestCase()
29     {
30         GTEST_LOG_(INFO) << "SetUpTestCase";
31     }
32 
TearDownTestCase()33     static void TearDownTestCase()
34     {
35         GTEST_LOG_(INFO) << "TearDownCase";
36     }
37 
SetUp()38     void SetUp() override
39     {
40         JSRuntimeOptions options;
41 #if PANDA_TARGET_LINUX
42         // for consistency requirement, use ohos_icu4j/data as icu-data-path
43         options.SetIcuDataPath(ICU_PATH);
44 #endif
45         options.SetEnableForceGC(true);
46         instance = JSNApi::CreateEcmaVM(options);
47         instance->SetEnableForceGC(true);
48         ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
49         thread = instance->GetJSThread();
50         scope = new EcmaHandleScope(thread);
51     }
52 
TearDown()53     void TearDown() override
54     {
55         TestHelper::DestroyEcmaVMWithScope(instance, scope);
56     }
57 
58     EcmaVM *instance {nullptr};
59     EcmaHandleScope *scope {nullptr};
60     JSThread *thread {nullptr};
61 };
62 
63 // new RelativeTimeFormat(newTarget is undefined)
HWTEST_F_L0(BuiltinsRelativeTimeFormatTest,RelativeTimeFormatConstructor)64 HWTEST_F_L0(BuiltinsRelativeTimeFormatTest, RelativeTimeFormatConstructor)
65 {
66     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
67     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
68     JSHandle<JSFunction> newTarget(env->GetRelativeTimeFormatFunction());
69 
70     JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("en"));
71     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
72     ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
73     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
74     ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
75     // option tag is default value
76     ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
77 
78     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
79     JSTaggedValue result = BuiltinsRelativeTimeFormat::RelativeTimeFormatConstructor(ecmaRuntimeCallInfo);
80     TestHelper::TearDownFrame(thread, prev);
81 
82     EXPECT_TRUE(result.IsJSRelativeTimeFormat());
83 }
84 
JSRelativeTimeFormatCreateWithLocaleTest(JSThread * thread,JSHandle<JSTaggedValue> & locale,JSHandle<JSTaggedValue> & numericValue)85 static JSTaggedValue JSRelativeTimeFormatCreateWithLocaleTest(JSThread *thread, JSHandle<JSTaggedValue> &locale,
86                                                               JSHandle<JSTaggedValue> &numericValue)
87 {
88     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
89     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
90     JSHandle<JSFunction> newTarget(env->GetRelativeTimeFormatFunction());
91     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
92     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
93 
94     JSHandle<JSTaggedValue> typeKey = thread->GlobalConstants()->GetHandledNumericString();
95     JSObject::SetProperty(thread, optionsObj, typeKey, numericValue);
96 
97     JSHandle<JSTaggedValue> localesString = locale;
98     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
99     ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
100     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
101     ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
102     ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
103 
104     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
105     JSTaggedValue result = BuiltinsRelativeTimeFormat::RelativeTimeFormatConstructor(ecmaRuntimeCallInfo);
106     EXPECT_TRUE(result.IsJSRelativeTimeFormat());
107     TestHelper::TearDownFrame(thread, prev);
108     return result;
109 }
110 
111 // format(1, auto)
HWTEST_F_L0(BuiltinsRelativeTimeFormatTest,Format_001)112 HWTEST_F_L0(BuiltinsRelativeTimeFormatTest, Format_001)
113 {
114     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
115     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
116     JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("auto")); // the default value
117     JSHandle<JSRelativeTimeFormat> jsPluralRules =
118         JSHandle<JSRelativeTimeFormat>(thread, JSRelativeTimeFormatCreateWithLocaleTest(
119                                         thread, locale, numericValue));
120     JSHandle<JSTaggedValue> unitValue(factory->NewFromASCII("day"));
121     JSHandle<JSTaggedValue> numberValue(thread, JSTaggedValue(1));
122     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
123     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
124     ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
125     ecmaRuntimeCallInfo->SetCallArg(0, numberValue.GetTaggedValue());
126     ecmaRuntimeCallInfo->SetCallArg(1, unitValue.GetTaggedValue());
127 
128     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
129     JSTaggedValue result = BuiltinsRelativeTimeFormat::Format(ecmaRuntimeCallInfo);
130     TestHelper::TearDownFrame(thread, prev);
131 
132     JSHandle<EcmaString> handleEcmaStr(thread, result);
133     EXPECT_STREQ("tomorrow", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
134 }
135 
136 // format(0, auto)
HWTEST_F_L0(BuiltinsRelativeTimeFormatTest,Format_002)137 HWTEST_F_L0(BuiltinsRelativeTimeFormatTest, Format_002)
138 {
139     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
140     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
141     JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("auto"));
142     JSHandle<JSRelativeTimeFormat> jsPluralRules =
143         JSHandle<JSRelativeTimeFormat>(thread, JSRelativeTimeFormatCreateWithLocaleTest(
144                                         thread, locale, numericValue));
145     JSHandle<JSTaggedValue> unitValue(factory->NewFromASCII("day"));
146     JSHandle<JSTaggedValue> numberValue(thread, JSTaggedValue(0));
147     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
148     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
149     ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
150     ecmaRuntimeCallInfo->SetCallArg(0, numberValue.GetTaggedValue());
151     ecmaRuntimeCallInfo->SetCallArg(1, unitValue.GetTaggedValue());
152 
153     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
154     JSTaggedValue result = BuiltinsRelativeTimeFormat::Format(ecmaRuntimeCallInfo);
155     TestHelper::TearDownFrame(thread, prev);
156 
157     JSHandle<EcmaString> handleEcmaStr(thread, result);
158     EXPECT_STREQ("today", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
159 }
160 
161 // format(-1, auto)
HWTEST_F_L0(BuiltinsRelativeTimeFormatTest,Format_003)162 HWTEST_F_L0(BuiltinsRelativeTimeFormatTest, Format_003)
163 {
164     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
165     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
166     JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("auto")); // the default value
167     JSHandle<JSRelativeTimeFormat> jsPluralRules =
168         JSHandle<JSRelativeTimeFormat>(thread, JSRelativeTimeFormatCreateWithLocaleTest(
169                                         thread, locale, numericValue));
170     JSHandle<JSTaggedValue> unitValue(factory->NewFromASCII("day"));
171     JSHandle<JSTaggedValue> numberValue(thread, JSTaggedValue(-1));
172     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
173     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
174     ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
175     ecmaRuntimeCallInfo->SetCallArg(0, numberValue.GetTaggedValue());
176     ecmaRuntimeCallInfo->SetCallArg(1, unitValue.GetTaggedValue());
177 
178     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
179     JSTaggedValue result = BuiltinsRelativeTimeFormat::Format(ecmaRuntimeCallInfo);
180     TestHelper::TearDownFrame(thread, prev);
181 
182     JSHandle<EcmaString> handleEcmaStr(thread, result);
183     EXPECT_STREQ("yesterday", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
184 }
185 
186 // format(-1, always)
HWTEST_F_L0(BuiltinsRelativeTimeFormatTest,Format_004)187 HWTEST_F_L0(BuiltinsRelativeTimeFormatTest, Format_004)
188 {
189     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
190     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
191     JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("always")); // the default value
192     JSHandle<JSRelativeTimeFormat> jsPluralRules =
193         JSHandle<JSRelativeTimeFormat>(thread, JSRelativeTimeFormatCreateWithLocaleTest(
194                                         thread, locale, numericValue));
195     JSHandle<JSTaggedValue> unitValue(factory->NewFromASCII("day"));
196     JSHandle<JSTaggedValue> numberValue(thread, JSTaggedValue(-1));
197     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
198     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
199     ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
200     ecmaRuntimeCallInfo->SetCallArg(0, numberValue.GetTaggedValue());
201     ecmaRuntimeCallInfo->SetCallArg(1, unitValue.GetTaggedValue());
202 
203     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
204     JSTaggedValue result = BuiltinsRelativeTimeFormat::Format(ecmaRuntimeCallInfo);
205     TestHelper::TearDownFrame(thread, prev);
206 
207     JSHandle<EcmaString> handleEcmaStr(thread, result);
208     EXPECT_STREQ("1 day ago", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
209 }
210 
211 // format(1, always)
HWTEST_F_L0(BuiltinsRelativeTimeFormatTest,Format_005)212 HWTEST_F_L0(BuiltinsRelativeTimeFormatTest, Format_005)
213 {
214     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
215     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
216     JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("always")); // the default value
217     JSHandle<JSRelativeTimeFormat> jsPluralRules =
218         JSHandle<JSRelativeTimeFormat>(thread, JSRelativeTimeFormatCreateWithLocaleTest(
219                                         thread, locale, numericValue));
220     JSHandle<JSTaggedValue> unitValue(factory->NewFromASCII("day"));
221     JSHandle<JSTaggedValue> numberValue(thread, JSTaggedValue(1));
222     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
223     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
224     ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
225     ecmaRuntimeCallInfo->SetCallArg(0, numberValue.GetTaggedValue());
226     ecmaRuntimeCallInfo->SetCallArg(1, unitValue.GetTaggedValue());
227 
228     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
229     JSTaggedValue result = BuiltinsRelativeTimeFormat::Format(ecmaRuntimeCallInfo);
230     TestHelper::TearDownFrame(thread, prev);
231 
232     JSHandle<EcmaString> handleEcmaStr(thread, result);
233     EXPECT_STREQ("in 1 day", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
234 }
235 
HWTEST_F_L0(BuiltinsRelativeTimeFormatTest,FormatToParts)236 HWTEST_F_L0(BuiltinsRelativeTimeFormatTest, FormatToParts)
237 {
238     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
239     JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
240     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en"));
241     JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("always"));
242     JSHandle<JSRelativeTimeFormat> jsPluralRules =
243         JSHandle<JSRelativeTimeFormat>(thread, JSRelativeTimeFormatCreateWithLocaleTest(
244                                         thread, locale, numericValue));
245     JSHandle<JSTaggedValue> unitValue(factory->NewFromASCII("seconds"));
246     JSHandle<JSTaggedValue> numberValue(thread, JSTaggedValue(10));
247 
248     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
249     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
250     ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
251     ecmaRuntimeCallInfo->SetCallArg(0, numberValue.GetTaggedValue());
252     ecmaRuntimeCallInfo->SetCallArg(1, unitValue.GetTaggedValue());
253 
254     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
255     JSTaggedValue result = BuiltinsRelativeTimeFormat::FormatToParts(ecmaRuntimeCallInfo);
256     TestHelper::TearDownFrame(thread, prev);
257 
258     JSHandle<JSArray> resultArr(thread, result);
259     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSObject>(resultArr), lengthKey).GetValue()->GetInt(), 3);
260 }
261 
HWTEST_F_L0(BuiltinsRelativeTimeFormatTest,ResolvedOptions)262 HWTEST_F_L0(BuiltinsRelativeTimeFormatTest, ResolvedOptions)
263 {
264     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
265     auto globalConst = thread->GlobalConstants();
266     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("de-DE"));
267     JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("auto"));
268     JSHandle<JSRelativeTimeFormat> jsPluralRules =
269         JSHandle<JSRelativeTimeFormat>(thread, JSRelativeTimeFormatCreateWithLocaleTest(
270                                         thread, locale, numericValue));
271 
272     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
273     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
274     ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
275 
276     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
277     JSTaggedValue result = BuiltinsRelativeTimeFormat::ResolvedOptions(ecmaRuntimeCallInfo);
278     TestHelper::TearDownFrame(thread, prev);
279 
280     JSHandle<JSTaggedValue> resultObj =
281         JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<JSTaggedType>(result.GetRawData())));
282     // judge whether the properties of the object are the same as those of jsrelativetimeformat tag
283     JSHandle<JSTaggedValue> localeKey = globalConst->GetHandledLocaleString();
284     EXPECT_EQ(JSTaggedValue::SameValue(
285         JSObject::GetProperty(thread, resultObj, localeKey).GetValue(), locale), true);
286     JSHandle<JSTaggedValue> styleKey = globalConst->GetHandledStyleString();
287     JSHandle<JSTaggedValue> styleValue(factory->NewFromASCII("long"));
288     EXPECT_EQ(JSTaggedValue::SameValue(
289         JSObject::GetProperty(thread, resultObj, styleKey).GetValue(), styleValue), true);
290     JSHandle<JSTaggedValue> numberingSystemKey = globalConst->GetHandledNumberingSystemString();
291     JSHandle<JSTaggedValue> numberingSystemValue(factory->NewFromASCII("latn"));
292     EXPECT_EQ(JSTaggedValue::SameValue(
293         JSObject::GetProperty(thread, resultObj, numberingSystemKey).GetValue(), numberingSystemValue), true);
294 }
295 } // namespace panda::test
296