storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/wildcard/match_test.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2015, 2016 MinIO, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package wildcard_test 18 19 import ( 20 "testing" 21 22 "storj.io/minio/pkg/wildcard" 23 ) 24 25 // TestMatch - Tests validate the logic of wild card matching. 26 // `Match` supports '*' and '?' wildcards. 27 // Sample usage: In resource matching for bucket policy validation. 28 func TestMatch(t *testing.T) { 29 testCases := []struct { 30 pattern string 31 text string 32 matched bool 33 }{ 34 // Test case - 1. 35 // Test case with pattern "*". Expected to match any text. 36 { 37 pattern: "*", 38 text: "s3:GetObject", 39 matched: true, 40 }, 41 // Test case - 2. 42 // Test case with empty pattern. This only matches empty string. 43 { 44 pattern: "", 45 text: "s3:GetObject", 46 matched: false, 47 }, 48 // Test case - 3. 49 // Test case with empty pattern. This only matches empty string. 50 { 51 pattern: "", 52 text: "", 53 matched: true, 54 }, 55 // Test case - 4. 56 // Test case with single "*" at the end. 57 { 58 pattern: "s3:*", 59 text: "s3:ListMultipartUploadParts", 60 matched: true, 61 }, 62 // Test case - 5. 63 // Test case with a no "*". In this case the pattern and text should be the same. 64 { 65 pattern: "s3:ListBucketMultipartUploads", 66 text: "s3:ListBucket", 67 matched: false, 68 }, 69 // Test case - 6. 70 // Test case with a no "*". In this case the pattern and text should be the same. 71 { 72 pattern: "s3:ListBucket", 73 text: "s3:ListBucket", 74 matched: true, 75 }, 76 // Test case - 7. 77 // Test case with a no "*". In this case the pattern and text should be the same. 78 { 79 pattern: "s3:ListBucketMultipartUploads", 80 text: "s3:ListBucketMultipartUploads", 81 matched: true, 82 }, 83 // Test case - 8. 84 // Test case with pattern containing key name with a prefix. Should accept the same text without a "*". 85 { 86 pattern: "my-bucket/oo*", 87 text: "my-bucket/oo", 88 matched: true, 89 }, 90 // Test case - 9. 91 // Test case with "*" at the end of the pattern. 92 { 93 pattern: "my-bucket/In*", 94 text: "my-bucket/India/Karnataka/", 95 matched: true, 96 }, 97 // Test case - 10. 98 // Test case with prefixes shuffled. 99 // This should fail. 100 { 101 pattern: "my-bucket/In*", 102 text: "my-bucket/Karnataka/India/", 103 matched: false, 104 }, 105 // Test case - 11. 106 // Test case with text expanded to the wildcards in the pattern. 107 { 108 pattern: "my-bucket/In*/Ka*/Ban", 109 text: "my-bucket/India/Karnataka/Ban", 110 matched: true, 111 }, 112 // Test case - 12. 113 // Test case with the keyname part is repeated as prefix several times. 114 // This is valid. 115 { 116 pattern: "my-bucket/In*/Ka*/Ban", 117 text: "my-bucket/India/Karnataka/Ban/Ban/Ban/Ban/Ban", 118 matched: true, 119 }, 120 // Test case - 13. 121 // Test case to validate that `*` can be expanded into multiple prefixes. 122 { 123 pattern: "my-bucket/In*/Ka*/Ban", 124 text: "my-bucket/India/Karnataka/Area1/Area2/Area3/Ban", 125 matched: true, 126 }, 127 // Test case - 14. 128 // Test case to validate that `*` can be expanded into multiple prefixes. 129 { 130 pattern: "my-bucket/In*/Ka*/Ban", 131 text: "my-bucket/India/State1/State2/Karnataka/Area1/Area2/Area3/Ban", 132 matched: true, 133 }, 134 // Test case - 15. 135 // Test case where the keyname part of the pattern is expanded in the text. 136 { 137 pattern: "my-bucket/In*/Ka*/Ban", 138 text: "my-bucket/India/Karnataka/Bangalore", 139 matched: false, 140 }, 141 // Test case - 16. 142 // Test case with prefixes and wildcard expanded for all "*". 143 { 144 pattern: "my-bucket/In*/Ka*/Ban*", 145 text: "my-bucket/India/Karnataka/Bangalore", 146 matched: true, 147 }, 148 // Test case - 17. 149 // Test case with keyname part being a wildcard in the pattern. 150 { 151 pattern: "my-bucket/*", 152 text: "my-bucket/India", 153 matched: true, 154 }, 155 // Test case - 18. 156 { 157 pattern: "my-bucket/oo*", 158 text: "my-bucket/odo", 159 matched: false, 160 }, 161 162 // Test case with pattern containing wildcard '?'. 163 // Test case - 19. 164 // "my-bucket?/" matches "my-bucket1/", "my-bucket2/", "my-bucket3" etc... 165 // doesn't match "mybucket/". 166 { 167 pattern: "my-bucket?/abc*", 168 text: "mybucket/abc", 169 matched: false, 170 }, 171 // Test case - 20. 172 { 173 pattern: "my-bucket?/abc*", 174 text: "my-bucket1/abc", 175 matched: true, 176 }, 177 // Test case - 21. 178 { 179 pattern: "my-?-bucket/abc*", 180 text: "my--bucket/abc", 181 matched: false, 182 }, 183 // Test case - 22. 184 { 185 pattern: "my-?-bucket/abc*", 186 text: "my-1-bucket/abc", 187 matched: true, 188 }, 189 // Test case - 23. 190 { 191 pattern: "my-?-bucket/abc*", 192 text: "my-k-bucket/abc", 193 matched: true, 194 }, 195 // Test case - 24. 196 { 197 pattern: "my??bucket/abc*", 198 text: "mybucket/abc", 199 matched: false, 200 }, 201 // Test case - 25. 202 { 203 pattern: "my??bucket/abc*", 204 text: "my4abucket/abc", 205 matched: true, 206 }, 207 // Test case - 26. 208 { 209 pattern: "my-bucket?abc*", 210 text: "my-bucket/abc", 211 matched: true, 212 }, 213 // Test case 27-28. 214 // '?' matches '/' too. (works with s3). 215 // This is because the namespace is considered flat. 216 // "abc?efg" matches both "abcdefg" and "abc/efg". 217 { 218 pattern: "my-bucket/abc?efg", 219 text: "my-bucket/abcdefg", 220 matched: true, 221 }, 222 { 223 pattern: "my-bucket/abc?efg", 224 text: "my-bucket/abc/efg", 225 matched: true, 226 }, 227 // Test case - 29. 228 { 229 pattern: "my-bucket/abc????", 230 text: "my-bucket/abc", 231 matched: false, 232 }, 233 // Test case - 30. 234 { 235 pattern: "my-bucket/abc????", 236 text: "my-bucket/abcde", 237 matched: false, 238 }, 239 // Test case - 31. 240 { 241 pattern: "my-bucket/abc????", 242 text: "my-bucket/abcdefg", 243 matched: true, 244 }, 245 // Test case 32-34. 246 // test case with no '*'. 247 { 248 pattern: "my-bucket/abc?", 249 text: "my-bucket/abc", 250 matched: false, 251 }, 252 { 253 pattern: "my-bucket/abc?", 254 text: "my-bucket/abcd", 255 matched: true, 256 }, 257 { 258 pattern: "my-bucket/abc?", 259 text: "my-bucket/abcde", 260 matched: false, 261 }, 262 // Test case 35. 263 { 264 pattern: "my-bucket/mnop*?", 265 text: "my-bucket/mnop", 266 matched: false, 267 }, 268 // Test case 36. 269 { 270 pattern: "my-bucket/mnop*?", 271 text: "my-bucket/mnopqrst/mnopqr", 272 matched: true, 273 }, 274 // Test case 37. 275 { 276 pattern: "my-bucket/mnop*?", 277 text: "my-bucket/mnopqrst/mnopqrs", 278 matched: true, 279 }, 280 // Test case 38. 281 { 282 pattern: "my-bucket/mnop*?", 283 text: "my-bucket/mnop", 284 matched: false, 285 }, 286 // Test case 39. 287 { 288 pattern: "my-bucket/mnop*?", 289 text: "my-bucket/mnopq", 290 matched: true, 291 }, 292 // Test case 40. 293 { 294 pattern: "my-bucket/mnop*?", 295 text: "my-bucket/mnopqr", 296 matched: true, 297 }, 298 // Test case 41. 299 { 300 pattern: "my-bucket/mnop*?and", 301 text: "my-bucket/mnopqand", 302 matched: true, 303 }, 304 // Test case 42. 305 { 306 pattern: "my-bucket/mnop*?and", 307 text: "my-bucket/mnopand", 308 matched: false, 309 }, 310 // Test case 43. 311 { 312 pattern: "my-bucket/mnop*?and", 313 text: "my-bucket/mnopqand", 314 matched: true, 315 }, 316 // Test case 44. 317 { 318 pattern: "my-bucket/mnop*?", 319 text: "my-bucket/mn", 320 matched: false, 321 }, 322 // Test case 45. 323 { 324 pattern: "my-bucket/mnop*?", 325 text: "my-bucket/mnopqrst/mnopqrs", 326 matched: true, 327 }, 328 // Test case 46. 329 { 330 pattern: "my-bucket/mnop*??", 331 text: "my-bucket/mnopqrst", 332 matched: true, 333 }, 334 // Test case 47. 335 { 336 pattern: "my-bucket/mnop*qrst", 337 text: "my-bucket/mnopabcdegqrst", 338 matched: true, 339 }, 340 // Test case 48. 341 { 342 pattern: "my-bucket/mnop*?and", 343 text: "my-bucket/mnopqand", 344 matched: true, 345 }, 346 // Test case 49. 347 { 348 pattern: "my-bucket/mnop*?and", 349 text: "my-bucket/mnopand", 350 matched: false, 351 }, 352 // Test case 50. 353 { 354 pattern: "my-bucket/mnop*?and?", 355 text: "my-bucket/mnopqanda", 356 matched: true, 357 }, 358 // Test case 51. 359 { 360 pattern: "my-bucket/mnop*?and", 361 text: "my-bucket/mnopqanda", 362 matched: false, 363 }, 364 // Test case 52. 365 366 { 367 pattern: "my-?-bucket/abc*", 368 text: "my-bucket/mnopqanda", 369 matched: false, 370 }, 371 } 372 // Iterating over the test cases, call the function under test and asert the output. 373 for i, testCase := range testCases { 374 actualResult := wildcard.Match(testCase.pattern, testCase.text) 375 if testCase.matched != actualResult { 376 t.Errorf("Test %d: Expected the result to be `%v`, but instead found it to be `%v`", i+1, testCase.matched, actualResult) 377 } 378 } 379 } 380 381 // TestMatchSimple - Tests validate the logic of wild card matching. 382 // `MatchSimple` supports matching for only '*' in the pattern string. 383 func TestMatchSimple(t *testing.T) { 384 testCases := []struct { 385 pattern string 386 text string 387 matched bool 388 }{ 389 // Test case - 1. 390 // Test case with pattern "*". Expected to match any text. 391 { 392 pattern: "*", 393 text: "s3:GetObject", 394 matched: true, 395 }, 396 // Test case - 2. 397 // Test case with empty pattern. This only matches empty string. 398 { 399 pattern: "", 400 text: "s3:GetObject", 401 matched: false, 402 }, 403 // Test case - 3. 404 // Test case with empty pattern. This only matches empty string. 405 { 406 pattern: "", 407 text: "", 408 matched: true, 409 }, 410 // Test case - 4. 411 // Test case with single "*" at the end. 412 { 413 pattern: "s3:*", 414 text: "s3:ListMultipartUploadParts", 415 matched: true, 416 }, 417 // Test case - 5. 418 // Test case with a no "*". In this case the pattern and text should be the same. 419 { 420 pattern: "s3:ListBucketMultipartUploads", 421 text: "s3:ListBucket", 422 matched: false, 423 }, 424 // Test case - 6. 425 // Test case with a no "*". In this case the pattern and text should be the same. 426 { 427 pattern: "s3:ListBucket", 428 text: "s3:ListBucket", 429 matched: true, 430 }, 431 // Test case - 7. 432 // Test case with a no "*". In this case the pattern and text should be the same. 433 { 434 pattern: "s3:ListBucketMultipartUploads", 435 text: "s3:ListBucketMultipartUploads", 436 matched: true, 437 }, 438 // Test case - 8. 439 // Test case with pattern containing key name with a prefix. Should accept the same text without a "*". 440 { 441 pattern: "my-bucket/oo*", 442 text: "my-bucket/oo", 443 matched: true, 444 }, 445 // Test case - 9. 446 // Test case with "*" at the end of the pattern. 447 { 448 pattern: "my-bucket/In*", 449 text: "my-bucket/India/Karnataka/", 450 matched: true, 451 }, 452 // Test case - 10. 453 // Test case with prefixes shuffled. 454 // This should fail. 455 { 456 pattern: "my-bucket/In*", 457 text: "my-bucket/Karnataka/India/", 458 matched: false, 459 }, 460 // Test case - 11. 461 // Test case with text expanded to the wildcards in the pattern. 462 { 463 pattern: "my-bucket/In*/Ka*/Ban", 464 text: "my-bucket/India/Karnataka/Ban", 465 matched: true, 466 }, 467 // Test case - 12. 468 // Test case with the keyname part is repeated as prefix several times. 469 // This is valid. 470 { 471 pattern: "my-bucket/In*/Ka*/Ban", 472 text: "my-bucket/India/Karnataka/Ban/Ban/Ban/Ban/Ban", 473 matched: true, 474 }, 475 // Test case - 13. 476 // Test case to validate that `*` can be expanded into multiple prefixes. 477 { 478 pattern: "my-bucket/In*/Ka*/Ban", 479 text: "my-bucket/India/Karnataka/Area1/Area2/Area3/Ban", 480 matched: true, 481 }, 482 // Test case - 14. 483 // Test case to validate that `*` can be expanded into multiple prefixes. 484 { 485 pattern: "my-bucket/In*/Ka*/Ban", 486 text: "my-bucket/India/State1/State2/Karnataka/Area1/Area2/Area3/Ban", 487 matched: true, 488 }, 489 // Test case - 15. 490 // Test case where the keyname part of the pattern is expanded in the text. 491 { 492 pattern: "my-bucket/In*/Ka*/Ban", 493 text: "my-bucket/India/Karnataka/Bangalore", 494 matched: false, 495 }, 496 // Test case - 16. 497 // Test case with prefixes and wildcard expanded for all "*". 498 { 499 pattern: "my-bucket/In*/Ka*/Ban*", 500 text: "my-bucket/India/Karnataka/Bangalore", 501 matched: true, 502 }, 503 // Test case - 17. 504 // Test case with keyname part being a wildcard in the pattern. 505 { 506 pattern: "my-bucket/*", 507 text: "my-bucket/India", 508 matched: true, 509 }, 510 // Test case - 18. 511 { 512 pattern: "my-bucket/oo*", 513 text: "my-bucket/odo", 514 matched: false, 515 }, 516 // Test case - 11. 517 { 518 pattern: "my-bucket/oo?*", 519 text: "my-bucket/oo???", 520 matched: true, 521 }, 522 // Test case - 12: 523 { 524 pattern: "my-bucket/oo??*", 525 text: "my-bucket/odo", 526 matched: false, 527 }, 528 // Test case - 13: 529 { 530 pattern: "?h?*", 531 text: "?h?hello", 532 matched: true, 533 }, 534 } 535 // Iterating over the test cases, call the function under test and asert the output. 536 for i, testCase := range testCases { 537 actualResult := wildcard.MatchSimple(testCase.pattern, testCase.text) 538 if testCase.matched != actualResult { 539 t.Errorf("Test %d: Expected the result to be `%v`, but instead found it to be `%v`", i+1, testCase.matched, actualResult) 540 } 541 } 542 }