Skip to content

Commit 4ee2881

Browse files
committed
tests: add appender tests
1 parent 049e2cc commit 4ee2881

File tree

5 files changed

+413
-54
lines changed

5 files changed

+413
-54
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ streaming-stats = "0.2.3"
8888
humantime = "2.1"
8989
tempfile = "3.8"
9090
mock_instant = "0.3"
91+
serde_test = "1.0.176"
9192

9293
[[example]]
9394
name = "json_logger"

src/append/console.rs

+114
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,117 @@ impl Deserialize for ConsoleAppenderDeserializer {
263263
Ok(Box::new(appender.build()))
264264
}
265265
}
266+
267+
#[cfg(test)]
268+
mod test {
269+
use super::*;
270+
use crate::encode::Write;
271+
272+
#[test]
273+
fn test_console_append() {
274+
use log::Level;
275+
276+
// Build a std out appender
277+
let appender = ConsoleAppender::builder()
278+
.tty_only(false)
279+
.target(Target::Stdout)
280+
.encoder(Box::new(PatternEncoder::new("{m}{n}")))
281+
.build();
282+
283+
assert!(appender
284+
.append(
285+
&Record::builder()
286+
.level(Level::Debug)
287+
.target("target")
288+
.module_path(Some("module_path"))
289+
.file(Some("file"))
290+
.line(Some(100))
291+
.args(format_args!("{}", "message"))
292+
.build()
293+
)
294+
.is_ok());
295+
296+
// No op, but test coverage :)
297+
appender.flush();
298+
}
299+
300+
#[test]
301+
fn test_appender_builder() {
302+
// Build a std out appender
303+
let _appender = ConsoleAppender::builder()
304+
.tty_only(false)
305+
.target(Target::Stdout)
306+
.encoder(Box::new(PatternEncoder::new("{m}{n}")))
307+
.build();
308+
309+
// Build a std err appender
310+
let _appender = ConsoleAppender::builder()
311+
.tty_only(false)
312+
.target(Target::Stderr)
313+
.encoder(Box::new(PatternEncoder::new("{m}{n}")))
314+
.build();
315+
316+
// Build a default encoder appender
317+
let _appender = ConsoleAppender::builder()
318+
.tty_only(true)
319+
.target(Target::Stderr)
320+
.build();
321+
}
322+
323+
#[test]
324+
#[cfg(feature = "config_parsing")]
325+
fn test_config_deserializer() {
326+
use crate::{config::Deserializers, encode::EncoderConfig};
327+
use serde_value::Value;
328+
use std::collections::BTreeMap;
329+
let deserializer = ConsoleAppenderDeserializer;
330+
331+
let targets = vec![ConfigTarget::Stdout, ConfigTarget::Stderr];
332+
333+
for target in targets {
334+
let console_cfg = ConsoleAppenderConfig {
335+
target: Some(target),
336+
encoder: Some(EncoderConfig {
337+
kind: "pattern".to_owned(),
338+
config: Value::Map(BTreeMap::new()),
339+
}),
340+
tty_only: Some(true),
341+
};
342+
assert!(deserializer
343+
.deserialize(console_cfg, &Deserializers::default())
344+
.is_ok());
345+
}
346+
}
347+
348+
fn write_test(mut writer: WriterLock) {
349+
use std::io::Write;
350+
351+
assert_eq!(writer.write(b"Write log\n").unwrap(), 10);
352+
assert!(writer.set_style(&Style::new()).is_ok());
353+
assert!(writer.write_all(b"Write All log\n").is_ok());
354+
assert!(writer.write_fmt(format_args!("{} \n", "normal")).is_ok());
355+
assert!(writer.flush().is_ok());
356+
}
357+
358+
#[test]
359+
fn test_tty_writer() {
360+
// Note that this fails in GitHub Actions and therefore does not
361+
// show as covered.
362+
let w = match ConsoleWriter::stdout() {
363+
Some(w) => w,
364+
None => return,
365+
};
366+
367+
let tty = Writer::Tty(w);
368+
assert!(tty.is_tty());
369+
370+
write_test(tty.lock());
371+
}
372+
373+
#[test]
374+
fn test_raw_writer() {
375+
let raw = Writer::Raw(StdWriter::stdout());
376+
assert!(!raw.is_tty());
377+
write_test(raw.lock());
378+
}
379+
}

src/append/file.rs

