diff --git a/src/encode/json.rs b/src/encode/json.rs index 784a8739..2674db69 100644 --- a/src/encode/json.rs +++ b/src/encode/json.rs @@ -85,7 +85,15 @@ impl JsonEncoder { impl Encode for JsonEncoder { fn encode(&self, w: &mut dyn Write, record: &Record) -> anyhow::Result<()> { - self.encode_inner(w, Local::now(), record) + #[cfg(test)] + let time = DateTime::parse_from_rfc3339("2016-03-20T14:22:20.644420340-08:00") + .unwrap() + .with_timezone(&Local); + + #[cfg(not(test))] + let time = Local::now(); + + self.encode_inner(w, time, record) } } @@ -168,13 +176,17 @@ impl Deserialize for JsonEncoderDeserializer { mod test { #[cfg(feature = "chrono")] use chrono::{DateTime, Local}; - use log::Level; + use log::{Level, Record}; use super::*; + + #[cfg(feature = "config_parsing")] + use crate::config::Deserializers; + use crate::encode::writer::simple::SimpleWriter; #[test] - fn default() { + fn test_json_encode() { let time = DateTime::parse_from_rfc3339("2016-03-20T14:22:20.644420340-08:00") .unwrap() .with_timezone(&Local); @@ -184,16 +196,15 @@ mod test { let file = "file"; let line = 100; let message = "message"; - let thread = "encode::json::test::default"; + let thread = "encode::json::test::test_json_encode"; log_mdc::insert("foo", "bar"); let encoder = JsonEncoder::new(); let mut buf = vec![]; encoder - .encode_inner( + .encode( &mut SimpleWriter(&mut buf), - time, &Record::builder() .level(level) .target(target) @@ -221,4 +232,15 @@ mod test { ); assert_eq!(expected, String::from_utf8(buf).unwrap().trim()); } + + #[test] + #[cfg(feature = "config_parsing")] + fn test_cfg_deserializer() { + let json_cfg = JsonEncoderConfig { _p: () }; + + let deserializer = JsonEncoderDeserializer; + + let res = deserializer.deserialize(json_cfg, &Deserializers::default()); + assert!(res.is_ok()); + } } diff --git a/src/encode/mod.rs b/src/encode/mod.rs index aa290b3c..efe386c4 100644 --- a/src/encode/mod.rs +++ b/src/encode/mod.rs @@ -154,3 +154,80 @@ impl<'a, W: Write + ?Sized> Write for &'a mut W { ::set_style(*self, style) } } + +#[cfg(test)] +mod test { + #[cfg(feature = "config_parsing")] + use serde_test::{assert_de_tokens, assert_de_tokens_error, Token}; + + #[test] + #[cfg(feature = "config_parsing")] + fn test_cfg_deserialize() { + use super::*; + use std::collections::BTreeMap; + + let pattern = "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}".to_owned(); + + let mut config = BTreeMap::new(); + config.insert(Value::String("pattern".to_owned()), Value::String(pattern)); + + let encoder_cfg = EncoderConfig { + kind: "pattern".to_owned(), + config: Value::Map(config), + }; + + assert_de_tokens( + &encoder_cfg, + &[ + Token::Struct { + name: "EncoderConfig", + len: 2, + }, + Token::Str("kind"), + Token::Str("pattern"), + Token::Str("pattern"), + Token::Str("[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}"), + Token::StructEnd, + ], + ); + + // No pattern defined, should fail to deserializez into a map + assert_de_tokens_error::( + &[ + Token::Struct { + name: "EncoderConfig", + len: 2, + }, + Token::Str("kind"), + Token::Str("pattern"), + Token::Str("pattern"), + Token::StructEnd, + ], + "deserialization did not expect this token: StructEnd", + ); + } + + #[test] + #[cfg(feature = "console_writer")] + fn test_set_console_writer_style() { + use super::*; + use crate::encode::writer::console::ConsoleWriter; + + let w = match ConsoleWriter::stdout() { + Some(w) => w, + None => return, + }; + let mut w = w.lock(); + + assert!(w + .set_style( + Style::new() + .text(Color::Red) + .background(Color::Blue) + .intense(true), + ) + .is_ok()); + + w.set_style(&Style::new()).unwrap(); + } +} diff --git a/src/encode/pattern/parser.rs b/src/encode/pattern/parser.rs index 8e91e8ec..aefa9377 100644 --- a/src/encode/pattern/parser.rs +++ b/src/encode/pattern/parser.rs @@ -268,3 +268,91 @@ impl<'a> Iterator for Parser<'a> { } } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_arg_parser() { + let pattern = "(%Y-%m-%dT%H:%M:%S%.6f"; + let mut parser = Parser::new(pattern); + + let arg = parser.arg(); + assert!(arg.is_err()); + + let pattern = "(%Y-%m-%dT%H:%M:%S%.6f)"; + let mut parser = Parser::new(pattern); + + let arg = parser.arg(); + assert!(arg.is_ok()); + + let pattern = "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}"; + let mut parser = Parser::new(pattern); + + let arg = parser.arg(); + assert!(arg.is_ok()); + assert!(arg.unwrap().is_empty()); + } + + #[test] + fn test_name() { + // match up to first non alpha numberic + let pattern = "test["; + let mut parser = Parser::new(pattern); + let name = parser.name(); + assert_eq!(name, "test"); + + // match up to first non alpha numberic, so empty string + let pattern = "["; + let mut parser = Parser::new(pattern); + let name = parser.name(); + assert_eq!(name, ""); + + // match up to first non alpha numberic, so empty string + let pattern = "test"; + let mut parser = Parser::new(pattern); + let name = parser.name(); + assert_eq!(name, "test"); + } + + #[test] + fn test_argument_invalid_and_valid() { + let pattern = "(%Y-%m-%dT%H:%M:%S%.6f"; + let mut parser = Parser::new(pattern); + + let piece = parser.argument(); + assert!(match piece { + Piece::Error(_) => true, + _ => false, + }); + + let pattern = "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}"; + let mut parser = Parser::new(pattern); + + let piece = parser.argument(); + assert!(match piece { + Piece::Argument { .. } => true, + _ => false, + }); + } + + #[test] + fn test_unmatched_bracket() { + let pattern = "d}"; + let parser = Parser::new(pattern); + let mut iter = parser.into_iter(); + + // First parse the d + assert!(match iter.next().unwrap() { + Piece::Text { .. } => true, + _ => false, + }); + + // Next try and parse the } but it's unmatched + assert!(match iter.next().unwrap() { + Piece::Error { .. } => true, + _ => false, + }); + } +} diff --git a/src/encode/writer/ansi.rs b/src/encode/writer/ansi.rs index 8b8b4226..9d35d247 100644 --- a/src/encode/writer/ansi.rs +++ b/src/encode/writer/ansi.rs @@ -87,11 +87,11 @@ mod test { use crate::encode::{Color, Style, Write as EncodeWrite}; #[test] - fn basic() { + fn test_ansi_writer() { let stdout = io::stdout(); let mut w = AnsiWriter(stdout.lock()); - w.write_all(b"normal ").unwrap(); + w.write(b"normal ").unwrap(); w.set_style( Style::new() .text(Color::Red) @@ -100,10 +100,24 @@ mod test { ) .unwrap(); w.write_all(b"styled").unwrap(); - w.set_style(Style::new().text(Color::Green)).unwrap(); + // Call out intense false here to hit else case + w.set_style(Style::new().text(Color::Green).intense(false)) + .unwrap(); w.write_all(b" styled2").unwrap(); w.set_style(&Style::new()).unwrap(); - w.write_all(b" normal\n").unwrap(); + w.write_fmt(format_args!(" {} \n", "normal")).unwrap(); w.flush().unwrap(); } + + #[test] + fn test_color_enum() { + assert_eq!(color_byte(Color::Black), b'0'); + assert_eq!(color_byte(Color::Red), b'1'); + assert_eq!(color_byte(Color::Green), b'2'); + assert_eq!(color_byte(Color::Yellow), b'3'); + assert_eq!(color_byte(Color::Blue), b'4'); + assert_eq!(color_byte(Color::Magenta), b'5'); + assert_eq!(color_byte(Color::Cyan), b'6'); + assert_eq!(color_byte(Color::White), b'7'); + } } diff --git a/tests/color_control.rs b/tests/color_control.rs deleted file mode 100644 index 344f032f..00000000 --- a/tests/color_control.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::process::Command; - -fn execute_test(env_key: &str, env_val: &str) { - let mut child_proc = Command::new("cargo") - .args(&["run", "--example", "compile_time_config"]) - .env(env_key, env_val) - .spawn() - .expect("Cargo command failed to start"); - - let ecode = child_proc.wait().expect("failed to wait on child"); - - assert!(ecode.success()); -} - -// Maintaining as a single test to avoid blocking calls to the package cache -#[test] -fn test_no_color() { - let keys = vec!["NO_COLOR", "CLICOLOR_FORCE", "CLICOLOR"]; - - for key in keys { - execute_test(key, "1"); - execute_test(key, "0"); - } -}