1 use {Discard, Logger, Never, KV, Drain, OwnedKVList, Record, AsFmtSerializer};
2 
3 // Separate module to test lack of imports
4 mod no_imports {
5     use {Discard, Logger};
6     /// ensure o! macro expands without error inside a module
7     #[test]
test_o_macro_expansion()8     fn test_o_macro_expansion() {
9         let _ = Logger::root(Discard, o!("a" => "aa"));
10     }
11     /// ensure o! macro expands without error inside a module
12     #[test]
test_slog_o_macro_expansion()13     fn test_slog_o_macro_expansion() {
14         let _ = Logger::root(Discard, slog_o!("a" => "aa"));
15     }
16 }
17 
18 #[cfg(feature = "std")]
19 mod std_only {
20     use super::super::*;
21     use std;
22 
23     #[derive(Clone)]
24     struct CheckError;
25 
26     impl Drain for CheckError {
27         type Ok = ();
28         type Err = Never;
log( &self, record: &Record, values: &OwnedKVList, ) -> std::result::Result<Self::Ok, Self::Err>29         fn log(
30             &self,
31             record: &Record,
32             values: &OwnedKVList,
33         ) -> std::result::Result<Self::Ok, Self::Err> {
34             struct ErrorSerializer(String);
35 
36             impl Serializer for ErrorSerializer {
37                 fn emit_arguments(&mut self, key: Key, val: &fmt::Arguments) -> Result {
38                     use core::fmt::Write;
39 
40                     assert!(key == "error");
41                     self.0.write_fmt(*val).unwrap();
42                     Ok(())
43                 }
44             }
45 
46             let mut serializer = ErrorSerializer(String::new());
47             values.serialize(record, &mut serializer).unwrap();
48             assert_eq!(
49                 serializer.0,
50                 format!("{}", record.msg())
51             );
52             Ok(())
53         }
54     }
55 
56     #[derive(Debug)]
57     struct TestError<E=std::string::ParseError>(&'static str, Option<E>);
58 
59     impl TestError {
new(message: &'static str) -> Self60         fn new(message: &'static str) -> Self {
61             TestError(message, None)
62         }
63     }
64 
65     impl<E> fmt::Display for TestError<E> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result66         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67             write!(f, "{}", self.0)
68         }
69     }
70 
71     impl<E: std::error::Error + 'static> std::error::Error for TestError<E> {
72         #[allow(deprecated)]
cause(&self) -> Option<&std::error::Error>73         fn cause(&self) -> Option<&std::error::Error> {
74             self.1.as_ref().map(|error| error as _)
75         }
76 
77         #[allow(deprecated)]
description(&self) -> &str78         fn description(&self) -> &str {
79             "test error"
80         }
81     }
82 
83     #[test]
logger_fmt_debug_sanity()84     fn logger_fmt_debug_sanity() {
85         let root = Logger::root(Discard, o!("a" => "aa"));
86         let log = root.new(o!("b" => "bb", "c" => "cc"));
87 
88         assert_eq!(format!("{:?}", log), "Logger(c, b, a)");
89     }
90 
91     #[test]
multichain()92     fn multichain() {
93         #[derive(Clone)]
94         struct CheckOwned;
95 
96         impl Drain for CheckOwned {
97             type Ok = ();
98             type Err = Never;
99             fn log(
100                 &self,
101                 record: &Record,
102                 values: &OwnedKVList,
103             ) -> std::result::Result<Self::Ok, Self::Err> {
104                 assert_eq!(
105                     format!("{}", record.msg()),
106                     format!("{:?}", values)
107                 );
108                 Ok(())
109             }
110         }
111 
112         let root = Logger::root(CheckOwned, o!("a" => "aa"));
113         let log = root.new(o!("b1" => "bb", "b2" => "bb"));
114 
115         info!(log, "(b2, b1, a)");
116 
117         let log = Logger::root(log, o!("c" => "cc"));
118         info!(log, "(c, b2, b1, a)");
119         let log = Logger::root(log, o!("d1" => "dd", "d2" => "dd"));
120         info!(log, "(d2, d1, c, b2, b1, a)");
121     }
122 
123     #[test]
error_fmt_no_source()124     fn error_fmt_no_source() {
125         let logger = Logger::root(CheckError, o!("error" => #TestError::new("foo")));
126         info!(logger, "foo");
127     }
128 
129     #[test]
error_fmt_single_source()130     fn error_fmt_single_source() {
131         let logger = Logger::root(CheckError, o!("error" => #TestError("foo", Some(TestError::new("bar")))));
132         info!(logger, "foo: bar");
133     }
134 
135     #[test]
error_fmt_two_sources()136     fn error_fmt_two_sources() {
137         let logger = Logger::root(CheckError, o!("error" => #TestError("foo", Some(TestError("bar", Some(TestError::new("baz")))))));
138         info!(logger, "foo: bar: baz");
139     }
140 
141     #[test]
ioerror_impls_value()142     fn ioerror_impls_value() {
143         let logger = Logger::root(Discard, o!());
144         info!(logger, "not found"; "error" => std::io::Error::from(std::io::ErrorKind::NotFound));
145         // compiles?
146         info!(logger, "not found"; "error" => #std::io::Error::from(std::io::ErrorKind::NotFound));
147     }
148 }
149 
150 #[test]
expressions()151 fn expressions() {
152     use super::{Record, Result, Serializer, KV};
153 
154     struct Foo;
155 
156     impl Foo {
157         fn bar(&self) -> u32 {
158             1
159         }
160     }
161 
162     struct X {
163         foo: Foo,
164     }
165 
166     let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));
167 
168     let foo = Foo;
169     let r = X { foo: foo };
170 
171     warn!(log, "logging message");
172     slog_warn!(log, "logging message");
173 
174     info!(log, #"with tag", "logging message");
175     slog_info!(log, #"with tag", "logging message");
176 
177     warn!(log, "logging message"; "a" => "b");
178     slog_warn!(log, "logging message"; "a" => "b");
179 
180     warn!(log, "logging message bar={}", r.foo.bar());
181     slog_warn!(log, "logging message bar={}", r.foo.bar());
182 
183     warn!(
184         log,
185         "logging message bar={} foo={}",
186         r.foo.bar(),
187         r.foo.bar()
188     );
189     slog_warn!(
190         log,
191         "logging message bar={} foo={}",
192         r.foo.bar(),
193         r.foo.bar()
194     );
195 
196     // trailing comma check
197     warn!(
198         log,
199         "logging message bar={} foo={}",
200         r.foo.bar(),
201         r.foo.bar(),
202     );
203     slog_warn!(
204         log,
205         "logging message bar={} foo={}",
206         r.foo.bar(),
207         r.foo.bar(),
208     );
209 
210     warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);
211     slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);
212 
213     // trailing comma check
214     warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);
215     slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);
216 
217     warn!(log,
218           "logging message bar={}", r.foo.bar(); "x" => 1, "y" => r.foo.bar());
219     slog_warn!(log,
220                "logging message bar={}", r.foo.bar();
221                "x" => 1, "y" => r.foo.bar());
222 
223     warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());
224     slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());
225 
226     warn!(log, "logging message bar={}", r.foo.bar();
227           "x" => r.foo.bar(), "y" => r.foo.bar());
228     slog_warn!(log,
229                "logging message bar={}", r.foo.bar();
230                "x" => r.foo.bar(), "y" => r.foo.bar());
231 
232     // trailing comma check
233     warn!(log,
234           "logging message bar={}", r.foo.bar();
235           "x" => r.foo.bar(), "y" => r.foo.bar(),);
236     slog_warn!(log,
237                "logging message bar={}", r.foo.bar();
238                "x" => r.foo.bar(), "y" => r.foo.bar(),);
239 
240     {
241         #[derive(Clone)]
242         struct K;
243 
244         impl KV for K {
245             fn serialize(
246                 &self,
247                 _record: &Record,
248                 _serializer: &mut Serializer,
249             ) -> Result {
250                 Ok(())
251             }
252         }
253 
254         let x = K;
255 
256         let _log = log.new(o!(x.clone()));
257         let _log = log.new(o!("foo" => "bar", x.clone()));
258         let _log = log.new(o!("foo" => "bar", x.clone(), x.clone()));
259         let _log = log.new(
260             slog_o!("foo" => "bar", x.clone(), x.clone(), "aaa" => "bbb"),
261         );
262 
263         info!(log, "message"; "foo" => "bar", &x, &x, "aaa" => "bbb");
264     }
265 
266     info!(
267         log,
268         "message {}",
269           { 3 + 3; 2};
270           "foo" => "bar",
271           "foo" => { 3 + 3; 2},
272           "aaa" => "bbb");
273 }
274 
275 #[cfg(integer128)]
276 #[test]
integer_128_types()277 fn integer_128_types() {
278     let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));
279 
280     info!(log, "i128 = {}", 42i128; "foo" => 7i128);
281     info!(log, "u128 = {}", 42u128; "foo" => 7u128);
282 }
283 
284 #[test]
expressions_fmt()285 fn expressions_fmt() {
286     let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));
287 
288     let f = "f";
289     let d = (1, 2);
290 
291     info!(log, "message"; "f" => %f, "d" => ?d);
292 }
293 
294 #[cfg(feature = "std")]
295 #[test]
display_and_alternate_display()296 fn display_and_alternate_display() {
297     use core::fmt;
298     use core::cell::Cell;
299 
300     struct Example;
301 
302     impl fmt::Display for Example {
303         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
304             if f.alternate() {
305                 f.write_str("alternate")
306             } else {
307                 f.write_str("normal")
308             }
309         }
310     }
311 
312     #[derive(Clone, Default)]
313     struct CheckExample;
314 
315     impl Drain for CheckExample {
316         type Ok = ();
317         type Err = Never;
318 
319         fn log(&self, record: &Record, values: &OwnedKVList) -> Result<(), Never> {
320             let mut checked_n = false;
321             let mut checked_a = false;
322             {
323                 let mut serializer = AsFmtSerializer(|key, fmt_args| {
324                     if key == "n" {
325                         assert_eq!(format!("{}", fmt_args), "normal");
326                         checked_n = true;
327                     } else if key == "a" {
328                         assert_eq!(format!("{}", fmt_args), "alternate");
329                         checked_a = true;
330                     } else {
331                         panic!("Unexpected key: {}", key);
332                     }
333                     Ok(())
334                 });
335 
336                 record.kv.serialize(record, &mut serializer).unwrap();
337             }
338 
339             assert!(checked_n, "Expected the normal formatter to be used");
340             assert!(checked_a, "Expected the alternate formatter to be used");
341 
342             Ok(())
343         }
344     }
345 
346     let log = Logger::root(CheckExample, o!());
347 
348     info!(log, ""; "n" => %Example, "a" => #%Example);
349 }
350 
351 #[test]
makers()352 fn makers() {
353     use ::*;
354     let drain = Duplicate(
355         Discard.filter(|r| r.level().is_at_least(Level::Info)),
356         Discard.filter_level(Level::Warning),
357     ).map(Fuse);
358     let _log = Logger::root(
359         Arc::new(drain),
360         o!("version" => env!("CARGO_PKG_VERSION")),
361     );
362 }
363 
364 #[test]
simple_logger_erased()365 fn simple_logger_erased() {
366     use ::*;
367 
368     fn takes_arced_drain(_l: Logger) {}
369 
370     let drain = Discard.filter_level(Level::Warning).map(Fuse);
371     let log =
372         Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));
373 
374     takes_arced_drain(log.to_erased());
375 }
376 
377 #[test]
logger_to_erased()378 fn logger_to_erased() {
379     use ::*;
380 
381     fn takes_arced_drain(_l: Logger) {}
382 
383     let drain = Duplicate(
384         Discard.filter(|r| r.level().is_at_least(Level::Info)),
385         Discard.filter_level(Level::Warning),
386     ).map(Fuse);
387     let log =
388         Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));
389 
390     takes_arced_drain(log.into_erased());
391 }
392 
393 #[test]
logger_by_ref()394 fn logger_by_ref() {
395     use ::*;
396     let drain = Discard.filter_level(Level::Warning).map(Fuse);
397     let log = Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));
398     let f = "f";
399     let d = (1, 2);
400     info!(&log, "message"; "f" => %f, "d" => ?d);
401 }
402 
403 #[test]
test_never_type_clone()404 fn test_never_type_clone() {
405     // We just want to make sure that this compiles
406     fn _do_not_run() {
407         let x: Never = panic!("Can't actually construct a Never type here!");
408         let y = x.clone();
409     }
410     // Always pass if we compiled
411 }
412 
413 #[cfg(feature = "std")]
414 #[test]
can_hash_keys()415 fn can_hash_keys() {
416     use std::collections::HashSet;
417     use Key;
418     let tab: HashSet<Key> = ["foo"].iter().map(|&k| k.into()).collect();
419 }
420