blob: b84c240057ab3fdcf78885d543bc718c4fcd29e9 [file] [log] [blame]
//! This provides testing of the 'meta-logging' feature, which allows for
//! deadlock-free logging within logging formatters.
//!
//! These tests *will* deadlock if the feature is not enabled, so they're
//! disabled by default.
#![cfg(feature = "meta-logging-in-format")]
use std::{fmt, fs, io, io::prelude::*};
use log::{Level::*, Log};
mod support;
use support::manual_log;
// in order to actually trigger the situation that deadlocks, we need a custom
// Display implementation which performs logging:
struct VerboseDisplayThing<'a> {
log_copy: &'a dyn Log,
msg: &'a str,
}
impl<'a> fmt::Display for VerboseDisplayThing<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
manual_log(
self.log_copy,
Debug,
format_args!(
"VerboseDisplayThing is being displayed! [contents: {}]",
self.msg
),
);
f.write_str(self.msg)
}
}
#[test]
fn file_deadlock() {
// Create a temporary directory to put a log file into for testing
let temp_log_dir = tempfile::tempdir().expect("Failed to set up temporary directory");
let log_file = temp_log_dir.path().join("test.log");
{
let (_max_level, logger) = fern::Dispatch::new()
.format(|out, msg, record| out.finish(format_args!("[{}] {}", record.level(), msg)))
.chain(io::stdout())
.chain(fern::log_file(log_file).expect("Failed to open log file"))
.into_log();
let l = &*logger;
manual_log(
l,
Info,
format_args!(
"Hello, world! {}",
VerboseDisplayThing {
log_copy: l,
msg: "it's verbose!",
}
),
);
// ensure all File objects are dropped and OS buffers are flushed.
log::logger().flush();
{
let contents = {
let mut log_read = fs::File::open(temp_log_dir.path().join("test.log")).unwrap();
let mut buf = String::new();
log_read.read_to_string(&mut buf).unwrap();
buf
};
assert_eq!(
contents,
// double logs because we're logging to stdout & the file
"[DEBUG] VerboseDisplayThing is being displayed! [contents: it's verbose!]\
\n[DEBUG] VerboseDisplayThing is being displayed! [contents: it's verbose!]\
\n[INFO] Hello, world! it's verbose!\n"
);
}
} // ensure logger is dropped before temp dir
temp_log_dir
.close()
.expect("Failed to clean up temporary directory");
}