1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Provides random utilities for components in AVF
16 
17 use log::error;
18 use std::fmt::Debug;
19 
20 /// Convenient trait for logging an error while returning it
21 pub trait LogResult<T, E> {
22     /// If this is `Err`, the error is debug-formatted and is logged via `error!`.
with_log(self) -> Result<T, E>23     fn with_log(self) -> Result<T, E>;
24 }
25 
26 impl<T, E: Debug> LogResult<T, E> for Result<T, E> {
with_log(self) -> Result<T, E>27     fn with_log(self) -> Result<T, E> {
28         self.map_err(|e| {
29             error!("{e:?}");
30             e
31         })
32     }
33 }
34 
35 #[cfg(test)]
36 mod tests {
37     use super::*;
38     use log::{LevelFilter, Log, Metadata, Record};
39     use std::cell::RefCell;
40     use std::io::{Error, ErrorKind};
41 
42     struct TestLogger {
43         last_log: RefCell<String>,
44     }
45     static TEST_LOGGER: TestLogger = TestLogger { last_log: RefCell::new(String::new()) };
46 
47     // SAFETY: TestLogger is used only inside the test which is single-treaded.
48     unsafe impl Sync for TestLogger {}
49 
50     impl Log for TestLogger {
enabled(&self, _metadata: &Metadata) -> bool51         fn enabled(&self, _metadata: &Metadata) -> bool {
52             true
53         }
log(&self, record: &Record)54         fn log(&self, record: &Record) {
55             *self.last_log.borrow_mut() = format!("{}", record.args());
56         }
flush(&self)57         fn flush(&self) {}
58     }
59 
60     #[test]
test_logresult_emits_error_log()61     fn test_logresult_emits_error_log() {
62         log::set_logger(&TEST_LOGGER).unwrap();
63         log::set_max_level(LevelFilter::Info);
64 
65         let e = Error::from(ErrorKind::NotFound);
66         let res: Result<(), Error> = Err(e).with_log();
67 
68         assert!(res.is_err());
69         assert_eq!(TEST_LOGGER.last_log.borrow().as_str(), "Kind(NotFound)");
70     }
71 }
72