summaryrefslogtreecommitdiffstats
path: root/js/src/jsapi-tests/testNumberToString.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsapi-tests/testNumberToString.cpp')
-rw-r--r--js/src/jsapi-tests/testNumberToString.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/js/src/jsapi-tests/testNumberToString.cpp b/js/src/jsapi-tests/testNumberToString.cpp
new file mode 100644
index 0000000000..d5107327c6
--- /dev/null
+++ b/js/src/jsapi-tests/testNumberToString.cpp
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/FloatingPoint.h" // mozilla::{PositiveInfinity,UnspecifiedNaN}
+
+#include <stddef.h> // size_t
+#include <string.h> // memcmp, memset
+
+#include "js/Conversions.h" // JS::NumberToString, JS::MaximumNumberToStringLength
+#include "jsapi-tests/tests.h" // BEGIN_TEST, CHECK_EQUAL, END_TEST
+#include "util/Text.h" // js_strlen
+
+#define REST(x) x, (js_strlen(x)), __LINE__
+
+static const struct NumberToStringTest {
+ double number;
+ const char* expected;
+ size_t expectedLength;
+ size_t lineno;
+} numberToStringTests[] = {
+ {5e-324, REST("5e-324")}, // 2**-1074
+ {9.5367431640625e-7, REST("9.5367431640625e-7")}, // 2**-20
+ {0.0000010984284297360395, REST("0.0000010984284297360395")},
+ {0.0000019073486328125, REST("0.0000019073486328125")}, // 2**-19
+ {0.000003814697265625, REST("0.000003814697265625")}, // 2**-18
+ {0.0000057220458984375, REST("0.0000057220458984375")}, // 2**-18 + 2**-19
+ {0.000244140625, REST("0.000244140625")}, // 2**-12
+ {0.125, REST("0.125")},
+ {0.25, REST("0.25")},
+ {0.5, REST("0.5")},
+ {1, REST("1")},
+ {1.5, REST("1.5")},
+ {2, REST("2")},
+ {9, REST("9")},
+ {10, REST("10")},
+ {15, REST("15")},
+ {16, REST("16")},
+ {389427, REST("389427")},
+ {1073741823, REST("1073741823")},
+ {1073741824, REST("1073741824")},
+ {1073741825, REST("1073741825")},
+ {2147483647, REST("2147483647")},
+ {2147483648, REST("2147483648")},
+ {2147483649, REST("2147483649")},
+ {4294967294, REST("4294967294")},
+ {4294967295, REST("4294967295")},
+ {4294967296, REST("4294967296")},
+ {999999999999999900000.0, REST("999999999999999900000")},
+ {999999999999999900000.0 + 65535, REST("999999999999999900000")},
+ {999999999999999900000.0 + 65536, REST("1e+21")},
+ {1.7976931348623157e+308, REST("1.7976931348623157e+308")}, // MAX_VALUE
+};
+
+static constexpr char PoisonChar = 0x37;
+
+struct StorageForNumberToString {
+ char out[JS::MaximumNumberToStringLength];
+ char overflow;
+} storage;
+
+BEGIN_TEST(testNumberToString) {
+ StorageForNumberToString storage;
+
+ if (!testNormalValues(false, storage)) {
+ return false;
+ }
+
+ if (!testNormalValues(true, storage)) {
+ return false;
+ }
+
+ NumberToStringTest zeroTest = {0.0, REST("0")};
+ if (!testOne(zeroTest, false, storage)) {
+ return false;
+ }
+ NumberToStringTest negativeZeroTest = {-0.0, REST("0")};
+ if (!testOne(negativeZeroTest, false, storage)) {
+ return false;
+ }
+
+ NumberToStringTest infTest = {mozilla::PositiveInfinity<double>(),
+ REST("Infinity")};
+ if (!testOne(infTest, false, storage)) {
+ return false;
+ }
+ if (!testOne(infTest, true, storage)) {
+ return false;
+ }
+
+ NumberToStringTest nanTest = {mozilla::UnspecifiedNaN<double>(), REST("NaN")};
+ return testOne(nanTest, false, storage);
+}
+
+bool testNormalValues(bool hasMinusSign, StorageForNumberToString& storage) {
+ for (const auto& test : numberToStringTests) {
+ if (!testOne(test, hasMinusSign, storage)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool testOne(const NumberToStringTest& test, bool hasMinusSign,
+ StorageForNumberToString& storage) {
+ memset(&storage, PoisonChar, sizeof(storage));
+
+ JS::NumberToString(hasMinusSign ? -test.number : test.number, storage.out);
+
+ CHECK_EQUAL(storage.overflow, PoisonChar);
+
+ const char* start = storage.out;
+ if (hasMinusSign) {
+ CHECK_EQUAL(start[0], '-');
+ start++;
+ }
+
+ if (!checkEqual(memcmp(start, test.expected, test.expectedLength), 0, start,
+ test.expected, __FILE__, test.lineno)) {
+ return false;
+ }
+
+ char actualTerminator[] = {start[test.expectedLength], '\0'};
+ return checkEqual(actualTerminator[0], '\0', actualTerminator, "'\\0'",
+ __FILE__, test.lineno);
+}
+END_TEST(testNumberToString)
+
+#undef REST