From 4c92d73f422011d9bd5a51bc463b04191c6b3ab1 Mon Sep 17 00:00:00 2001 From: mcmah309 Date: Mon, 23 Dec 2024 22:05:56 +0000 Subject: [PATCH] test: Add err_trail tests --- .github/workflows/ci.yml | 8 +- err_trail/Cargo.toml | 4 + err_trail/tests/mod.rs | 236 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 err_trail/tests/mod.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6b4b38..f3c6c95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,8 @@ jobs: - name: Run std tests run: cargo test --verbose --tests - name: Run no_std tests - run: rustup target add x86_64-unknown-linux-gnu && cd test_no_std && cargo run - - name: Run feature flags tests - run: cargo test --tests --features tracing && cargo test --tests --features log + run: rustup target add x86_64-unknown-linux-gnu && cd error_set/test_no_std && cargo run + - name: Run error_set feature flags tests + run: cd error_set && cargo test --tests --features tracing && cargo test --tests --features log + - name: Run err_trail feature flags tests + run: cd err_trail && cargo test --tests --features tracing && cargo test --tests --features log diff --git a/err_trail/Cargo.toml b/err_trail/Cargo.toml index e527cac..3151b1f 100644 --- a/err_trail/Cargo.toml +++ b/err_trail/Cargo.toml @@ -8,6 +8,10 @@ tracing = { version = "0.1", optional = true } log = { version = "0.4", optional = true } defmt = { version = "0.3", optional = true } +[dev-dependencies] +tracing-test = { version = "0.2", features = ["no-env-filter"] } +lazy_static = "1" + [features] default = ["stub"] # Enables support for the tracing crate. Adds methods to `Result` that are applied on `Err` - e.g. `result.warn(...)`. diff --git a/err_trail/tests/mod.rs b/err_trail/tests/mod.rs new file mode 100644 index 0000000..92e57ed --- /dev/null +++ b/err_trail/tests/mod.rs @@ -0,0 +1,236 @@ +#[cfg(feature = "tracing")] +#[cfg(test)] +mod tracing { + use err_trail::{ErrContext, ErrContextDisplay, NoneContext}; + use tracing_test::traced_test; + + #[traced_test] + #[test] + fn test_error_context() { + let result: Result<(), &str> = Err("error"); + let _ = result.error_context("An error occurred"); + + assert!(logs_contain("An error occurred")); + } + + #[traced_test] + #[test] + fn test_warn_context() { + let result: Result<(), &str> = Err("warning"); + let _ = result.warn_context("A warning occurred"); + + assert!(logs_contain("A warning occurred")); + } + + #[traced_test] + #[test] + fn test_with_error_context() { + let result: Result<(), &str> = Err("error"); + let _ = result.with_error_context(|e| format!("An error occurred: `{}`", e)); + + assert!(logs_contain("An error occurred: `error`")); + } + + #[traced_test] + #[test] + fn test_with_warn_context() { + let result: Result<(), &str> = Err("warning"); + let _ = result.with_warn_context(|e| format!("A warning occurred: `{}`", e)); + + assert!(logs_contain("A warning occurred: `warning`")); + } + + #[traced_test] + #[test] + fn test_consume_as_error() { + let result: Result<(), &str> = Err("consumed error"); + let _ = result.consume_as_error(); + + assert!(logs_contain("consumed error")); + } + + #[traced_test] + #[test] + fn test_consume_as_warn() { + let result: Result<(), &str> = Err("consumed warning"); + let _ = result.consume_as_warn(); + + assert!(logs_contain("consumed warning")); + } + + #[traced_test] + #[test] + fn test_option_error_context() { + let option: Option<()> = None; + let _ = option.error_context("Option was none"); + + assert!(logs_contain("Option was none")); + } + + #[traced_test] + #[test] + fn test_option_warn_context() { + let option: Option<()> = None; + let _ = option.warn_context("Option was none"); + + assert!(logs_contain("Option was none")); + } + + #[traced_test] + #[test] + fn test_option_with_error_context() { + let option: Option<()> = None; + let _ = option.with_error_context(|| "Lazy error context"); + + assert!(logs_contain("Lazy error context")); + } + + #[traced_test] + #[test] + fn test_option_with_warn_context() { + let option: Option<()> = None; + let _ = option.with_warn_context(|| "Lazy warn context"); + + assert!(logs_contain("Lazy warn context")); + } +} + +#[cfg(feature = "log")] +#[cfg(test)] +mod log { + use err_trail::{ErrContext, ErrContextDisplay, NoneContext}; + use lazy_static::lazy_static; + use log::{Level, Metadata, Record}; + use std::sync::{Arc, Mutex}; + + struct TestLogger { + logs: Arc>>, + } + + impl log::Log for TestLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + metadata.level() <= Level::Trace + } + + fn log(&self, record: &Record) { + if self.enabled(record.metadata()) { + let mut logs = self.logs.lock().unwrap(); + logs.push(format!("{}", record.args())); + } + } + + fn flush(&self) {} + } + + lazy_static! { + static ref LOGS: Arc>> = { + let logs = Arc::new(Mutex::new(Vec::new())); + let test_logger = TestLogger { logs: logs.clone() }; + + log::set_boxed_logger(Box::new(test_logger)).unwrap(); + log::set_max_level(log::LevelFilter::Trace); + + logs + }; + } + + fn logs_contain(expected: &str) -> bool { + let logs = LOGS.lock().unwrap(); + logs.iter().any(|log| log.contains(expected)) + } + + fn clear_logs() { + let mut logs = LOGS.lock().unwrap(); + logs.clear(); + } + + #[test] + fn test_error_context() { + clear_logs(); + let result: Result<(), &str> = Err("error"); + let _ = result.error_context("An error occurred"); + + assert!(logs_contain("An error occurred")); + } + + #[test] + fn test_warn_context() { + clear_logs(); + let result: Result<(), &str> = Err("warning"); + let _ = result.warn_context("A warning occurred"); + + assert!(logs_contain("A warning occurred")); + } + + #[test] + fn test_with_error_context() { + clear_logs(); + let result: Result<(), &str> = Err("error"); + let _ = result.with_error_context(|e| format!("An error occurred: `{}`", e)); + + assert!(logs_contain("An error occurred: `error`")); + } + + #[test] + fn test_with_warn_context() { + clear_logs(); + let result: Result<(), &str> = Err("warning"); + let _ = result.with_warn_context(|e| format!("A warning occurred: `{}`", e)); + + assert!(logs_contain("A warning occurred: `warning`")); + } + + #[test] + fn test_consume_as_error() { + clear_logs(); + let result: Result<(), &str> = Err("consumed error"); + let _ = result.consume_as_error(); + + assert!(logs_contain("consumed error")); + } + + #[test] + fn test_consume_as_warn() { + clear_logs(); + let result: Result<(), &str> = Err("consumed warning"); + let _ = result.consume_as_warn(); + + assert!(logs_contain("consumed warning")); + } + + #[test] + fn test_option_error_context() { + clear_logs(); + let option: Option<()> = None; + let _ = option.error_context("Option was none"); + + assert!(logs_contain("Option was none")); + } + + #[test] + fn test_option_warn_context() { + clear_logs(); + let option: Option<()> = None; + let _ = option.warn_context("Option was none"); + + assert!(logs_contain("Option was none")); + } + + #[test] + fn test_option_with_error_context() { + clear_logs(); + let option: Option<()> = None; + let _ = option.with_error_context(|| "Lazy error context"); + + assert!(logs_contain("Lazy error context")); + } + + #[test] + fn test_option_with_warn_context() { + clear_logs(); + let option: Option<()> = None; + let _ = option.with_warn_context(|| "Lazy warn context"); + + assert!(logs_contain("Lazy warn context")); + } +}