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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "src/__support/CPP/limits.h"
10#include "src/__support/CPP/type_traits.h"
11#include "src/__support/macros/properties/architectures.h"
12#include "src/__support/wctype_utils.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 WcstoTest : public LIBC_NAMESPACE::testing::ErrnoCheckingTest {
22 using FunctionT = ReturnT (*)(const wchar_t *, wchar_t **, 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 wchar_t *ten = L"10";
31 ASSERT_EQ(func(ten, nullptr, -1), ReturnT(0));
32 ASSERT_ERRNO_EQ(EINVAL);
33 }
34
35 void CleanBaseTenDecode(FunctionT func) {
36 wchar_t *str_end = nullptr;
37
38 // TODO: Look into collapsing these repeated segments.
39 const wchar_t *ten = L"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 wchar_t *hundred = L"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 wchar_t *big_number = L"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 bits
58 // wide, strtol will return LONG_MAX.
59 const wchar_t *bigger_number = L"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 wchar_t *too_big_number = L"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 wchar_t *long_number_range_test =
75 L"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 as
81 // casting a negative variable to an unsigned type.
82 const wchar_t *negative = L"-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 wchar_t *big_negative_number = L"-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 wchar_t *too_big_negative_number = L"-123456789012345678901";
93 // If the number is signed, it should return the smallest negative number
94 // for the current type, but if it's unsigned it should max out and return
95 // 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 is
98 // 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 wchar_t *str_end = nullptr;
108
109 const wchar_t *spaces_before = L" 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 wchar_t *spaces_after = L"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 wchar_t *word_before = L"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 wchar_t *word_after = L"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 wchar_t *two_numbers = L"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 wchar_t *two_signs = L"--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 wchar_t *sign_before = L"+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 wchar_t *sign_after = L"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 wchar_t *tab_before = L"\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 wchar_t *all_together = L"\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 wchar_t *just_spaces = L" ";
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 wchar_t *just_space_and_sign = L" +";
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#else
175 constexpr int limit = 36;
176#endif
177 wchar_t small_string[4] = {L'\0', L'\0', L'\0', L'\0'};
178 for (int base = 2; base <= 36; ++base) {
179 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
180 small_string[0] = static_cast<wchar_t>(
181 LIBC_NAMESPACE::internal::int_to_b36_wchar(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] = static_cast<wchar_t>(
196 LIBC_NAMESPACE::internal::int_to_b36_wchar(first_digit));
197 for (int second_digit = 0; second_digit <= 36; ++second_digit) {
198 small_string[1] = static_cast<wchar_t>(
199 LIBC_NAMESPACE::internal::int_to_b36_wchar(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] = static_cast<wchar_t>(
220 LIBC_NAMESPACE::internal::int_to_b36_wchar(first_digit));
221 for (int second_digit = 0; second_digit <= 36; ++second_digit) {
222 small_string[1] = static_cast<wchar_t>(
223 LIBC_NAMESPACE::internal::int_to_b36_wchar(second_digit));
224 for (int third_digit = 0; third_digit <= limit; ++third_digit) {
225 small_string[2] = static_cast<wchar_t>(
226 LIBC_NAMESPACE::internal::int_to_b36_wchar(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 wchar_t *str_end = nullptr;
269
270 const wchar_t *no_prefix = L"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 wchar_t *yes_prefix = L"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 wchar_t *letter_after_prefix = L"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 max
286 // value for the conversion.
287
288 // Max size for unsigned 32 bit numbers
289
290 const wchar_t *max_32_bit_value = L"0xFFFFFFFF";
291 ASSERT_EQ(func(max_32_bit_value, &str_end, 0),
292 ((is_signed_v<ReturnT> && sizeof(ReturnT) == 4)
293 ? T_MAX
294 : 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 wchar_t *negative_max_32_bit_value = L"-0xFFFFFFFF";
299 ASSERT_EQ(func(negative_max_32_bit_value, &str_end, 0),
300 ((is_signed_v<ReturnT> && sizeof(ReturnT) == 4)
301 ? T_MIN
302 : -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 numbers
307
308 const wchar_t *max_31_bit_value = L"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 wchar_t *negative_max_31_bit_value = L"-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 numbers
320
321 const wchar_t *max_64_bit_value = L"0xFFFFFFFFFFFFFFFF";
322 ASSERT_EQ(func(max_64_bit_value, &str_end, 0),
323 (is_signed_v<ReturnT> || sizeof(ReturnT) < 8
324 ? T_MAX
325 : 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 large
330 // negative number can end up as T_MAX.
331 const wchar_t *negative_max_64_bit_value = L"-0xFFFFFFFFFFFFFFFF";
332 ASSERT_EQ(
333 func(negative_max_64_bit_value, &str_end, 0),
334 (is_signed_v<ReturnT>
335 ? T_MIN
336 : (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 numbers
341
342 const wchar_t *max_63_bit_value = L"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 wchar_t *negative_max_63_bit_value = L"-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 wchar_t *str_end = nullptr;
358
359 const wchar_t *just_prefix = L"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 wchar_t *prefix_with_x_after = L"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 wchar_t *str_end = nullptr;
380
381 const wchar_t *base_ten = L"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 wchar_t *base_sixteen_no_prefix = L"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 wchar_t *base_sixteen_with_prefix = L"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 wchar_t *base_eight_with_prefix = L"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 wchar_t *just_zero = L"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 wchar_t *just_zero_x = L"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 wchar_t *just_zero_eight = L"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>
419WcstoTest(ReturnType (*)(const wchar_t *)) -> WcstoTest<ReturnType>;
420
421#define WCSTOL_TEST(name, func) \
422 using LlvmLibc##name##Test = WcstoTest<decltype(func(L"", 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

source code of libc/test/src/wchar/WcstolTest.h