github.com/searKing/golang/go@v1.2.117/strings/strings_test.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package strings_test 6 7 import ( 8 "testing" 9 "unicode" 10 "unicode/utf8" 11 "unsafe" 12 13 "github.com/searKing/golang/go/strings" 14 ) 15 16 type SliceContainsTest struct { 17 inputSS []string 18 inputTT []string 19 output bool 20 } 21 22 var ( 23 sliceContainsAnyTests = []SliceContainsTest{ 24 { 25 []string{"A", "B", "C", "D"}, 26 nil, 27 true, 28 }, 29 { 30 []string{}, 31 []string{"E"}, 32 false, 33 }, 34 { 35 []string{"A", "B", "C", "D"}, 36 []string{"A"}, 37 true, 38 }, 39 { 40 []string{"A", "B", "C", "D"}, 41 []string{"A", "D"}, 42 true, 43 }, 44 { 45 []string{"A", "B", "C", "D"}, 46 []string{"A", "E"}, 47 true, 48 }, 49 { 50 []string{"A", "B", "C", "D"}, 51 []string{"E", "A"}, 52 true, 53 }, 54 { 55 []string{"A", "B", "C", "D"}, 56 []string{"E"}, 57 false, 58 }, 59 } 60 ) 61 62 func TestSliceContainsAny(t *testing.T) { 63 for n, test := range sliceContainsAnyTests { 64 out := strings.SliceContainsAny(test.inputSS, test.inputTT...) 65 if out != test.output { 66 t.Errorf("#%d: got %v; expected %v", n, out, test.output) 67 } 68 } 69 } 70 71 var ( 72 sliceContainsTests = []SliceContainsTest{ 73 { 74 []string{"A", "B", "C", "D"}, 75 nil, 76 true, 77 }, 78 { 79 []string{"A", "B", "C", "D"}, 80 []string{"A"}, 81 true, 82 }, 83 { 84 []string{"A", "B", "C", "D"}, 85 []string{"A", "D"}, 86 true, 87 }, 88 { 89 []string{"A", "B", "C", "D"}, 90 []string{"A", "E"}, 91 false, 92 }, 93 { 94 []string{"A", "B", "C", "D"}, 95 []string{"E", "A"}, 96 false, 97 }, 98 { 99 []string{"A", "B", "C", "D"}, 100 []string{"E"}, 101 false, 102 }, 103 } 104 ) 105 106 func TestSliceContains(t *testing.T) { 107 for n, test := range sliceContainsTests { 108 out := strings.SliceContains(test.inputSS, test.inputTT...) 109 if out != test.output { 110 t.Errorf("#%d: got %v; expected %v", n, out, test.output) 111 } 112 } 113 } 114 115 func tenRunes(ch rune) string { 116 r := make([]rune, 10) 117 for i := range r { 118 r[i] = ch 119 } 120 return string(r) 121 } 122 123 func leadingTenRunes(lead, ch rune) string { 124 r := make([]rune, 10) 125 for i := range r { 126 if i == 0 { 127 if lead < 0 { 128 continue 129 } 130 r[i] = lead 131 continue 132 } 133 if ch < 0 { 134 continue 135 } 136 r[i] = ch 137 } 138 return string(r) 139 } 140 141 // User-defined self-inverse mapping function 142 func rot13(r rune) rune { 143 step := rune(13) 144 if r >= 'a' && r <= 'z' { 145 return ((r - 'a' + step) % 26) + 'a' 146 } 147 if r >= 'A' && r <= 'Z' { 148 return ((r - 'A' + step) % 26) + 'A' 149 } 150 return r 151 } 152 153 func TestMapLeading(t *testing.T) { 154 // Run a couple of awful growth/shrinkage tests 155 a := tenRunes('a') 156 // 1. Grow. This triggers two reallocations in Map. 157 maxRune := func(rune) rune { return unicode.MaxRune } 158 m := strings.MapLeading(maxRune, a) 159 expect := leadingTenRunes(unicode.MaxRune, 'a') 160 if m != expect { 161 t.Errorf("growing: expected %q got %q", expect, m) 162 } 163 164 // 2. Shrink 165 minRune := func(rune) rune { return 'a' } 166 m = strings.MapLeading(minRune, leadingTenRunes(unicode.MaxRune, 'a')) 167 expect = a 168 if m != expect { 169 t.Errorf("shrinking: expected %q got %q", expect, m) 170 } 171 172 // 3. Rot13 173 m = strings.MapLeading(rot13, "a to zed") 174 expect = "n to zed" 175 if m != expect { 176 t.Errorf("rot13: expected %q got %q", expect, m) 177 } 178 179 // 4. Rot13^2 180 m = strings.MapLeading(rot13, strings.MapLeading(rot13, "a to zed")) 181 expect = "a to zed" 182 if m != expect { 183 t.Errorf("rot13: expected %q got %q", expect, m) 184 } 185 186 // 5. Drop 187 dropNotLatin := func(r rune) rune { 188 if unicode.Is(unicode.Latin, r) { 189 return r 190 } 191 return -1 192 } 193 m = strings.MapLeading(dropNotLatin, "세계, Hello") 194 expect = "계, Hello" 195 if m != expect { 196 t.Errorf("drop: expected %q got %q", expect, m) 197 } 198 199 // 6. Identity 200 identity := func(r rune) rune { 201 return r 202 } 203 orig := "Input string that we expect not to be copied." 204 m = strings.MapLeading(identity, orig) 205 if unsafe.StringData(orig) != unsafe.StringData(m) { 206 t.Error("unexpected copy during identity map") 207 } 208 209 // 7. Handle invalid UTF-8 sequence 210 replaceNotLatin := func(r rune) rune { 211 if unicode.Is(unicode.Latin, r) { 212 return r 213 } 214 return utf8.RuneError 215 } 216 m = strings.MapLeading(replaceNotLatin, "中 Hello\255World") 217 expect = "\uFFFD Hello\255World" 218 if m != expect { 219 t.Errorf("replace invalid sequence: expected %q got %q", expect, m) 220 } 221 222 // 8. Check utf8.RuneSelf and utf8.MaxRune encoding 223 encode := func(r rune) rune { 224 switch r { 225 case utf8.RuneSelf: 226 return unicode.MaxRune 227 case unicode.MaxRune: 228 return utf8.RuneSelf 229 } 230 return r 231 } 232 s := string(rune(utf8.RuneSelf)) + string(utf8.MaxRune) 233 r := string(utf8.MaxRune) + string(utf8.MaxRune) // reverse of s 234 m = strings.MapLeading(encode, s) 235 if m != r { 236 t.Errorf("encoding not handled correctly: expected %q got %q", r, m) 237 } 238 m = strings.MapLeading(encode, r) 239 if m != s { 240 t.Errorf("encoding not handled correctly: expected %q got %q", s, m) 241 } 242 243 // 9. Check mapping occurs in the front, middle and back 244 trimSpaces := func(r rune) rune { 245 if unicode.IsSpace(r) { 246 return -1 247 } 248 return r 249 } 250 m = strings.MapLeading(trimSpaces, " abc 123 ") 251 expect = " abc 123 " 252 if m != expect { 253 t.Errorf("trimSpaces: expected %q got %q", expect, m) 254 } 255 } 256 257 func TestContainsAsciiVisual(t *testing.T) { 258 table := []struct { 259 Q string 260 R bool 261 }{ 262 { 263 Q: string(rune(0x00)), 264 R: false, 265 }, 266 { 267 Q: " ", 268 R: false, 269 }, 270 { 271 Q: "!", 272 R: true, 273 }, 274 { 275 Q: `"`, 276 R: true, 277 }, 278 { 279 Q: "0", 280 R: true, 281 }, 282 { 283 Q: ":", 284 R: true, 285 }, 286 { 287 Q: "A", 288 R: true, 289 }, 290 { 291 Q: "{", 292 R: true, 293 }, 294 { 295 Q: "~", 296 R: true, 297 }, 298 { 299 Q: string(rune(0xFF)), 300 R: false, 301 }, 302 } 303 304 for i, test := range table { 305 qr := strings.ContainsAsciiVisual(test.Q) 306 if qr != test.R { 307 t.Errorf("#%d. got %t, want %t", i, qr, test.R) 308 } 309 } 310 } 311 312 func TestContainsOnlyAsciiVisual(t *testing.T) { 313 table := []struct { 314 Q string 315 R bool 316 }{ 317 //{ 318 // Q: "123qwe<>?+_{", 319 // R: true, 320 //}, 321 { 322 Q: string(rune(0x00)) + "a", 323 R: false, 324 }, 325 { 326 Q: string(rune(0xFF)) + "a", 327 R: false, 328 }, 329 } 330 331 for i, test := range table { 332 qr := strings.ContainsOnlyAsciiVisual(test.Q) 333 if qr != test.R { 334 t.Errorf("#%d. got %t, want %t", i, qr, test.R) 335 } 336 } 337 } 338 339 func TestJoinRepeat(t *testing.T) { 340 table := []struct { 341 Q string 342 sep string 343 n int 344 R string 345 }{ 346 { 347 Q: "a", 348 sep: ",", 349 n: -1, 350 R: "", 351 }, 352 { 353 Q: "a", 354 sep: ",", 355 n: 0, 356 R: "", 357 }, 358 { 359 Q: "a", 360 sep: ",", 361 n: 1, 362 R: "a", 363 }, 364 { 365 Q: "a", 366 sep: ",", 367 n: 10, 368 R: "a,a,a,a,a,a,a,a,a,a", 369 }, 370 } 371 372 for i, test := range table { 373 qr := strings.JoinRepeat(test.Q, test.sep, test.n) 374 if qr != test.R { 375 t.Errorf("#%d. got %q, want %q", i, qr, test.R) 376 } 377 } 378 } 379 380 func TestPadLeft(t *testing.T) { 381 table := []struct { 382 Q string 383 pad string 384 n int 385 R string 386 }{ 387 { 388 Q: "a", 389 pad: "*", 390 n: -1, 391 R: "a", 392 }, 393 { 394 Q: "a", 395 pad: "*", 396 n: 10, 397 R: "*********a", 398 }, 399 { 400 Q: "a", 401 pad: "*^", 402 n: 5, 403 R: "*^*^a", 404 }, 405 { 406 Q: "a", 407 pad: "*^", 408 n: 6, 409 R: "*^*^ a", 410 }, 411 } 412 413 for i, test := range table { 414 qr := strings.PadLeft(test.Q, test.pad, test.n) 415 if qr != test.R { 416 t.Errorf("#%d. got %q, want %q", i, qr, test.R) 417 } 418 } 419 } 420 421 func TestPadRight(t *testing.T) { 422 table := []struct { 423 Q string 424 pad string 425 n int 426 R string 427 }{ 428 { 429 Q: "a", 430 pad: "*", 431 n: -1, 432 R: "a", 433 }, 434 { 435 Q: "a", 436 pad: "*", 437 n: 1, 438 R: "a", 439 }, 440 { 441 Q: "a", 442 pad: "*", 443 n: 10, 444 R: "a*********", 445 }, 446 { 447 Q: "a", 448 pad: "*^", 449 n: 5, 450 R: "a*^*^", 451 }, 452 { 453 Q: "a", 454 pad: "*^", 455 n: 6, 456 R: "a *^*^", 457 }, 458 } 459 460 for i, test := range table { 461 qr := strings.PadRight(test.Q, test.pad, test.n) 462 if qr != test.R { 463 t.Errorf("#%d. got %q, want %q", i, qr, test.R) 464 } 465 } 466 } 467 468 func TestReverseByByte(t *testing.T) { 469 table := []struct { 470 Q string 471 R string 472 }{ 473 { 474 Q: "abc123", 475 R: "321cba", 476 }, 477 { 478 Q: "Hello, 世界", 479 R: "\x8c\x95疸\xe4 ,olleH", 480 }, 481 } 482 483 for i, test := range table { 484 qr := strings.ReverseByByte(test.Q) 485 if qr != test.R { 486 t.Errorf("#%d. got %q, want %q", i, qr, test.R) 487 } 488 } 489 } 490 491 func TestReverseByRune(t *testing.T) { 492 table := []struct { 493 Q string 494 R string 495 }{ 496 { 497 Q: "abc123", 498 R: "321cba", 499 }, 500 { 501 Q: "Hello, 世界", 502 R: "界世 ,olleH", 503 }, 504 } 505 506 for i, test := range table { 507 qr := strings.ReverseByRune(test.Q) 508 if qr != test.R { 509 t.Errorf("#%d. got %q, want %q", i, qr, test.R) 510 } 511 } 512 } 513 514 func TestCountPrefix(t *testing.T) { 515 table := []struct { 516 Q string 517 p string 518 R int 519 }{ 520 { 521 Q: "abc123", 522 p: "a", 523 R: 1, 524 }, 525 { 526 Q: "世界, Hello", 527 p: "世界", 528 R: 1, 529 }, 530 { 531 Q: "aaaabc123", 532 p: "a", 533 R: 4, 534 }, 535 { 536 Q: "aaaabc123", 537 p: "aa", 538 R: 2, 539 }, 540 { 541 Q: "aaaabc123", 542 p: "aaa", 543 R: 1, 544 }, 545 { 546 Q: "aaaabc123", 547 p: "aaaa", 548 R: 1, 549 }, 550 { 551 Q: "aaaabc123", 552 p: "aaaaa", 553 R: 0, 554 }, 555 } 556 557 for i, test := range table { 558 qr := strings.CountPrefix(test.Q, test.p) 559 if qr != test.R { 560 t.Errorf("#%d. got %d, want %d", i, qr, test.R) 561 } 562 } 563 } 564 565 func TestCountSuffix(t *testing.T) { 566 table := []struct { 567 Q string 568 p string 569 R int 570 }{ 571 { 572 Q: "abc123", 573 p: "3", 574 R: 1, 575 }, 576 { 577 Q: "Hello, 世界", 578 p: "世界", 579 R: 1, 580 }, 581 { 582 Q: "abc123333", 583 p: "3", 584 R: 4, 585 }, 586 { 587 Q: "abc123333", 588 p: "33", 589 R: 2, 590 }, 591 { 592 Q: "abc123333", 593 p: "333", 594 R: 1, 595 }, 596 { 597 Q: "abc123333", 598 p: "3333", 599 R: 1, 600 }, 601 { 602 Q: "abc123333", 603 p: "33333", 604 R: 0, 605 }, 606 } 607 608 for i, test := range table { 609 qr := strings.CountSuffix(test.Q, test.p) 610 if qr != test.R { 611 t.Errorf("#%d. got %d, want %d", i, qr, test.R) 612 } 613 } 614 }