1 //===- StringExtrasTest.cpp - Unit tests for String extras ----------------===// 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 "llvm/ADT/StringExtras.h" 10 #include "llvm/Support/raw_ostream.h" 11 #include "gmock/gmock.h" 12 #include "gtest/gtest.h" 13 14 using namespace llvm; 15 16 TEST(StringExtrasTest, isPrint) { 17 EXPECT_FALSE(isPrint('\0')); 18 EXPECT_FALSE(isPrint('\t')); 19 EXPECT_TRUE(isPrint('0')); 20 EXPECT_TRUE(isPrint('a')); 21 EXPECT_TRUE(isPrint('A')); 22 EXPECT_TRUE(isPrint(' ')); 23 EXPECT_TRUE(isPrint('~')); 24 EXPECT_TRUE(isPrint('?')); 25 } 26 27 TEST(StringExtrasTest, isSpace) { 28 EXPECT_TRUE(isSpace(' ')); 29 EXPECT_TRUE(isSpace('\t')); 30 EXPECT_TRUE(isSpace('\n')); 31 EXPECT_TRUE(isSpace('\v')); 32 EXPECT_TRUE(isSpace('\f')); 33 EXPECT_TRUE(isSpace('\v')); 34 EXPECT_FALSE(isSpace('\0')); 35 EXPECT_FALSE(isSpace('_')); 36 } 37 38 TEST(StringExtrasTest, isLower) { 39 EXPECT_TRUE(isLower('a')); 40 EXPECT_TRUE(isLower('b')); 41 EXPECT_TRUE(isLower('z')); 42 EXPECT_FALSE(isLower('A')); 43 EXPECT_FALSE(isLower('B')); 44 EXPECT_FALSE(isLower('Z')); 45 EXPECT_FALSE(isLower('\0')); 46 EXPECT_FALSE(isLower('\t')); 47 EXPECT_FALSE(isLower('\?')); 48 } 49 50 TEST(StringExtrasTest, isUpper) { 51 EXPECT_FALSE(isUpper('a')); 52 EXPECT_FALSE(isUpper('b')); 53 EXPECT_FALSE(isUpper('z')); 54 EXPECT_TRUE(isUpper('A')); 55 EXPECT_TRUE(isUpper('B')); 56 EXPECT_TRUE(isUpper('Z')); 57 EXPECT_FALSE(isUpper('\0')); 58 EXPECT_FALSE(isUpper('\t')); 59 EXPECT_FALSE(isUpper('\?')); 60 } 61 62 TEST(StringExtrasTest, isPunct) { 63 EXPECT_FALSE(isPunct('a')); 64 EXPECT_FALSE(isPunct('b')); 65 EXPECT_FALSE(isPunct('z')); 66 EXPECT_TRUE(isPunct('-')); 67 EXPECT_TRUE(isPunct(';')); 68 EXPECT_TRUE(isPunct('@')); 69 EXPECT_FALSE(isPunct('0')); 70 EXPECT_FALSE(isPunct('1')); 71 EXPECT_FALSE(isPunct('x')); 72 } 73 74 template <class ContainerT> void testJoin() { 75 ContainerT Items; 76 EXPECT_EQ("", join(Items.begin(), Items.end(), " <sep> ")); 77 78 Items = {"foo"}; 79 EXPECT_EQ("foo", join(Items.begin(), Items.end(), " <sep> ")); 80 81 Items = {"foo", "bar"}; 82 EXPECT_EQ("foo <sep> bar", join(Items.begin(), Items.end(), " <sep> ")); 83 84 Items = {"foo", "bar", "baz"}; 85 EXPECT_EQ("foo <sep> bar <sep> baz", 86 join(Items.begin(), Items.end(), " <sep> ")); 87 } 88 89 TEST(StringExtrasTest, Join) { 90 { 91 SCOPED_TRACE("std::vector<std::string>"); 92 testJoin<std::vector<std::string>>(); 93 } 94 { 95 SCOPED_TRACE("std::vector<const char*>"); 96 testJoin<std::vector<const char *>>(); 97 } 98 } 99 100 TEST(StringExtrasTest, JoinItems) { 101 const char *Foo = "foo"; 102 std::string Bar = "bar"; 103 llvm::StringRef Baz = "baz"; 104 char X = 'x'; 105 106 EXPECT_EQ("", join_items(" <sep> ")); 107 EXPECT_EQ("", join_items('/')); 108 109 EXPECT_EQ("foo", join_items(" <sep> ", Foo)); 110 EXPECT_EQ("foo", join_items('/', Foo)); 111 112 EXPECT_EQ("foo <sep> bar", join_items(" <sep> ", Foo, Bar)); 113 EXPECT_EQ("foo/bar", join_items('/', Foo, Bar)); 114 115 EXPECT_EQ("foo <sep> bar <sep> baz", join_items(" <sep> ", Foo, Bar, Baz)); 116 EXPECT_EQ("foo/bar/baz", join_items('/', Foo, Bar, Baz)); 117 118 EXPECT_EQ("foo <sep> bar <sep> baz <sep> x", 119 join_items(" <sep> ", Foo, Bar, Baz, X)); 120 121 EXPECT_EQ("foo/bar/baz/x", join_items('/', Foo, Bar, Baz, X)); 122 } 123 124 TEST(StringExtrasTest, ToAndFromHex) { 125 std::vector<uint8_t> OddBytes = {0x5, 0xBD, 0x0D, 0x3E, 0xCD}; 126 std::string OddStr = "05BD0D3ECD"; 127 StringRef OddData(reinterpret_cast<const char *>(OddBytes.data()), 128 OddBytes.size()); 129 EXPECT_EQ(OddStr, toHex(OddData)); 130 EXPECT_EQ(OddData, fromHex(StringRef(OddStr).drop_front())); 131 EXPECT_EQ(StringRef(OddStr).lower(), toHex(OddData, true)); 132 133 std::vector<uint8_t> EvenBytes = {0xA5, 0xBD, 0x0D, 0x3E, 0xCD}; 134 std::string EvenStr = "A5BD0D3ECD"; 135 StringRef EvenData(reinterpret_cast<const char *>(EvenBytes.data()), 136 EvenBytes.size()); 137 EXPECT_EQ(EvenStr, toHex(EvenData)); 138 EXPECT_EQ(EvenData, fromHex(EvenStr)); 139 EXPECT_EQ(StringRef(EvenStr).lower(), toHex(EvenData, true)); 140 141 std::string InvalidStr = "A50\xFF"; 142 std::string IgnoredOutput; 143 EXPECT_FALSE(tryGetFromHex(InvalidStr, IgnoredOutput)); 144 } 145 146 TEST(StringExtrasTest, UINT64ToHex) { 147 EXPECT_EQ(utohexstr(0xA0u), "A0"); 148 EXPECT_EQ(utohexstr(0xA0u, false, 4), "00A0"); 149 EXPECT_EQ(utohexstr(0xA0u, false, 8), "000000A0"); 150 } 151 152 TEST(StringExtrasTest, to_float) { 153 float F; 154 EXPECT_TRUE(to_float("4.7", F)); 155 EXPECT_FLOAT_EQ(4.7f, F); 156 157 double D; 158 EXPECT_TRUE(to_float("4.7", D)); 159 EXPECT_DOUBLE_EQ(4.7, D); 160 161 long double LD; 162 EXPECT_TRUE(to_float("4.7", LD)); 163 EXPECT_DOUBLE_EQ(4.7, LD); 164 165 EXPECT_FALSE(to_float("foo", F)); 166 EXPECT_FALSE(to_float("7.4 foo", F)); 167 EXPECT_FLOAT_EQ(4.7f, F); // F should be unchanged 168 } 169 170 TEST(StringExtrasTest, printLowerCase) { 171 std::string str; 172 raw_string_ostream OS(str); 173 printLowerCase("ABCdefg01234.,&!~`'}\"", OS); 174 EXPECT_EQ("abcdefg01234.,&!~`'}\"", OS.str()); 175 } 176 177 TEST(StringExtrasTest, printEscapedString) { 178 std::string str; 179 raw_string_ostream OS(str); 180 printEscapedString("ABCdef123&<>\\\"'\t", OS); 181 EXPECT_EQ("ABCdef123&<>\\\\\\22'\\09", OS.str()); 182 } 183 184 TEST(StringExtrasTest, printHTMLEscaped) { 185 std::string str; 186 raw_string_ostream OS(str); 187 printHTMLEscaped("ABCdef123&<>\"'", OS); 188 EXPECT_EQ("ABCdef123&<>"'", OS.str()); 189 } 190 191 TEST(StringExtrasTest, ConvertToSnakeFromCamelCase) { 192 auto testConvertToSnakeCase = [](llvm::StringRef input, 193 llvm::StringRef expected) { 194 EXPECT_EQ(convertToSnakeFromCamelCase(input), expected.str()); 195 }; 196 197 testConvertToSnakeCase("OpName", "op_name"); 198 testConvertToSnakeCase("opName", "op_name"); 199 testConvertToSnakeCase("OPName", "op_name"); 200 testConvertToSnakeCase("Intel_OCL_BI", "intel_ocl_bi"); 201 testConvertToSnakeCase("I32Attr", "i32_attr"); 202 testConvertToSnakeCase("opNAME", "op_name"); 203 testConvertToSnakeCase("opNAMe", "op_na_me"); 204 testConvertToSnakeCase("opnameE", "opname_e"); 205 testConvertToSnakeCase("OPNameOPName", "op_name_op_name"); 206 testConvertToSnakeCase("_OpName", "_op_name"); 207 testConvertToSnakeCase("Op_Name", "op_name"); 208 testConvertToSnakeCase("", ""); 209 testConvertToSnakeCase("A", "a"); 210 testConvertToSnakeCase("_", "_"); 211 testConvertToSnakeCase("a", "a"); 212 testConvertToSnakeCase("op_name", "op_name"); 213 testConvertToSnakeCase("_op_name", "_op_name"); 214 testConvertToSnakeCase("__op_name", "__op_name"); 215 testConvertToSnakeCase("op__name", "op__name"); 216 } 217 218 TEST(StringExtrasTest, ConvertToCamelFromSnakeCase) { 219 auto testConvertToCamelCase = [](bool capitalizeFirst, llvm::StringRef input, 220 llvm::StringRef expected) { 221 EXPECT_EQ(convertToCamelFromSnakeCase(input, capitalizeFirst), 222 expected.str()); 223 }; 224 225 testConvertToCamelCase(false, "op_name", "opName"); 226 testConvertToCamelCase(false, "_op_name", "_opName"); 227 testConvertToCamelCase(false, "__op_name", "_OpName"); 228 testConvertToCamelCase(false, "op__name", "op_Name"); 229 testConvertToCamelCase(false, "", ""); 230 testConvertToCamelCase(false, "A", "A"); 231 testConvertToCamelCase(false, "_", "_"); 232 testConvertToCamelCase(false, "a", "a"); 233 testConvertToCamelCase(false, "OpName", "OpName"); 234 testConvertToCamelCase(false, "opName", "opName"); 235 testConvertToCamelCase(false, "_OpName", "_OpName"); 236 testConvertToCamelCase(false, "Op_Name", "Op_Name"); 237 testConvertToCamelCase(true, "op_name", "OpName"); 238 testConvertToCamelCase(true, "_op_name", "_opName"); 239 testConvertToCamelCase(true, "__op_name", "_OpName"); 240 testConvertToCamelCase(true, "op__name", "Op_Name"); 241 testConvertToCamelCase(true, "", ""); 242 testConvertToCamelCase(true, "A", "A"); 243 testConvertToCamelCase(true, "_", "_"); 244 testConvertToCamelCase(true, "a", "A"); 245 testConvertToCamelCase(true, "OpName", "OpName"); 246 testConvertToCamelCase(true, "_OpName", "_OpName"); 247 testConvertToCamelCase(true, "Op_Name", "Op_Name"); 248 testConvertToCamelCase(true, "opName", "OpName"); 249 } 250 251 constexpr uint64_t MaxUint64 = std::numeric_limits<uint64_t>::max(); 252 constexpr int64_t MaxInt64 = std::numeric_limits<int64_t>::max(); 253 constexpr int64_t MinInt64 = std::numeric_limits<int64_t>::min(); 254 255 TEST(StringExtrasTest, UToStr) { 256 EXPECT_EQ("0", utostr(0)); 257 EXPECT_EQ("0", utostr(0, /*isNeg=*/false)); 258 EXPECT_EQ("1", utostr(1)); 259 EXPECT_EQ("1", utostr(1, /*isNeg=*/false)); 260 EXPECT_EQ(std::to_string(MaxUint64), utostr(MaxUint64)); 261 EXPECT_EQ(std::to_string(MaxUint64), utostr(MaxUint64, /*isNeg=*/false)); 262 263 EXPECT_EQ("-0", utostr(0, /*isNeg=*/true)); 264 EXPECT_EQ("-1", utostr(1, /*isNeg=*/true)); 265 EXPECT_EQ("-" + std::to_string(MaxInt64), utostr(MaxInt64, /*isNeg=*/true)); 266 constexpr uint64_t MinusMinInt64 = -static_cast<uint64_t>(MinInt64); 267 EXPECT_EQ("-" + std::to_string(MinusMinInt64), 268 utostr(MinusMinInt64, /*isNeg=*/true)); 269 EXPECT_EQ("-" + std::to_string(MaxUint64), utostr(MaxUint64, /*isNeg=*/true)); 270 } 271 272 TEST(StringExtrasTest, IToStr) { 273 EXPECT_EQ("0", itostr(0)); 274 EXPECT_EQ("1", itostr(1)); 275 EXPECT_EQ("-1", itostr(-1)); 276 EXPECT_EQ(std::to_string(MinInt64), itostr(MinInt64)); 277 EXPECT_EQ(std::to_string(MaxInt64), itostr(MaxInt64)); 278 } 279 280 TEST(StringExtrasTest, ListSeparator) { 281 ListSeparator LS; 282 StringRef S = LS; 283 EXPECT_EQ(S, ""); 284 S = LS; 285 EXPECT_EQ(S, ", "); 286 287 ListSeparator LS2(" "); 288 S = LS2; 289 EXPECT_EQ(S, ""); 290 S = LS2; 291 EXPECT_EQ(S, " "); 292 } 293 294 TEST(StringExtrasTest, toStringAPInt) { 295 bool isSigned; 296 297 EXPECT_EQ(toString(APInt(8, 0), 2, true, true), "0b0"); 298 EXPECT_EQ(toString(APInt(8, 0), 8, true, true), "00"); 299 EXPECT_EQ(toString(APInt(8, 0), 10, true, true), "0"); 300 EXPECT_EQ(toString(APInt(8, 0), 16, true, true), "0x0"); 301 EXPECT_EQ(toString(APInt(8, 0), 36, true, false), "0"); 302 303 isSigned = false; 304 EXPECT_EQ(toString(APInt(8, 255, isSigned), 2, isSigned, true), "0b11111111"); 305 EXPECT_EQ(toString(APInt(8, 255, isSigned), 8, isSigned, true), "0377"); 306 EXPECT_EQ(toString(APInt(8, 255, isSigned), 10, isSigned, true), "255"); 307 EXPECT_EQ(toString(APInt(8, 255, isSigned), 16, isSigned, true), "0xFF"); 308 EXPECT_EQ(toString(APInt(8, 255, isSigned), 36, isSigned, false), "73"); 309 310 isSigned = true; 311 EXPECT_EQ(toString(APInt(8, -1, isSigned), 2, isSigned, true), "-0b1"); 312 EXPECT_EQ(toString(APInt(8, -1, isSigned), 8, isSigned, true), "-01"); 313 EXPECT_EQ(toString(APInt(8, -1, isSigned), 10, isSigned, true), "-1"); 314 EXPECT_EQ(toString(APInt(8, -1, isSigned), 16, isSigned, true), "-0x1"); 315 EXPECT_EQ(toString(APInt(8, -1, isSigned), 36, isSigned, false), "-1"); 316 } 317 318 TEST(StringExtrasTest, toStringAPSInt) { 319 bool isUnsigned; 320 321 EXPECT_EQ(toString(APSInt(APInt(8, 0), false), 2), "0"); 322 EXPECT_EQ(toString(APSInt(APInt(8, 0), false), 8), "0"); 323 EXPECT_EQ(toString(APSInt(APInt(8, 0), false), 10), "0"); 324 EXPECT_EQ(toString(APSInt(APInt(8, 0), false), 16), "0"); 325 326 isUnsigned = true; 327 EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 2), "11111111"); 328 EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 8), "377"); 329 EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 10), "255"); 330 EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 16), "FF"); 331 332 isUnsigned = false; 333 EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 2), "-1"); 334 EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 8), "-1"); 335 EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 10), "-1"); 336 EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 16), "-1"); 337 } 338 339 TEST(StringExtrasTest, splitStringRef) { 340 auto Spl = split("foo<=>bar<=><=>baz", "<=>"); 341 auto It = Spl.begin(); 342 auto End = Spl.end(); 343 344 ASSERT_NE(It, End); 345 EXPECT_EQ(*It, StringRef("foo")); 346 ASSERT_NE(++It, End); 347 EXPECT_EQ(*It, StringRef("bar")); 348 ASSERT_NE(++It, End); 349 EXPECT_EQ(*It, StringRef("")); 350 ASSERT_NE(++It, End); 351 EXPECT_EQ(*It, StringRef("baz")); 352 ASSERT_EQ(++It, End); 353 } 354 355 TEST(StringExtrasTest, splitStringRefForLoop) { 356 llvm::SmallVector<StringRef, 4> Result; 357 for (StringRef x : split("foo<=>bar<=><=>baz", "<=>")) 358 Result.push_back(x); 359 EXPECT_THAT(Result, testing::ElementsAre("foo", "bar", "", "baz")); 360 } 361 362 TEST(StringExtrasTest, splitChar) { 363 auto Spl = split("foo,bar,,baz", ','); 364 auto It = Spl.begin(); 365 auto End = Spl.end(); 366 367 ASSERT_NE(It, End); 368 EXPECT_EQ(*It, StringRef("foo")); 369 ASSERT_NE(++It, End); 370 EXPECT_EQ(*It, StringRef("bar")); 371 ASSERT_NE(++It, End); 372 EXPECT_EQ(*It, StringRef("")); 373 ASSERT_NE(++It, End); 374 EXPECT_EQ(*It, StringRef("baz")); 375 ASSERT_EQ(++It, End); 376 } 377 378 TEST(StringExtrasTest, splitCharForLoop) { 379 llvm::SmallVector<StringRef, 4> Result; 380 for (StringRef x : split("foo,bar,,baz", ',')) 381 Result.push_back(x); 382 EXPECT_THAT(Result, testing::ElementsAre("foo", "bar", "", "baz")); 383 } 384 385 TEST(StringExtrasTest, arrayToStringRef) { 386 auto roundTripTestString = [](llvm::StringRef Str) { 387 EXPECT_EQ(Str, toStringRef(arrayRefFromStringRef<uint8_t>(Str))); 388 EXPECT_EQ(Str, toStringRef(arrayRefFromStringRef<char>(Str))); 389 }; 390 roundTripTestString(""); 391 roundTripTestString("foo"); 392 roundTripTestString("\0\n"); 393 roundTripTestString("\xFF\xFE"); 394 } 395