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 "builtin_test_util.h"
17 #include "ecmascript/builtins/builtins_date_time_format.h"
18
19 #include <ctime>
20 #include <algorithm>
21 #include "ecmascript/builtins/builtins_array.h"
22 #include "ecmascript/global_env.h"
23 #include "ecmascript/js_date.h"
24 #include "ecmascript/js_date_time_format.h"
25 #include "ecmascript/tests/test_helper.h"
26
27 using namespace panda::ecmascript;
28 using namespace panda::ecmascript::builtins;
29
30 namespace panda::test {
31 using BuiltinsArray = ecmascript::builtins::BuiltinsArray;
32 class BuiltinsDateTimeFormatTest : public BaseTestWithScope<true> {
33 };
34
35 // new DateTimeFormat(locale)
HWTEST_F_L0(BuiltinsDateTimeFormatTest,DateTimeFormatConstructor)36 HWTEST_F_L0(BuiltinsDateTimeFormatTest, DateTimeFormatConstructor)
37 {
38 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
39 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
40 JSHandle<JSFunction> newTarget(env->GetDateTimeFormatFunction());
41
42 JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("en-US"));
43 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
44 ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
45 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
46 ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
47 // option tag is default value
48 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
49
50 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
51 JSTaggedValue result = BuiltinsDateTimeFormat::DateTimeFormatConstructor(ecmaRuntimeCallInfo);
52 TestHelper::TearDownFrame(thread, prev);
53 EXPECT_TRUE(result.IsJSDateTimeFormat());
54 }
55
BuiltinsDateCreate(const double year,const double month,const double date)56 static double BuiltinsDateCreate(const double year, const double month, const double date)
57 {
58 const double day = JSDate::MakeDay(year, month, date);
59 const double time = JSDate::MakeTime(0, 0, 0, 0); // 24:00:00
60 double days = JSDate::MakeDate(day, time);
61 return days;
62 }
63
64 enum class AlgorithmType {
65 ALGORITHM_FORMAT,
66 ALGORITHM_FORMAT_TO_PARTS,
67 ALGORITHM_FORMAT_RANGE,
68 ALGORITHM_FORMAT_RANGE_TO_PARTS,
69 };
70
AtomicsAlgorithm(JSThread * thread,JSHandle<JSDateTimeFormat> & jsDateTimeFormat,std::vector<JSTaggedValue> vals,uint32_t argLen,AlgorithmType type=AlgorithmType::ALGORITHM_FORMAT)71 static JSTaggedValue AtomicsAlgorithm(JSThread *thread, JSHandle<JSDateTimeFormat>& jsDateTimeFormat,
72 std::vector<JSTaggedValue> vals, uint32_t argLen, AlgorithmType type = AlgorithmType::ALGORITHM_FORMAT)
73 {
74 auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), argLen);
75 ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
76 ecmaRuntimeCallInfos->SetThis(jsDateTimeFormat.GetTaggedValue());
77 for (size_t i = 0; i < vals.size(); i++) {
78 ecmaRuntimeCallInfos->SetCallArg(i, vals[i]);
79 }
80 auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos);
81 JSTaggedValue result;
82 switch (type) {
83 case AlgorithmType::ALGORITHM_FORMAT:
84 result = BuiltinsDateTimeFormat::Format(ecmaRuntimeCallInfos);
85 break;
86 case AlgorithmType::ALGORITHM_FORMAT_TO_PARTS:
87 result = BuiltinsDateTimeFormat::FormatToParts(ecmaRuntimeCallInfos);
88 break;
89 case AlgorithmType::ALGORITHM_FORMAT_RANGE:
90 result = BuiltinsDateTimeFormat::FormatRange(ecmaRuntimeCallInfos);
91 break;
92 case AlgorithmType::ALGORITHM_FORMAT_RANGE_TO_PARTS:
93 result = BuiltinsDateTimeFormat::FormatRangeToParts(ecmaRuntimeCallInfos);
94 break;
95 default:
96 break;
97 }
98 TestHelper::TearDownFrame(thread, prev);
99 return result;
100 }
101
FormatCommon(JSThread * thread,std::string_view localeStr,double days)102 JSHandle<EcmaString> FormatCommon(JSThread *thread, std::string_view localeStr, double days)
103 {
104 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
105 JSHandle<JSTaggedValue> locale(factory->NewFromASCII(localeStr));
106 JSHandle<JSDateTimeFormat> jsDateTimeFormat =
107 JSHandle<JSDateTimeFormat>(thread, BuiltTestUtil::JSDateTimeFormatCreateWithLocaleTest(thread, locale));
108
109 std::vector<JSTaggedValue> vals{JSTaggedValue::Undefined()};
110 auto result1 =
111 AtomicsAlgorithm(thread, jsDateTimeFormat, vals, 6, AlgorithmType::ALGORITHM_FORMAT); // 6: args length
112 JSHandle<JSFunction> jsFunction(thread, result1);
113 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(static_cast<double>(days)));
114 auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
115 ecmaRuntimeCallInfo2->SetFunction(jsFunction.GetTaggedValue());
116 ecmaRuntimeCallInfo2->SetThis(jsFunction.GetTaggedValue());
117 ecmaRuntimeCallInfo2->SetCallArg(0, value.GetTaggedValue());
118
119 auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
120 JSTaggedValue result2 = JSFunction::Call(ecmaRuntimeCallInfo2);
121 TestHelper::TearDownFrame(thread, prev);
122 JSHandle<EcmaString> resultStr(thread, result2);
123 return resultStr;
124 }
125
126 // Format.Tostring(en-US)
HWTEST_F_L0(BuiltinsDateTimeFormatTest,Format_001)127 HWTEST_F_L0(BuiltinsDateTimeFormatTest, Format_001)
128 {
129 double days = BuiltinsDateCreate(2020, 10, 1);
130 auto resultStr = FormatCommon(thread, "en-US", days);
131 EXPECT_STREQ("Sun, 11/1/2020, 24:00:00", EcmaStringAccessor(resultStr).ToCString().c_str());
132 }
133
134 // Format.Tostring(pt-BR)
HWTEST_F_L0(BuiltinsDateTimeFormatTest,Format_002)135 HWTEST_F_L0(BuiltinsDateTimeFormatTest, Format_002)
136 {
137 double days = BuiltinsDateCreate(2020, 5, 11);
138 auto resultStr = FormatCommon(thread, "pt-BR", days);
139 CString resStr = EcmaStringAccessor(resultStr).ToCString();
140 // the index of string "qui" is zero.
141 EXPECT_TRUE(resStr.find("qui") == 0);
142 // the index of string "11/06/2020 24:00:00" is not zero.
143 EXPECT_TRUE(resStr.find("11/06/2020 24:00:00") != 0);
144 }
145
HWTEST_F_L0(BuiltinsDateTimeFormatTest,FormatToParts)146 HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatToParts)
147 {
148 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
149 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
150 JSHandle<JSDateTimeFormat> jsDateTimeFormat =
151 JSHandle<JSDateTimeFormat>(thread, BuiltTestUtil::JSDateTimeFormatCreateWithLocaleTest(thread, locale));
152
153 std::vector<JSTaggedValue> vals{JSTaggedValue::Undefined()};
154 auto result = AtomicsAlgorithm(thread, jsDateTimeFormat, vals, 6,
155 AlgorithmType::ALGORITHM_FORMAT_TO_PARTS); // 6: args length
156 JSHandle<JSArray> resultHandle(thread, result);
157 JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
158 EXPECT_EQ(elements->GetLength(), 16U); // sixteen formatters
159 }
160
161 // FormatRange(zh)
HWTEST_F_L0(BuiltinsDateTimeFormatTest,FormatRange_001)162 HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatRange_001)
163 {
164 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
165 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("zh"));
166 JSHandle<JSDateTimeFormat> jsDateTimeFormat =
167 JSHandle<JSDateTimeFormat>(thread, BuiltTestUtil::JSDateTimeFormatCreateWithLocaleTest(thread, locale));
168
169 double days1 = BuiltinsDateCreate(2020, 10, 1);
170 double days2 = BuiltinsDateCreate(2021, 6, 1);
171
172 std::vector<JSTaggedValue> vals{JSTaggedValue(static_cast<double>(days1)),
173 JSTaggedValue(static_cast<double>(days2))};
174 auto result =
175 AtomicsAlgorithm(thread, jsDateTimeFormat, vals, 8, AlgorithmType::ALGORITHM_FORMAT_RANGE); // 8: args length
176
177 JSHandle<EcmaString> handleStr(thread, result);
178 JSHandle<EcmaString> resultStr = factory->NewFromUtf8("2020/11/1周日 24:00:00 – 2021/7/1周四 24:00:00");
179 EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleStr, resultStr), 0);
180 }
181
182 // FormatRange(en)
HWTEST_F_L0(BuiltinsDateTimeFormatTest,FormatRange_002)183 HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatRange_002)
184 {
185 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
186 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
187 JSHandle<JSDateTimeFormat> jsDateTimeFormat =
188 JSHandle<JSDateTimeFormat>(thread, BuiltTestUtil::JSDateTimeFormatCreateWithLocaleTest(thread, locale));
189
190 double days1 = BuiltinsDateCreate(2020, 12, 1);
191 double days2 = BuiltinsDateCreate(2021, 2, 1);
192
193 std::vector<JSTaggedValue> vals{JSTaggedValue(static_cast<double>(days1)),
194 JSTaggedValue(static_cast<double>(days2))};
195 auto result =
196 AtomicsAlgorithm(thread, jsDateTimeFormat, vals, 8, AlgorithmType::ALGORITHM_FORMAT_RANGE); // 8: args length
197
198 JSHandle<EcmaString> handleStr(thread, result);
199 JSHandle<EcmaString> resultStr = factory->NewFromUtf8("Fri, 1/1/2021, 24:00:00 – Mon, 3/1/2021, 24:00:00");
200 EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleStr, resultStr), 0);
201 }
202
HWTEST_F_L0(BuiltinsDateTimeFormatTest,FormatRangeToParts)203 HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatRangeToParts)
204 {
205 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
206 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
207 JSHandle<JSDateTimeFormat> jsDateTimeFormat =
208 JSHandle<JSDateTimeFormat>(thread, BuiltTestUtil::JSDateTimeFormatCreateWithLocaleTest(thread, locale));
209
210 double days1 = BuiltinsDateCreate(2020, 12, 1);
211 double days2 = BuiltinsDateCreate(2021, 2, 1);
212 std::vector<JSTaggedValue> vals{JSTaggedValue(static_cast<double>(days1)),
213 JSTaggedValue(static_cast<double>(days2))};
214 auto result = AtomicsAlgorithm(thread, jsDateTimeFormat, vals, 8,
215 AlgorithmType::ALGORITHM_FORMAT_RANGE_TO_PARTS); // 8: args length
216
217 JSHandle<JSArray> resultHandle(thread, result);
218 JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
219 EXPECT_EQ(elements->GetLength(), 39U); // The number of characters of "Fri1/1/202124:00:00–Mon3/1/202124:00:00"
220 }
221 } // namespace panda::test
222
223