brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.7 KiB · 3a7da1f Raw
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