• 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 "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