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]
|
[dependencies]
|
||||||
clap = "4.3.11"
|
clap = "4.3.11"
|
||||||
env_logger = "0.10.0"
|
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"
|
pyo3 = "0.18.1"
|
||||||
|
testing_logger = "0.1.1"
|
||||||
|
|
|
@ -14,3 +14,5 @@ classifiers = [
|
||||||
|
|
||||||
[tool.maturin]
|
[tool.maturin]
|
||||||
features = ["pyo3/extension-module"]
|
features = ["pyo3/extension-module"]
|
||||||
|
python-source = "python"
|
||||||
|
module-name = "libpt._libpt"
|
||||||
|
|
|
@ -13,48 +13,79 @@
|
||||||
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
//// ATTRIBUTES ////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// IMPORTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
use std::{fmt, str::FromStr};
|
use std::{
|
||||||
|
fmt,
|
||||||
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
|
};
|
||||||
|
|
||||||
use log::{debug, error, info, trace, warn};
|
use env_logger::{Env, Target};
|
||||||
|
use log::{debug, error, info, trace, warn, Level};
|
||||||
use env_logger;
|
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////////
|
//// CONSTANTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// The log level used when none is specified
|
/// 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 ///////////////////////////////////////////////////////////////////////////////////////
|
//// STRUCTS ///////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// ## Logger for [`libpt`](crate::libpt)
|
/// ## Logger for [`libpt`](crate::libpt)
|
||||||
///
|
///
|
||||||
/// This struct exists mainly for the python module, so that we can use the same logger with both
|
/// This struct exists mainly for the python module, so that we can use the same logger with both
|
||||||
/// python and rust.
|
/// 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]
|
#[pyclass]
|
||||||
pub struct Logger {
|
pub struct Logger {}
|
||||||
/// keeps track of if the logger was initialized
|
|
||||||
pub initialized: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
//// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
|
||||||
impl Logger {
|
impl Logger {
|
||||||
/// ## create a `Logger`
|
/// ## create a `Logger`
|
||||||
pub fn new(level: log::Level) -> Self {
|
///
|
||||||
let mut l = Logger { initialized: false };
|
/// Creates a new uninitialized [`Logger`] object.
|
||||||
l.init(level);
|
pub fn new() -> Self {
|
||||||
|
let l = Logger {};
|
||||||
l
|
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
|
// only init if no init has been performed yet
|
||||||
if self.initialized {
|
if INITIALIZED.load(Ordering::Relaxed) {
|
||||||
self.warn("trying to reinitialize the logger, ignoring");
|
warn!("trying to reinitialize the logger, ignoring");
|
||||||
return;
|
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`]
|
/// ## logging at [`Level::Error`]
|
||||||
|
@ -99,17 +130,14 @@ impl Logger {
|
||||||
impl Logger {
|
impl Logger {
|
||||||
/// ## Python version of [`new()`](Logger::new)
|
/// ## Python version of [`new()`](Logger::new)
|
||||||
#[new]
|
#[new]
|
||||||
pub fn py_new(level: String) -> PyResult<Self> {
|
pub fn py_new() -> PyResult<Self> {
|
||||||
Ok(Self::new(log::Level::from_str(level.as_str()).expect(
|
Ok(Logger::new())
|
||||||
format!("could not get log level for '{}'", level).as_str(),
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
/// ## Python version of [`init()`](Logger::init)
|
/// ## Python version of [`init()`](Logger::init)
|
||||||
#[pyo3(name = "init")]
|
#[pyo3(name = "init")]
|
||||||
pub fn py_init(&mut self, level: String) {
|
#[staticmethod]
|
||||||
Self::init(self, log::Level::from_str(level.as_str()).expect(
|
pub fn py_init() {
|
||||||
format!("could not get log level for '{}'", level).as_str(),
|
Self::init()
|
||||||
))
|
|
||||||
}
|
}
|
||||||
/// ## Python version of [`error()`](Logger::error)
|
/// ## Python version of [`error()`](Logger::error)
|
||||||
#[pyo3(name = "error")]
|
#[pyo3(name = "error")]
|
||||||
|
@ -142,7 +170,11 @@ impl Logger {
|
||||||
impl fmt::Debug for Logger {
|
impl fmt::Debug for Logger {
|
||||||
/// ## Debug representation for [`Logger`]
|
/// ## Debug representation for [`Logger`]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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