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}