nucleo/matcher/fuzz/fuzz_targets/fuzz_target_1.rs

79 lines
2.6 KiB
Rust
Raw Normal View History

#![no_main]
use fzf_oxide::{chars, Matcher, MatcherConfig, Utf32Str};
use libfuzzer_sys::arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
#[derive(Arbitrary, Debug)]
pub struct Input<'a> {
haystack: &'a str,
needle: &'a str,
ignore_case: bool,
normalize: bool,
}
fuzz_target!(|data: Input<'_>| {
let mut data = data;
let mut config = MatcherConfig::DEFAULT;
config.ignore_case = data.ignore_case;
config.normalize = data.normalize;
let mut matcher = Matcher::new(config);
let mut indices_optimal = Vec::new();
let mut indices_greedy = Vec::new();
let mut needle_buf = Vec::new();
let mut haystack_buf = Vec::new();
let normalize = |mut c: char| {
if config.normalize {
c = chars::normalize(c);
}
if config.ignore_case {
c = chars::to_lower_case(c);
}
c
};
let needle: String = data.needle.chars().map(normalize).collect();
let needle_chars: Vec<_> = needle.chars().collect();
let needle = Utf32Str::new(&needle, &mut needle_buf);
let haystack = Utf32Str::new(data.haystack, &mut haystack_buf);
let greedy_score = matcher.fuzzy_indices_greedy(haystack, needle, &mut indices_greedy);
if greedy_score.is_some() {
let match_chars: Vec<_> = indices_greedy
.iter()
.map(|&i| normalize(haystack.get(i)))
.collect();
assert_eq!(
match_chars, needle_chars,
"failed match, found {indices_greedy:?} {match_chars:?} (greedy)"
);
}
let optimal_score = matcher.fuzzy_indices(haystack, needle, &mut indices_optimal);
if optimal_score.is_some() {
let match_chars: Vec<_> = indices_optimal
.iter()
.map(|&i| normalize(haystack.get(i)))
.collect();
assert_eq!(
match_chars, needle_chars,
"failed match, found {indices_optimal:?} {match_chars:?}"
);
}
match (greedy_score, optimal_score) {
(None, Some(score)) => unreachable!("optimal matched {score} but greedy did not match"),
(Some(score), None) => unreachable!("greedy matched {score} but optimal did not match"),
(Some(greedy), Some(optimal)) => {
assert!(
greedy <= optimal,
"optimal score must be atleast the same as greedy score {greedy} {optimal}"
);
if indices_greedy == indices_optimal {
assert_eq!(
greedy, optimal,
"if matching same char greedy and optimal score should be identical"
)
}
}
(None, None) => (),
}
});