#![allow(missing_docs)]
use proptest::prelude::*;
use rlg::log::Log;
use rlg::log_format::LogFormat;
use rlg::log_level::LogLevel;
use rlg_cli::Filter;
use std::borrow::Cow;
use std::collections::BTreeMap;
fn any_level() -> impl Strategy<Value = LogLevel> {
prop_oneof![
Just(LogLevel::TRACE),
Just(LogLevel::DEBUG),
Just(LogLevel::VERBOSE),
Just(LogLevel::INFO),
Just(LogLevel::WARN),
Just(LogLevel::ERROR),
Just(LogLevel::FATAL),
Just(LogLevel::CRITICAL),
]
}
fn any_log() -> impl Strategy<Value = Log> {
(
any::<u64>(),
any_level(),
"[a-z]{1,10}",
"[a-zA-Z0-9 ]{0,32}",
)
.prop_map(|(sid, level, component, description)| Log {
session_id: sid,
time: Cow::Borrowed("t"),
level,
component: component.into(),
description,
format: LogFormat::JSON,
attributes: BTreeMap::new(),
})
}
proptest! {
#[test]
fn default_filter_matches_every_log(log in any_log()) {
prop_assert!(Filter::new().matches(&log));
}
}
proptest! {
#[test]
fn min_level_is_monotone(
log in any_log(),
high in any_level(),
low in any_level(),
) {
prop_assume!(low.to_numeric() <= high.to_numeric());
let strict = Filter::new().min_level(high);
let relaxed = Filter::new().min_level(low);
if strict.matches(&log) {
prop_assert!(
relaxed.matches(&log),
"monotonicity violated: strict min_level={:?} matched but relaxed min_level={:?} rejected {:?}",
high, low, log
);
}
}
}
proptest! {
#[test]
fn component_filter_matches_only_exact(
log in any_log(),
needle in "[a-z]{1,10}",
) {
let filter = Filter::new().component(needle.clone());
if filter.matches(&log) {
prop_assert_eq!(log.component.as_ref(), needle.as_str());
}
}
}