1 //===-- Unittests for strtoul ---------------------------------------------===// 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/stdlib/strtoul.h" 10 11 #include "utils/UnitTest/Test.h" 12 13 #include <errno.h> 14 #include <limits.h> 15 16 TEST(LlvmLibcStrToULTest, InvalidBase) { 17 const char *ten = "10"; 18 errno = 0; 19 ASSERT_EQ(__llvm_libc::strtoul(ten, nullptr, -1), 0ul); 20 ASSERT_EQ(errno, EINVAL); 21 } 22 23 TEST(LlvmLibcStrToULTest, CleanBaseTenDecode) { 24 char *str_end = nullptr; 25 26 const char *ten = "10"; 27 errno = 0; 28 ASSERT_EQ(__llvm_libc::strtoul(ten, &str_end, 10), 10ul); 29 ASSERT_EQ(errno, 0); 30 EXPECT_EQ(str_end - ten, 2l); 31 errno = 0; 32 ASSERT_EQ(__llvm_libc::strtoul(ten, nullptr, 10), 10ul); 33 ASSERT_EQ(errno, 0); 34 35 const char *hundred = "100"; 36 errno = 0; 37 ASSERT_EQ(__llvm_libc::strtoul(hundred, &str_end, 10), 100ul); 38 ASSERT_EQ(errno, 0); 39 EXPECT_EQ(str_end - hundred, 3l); 40 41 const char *negative = "-100"; 42 errno = 0; 43 ASSERT_EQ(__llvm_libc::strtoul(negative, &str_end, 10), -(100ul)); 44 ASSERT_EQ(errno, 0); 45 EXPECT_EQ(str_end - negative, 4l); 46 47 const char *big_number = "123456789012345"; 48 errno = 0; 49 ASSERT_EQ(__llvm_libc::strtoul(big_number, &str_end, 10), 123456789012345ul); 50 ASSERT_EQ(errno, 0); 51 EXPECT_EQ(str_end - big_number, 15l); 52 53 const char *too_big_number = "123456789012345678901"; 54 errno = 0; 55 ASSERT_EQ(__llvm_libc::strtoul(too_big_number, &str_end, 10), ULONG_MAX); 56 ASSERT_EQ(errno, ERANGE); 57 EXPECT_EQ(str_end - too_big_number, 21l); 58 59 const char *too_big_negative_number = "-123456789012345678901"; 60 errno = 0; 61 ASSERT_EQ(__llvm_libc::strtoul(too_big_negative_number, &str_end, 10), 62 ULONG_MAX); 63 ASSERT_EQ(errno, ERANGE); 64 EXPECT_EQ(str_end - too_big_negative_number, 22l); 65 66 const char *long_number_range_test = 67 "10000000000000000000000000000000000000000000000000"; 68 errno = 0; 69 ASSERT_EQ(__llvm_libc::strtoul(long_number_range_test, &str_end, 10), 70 ULONG_MAX); 71 ASSERT_EQ(errno, ERANGE); 72 EXPECT_EQ(str_end - long_number_range_test, 50l); 73 } 74 75 TEST(LlvmLibcStrToULTest, MessyBaseTenDecode) { 76 char *str_end = nullptr; 77 78 const char *spaces_before = " 10"; 79 errno = 0; 80 ASSERT_EQ(__llvm_libc::strtoul(spaces_before, &str_end, 10), 10ul); 81 ASSERT_EQ(errno, 0); 82 EXPECT_EQ(str_end - spaces_before, 7l); 83 84 const char *spaces_after = "10 "; 85 errno = 0; 86 ASSERT_EQ(__llvm_libc::strtoul(spaces_after, &str_end, 10), 10ul); 87 ASSERT_EQ(errno, 0); 88 EXPECT_EQ(str_end - spaces_after, 2l); 89 90 const char *word_before = "word10"; 91 errno = 0; 92 ASSERT_EQ(__llvm_libc::strtoul(word_before, &str_end, 10), 0ul); 93 ASSERT_EQ(errno, 0); 94 EXPECT_EQ(str_end - word_before, 0l); 95 96 const char *word_after = "10word"; 97 errno = 0; 98 ASSERT_EQ(__llvm_libc::strtoul(word_after, &str_end, 10), 10ul); 99 ASSERT_EQ(errno, 0); 100 EXPECT_EQ(str_end - word_after, 2l); 101 102 const char *two_numbers = "10 999"; 103 errno = 0; 104 ASSERT_EQ(__llvm_libc::strtoul(two_numbers, &str_end, 10), 10ul); 105 ASSERT_EQ(errno, 0); 106 EXPECT_EQ(str_end - two_numbers, 2l); 107 108 const char *two_signs = "--10 999"; 109 errno = 0; 110 ASSERT_EQ(__llvm_libc::strtoul(two_signs, &str_end, 10), 0ul); 111 ASSERT_EQ(errno, 0); 112 EXPECT_EQ(str_end - two_signs, 1l); 113 114 const char *sign_before = "+2=4"; 115 errno = 0; 116 ASSERT_EQ(__llvm_libc::strtoul(sign_before, &str_end, 10), 2ul); 117 ASSERT_EQ(errno, 0); 118 EXPECT_EQ(str_end - sign_before, 2l); 119 120 const char *sign_after = "2+2=4"; 121 errno = 0; 122 ASSERT_EQ(__llvm_libc::strtoul(sign_after, &str_end, 10), 2ul); 123 ASSERT_EQ(errno, 0); 124 EXPECT_EQ(str_end - sign_after, 1l); 125 126 const char *tab_before = "\t10"; 127 errno = 0; 128 ASSERT_EQ(__llvm_libc::strtoul(tab_before, &str_end, 10), 10ul); 129 ASSERT_EQ(errno, 0); 130 EXPECT_EQ(str_end - tab_before, 3l); 131 132 const char *all_together = "\t -12345and+67890"; 133 errno = 0; 134 ASSERT_EQ(__llvm_libc::strtoul(all_together, &str_end, 10), -(12345ul)); 135 ASSERT_EQ(errno, 0); 136 EXPECT_EQ(str_end - all_together, 9l); 137 } 138 139 static char int_to_b36_char(int input) { 140 if (input < 0 || input > 36) 141 return '0'; 142 if (input < 10) 143 return '0' + input; 144 return 'A' + input - 10; 145 } 146 147 TEST(LlvmLibcStrToULTest, DecodeInOtherBases) { 148 char small_string[4] = {'\0', '\0', '\0', '\0'}; 149 for (unsigned int base = 2; base <= 36; ++base) { 150 for (unsigned long first_digit = 0; first_digit <= 36; ++first_digit) { 151 small_string[0] = int_to_b36_char(first_digit); 152 if (first_digit < base) { 153 errno = 0; 154 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 155 first_digit); 156 ASSERT_EQ(errno, 0); 157 } else { 158 errno = 0; 159 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 0ul); 160 ASSERT_EQ(errno, 0); 161 } 162 } 163 } 164 165 for (unsigned int base = 2; base <= 36; ++base) { 166 for (unsigned long first_digit = 0; first_digit <= 36; ++first_digit) { 167 small_string[0] = int_to_b36_char(first_digit); 168 for (unsigned long second_digit = 0; second_digit <= 36; ++second_digit) { 169 small_string[1] = int_to_b36_char(second_digit); 170 if (first_digit < base && second_digit < base) { 171 errno = 0; 172 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 173 second_digit + (first_digit * base)); 174 ASSERT_EQ(errno, 0); 175 } else if (first_digit < base) { 176 errno = 0; 177 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 178 first_digit); 179 ASSERT_EQ(errno, 0); 180 } else { 181 errno = 0; 182 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 0ul); 183 ASSERT_EQ(errno, 0); 184 } 185 } 186 } 187 } 188 189 for (unsigned int base = 2; base <= 36; ++base) { 190 for (unsigned long first_digit = 0; first_digit <= 36; ++first_digit) { 191 small_string[0] = int_to_b36_char(first_digit); 192 for (unsigned long second_digit = 0; second_digit <= 36; ++second_digit) { 193 small_string[1] = int_to_b36_char(second_digit); 194 for (unsigned long third_digit = 0; third_digit <= 36; ++third_digit) { 195 small_string[2] = int_to_b36_char(third_digit); 196 197 if (first_digit < base && second_digit < base && third_digit < base) { 198 errno = 0; 199 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 200 third_digit + (second_digit * base) + 201 (first_digit * base * base)); 202 ASSERT_EQ(errno, 0); 203 } else if (first_digit < base && second_digit < base) { 204 errno = 0; 205 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 206 second_digit + (first_digit * base)); 207 ASSERT_EQ(errno, 0); 208 } else if (first_digit < base) { 209 // if the base is 16 there is a special case for the prefix 0X. 210 // The number is treated as a one digit hexadecimal. 211 if (base == 16 && first_digit == 0 && second_digit == 33) { 212 if (third_digit < base) { 213 errno = 0; 214 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 215 third_digit); 216 ASSERT_EQ(errno, 0); 217 } else { 218 errno = 0; 219 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 220 0ul); 221 ASSERT_EQ(errno, 0); 222 } 223 } else { 224 errno = 0; 225 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 226 first_digit); 227 ASSERT_EQ(errno, 0); 228 } 229 } else { 230 errno = 0; 231 ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 0ul); 232 ASSERT_EQ(errno, 0); 233 } 234 } 235 } 236 } 237 } 238 } 239 240 TEST(LlvmLibcStrToULTest, CleanBaseSixteenDecode) { 241 char *str_end = nullptr; 242 243 const char *no_prefix = "123abc"; 244 errno = 0; 245 ASSERT_EQ(__llvm_libc::strtoul(no_prefix, &str_end, 16), 0x123abcul); 246 ASSERT_EQ(errno, 0); 247 EXPECT_EQ(str_end - no_prefix, 6l); 248 249 const char *yes_prefix = "0x456def"; 250 errno = 0; 251 ASSERT_EQ(__llvm_libc::strtoul(yes_prefix, &str_end, 16), 0x456deful); 252 ASSERT_EQ(errno, 0); 253 EXPECT_EQ(str_end - yes_prefix, 8l); 254 } 255 256 TEST(LlvmLibcStrToULTest, AutomaticBaseSelection) { 257 char *str_end = nullptr; 258 259 const char *base_ten = "12345"; 260 errno = 0; 261 ASSERT_EQ(__llvm_libc::strtoul(base_ten, &str_end, 0), 12345ul); 262 ASSERT_EQ(errno, 0); 263 EXPECT_EQ(str_end - base_ten, 5l); 264 265 const char *base_sixteen_no_prefix = "123abc"; 266 errno = 0; 267 ASSERT_EQ(__llvm_libc::strtoul(base_sixteen_no_prefix, &str_end, 0), 123ul); 268 ASSERT_EQ(errno, 0); 269 EXPECT_EQ(str_end - base_sixteen_no_prefix, 3l); 270 271 const char *base_sixteen_with_prefix = "0x456def"; 272 errno = 0; 273 ASSERT_EQ(__llvm_libc::strtoul(base_sixteen_with_prefix, &str_end, 0), 274 0x456deful); 275 ASSERT_EQ(errno, 0); 276 EXPECT_EQ(str_end - base_sixteen_with_prefix, 8l); 277 278 const char *base_eight_with_prefix = "012345"; 279 errno = 0; 280 ASSERT_EQ(__llvm_libc::strtoul(base_eight_with_prefix, &str_end, 0), 281 012345ul); 282 ASSERT_EQ(errno, 0); 283 EXPECT_EQ(str_end - base_eight_with_prefix, 6l); 284 } 285