1//===-- A template class for testing strto* functions -----------*- C++ -*-===//
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/type_traits.h"
11#include "src/__support/ctype_utils.h"
12#include "src/__support/libc_errno.h"
13#include "src/__support/macros/properties/architectures.h"
14#include "test/UnitTest/ErrnoCheckingTest.h"
15#include "test/UnitTest/Test.h"
16
17#include <stddef.h>
18
19using LIBC_NAMESPACE::cpp::is_signed_v;
20
21template <typename ReturnT>
22struct StrtoTest : public LIBC_NAMESPACE::testing::ErrnoCheckingTest {
23 using FunctionT = ReturnT (*)(const char *, char **, int);
24
25 static constexpr ReturnT T_MAX =
26 LIBC_NAMESPACE::cpp::numeric_limits<ReturnT>::max();
27 static constexpr ReturnT T_MIN =
28 LIBC_NAMESPACE::cpp::numeric_limits<ReturnT>::min();
29
30 void InvalidBase(FunctionT func) {
31 const char *ten = "10";
32 ASSERT_EQ(func(ten, nullptr, -1), ReturnT(0));
33 ASSERT_ERRNO_EQ(EINVAL);
34 }
35
36 void CleanBaseTenDecode(FunctionT func) {
37 char *str_end = nullptr;
38
39 // TODO: Look into collapsing these repeated segments.
40 const char *ten = "10";
41 ASSERT_EQ(func(ten, &str_end, 10), ReturnT(10));
42 ASSERT_ERRNO_SUCCESS();
43 EXPECT_EQ(str_end - ten, ptrdiff_t(2));
44
45 ASSERT_EQ(func(ten, nullptr, 10), ReturnT(10));
46 ASSERT_ERRNO_SUCCESS();
47
48 const char *hundred = "100";
49 ASSERT_EQ(func(hundred, &str_end, 10), ReturnT(100));
50 ASSERT_ERRNO_SUCCESS();
51 EXPECT_EQ(str_end - hundred, ptrdiff_t(3));
52
53 const char *big_number = "1234567890";
54 ASSERT_EQ(func(big_number, &str_end, 10), ReturnT(1234567890));
55 ASSERT_ERRNO_SUCCESS();
56 EXPECT_EQ(str_end - big_number, ptrdiff_t(10));
57
58 // This number is larger than 2^32, meaning that if long is only 32 bits
59 // wide, strtol will return LONG_MAX.
60 const char *bigger_number = "12345678900";
61 if constexpr (sizeof(ReturnT) < 8) {
62 ASSERT_EQ(func(bigger_number, &str_end, 10), T_MAX);
63 ASSERT_ERRNO_EQ(ERANGE);
64 } else {
65 ASSERT_EQ(func(bigger_number, &str_end, 10), ReturnT(12345678900));
66 ASSERT_ERRNO_SUCCESS();
67 }
68 EXPECT_EQ(str_end - bigger_number, ptrdiff_t(11));
69
70 const char *too_big_number = "123456789012345678901";
71 ASSERT_EQ(func(too_big_number, &str_end, 10), T_MAX);
72 ASSERT_ERRNO_EQ(ERANGE);
73 EXPECT_EQ(str_end - too_big_number, ptrdiff_t(21));
74
75 const char *long_number_range_test =
76 "10000000000000000000000000000000000000000000000000";
77 ASSERT_EQ(func(long_number_range_test, &str_end, 10), T_MAX);
78 ASSERT_ERRNO_EQ(ERANGE);
79 EXPECT_EQ(str_end - long_number_range_test, ptrdiff_t(50));
80
81 // For most negative numbers, the unsigned functions treat it the same as
82 // casting a negative variable to an unsigned type.
83 const char *negative = "-100";
84 ASSERT_EQ(func(negative, &str_end, 10), ReturnT(-100));
85 ASSERT_ERRNO_SUCCESS();
86 EXPECT_EQ(str_end - negative, ptrdiff_t(4));
87
88 const char *big_negative_number = "-1234567890";
89 ASSERT_EQ(func(big_negative_number, &str_end, 10), ReturnT(-1234567890));
90 ASSERT_ERRNO_SUCCESS();
91 EXPECT_EQ(str_end - big_negative_number, ptrdiff_t(11));
92
93 const char *too_big_negative_number = "-123456789012345678901";
94 // If the number is signed, it should return the smallest negative number
95 // for the current type, but if it's unsigned it should max out and return
96 // the largest positive number for the current type. From the standard:
97 // "If the correct value is outside the range of representable values,
98 // LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, or ULLONG_MAX is
99 // returned"
100 // Note that 0 is not on that list.
101 ASSERT_EQ(func(too_big_negative_number, &str_end, 10),
102 (is_signed_v<ReturnT> ? T_MIN : T_MAX));
103 ASSERT_ERRNO_EQ(ERANGE);
104 EXPECT_EQ(str_end - too_big_negative_number, ptrdiff_t(22));
105 }
106
107 void MessyBaseTenDecode(FunctionT func) {
108 char *str_end = nullptr;
109
110 const char *spaces_before = " 10";
111 ASSERT_EQ(func(spaces_before, &str_end, 10), ReturnT(10));
112 ASSERT_ERRNO_SUCCESS();
113 EXPECT_EQ(str_end - spaces_before, ptrdiff_t(7));
114
115 const char *spaces_after = "10 ";
116 ASSERT_EQ(func(spaces_after, &str_end, 10), ReturnT(10));
117 ASSERT_ERRNO_SUCCESS();
118 EXPECT_EQ(str_end - spaces_after, ptrdiff_t(2));
119
120 const char *word_before = "word10";
121 ASSERT_EQ(func(word_before, &str_end, 10), ReturnT(0));
122 ASSERT_ERRNO_SUCCESS();
123 EXPECT_EQ(str_end - word_before, ptrdiff_t(0));
124
125 const char *word_after = "10word";
126 ASSERT_EQ(func(word_after, &str_end, 10), ReturnT(10));
127 ASSERT_ERRNO_SUCCESS();
128 EXPECT_EQ(str_end - word_after, ptrdiff_t(2));
129
130 const char *two_numbers = "10 999";
131 ASSERT_EQ(func(two_numbers, &str_end, 10), ReturnT(10));
132 ASSERT_ERRNO_SUCCESS();
133 EXPECT_EQ(str_end - two_numbers, ptrdiff_t(2));
134
135 const char *two_signs = "--10 999";
136 ASSERT_EQ(func(two_signs, &str_end, 10), ReturnT(0));
137 ASSERT_ERRNO_SUCCESS();
138 EXPECT_EQ(str_end - two_signs, ptrdiff_t(0));
139
140 const char *sign_before = "+2=4";
141 ASSERT_EQ(func(sign_before, &str_end, 10), ReturnT(2));
142 ASSERT_ERRNO_SUCCESS();
143 EXPECT_EQ(str_end - sign_before, ptrdiff_t(2));
144
145 const char *sign_after = "2+2=4";
146 ASSERT_EQ(func(sign_after, &str_end, 10), ReturnT(2));
147 ASSERT_ERRNO_SUCCESS();
148 EXPECT_EQ(str_end - sign_after, ptrdiff_t(1));
149
150 const char *tab_before = "\t10";
151 ASSERT_EQ(func(tab_before, &str_end, 10), ReturnT(10));
152 ASSERT_ERRNO_SUCCESS();
153 EXPECT_EQ(str_end - tab_before, ptrdiff_t(3));
154
155 const char *all_together = "\t -12345and+67890";
156 ASSERT_EQ(func(all_together, &str_end, 10), ReturnT(-12345));
157 ASSERT_ERRNO_SUCCESS();
158 EXPECT_EQ(str_end - all_together, ptrdiff_t(9));
159
160 const char *just_spaces = " ";
161 ASSERT_EQ(func(just_spaces, &str_end, 10), ReturnT(0));
162 ASSERT_ERRNO_SUCCESS();
163 EXPECT_EQ(str_end - just_spaces, ptrdiff_t(0));
164
165 const char *just_space_and_sign = " +";
166 ASSERT_EQ(func(just_space_and_sign, &str_end, 10), ReturnT(0));
167 ASSERT_ERRNO_SUCCESS();
168 EXPECT_EQ(str_end - just_space_and_sign, ptrdiff_t(0));
169 }
170
171 void DecodeInOtherBases(FunctionT func) {
172 // This test is excessively slow on the GPU, so we limit the innermost loop.
173#if defined(LIBC_TARGET_ARCH_IS_GPU)
174 constexpr int limit = 0;
175#else
176 constexpr int limit = 36;
177#endif
178 char small_string[4] = {'\0', '\0', '\0', '\0'};
179 for (int base = 2; base <= 36; ++base) {
180 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
181 small_string[0] = static_cast<char>(
182 LIBC_NAMESPACE::internal::int_to_b36_char(first_digit));
183 if (first_digit < base) {
184 ASSERT_EQ(func(small_string, nullptr, base),
185 static_cast<ReturnT>(first_digit));
186 ASSERT_ERRNO_SUCCESS();
187 } else {
188 ASSERT_EQ(func(small_string, nullptr, base), ReturnT(0));
189 ASSERT_ERRNO_SUCCESS();
190 }
191 }
192 }
193
194 for (int base = 2; base <= 36; ++base) {
195 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
196 small_string[0] = static_cast<char>(
197 LIBC_NAMESPACE::internal::int_to_b36_char(first_digit));
198 for (int second_digit = 0; second_digit <= 36; ++second_digit) {
199 small_string[1] = static_cast<char>(
200 LIBC_NAMESPACE::internal::int_to_b36_char(second_digit));
201 if (first_digit < base && second_digit < base) {
202 ASSERT_EQ(
203 func(small_string, nullptr, base),
204 static_cast<ReturnT>(second_digit + (first_digit * base)));
205 ASSERT_ERRNO_SUCCESS();
206 } else if (first_digit < base) {
207 ASSERT_EQ(func(small_string, nullptr, base),
208 static_cast<ReturnT>(first_digit));
209 ASSERT_ERRNO_SUCCESS();
210 } else {
211 ASSERT_EQ(func(small_string, nullptr, base), ReturnT(0));
212 ASSERT_ERRNO_SUCCESS();
213 }
214 }
215 }
216 }
217
218 for (int base = 2; base <= 36; ++base) {
219 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
220 small_string[0] = static_cast<char>(
221 LIBC_NAMESPACE::internal::int_to_b36_char(first_digit));
222 for (int second_digit = 0; second_digit <= 36; ++second_digit) {
223 small_string[1] = static_cast<char>(
224 LIBC_NAMESPACE::internal::int_to_b36_char(second_digit));
225 for (int third_digit = 0; third_digit <= limit; ++third_digit) {
226 small_string[2] = static_cast<char>(
227 LIBC_NAMESPACE::internal::int_to_b36_char(third_digit));
228
229 if (first_digit < base && second_digit < base &&
230 third_digit < base) {
231 ASSERT_EQ(func(small_string, nullptr, base),
232 static_cast<ReturnT>(third_digit +
233 (second_digit * base) +
234 (first_digit * base * base)));
235 ASSERT_ERRNO_SUCCESS();
236 } else if (first_digit < base && second_digit < base) {
237 ASSERT_EQ(
238 func(small_string, nullptr, base),
239 static_cast<ReturnT>(second_digit + (first_digit * base)));
240 ASSERT_ERRNO_SUCCESS();
241 } else if (first_digit < base) {
242 // if the base is 16 there is a special case for the prefix 0X.
243 // The number is treated as a one digit hexadecimal.
244 if (base == 16 && first_digit == 0 && second_digit == 33) {
245 if (third_digit < base) {
246 ASSERT_EQ(func(small_string, nullptr, base),
247 static_cast<ReturnT>(third_digit));
248 ASSERT_ERRNO_SUCCESS();
249 } else {
250 ASSERT_EQ(func(small_string, nullptr, base), ReturnT(0));
251 ASSERT_ERRNO_SUCCESS();
252 }
253 } else {
254 ASSERT_EQ(func(small_string, nullptr, base),
255 static_cast<ReturnT>(first_digit));
256 ASSERT_ERRNO_SUCCESS();
257 }
258 } else {
259 ASSERT_EQ(func(small_string, nullptr, base), ReturnT(0));
260 ASSERT_ERRNO_SUCCESS();
261 }
262 }
263 }
264 }
265 }
266 }
267
268 void CleanBaseSixteenDecode(FunctionT func) {
269 char *str_end = nullptr;
270
271 const char *no_prefix = "123abc";
272 ASSERT_EQ(func(no_prefix, &str_end, 16), ReturnT(0x123abc));
273 ASSERT_ERRNO_SUCCESS();
274 EXPECT_EQ(str_end - no_prefix, ptrdiff_t(6));
275
276 const char *yes_prefix = "0x456def";
277 ASSERT_EQ(func(yes_prefix, &str_end, 16), ReturnT(0x456def));
278 ASSERT_ERRNO_SUCCESS();
279 EXPECT_EQ(str_end - yes_prefix, ptrdiff_t(8));
280
281 const char *letter_after_prefix = "0xabc123";
282 ASSERT_EQ(func(letter_after_prefix, &str_end, 16), ReturnT(0xabc123));
283 ASSERT_ERRNO_SUCCESS();
284 EXPECT_EQ(str_end - letter_after_prefix, ptrdiff_t(8));
285
286 // These tests check what happens when the number passed is exactly the max
287 // value for the conversion.
288
289 // Max size for unsigned 32 bit numbers
290
291 const char *max_32_bit_value = "0xFFFFFFFF";
292 ASSERT_EQ(func(max_32_bit_value, &str_end, 0),
293 ((is_signed_v<ReturnT> && sizeof(ReturnT) == 4)
294 ? T_MAX
295 : ReturnT(0xFFFFFFFF)));
296 ASSERT_ERRNO_EQ(is_signed_v<ReturnT> && sizeof(ReturnT) == 4 ? ERANGE : 0);
297 EXPECT_EQ(str_end - max_32_bit_value, ptrdiff_t(10));
298
299 const char *negative_max_32_bit_value = "-0xFFFFFFFF";
300 ASSERT_EQ(func(negative_max_32_bit_value, &str_end, 0),
301 ((is_signed_v<ReturnT> && sizeof(ReturnT) == 4)
302 ? T_MIN
303 : -ReturnT(0xFFFFFFFF)));
304 ASSERT_ERRNO_EQ(is_signed_v<ReturnT> && sizeof(ReturnT) == 4 ? ERANGE : 0);
305 EXPECT_EQ(str_end - negative_max_32_bit_value, ptrdiff_t(11));
306
307 // Max size for signed 32 bit numbers
308
309 const char *max_31_bit_value = "0x7FFFFFFF";
310 ASSERT_EQ(func(max_31_bit_value, &str_end, 0), ReturnT(0x7FFFFFFF));
311 ASSERT_ERRNO_SUCCESS();
312 EXPECT_EQ(str_end - max_31_bit_value, ptrdiff_t(10));
313
314 const char *negative_max_31_bit_value = "-0x7FFFFFFF";
315 ASSERT_EQ(func(negative_max_31_bit_value, &str_end, 0),
316 -ReturnT(0x7FFFFFFF));
317 ASSERT_ERRNO_SUCCESS();
318 EXPECT_EQ(str_end - negative_max_31_bit_value, ptrdiff_t(11));
319
320 // Max size for unsigned 64 bit numbers
321
322 const char *max_64_bit_value = "0xFFFFFFFFFFFFFFFF";
323 ASSERT_EQ(func(max_64_bit_value, &str_end, 0),
324 (is_signed_v<ReturnT> || sizeof(ReturnT) < 8
325 ? T_MAX
326 : ReturnT(0xFFFFFFFFFFFFFFFF)));
327 ASSERT_ERRNO_EQ((is_signed_v<ReturnT> || sizeof(ReturnT) < 8 ? ERANGE : 0));
328 EXPECT_EQ(str_end - max_64_bit_value, ptrdiff_t(18));
329
330 // See the end of CleanBase10Decode for an explanation of how this large
331 // negative number can end up as T_MAX.
332 const char *negative_max_64_bit_value = "-0xFFFFFFFFFFFFFFFF";
333 ASSERT_EQ(
334 func(negative_max_64_bit_value, &str_end, 0),
335 (is_signed_v<ReturnT>
336 ? T_MIN
337 : (sizeof(ReturnT) < 8 ? T_MAX : -ReturnT(0xFFFFFFFFFFFFFFFF))));
338 ASSERT_ERRNO_EQ((is_signed_v<ReturnT> || sizeof(ReturnT) < 8 ? ERANGE : 0));
339 EXPECT_EQ(str_end - negative_max_64_bit_value, ptrdiff_t(19));
340
341 // Max size for signed 64 bit numbers
342
343 const char *max_63_bit_value = "0x7FFFFFFFFFFFFFFF";
344 ASSERT_EQ(func(max_63_bit_value, &str_end, 0),
345 (sizeof(ReturnT) < 8 ? T_MAX : ReturnT(0x7FFFFFFFFFFFFFFF)));
346 ASSERT_ERRNO_EQ(sizeof(ReturnT) < 8 ? ERANGE : 0);
347 EXPECT_EQ(str_end - max_63_bit_value, ptrdiff_t(18));
348
349 const char *negative_max_63_bit_value = "-0x7FFFFFFFFFFFFFFF";
350 ASSERT_EQ(func(negative_max_63_bit_value, &str_end, 0),
351 (sizeof(ReturnT) >= 8 ? -ReturnT(0x7FFFFFFFFFFFFFFF)
352 : (is_signed_v<ReturnT> ? T_MIN : T_MAX)));
353 ASSERT_ERRNO_EQ(sizeof(ReturnT) < 8 ? ERANGE : 0);
354 EXPECT_EQ(str_end - negative_max_63_bit_value, ptrdiff_t(19));
355 }
356
357 void MessyBaseSixteenDecode(FunctionT func) {
358 char *str_end = nullptr;
359
360 const char *just_prefix = "0x";
361 ASSERT_EQ(func(just_prefix, &str_end, 16), ReturnT(0));
362 ASSERT_ERRNO_SUCCESS();
363 EXPECT_EQ(str_end - just_prefix, ptrdiff_t(1));
364
365 ASSERT_EQ(func(just_prefix, &str_end, 0), ReturnT(0));
366 ASSERT_ERRNO_SUCCESS();
367 EXPECT_EQ(str_end - just_prefix, ptrdiff_t(1));
368
369 const char *prefix_with_x_after = "0xx";
370 ASSERT_EQ(func(prefix_with_x_after, &str_end, 16), ReturnT(0));
371 ASSERT_ERRNO_SUCCESS();
372 EXPECT_EQ(str_end - prefix_with_x_after, ptrdiff_t(1));
373
374 ASSERT_EQ(func(prefix_with_x_after, &str_end, 0), ReturnT(0));
375 ASSERT_ERRNO_SUCCESS();
376 EXPECT_EQ(str_end - prefix_with_x_after, ptrdiff_t(1));
377 }
378
379 void AutomaticBaseSelection(FunctionT func) {
380 char *str_end = nullptr;
381
382 const char *base_ten = "12345";
383 ASSERT_EQ(func(base_ten, &str_end, 0), ReturnT(12345));
384 ASSERT_ERRNO_SUCCESS();
385 EXPECT_EQ(str_end - base_ten, ptrdiff_t(5));
386
387 const char *base_sixteen_no_prefix = "123abc";
388 ASSERT_EQ(func(base_sixteen_no_prefix, &str_end, 0), ReturnT(123));
389 ASSERT_ERRNO_SUCCESS();
390 EXPECT_EQ(str_end - base_sixteen_no_prefix, ptrdiff_t(3));
391
392 const char *base_sixteen_with_prefix = "0x456def";
393 ASSERT_EQ(func(base_sixteen_with_prefix, &str_end, 0), ReturnT(0x456def));
394 ASSERT_ERRNO_SUCCESS();
395 EXPECT_EQ(str_end - base_sixteen_with_prefix, ptrdiff_t(8));
396
397 const char *base_eight_with_prefix = "012345";
398 ASSERT_EQ(func(base_eight_with_prefix, &str_end, 0), ReturnT(012345));
399 ASSERT_ERRNO_SUCCESS();
400 EXPECT_EQ(str_end - base_eight_with_prefix, ptrdiff_t(6));
401
402 const char *just_zero = "0";
403 ASSERT_EQ(func(just_zero, &str_end, 0), ReturnT(0));
404 ASSERT_ERRNO_SUCCESS();
405 EXPECT_EQ(str_end - just_zero, ptrdiff_t(1));
406
407 const char *just_zero_x = "0x";
408 ASSERT_EQ(func(just_zero_x, &str_end, 0), ReturnT(0));
409 ASSERT_ERRNO_SUCCESS();
410 EXPECT_EQ(str_end - just_zero_x, ptrdiff_t(1));
411
412 const char *just_zero_eight = "08";
413 ASSERT_EQ(func(just_zero_eight, &str_end, 0), ReturnT(0));
414 ASSERT_ERRNO_SUCCESS();
415 EXPECT_EQ(str_end - just_zero_eight, ptrdiff_t(1));
416 }
417};
418
419template <typename ReturnType>
420StrtoTest(ReturnType (*)(const char *)) -> StrtoTest<ReturnType>;
421
422#define STRTOL_TEST(name, func) \
423 using LlvmLibc##name##Test = StrtoTest<decltype(func("", nullptr, 0))>; \
424 TEST_F(LlvmLibc##name##Test, InvalidBase) { InvalidBase(func); } \
425 TEST_F(LlvmLibc##name##Test, CleanBaseTenDecode) { \
426 CleanBaseTenDecode(func); \
427 } \
428 TEST_F(LlvmLibc##name##Test, MessyBaseTenDecode) { \
429 MessyBaseTenDecode(func); \
430 } \
431 TEST_F(LlvmLibc##name##Test, DecodeInOtherBases) { \
432 DecodeInOtherBases(func); \
433 } \
434 TEST_F(LlvmLibc##name##Test, CleanBaseSixteenDecode) { \
435 CleanBaseSixteenDecode(func); \
436 } \
437 TEST_F(LlvmLibc##name##Test, MessyBaseSixteenDecode) { \
438 MessyBaseSixteenDecode(func); \
439 } \
440 TEST_F(LlvmLibc##name##Test, AutomaticBaseSelection) { \
441 AutomaticBaseSelection(func); \
442 }
443

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of libc/test/src/stdlib/StrtolTest.h