testNumberToString.cpp (4220B)
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: 3 */ 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/. */ 7 8 #include "mozilla/FloatingPoint.h" // mozilla::{PositiveInfinity,UnspecifiedNaN} 9 10 #include <stddef.h> // size_t 11 #include <string.h> // memcmp, memset 12 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 16 17 #define REST(x) x, (js_strlen(x)), __LINE__ 18 19 static const struct NumberToStringTest { 20 double number; 21 const char* expected; 22 size_t expectedLength; 23 size_t lineno; 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")}, 33 {0.25, REST("0.25")}, 34 {0.5, REST("0.5")}, 35 {1, REST("1")}, 36 {1.5, REST("1.5")}, 37 {2, REST("2")}, 38 {9, REST("9")}, 39 {10, REST("10")}, 40 {15, REST("15")}, 41 {16, REST("16")}, 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 56 }; 57 58 static constexpr char PoisonChar = 0x37; 59 60 struct StorageForNumberToString { 61 char out[JS::MaximumNumberToStringLength]; 62 char overflow; 63 } storage; 64 65 BEGIN_TEST(testNumberToString) { 66 StorageForNumberToString storage; 67 68 if (!testNormalValues(false, storage)) { 69 return false; 70 } 71 72 if (!testNormalValues(true, storage)) { 73 return false; 74 } 75 76 NumberToStringTest zeroTest = {0.0, REST("0")}; 77 if (!testOne(zeroTest, false, storage)) { 78 return false; 79 } 80 NumberToStringTest negativeZeroTest = {-0.0, REST("0")}; 81 if (!testOne(negativeZeroTest, false, storage)) { 82 return false; 83 } 84 85 NumberToStringTest infTest = {mozilla::PositiveInfinity<double>(), 86 REST("Infinity")}; 87 if (!testOne(infTest, false, storage)) { 88 return false; 89 } 90 if (!testOne(infTest, true, storage)) { 91 return false; 92 } 93 94 NumberToStringTest nanTest = {mozilla::UnspecifiedNaN<double>(), REST("NaN")}; 95 return testOne(nanTest, false, storage); 96 } 97 98 bool testNormalValues(bool hasMinusSign, StorageForNumberToString& storage) { 99 for (const auto& test : numberToStringTests) { 100 if (!testOne(test, hasMinusSign, storage)) { 101 return false; 102 } 103 } 104 105 return true; 106 } 107 108 bool testOne(const NumberToStringTest& test, bool hasMinusSign, 109 StorageForNumberToString& storage) { 110 memset(&storage, PoisonChar, sizeof(storage)); 111 112 JS::NumberToString(hasMinusSign ? -test.number : test.number, storage.out); 113 114 CHECK_EQUAL(storage.overflow, PoisonChar); 115 116 const char* start = storage.out; 117 if (hasMinusSign) { 118 CHECK_EQUAL(start[0], '-'); 119 start++; 120 } 121 122 if (!checkEqual(memcmp(start, test.expected, test.expectedLength), 0, start, 123 test.expected, __FILE__, test.lineno)) { 124 return false; 125 } 126 127 char actualTerminator[] = {start[test.expectedLength], '\0'}; 128 return checkEqual(actualTerminator[0], '\0', actualTerminator, "'\\0'", 129 __FILE__, test.lineno); 130 } 131 END_TEST(testNumberToString) 132 133 #undef REST