1 | //===-- Unittests for IntegerToString -------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "src/__support/CPP/limits.h" |
10 | #include "src/__support/CPP/span.h" |
11 | #include "src/__support/CPP/string_view.h" |
12 | #include "src/__support/big_int.h" |
13 | #include "src/__support/integer_literals.h" |
14 | #include "src/__support/integer_to_string.h" |
15 | #include "src/__support/uint128.h" |
16 | |
17 | #include "test/UnitTest/Test.h" |
18 | |
19 | using LIBC_NAMESPACE::IntegerToString; |
20 | using LIBC_NAMESPACE::cpp::span; |
21 | using LIBC_NAMESPACE::cpp::string_view; |
22 | using LIBC_NAMESPACE::radix::Bin; |
23 | using LIBC_NAMESPACE::radix::Custom; |
24 | using LIBC_NAMESPACE::radix::Dec; |
25 | using LIBC_NAMESPACE::radix::Hex; |
26 | using LIBC_NAMESPACE::radix::Oct; |
27 | using LIBC_NAMESPACE::operator""_u128 ; |
28 | using LIBC_NAMESPACE::operator""_u256 ; |
29 | |
30 | #define EXPECT(type, value, string_value) \ |
31 | { \ |
32 | const type buffer(value); \ |
33 | EXPECT_EQ(buffer.view(), string_view(string_value)); \ |
34 | } |
35 | |
36 | TEST(LlvmLibcIntegerToStringTest, UINT8) { |
37 | using type = IntegerToString<uint8_t>; |
38 | EXPECT(type, 0, "0" ); |
39 | EXPECT(type, 1, "1" ); |
40 | EXPECT(type, 12, "12" ); |
41 | EXPECT(type, 123, "123" ); |
42 | EXPECT(type, UINT8_MAX, "255" ); |
43 | EXPECT(type, -1, "255" ); |
44 | } |
45 | |
46 | TEST(LlvmLibcIntegerToStringTest, INT8) { |
47 | using type = IntegerToString<int8_t>; |
48 | EXPECT(type, 0, "0" ); |
49 | EXPECT(type, 1, "1" ); |
50 | EXPECT(type, 12, "12" ); |
51 | EXPECT(type, 123, "123" ); |
52 | EXPECT(type, -12, "-12" ); |
53 | EXPECT(type, -123, "-123" ); |
54 | EXPECT(type, INT8_MAX, "127" ); |
55 | EXPECT(type, INT8_MIN, "-128" ); |
56 | } |
57 | |
58 | TEST(LlvmLibcIntegerToStringTest, UINT16) { |
59 | using type = IntegerToString<uint16_t>; |
60 | EXPECT(type, 0, "0" ); |
61 | EXPECT(type, 1, "1" ); |
62 | EXPECT(type, 12, "12" ); |
63 | EXPECT(type, 123, "123" ); |
64 | EXPECT(type, 1234, "1234" ); |
65 | EXPECT(type, 12345, "12345" ); |
66 | EXPECT(type, UINT16_MAX, "65535" ); |
67 | EXPECT(type, -1, "65535" ); |
68 | } |
69 | |
70 | TEST(LlvmLibcIntegerToStringTest, INT16) { |
71 | using type = IntegerToString<int16_t>; |
72 | EXPECT(type, 0, "0" ); |
73 | EXPECT(type, 1, "1" ); |
74 | EXPECT(type, 12, "12" ); |
75 | EXPECT(type, 123, "123" ); |
76 | EXPECT(type, 1234, "1234" ); |
77 | EXPECT(type, 12345, "12345" ); |
78 | EXPECT(type, -1, "-1" ); |
79 | EXPECT(type, -12, "-12" ); |
80 | EXPECT(type, -123, "-123" ); |
81 | EXPECT(type, -1234, "-1234" ); |
82 | EXPECT(type, -12345, "-12345" ); |
83 | EXPECT(type, INT16_MAX, "32767" ); |
84 | EXPECT(type, INT16_MIN, "-32768" ); |
85 | } |
86 | |
87 | TEST(LlvmLibcIntegerToStringTest, UINT32) { |
88 | using type = IntegerToString<uint32_t>; |
89 | EXPECT(type, 0, "0" ); |
90 | EXPECT(type, 1, "1" ); |
91 | EXPECT(type, 12, "12" ); |
92 | EXPECT(type, 123, "123" ); |
93 | EXPECT(type, 1234, "1234" ); |
94 | EXPECT(type, 12345, "12345" ); |
95 | EXPECT(type, 123456, "123456" ); |
96 | EXPECT(type, 1234567, "1234567" ); |
97 | EXPECT(type, 12345678, "12345678" ); |
98 | EXPECT(type, 123456789, "123456789" ); |
99 | EXPECT(type, 1234567890, "1234567890" ); |
100 | EXPECT(type, UINT32_MAX, "4294967295" ); |
101 | EXPECT(type, -1, "4294967295" ); |
102 | } |
103 | |
104 | TEST(LlvmLibcIntegerToStringTest, INT32) { |
105 | using type = IntegerToString<int32_t>; |
106 | EXPECT(type, 0, "0" ); |
107 | EXPECT(type, 1, "1" ); |
108 | EXPECT(type, 12, "12" ); |
109 | EXPECT(type, 123, "123" ); |
110 | EXPECT(type, 1234, "1234" ); |
111 | EXPECT(type, 12345, "12345" ); |
112 | EXPECT(type, 123456, "123456" ); |
113 | EXPECT(type, 1234567, "1234567" ); |
114 | EXPECT(type, 12345678, "12345678" ); |
115 | EXPECT(type, 123456789, "123456789" ); |
116 | EXPECT(type, 1234567890, "1234567890" ); |
117 | EXPECT(type, -1, "-1" ); |
118 | EXPECT(type, -12, "-12" ); |
119 | EXPECT(type, -123, "-123" ); |
120 | EXPECT(type, -1234, "-1234" ); |
121 | EXPECT(type, -12345, "-12345" ); |
122 | EXPECT(type, -123456, "-123456" ); |
123 | EXPECT(type, -1234567, "-1234567" ); |
124 | EXPECT(type, -12345678, "-12345678" ); |
125 | EXPECT(type, -123456789, "-123456789" ); |
126 | EXPECT(type, -1234567890, "-1234567890" ); |
127 | EXPECT(type, INT32_MAX, "2147483647" ); |
128 | EXPECT(type, INT32_MIN, "-2147483648" ); |
129 | } |
130 | |
131 | TEST(LlvmLibcIntegerToStringTest, UINT64) { |
132 | using type = IntegerToString<uint64_t>; |
133 | EXPECT(type, 0, "0" ); |
134 | EXPECT(type, 1, "1" ); |
135 | EXPECT(type, 12, "12" ); |
136 | EXPECT(type, 123, "123" ); |
137 | EXPECT(type, 1234, "1234" ); |
138 | EXPECT(type, 12345, "12345" ); |
139 | EXPECT(type, 123456, "123456" ); |
140 | EXPECT(type, 1234567, "1234567" ); |
141 | EXPECT(type, 12345678, "12345678" ); |
142 | EXPECT(type, 123456789, "123456789" ); |
143 | EXPECT(type, 1234567890, "1234567890" ); |
144 | EXPECT(type, 1234567890123456789, "1234567890123456789" ); |
145 | EXPECT(type, UINT64_MAX, "18446744073709551615" ); |
146 | EXPECT(type, -1, "18446744073709551615" ); |
147 | } |
148 | |
149 | TEST(LlvmLibcIntegerToStringTest, INT64) { |
150 | using type = IntegerToString<int64_t>; |
151 | EXPECT(type, 0, "0" ); |
152 | EXPECT(type, 1, "1" ); |
153 | EXPECT(type, 12, "12" ); |
154 | EXPECT(type, 123, "123" ); |
155 | EXPECT(type, 1234, "1234" ); |
156 | EXPECT(type, 12345, "12345" ); |
157 | EXPECT(type, 123456, "123456" ); |
158 | EXPECT(type, 1234567, "1234567" ); |
159 | EXPECT(type, 12345678, "12345678" ); |
160 | EXPECT(type, 123456789, "123456789" ); |
161 | EXPECT(type, 1234567890, "1234567890" ); |
162 | EXPECT(type, 1234567890123456789, "1234567890123456789" ); |
163 | EXPECT(type, -1, "-1" ); |
164 | EXPECT(type, -12, "-12" ); |
165 | EXPECT(type, -123, "-123" ); |
166 | EXPECT(type, -1234, "-1234" ); |
167 | EXPECT(type, -12345, "-12345" ); |
168 | EXPECT(type, -123456, "-123456" ); |
169 | EXPECT(type, -1234567, "-1234567" ); |
170 | EXPECT(type, -12345678, "-12345678" ); |
171 | EXPECT(type, -123456789, "-123456789" ); |
172 | EXPECT(type, -1234567890, "-1234567890" ); |
173 | EXPECT(type, -1234567890123456789, "-1234567890123456789" ); |
174 | EXPECT(type, INT64_MAX, "9223372036854775807" ); |
175 | EXPECT(type, INT64_MIN, "-9223372036854775808" ); |
176 | } |
177 | |
178 | TEST(LlvmLibcIntegerToStringTest, UINT64_Base_8) { |
179 | using type = IntegerToString<int64_t, Oct>; |
180 | EXPECT(type, 0, "0" ); |
181 | EXPECT(type, 012345, "12345" ); |
182 | EXPECT(type, 0123456701234567012345, "123456701234567012345" ); |
183 | EXPECT(type, 01777777777777777777777, "1777777777777777777777" ); |
184 | } |
185 | |
186 | TEST(LlvmLibcIntegerToStringTest, UINT64_Base_16) { |
187 | using type = IntegerToString<uint64_t, Hex>; |
188 | EXPECT(type, 0, "0" ); |
189 | EXPECT(type, 0x12345, "12345" ); |
190 | EXPECT(type, 0x123456789abcdef, "123456789abcdef" ); |
191 | EXPECT(type, 0xffffffffffffffff, "ffffffffffffffff" ); |
192 | using TYPE = IntegerToString<uint64_t, Hex::Uppercase>; |
193 | EXPECT(TYPE, 0x123456789abcdef, "123456789ABCDEF" ); |
194 | } |
195 | |
196 | TEST(LlvmLibcIntegerToStringTest, UINT64_Base_2) { |
197 | using type = IntegerToString<uint64_t, Bin>; |
198 | EXPECT(type, 0, "0" ); |
199 | EXPECT(type, 0b111100001100, "111100001100" ); |
200 | EXPECT(type, 0b100100011101010111100, "100100011101010111100" ); |
201 | EXPECT(type, 0xffffffffffffffff, |
202 | "1111111111111111111111111111111111111111111111111111111111111111" ); |
203 | } |
204 | |
205 | TEST(LlvmLibcIntegerToStringTest, UINT128_Base_16) { |
206 | using type = IntegerToString<UInt128, Hex::WithWidth<32>>; |
207 | EXPECT(type, 0, "00000000000000000000000000000000" ); |
208 | EXPECT(type, 0x12345, "00000000000000000000000000012345" ); |
209 | EXPECT(type, 0x12340000'00000000'00000000'00000000_u128, |
210 | "12340000000000000000000000000000" ); |
211 | EXPECT(type, 0x00000000'00000000'12340000'00000000_u128, |
212 | "00000000000000001234000000000000" ); |
213 | EXPECT(type, 0x00000000'00000001'23400000'00000000_u128, |
214 | "00000000000000012340000000000000" ); |
215 | } |
216 | |
217 | TEST(LlvmLibcIntegerToStringTest, UINT64_Base_36) { |
218 | using type = IntegerToString<uint64_t, Custom<36>>; |
219 | EXPECT(type, 0, "0" ); |
220 | EXPECT(type, 12345, "9ix" ); |
221 | EXPECT(type, 1047601316295595, "abcdefghij" ); |
222 | EXPECT(type, 2092218013456445, "klmnopqrst" ); |
223 | EXPECT(type, 0xffffffffffffffff, "3w5e11264sgsf" ); |
224 | |
225 | using TYPE = IntegerToString<uint64_t, Custom<36>::Uppercase>; |
226 | EXPECT(TYPE, 1867590395, "UVWXYZ" ); |
227 | } |
228 | |
229 | TEST(LlvmLibcIntegerToStringTest, UINT256_Base_16) { |
230 | using UInt256 = LIBC_NAMESPACE::UInt<256>; |
231 | using type = IntegerToString<UInt256, Hex::WithWidth<64>>; |
232 | EXPECT( |
233 | type, |
234 | 0x0000000000000000000000000000000000000000000000000000000000000000_u256, |
235 | "0000000000000000000000000000000000000000000000000000000000000000" ); |
236 | EXPECT( |
237 | type, |
238 | 0x0000000000000000000000000000000000000000000000000000000000012345_u256, |
239 | "0000000000000000000000000000000000000000000000000000000000012345" ); |
240 | EXPECT( |
241 | type, |
242 | 0x0000000000000000000000000000000012340000000000000000000000000000_u256, |
243 | "0000000000000000000000000000000012340000000000000000000000000000" ); |
244 | EXPECT( |
245 | type, |
246 | 0x0000000000000000000000000000000123400000000000000000000000000000_u256, |
247 | "0000000000000000000000000000000123400000000000000000000000000000" ); |
248 | EXPECT( |
249 | type, |
250 | 0x1234000000000000000000000000000000000000000000000000000000000000_u256, |
251 | "1234000000000000000000000000000000000000000000000000000000000000" ); |
252 | } |
253 | |
254 | TEST(LlvmLibcIntegerToStringTest, NegativeInterpretedAsPositive) { |
255 | using BIN = IntegerToString<int8_t, Bin>; |
256 | using OCT = IntegerToString<int8_t, Oct>; |
257 | using DEC = IntegerToString<int8_t, Dec>; |
258 | using HEX = IntegerToString<int8_t, Hex>; |
259 | EXPECT(BIN, -1, "11111111" ); |
260 | EXPECT(OCT, -1, "377" ); |
261 | EXPECT(DEC, -1, "-1" ); // Only DEC format negative values |
262 | EXPECT(HEX, -1, "ff" ); |
263 | } |
264 | |
265 | TEST(LlvmLibcIntegerToStringTest, Width) { |
266 | using BIN = IntegerToString<uint8_t, Bin::WithWidth<4>>; |
267 | using OCT = IntegerToString<uint8_t, Oct::WithWidth<4>>; |
268 | using DEC = IntegerToString<uint8_t, Dec::WithWidth<4>>; |
269 | using HEX = IntegerToString<uint8_t, Hex::WithWidth<4>>; |
270 | EXPECT(BIN, 1, "0001" ); |
271 | EXPECT(HEX, 1, "0001" ); |
272 | EXPECT(OCT, 1, "0001" ); |
273 | EXPECT(DEC, 1, "0001" ); |
274 | } |
275 | |
276 | TEST(LlvmLibcIntegerToStringTest, Prefix) { |
277 | // WithPrefix is not supported for Decimal |
278 | using BIN = IntegerToString<uint8_t, Bin::WithPrefix>; |
279 | using OCT = IntegerToString<uint8_t, Oct::WithPrefix>; |
280 | using HEX = IntegerToString<uint8_t, Hex::WithPrefix>; |
281 | EXPECT(BIN, 1, "0b1" ); |
282 | EXPECT(HEX, 1, "0x1" ); |
283 | EXPECT(OCT, 1, "01" ); |
284 | EXPECT(OCT, 0, "0" ); // Zero is not prefixed for octal |
285 | } |
286 | |
287 | TEST(LlvmLibcIntegerToStringTest, Uppercase) { |
288 | using HEX = IntegerToString<uint64_t, Hex::Uppercase>; |
289 | EXPECT(HEX, 0xDEADC0DE, "DEADC0DE" ); |
290 | } |
291 | |
292 | TEST(LlvmLibcIntegerToStringTest, Sign) { |
293 | // WithSign only compiles with DEC |
294 | using DEC = IntegerToString<int8_t, Dec::WithSign>; |
295 | EXPECT(DEC, -1, "-1" ); |
296 | EXPECT(DEC, 0, "+0" ); |
297 | EXPECT(DEC, 1, "+1" ); |
298 | } |
299 | |
300 | TEST(LlvmLibcIntegerToStringTest, BufferOverrun) { |
301 | { // Writing '0' in an empty buffer requiring zero digits : works |
302 | const auto view = |
303 | IntegerToString<int, Dec::WithWidth<0>>::format_to(buffer: span<char>(), value: 0); |
304 | ASSERT_TRUE(view.has_value()); |
305 | ASSERT_EQ(*view, string_view("" )); |
306 | } |
307 | char buffer[1]; |
308 | { // Writing '1' in a buffer of one char : works |
309 | const auto view = IntegerToString<int>::format_to(buffer, value: 1); |
310 | ASSERT_TRUE(view.has_value()); |
311 | ASSERT_EQ(*view, string_view("1" )); |
312 | } |
313 | { // Writing '11' in a buffer of one char : fails |
314 | const auto view = IntegerToString<int>::format_to(buffer, value: 11); |
315 | ASSERT_FALSE(view.has_value()); |
316 | } |
317 | } |
318 | |