Feat: Fügt Integrationstests für Logging-Funktionen und verwendet für die Ermittlung des Programmnamen die Crate program-ctdra
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
[registry]
|
||||||
|
default = "gitea"
|
||||||
|
|
||||||
|
[registries.gitea]
|
||||||
|
index = "sparse+https://gitea.creative-dragonslayer.de/api/packages/Rust-Crates/cargo/" # Sparse index
|
||||||
|
# index = "https://gitea.creative-dragonslayer.de/Rust-Crates/_cargo-index.git" # Git
|
||||||
|
|
||||||
|
[net]
|
||||||
|
git-fetch-with-cli = true
|
||||||
Generated
+1
@@ -3,6 +3,7 @@
|
|||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Diese Datei dient als Leitfaden und Kontextdokumentation für autonome Agenten u
|
|||||||
|
|
||||||
- **Keine Unicode-Emojis im Logging**: Das Logging verwendet einheitliche ASCII-Präfixe (`[!]` Error, `[?]` Warn, `[i]` Info, `[d]` Debug).
|
- **Keine Unicode-Emojis im Logging**: Das Logging verwendet einheitliche ASCII-Präfixe (`[!]` Error, `[?]` Warn, `[i]` Info, `[d]` Debug).
|
||||||
- **Threadsicherheit**: Sämtliche Zustände (Log-Level, Dateizugriffe, Pfade) sind threadsicher gekapselt.
|
- **Threadsicherheit**: Sämtliche Zustände (Log-Level, Dateizugriffe, Pfade) sind threadsicher gekapselt.
|
||||||
- **Minimaler Overhead**: Geringe Abhängigkeiten (ausschließlich `time` für formatierte Zeitstempel).
|
- **Minimaler Overhead**: Geringe Abhängigkeiten (`time` für formatierte Zeitstempel, `program-ctdra` zur Programmnamen-Ermittlung).
|
||||||
- **Lizenz**: GNU General Public License v3.0 or later (`GPL-3.0-or-later`).
|
- **Lizenz**: GNU General Public License v3.0 or later (`GPL-3.0-or-later`).
|
||||||
- **Veröffentlichung**: Über Gitea Actions CI/CD in die Gitea Cargo Package Registry.
|
- **Veröffentlichung**: Über Gitea Actions CI/CD in die Gitea Cargo Package Registry.
|
||||||
|
|
||||||
@@ -31,8 +31,10 @@ Logger/
|
|||||||
├── LICENSE # GPL-3.0 Lizenztext
|
├── LICENSE # GPL-3.0 Lizenztext
|
||||||
├── README.md # Projektdokumentation & Nutzungsbeispiele
|
├── README.md # Projektdokumentation & Nutzungsbeispiele
|
||||||
├── AGENTS.md # Entwickler- und Agenten-Richtlinien
|
├── AGENTS.md # Entwickler- und Agenten-Richtlinien
|
||||||
└── src/
|
├── src/
|
||||||
└── lib.rs # Hauptimplementierung (LogLevel, log, set_log_level, format_message, Tests)
|
│ └── lib.rs # Hauptimplementierung (LogLevel, log, set_log_level, format_message)
|
||||||
|
└── tests/
|
||||||
|
└── integration_tests.rs # Integrationstests für alle Modulfunktionen und Traits
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Generated
+7
@@ -18,6 +18,7 @@ checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
|||||||
name = "logger-ctdra"
|
name = "logger-ctdra"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"program-ctdra",
|
||||||
"time",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -51,6 +52,12 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "program-ctdra"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "sparse+https://gitea.creative-dragonslayer.de/api/packages/Rust-Crates/cargo/"
|
||||||
|
checksum = "54f20af67f90bf6d10697dd77bb4beb41dafad7fe0fb46aacfc81ad45a8e48bd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.47"
|
version = "1.0.47"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ repository = "https://gitea.creative-dragonslayer.de/Rust-Crates/logger"
|
|||||||
description = "Einfaches, threadsicheres Logging-Framework für Rust mit Schweregrad-Filterung, formatierten Ausgaben und automatischer Dateiprotokollierung"
|
description = "Einfaches, threadsicheres Logging-Framework für Rust mit Schweregrad-Filterung, formatierten Ausgaben und automatischer Dateiprotokollierung"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
program-ctdra = { version = "1.0.0", registry = "gitea" }
|
||||||
time = { version = "0.3.55", features = ["formatting", "macros", "local-offset"] }
|
time = { version = "0.3.55", features = ["formatting", "macros", "local-offset"] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
- **Einheitliches Format**: `[Präfix][DD.MM.YYYY HH:MM:SS.mmm][LEVEL][Tag]: Nachricht`
|
- **Einheitliches Format**: `[Präfix][DD.MM.YYYY HH:MM:SS.mmm][LEVEL][Tag]: Nachricht`
|
||||||
- **Flexible Konfiguration**:
|
- **Flexible Konfiguration**:
|
||||||
- Log-Level per Code (`set_log_level`), Umgebungsvariable (`LOG_LEVEL` bzw. `RUST_LOG`) oder Fallback (`Info`).
|
- Log-Level per Code (`set_log_level`), Umgebungsvariable (`LOG_LEVEL` bzw. `RUST_LOG`) oder Fallback (`Info`).
|
||||||
- Einstellbarer Programmname (`set_program_name`) oder automatisches Ermitteln via `current_exe()`.
|
- Automatisches Ermitteln des Programmnamens via `program-ctdra` (mit zufälligem Fallback-Wert).
|
||||||
- Anpassbares Log-Verzeichnis (`set_log_dir`) oder automatische Ablage im Temp-Verzeichnis (`std::env::temp_dir()`).
|
- Anpassbares Log-Verzeichnis (`set_log_dir`) oder automatische Ablage im Temp-Verzeichnis (`std::env::temp_dir()`).
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -81,17 +81,14 @@ fn run() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Konfiguration des Programmnamens und Logpfads
|
### Konfiguration des Logpfads
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use logger_ctdra::{set_log_dir, set_program_name};
|
use logger_ctdra::set_log_dir;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
fn init() {
|
fn init() {
|
||||||
// Setzt den App-Namen für das Logverzeichnis (/tmp/<app-name>-<uuid>/)
|
// Individuelles Logverzeichnis vorgeben:
|
||||||
set_program_name("my-service");
|
|
||||||
|
|
||||||
// Oder ein individuelles Logverzeichnis vorgeben:
|
|
||||||
set_log_dir(PathBuf::from("/var/log/my-service"));
|
set_log_dir(PathBuf::from("/var/log/my-service"));
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
+10
-118
@@ -99,9 +99,6 @@ static LOG_LEVEL: AtomicU8 = AtomicU8::new(0);
|
|||||||
/// Lazy-initialisiertes Handle zur Logdatei; kann `None` sein, falls das Öffnen fehlschlug.
|
/// Lazy-initialisiertes Handle zur Logdatei; kann `None` sein, falls das Öffnen fehlschlug.
|
||||||
static LOG_FILE: OnceLock<Mutex<Option<File>>> = OnceLock::new();
|
static LOG_FILE: OnceLock<Mutex<Option<File>>> = OnceLock::new();
|
||||||
|
|
||||||
/// Optionaler benutzerdefinierter Programmname für die Verzeichnisstruktur im Temp-Ordner.
|
|
||||||
static PROGRAM_NAME: OnceLock<RwLock<Option<String>>> = OnceLock::new();
|
|
||||||
|
|
||||||
/// Optionaler benutzerdefinierter Pfad für Logdateien.
|
/// Optionaler benutzerdefinierter Pfad für Logdateien.
|
||||||
static CUSTOM_LOG_DIR: OnceLock<RwLock<Option<PathBuf>>> = OnceLock::new();
|
static CUSTOM_LOG_DIR: OnceLock<RwLock<Option<PathBuf>>> = OnceLock::new();
|
||||||
|
|
||||||
@@ -151,30 +148,6 @@ pub fn get_log_level() -> LogLevel {
|
|||||||
LogLevel::Info
|
LogLevel::Info
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Setzt den Programmnamen für die Logdateibenennung explizit.
|
|
||||||
pub fn set_program_name(name: impl Into<String>) {
|
|
||||||
let lock = PROGRAM_NAME.get_or_init(|| RwLock::new(None));
|
|
||||||
if let Ok(mut guard) = lock.write() {
|
|
||||||
*guard = Some(name.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ermittelt den Programmnamen (aus `set_program_name` oder `std::env::current_exe`).
|
|
||||||
pub fn get_program_name() -> String {
|
|
||||||
if let Some(lock) = PROGRAM_NAME.get() {
|
|
||||||
if let Ok(guard) = lock.read() {
|
|
||||||
if let Some(name) = guard.as_ref() {
|
|
||||||
return name.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
env::current_exe()
|
|
||||||
.ok()
|
|
||||||
.and_then(|p| p.file_stem().map(|s| s.to_string_lossy().to_string()))
|
|
||||||
.filter(|s| !s.is_empty())
|
|
||||||
.unwrap_or_else(|| "app".to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Setzt ein benutzerdefiniertes Verzeichnis für Logdateien.
|
/// Setzt ein benutzerdefiniertes Verzeichnis für Logdateien.
|
||||||
pub fn set_log_dir(path: impl Into<PathBuf>) {
|
pub fn set_log_dir(path: impl Into<PathBuf>) {
|
||||||
let lock = CUSTOM_LOG_DIR.get_or_init(|| RwLock::new(None));
|
let lock = CUSTOM_LOG_DIR.get_or_init(|| RwLock::new(None));
|
||||||
@@ -292,6 +265,15 @@ fn get_or_init_log_file() -> &'static Mutex<Option<File>> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generiert einen zufälligen Fallback-Programmnamen, falls der Name der ausführbaren Datei nicht ermittelt werden kann.
|
||||||
|
fn random_fallback_program_name() -> String {
|
||||||
|
use std::hash::{BuildHasher, Hasher, RandomState};
|
||||||
|
let mut hasher = RandomState::new().build_hasher();
|
||||||
|
hasher.write_i128(OffsetDateTime::now_utc().unix_timestamp_nanos());
|
||||||
|
let val = hasher.finish();
|
||||||
|
format!("app-{:016x}", val)
|
||||||
|
}
|
||||||
|
|
||||||
/// Öffnet (und erstellt bei Bedarf) die tagesbasierte Logdatei.
|
/// Öffnet (und erstellt bei Bedarf) die tagesbasierte Logdatei.
|
||||||
fn open_log_file() -> std::io::Result<File> {
|
fn open_log_file() -> std::io::Result<File> {
|
||||||
let custom_dir = if let Some(lock) = CUSTOM_LOG_DIR.get() {
|
let custom_dir = if let Some(lock) = CUSTOM_LOG_DIR.get() {
|
||||||
@@ -305,7 +287,7 @@ fn open_log_file() -> std::io::Result<File> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut dir = custom_dir.unwrap_or_else(|| {
|
let mut dir = custom_dir.unwrap_or_else(|| {
|
||||||
let program = get_program_name();
|
let program = program_ctdra::program_name_or(random_fallback_program_name());
|
||||||
let mut d = env::temp_dir();
|
let mut d = env::temp_dir();
|
||||||
d.push(format!("{}-{}", program, DEFAULT_LOG_UUID));
|
d.push(format!("{}-{}", program, DEFAULT_LOG_UUID));
|
||||||
d
|
d
|
||||||
@@ -324,93 +306,3 @@ fn open_log_file() -> std::io::Result<File> {
|
|||||||
|
|
||||||
OpenOptions::new().create(true).append(true).open(dir)
|
OpenOptions::new().create(true).append(true).open(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_message_prefixes() {
|
|
||||||
let msg_info = format_message("test", "Info message", &LogLevel::Info);
|
|
||||||
assert!(msg_info.starts_with("[i]"));
|
|
||||||
assert!(msg_info.contains("[INFO][test]: Info message"));
|
|
||||||
|
|
||||||
let msg_err = format_message("test", "Error message", &LogLevel::Error);
|
|
||||||
assert!(msg_err.starts_with("[!]"));
|
|
||||||
assert!(msg_err.contains("[ERROR][test]: Error message"));
|
|
||||||
|
|
||||||
let msg_warn = format_message("test", "Warn message", &LogLevel::Warn);
|
|
||||||
assert!(msg_warn.starts_with("[?]"));
|
|
||||||
assert!(msg_warn.contains("[WARN][test]: Warn message"));
|
|
||||||
|
|
||||||
let msg_debug = format_message("test", "Debug message", &LogLevel::Debug);
|
|
||||||
assert!(msg_debug.starts_with("[d]"));
|
|
||||||
assert!(msg_debug.contains("[DEBUG][test]: Debug message"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_format_message_empty_tag() {
|
|
||||||
let msg = format_message("", "No tag message", &LogLevel::Info);
|
|
||||||
assert!(msg.starts_with("[i]"));
|
|
||||||
assert!(msg.contains("[INFO]: No tag message"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_log_level_display() {
|
|
||||||
assert_eq!(LogLevel::Error.to_string(), "ERROR");
|
|
||||||
assert_eq!(LogLevel::Warn.to_string(), "WARN");
|
|
||||||
assert_eq!(LogLevel::Info.to_string(), "INFO");
|
|
||||||
assert_eq!(LogLevel::Debug.to_string(), "DEBUG");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_log_level_parsing() {
|
|
||||||
assert_eq!(LogLevel::try_from("error").unwrap(), LogLevel::Error);
|
|
||||||
assert_eq!(LogLevel::try_from("ERROR").unwrap(), LogLevel::Error);
|
|
||||||
assert_eq!(LogLevel::try_from("warn").unwrap(), LogLevel::Warn);
|
|
||||||
assert_eq!(LogLevel::try_from("warning").unwrap(), LogLevel::Warn);
|
|
||||||
assert_eq!(LogLevel::try_from("info").unwrap(), LogLevel::Info);
|
|
||||||
assert_eq!(LogLevel::try_from("debug").unwrap(), LogLevel::Debug);
|
|
||||||
assert_eq!(LogLevel::try_from("invalid").unwrap_err(), LogLevel::Info);
|
|
||||||
assert_eq!(LogLevel::from_str("debug").unwrap(), LogLevel::Debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_log_level_ordering() {
|
|
||||||
assert!(LogLevel::Error < LogLevel::Warn);
|
|
||||||
assert!(LogLevel::Warn < LogLevel::Info);
|
|
||||||
assert!(LogLevel::Info < LogLevel::Debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_set_and_get_log_level() {
|
|
||||||
set_log_level(LogLevel::Debug);
|
|
||||||
assert_eq!(get_log_level(), LogLevel::Debug);
|
|
||||||
|
|
||||||
set_log_level(LogLevel::Error);
|
|
||||||
assert_eq!(get_log_level(), LogLevel::Error);
|
|
||||||
|
|
||||||
set_log_level(LogLevel::Info);
|
|
||||||
assert_eq!(get_log_level(), LogLevel::Info);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_convenience_functions() {
|
|
||||||
set_log_level(LogLevel::Debug);
|
|
||||||
error("test", "An error occurred");
|
|
||||||
warn("test", "A warning occurred");
|
|
||||||
info("test", "An info message");
|
|
||||||
debug("test", "A debug message");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_program_name_and_custom_dir() {
|
|
||||||
set_program_name("my-custom-app");
|
|
||||||
assert_eq!(get_program_name(), "my-custom-app");
|
|
||||||
|
|
||||||
let custom_dir = env::temp_dir().join("test-logger-custom-dir");
|
|
||||||
set_log_dir(custom_dir.clone());
|
|
||||||
let file = open_log_file();
|
|
||||||
assert!(file.is_ok());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
use logger_ctdra::{
|
||||||
|
debug, error, format_message, get_log_level, info, init, log, set_log_dir, set_log_level,
|
||||||
|
warn, LogLevel,
|
||||||
|
};
|
||||||
|
use std::env;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_format_message_prefixes() {
|
||||||
|
let msg_info = format_message("test", "Info message", &LogLevel::Info);
|
||||||
|
assert!(msg_info.starts_with("[i]"));
|
||||||
|
assert!(msg_info.contains("[INFO][test]: Info message"));
|
||||||
|
|
||||||
|
let msg_err = format_message("test", "Error message", &LogLevel::Error);
|
||||||
|
assert!(msg_err.starts_with("[!]"));
|
||||||
|
assert!(msg_err.contains("[ERROR][test]: Error message"));
|
||||||
|
|
||||||
|
let msg_warn = format_message("test", "Warn message", &LogLevel::Warn);
|
||||||
|
assert!(msg_warn.starts_with("[?]"));
|
||||||
|
assert!(msg_warn.contains("[WARN][test]: Warn message"));
|
||||||
|
|
||||||
|
let msg_debug = format_message("test", "Debug message", &LogLevel::Debug);
|
||||||
|
assert!(msg_debug.starts_with("[d]"));
|
||||||
|
assert!(msg_debug.contains("[DEBUG][test]: Debug message"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_format_message_empty_tag() {
|
||||||
|
let msg = format_message("", "No tag message", &LogLevel::Info);
|
||||||
|
assert!(msg.starts_with("[i]"));
|
||||||
|
assert!(msg.contains("[INFO]: No tag message"));
|
||||||
|
assert!(!msg.contains("[INFO][]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_format_message_timestamp_format() {
|
||||||
|
let msg = format_message("tag", "payload", &LogLevel::Info);
|
||||||
|
// Format: [i][DD.MM.YYYY HH:MM:SS.mmm][INFO][tag]: payload
|
||||||
|
assert!(msg.starts_with("[i]["));
|
||||||
|
let closing_bracket = msg[3..].find(']').expect("Timestamp closing bracket");
|
||||||
|
let timestamp = &msg[4..4 + closing_bracket - 1];
|
||||||
|
// Timestamp format: DD.MM.YYYY HH:MM:SS.mmm (length: 23)
|
||||||
|
assert_eq!(timestamp.len(), 23);
|
||||||
|
assert_eq!(×tamp[2..3], ".");
|
||||||
|
assert_eq!(×tamp[5..6], ".");
|
||||||
|
assert_eq!(×tamp[10..11], " ");
|
||||||
|
assert_eq!(×tamp[13..14], ":");
|
||||||
|
assert_eq!(×tamp[16..17], ":");
|
||||||
|
assert_eq!(×tamp[19..20], ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_log_level_display() {
|
||||||
|
assert_eq!(LogLevel::Error.to_string(), "ERROR");
|
||||||
|
assert_eq!(LogLevel::Warn.to_string(), "WARN");
|
||||||
|
assert_eq!(LogLevel::Info.to_string(), "INFO");
|
||||||
|
assert_eq!(LogLevel::Debug.to_string(), "DEBUG");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_log_level_parsing_str() {
|
||||||
|
assert_eq!(LogLevel::try_from("error").unwrap(), LogLevel::Error);
|
||||||
|
assert_eq!(LogLevel::try_from("ERROR").unwrap(), LogLevel::Error);
|
||||||
|
assert_eq!(LogLevel::try_from(" error ").unwrap(), LogLevel::Error);
|
||||||
|
assert_eq!(LogLevel::try_from("warn").unwrap(), LogLevel::Warn);
|
||||||
|
assert_eq!(LogLevel::try_from("warning").unwrap(), LogLevel::Warn);
|
||||||
|
assert_eq!(LogLevel::try_from("WARN").unwrap(), LogLevel::Warn);
|
||||||
|
assert_eq!(LogLevel::try_from("WARNING").unwrap(), LogLevel::Warn);
|
||||||
|
assert_eq!(LogLevel::try_from("info").unwrap(), LogLevel::Info);
|
||||||
|
assert_eq!(LogLevel::try_from("INFO").unwrap(), LogLevel::Info);
|
||||||
|
assert_eq!(LogLevel::try_from("debug").unwrap(), LogLevel::Debug);
|
||||||
|
assert_eq!(LogLevel::try_from("DEBUG").unwrap(), LogLevel::Debug);
|
||||||
|
assert_eq!(LogLevel::try_from("invalid").unwrap_err(), LogLevel::Info);
|
||||||
|
assert_eq!(LogLevel::try_from("").unwrap_err(), LogLevel::Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_log_level_parsing_string_and_from_str() {
|
||||||
|
assert_eq!(
|
||||||
|
LogLevel::try_from(String::from("error")).unwrap(),
|
||||||
|
LogLevel::Error
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
LogLevel::try_from(String::from("WARN")).unwrap(),
|
||||||
|
LogLevel::Warn
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
LogLevel::try_from(String::from("invalid")).unwrap_err(),
|
||||||
|
LogLevel::Info
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(LogLevel::from_str("debug").unwrap(), LogLevel::Debug);
|
||||||
|
assert_eq!(LogLevel::from_str("INFO").unwrap(), LogLevel::Info);
|
||||||
|
assert_eq!(LogLevel::from_str("unknown").unwrap_err(), LogLevel::Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_log_level_discriminants_and_traits() {
|
||||||
|
assert_eq!(LogLevel::Error as u8, 1);
|
||||||
|
assert_eq!(LogLevel::Warn as u8, 2);
|
||||||
|
assert_eq!(LogLevel::Info as u8, 3);
|
||||||
|
assert_eq!(LogLevel::Debug as u8, 4);
|
||||||
|
|
||||||
|
let lvl = LogLevel::Info;
|
||||||
|
let lvl_cloned = lvl;
|
||||||
|
assert_eq!(lvl, lvl_cloned);
|
||||||
|
assert_eq!(format!("{:?}", LogLevel::Debug), "Debug");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_log_level_ordering() {
|
||||||
|
assert!(LogLevel::Error < LogLevel::Warn);
|
||||||
|
assert!(LogLevel::Warn < LogLevel::Info);
|
||||||
|
assert!(LogLevel::Info < LogLevel::Debug);
|
||||||
|
assert!(LogLevel::Error <= LogLevel::Error);
|
||||||
|
assert!(LogLevel::Debug >= LogLevel::Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_and_get_log_level() {
|
||||||
|
set_log_level(LogLevel::Debug);
|
||||||
|
assert_eq!(get_log_level(), LogLevel::Debug);
|
||||||
|
|
||||||
|
set_log_level(LogLevel::Error);
|
||||||
|
assert_eq!(get_log_level(), LogLevel::Error);
|
||||||
|
|
||||||
|
set_log_level(LogLevel::Warn);
|
||||||
|
assert_eq!(get_log_level(), LogLevel::Warn);
|
||||||
|
|
||||||
|
set_log_level(LogLevel::Info);
|
||||||
|
assert_eq!(get_log_level(), LogLevel::Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_init_alias() {
|
||||||
|
init(LogLevel::Debug);
|
||||||
|
assert_eq!(get_log_level(), LogLevel::Debug);
|
||||||
|
init(LogLevel::Warn);
|
||||||
|
assert_eq!(get_log_level(), LogLevel::Warn);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_convenience_functions() {
|
||||||
|
set_log_level(LogLevel::Debug);
|
||||||
|
error("test", "An error occurred");
|
||||||
|
warn("test", "A warning occurred");
|
||||||
|
info("test", "An info message");
|
||||||
|
debug("test", "A debug message");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_log_filtering_behavior() {
|
||||||
|
set_log_level(LogLevel::Error);
|
||||||
|
// Debug and Info should be filtered out, Error should pass
|
||||||
|
log("filter_test", "This debug log should be ignored", LogLevel::Debug);
|
||||||
|
log("filter_test", "This info log should be ignored", LogLevel::Info);
|
||||||
|
log("filter_test", "This warn log should be ignored", LogLevel::Warn);
|
||||||
|
log("filter_test", "This error log should pass", LogLevel::Error);
|
||||||
|
|
||||||
|
set_log_level(LogLevel::Debug);
|
||||||
|
log("filter_test", "All logs should pass in Debug level", LogLevel::Debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_log_dir_string_and_pathbuf() {
|
||||||
|
let dir_str = env::temp_dir().join("test-integration-str-dir");
|
||||||
|
set_log_dir(dir_str.to_string_lossy().to_string());
|
||||||
|
|
||||||
|
let dir_pathbuf = env::temp_dir().join("test-integration-pathbuf-dir");
|
||||||
|
set_log_dir(dir_pathbuf);
|
||||||
|
|
||||||
|
set_log_dir("/tmp/test-str-slice-dir");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user