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