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