11
#include <celutil/formatnum.h>
13
using namespace std::string_view_literals;
14
using celestia::util::NumberFormat;
15
using celestia::util::NumberFormatter;
20
class TestNumpunct : public std::numpunct<wchar_t>
24
wchar_t do_decimal_point() const override { return L'x'; }
25
wchar_t do_thousands_sep() const override { return L'_'; }
27
std::string do_grouping() const override { return "\003\002"; }
30
using TestCase = std::tuple<double, unsigned int, std::string_view>;
34
TEST_SUITE_BEGIN("Formatnum");
36
TEST_CASE("NumberFormat None")
38
constexpr auto format = NumberFormat::None;
40
std::locale testloc{ std::locale("C"), new TestNumpunct() };
42
NumberFormatter formatter(testloc);
44
constexpr std::array testCases
46
TestCase{ 0.0, 0, "0"sv },
47
TestCase{ 0.0, 2, "0x00"sv },
48
TestCase{ -0.0, 0, "-0"sv },
49
TestCase{ -0.0, 3, "-0x000"sv },
50
TestCase{ 12.345, 1, "12x3"sv },
51
TestCase{ -12.346, 2, "-12x35"sv },
54
for (const auto& [value, precision, expected] : testCases)
56
auto actual = fmt::format("{}", formatter.format(value, precision, format));
57
REQUIRE(expected == actual);
61
TEST_CASE("NumberFormat GroupThousands")
63
constexpr auto format = NumberFormat::GroupThousands;
65
std::locale testloc{ std::locale("C"), new TestNumpunct() };
67
NumberFormatter formatter(testloc);
69
constexpr std::array testCases
71
TestCase{ 0.0, 0, "0"sv },
72
TestCase{ 0.0, 2, "0x00"sv },
73
TestCase{ -0.0, 0, "-0"sv },
74
TestCase{ -0.0, 3, "-0x000"sv },
75
TestCase{ 12.345, 1, "12x3"sv },
76
TestCase{ -12.346, 2, "-12x35"sv },
77
TestCase{ 123.98, 1, "124x0"sv },
78
TestCase{ -123.98, 1, "-124x0"sv },
79
TestCase{ 1234.12, 1, "1_234x1"sv },
80
TestCase{ -1234.12, 1, "-1_234x1"sv },
81
TestCase{ 12345.12, 2, "12_345x12"sv },
82
TestCase{ -12345.12, 2, "-12_345x12"sv },
83
TestCase{ 123456.1, 0, "1_23_456"sv },
84
TestCase{ -123456.1, 0, "-1_23_456"sv },
85
TestCase{ 192837123, 0, "19_28_37_123"sv },
86
TestCase{ -192837123, 0, "-19_28_37_123"sv },
89
for (const auto& [value, precision, expected] : testCases)
91
auto actual = fmt::format("{}", formatter.format(value, precision, format));
92
REQUIRE(expected == actual);
96
TEST_CASE("NumberFormat SignificantFigures")
98
constexpr auto format = NumberFormat::SignificantFigures;
100
std::locale testloc{ std::locale("C"), new TestNumpunct() };
102
NumberFormatter formatter(testloc);
104
constexpr std::array testCases
106
TestCase{ 1.5292, 2, "1x5"sv },
107
TestCase{ -1.5292, 2, "-1x5"sv },
108
TestCase{ 15.292, 2, "15"sv },
109
TestCase{ -15.292, 2, "-15"sv },
110
TestCase{ 152.92, 2, "150"sv },
111
TestCase{ -152.92, 2, "-150"sv },
112
TestCase{ 1529.2, 2, "1500"sv },
113
TestCase{ -1529.2, 2, "-1500"sv },
114
TestCase{ 1529200, 2, "1500000"sv},
115
TestCase{ -1529200, 2, "-1500000"sv},
116
TestCase{ 0.00015292, 2, "0x00015"sv },
117
TestCase{ -0.00015292, 2, "-0x00015"sv },
120
for (const auto& [value, precision, expected] : testCases)
122
auto actual = fmt::format("{}", formatter.format(value, precision, format));
123
REQUIRE(expected == actual);
127
TEST_CASE("NumberFormat GroupThousands+SignificantFigures")
129
constexpr auto format = NumberFormat::GroupThousands | NumberFormat::SignificantFigures;
131
std::locale testloc{ std::locale("C"), new TestNumpunct() };
133
NumberFormatter formatter(testloc);
135
constexpr std::array testCases
137
TestCase{ 1.5292, 2, "1x5"sv },
138
TestCase{ -1.5292, 2, "-1x5"sv },
139
TestCase{ 15.292, 2, "15"sv },
140
TestCase{ -15.292, 2, "-15"sv },
141
TestCase{ 152.92, 2, "150"sv },
142
TestCase{ -152.92, 2, "-150"sv },
143
TestCase{ 1529.2, 2, "1_500"sv },
144
TestCase{ -1529.2, 2, "-1_500"sv },
145
TestCase{ 1529200, 2, "15_00_000"sv},
146
TestCase{ -1529200, 2, "-15_00_000"sv},
147
TestCase{ 0.00015292, 2, "0x00015"sv },
148
TestCase{ -0.00015292, 2, "-0x00015"sv },
151
for (const auto& [value, precision, expected] : testCases)
153
auto actual = fmt::format("{}", formatter.format(value, precision, format));
154
REQUIRE(expected == actual);