1 #[macro_use]
2 extern crate log;
3
4 use std::sync::{Arc, Mutex};
5 use log::{Level, LevelFilter, Log, Record, Metadata};
6
7 #[cfg(feature = "std")]
8 use log::set_boxed_logger;
9 #[cfg(not(feature = "std"))]
set_boxed_logger(logger: Box<Log>) -> Result<(), log::SetLoggerError>10 fn set_boxed_logger(logger: Box<Log>) -> Result<(), log::SetLoggerError> {
11 log::set_logger(Box::leak(logger))
12 }
13
14 struct State {
15 last_log: Mutex<Option<Level>>,
16 }
17
18 struct Logger(Arc<State>);
19
20 impl Log for Logger {
enabled(&self, _: &Metadata) -> bool21 fn enabled(&self, _: &Metadata) -> bool {
22 true
23 }
24
log(&self, record: &Record)25 fn log(&self, record: &Record) {
26 *self.0.last_log.lock().unwrap() = Some(record.level());
27 }
28
flush(&self)29 fn flush(&self) {}
30 }
31
main()32 fn main() {
33 let me = Arc::new(State { last_log: Mutex::new(None) });
34 let a = me.clone();
35 set_boxed_logger(Box::new(Logger(me))).unwrap();
36
37 test(&a, LevelFilter::Off);
38 test(&a, LevelFilter::Error);
39 test(&a, LevelFilter::Warn);
40 test(&a, LevelFilter::Info);
41 test(&a, LevelFilter::Debug);
42 test(&a, LevelFilter::Trace);
43 }
44
test(a: &State, filter: LevelFilter)45 fn test(a: &State, filter: LevelFilter) {
46 log::set_max_level(filter);
47 error!("");
48 last(&a, t(Level::Error, filter));
49 warn!("");
50 last(&a, t(Level::Warn, filter));
51 info!("");
52 last(&a, t(Level::Info, filter));
53
54 debug!("");
55 if cfg!(debug_assertions) {
56 last(&a, t(Level::Debug, filter));
57 } else {
58 last(&a, None);
59 }
60
61 trace!("");
62 last(&a, None);
63
64 fn t(lvl: Level, filter: LevelFilter) -> Option<Level> {
65 if lvl <= filter {Some(lvl)} else {None}
66 }
67 }
68
last(state: &State, expected: Option<Level>)69 fn last(state: &State, expected: Option<Level>) {
70 let mut lvl = state.last_log.lock().unwrap();
71 assert_eq!(*lvl, expected);
72 *lvl = None;
73 }
74