enh(generic-snmp): threshold works almost. Some error cases are still to implement

This commit is contained in:
David Boucher 2025-05-10 16:28:02 +02:00
parent c184f2d407
commit 48302c0fec
2 changed files with 130 additions and 17 deletions

View File

@ -5,6 +5,7 @@ use std::f64::INFINITY;
pub struct Threshold {
start: f64,
end: f64,
negation: bool,
}
impl Threshold {
@ -14,7 +15,8 @@ impl Threshold {
let mut in_number = false;
let mut current = 0;
let mut value = [-INFINITY, INFINITY];
let mut in_range = false;
let mut in_range = 0;
let mut negation = 0;
for (idx, c) in expr.char_indices() {
if in_number {
match c {
@ -24,10 +26,7 @@ impl Threshold {
in_number = false;
value[current] = match expr[start..idx].parse() {
Ok(x) => x,
Err(err) => {
error!("parse error: {}", err);
std::process::exit(3);
}
Err(_) => return Err(Error::BadThreshold),
}
}
}
@ -35,7 +34,14 @@ impl Threshold {
/* No else here, because we can continue the previous match */
if !in_number {
match c {
'@' => {
negation += 1;
}
' ' => continue,
'-' => {
in_number = true;
start = idx;
}
'0'..='9' => {
in_number = true;
start = idx;
@ -44,25 +50,25 @@ impl Threshold {
value[0] = -INFINITY;
}
':' => {
in_range = true;
in_range += 1;
current = 1;
}
_ => break,
_ => return Err(Error::BadThreshold),
}
}
}
if negation > 1 {
return Err(Error::BadThreshold);
}
if in_number {
value[current] = match expr[start..].parse() {
Ok(x) => x,
Err(err) => {
error!("parse error: {}", err);
std::process::exit(3);
}
Err(_) => return Err(Error::BadThreshold),
}
}
/* We have noticed a ':' character, so the threshold is a range */
if in_range {
if in_range == 1 {
if value[0] > value[1] {
return Err(Error::BadThresholdRange {
start: value[0],
@ -72,7 +78,10 @@ impl Threshold {
return Ok(Threshold {
start: value[0],
end: value[1],
negation: negation > 0,
});
} else if in_range > 1 {
return Err(Error::BadThreshold);
} else {
if value[0] <= 0_f64 {
return Err(Error::NegativeSimpleThreshold { value: value[0] });
@ -80,15 +89,24 @@ impl Threshold {
return Ok(Threshold {
start: 0_f64,
end: value[0],
negation: negation > 0,
});
}
}
fn in_alert(&self, value: f64) -> bool {
if value < self.start || value > self.end {
if self.negation {
return false;
} else {
return true;
}
}
if self.negation {
true
} else {
false
}
false
}
}
@ -178,9 +196,101 @@ mod Test {
Err(err) => {
assert_eq!(
err.to_string(),
"The start value 30 must be less than the end value 20"
"Threshold: The start value 30 must be less than the end value 20"
);
}
}
}
#[test]
fn test_bad_range() {
let expr = "10:20:30";
let threshold = Threshold::parse(expr);
match threshold {
Ok(_) => {
panic!("The threshold '{}' should not be valid", expr);
}
Err(err) => {
assert_eq!(
err.to_string(),
"Threshold: Threshold not of the form '[@]start:end'"
);
}
}
}
#[test]
fn test_threshold_foobar() {
let expr = "foobar";
let threshold = Threshold::parse(expr);
match threshold {
Ok(_) => {
panic!("The threshold '{}' should not be valid", expr);
}
Err(err) => {
assert_eq!(err.to_string(),
"Threshold: Threshold not of the form '[@]start:end'");
}
}
}
#[test]
fn test_threshold_12foo() {
let expr = "12foo";
let threshold = Threshold::parse(expr);
match threshold {
Ok(_) => {
panic!("The threshold '{}' should not be valid", expr);
}
Err(err) => {
assert_eq!(err.to_string(),
"Threshold: Threshold not of the form '[@]start:end'");
}
}
}
#[test]
fn test_threshold_bad_number() {
let expr = "12e.1.e28";
let threshold = Threshold::parse(expr);
match threshold {
Ok(_) => {
panic!("The threshold '{}' should not be valid", expr);
}
Err(err) => {
assert_eq!(err.to_string(),
"Threshold: Threshold not of the form '[@]start:end'");
}
}
}
#[test]
fn test_threshold_bad_number_and_range() {
let expr = "12e.1.e28:1.2.3.4";
let threshold = Threshold::parse(expr);
match threshold {
Ok(_) => {
panic!("The threshold '{}' should not be valid", expr);
}
Err(err) => {
assert_eq!(err.to_string(),
"Threshold: Threshold not of the form '[@]start:end'");
}
}
}
#[test]
fn test_threshold_not_allowed_negative() {
let expr = "-12";
let threshold = Threshold::parse(expr);
match threshold {
Ok(_) => {
panic!("The threshold '{}' should not be valid", expr);
}
Err(err) => {
assert_eq!(err.to_string(),
"Threshold: This syntax is a shortcut of '0:-12', so -12 must be greater than 0.");
}
}
}
}

View File

@ -4,18 +4,21 @@ use std::{fs, io, path::PathBuf};
#[derive(Debug, Snafu)]
pub enum Error {
#[snafu(display(
"This syntax is a shortcut of '0:{}', so {} must be greater than 0.",
"Threshold: This syntax is a shortcut of '0:{}', so {} must be greater than 0.",
value,
value
))]
NegativeSimpleThreshold { value: f64 },
#[snafu(display("The start value {} must be less than the end value {}", start, end))]
#[snafu(display("Threshold: The start value {} must be less than the end value {}", start, end))]
BadThresholdRange { start: f64, end: f64 },
#[snafu(display("Unable to read configuration from {}", path.display()))]
#[snafu(display("Threshold: Unable to read configuration from {}", path.display()))]
ReadConfiguration { source: io::Error, path: PathBuf },
#[snafu(display("Threshold: Threshold not of the form '[@]start:end'"))]
BadThreshold,
#[snafu(display("Unable to write result to {}", path.display()))]
WriteResult { source: io::Error, path: PathBuf },
}