443 lines · c
1//===-- A template class for testing wcsto* 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 "hdr/errno_macros.h"10#include "src/__support/CPP/limits.h"11#include "src/__support/CPP/type_traits.h"12#include "src/__support/macros/properties/architectures.h"13#include "src/__support/wctype_utils.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 WcstoTest : public LIBC_NAMESPACE::testing::ErrnoCheckingTest {23 using FunctionT = ReturnT (*)(const wchar_t *, wchar_t **, 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 wchar_t *ten = L"10";32 ASSERT_EQ(func(ten, nullptr, -1), ReturnT(0));33 ASSERT_ERRNO_EQ(EINVAL);34 }35 36 void CleanBaseTenDecode(FunctionT func) {37 wchar_t *str_end = nullptr;38 39 // TODO: Look into collapsing these repeated segments.40 const wchar_t *ten = L"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 wchar_t *hundred = L"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 wchar_t *big_number = L"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 bits59 // wide, strtol will return LONG_MAX.60 const wchar_t *bigger_number = L"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 wchar_t *too_big_number = L"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 wchar_t *long_number_range_test =76 L"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 as82 // casting a negative variable to an unsigned type.83 const wchar_t *negative = L"-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 wchar_t *big_negative_number = L"-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 wchar_t *too_big_negative_number = L"-123456789012345678901";94 // If the number is signed, it should return the smallest negative number95 // for the current type, but if it's unsigned it should max out and return96 // 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 is99 // 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 wchar_t *str_end = nullptr;109 110 const wchar_t *spaces_before = L" 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 wchar_t *spaces_after = L"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 wchar_t *word_before = L"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 wchar_t *word_after = L"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 wchar_t *two_numbers = L"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 wchar_t *two_signs = L"--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 wchar_t *sign_before = L"+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 wchar_t *sign_after = L"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 wchar_t *tab_before = L"\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 wchar_t *all_together = L"\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 wchar_t *just_spaces = L" ";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 wchar_t *just_space_and_sign = L" +";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#else176 constexpr int limit = 36;177#endif178 wchar_t small_string[4] = {L'\0', L'\0', L'\0', L'\0'};179 for (int base = 2; base <= 36; ++base) {180 for (int first_digit = 0; first_digit <= 36; ++first_digit) {181 small_string[0] =182 LIBC_NAMESPACE::internal::int_to_b36_wchar(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] =197 LIBC_NAMESPACE::internal::int_to_b36_wchar(first_digit);198 for (int second_digit = 0; second_digit <= 36; ++second_digit) {199 small_string[1] =200 LIBC_NAMESPACE::internal::int_to_b36_wchar(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] =221 LIBC_NAMESPACE::internal::int_to_b36_wchar(first_digit);222 for (int second_digit = 0; second_digit <= 36; ++second_digit) {223 small_string[1] =224 LIBC_NAMESPACE::internal::int_to_b36_wchar(second_digit);225 for (int third_digit = 0; third_digit <= limit; ++third_digit) {226 small_string[2] =227 LIBC_NAMESPACE::internal::int_to_b36_wchar(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 wchar_t *str_end = nullptr;270 271 const wchar_t *no_prefix = L"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 wchar_t *yes_prefix = L"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 wchar_t *letter_after_prefix = L"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 max287 // value for the conversion.288 289 // Max size for unsigned 32 bit numbers290 291 const wchar_t *max_32_bit_value = L"0xFFFFFFFF";292 ASSERT_EQ(func(max_32_bit_value, &str_end, 0),293 ((is_signed_v<ReturnT> && sizeof(ReturnT) == 4)294 ? T_MAX295 : 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 wchar_t *negative_max_32_bit_value = L"-0xFFFFFFFF";300 ASSERT_EQ(func(negative_max_32_bit_value, &str_end, 0),301 ((is_signed_v<ReturnT> && sizeof(ReturnT) == 4)302 ? T_MIN303 : -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 numbers308 309 const wchar_t *max_31_bit_value = L"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 wchar_t *negative_max_31_bit_value = L"-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 numbers321 322 const wchar_t *max_64_bit_value = L"0xFFFFFFFFFFFFFFFF";323 ASSERT_EQ(func(max_64_bit_value, &str_end, 0),324 (is_signed_v<ReturnT> || sizeof(ReturnT) < 8325 ? T_MAX326 : 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 large331 // negative number can end up as T_MAX.332 const wchar_t *negative_max_64_bit_value = L"-0xFFFFFFFFFFFFFFFF";333 ASSERT_EQ(334 func(negative_max_64_bit_value, &str_end, 0),335 (is_signed_v<ReturnT>336 ? T_MIN337 : (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 numbers342 343 const wchar_t *max_63_bit_value = L"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 wchar_t *negative_max_63_bit_value = L"-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 wchar_t *str_end = nullptr;359 360 const wchar_t *just_prefix = L"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 wchar_t *prefix_with_x_after = L"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 wchar_t *str_end = nullptr;381 382 const wchar_t *base_ten = L"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 wchar_t *base_sixteen_no_prefix = L"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 wchar_t *base_sixteen_with_prefix = L"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 wchar_t *base_eight_with_prefix = L"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 wchar_t *just_zero = L"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 wchar_t *just_zero_x = L"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 wchar_t *just_zero_eight = L"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>420WcstoTest(ReturnType (*)(const wchar_t *)) -> WcstoTest<ReturnType>;421 422#define WCSTOL_TEST(name, func) \423 using LlvmLibc##name##Test = WcstoTest<decltype(func(L"", 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