testing_logger-0.1.1/.gitignore010064400007650000024000000000361333173154600147410ustar0000000000000000/target **/*.rs.bk Cargo.lock testing_logger-0.1.1/.travis.yml010064400007650000024000000002301333215651300150520ustar0000000000000000language: rust rust: - stable - beta - nightly matrix: allow_failures: - rust: nightly fast_finish: true notifications: email: false testing_logger-0.1.1/Cargo.toml.orig010064400007650000024000000010521333217605600156370ustar0000000000000000[package] name = "testing_logger" version = "0.1.1" authors = ["brucechapman ", "NEC New Zealand Limited"] license = "BSD-3-Clause" description = "Supports writing tests to verify `log` crate calls" repository = "https://github.com/brucechapman/rust_testing_logger" readme = "README.md" categories = ["development-tools::testing", "development-tools::debugging"] keywords = ["testing", "logging", "log"] [badges] travis-ci = { repository = "brucechapman/rust_testing_logger", branch = "master" } [dependencies] log = "0.4.3" testing_logger-0.1.1/Cargo.toml0000644000000020660000000000000121100ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "testing_logger" version = "0.1.1" authors = ["brucechapman ", "NEC New Zealand Limited"] description = "Supports writing tests to verify `log` crate calls" readme = "README.md" keywords = ["testing", "logging", "log"] categories = ["development-tools::testing", "development-tools::debugging"] license = "BSD-3-Clause" repository = "https://github.com/brucechapman/rust_testing_logger" [dependencies.log] version = "0.4.3" [badges.travis-ci] branch = "master" repository = "brucechapman/rust_testing_logger" testing_logger-0.1.1/LICENSE010064400007650000024000000027641333215651300137640ustar0000000000000000BSD 3-Clause License Copyright (c) 2018, NEC New Zealand Limited. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. testing_logger-0.1.1/README.md010064400007650000024000000021031333217653600142300ustar0000000000000000# testing_logger A Rust library to support testing of code that uses `log` crate. [![Version][version-img]][version-url] [![Documentation][doc-img]][doc-url] ![license][license-img] [![Status][status-img]][status-url] ## Example ```rust #[macro_use] extern crate log; use log::Level; extern crate testing_logger; #[test] fn test_something() { testing_logger::setup(); warn!("Something went wrong with {}", 10); testing_logger::validate( |captured_logs| { assert_eq!(captured_logs.len(), 1); assert_eq!(captured_logs[0].body, "Something went wrong with 10"); assert_eq!(captured_logs[0].level, Level::Warn); }); } ``` [status-img]:https://travis-ci.com/brucechapman/rust_testing_logger.svg?branch=master [status-url]:https://travis-ci.com/brucechapman/rust_testing_logger [version-img]:https://img.shields.io/crates/v/testing_logger.svg [version-url]:https://crates.io/crates/testing_logger [doc-img]:https://docs.rs/testing_logger/badge.svg [doc-url]:https://docs.rs/testing_logger [license-img]:https://img.shields.io/crates/l/testing_logger.svg testing_logger-0.1.1/src/lib.rs010064400007650000024000000076761333214361200146650ustar0000000000000000//! This crate supports testing and asserting that appropriate log messages //! from the `log` crate are generated during tests. //! //! Log events are captured in a thread_local variable so this module behaves correctly //! when tests are run multithreaded. //! //! All log levels are captured, but none are sent to any logging system. The //! test developer should use the `validate()` function in order to check //! the captured log messages. //! //! # Examples //! ``` //! #[macro_use] //! extern crate log; //! use log::Level; //! extern crate testing_logger; //! //! # fn main() { test_something();} //! # /* Don't put #[test] in code when running doc tests but DO put it in the documentation //! #[test] //! # */ //! fn test_something() { //! testing_logger::setup(); //! warn!("Something went wrong with {}", 10); //! testing_logger::validate( |captured_logs| { //! assert_eq!(captured_logs.len(), 1); //! assert_eq!(captured_logs[0].body, "Something went wrong with 10"); //! assert_eq!(captured_logs[0].level, Level::Warn); //! }); //! } //! ``` //! The target is also captured if you want to validate that. //! ``` //! //! # #[macro_use] //! # extern crate log; //! # use log::Level; //! # extern crate testing_logger; //! # fn main() { test_target();} //! # /* Don't put #[test] in code when running doc tests but DO put it in the documentation //! #[test] //! # */ //! fn test_target() { //! testing_logger::setup(); //! log!(target: "documentation", Level::Trace, "targetted log message"); //! testing_logger::validate( |captured_logs| { //! assert_eq!(captured_logs.len(), 1); //! assert_eq!(captured_logs[0].target, "documentation"); //! assert_eq!(captured_logs[0].body, "targetted log message"); //! assert_eq!(captured_logs[0].level, Level::Trace); //! }); //! } //! ``` extern crate log; use log::{Log, Record, Metadata, LevelFilter, Level}; use std::cell::RefCell; use std::sync::{Once, ONCE_INIT}; /// A captured call to the logging system. A `Vec` of these is passed /// to the closure supplied to the `validate()` function. pub struct CapturedLog { /// The formatted log message. pub body: String, /// The level. pub level: Level, /// The target. pub target: String } thread_local!(static LOG_RECORDS: RefCell> = RefCell::new(Vec::with_capacity(3))); struct TestingLogger {} impl Log for TestingLogger { #[allow(unused_variables)] fn enabled(&self, metadata: &Metadata) -> bool { true // capture all log levels } fn log(& self, record: &Record) { LOG_RECORDS.with( |records| { let captured_record = CapturedLog { body: format!("{}",record.args()), level: record.level(), target: record.target().to_string() }; records.borrow_mut().push(captured_record); }); } fn flush(&self) {} } static FIRST_TEST: Once = ONCE_INIT; static TEST_LOGGER: TestingLogger = TestingLogger{}; /// Prepare the `testing_logger` to capture log messages for a test. /// /// Should be called from every test that calls `validate()`, before any calls to the logging system. /// This function will install an internal `TestingLogger` as the logger if not already done so, and initialise /// its thread local storage for a new test. pub fn setup() { FIRST_TEST.call_once( || { log::set_logger(&TEST_LOGGER).map(|()| log::set_max_level(LevelFilter::Trace)).unwrap(); }); LOG_RECORDS.with( |records| { records.borrow_mut().truncate(0); }); } /// Used to validate any captured log events. /// /// the `asserter` closure can check the number, body, target and level /// of captured log events. As a side effect, the records are cleared. pub fn validate(asserter: F) where F: Fn(&Vec) { LOG_RECORDS.with( |records| { asserter(&records.borrow()); records.borrow_mut().truncate(0); }); }