generated from PlexSheep/baserepo
logger works, but only half tests
This commit is contained in:
parent
2564eee991
commit
88de9b0fe0
|
@ -24,5 +24,7 @@ path = "src/bin/mod.rs"
|
|||
[dependencies]
|
||||
clap = "4.3.11"
|
||||
env_logger = "0.10.0"
|
||||
log = { version = "0.4.19", features = ["max_level_debug", "release_max_level_info"] }
|
||||
gag = "1.0.0"
|
||||
log = { version = "0.4.19", features = ["max_level_trace", "release_max_level_trace"] }
|
||||
pyo3 = "0.18.1"
|
||||
testing_logger = "0.1.1"
|
||||
|
|
|
@ -14,3 +14,5 @@ classifiers = [
|
|||
|
||||
[tool.maturin]
|
||||
features = ["pyo3/extension-module"]
|
||||
python-source = "python"
|
||||
module-name = "libpt._libpt"
|
||||
|
|
|
@ -13,48 +13,79 @@
|
|||
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
use std::{fmt, str::FromStr};
|
||||
use std::{
|
||||
fmt,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use log::{debug, error, info, trace, warn};
|
||||
|
||||
use env_logger;
|
||||
use env_logger::{Env, Target};
|
||||
use log::{debug, error, info, trace, warn, Level};
|
||||
|
||||
use pyo3::prelude::*;
|
||||
//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||
/// The log level used when none is specified
|
||||
const DEFAULT_LOG_LEVEL: log::Level = log::Level::Info;
|
||||
pub const DEFAULT_LOG_LEVEL: Level = Level::Info;
|
||||
/// Register your level to this ENVAR to override the used level
|
||||
pub const LOGGER_ENV_KEY: &'static str = "LIBPT_LOGLEVEL";
|
||||
|
||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
static INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
/// ## Logger for [`libpt`](crate::libpt)
|
||||
///
|
||||
/// This struct exists mainly for the python module, so that we can use the same logger with both
|
||||
/// python and rust.
|
||||
///
|
||||
/// ### Setting a [`Level`](log::Level)
|
||||
///
|
||||
/// To set a [`Level`](log::Level), you need to set the ENVAR `LIBPT_LOGLEVEL` to either of
|
||||
///
|
||||
/// - `Trace`
|
||||
/// - `Debug`
|
||||
/// - `Info`
|
||||
/// - `Warn`
|
||||
/// - `Error`
|
||||
#[pyclass]
|
||||
pub struct Logger {
|
||||
/// keeps track of if the logger was initialized
|
||||
pub initialized: bool,
|
||||
}
|
||||
pub struct Logger {}
|
||||
|
||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||
impl Logger {
|
||||
/// ## create a `Logger`
|
||||
pub fn new(level: log::Level) -> Self {
|
||||
let mut l = Logger { initialized: false };
|
||||
l.init(level);
|
||||
///
|
||||
/// Creates a new uninitialized [`Logger`] object.
|
||||
pub fn new() -> Self {
|
||||
let l = Logger {};
|
||||
l
|
||||
}
|
||||
pub fn init(&mut self, level: log::Level) {
|
||||
/// ## initializes the logger
|
||||
///
|
||||
/// Will enable the logger to be used.
|
||||
pub fn init() {
|
||||
// only init if no init has been performed yet
|
||||
if self.initialized {
|
||||
self.warn("trying to reinitialize the logger, ignoring");
|
||||
if INITIALIZED.load(Ordering::Relaxed) {
|
||||
warn!("trying to reinitialize the logger, ignoring");
|
||||
return;
|
||||
} else {
|
||||
let env = Env::default().filter_or(LOGGER_ENV_KEY, DEFAULT_LOG_LEVEL.to_string());
|
||||
env_logger::init_from_env(env);
|
||||
INITIALIZED.store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
/// ## initializes the logger to log to a target
|
||||
///
|
||||
/// Will enable the logger to be used.
|
||||
pub fn init_target(test: bool, target: Target) {
|
||||
// only init if no init has been performed yet
|
||||
if INITIALIZED.load(Ordering::Relaxed) {
|
||||
warn!("trying to reinitialize the logger, ignoring");
|
||||
return;
|
||||
} else {
|
||||
let env = Env::default().filter_or(LOGGER_ENV_KEY, DEFAULT_LOG_LEVEL.to_string());
|
||||
env_logger::Builder::from_env(env).is_test(test).target(target).init();
|
||||
INITIALIZED.store(true, Ordering::Relaxed);
|
||||
}
|
||||
#[allow(unused_imports)]
|
||||
use log::log_enabled;
|
||||
// TODO check if level is valid!
|
||||
std::env::set_var("RUST_LOG", level.as_str());
|
||||
env_logger::init();
|
||||
self.initialized = true;
|
||||
}
|
||||
|
||||
/// ## logging at [`Level::Error`]
|
||||
|
@ -99,17 +130,14 @@ impl Logger {
|
|||
impl Logger {
|
||||
/// ## Python version of [`new()`](Logger::new)
|
||||
#[new]
|
||||
pub fn py_new(level: String) -> PyResult<Self> {
|
||||
Ok(Self::new(log::Level::from_str(level.as_str()).expect(
|
||||
format!("could not get log level for '{}'", level).as_str(),
|
||||
)))
|
||||
pub fn py_new() -> PyResult<Self> {
|
||||
Ok(Logger::new())
|
||||
}
|
||||
/// ## Python version of [`init()`](Logger::init)
|
||||
#[pyo3(name = "init")]
|
||||
pub fn py_init(&mut self, level: String) {
|
||||
Self::init(self, log::Level::from_str(level.as_str()).expect(
|
||||
format!("could not get log level for '{}'", level).as_str(),
|
||||
))
|
||||
#[staticmethod]
|
||||
pub fn py_init() {
|
||||
Self::init()
|
||||
}
|
||||
/// ## Python version of [`error()`](Logger::error)
|
||||
#[pyo3(name = "error")]
|
||||
|
@ -142,7 +170,11 @@ impl Logger {
|
|||
impl fmt::Debug for Logger {
|
||||
/// ## Debug representation for [`Logger`]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Logger")
|
||||
write!(
|
||||
f,
|
||||
"Logger: {{initialized: {}}} ",
|
||||
INITIALIZED.load(Ordering::Relaxed)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
//! # very short description
|
||||
//!
|
||||
//! Short description
|
||||
//!
|
||||
//! Details
|
||||
//!
|
||||
//! ## Section 1
|
||||
//!
|
||||
//! ## Section 2
|
||||
|
||||
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
||||
// we want docs
|
||||
#![warn(missing_docs)]
|
||||
#![warn(rustdoc::missing_crate_level_docs)]
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// we want Debug everywhere.
|
||||
#![warn(missing_debug_implementations)]
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// enable clippy's extra lints, the pedantic version
|
||||
#![warn(clippy::pedantic)]
|
||||
|
||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// STATICS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// ENUMS /////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,80 @@
|
|||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// HELPERS ///////////////////////////////////////////////////////////////////////////////////////
|
||||
/// ## checks if the expected thing was printed to stdout
|
||||
///
|
||||
/// Source: [users.rust-lang.org](https://users.rust-lang.org/t/how-to-test-functions-that-use-
|
||||
/// println/67188/5)
|
||||
macro_rules! assert_stdout_eq {
|
||||
($test:expr, $expected:literal) => {{
|
||||
use gag::BufferRedirect;
|
||||
use std::io::Read;
|
||||
|
||||
let mut buf = BufferRedirect::stdout().unwrap();
|
||||
|
||||
$test;
|
||||
|
||||
let mut output = String::new();
|
||||
buf.read_to_string(&mut output).unwrap();
|
||||
drop(buf);
|
||||
|
||||
assert_eq!(&output, $expected);
|
||||
}};
|
||||
}
|
||||
|
||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||
/// ## Tests for basic logging functionality
|
||||
|
||||
mod test_logger_struct {
|
||||
use libpt::logger::*;
|
||||
|
||||
fn setup() {
|
||||
// we don't want to log messages during our tests!
|
||||
Logger::init_target(false, env_logger::Target::Stdout)
|
||||
}
|
||||
|
||||
/// ## Tests for basic logging
|
||||
///
|
||||
/// This test tests if the loggers basic logging functionality works, that is it's methods:
|
||||
///
|
||||
/// - [`Logger::trace`]
|
||||
/// - [`Logger::debug`]
|
||||
/// - [`Logger::info`]
|
||||
/// - [`Logger::warn`]
|
||||
/// - [`Logger::error`]
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_log_basic() {
|
||||
std::env::set_var(LOGGER_ENV_KEY, "Trace");
|
||||
setup();
|
||||
let l = Logger::new();
|
||||
l.error("HELP");
|
||||
assert_stdout_eq!(l.trace("hello world"), "\u{1b}[0m\u{1b}[38;5;8m[\u{1b}[0m2023-07-07T1\
|
||||
8:59:03Z \u{1b}[0m\u{1b}[36mTRACE\u{1b}[0m libpt::logger\u{1b}[0m\u{1b}[38;5;8m]\u{1b}[\
|
||||
0m hello world\n");
|
||||
assert_stdout_eq!(l.debug("hello world"), "\u{1b}[0m\u{1b}[38;5;8m[\u{1b} [0m2023-07-07T1\
|
||||
8:59:03Z \u{1b}[0m\u{1b}[34mDEBUG\u{1b}[0m libpt::logger\u{1b}[0m\u{1b}[38;5;8m]\u{1b}[\
|
||||
0m hello world\n");
|
||||
assert_stdout_eq!(l.info("hello world"), "\u{1b}[0m\u{1b}[38;5;8m[\u{1b} [0m2023-07-07T1\
|
||||
8:59:03Z \u{1b}[0m\u{1b}[34mINFO\u{1b}[0m libpt::logger\u{1b}[0m\u{1b}[38;5;8m]\u{1b}[\
|
||||
0m hello world\n");
|
||||
assert_stdout_eq!(l.warn("hello world"), "\u{1b}[0m\u{1b}[38;5;8m[\u{1b} [0m2023-07-07T1\
|
||||
8:59:03Z \u{1b}[0m\u{1b}[34mWARN\u{1b}[0m libpt::logger\u{1b}[0m\u{1b}[38;5;8m]\u{1b}[\
|
||||
0m hello world\n");
|
||||
assert_stdout_eq!(l.error("hello world"), "\u{1b}[0m\u{1b}[38;5;8m[\u{1b} [0m2023-07-07T1\
|
||||
8:59:03Z \u{1b}[0m\u{1b}[34mERROR\u{1b}[0m libpt::logger\u{1b}[0m\u{1b}[38;5;8m]\u{1b}[\
|
||||
0m hello world\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_initialize() {
|
||||
setup();
|
||||
let l = Logger::new();
|
||||
// these should be ignored due to the global flag
|
||||
Logger::init();
|
||||
Logger::init();
|
||||
Logger::init();
|
||||
Logger::init();
|
||||
l.info("Successfully ignored extra init");
|
||||
}
|
||||
}
|
Reference in New Issue