Skip to content

Commit feb4256

Browse files
author
Sudan Landge
committed
test: check all logger level case variants
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>
1 parent 51ab5ad commit feb4256

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/vmm/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ vm-fdt = "0.2.0"
5050
criterion = { version = "0.5.0", default-features = false }
5151
device_tree = "1.1.0"
5252
proptest = { version = "1.0.0", default-features = false, features = ["std"] }
53+
itertools = "0.12.0"
5354

5455
[features]
5556
tracing = ["log-instrument"]

src/vmm/src/logger/logging.rs

+49-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::sync::{Mutex, OnceLock};
1010
use std::thread;
1111

1212
use log::{Log, Metadata, Record};
13-
use serde::{Deserialize, Serialize};
13+
use serde::{Deserialize, Deserializer, Serialize};
1414
use utils::time::LocalTime;
1515

1616
use super::metrics::{IncMetric, METRICS};
@@ -200,7 +200,7 @@ pub struct LoggerConfig {
200200
/// the log level filter. It would be a breaking change to no longer support this. In the next
201201
/// breaking release this should be removed (replaced with `log::LevelFilter` and only supporting
202202
/// its default deserialization).
203-
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
203+
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
204204
pub enum LevelFilter {
205205
/// [`log::LevelFilter:Off`]
206206
#[serde(alias = "OFF")]
@@ -233,6 +233,25 @@ impl From<LevelFilter> for log::LevelFilter {
233233
}
234234
}
235235
}
236+
impl<'de> Deserialize<'de> for LevelFilter {
237+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
238+
where
239+
D: Deserializer<'de>,
240+
{
241+
use serde::de::Error;
242+
let key = String::deserialize(deserializer)?;
243+
let level = match key.to_lowercase().as_str() {
244+
"off" => Ok(LevelFilter::Off),
245+
"trace" => Ok(LevelFilter::Trace),
246+
"debug" => Ok(LevelFilter::Debug),
247+
"info" => Ok(LevelFilter::Info),
248+
"warn" | "warning" => Ok(LevelFilter::Warn),
249+
"error" => Ok(LevelFilter::Error),
250+
_ => Err(D::Error::custom("Invalid LevelFilter")),
251+
};
252+
level
253+
}
254+
}
236255

237256
/// Error type for [`<LevelFilter as FromStr>::from_str`].
238257
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
@@ -288,6 +307,34 @@ mod tests {
288307
);
289308
}
290309
#[test]
310+
fn levelfilter_from_str_all_variants() {
311+
use itertools::Itertools;
312+
313+
#[derive(Debug, Deserialize)]
314+
struct Foo {
315+
level: LevelFilter,
316+
}
317+
318+
for level in ["off", "trace", "debug", "info", "warn", "warning", "error"] {
319+
let multi = level.chars().map(|_| 0..=1).multi_cartesian_product();
320+
for combination in multi {
321+
let variant = level
322+
.chars()
323+
.zip_eq(combination)
324+
.map(|(c, v)| match v {
325+
0 => c.to_ascii_lowercase(),
326+
1 => c.to_ascii_uppercase(),
327+
_ => unreachable!(),
328+
})
329+
.collect::<String>();
330+
331+
let ex = format!("{} \"level\": \"{}\" {}", "{", variant, "}");
332+
assert!(LevelFilter::from_str(&variant).is_ok(), "{variant}");
333+
assert!(serde_json::from_str::<Foo>(&ex).is_ok(), "{ex}");
334+
}
335+
}
336+
}
337+
#[test]
291338
fn levelfilter_from_str() {
292339
assert_eq!(
293340
LevelFilter::from_str("bad"),

0 commit comments

Comments
 (0)