Skip to content

Commit

Permalink
test: check all logger level case variants
Browse files Browse the repository at this point in the history
Add unit test to cover all cases of LevelFilter.

Signed-off-by: Jonathan Woollett-Light <jcawl@amazon.co.uk>
Signed-off-by: Sudan Landge <sudanl@amazon.com>
  • Loading branch information
Sudan Landge committed Nov 24, 2023
1 parent 51ab5ad commit 68f56ff
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/vmm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ vm-fdt = "0.2.0"
criterion = { version = "0.5.0", default-features = false }
device_tree = "1.1.0"
proptest = { version = "1.0.0", default-features = false, features = ["std"] }
itertools = "0.12.0"

[features]
tracing = ["log-instrument"]
Expand Down
52 changes: 50 additions & 2 deletions src/vmm/src/logger/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::sync::{Mutex, OnceLock};
use std::thread;

use log::{Log, Metadata, Record};
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize};
use utils::time::LocalTime;

use super::metrics::{IncMetric, METRICS};
Expand Down Expand Up @@ -200,7 +200,7 @@ pub struct LoggerConfig {
/// the log level filter. It would be a breaking change to no longer support this. In the next
/// breaking release this should be removed (replaced with `log::LevelFilter` and only supporting
/// its default deserialization).
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub enum LevelFilter {
/// [`log::LevelFilter:Off`]
#[serde(alias = "OFF")]
Expand Down Expand Up @@ -233,6 +233,25 @@ impl From<LevelFilter> for log::LevelFilter {
}
}
}
impl<'de> Deserialize<'de> for LevelFilter {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error;
let key = String::deserialize(deserializer)?;
let level = match key.to_lowercase().as_str() {
"off" => Ok(LevelFilter::Off),
"trace" => Ok(LevelFilter::Trace),
"debug" => Ok(LevelFilter::Debug),
"info" => Ok(LevelFilter::Info),
"warn" | "warning" => Ok(LevelFilter::Warn),
"error" => Ok(LevelFilter::Error),
_ => Err(D::Error::custom("Invalid LevelFilter")),

Check warning on line 250 in src/vmm/src/logger/logging.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/logger/logging.rs#L250

Added line #L250 was not covered by tests
};
level
}
}

/// Error type for [`<LevelFilter as FromStr>::from_str`].
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
Expand Down Expand Up @@ -288,6 +307,35 @@ mod tests {
);
}
#[test]
fn levelfilter_from_str_all_variants() {
use itertools::Itertools;

#[derive(Debug, Deserialize)]
struct Foo {
#[allow(dead_code)]
level: LevelFilter,
}

for level in ["off", "trace", "debug", "info", "warn", "warning", "error"] {
let multi = level.chars().map(|_| 0..=1).multi_cartesian_product();
for combination in multi {
let variant = level
.chars()
.zip_eq(combination)
.map(|(c, v)| match v {
0 => c.to_ascii_lowercase(),
1 => c.to_ascii_uppercase(),
_ => unreachable!(),
})
.collect::<String>();

let ex = format!("{} \"level\": \"{}\" {}", "{", variant, "}");
assert!(LevelFilter::from_str(&variant).is_ok(), "{variant}");
assert!(serde_json::from_str::<Foo>(&ex).is_ok(), "{ex}");
}
}
}
#[test]
fn levelfilter_from_str() {
assert_eq!(
LevelFilter::from_str("bad"),
Expand Down

0 comments on commit 68f56ff

Please sign in to comment.