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