1 /*
2 * Copyright (c) 2021 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_number.h"
17
18 #include <cmath>
19 #include <iostream>
20 #include <limits>
21
22 #include "ecmascript/base/number_helper.h"
23 #include "ecmascript/base/string_helper.h"
24 #include "ecmascript/ecma_runtime_call_info.h"
25 #include "ecmascript/ecma_string.h"
26 #include "ecmascript/ecma_vm.h"
27 #include "ecmascript/global_env.h"
28 #include "ecmascript/js_function.h"
29 #include "ecmascript/js_global_object.h"
30 #include "ecmascript/js_handle.h"
31 #include "ecmascript/js_primitive_ref.h"
32 #include "ecmascript/js_tagged_value-inl.h"
33 #include "ecmascript/js_thread.h"
34 #include "ecmascript/object_factory.h"
35 #include "ecmascript/tests/test_helper.h"
36
37 using namespace panda::ecmascript;
38 using namespace panda::ecmascript::builtins;
39
40 namespace panda::test {
41 class BuiltinsNumberTest : public testing::Test {
42 public:
SetUpTestCase()43 static void SetUpTestCase()
44 {
45 GTEST_LOG_(INFO) << "SetUpTestCase";
46 }
47
TearDownTestCase()48 static void TearDownTestCase()
49 {
50 GTEST_LOG_(INFO) << "TearDownCase";
51 }
52
SetUp()53 void SetUp() override
54 {
55 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
56 }
57
TearDown()58 void TearDown() override
59 {
60 TestHelper::DestroyEcmaVMWithScope(instance, scope);
61 }
62
63 EcmaVM *instance {nullptr};
64 EcmaHandleScope *scope {nullptr};
65 JSThread *thread {nullptr};
66 };
67
68 // new Number(10)
HWTEST_F_L0(BuiltinsNumberTest,NumberConstructor)69 HWTEST_F_L0(BuiltinsNumberTest, NumberConstructor)
70 {
71 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
72
73 JSHandle<JSFunction> number(env->GetNumberFunction());
74 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
75
76 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*number), 6);
77 ecmaRuntimeCallInfo->SetFunction(number.GetTaggedValue());
78 ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
79 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(5)));
80
81 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
82 JSTaggedValue result = BuiltinsNumber::NumberConstructor(ecmaRuntimeCallInfo);
83 TestHelper::TearDownFrame(thread, prev);
84 JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
85 ASSERT_TRUE(value.IsECMAObject());
86 JSPrimitiveRef *ref = JSPrimitiveRef::Cast(value.GetTaggedObject());
87 ASSERT_EQ(ref->GetValue().GetDouble(), 5.0);
88 }
89
90 // Number.isFinite(-10)
HWTEST_F_L0(BuiltinsNumberTest,IsFinite)91 HWTEST_F_L0(BuiltinsNumberTest, IsFinite)
92 {
93 const double value = -10;
94 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
95 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
96 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
97 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(value)));
98
99 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
100 JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
101 ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
102 TestHelper::TearDownFrame(thread, prev);
103 }
104
105 // Number.isFinite(Number.MAX_VALUE)
HWTEST_F_L0(BuiltinsNumberTest,IsFinite1)106 HWTEST_F_L0(BuiltinsNumberTest, IsFinite1)
107 {
108 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
109 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
110 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
111 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(base::MAX_VALUE));
112
113 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
114 JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
115 ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
116 TestHelper::TearDownFrame(thread, prev);
117 }
118
119 // Number.isFinite("helloworld")
HWTEST_F_L0(BuiltinsNumberTest,IsFinite2)120 HWTEST_F_L0(BuiltinsNumberTest, IsFinite2)
121 {
122 JSHandle<EcmaString> test = thread->GetEcmaVM()->GetFactory()->NewFromASCII("helloworld");
123 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
124 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
125 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
126 ecmaRuntimeCallInfo->SetCallArg(0, test.GetTaggedValue());
127
128 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
129 JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
130 ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
131 TestHelper::TearDownFrame(thread, prev);
132 }
133
134 // Number.isFinite(NaN)
HWTEST_F_L0(BuiltinsNumberTest,IsFinite3)135 HWTEST_F_L0(BuiltinsNumberTest, IsFinite3)
136 {
137 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
138 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
139 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
140 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(base::NAN_VALUE));
141
142 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
143 JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
144 ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
145 TestHelper::TearDownFrame(thread, prev);
146 }
147
148 // Number.isFinite(Infinity)
HWTEST_F_L0(BuiltinsNumberTest,IsFinite4)149 HWTEST_F_L0(BuiltinsNumberTest, IsFinite4)
150 {
151 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
152 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
153 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
154 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(base::POSITIVE_INFINITY));
155
156 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
157 JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
158 ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
159 TestHelper::TearDownFrame(thread, prev);
160 }
161
162 // Number.isFinite(undefined)
HWTEST_F_L0(BuiltinsNumberTest,IsFinite5)163 HWTEST_F_L0(BuiltinsNumberTest, IsFinite5)
164 {
165 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
166 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
167 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
168 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Undefined());
169
170 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
171 JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
172 ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
173 TestHelper::TearDownFrame(thread, prev);
174 }
175
176 // Number.isFinite(null)
HWTEST_F_L0(BuiltinsNumberTest,IsFinite6)177 HWTEST_F_L0(BuiltinsNumberTest, IsFinite6)
178 {
179 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
180 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
181 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
182 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Null());
183
184 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
185 JSTaggedValue result = BuiltinsNumber::IsFinite(ecmaRuntimeCallInfo);
186 ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
187 TestHelper::TearDownFrame(thread, prev);
188 }
189
190 // Number.isInteger(0.1)
HWTEST_F_L0(BuiltinsNumberTest,IsInteger)191 HWTEST_F_L0(BuiltinsNumberTest, IsInteger)
192 {
193 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
194 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
195 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
196 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(0.1));
197
198 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
199 JSTaggedValue result = BuiltinsNumber::IsInteger(ecmaRuntimeCallInfo);
200 ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
201 TestHelper::TearDownFrame(thread, prev);
202 }
203
204 // Number.isNaN(0.1)
HWTEST_F_L0(BuiltinsNumberTest,IsNaN)205 HWTEST_F_L0(BuiltinsNumberTest, IsNaN)
206 {
207 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
208 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
209 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
210 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(0.1));
211
212 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
213 JSTaggedValue result = BuiltinsNumber::IsNaN(ecmaRuntimeCallInfo);
214 ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
215 TestHelper::TearDownFrame(thread, prev);
216 }
217
218 // new Number(123.456).toString(7)
HWTEST_F_L0(BuiltinsNumberTest,ToString)219 HWTEST_F_L0(BuiltinsNumberTest, ToString)
220 {
221 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
222 auto ecmaVM = thread->GetEcmaVM();
223 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
224
225 JSHandle<JSFunction> numberObject(env->GetNumberFunction());
226 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
227 JSHandle<JSPrimitiveRef> number = thread->GetEcmaVM()->GetFactory()->NewJSPrimitiveRef(numberObject, value);
228
229 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
230 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
231 ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
232 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(7.0));
233
234 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
235 JSTaggedValue result = BuiltinsNumber::ToString(ecmaRuntimeCallInfo);
236 ASSERT_TRUE(result.IsString());
237 JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
238 JSHandle<EcmaString> correctResult = factory->NewFromASCII("234.312256641535441");
239 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*res, *correctResult));
240 TestHelper::TearDownFrame(thread, prev);
241 }
242
243 // new Number(123.456).toExponential(5)
HWTEST_F_L0(BuiltinsNumberTest,IsExponential)244 HWTEST_F_L0(BuiltinsNumberTest, IsExponential)
245 {
246 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
247 auto ecmaVM = thread->GetEcmaVM();
248 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
249
250 JSHandle<JSFunction> numberObject(env->GetNumberFunction());
251 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
252 JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
253
254 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
255 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
256 ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
257 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(5.0));
258
259 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
260 JSTaggedValue result = BuiltinsNumber::ToExponential(ecmaRuntimeCallInfo);
261 ASSERT_TRUE(result.IsString());
262 JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
263 JSHandle<EcmaString> correctResult = factory->NewFromASCII("1.23456e+2");
264 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*res, *correctResult));
265 TestHelper::TearDownFrame(thread, prev);
266 }
267
268 // new Number(123.456).toFixed(10)
HWTEST_F_L0(BuiltinsNumberTest,ToFixed)269 HWTEST_F_L0(BuiltinsNumberTest, ToFixed)
270 {
271 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
272 auto ecmaVM = thread->GetEcmaVM();
273 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
274
275 JSHandle<JSFunction> numberObject(env->GetNumberFunction());
276 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
277 JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
278
279 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
280 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
281 ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
282 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(10.0));
283
284 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
285 JSTaggedValue result = BuiltinsNumber::ToFixed(ecmaRuntimeCallInfo);
286 ASSERT_TRUE(result.IsString());
287 JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
288 JSHandle<EcmaString> correctResult = factory->NewFromASCII("123.4560000000");
289 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*res, *correctResult));
290 TestHelper::TearDownFrame(thread, prev);
291 }
292
293 // new Number(123.456).toFixed(30)
HWTEST_F_L0(BuiltinsNumberTest,ToFixed1)294 HWTEST_F_L0(BuiltinsNumberTest, ToFixed1)
295 {
296 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
297 auto ecmaVM = thread->GetEcmaVM();
298 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
299
300 JSHandle<JSFunction> numberObject(env->GetNumberFunction());
301 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
302 JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
303
304 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
305 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
306 ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
307 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(30.0));
308
309 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
310 JSTaggedValue result = BuiltinsNumber::ToFixed(ecmaRuntimeCallInfo);
311 ASSERT_TRUE(result.IsString());
312 JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
313 JSHandle<EcmaString> correctResult = factory->NewFromASCII("123.456000000000003069544618483633");
314 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*res, *correctResult));
315 TestHelper::TearDownFrame(thread, prev);
316 }
317
318 // new Number(1e21).toFixed(20)
HWTEST_F_L0(BuiltinsNumberTest,ToFixed2)319 HWTEST_F_L0(BuiltinsNumberTest, ToFixed2) {
320 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
321 auto ecmaVM = thread->GetEcmaVM();
322 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
323
324 JSHandle<JSFunction> numberObject(env->GetNumberFunction());
325 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1e21));
326 JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
327
328 auto ecmaRuntimeCallInfo =
329 TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
330 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
331 ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
332 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(20.0));
333
334 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
335 JSTaggedValue result = BuiltinsNumber::ToFixed(ecmaRuntimeCallInfo);
336 ASSERT_TRUE(result.IsString());
337 JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
338 JSHandle<EcmaString> correctResult = factory->NewFromASCII("1e+21");
339 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*res, *correctResult));
340 TestHelper::TearDownFrame(thread, prev);
341 }
342
343 // new Number(123.456).toPrecision(8)
HWTEST_F_L0(BuiltinsNumberTest,ToPrecision)344 HWTEST_F_L0(BuiltinsNumberTest, ToPrecision)
345 {
346 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
347 auto ecmaVM = thread->GetEcmaVM();
348 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
349
350 JSHandle<JSFunction> numberObject(env->GetNumberFunction());
351 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(123.456));
352 JSHandle<JSPrimitiveRef> number = factory->NewJSPrimitiveRef(numberObject, value);
353
354 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
355 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
356 ecmaRuntimeCallInfo->SetThis(number.GetTaggedValue());
357 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(8.0));
358
359 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
360 JSTaggedValue result = BuiltinsNumber::ToPrecision(ecmaRuntimeCallInfo);
361 ASSERT_TRUE(result.IsString());
362 JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
363 JSHandle<EcmaString> correctResult = factory->NewFromASCII("123.45600");
364 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*res, *correctResult));
365 TestHelper::TearDownFrame(thread, prev);
366 }
367
368 // Number.parseFloat(0x123)
HWTEST_F_L0(BuiltinsNumberTest,parseFloat)369 HWTEST_F_L0(BuiltinsNumberTest, parseFloat)
370 {
371 JSHandle<EcmaString> param = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0x123");
372 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
373 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
374 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
375 ecmaRuntimeCallInfo->SetCallArg(0, param.GetTaggedValue());
376
377 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
378 JSTaggedValue result = BuiltinsNumber::ParseFloat(ecmaRuntimeCallInfo);
379 ASSERT_EQ(result.GetRawData(), JSTaggedValue(static_cast<double>(0)).GetRawData());
380 TestHelper::TearDownFrame(thread, prev);
381 }
382
383 // Number.parseFloat(0x123xx)
HWTEST_F_L0(BuiltinsNumberTest,parseFloat1)384 HWTEST_F_L0(BuiltinsNumberTest, parseFloat1)
385 {
386 JSHandle<EcmaString> param = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0x123xx");
387 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
388 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
389 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
390 ecmaRuntimeCallInfo->SetCallArg(0, param.GetTaggedValue());
391
392 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
393 JSTaggedValue result = BuiltinsNumber::ParseFloat(ecmaRuntimeCallInfo);
394 ASSERT_EQ(result.GetRawData(), JSTaggedValue(static_cast<double>(0)).GetRawData());
395 TestHelper::TearDownFrame(thread, prev);
396 }
397
398 // Number.parseInt(0x123)
HWTEST_F_L0(BuiltinsNumberTest,parseInt)399 HWTEST_F_L0(BuiltinsNumberTest, parseInt)
400 {
401 const char *number = "0x123";
402
403 JSHandle<EcmaString> param = thread->GetEcmaVM()->GetFactory()->NewFromASCII(number);
404 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
405 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
406 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
407 ecmaRuntimeCallInfo->SetCallArg(0, param.GetTaggedValue());
408 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(16.0));
409
410 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
411 JSTaggedValue result = BuiltinsNumber::ParseInt(ecmaRuntimeCallInfo);
412 ASSERT_EQ(result.GetRawData(), JSTaggedValue(static_cast<int>(291)).GetRawData());
413 TestHelper::TearDownFrame(thread, prev);
414 }
415
416 // testcases of StringToDouble flags
HWTEST_F_L0(BuiltinsNumberTest,StringToDoubleFlags)417 HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleFlags)
418 {
419 JSHandle<EcmaString> str;
420 Span<const uint8_t> sp;
421 [[maybe_unused]] CVector<uint8_t> buf;
422
423 // flags of IGNORE_TRAILING
424
425 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0a");
426 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
427 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0);
428 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0b");
429 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
430 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0);
431 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0o");
432 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
433 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0);
434 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 00x");
435 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
436 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0);
437 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 000.4_");
438 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
439 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 0.4);
440 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0010.s ");
441 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
442 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 10);
443 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0010e2");
444 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
445 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 1000);
446 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0010e+3_0");
447 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
448 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::IGNORE_TRAILING), 10000);
449
450 // flags of ALLOW_HEX
451 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0x");
452 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
453 ASSERT_TRUE(std::isnan(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_HEX)));
454 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0x10 ");
455 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
456 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_HEX), 16);
457 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0x1g");
458 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
459 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_HEX + base::IGNORE_TRAILING), 1);
460 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0xh");
461 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
462 ASSERT_TRUE(std::isnan(
463 base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_HEX + base::IGNORE_TRAILING)));
464
465 // flags of ALLOW_OCTAL
466 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0O");
467 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
468 ASSERT_TRUE(std::isnan(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_OCTAL)));
469 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0o10 ");
470 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
471 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_OCTAL), 8);
472 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0o1d");
473 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
474 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_OCTAL | base::IGNORE_TRAILING),
475 1);
476 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0o8");
477 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
478 ASSERT_TRUE(std::isnan(
479 base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_OCTAL | base::IGNORE_TRAILING)));
480
481 // flags of ALLOW_BINARY
482 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0b");
483 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
484 ASSERT_TRUE(std::isnan(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_BINARY)));
485 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0b10 ");
486 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
487 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_BINARY), 2);
488 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0b1d");
489 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
490 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_BINARY | base::IGNORE_TRAILING),
491 1);
492 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0b2");
493 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
494 ASSERT_TRUE(std::isnan(
495 base::NumberHelper::StringToDouble(sp.begin(), sp.end(), 0, base::ALLOW_BINARY | base::IGNORE_TRAILING)));
496 }
497
498 // testcases of StringToDouble radix
HWTEST_F_L0(BuiltinsNumberTest,StringToDoubleRadix)499 HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleRadix)
500 {
501 JSHandle<EcmaString> str;
502 Span<const uint8_t> sp;
503 [[maybe_unused]] CVector<uint8_t> buf;
504 int radix;
505
506 radix = 0; // default 10
507 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
508 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
509 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 100);
510 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100.3e2 ");
511 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
512 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 10030);
513 radix = 1;
514 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0000 ");
515 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
516 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 0);
517 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0001 ");
518 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
519 ASSERT_TRUE(std::isnan(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS)));
520 radix = 2;
521 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
522 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
523 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 4);
524 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 11 ");
525 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
526 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 3);
527 radix = 3;
528 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
529 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
530 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 9);
531 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 21 ");
532 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
533 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 7);
534 radix = 4;
535 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
536 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
537 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 16);
538 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 31 ");
539 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
540 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 13);
541 radix = 8;
542 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
543 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
544 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 64);
545 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 71 ");
546 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
547 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 57);
548 radix = 10;
549 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
550 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
551 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 100);
552 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 0020 ");
553 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
554 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 20);
555 radix = 16;
556 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
557 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
558 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 256);
559 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 1e ");
560 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
561 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 30);
562 radix = 18;
563 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
564 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
565 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 324);
566 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 1g ");
567 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
568 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 34);
569 radix = 25;
570 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
571 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
572 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 625);
573 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 1g ");
574 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
575 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 41);
576 radix = 36;
577 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 100 ");
578 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
579 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 1296);
580 str = thread->GetEcmaVM()->GetFactory()->NewFromASCII(" 1z ");
581 sp = EcmaStringAccessor(str).ToUtf8Span(buf);
582 ASSERT_EQ(base::NumberHelper::StringToDouble(sp.begin(), sp.end(), radix, base::NO_FLAGS), 71);
583 }
584
HWTEST_F_L0(BuiltinsNumberTest,NumberToString)585 HWTEST_F_L0(BuiltinsNumberTest, NumberToString)
586 {
587 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
588 JSHandle<EcmaString> res = factory->NewFromASCII("100");
589 ASSERT_EQ(EcmaStringAccessor::Compare(*base::NumberHelper::NumberToString(thread, JSTaggedValue(100)), *res), 0);
590 res = factory->NewFromASCII("11223344");
591 ASSERT_EQ(EcmaStringAccessor::Compare(
592 *base::NumberHelper::NumberToString(thread, JSTaggedValue(11223344)), *res), 0);
593 res = factory->NewFromASCII("1234567890");
594 ASSERT_EQ(EcmaStringAccessor::Compare(
595 *base::NumberHelper::NumberToString(thread, JSTaggedValue(1234567890)), *res), 0);
596 res = factory->NewFromASCII("100");
597 ASSERT_EQ(EcmaStringAccessor::Compare(
598 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.0))), *res), 0);
599 res = factory->NewFromASCII("100.5");
600 ASSERT_EQ(EcmaStringAccessor::Compare(
601 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.5))), *res), 0);
602 res = factory->NewFromASCII("100.25");
603 ASSERT_EQ(EcmaStringAccessor::Compare(
604 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.25))), *res), 0);
605 res = factory->NewFromASCII("100.125");
606 ASSERT_EQ(EcmaStringAccessor::Compare(
607 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.125))), *res), 0);
608 res = factory->NewFromASCII("100.6125");
609 ASSERT_EQ(EcmaStringAccessor::Compare(
610 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.6125))), *res), 0);
611 res = factory->NewFromASCII("0.0006125");
612 ASSERT_EQ(EcmaStringAccessor::Compare(
613 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(0.0006125))), *res), 0);
614 res = factory->NewFromASCII("-0.0006125");
615 ASSERT_EQ(EcmaStringAccessor::Compare(
616 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-0.0006125))), *res), 0);
617 res = factory->NewFromASCII("-1234567890.0006125");
618 ASSERT_EQ(EcmaStringAccessor::Compare(
619 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-1234567890.0006125))), *res), 0);
620 res = factory->NewFromASCII("1234567890.0006125");
621 ASSERT_EQ(EcmaStringAccessor::Compare(
622 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(1234567890.0006125))), *res), 0);
623 res = factory->NewFromASCII("11234567890.000612");
624 ASSERT_EQ(EcmaStringAccessor::Compare(
625 *base::NumberHelper::NumberToString(thread, JSTaggedValue(double(11234567890.0006125))), *res), 0);
626 }
627 } // namespace panda::test
628