blob: 27c8628eb755660b5f374f837b5f42f1d44e4d47 [file] [log] [blame]
// Copyright 2023, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Provides random utilities for components in AVF
use log::error;
use std::fmt::Debug;
/// Convenient trait for logging an error while returning it
pub trait LogResult<T, E> {
/// If this is `Err`, the error is debug-formatted and is logged via `error!`.
fn with_log(self) -> Result<T, E>;
}
impl<T, E: Debug> LogResult<T, E> for Result<T, E> {
fn with_log(self) -> Result<T, E> {
self.map_err(|e| {
error!("{e:?}");
e
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use log::{LevelFilter, Log, Metadata, Record};
use std::cell::RefCell;
use std::io::{Error, ErrorKind};
struct TestLogger {
last_log: RefCell<String>,
}
static TEST_LOGGER: TestLogger = TestLogger { last_log: RefCell::new(String::new()) };
// SAFETY: TestLogger is used only inside the test which is single-treaded.
unsafe impl Sync for TestLogger {}
impl Log for TestLogger {
fn enabled(&self, _metadata: &Metadata) -> bool {
true
}
fn log(&self, record: &Record) {
*self.last_log.borrow_mut() = format!("{}", record.args());
}
fn flush(&self) {}
}
#[test]
fn test_logresult_emits_error_log() {
log::set_logger(&TEST_LOGGER).unwrap();
log::set_max_level(LevelFilter::Info);
let e = Error::from(ErrorKind::NotFound);
let res: Result<(), Error> = Err(e).with_log();
assert!(res.is_err());
assert_eq!(TEST_LOGGER.last_log.borrow().as_str(), "Kind(NotFound)");
}
}