1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "mozilla/FloatingPoint.h" // mozilla::{PositiveInfinity,UnspecifiedNaN}
10 #include <stddef.h> // size_t
11 #include <string.h> // memcmp, memset
13 #include "js/Conversions.h" // JS::NumberToString, JS::MaximumNumberToStringLength
14 #include "jsapi-tests/tests.h" // BEGIN_TEST, CHECK_EQUAL, END_TEST
15 #include "util/Text.h" // js_strlen
17 #define REST(x) x, (js_strlen(x)), __LINE__
19 static const struct NumberToStringTest
{
22 size_t expectedLength
;
24 } numberToStringTests
[] = {
25 {5e-324, REST("5e-324")}, // 2**-1074
26 {9.5367431640625e-7, REST("9.5367431640625e-7")}, // 2**-20
27 {0.0000010984284297360395, REST("0.0000010984284297360395")},
28 {0.0000019073486328125, REST("0.0000019073486328125")}, // 2**-19
29 {0.000003814697265625, REST("0.000003814697265625")}, // 2**-18
30 {0.0000057220458984375, REST("0.0000057220458984375")}, // 2**-18 + 2**-19
31 {0.000244140625, REST("0.000244140625")}, // 2**-12
32 {0.125, REST("0.125")},
42 {389427, REST("389427")},
43 {1073741823, REST("1073741823")},
44 {1073741824, REST("1073741824")},
45 {1073741825, REST("1073741825")},
46 {2147483647, REST("2147483647")},
47 {2147483648, REST("2147483648")},
48 {2147483649, REST("2147483649")},
49 {4294967294, REST("4294967294")},
50 {4294967295, REST("4294967295")},
51 {4294967296, REST("4294967296")},
52 {999999999999999900000.0, REST("999999999999999900000")},
53 {999999999999999900000.0 + 65535, REST("999999999999999900000")},
54 {999999999999999900000.0 + 65536, REST("1e+21")},
55 {1.7976931348623157e+308, REST("1.7976931348623157e+308")}, // MAX_VALUE
58 static constexpr char PoisonChar
= 0x37;
60 struct StorageForNumberToString
{
61 char out
[JS::MaximumNumberToStringLength
];
65 BEGIN_TEST(testNumberToString
) {
66 StorageForNumberToString storage
;
68 if (!testNormalValues(false, storage
)) {
72 if (!testNormalValues(true, storage
)) {
76 NumberToStringTest zeroTest
= {0.0, REST("0")};
77 if (!testOne(zeroTest
, false, storage
)) {
80 NumberToStringTest negativeZeroTest
= {-0.0, REST("0")};
81 if (!testOne(negativeZeroTest
, false, storage
)) {
85 NumberToStringTest infTest
= {mozilla::PositiveInfinity
<double>(),
87 if (!testOne(infTest
, false, storage
)) {
90 if (!testOne(infTest
, true, storage
)) {
94 NumberToStringTest nanTest
= {mozilla::UnspecifiedNaN
<double>(), REST("NaN")};
95 return testOne(nanTest
, false, storage
);
98 bool testNormalValues(bool hasMinusSign
, StorageForNumberToString
& storage
) {
99 for (const auto& test
: numberToStringTests
) {
100 if (!testOne(test
, hasMinusSign
, storage
)) {
108 bool testOne(const NumberToStringTest
& test
, bool hasMinusSign
,
109 StorageForNumberToString
& storage
) {
110 memset(&storage
, PoisonChar
, sizeof(storage
));
112 JS::NumberToString(hasMinusSign
? -test
.number
: test
.number
, storage
.out
);
114 CHECK_EQUAL(storage
.overflow
, PoisonChar
);
116 const char* start
= storage
.out
;
118 CHECK_EQUAL(start
[0], '-');
122 if (!checkEqual(memcmp(start
, test
.expected
, test
.expectedLength
), 0, start
,
123 test
.expected
, __FILE__
, test
.lineno
)) {
127 char actualTerminator
[] = {start
[test
.expectedLength
], '\0'};
128 return checkEqual(actualTerminator
[0], '\0', actualTerminator
, "'\\0'",
129 __FILE__
, test
.lineno
);
131 END_TEST(testNumberToString
)