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