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