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