github.com/Aoi-hosizora/ahlib@v1.5.1-0.20230404072829-241b93cf91c7/xstring/xstring_test.go (about) 1 package xstring 2 3 import ( 4 "fmt" 5 "github.com/Aoi-hosizora/ahlib/xtesting" 6 "net/url" 7 "strings" 8 "testing" 9 "time" 10 "unicode" 11 ) 12 13 func TestCapitalize(t *testing.T) { 14 for _, tc := range []struct { 15 give string 16 want string 17 }{ 18 {"", ""}, 19 {" ", " "}, 20 {"abc", "Abc"}, 21 {"Abc", "Abc"}, 22 {"abc def", "Abc def"}, 23 {"测试", "测试"}, 24 {"テス", "テス"}, 25 {"тест", "Тест"}, 26 } { 27 xtesting.Equal(t, Capitalize(tc.give), tc.want) 28 } 29 } 30 31 func TestUncapitalize(t *testing.T) { 32 for _, tc := range []struct { 33 give string 34 want string 35 }{ 36 {"", ""}, 37 {" ", " "}, 38 {"Abc", "abc"}, 39 {"abc", "abc"}, 40 {"Abc Def", "abc Def"}, 41 {"测试", "测试"}, 42 {"テス", "テス"}, 43 {"Тест", "тест"}, 44 } { 45 xtesting.Equal(t, Uncapitalize(tc.give), tc.want) 46 } 47 } 48 49 func TestCapitalizeAll(t *testing.T) { 50 for _, tc := range []struct { 51 give string 52 want string 53 }{ 54 {"", ""}, 55 {" ", " "}, 56 {"abc", "Abc"}, 57 {"abc def", "Abc Def"}, 58 {"abc\tDef ", "Abc\tDef "}, 59 {" abc\ndef\r\n ghi\v", " Abc\nDef\r\n Ghi\v"}, 60 {"测试 测试", "测试 测试"}, 61 {"テス テス", "テス テス"}, 62 {"тест тест", "Тест Тест"}, 63 } { 64 xtesting.Equal(t, CapitalizeAll(tc.give), tc.want) 65 } 66 } 67 68 func TestUncapitalizeAll(t *testing.T) { 69 for _, tc := range []struct { 70 give string 71 want string 72 }{ 73 {"", ""}, 74 {" ", " "}, 75 {"Abc", "abc"}, 76 {"Abc Def", "abc def"}, 77 {"abc\tDef ", "abc\tdef "}, 78 {" abc\nDef\r\n Ghi\v", " abc\ndef\r\n ghi\v"}, 79 {"测试 测试", "测试 测试"}, 80 {"テス テス", "テス テス"}, 81 {"Тест Тест", "тест тест"}, 82 } { 83 xtesting.Equal(t, UncapitalizeAll(tc.give), tc.want) 84 } 85 } 86 87 func TestIsArabicNumber(t *testing.T) { 88 xtesting.True(t, unicode.IsNumber('0'), true) 89 xtesting.True(t, unicode.IsNumber('5'), true) 90 for _, tc := range []struct { 91 give rune 92 want bool 93 }{ 94 {' ', false}, 95 {'0', true}, 96 {'1', true}, 97 {'2', true}, 98 {'3', true}, 99 {'4', true}, 100 {'5', true}, 101 {'6', true}, 102 {'7', true}, 103 {'8', true}, 104 {'9', true}, 105 {'0', false}, // <- true for unicode.IsNumber 106 {'1', false}, 107 {'2', false}, 108 {'3', false}, 109 {'4', false}, 110 {'5', false}, 111 {'6', false}, 112 {'7', false}, 113 {'8', false}, 114 {'9', false}, 115 } { 116 t.Run(string(tc.give), func(t *testing.T) { 117 xtesting.Equal(t, IsArabicNumber(tc.give), tc.want) 118 }) 119 } 120 } 121 122 func TestIsBlank(t *testing.T) { 123 for _, tc := range []struct { 124 give rune 125 want bool 126 }{ 127 {' ', true}, 128 {'\t', true}, 129 {'\n', true}, 130 {'\r', true}, 131 {'\v', true}, 132 {'\f', true}, 133 {' ', true}, 134 {'\x85', true}, 135 {'\xA0', true}, 136 {0x2000, true}, 137 {0x2001, true}, 138 {0x2002, true}, 139 {0x2003, true}, 140 {0x2004, true}, 141 {0x2005, true}, 142 {0x2006, true}, 143 {0x2007, true}, 144 {0x2008, true}, 145 {0x2009, true}, 146 {0x200A, true}, 147 {0x200B, false}, 148 {0x200F, false}, 149 {0x2028, true}, 150 {0x2029, true}, 151 {0x202F, true}, 152 {0x205F, true}, 153 {'a', false}, 154 {'0', false}, 155 {'测', false}, 156 } { 157 xtesting.Equal(t, IsBlank(tc.give), tc.want) 158 } 159 } 160 161 func TestTrimBlanks(t *testing.T) { 162 for _, tc := range []struct { 163 give string 164 want string 165 }{ 166 {"", ""}, 167 {" ", ""}, 168 {"\t", ""}, 169 {"\n|\r", "|"}, 170 {"\t\t\r\r\n\n", ""}, 171 {" a b\tc\r\nd\v\f", "a b\tc\r\nd"}, 172 } { 173 t.Run(tc.give, func(t *testing.T) { 174 xtesting.Equal(t, TrimBlanks(tc.give), tc.want) 175 }) 176 } 177 } 178 179 func TestReplaceAndRemoveExtraBlanks(t *testing.T) { 180 for _, tc := range []struct { 181 give string 182 want1 string 183 want2 string 184 }{ 185 {"", "", ""}, 186 {" ", "", ""}, 187 {" \n ", "", ""}, 188 {"\t\v ", "", ""}, 189 {"a b", "a|b", "a b"}, 190 {"a b", "a|b", "a b"}, 191 {" a b\tc\r\nd", "a|b|c|d", "a b c d"}, 192 {" ab cd ef\n\tgh\n", "ab|cd|ef|gh", "ab cd ef gh"}, 193 {"\t\t\r\r\n\n", "", ""}, 194 } { 195 t.Run(tc.give, func(t *testing.T) { 196 xtesting.Equal(t, ReplaceExtraBlanks(tc.give, "|"), tc.want1) 197 xtesting.Equal(t, RemoveExtraBlanks(tc.give), tc.want2) 198 }) 199 } 200 } 201 202 func TestIsBreakLine(t *testing.T) { 203 for _, tc := range []struct { 204 give rune 205 want bool 206 }{ 207 {' ', false}, 208 {'\t', false}, 209 {'\n', true}, 210 {'\r', true}, 211 {'\v', false}, 212 {'\f', false}, 213 {'a', false}, 214 {'0', false}, 215 {'测', false}, 216 } { 217 xtesting.Equal(t, IsBreakLine(tc.give), tc.want) 218 } 219 } 220 221 func TestTrimBreakLines(t *testing.T) { 222 for _, tc := range []struct { 223 give string 224 want string 225 }{ 226 {"", ""}, 227 {" ", " "}, 228 {"\n", ""}, 229 {"\n|\r", "|"}, 230 {"\n\r\t\r\t\n", "\t\r\t"}, 231 {" a b\tc\r\nd\r\n", " a b\tc\r\nd"}, 232 } { 233 t.Run(tc.give, func(t *testing.T) { 234 xtesting.Equal(t, TrimBreakLines(tc.give), tc.want) 235 }) 236 } 237 } 238 239 func TestReplaceAndRemoveExtraBreakLines(t *testing.T) { 240 for _, tc := range []struct { 241 give string 242 want1 string 243 want2 string 244 }{ 245 {"", "", ""}, 246 {" ", " ", " "}, 247 {" \n\n ", " | ", " \n "}, 248 {"\t\r\n", "\t", "\t"}, 249 {"a\nb", "a|b", "a\nb"}, 250 {"a\n\rb", "a|b", "a\nb"}, 251 {" a\rb\tc\n\nd", " a|b\tc|d", " a\nb\tc\nd"}, 252 {" \n ab\t cd ef\n\rgh\n", " | ab\t cd ef|gh", " \n ab\t cd ef\ngh"}, 253 {"\n\r\t\r\t\n", "\t|\t", "\t\n\t"}, 254 } { 255 t.Run(tc.give, func(t *testing.T) { 256 xtesting.Equal(t, ReplaceExtraBreakLines(tc.give, "|"), tc.want1) 257 xtesting.Equal(t, RemoveExtraBreakLines(tc.give), tc.want2) 258 }) 259 } 260 } 261 262 func TestSplitToWords(t *testing.T) { 263 for _, tc := range []struct { 264 giveString string 265 giveSeps []string 266 want []string 267 }{ 268 {"", []string{}, []string{}}, 269 {"a", []string{}, []string{"a"}}, 270 {"ABC", []string{}, []string{"ABC"}}, 271 272 {"a", []string{"a"}, []string{}}, 273 {"abc", []string{"a"}, []string{"bc"}}, 274 {"abc", []string{"b"}, []string{"a", "c"}}, 275 {"abc", []string{"c"}, []string{"ab"}}, 276 {"abc", []string{"a", "b"}, []string{"c"}}, 277 {"abc", []string{"a", "b", "c"}, []string{}}, 278 {"abc#d", []string{"c", "#"}, []string{"ab", "d"}}, 279 280 {" ", []string{}, []string{}}, 281 {"a b", []string{}, []string{"a", "b"}}, 282 {" a b c ", []string{}, []string{"a", "b", "c"}}, 283 {" a b c ", []string{"="}, []string{"a", "b", "c"}}, 284 285 {"Abc", []string{}, []string{"Abc"}}, 286 {"aBc", []string{}, []string{"a", "Bc"}}, 287 {"abC", []string{}, []string{"ab", "C"}}, 288 {"aBC", []string{}, []string{"a", "BC"}}, 289 {"Abc", []string{"="}, []string{"Abc"}}, 290 {"aBc", []string{"="}, []string{"aBc"}}, 291 {"abC", []string{"="}, []string{"abC"}}, 292 {"aBC", []string{"="}, []string{"aBC"}}, 293 {"Abc", []string{"=", CaseSplitter}, []string{"Abc"}}, 294 {"aBc", []string{"=", CaseSplitter}, []string{"a", "Bc"}}, 295 {"abC", []string{"=", CaseSplitter}, []string{"ab", "C"}}, 296 {"aBC", []string{"=", CaseSplitter}, []string{"a", "BC"}}, 297 298 {"ab cd_ef.ghIj-kl", []string{}, []string{"ab", "cd", "ef", "gh", "Ij", "kl"}}, 299 {"ab cd_ef.ghIj-kl", []string{"="}, []string{"ab", "cd_ef.ghIj-kl"}}, 300 {"ab cd_ef.ghIj-kl", []string{CaseSplitter}, []string{"ab", "cd_ef.gh", "Ij-kl"}}, 301 {"ab cd_ef.ghIj-kl", []string{"_", "-"}, []string{"ab", "cd", "ef.ghIj", "kl"}}, 302 {"ab cd_ef.ghIj-kl", []string{" ", ".", ".", CaseSplitter}, []string{"ab", "cd_ef", "gh", "Ij-kl"}}, 303 304 {"!", []string{"!"}, []string{}}, 305 {"!!a!!", []string{"!"}, []string{"a"}}, 306 {"aB_c-d.e+f g h?i", []string{CaseSplitter, "+", "?", "!"}, []string{"a", "B_c-d.e", "f", "g", "h", "i"}}, 307 {"aB_c-d.e+f g h?i", []string{CaseSplitter, "_", "-", ".", "+"}, []string{"a", "B", "c", "d", "e", "f", "g", "h?i"}}, 308 {"тестТест-a", []string{}, []string{"тест", "Тест", "a"}}, 309 {"тестТест-a", []string{"-"}, []string{"тестТест", "a"}}, 310 {"测试andテスТестOr", []string{}, []string{"测试andテス", "Тест", "Or"}}, 311 {"测试 and テス тест or", []string{"and"}, []string{"测试", "テス", "тест", "or"}}, 312 {"mix-Mix_Mix.Mix?mix", []string{"-", "_", ".", "?"}, []string{"mix", "Mix", "Mix", "Mix", "mix"}}, 313 } { 314 t.Run(tc.giveString, func(t *testing.T) { 315 words := SplitToWords(tc.giveString, tc.giveSeps...) 316 xtesting.Equal(t, words, tc.want) 317 }) 318 } 319 } 320 321 func TestXXXCase(t *testing.T) { 322 for _, tc := range []struct { 323 give string 324 wantP string 325 wantC string 326 wantS string 327 wantK string 328 }{ 329 {"", "", "", "", ""}, 330 {"a", "A", "a", "a", "a"}, 331 {"A", "A", "a", "a", "a"}, 332 {"abc", "Abc", "abc", "abc", "abc"}, 333 {"abCdEF", "AbCdEF", "abCdEF", "ab_cd_ef", "ab-cd-ef"}, 334 {"AAaaAA_bbBBbb", "AAaaAABbBBbb", "aaaaAABbBBbb", "aaaa_aa_bb_bbbb", "aaaa-aa-bb-bbbb"}, 335 {"a1a b2B C3c D4D", "A1aB2BC3cD4D", "a1aB2BC3cD4D", "a1a_b2_b_c3c_d4_d", "a1a-b2-b-c3c-d4-d"}, 336 {"IPv4Address-and-Port", "IPv4AddressAndPort", "ipv4AddressAndPort", "ipv4_address_and_port", "ipv4-address-and-port"}, 337 {"TestPascalCase", "TestPascalCase", "testPascalCase", "test_pascal_case", "test-pascal-case"}, 338 {"testCamelCase", "TestCamelCase", "testCamelCase", "test_camel_case", "test-camel-case"}, 339 {"test_snake_case", "TestSnakeCase", "testSnakeCase", "test_snake_case", "test-snake-case"}, 340 {"test-kebab-case", "TestKebabCase", "testKebabCase", "test_kebab_case", "test-kebab-case"}, 341 {"testMixed_Case-Test.Test", "TestMixedCaseTestTest", "testMixedCaseTestTest", "test_mixed_case_test_test", "test-mixed-case-test-test"}, 342 } { 343 t.Run(tc.give, func(t *testing.T) { 344 xtesting.Equal(t, PascalCase(tc.give), tc.wantP) 345 xtesting.Equal(t, CamelCase(tc.give), tc.wantC) 346 xtesting.Equal(t, SnakeCase(tc.give), tc.wantS) 347 xtesting.Equal(t, KebabCase(tc.give), tc.wantK) 348 }) 349 } 350 } 351 352 // showFn represents if tests need to show shuffle and random result. 353 var showFn = func() bool { return false } 354 355 func TestTimeID(t *testing.T) { 356 zero := time.Time{} 357 now := time.Date(2021, time.Month(1), 18, 15, 07, 25, 123456789, time.UTC) 358 for _, tc := range []struct { 359 giveTime time.Time 360 giveCount int 361 want string 362 }{ 363 {now, 0, ""}, 364 {now, 1, "2"}, 365 {zero, 4, "0001"}, 366 {now, 5, "20210"}, 367 {now, 8, "20210118"}, 368 {zero, 8, "00010101"}, 369 {now, 14, "20210118150725"}, 370 {now, 23, "20210118150725123456789"}, 371 {zero, 23, "00010101000000000000000"}, 372 {now, 30, "20210118150725123456789"}, // 25 373 {now, 38, "20210118150725123456789"}, 374 } { 375 uuid := TimeID(tc.giveTime, tc.giveCount) 376 if tc.giveCount <= 23 { 377 xtesting.Equal(t, uuid, tc.want) 378 } else { 379 xtesting.Equal(t, len(uuid), tc.giveCount) 380 xtesting.Equal(t, uuid[:23], tc.want) 381 382 for i := 0; i < 4; i++ { 383 time.Sleep(2 * time.Nanosecond) 384 uuid1 := TimeID(tc.giveTime, tc.giveCount) 385 time.Sleep(2 * time.Nanosecond) 386 uuid2 := TimeID(tc.giveTime, tc.giveCount) 387 xtesting.NotEqual(t, uuid1, uuid2) 388 if showFn() { 389 fmt.Println(uuid1, uuid2) 390 } 391 } 392 } 393 } 394 } 395 396 func TestRandString(t *testing.T) { 397 for _, tc := range []struct { 398 giveFn func(int) string 399 giveCount int 400 }{ 401 {RandCapitalLetterString, 0}, 402 {RandCapitalLetterString, 5}, 403 {RandCapitalLetterString, 20}, 404 405 {RandLowercaseLetterString, 0}, 406 {RandLowercaseLetterString, 5}, 407 {RandLowercaseLetterString, 20}, 408 409 {RandLetterString, 0}, 410 {RandLetterString, 5}, 411 {RandLetterString, 20}, 412 413 {RandNumberString, 0}, 414 {RandNumberString, 5}, 415 {RandNumberString, 20}, 416 417 {RandCapitalLetterNumberString, 0}, 418 {RandCapitalLetterNumberString, 5}, 419 {RandCapitalLetterNumberString, 20}, 420 421 {RandLowercaseLetterNumberString, 0}, 422 {RandLowercaseLetterNumberString, 5}, 423 {RandLowercaseLetterNumberString, 20}, 424 425 {RandLetterNumberString, 0}, 426 {RandLetterNumberString, 5}, 427 {RandLetterNumberString, 20}, 428 } { 429 r := tc.giveFn(tc.giveCount) 430 if tc.giveCount == 0 { 431 xtesting.Equal(t, r, "") 432 } else { 433 xtesting.Equal(t, len(r), tc.giveCount) 434 435 for i := 0; i < 4; i++ { 436 time.Sleep(2 * time.Nanosecond) 437 r1 := tc.giveFn(tc.giveCount) 438 time.Sleep(2 * time.Nanosecond) 439 r2 := tc.giveFn(tc.giveCount) 440 xtesting.NotEqual(t, r1, r2) 441 if showFn() { 442 fmt.Println(r1, r2) 443 } 444 } 445 } 446 } 447 } 448 449 func TestFastStob(t *testing.T) { 450 for _, tc := range []struct { 451 give string 452 want []byte 453 }{ 454 {"", []byte{}}, 455 {"a", []byte{'a'}}, 456 {"hello", []byte{'h', 'e', 'l', 'l', 'o'}}, 457 {"a b c", []byte{'a', ' ', 'b', ' ', 'c'}}, 458 {"测试", []byte("测试")}, 459 {"テス", []byte("テス")}, 460 {"тест", []byte("тест")}, 461 } { 462 xtesting.Equal(t, FastStob(tc.give), tc.want) 463 } 464 } 465 466 func TestFastBtos(t *testing.T) { 467 for _, tc := range []struct { 468 give []byte 469 want string 470 }{ 471 {[]byte{}, ""}, 472 {[]byte{'a'}, "a"}, 473 {[]byte{'h', 'e', 'l', 'l', 'o'}, "hello"}, 474 {[]byte{'a', ' ', 'b', ' ', 'c'}, "a b c"}, 475 {[]byte("测试"), "测试"}, 476 {[]byte("テス"), "テス"}, 477 {[]byte("тест"), "тест"}, 478 } { 479 xtesting.Equal(t, FastBtos(tc.give), tc.want) 480 } 481 } 482 483 func BenchmarkFastStob(b *testing.B) { 484 s := "hello world" 485 486 b.Run("FastStob", func(b *testing.B) { 487 b.ReportAllocs() 488 b.ResetTimer() 489 for i := 0; i < b.N; i++ { 490 _ = FastStob(s) 491 } 492 }) 493 b.Run("ConvertToBytes", func(b *testing.B) { 494 b.ReportAllocs() 495 b.ResetTimer() 496 for i := 0; i < b.N; i++ { 497 _ = []byte(s) 498 } 499 }) 500 } 501 502 func BenchmarkFastBtos(b *testing.B) { 503 bs := []byte{'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'} 504 505 b.Run("FastBtos", func(b *testing.B) { 506 b.ReportAllocs() 507 b.ResetTimer() 508 for i := 0; i < b.N; i++ { 509 _ = FastBtos(bs) 510 } 511 }) 512 b.Run("ConvertToString", func(b *testing.B) { 513 b.ReportAllocs() 514 b.ResetTimer() 515 for i := 0; i < b.N; i++ { 516 _ = string(bs) 517 } 518 }) 519 } 520 521 func TestTrimUTF8XXX(t *testing.T) { 522 // Bom 523 for _, tc := range []struct { 524 giveStr string 525 giveBs []byte 526 wantStr string 527 wantBs []byte 528 }{ 529 {"", []byte{}, "", []byte{}}, 530 {"test", []byte{'t', 'e', 's', 't'}, "test", []byte{'t', 'e', 's', 't'}}, 531 {"\xef\xbb\xbf", []byte{0xEF, 0xBB, 0xBF}, "", []byte{}}, 532 {"\xef\xbb\xbftest", []byte{0xEF, 0xBB, 0xBF, 't', 'e', 's', 't'}, "test", []byte{'t', 'e', 's', 't'}}, 533 } { 534 xtesting.Equal(t, TrimUTF8Bom(tc.giveStr), tc.wantStr) 535 xtesting.Equal(t, TrimUTF8BomBytes(tc.giveBs), tc.wantBs) 536 } 537 538 // Rc 539 for _, tc := range []struct { 540 giveStr string 541 giveBs []byte 542 wantStr string 543 wantBs []byte 544 }{ 545 {"", []byte{}, "", []byte{}}, 546 {"test", []byte{'t', 'e', 's', 't'}, "test", []byte{'t', 'e', 's', 't'}}, 547 {"\xef\xbf\xbd", []byte{0xEF, 0xBF, 0xBD}, "", []byte{}}, 548 {"\xef\xbf\xbdtest", []byte{0xEF, 0xBF, 0xBD, 't', 'e', 's', 't'}, "test", []byte{'t', 'e', 's', 't'}}, 549 } { 550 xtesting.Equal(t, TrimUTF8Replacement(tc.giveStr), tc.wantStr) 551 xtesting.Equal(t, TrimUTF8ReplacementBytes(tc.giveBs), tc.wantBs) 552 } 553 } 554 555 func TestPadGetLeftRight(t *testing.T) { 556 for _, tc := range []struct { 557 give string 558 givePad rune 559 giveLength int 560 wantPadL string 561 wantPadR string 562 wantGetL string 563 wantGetR string 564 wantL string 565 wantR string 566 }{ 567 {"", '0', -2, "", "", "", "", "", ""}, 568 {"", '0', -1, "", "", "", "", "", ""}, 569 {"", '0', 0, "", "", "", "", "", ""}, 570 {"", '0', 1, "0", "0", "", "", "0", "0"}, 571 {"", '0', 2, "00", "00", "", "", "00", "00"}, 572 573 {"1", '0', -2, "1", "1", "", "", "", ""}, 574 {"1", '0', -1, "1", "1", "", "", "", ""}, 575 {"1", '0', 0, "1", "1", "", "", "", ""}, 576 {"1", '0', 1, "1", "1", "1", "1", "1", "1"}, 577 {"1", '0', 2, "01", "10", "1", "1", "01", "10"}, 578 {"1", '0', 3, "001", "100", "1", "1", "001", "100"}, 579 580 {"123", '0', -1, "123", "123", "", "", "", ""}, 581 {"123", '0', 0, "123", "123", "", "", "", ""}, 582 {"123", '0', 1, "123", "123", "1", "3", "1", "3"}, 583 {"123", '0', 2, "123", "123", "12", "23", "12", "23"}, 584 {"123", '0', 3, "123", "123", "123", "123", "123", "123"}, 585 {"123", '0', 4, "0123", "1230", "123", "123", "0123", "1230"}, 586 {"123", '0', 5, "00123", "12300", "123", "123", "00123", "12300"}, 587 588 {"test", ' ', -1, "test", "test", "", "", "", ""}, 589 {"test", ' ', 3, "test", "test", "tes", "est", "tes", "est"}, 590 {"test", ' ', 4, "test", "test", "test", "test", "test", "test"}, 591 {"test", ' ', 5, " test", "test ", "test", "test", " test", "test "}, 592 {"test", ' ', 8, " test", "test ", "test", "test", " test", "test "}, 593 594 {"测试テスтест", '零', 1, "测试テスтест", "测试テスтест", "测", "т", "测", "т"}, 595 {"测试テスтест", '零', 3, "测试テスтест", "测试テスтест", "测试テ", "ест", "测试テ", "ест"}, 596 {"测试テスтест", '零', 6, "测试テスтест", "测试テスтест", "测试テスте", "テスтест", "测试テスте", "テスтест"}, 597 {"测试テスтест", '零', 7, "测试テスтест", "测试テスтест", "测试テスтес", "试テスтест", "测试テスтес", "试テスтест"}, 598 {"测试テスтест", '零', 8, "测试テスтест", "测试テスтест", "测试テスтест", "测试テスтест", "测试テスтест", "测试テスтест"}, 599 {"测试テスтест", '零', 9, "零测试テスтест", "测试テスтест零", "测试テスтест", "测试テスтест", "零测试テスтест", "测试テスтест零"}, 600 {"测试テスтест", '零', 11, "零零零测试テスтест", "测试テスтест零零零", "测试テスтест", "测试テスтест", "零零零测试テスтест", "测试テスтест零零零"}, 601 } { 602 t.Run(tc.give, func(t *testing.T) { 603 xtesting.Equal(t, PadLeft(tc.give, tc.givePad, tc.giveLength), tc.wantPadL) 604 xtesting.Equal(t, PadRight(tc.give, tc.givePad, tc.giveLength), tc.wantPadR) 605 xtesting.Equal(t, GetLeft(tc.give, tc.giveLength), tc.wantGetL) 606 xtesting.Equal(t, GetRight(tc.give, tc.giveLength), tc.wantGetR) 607 xtesting.Equal(t, GetOrPadLeft(tc.give, tc.giveLength, tc.givePad), tc.wantL) 608 xtesting.Equal(t, GetOrPadRight(tc.give, tc.giveLength, tc.givePad), tc.wantR) 609 }) 610 } 611 } 612 613 func TestBool(t *testing.T) { 614 for _, tc := range []struct { 615 giveBool bool 616 giveT string 617 giveF string 618 want string 619 }{ 620 {true, "T", "F", "T"}, 621 {true, "true", "false", "true"}, 622 {true, "1", "0", "1"}, 623 {false, "T", "F", "F"}, 624 {false, "true", "false", "false"}, 625 {false, "1", "0", "0"}, 626 } { 627 xtesting.Equal(t, Bool(tc.giveBool, tc.giveT, tc.giveF), tc.want) 628 } 629 } 630 631 func TestExtraSpace(t *testing.T) { 632 for _, tc := range []struct { 633 give string 634 wantLeftS string 635 wantRightS string 636 wantLeftB string 637 wantRightB string 638 }{ 639 {"", "", "", "", ""}, 640 {" ", " ", " ", " ", " "}, 641 {"\t", " \t", "\t ", "\t", "\t"}, 642 {"\r\n", " \r\n", "\r\n ", "\r\n", "\r\n"}, 643 {"a", " a", "a ", " a", "a "}, 644 {" a|\n\n\n ", " a|\n\n\n ", " a|\n\n\n ", " a|", "a| "}, 645 {"\r\ta| ", " \r\ta| ", "\r\ta| ", " a|", "a| "}, 646 } { 647 t.Run(tc.give, func(t *testing.T) { 648 xtesting.Equal(t, ExtraSpaceOnLeftIfNotEmpty(tc.give), tc.wantLeftS) 649 xtesting.Equal(t, ExtraSpaceOnRightIfNotEmpty(tc.give), tc.wantRightS) 650 xtesting.Equal(t, ExtraSpaceOnLeftIfNotBlank(tc.give), tc.wantLeftB) 651 xtesting.Equal(t, ExtraSpaceOnRightIfNotBlank(tc.give), tc.wantRightB) 652 }) 653 } 654 } 655 656 func TestMaskToken(t *testing.T) { 657 for _, tc := range []struct { 658 giveString string 659 giveIndices []int 660 want string 661 wantR string 662 }{ 663 {"", []int{}, "", ""}, 664 {"", []int{-2}, "", ""}, 665 {"", []int{-1}, "", ""}, 666 {"", []int{0}, "", ""}, 667 {"", []int{1}, "", ""}, 668 {"", []int{2}, "", ""}, 669 670 {"a", []int{}, "a", "*"}, 671 {"a", []int{-3}, "a", "*"}, 672 {"a", []int{-2}, "a", "*"}, 673 {"a", []int{-1}, "*", "a"}, // <<< 674 {"a", []int{0}, "*", "a"}, // <<< 675 {"a", []int{1}, "a", "*"}, 676 {"a", []int{2}, "a", "*"}, 677 {"a", []int{3}, "a", "*"}, 678 {"a", []int{0, 1}, "*", "a"}, 679 {"a", []int{-1, -2}, "*", "a"}, 680 {"a", []int{0, -1}, "*", "a"}, // <<< 681 682 {"aa", []int{}, "aa", "**"}, 683 {"aa", []int{-3}, "aa", "**"}, 684 {"aa", []int{-2}, "*a", "a*"}, // <<< 685 {"aa", []int{-1}, "a*", "*a"}, // <<< 686 {"aa", []int{0}, "*a", "a*"}, // <<< 687 {"aa", []int{1}, "a*", "*a"}, // <<< 688 {"aa", []int{2}, "aa", "**"}, 689 {"aa", []int{3}, "aa", "**"}, 690 {"aa", []int{-3, 0}, "*a", "a*"}, 691 {"aa", []int{0, 1}, "**", "aa"}, // <<< 692 {"aa", []int{1, 2}, "a*", "*a"}, 693 {"aa", []int{-1, -2}, "**", "aa"}, // <<< 694 {"aa", []int{-2, -3}, "*a", "a*"}, 695 {"aa", []int{0, -1}, "**", "aa"}, // <<< 696 697 {"aaa", []int{}, "aaa", "***"}, 698 {"aaa", []int{0}, "*aa", "a**"}, 699 {"aaa", []int{1}, "a*a", "*a*"}, 700 {"aaa", []int{2}, "aa*", "**a"}, 701 {"aaa", []int{-1}, "aa*", "**a"}, 702 {"aaa", []int{-2}, "a*a", "*a*"}, 703 {"aaa", []int{-3}, "*aa", "a**"}, 704 {"aaa", []int{0, 1}, "**a", "aa*"}, 705 {"aaa", []int{-1, -3}, "*a*", "a*a"}, 706 {"aaa", []int{1, -1}, "a**", "*aa"}, 707 708 {"pwd123abcpwd", []int{3, 4, 5, 6, 7, 8, 20}, "pwd******pwd", "***123abc***"}, 709 {"pwd123abcpwd", []int{0, 1, 2, 9, 10, 11, 20}, "***123abc***", "pwd******pwd"}, 710 {"pwd123abcpwd", []int{-3, -4, -5, -6, -7, -8, -20}, "pwd1******wd", "****23abcp**"}, 711 {"pwd123abcpwd", []int{0, -1, -2, -9, -10, -11, -20}, "****23abcp**", "pwd1******wd"}, 712 } { 713 xtesting.Equal(t, MaskToken(tc.giveString, '*', tc.giveIndices...), tc.want) 714 xtesting.Equal(t, MaskTokenR(tc.giveString, '*', tc.giveIndices...), tc.wantR) 715 xtesting.Equal(t, StringMaskToken(tc.giveString, "#$%", tc.giveIndices...), strings.ReplaceAll(tc.want, "*", "#$%")) 716 xtesting.Equal(t, StringMaskTokenR(tc.giveString, "#$%", tc.giveIndices...), strings.ReplaceAll(tc.wantR, "*", "#$%")) 717 } 718 } 719 720 func TestEncodeUrlValues(t *testing.T) { 721 for _, tc := range []struct { 722 give map[string][]string 723 giveEscapeFunc func(string) string 724 want string 725 }{ 726 {map[string][]string{}, nil, ""}, 727 {map[string][]string{"a": {}}, nil, ""}, 728 {map[string][]string{"a": {""}}, nil, "a="}, 729 {map[string][]string{"": {"a"}}, nil, "=a"}, 730 {map[string][]string{"a": {"", "", ""}}, nil, "a=&a=&a="}, 731 732 {map[string][]string{"a": {"b"}, "c": {}}, nil, "a=b"}, 733 {map[string][]string{"a": {"b"}, "c": {"d"}}, nil, "a=b&c=d"}, 734 {map[string][]string{"c": {"e", "d"}, "a": {"b"}}, nil, "a=b&c=e&c=d"}, 735 {map[string][]string{"a": {"a1", "a2", "a3"}, "b": {"b1", "b2", "b3"}}, nil, "a=a1&a=a2&a=a3&b=b1&b=b2&b=b3"}, 736 737 {map[string][]string{"q": {"a+b"}, "order": {"-true"}, "%": {"?"}}, url.QueryEscape, "%25=%3F&order=-true&q=a%2Bb"}, 738 {map[string][]string{"test": {"测试", "テス", "тест"}}, url.QueryEscape, "test=%E6%B5%8B%E8%AF%95&test=%E3%83%86%E3%82%B9&test=%D1%82%D0%B5%D1%81%D1%82"}, 739 {map[string][]string{"q": {"a+b"}, "order": {"-true"}, "%": {"?"}}, url.PathEscape, "%25=%3F&order=-true&q=a+b"}, 740 {map[string][]string{"test": {"测试", "テス", "тест"}}, url.PathEscape, "test=%E6%B5%8B%E8%AF%95&test=%E3%83%86%E3%82%B9&test=%D1%82%D0%B5%D1%81%D1%82"}, 741 {map[string][]string{"a": {"b"}, "c": {"d"}}, func(s string) string { return "?" }, "?=?&?=?"}, 742 } { 743 xtesting.Equal(t, EncodeUrlValues(tc.give, tc.giveEscapeFunc), tc.want) 744 } 745 } 746 747 func TestSplitAndGet(t *testing.T) { 748 for _, tc := range []struct { 749 give string 750 giveSep string 751 giveIndex int 752 want string 753 wantPanic bool 754 }{ 755 {"", "", 0, "", true}, 756 {"", "", 1, "", true}, 757 {"", "", -1, "", true}, 758 {" ", "", 0, " ", false}, 759 {" ", "", -1, " ", false}, 760 761 {"a b", "", 0, "a", false}, 762 {"a b", "", 1, " ", false}, 763 {"a b", "", 2, "b", false}, 764 {"a b", "", 3, "", true}, 765 {"a b", "", -1, "b", false}, 766 {"a b", "", -2, " ", false}, 767 {"a b", "", -3, "a", false}, 768 {"a b", "", -4, "", true}, 769 770 {"a b", " ", 0, "a", false}, 771 {"a b", " ", 1, "b", false}, 772 {"a b", " ", 2, "", true}, 773 {"a b", " ", -1, "b", false}, 774 {"a b", " ", -2, "a", false}, 775 {"a b", " ", -3, "", true}, 776 } { 777 if tc.wantPanic { 778 xtesting.Panic(t, func() { SplitAndGet(tc.give, tc.giveSep, tc.giveIndex) }) 779 } else { 780 xtesting.Equal(t, SplitAndGet(tc.give, tc.giveSep, tc.giveIndex), tc.want) 781 } 782 } 783 } 784 785 func TestStringSliceToStringMap(t *testing.T) { 786 type Map = map[string]string 787 for _, tc := range []struct { 788 give []string 789 want Map 790 }{ 791 {nil, Map{}}, 792 {[]string{}, Map{}}, 793 {[]string{""}, Map{}}, 794 {[]string{"xxx"}, Map{}}, 795 796 {[]string{"a", "b"}, Map{"a": "b"}}, 797 {[]string{"a", "b", "c"}, Map{"a": "b"}}, 798 {[]string{"a", "", "b", "c", "d"}, Map{"a": "", "b": "c"}}, 799 {[]string{"a", "", "a", "b", "c"}, Map{"a": "b"}}, 800 {[]string{"", "", "", " ", " ", "", "x"}, Map{"": " ", " ": ""}}, 801 } { 802 xtesting.Equal(t, StringSliceToMap(tc.give), tc.want) 803 } 804 } 805 806 func TestSliceToStringMap(t *testing.T) { 807 type Map = map[string]interface{} 808 for _, tc := range []struct { 809 give []interface{} 810 want Map 811 }{ 812 {nil, Map{}}, 813 {[]interface{}{}, Map{}}, 814 {[]interface{}{1}, Map{}}, 815 {[]interface{}{nil}, Map{}}, 816 817 {[]interface{}{"1", 2}, Map{"1": 2}}, 818 {[]interface{}{1, uint32(2)}, Map{"1": uint32(2)}}, 819 {[]interface{}{uint(1), 2.3}, Map{"1": 2.3}}, 820 {[]interface{}{true, 2i}, Map{"true": 2i}}, 821 {[]interface{}{1 + 2i, false}, Map{"(1+2i)": false}}, 822 {[]interface{}{[]byte("key"), []byte("value")}, Map{"key": []byte("value")}}, 823 824 {[]interface{}{nil, 2}, Map{}}, 825 {[]interface{}{1, 2, 3}, Map{"1": 2}}, 826 {[]interface{}{nil, 2, 3}, Map{"2": 3}}, 827 {[]interface{}{1, 2, nil, 3, 4}, Map{"1": 2, "3": 4}}, 828 {[]interface{}{1, 2, 1, 3, 1, 4, 2, 3}, Map{"1": 4, "2": 3}}, 829 {[]interface{}{1, "2", []byte("3"), 4.4}, Map{"1": "2", "3": 4.4}}, 830 {[]interface{}{true, 2, 3.3, true}, Map{"true": 2, "3.3": true}}, 831 } { 832 xtesting.Equal(t, SliceToStringMap(tc.give), tc.want) 833 } 834 } 835 836 func TestSemanticVersion(t *testing.T) { 837 for _, tc := range []struct { 838 give string 839 wantP1 uint64 840 wantP2 uint64 841 wantP3 uint64 842 wantError bool 843 }{ 844 {"", 0, 0, 0, true}, 845 {".1", 0, 0, 0, true}, 846 {"v", 0, 0, 0, true}, 847 {"vw", 0, 0, 0, true}, 848 {"w1", 0, 0, 0, true}, 849 {"0v", 0, 0, 0, true}, 850 {"0.v", 0, 0, 0, true}, 851 {"0.0.v", 0, 0, 0, true}, 852 {"0v", 0, 0, 0, true}, 853 {"v0.v", 0, 0, 0, true}, 854 {"v0.v.0", 0, 0, 0, true}, 855 856 {"1", 1, 0, 0, false}, 857 {"1.2", 1, 2, 0, false}, 858 {"1.2.3", 1, 2, 3, false}, 859 {"v1", 1, 0, 0, false}, 860 {"v1.2", 1, 2, 0, false}, 861 {"v1.2.3", 1, 3, 3, false}, 862 } { 863 t.Run(tc.give, func(t *testing.T) { 864 p1, p2, p3, err := SemanticVersion(tc.give) 865 xtesting.Equal(t, err != nil, tc.wantError) 866 if err != nil { 867 xtesting.Equal(t, p1, tc.wantP1) 868 xtesting.Equal(t, p2, tc.wantP2) 869 xtesting.Equal(t, p3, tc.wantP3) 870 } 871 }) 872 } 873 }