Files
rustfs/crates/notify/src/rules/pattern_test.rs
T

167 lines
6.3 KiB
Rust

// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Pattern matching tests for notification filter rules
//!
//! This module contains tests for the pattern matching logic used in
//! bucket notification filters, specifically testing prefix and suffix
//! filter rules as used in S3 bucket notifications.
use super::pattern;
#[cfg(test)]
mod bug_reproduction_tests {
use super::*;
/// Test case from bug report:
/// - Prefix: "uploads/"
/// - Suffix: ".csv"
/// - Object key: "uploads/test.csv"
#[test]
fn test_uploads_csv_pattern() {
let pattern = pattern::new_pattern(Some("uploads/"), Some(".csv"));
assert_eq!(pattern, "uploads/*.csv");
assert!(pattern::match_simple(&pattern, "uploads/test.csv"));
assert!(pattern::match_simple(&pattern, "uploads/subdir/file.csv"));
assert!(!pattern::match_simple(&pattern, "uploads/test.txt"));
}
/// Test prefix only
#[test]
fn test_prefix_only() {
let pattern = pattern::new_pattern(Some("images/"), None);
assert_eq!(pattern, "images/*");
assert!(pattern::match_simple(&pattern, "images/photo.jpg"));
assert!(pattern::match_simple(&pattern, "images/subdir/photo.png"));
assert!(!pattern::match_simple(&pattern, "documents/photo.jpg"));
}
/// Test suffix only
#[test]
fn test_suffix_only() {
let pattern = pattern::new_pattern(None, Some(".jpg"));
assert_eq!(pattern, "*.jpg");
assert!(pattern::match_simple(&pattern, "photo.jpg"));
assert!(pattern::match_simple(&pattern, "uploads/photo.jpg"));
assert!(pattern::match_simple(&pattern, "a/b/photo.jpg"));
assert!(!pattern::match_simple(&pattern, "photo.png"));
}
/// Test empty pattern (no filter)
#[test]
fn test_empty_pattern() {
let pattern = pattern::new_pattern(None, None);
assert_eq!(pattern, "");
// Empty pattern should not match anything
assert!(!pattern::match_simple(&pattern, "anything"));
}
/// Test complex patterns
#[test]
fn test_complex_patterns() {
// Pattern with both prefix and suffix
let pattern = pattern::new_pattern(Some("data/uploads/"), Some(".csv"));
assert_eq!(pattern, "data/uploads/*.csv");
assert!(pattern::match_simple(&pattern, "data/uploads/test.csv"));
assert!(!pattern::match_simple(&pattern, "data/test.csv"));
// Pattern with prefix containing special characters
let pattern = pattern::new_pattern(Some("special-chars_123/"), Some(".txt"));
assert_eq!(pattern, "special-chars_123/*.txt");
assert!(pattern::match_simple(&pattern, "special-chars_123/file.txt"));
}
/// Test edge cases
#[test]
fn test_edge_cases() {
// Empty prefix and non-empty suffix
let pattern = pattern::new_pattern(Some(""), Some(".csv"));
assert_eq!(pattern, "*.csv");
// Non-empty prefix and empty suffix
let pattern = pattern::new_pattern(Some("uploads/"), Some(""));
assert_eq!(pattern, "uploads/*");
// Pattern ending with star in prefix
let pattern = pattern::new_pattern(Some("uploads*"), Some(".csv"));
assert_eq!(pattern, "uploads*.csv");
// Pattern starting with star in suffix
let pattern = pattern::new_pattern(Some("uploads/"), Some("*csv"));
assert_eq!(pattern, "uploads/*csv");
}
/// Test the exact scenario from bug report
#[test]
fn test_bug_report_exact_scenario() {
// Configuration: prefix="uploads/", suffix=".csv"
let prefix = Some("uploads/");
let suffix = Some(".csv");
let object_key = "uploads/test.csv";
// Generate pattern from filter rules
let pattern = pattern::new_pattern(prefix, suffix);
println!("Generated pattern: '{}'", pattern);
// Verify pattern is correct
assert_eq!(pattern, "uploads/*.csv");
// Test matching
let matches = pattern::match_simple(&pattern, object_key);
println!("Pattern '{}' matches key '{}': {}", pattern, object_key, matches);
assert!(matches, "Pattern '{}' should match object key '{}'", pattern, object_key);
// Test other keys
assert!(pattern::match_simple(&pattern, "uploads/file1.csv"));
assert!(pattern::match_simple(&pattern, "uploads/nested/file.csv"));
assert!(!pattern::match_simple(&pattern, "uploads/file.txt"));
assert!(!pattern::match_simple(&pattern, "files/test.csv"));
}
/// Test with multiple slashes in path
#[test]
fn test_multiple_slashes() {
let pattern = pattern::new_pattern(Some("a/b/c/"), Some(".csv"));
assert_eq!(pattern, "a/b/c/*.csv");
assert!(pattern::match_simple(&pattern, "a/b/c/test.csv"));
assert!(!pattern::match_simple(&pattern, "a/b/test.csv"));
}
/// Test wildcard behavior
#[test]
fn test_wildcard_behavior() {
// Test that * matches any characters including slashes
let pattern = "uploads/*.csv";
assert!(pattern::match_simple(pattern, "uploads/test.csv"));
assert!(pattern::match_simple(pattern, "uploads/subdir/test.csv"));
assert!(pattern::match_simple(pattern, "uploads/a/b/c/test.csv"));
// Test that multiple wildcards work
let pattern = "a*b*c.csv";
assert!(pattern::match_simple(pattern, "a123b456c.csv"));
assert!(pattern::match_simple(pattern, "abc.csv"));
}
/// Test match_all pattern
#[test]
fn test_match_all_pattern() {
// S3 uses "*" to match all objects
let pattern = "*";
assert!(pattern::match_simple(pattern, "anything"));
assert!(pattern::match_simple(pattern, "uploads/test.csv"));
assert!(pattern::match_simple(pattern, ""));
}
}