1 //===-- Unittests for strtoull --------------------------------------------===//
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/stdlib/strtoull.h"
10
11 #include <errno.h>
12 #include <limits.h>
13 #include <stddef.h>
14
15 #include "utils/UnitTest/Test.h"
16
TEST(LlvmLibcStrToULLTest,InvalidBase)17 TEST(LlvmLibcStrToULLTest, InvalidBase) {
18 const char *ten = "10";
19 errno = 0;
20 ASSERT_EQ(__llvm_libc::strtoull(ten, nullptr, -1), 0ull);
21 ASSERT_EQ(errno, EINVAL);
22 }
23
TEST(LlvmLibcStrToULLTest,CleanBaseTenDecode)24 TEST(LlvmLibcStrToULLTest, CleanBaseTenDecode) {
25 char *str_end = nullptr;
26
27 const char *ten = "10";
28 errno = 0;
29 ASSERT_EQ(__llvm_libc::strtoull(ten, &str_end, 10), 10ull);
30 ASSERT_EQ(errno, 0);
31 EXPECT_EQ(str_end - ten, ptrdiff_t(2));
32 errno = 0;
33 ASSERT_EQ(__llvm_libc::strtoull(ten, nullptr, 10), 10ull);
34 ASSERT_EQ(errno, 0);
35
36 const char *hundred = "100";
37 errno = 0;
38 ASSERT_EQ(__llvm_libc::strtoull(hundred, &str_end, 10), 100ull);
39 ASSERT_EQ(errno, 0);
40 EXPECT_EQ(str_end - hundred, ptrdiff_t(3));
41
42 const char *negative = "-100";
43 errno = 0;
44 ASSERT_EQ(__llvm_libc::strtoull(negative, &str_end, 10), -(100ull));
45 ASSERT_EQ(errno, 0);
46 EXPECT_EQ(str_end - negative, ptrdiff_t(4));
47
48 const char *big_number = "123456789012345";
49 errno = 0;
50 ASSERT_EQ(__llvm_libc::strtoull(big_number, &str_end, 10),
51 123456789012345ull);
52 ASSERT_EQ(errno, 0);
53 EXPECT_EQ(str_end - big_number, ptrdiff_t(15));
54
55 const char *unsigned_long_long_max_number = "18446744073709551615";
56 errno = 0;
57 ASSERT_EQ(__llvm_libc::strtoull(unsigned_long_long_max_number, &str_end, 10),
58 18446744073709551615ull);
59 ASSERT_EQ(errno, 0);
60 EXPECT_EQ(str_end - unsigned_long_long_max_number, ptrdiff_t(20));
61
62 const char *too_big_number = "123456789012345678901";
63 errno = 0;
64 ASSERT_EQ(__llvm_libc::strtoull(too_big_number, &str_end, 10), ULLONG_MAX);
65 ASSERT_EQ(errno, ERANGE);
66 EXPECT_EQ(str_end - too_big_number, ptrdiff_t(21));
67
68 const char *too_big_negative_number = "-123456789012345678901";
69 errno = 0;
70 ASSERT_EQ(__llvm_libc::strtoull(too_big_negative_number, &str_end, 10),
71 ULLONG_MAX);
72 ASSERT_EQ(errno, ERANGE);
73 EXPECT_EQ(str_end - too_big_negative_number, ptrdiff_t(22));
74
75 const char *long_number_range_test =
76 "10000000000000000000000000000000000000000000000000";
77 errno = 0;
78 ASSERT_EQ(__llvm_libc::strtoull(long_number_range_test, &str_end, 10),
79 ULLONG_MAX);
80 ASSERT_EQ(errno, ERANGE);
81 EXPECT_EQ(str_end - long_number_range_test, ptrdiff_t(50));
82 }
83
TEST(LlvmLibcStrToULLTest,MessyBaseTenDecode)84 TEST(LlvmLibcStrToULLTest, MessyBaseTenDecode) {
85 char *str_end = nullptr;
86
87 const char *spaces_before = " 10";
88 errno = 0;
89 ASSERT_EQ(__llvm_libc::strtoull(spaces_before, &str_end, 10), 10ull);
90 ASSERT_EQ(errno, 0);
91 EXPECT_EQ(str_end - spaces_before, ptrdiff_t(7));
92
93 const char *spaces_after = "10 ";
94 errno = 0;
95 ASSERT_EQ(__llvm_libc::strtoull(spaces_after, &str_end, 10), 10ull);
96 ASSERT_EQ(errno, 0);
97 EXPECT_EQ(str_end - spaces_after, ptrdiff_t(2));
98
99 const char *word_before = "word10";
100 errno = 0;
101 ASSERT_EQ(__llvm_libc::strtoull(word_before, &str_end, 10), 0ull);
102 ASSERT_EQ(errno, 0);
103 EXPECT_EQ(str_end - word_before, ptrdiff_t(0));
104
105 const char *word_after = "10word";
106 errno = 0;
107 ASSERT_EQ(__llvm_libc::strtoull(word_after, &str_end, 10), 10ull);
108 ASSERT_EQ(errno, 0);
109 EXPECT_EQ(str_end - word_after, ptrdiff_t(2));
110
111 const char *two_numbers = "10 999";
112 errno = 0;
113 ASSERT_EQ(__llvm_libc::strtoull(two_numbers, &str_end, 10), 10ull);
114 ASSERT_EQ(errno, 0);
115 EXPECT_EQ(str_end - two_numbers, ptrdiff_t(2));
116
117 const char *two_signs = "--10 999";
118 errno = 0;
119 ASSERT_EQ(__llvm_libc::strtoull(two_signs, &str_end, 10), 0ull);
120 ASSERT_EQ(errno, 0);
121 EXPECT_EQ(str_end - two_signs, ptrdiff_t(0));
122
123 const char *sign_before = "+2=4";
124 errno = 0;
125 ASSERT_EQ(__llvm_libc::strtoull(sign_before, &str_end, 10), 2ull);
126 ASSERT_EQ(errno, 0);
127 EXPECT_EQ(str_end - sign_before, ptrdiff_t(2));
128
129 const char *sign_after = "2+2=4";
130 errno = 0;
131 ASSERT_EQ(__llvm_libc::strtoull(sign_after, &str_end, 10), 2ull);
132 ASSERT_EQ(errno, 0);
133 EXPECT_EQ(str_end - sign_after, ptrdiff_t(1));
134
135 const char *tab_before = "\t10";
136 errno = 0;
137 ASSERT_EQ(__llvm_libc::strtoull(tab_before, &str_end, 10), 10ull);
138 ASSERT_EQ(errno, 0);
139 EXPECT_EQ(str_end - tab_before, ptrdiff_t(3));
140
141 const char *all_together = "\t -12345and+67890";
142 errno = 0;
143 ASSERT_EQ(__llvm_libc::strtoull(all_together, &str_end, 10), -(12345ull));
144 ASSERT_EQ(errno, 0);
145 EXPECT_EQ(str_end - all_together, ptrdiff_t(9));
146
147 const char *just_spaces = " ";
148 errno = 0;
149 ASSERT_EQ(__llvm_libc::strtoull(just_spaces, &str_end, 10), 0ull);
150 ASSERT_EQ(errno, 0);
151 EXPECT_EQ(str_end - just_spaces, ptrdiff_t(0));
152
153 const char *just_space_and_sign = " +";
154 errno = 0;
155 ASSERT_EQ(__llvm_libc::strtoull(just_space_and_sign, &str_end, 10), 0ull);
156 ASSERT_EQ(errno, 0);
157 EXPECT_EQ(str_end - just_space_and_sign, ptrdiff_t(0));
158 }
159
int_to_b36_char(int input)160 static char int_to_b36_char(int input) {
161 if (input < 0 || input > 36)
162 return '0';
163 if (input < 10)
164 return static_cast<char>('0' + input);
165 return static_cast<char>('A' + input - 10);
166 }
167
TEST(LlvmLibcStrToULLTest,DecodeInOtherBases)168 TEST(LlvmLibcStrToULLTest, DecodeInOtherBases) {
169 char small_string[4] = {'\0', '\0', '\0', '\0'};
170 for (int base = 2; base <= 36; ++base) {
171 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
172 small_string[0] = int_to_b36_char(first_digit);
173 if (first_digit < base) {
174 errno = 0;
175 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
176 static_cast<unsigned long long int>(first_digit));
177 ASSERT_EQ(errno, 0);
178 } else {
179 errno = 0;
180 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), 0ull);
181 ASSERT_EQ(errno, 0);
182 }
183 }
184 }
185
186 for (int base = 2; base <= 36; ++base) {
187 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
188 small_string[0] = int_to_b36_char(first_digit);
189 for (int second_digit = 0; second_digit <= 36; ++second_digit) {
190 small_string[1] = int_to_b36_char(second_digit);
191 if (first_digit < base && second_digit < base) {
192 errno = 0;
193 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
194 static_cast<unsigned long long int>(second_digit +
195 (first_digit * base)));
196 ASSERT_EQ(errno, 0);
197 } else if (first_digit < base) {
198 errno = 0;
199 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
200 static_cast<unsigned long long int>(first_digit));
201 ASSERT_EQ(errno, 0);
202 } else {
203 errno = 0;
204 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), 0ull);
205 ASSERT_EQ(errno, 0);
206 }
207 }
208 }
209 }
210
211 for (int base = 2; base <= 36; ++base) {
212 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
213 small_string[0] = int_to_b36_char(first_digit);
214 for (int second_digit = 0; second_digit <= 36; ++second_digit) {
215 small_string[1] = int_to_b36_char(second_digit);
216 for (int third_digit = 0; third_digit <= 36; ++third_digit) {
217 small_string[2] = int_to_b36_char(third_digit);
218
219 if (first_digit < base && second_digit < base && third_digit < base) {
220 errno = 0;
221 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
222 static_cast<unsigned long long int>(
223 third_digit + (second_digit * base) +
224 (first_digit * base * base)));
225 ASSERT_EQ(errno, 0);
226 } else if (first_digit < base && second_digit < base) {
227 errno = 0;
228 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
229 static_cast<unsigned long long int>(
230 second_digit + (first_digit * base)));
231 ASSERT_EQ(errno, 0);
232 } else if (first_digit < base) {
233 // if the base is 16 there is a special case for the prefix 0X.
234 // The number is treated as a one digit hexadecimal.
235 if (base == 16 && first_digit == 0 && second_digit == 33) {
236 if (third_digit < base) {
237 errno = 0;
238 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
239 static_cast<unsigned long long int>(third_digit));
240 ASSERT_EQ(errno, 0);
241 } else {
242 errno = 0;
243 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
244 0ull);
245 ASSERT_EQ(errno, 0);
246 }
247 } else {
248 errno = 0;
249 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
250 static_cast<unsigned long long int>(first_digit));
251 ASSERT_EQ(errno, 0);
252 }
253 } else {
254 errno = 0;
255 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), 0ull);
256 ASSERT_EQ(errno, 0);
257 }
258 }
259 }
260 }
261 }
262 }
263
TEST(LlvmLibcStrToULLTest,CleanBaseSixteenDecode)264 TEST(LlvmLibcStrToULLTest, CleanBaseSixteenDecode) {
265 char *str_end = nullptr;
266
267 const char *no_prefix = "123abc";
268 errno = 0;
269 ASSERT_EQ(__llvm_libc::strtoull(no_prefix, &str_end, 16), 0x123abcull);
270 ASSERT_EQ(errno, 0);
271 EXPECT_EQ(str_end - no_prefix, ptrdiff_t(6));
272
273 const char *yes_prefix = "0x456def";
274 errno = 0;
275 ASSERT_EQ(__llvm_libc::strtoull(yes_prefix, &str_end, 16), 0x456defull);
276 ASSERT_EQ(errno, 0);
277 EXPECT_EQ(str_end - yes_prefix, ptrdiff_t(8));
278
279 const char *letter_after_prefix = "0xabc123";
280 errno = 0;
281 ASSERT_EQ(__llvm_libc::strtoull(letter_after_prefix, &str_end, 16),
282 0xabc123ull);
283 ASSERT_EQ(errno, 0);
284 EXPECT_EQ(str_end - letter_after_prefix, ptrdiff_t(8));
285 }
286
TEST(LlvmLibcStrToULLTest,MessyBaseSixteenDecode)287 TEST(LlvmLibcStrToULLTest, MessyBaseSixteenDecode) {
288 char *str_end = nullptr;
289
290 const char *just_prefix = "0x";
291 errno = 0;
292 ASSERT_EQ(__llvm_libc::strtoull(just_prefix, &str_end, 16), 0ull);
293 ASSERT_EQ(errno, 0);
294 EXPECT_EQ(str_end - just_prefix, ptrdiff_t(1));
295
296 errno = 0;
297 ASSERT_EQ(__llvm_libc::strtoull(just_prefix, &str_end, 0), 0ull);
298 ASSERT_EQ(errno, 0);
299 EXPECT_EQ(str_end - just_prefix, ptrdiff_t(1));
300
301 const char *prefix_with_x_after = "0xx";
302 errno = 0;
303 ASSERT_EQ(__llvm_libc::strtoull(prefix_with_x_after, &str_end, 16), 0ull);
304 ASSERT_EQ(errno, 0);
305 EXPECT_EQ(str_end - prefix_with_x_after, ptrdiff_t(1));
306
307 errno = 0;
308 ASSERT_EQ(__llvm_libc::strtoull(prefix_with_x_after, &str_end, 0), 0ull);
309 ASSERT_EQ(errno, 0);
310 EXPECT_EQ(str_end - prefix_with_x_after, ptrdiff_t(1));
311 }
312
TEST(LlvmLibcStrToULLTest,AutomaticBaseSelection)313 TEST(LlvmLibcStrToULLTest, AutomaticBaseSelection) {
314 char *str_end = nullptr;
315
316 const char *base_ten = "12345";
317 errno = 0;
318 ASSERT_EQ(__llvm_libc::strtoull(base_ten, &str_end, 0), 12345ull);
319 ASSERT_EQ(errno, 0);
320 EXPECT_EQ(str_end - base_ten, ptrdiff_t(5));
321
322 const char *base_sixteen_no_prefix = "123abc";
323 errno = 0;
324 ASSERT_EQ(__llvm_libc::strtoull(base_sixteen_no_prefix, &str_end, 0), 123ull);
325 ASSERT_EQ(errno, 0);
326 EXPECT_EQ(str_end - base_sixteen_no_prefix, ptrdiff_t(3));
327
328 const char *base_sixteen_with_prefix = "0x456def";
329 errno = 0;
330 ASSERT_EQ(__llvm_libc::strtoull(base_sixteen_with_prefix, &str_end, 0),
331 0x456defull);
332 ASSERT_EQ(errno, 0);
333 EXPECT_EQ(str_end - base_sixteen_with_prefix, ptrdiff_t(8));
334
335 const char *base_eight_with_prefix = "012345";
336 errno = 0;
337 ASSERT_EQ(__llvm_libc::strtoull(base_eight_with_prefix, &str_end, 0),
338 012345ull);
339 ASSERT_EQ(errno, 0);
340 EXPECT_EQ(str_end - base_eight_with_prefix, ptrdiff_t(6));
341
342 const char *just_zero = "0";
343 errno = 0;
344 ASSERT_EQ(__llvm_libc::strtoull(just_zero, &str_end, 0), 0ull);
345 ASSERT_EQ(errno, 0);
346 EXPECT_EQ(str_end - just_zero, ptrdiff_t(1));
347
348 const char *just_zero_x = "0x";
349 errno = 0;
350 ASSERT_EQ(__llvm_libc::strtoull(just_zero_x, &str_end, 0), 0ull);
351 ASSERT_EQ(errno, 0);
352 EXPECT_EQ(str_end - just_zero_x, ptrdiff_t(1));
353
354 const char *just_zero_eight = "08";
355 errno = 0;
356 ASSERT_EQ(__llvm_libc::strtoull(just_zero_eight, &str_end, 0), 0ull);
357 ASSERT_EQ(errno, 0);
358 EXPECT_EQ(str_end - just_zero_eight, ptrdiff_t(1));
359 }
360