env_assert/
lib.rs

1//! `env_assert` is a incredibly simple Rust library that allows you to only run an `assert!` when an the `RUST_ENV_ASSERT` environmental variable is set to `true`.
2//!
3//! For example:
4//!
5//! ```no_run
6//! use env_assert::env_assert;
7//! fn main() {
8//!     let res = expensive_func_that_should_return_positive();
9//!     env_assert!(res.is_positive()); // "sanity check"
10//!
11//!     println!("We got here because the environmental variable was not set!");
12//! }
13//!
14//! fn expensive_func_that_should_return_positive() -> i8 {
15//!     // do some really hard things here
16//!
17//!     // oh no! our expensive function messed up and is going to return a negative value
18//!     -42
19//! }
20//! ```
21//!
22//! ```text
23//! $ cargo run
24//! We got here because the environmental variable was not set!
25//! ```
26//!
27//! Now lets set our variable and then run
28//!
29//! ```text
30//! $ RUST_ENV_ASSERT=true cargo run
31//! thread 'main' panicked at 'assertion failed: res.is_positive()', src/main.rs:4:5
32//! ```
33//!
34//! ## What problem does this solve?
35//!
36//! Sometimes, the performance increase for running in release mode is significant, but I still want asserts.
37//! However, some of those asserts are in a sense debug asserts, and I would rather the program continue than crash when it is deployed.
38//! This library lets you have asserts while in release mode, without negatively impacting performance for end users.
39//!
40//! ## Should I use this?
41//!
42//! Eh, probably not.
43//! This crate is good for simple testing and pet projects, but if this behavior is desired you should probably now use a [Cargo profile](https://doc.rust-lang.org/cargo/reference/profiles.html) to enable `debug_assert!()` and optimizations at the same time.
44#[macro_export]
45macro_rules! env_assert {
46    ($cond:expr) => {{
47        const KEY: &'static str = "RUST_ENV_ASSERT";
48        match std::env::var(KEY) {
49            Ok(v) => if v == "true" {
50                assert!($cond)
51            }
52            _ => ()
53        }
54    }};
55    ($cond:expr,) => {{
56        const KEY: &'static str = "RUST_ENV_ASSERT";
57        match std::env::var(KEY) {
58            Ok(v) => if v == "true" {
59                assert!($cond)
60            }
61            _ => ()
62        }
63    }};
64    ($cond:expr, $($arg:tt)+) => {{
65        const KEY: &'static str = "RUST_ENV_ASSERT";
66        match std::env::var(KEY) {
67            Ok(v) => if v == "true" {
68                let s = format!($($arg)+);
69                assert!($cond, s)
70            }
71            _ => ()
72        }
73
74    }};
75}
76
77// Note, tests should be run with the environmental variable set, aka RUST_ENV_ASSERT=true cargo test
78#[cfg(test)]
79mod tests {
80    const KEY: &'static str = "RUST_ENV_ASSERT";
81
82    fn set_var_to_true() {
83        std::env::set_var(KEY, "true");
84    }
85
86    fn remove_var() {
87        std::env::remove_var(KEY);
88    }
89
90    #[test]
91    fn just_true() {
92        set_var_to_true();
93        super::env_assert!(true);
94    }
95
96    #[test]
97    fn true_with_comma() {
98        set_var_to_true();
99        super::env_assert!(true,);
100    }
101
102    #[test]
103    fn true_with_fmt() {
104        set_var_to_true();
105        super::env_assert!(true, "didn't crash with {}", 5);
106    }
107
108    #[test]
109    #[should_panic(expected = "false assert is panic")]
110    fn test_panic_var_true() {
111        set_var_to_true();
112        super::env_assert!(false, "false assert is panic");
113    }
114
115    #[test]
116    fn assert_when_var_is_not_set() {
117        remove_var();
118        assert!(std::env::var(KEY).is_err());
119        super::env_assert!(true, "asserting with true");
120        super::env_assert!(false, "asserting with false");
121    }
122}