github.com/songzhibin97/gkit@v1.2.13/tools/match/match_test.go (about) 1 package match 2 3 import ( 4 "fmt" 5 "math/rand" 6 "strings" 7 "testing" 8 "time" 9 "unicode/utf8" 10 ) 11 12 func TestMatch(t *testing.T) { 13 if !Match("hello world", "hello world") { 14 t.Fatal("fail") 15 } 16 if Match("hello world", "jello world") { 17 t.Fatal("fail") 18 } 19 if !Match("hello world", "hello*") { 20 t.Fatal("fail") 21 } 22 if Match("hello world", "jello*") { 23 t.Fatal("fail") 24 } 25 if !Match("hello world", "hello?world") { 26 t.Fatal("fail") 27 } 28 if Match("hello world", "jello?world") { 29 t.Fatal("fail") 30 } 31 if !Match("hello world", "he*o?world") { 32 t.Fatal("fail") 33 } 34 if !Match("hello world", "he*o?wor*") { 35 t.Fatal("fail") 36 } 37 if !Match("hello world", "he*o?*r*") { 38 t.Fatal("fail") 39 } 40 if !Match("的情况下解析一个", "*") { 41 t.Fatal("fail") 42 } 43 if !Match("的情况下解析一个", "*况下*") { 44 t.Fatal("fail") 45 } 46 if !Match("的情况下解析一个", "*况?*") { 47 t.Fatal("fail") 48 } 49 if !Match("的情况下解析一个", "的情况?解析一个") { 50 t.Fatal("fail") 51 } 52 } 53 54 // TestWildcardMatch - Tests validate the logic of wild card matching. 55 // `WildcardMatch` supports '*' and '?' wildcards. 56 // Sample usage: In resource matching for folder policy validation. 57 func TestWildcardMatch(t *testing.T) { 58 testCases := []struct { 59 pattern string 60 text string 61 matched bool 62 }{ 63 // Test case - 1. 64 // Test case with pattern containing key name with a prefix. Should accept the same text without a "*". 65 { 66 pattern: "my-folder/oo*", 67 text: "my-folder/oo", 68 matched: true, 69 }, 70 // Test case - 2. 71 // Test case with "*" at the end of the pattern. 72 { 73 pattern: "my-folder/In*", 74 text: "my-folder/India/Karnataka/", 75 matched: true, 76 }, 77 // Test case - 3. 78 // Test case with prefixes shuffled. 79 // This should fail. 80 { 81 pattern: "my-folder/In*", 82 text: "my-folder/Karnataka/India/", 83 matched: false, 84 }, 85 // Test case - 4. 86 // Test case with text expanded to the wildcards in the pattern. 87 { 88 pattern: "my-folder/In*/Ka*/Ban", 89 text: "my-folder/India/Karnataka/Ban", 90 matched: true, 91 }, 92 // Test case - 5. 93 // Test case with the keyname part is repeated as prefix several times. 94 // This is valid. 95 { 96 pattern: "my-folder/In*/Ka*/Ban", 97 text: "my-folder/India/Karnataka/Ban/Ban/Ban/Ban/Ban", 98 matched: true, 99 }, 100 // Test case - 6. 101 // Test case to validate that `*` can be expanded into multiple prefixes. 102 { 103 pattern: "my-folder/In*/Ka*/Ban", 104 text: "my-folder/India/Karnataka/Area1/Area2/Area3/Ban", 105 matched: true, 106 }, 107 // Test case - 7. 108 // Test case to validate that `*` can be expanded into multiple prefixes. 109 { 110 pattern: "my-folder/In*/Ka*/Ban", 111 text: "my-folder/India/State1/State2/Karnataka/Area1/Area2/Area3/Ban", 112 matched: true, 113 }, 114 // Test case - 8. 115 // Test case where the keyname part of the pattern is expanded in the text. 116 { 117 pattern: "my-folder/In*/Ka*/Ban", 118 text: "my-folder/India/Karnataka/Bangalore", 119 matched: false, 120 }, 121 // Test case - 9. 122 // Test case with prefixes and wildcard expanded for all "*". 123 { 124 pattern: "my-folder/In*/Ka*/Ban*", 125 text: "my-folder/India/Karnataka/Bangalore", 126 matched: true, 127 }, 128 // Test case - 10. 129 // Test case with keyname part being a wildcard in the pattern. 130 { 131 pattern: "my-folder/*", 132 text: "my-folder/India", 133 matched: true, 134 }, 135 // Test case - 11. 136 { 137 pattern: "my-folder/oo*", 138 text: "my-folder/odo", 139 matched: false, 140 }, 141 142 // Test case with pattern containing wildcard '?'. 143 // Test case - 12. 144 // "my-folder?/" matches "my-folder1/", "my-folder2/", "my-folder3" etc... 145 // doesn't match "myfolder/". 146 { 147 pattern: "my-folder?/abc*", 148 text: "myfolder/abc", 149 matched: false, 150 }, 151 // Test case - 13. 152 { 153 pattern: "my-folder?/abc*", 154 text: "my-folder1/abc", 155 matched: true, 156 }, 157 // Test case - 14. 158 { 159 pattern: "my-?-folder/abc*", 160 text: "my--folder/abc", 161 matched: false, 162 }, 163 // Test case - 15. 164 { 165 pattern: "my-?-folder/abc*", 166 text: "my-1-folder/abc", 167 matched: true, 168 }, 169 // Test case - 16. 170 { 171 pattern: "my-?-folder/abc*", 172 text: "my-k-folder/abc", 173 matched: true, 174 }, 175 // Test case - 17. 176 { 177 pattern: "my??folder/abc*", 178 text: "myfolder/abc", 179 matched: false, 180 }, 181 // Test case - 18. 182 { 183 pattern: "my??folder/abc*", 184 text: "my4afolder/abc", 185 matched: true, 186 }, 187 // Test case - 19. 188 { 189 pattern: "my-folder?abc*", 190 text: "my-folder/abc", 191 matched: true, 192 }, 193 // Test case 20-21. 194 // '?' matches '/' too. (works with s3). 195 // This is because the namespace is considered flat. 196 // "abc?efg" matches both "abcdefg" and "abc/efg". 197 { 198 pattern: "my-folder/abc?efg", 199 text: "my-folder/abcdefg", 200 matched: true, 201 }, 202 { 203 pattern: "my-folder/abc?efg", 204 text: "my-folder/abc/efg", 205 matched: true, 206 }, 207 // Test case - 22. 208 { 209 pattern: "my-folder/abc????", 210 text: "my-folder/abc", 211 matched: false, 212 }, 213 // Test case - 23. 214 { 215 pattern: "my-folder/abc????", 216 text: "my-folder/abcde", 217 matched: false, 218 }, 219 // Test case - 24. 220 { 221 pattern: "my-folder/abc????", 222 text: "my-folder/abcdefg", 223 matched: true, 224 }, 225 // Test case 25-26. 226 // test case with no '*'. 227 { 228 pattern: "my-folder/abc?", 229 text: "my-folder/abc", 230 matched: false, 231 }, 232 { 233 pattern: "my-folder/abc?", 234 text: "my-folder/abcd", 235 matched: true, 236 }, 237 { 238 pattern: "my-folder/abc?", 239 text: "my-folder/abcde", 240 matched: false, 241 }, 242 // Test case 27. 243 { 244 pattern: "my-folder/mnop*?", 245 text: "my-folder/mnop", 246 matched: false, 247 }, 248 // Test case 28. 249 { 250 pattern: "my-folder/mnop*?", 251 text: "my-folder/mnopqrst/mnopqr", 252 matched: true, 253 }, 254 // Test case 29. 255 { 256 pattern: "my-folder/mnop*?", 257 text: "my-folder/mnopqrst/mnopqrs", 258 matched: true, 259 }, 260 // Test case 30. 261 { 262 pattern: "my-folder/mnop*?", 263 text: "my-folder/mnop", 264 matched: false, 265 }, 266 // Test case 31. 267 { 268 pattern: "my-folder/mnop*?", 269 text: "my-folder/mnopq", 270 matched: true, 271 }, 272 // Test case 32. 273 { 274 pattern: "my-folder/mnop*?", 275 text: "my-folder/mnopqr", 276 matched: true, 277 }, 278 // Test case 33. 279 { 280 pattern: "my-folder/mnop*?and", 281 text: "my-folder/mnopqand", 282 matched: true, 283 }, 284 // Test case 34. 285 { 286 pattern: "my-folder/mnop*?and", 287 text: "my-folder/mnopand", 288 matched: false, 289 }, 290 // Test case 35. 291 { 292 pattern: "my-folder/mnop*?and", 293 text: "my-folder/mnopqand", 294 matched: true, 295 }, 296 // Test case 36. 297 { 298 pattern: "my-folder/mnop*?", 299 text: "my-folder/mn", 300 matched: false, 301 }, 302 // Test case 37. 303 { 304 pattern: "my-folder/mnop*?", 305 text: "my-folder/mnopqrst/mnopqrs", 306 matched: true, 307 }, 308 // Test case 38. 309 { 310 pattern: "my-folder/mnop*??", 311 text: "my-folder/mnopqrst", 312 matched: true, 313 }, 314 // Test case 39. 315 { 316 pattern: "my-folder/mnop*qrst", 317 text: "my-folder/mnopabcdegqrst", 318 matched: true, 319 }, 320 // Test case 40. 321 { 322 pattern: "my-folder/mnop*?and", 323 text: "my-folder/mnopqand", 324 matched: true, 325 }, 326 // Test case 41. 327 { 328 pattern: "my-folder/mnop*?and", 329 text: "my-folder/mnopand", 330 matched: false, 331 }, 332 // Test case 42. 333 { 334 pattern: "my-folder/mnop*?and?", 335 text: "my-folder/mnopqanda", 336 matched: true, 337 }, 338 // Test case 43. 339 { 340 pattern: "my-folder/mnop*?and", 341 text: "my-folder/mnopqanda", 342 matched: false, 343 }, 344 // Test case 44. 345 346 { 347 pattern: "my-?-folder/abc*", 348 text: "my-folder/mnopqanda", 349 matched: false, 350 }, 351 } 352 // Iterating over the test cases, call the function under test and asert the output. 353 for i, testCase := range testCases { 354 actualResult := Match(testCase.text, testCase.pattern) 355 if testCase.matched != actualResult { 356 t.Errorf("Test %d: Expected the result to be `%v`, but instead found it to be `%v`", i+1, testCase.matched, actualResult) 357 } 358 } 359 } 360 361 func TestRandomInput(t *testing.T) { 362 rand.Seed(time.Now().UnixNano()) 363 b1 := make([]byte, 100) 364 b2 := make([]byte, 100) 365 for i := 0; i < 1000000; i++ { 366 if _, err := rand.Read(b1); err != nil { 367 t.Fatal(err) 368 } 369 if _, err := rand.Read(b2); err != nil { 370 t.Fatal(err) 371 } 372 Match(string(b1), string(b2)) 373 } 374 } 375 376 func testAllowable(pattern, exmin, exmax string) error { 377 min, max := Allowable(pattern) 378 if min != exmin || max != exmax { 379 return fmt.Errorf("expected '%v'/'%v', got '%v'/'%v'", 380 exmin, exmax, min, max) 381 } 382 return nil 383 } 384 385 func TestAllowable(t *testing.T) { 386 if err := testAllowable("hell*", "hell", "helm"); err != nil { 387 t.Fatal(err) 388 } 389 if err := testAllowable("hell?", "hell"+string(rune(0)), "hell"+string(utf8.MaxRune)); err != nil { 390 t.Fatal(err) 391 } 392 if err := testAllowable("h解析ell*", "h解析ell", "h解析elm"); err != nil { 393 t.Fatal(err) 394 } 395 if err := testAllowable("h解*ell*", "h解", "h觤"); err != nil { 396 t.Fatal(err) 397 } 398 } 399 400 func TestIsPattern(t *testing.T) { 401 patterns := []string{ 402 "*", "hello*", "hello*world", "*world", 403 "?", "hello?", "hello?world", "?world", 404 } 405 nonPatterns := []string{ 406 "", "hello", 407 } 408 for _, pattern := range patterns { 409 if !IsPattern(pattern) { 410 t.Fatalf("expected true") 411 } 412 } 413 414 for _, s := range nonPatterns { 415 if IsPattern(s) { 416 t.Fatalf("expected false") 417 } 418 } 419 } 420 421 func BenchmarkAscii(t *testing.B) { 422 for i := 0; i < t.N; i++ { 423 if !Match("hello", "hello") { 424 t.Fatal("fail") 425 } 426 } 427 } 428 429 func BenchmarkUnicode(t *testing.B) { 430 for i := 0; i < t.N; i++ { 431 if !Match("h情llo", "h情llo") { 432 t.Fatal("fail") 433 } 434 } 435 } 436 437 func TestLotsStars(t *testing.T) { 438 // This tests that a pattern with lots of stars will complete quickly. 439 var str, pat string 440 441 str = `,**,,**,**,**,**,**,**,` 442 pat = `,**********************************************{**",**,,**,**,` + 443 `**,**,"",**,**,**,**,**,**,**,**,**,**]` 444 Match(pat, str) 445 446 str = strings.Replace(str, ",", "情", -1) 447 pat = strings.Replace(pat, ",", "情", -1) 448 Match(pat, str) 449 }