+57-4
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ mod test {
164164
use super::*;
165165

166166
#[test]
167-
fn create_directories() {
167+
fn test_create_directories() {
168168
let tempdir = tempfile::tempdir().unwrap();
169169

170170
FileAppender::builder()
@@ -173,11 +173,64 @@ mod test {
173173
}
174174

175175
#[test]
176-
fn append_false() {
176+
fn test_append_trait() {
177+
use log::Level;
178+
177179
let tempdir = tempfile::tempdir().unwrap();
178-
FileAppender::builder()
179-
.append(false)
180+
let appender = FileAppender::builder()
180181
.build(tempdir.path().join("foo.log"))
181182
.unwrap();
183+
184+
log_mdc::insert("foo", "bar");
185+
let res = appender.append(
186+
&Record::builder()
187+
.level(Level::Debug)
188+
.target("target")
189+
.module_path(Some("module_path"))
190+
.file(Some("file"))
191+
.line(Some(100))
192+
.args(format_args!("{}", "message"))
193+
.build(),
194+
);
195+
assert!(res.is_ok());
196+
197+
appender.flush();
198+
}
199+
200+
#[test]
201+
fn test_appender_builder() {
202+
let append_choices = vec![true, false];
203+
let tempdir = tempfile::tempdir().unwrap();
204+
205+
for do_append in append_choices {
206+
// No actionable test
207+
FileAppender::builder()
208+
.append(do_append)
209+
.build(tempdir.path().join("foo.log"))
210+
.unwrap();
211+
}
212+
}
213+
214+
#[test]
215+
#[cfg(feature = "config_parsing")]
216+
fn test_config_deserializer() {
217+
use crate::config::Deserializers;
218+
use serde_value::Value;
219+
use std::collections::BTreeMap;
220+
221+
let tempdir = tempfile::tempdir().unwrap();
222+
let file_cfg = FileAppenderConfig {
223+
path: tempdir.path().join("foo.log").to_str().unwrap().to_owned(),
224+
encoder: Some(EncoderConfig {
225+
kind: "pattern".to_owned(),
226+
config: Value::Map(BTreeMap::new()),
227+
}),
228+
append: Some(true),
229+
};
230+
231+
let deserializer = FileAppenderDeserializer;
232+
233+
let res = deserializer.deserialize(file_cfg, &Deserializers::default());
234+
assert!(res.is_ok());
182235
}
183236
}

src/append/mod.rs

+59-1
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,15 @@ impl<'de> Deserialize<'de> for AppenderConfig {
153153

154154
#[cfg(test)]
155155
mod test {
156+
#[cfg(feature = "config_parsing")]
157+
use super::*;
158+
156159
#[cfg(any(feature = "file_appender", feature = "rolling_file_appender"))]
157160
use std::env::{set_var, var};
158161

159162
#[test]
160163
#[cfg(any(feature = "file_appender", feature = "rolling_file_appender"))]
161-
fn expand_env_vars_tests() {
164+
fn test_expand_env_vars() {
162165
set_var("HELLO_WORLD", "GOOD BYE");
163166
#[cfg(not(target_os = "windows"))]
164167
let test_cases = vec![
@@ -250,4 +253,59 @@ mod test {
250253
assert_eq!(res, expected)
251254
}
252255
}
256+
257+
#[test]
258+
#[cfg(feature = "config_parsing")]
259+
fn test_config_deserialize() {
260+
use std::collections::BTreeMap;
261+
262+
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
263+
use serde_value::Value;
264+
265+
use crate::filter::FilterConfig;
266+
267+
let appender = AppenderConfig {
268+
kind: "file".to_owned(),
269+
filters: vec![FilterConfig {
270+
kind: "threshold".to_owned(),
271+
config: Value::Map({
272+
let mut map = BTreeMap::new();
273+
map.insert(
274+
Value::String("level".to_owned()),
275+
Value::String("error".to_owned()),
276+
);
277+
map
278+
}),
279+
}],
280+
config: Value::Map(BTreeMap::new()),
281+
};
282+
283+
let mut cfg = vec![
284+
Token::Struct {
285+
name: "AppenderConfig",
286+
len: 3,
287+
},
288+
Token::Str("kind"),
289+
Token::Str("file"),
290+
Token::Str("filters"),
291+
Token::Seq { len: Some(1) },
292+
Token::Struct {
293+
name: "FilterConfig",
294+
len: 2,
295+
},
296+
Token::Str("kind"),
297+
Token::Str("threshold"),
298+
Token::Str("level"),
299+
Token::Str("error"),
300+
Token::StructEnd,
301+
Token::SeqEnd,
302+
Token::StructEnd,
303+
];
304+
305+
assert_de_tokens(&appender, &cfg);
306+
307+
// Intentional typo on expected field
308+
cfg[1] = Token::Str("kid");
309+
assert_de_tokens_error::<AppenderConfig>(&cfg, "missing field `kind`");
310+
}
253311
}

0 commit comments

Comments
 (0)