Skip to main content

fungus/core/
assert.rs

1#![allow(unused_imports)]
2use crate::function;
3use gory::*;
4
5pub const TEST_TEMP_DIR: &str = "tests/temp";
6
7/// Create the test `setup` function to be called in tests to disable RUST_BACKTRACE
8/// and create a directory to work in for testing that depends on modifying files on
9/// disk. The intent is to provide a thread safe space from which to manipulate
10/// files during a test.
11///
12/// `setup` accepts two arguments `root` and `func_name`. `root` and `func_name` are
13/// joined as a path and treated as the directory path that will be created for
14/// tests.
15///
16/// ### Examples
17/// ```
18/// use fungus::assert::*;
19///
20/// create_test_setup_func!();
21/// setup("tests/temp", "create_test_setup_func");
22/// assert_dir!("tests/temp/create_test_setup_func");
23/// assert_remove_all!("tests/temp/create_test_setup_func");
24/// ```
25#[macro_export]
26macro_rules! create_test_setup_func {
27    () => {
28        use std::sync::Once;
29        static TEST_INIT: Once = Once::new();
30        fn setup<T: AsRef<Path>, U: AsRef<Path>>(root: T, func_name: U) -> PathBuf {
31            TEST_INIT.call_once(|| {
32                std::env::set_var("RUST_BACKTRACE", "0");
33            });
34            let target = root.as_ref().to_owned().mash(func_name.as_ref());
35            assert!(sys::remove_all(&target).is_ok());
36            assert!(sys::mkdir(&target).is_ok());
37            target
38        }
39    };
40}
41
42/// Call the `setup` function created by `create_test_setup_func!` with default
43/// `root` and `func_name` or optionally override those values. `root` will
44/// default to `TEST_TEMP_DIR` and `func_name` defaults to the function name
45/// using `function!`. However since doc tests always have a default function
46/// name of `rust_out::main` its useful to override the function name in those
47/// cases.
48///
49/// ### Examples
50/// ```
51/// use fungus::assert::*;
52/// create_test_setup_func!();
53///
54/// // Defaults
55/// fn assert_setup_default() {
56///     let tmpdir = assert_setup!();
57///     assert_dir!(&tmpdir);
58///     assert_eq!(&tmpdir, &PathBuf::from(TEST_TEMP_DIR).mash("assert_setup_default"));
59///     assert_remove_all!(&tmpdir);
60/// }
61/// assert_setup_default();
62///
63/// // Alternate function name
64/// let func_name = "assert_setup_func";
65/// let tmpdir = assert_setup!(&func_name);
66/// assert_dir!(&tmpdir);
67/// assert_eq!(&tmpdir, &PathBuf::from(TEST_TEMP_DIR).mash(&func_name));
68/// assert_remove_all!(&tmpdir);
69///
70/// // Alternate root and function name
71/// let root = "tests/temp/assert_setup_root";
72/// let func_name = "assert_setup_func";
73/// let tmpdir = assert_setup!(&root, &func_name);
74/// assert_dir!(&tmpdir);
75/// assert_eq!(&tmpdir, &PathBuf::from(&root).mash(&func_name));
76/// assert_remove_all!(&root);
77/// ```
78#[macro_export]
79macro_rules! assert_setup {
80    () => {
81        setup(TEST_TEMP_DIR, function!())
82    };
83    ($func:expr) => {
84        setup(TEST_TEMP_DIR, $func)
85    };
86    ($root:expr, $func:expr) => {
87        setup($root, $func)
88    };
89}
90
91/// Assert that a directory exists
92///
93/// ### Examples
94/// ```
95/// use fungus::assert::*;
96/// create_test_setup_func!();
97///
98/// let tmpdir = assert_setup!("assert_dir");
99/// assert_dir!(&tmpdir);
100/// assert_remove_all!(&tmpdir);
101/// ```
102#[macro_export]
103macro_rules! assert_dir {
104    ($path:expr) => {
105        if !sys::is_dir($path) {
106            panic!("\n{}:\n  {} => {}\n", "assert_dir!".cyan(), format!("{:?}", $path).red(), "doesn't exist or not a directory".yellow());
107        }
108    };
109}
110
111/// Assert that a directory doesn't exists
112///
113/// ### Examples
114/// ```
115/// use fungus::assert::*;
116///
117/// let tmpdir = PathBuf::from(TEST_TEMP_DIR).mash("assert_no_dir");
118/// assert_no_dir!(&tmpdir);
119/// ```
120#[macro_export]
121macro_rules! assert_no_dir {
122    ($path:expr) => {
123        if sys::is_dir($path) {
124            panic!("\n{}:\n  {} => {}\n", "assert_no_dir!".cyan(), format!("{:?}", $path).red(), "exists".yellow());
125        }
126    };
127}
128
129/// Assert that a file or directory exists
130///
131/// ### Examples
132/// ```
133/// use fungus::assert::*;
134/// create_test_setup_func!();
135///
136/// let tmpdir = assert_setup!("assert_exists");
137/// assert_exists!(&tmpdir);
138/// let file = tmpdir.mash("file");
139/// sys::touch(&file).unwrap();
140/// assert_exists!(&file);
141/// assert_remove_all!(&tmpdir);
142/// ```
143#[macro_export]
144macro_rules! assert_exists {
145    ($path:expr) => {
146        if !sys::exists($path) {
147            panic!("\n{}:\n  {} => {}\n", "assert_exists!".cyan(), format!("{:?}", $path).red(), "doesn't exist".yellow());
148        }
149    };
150}
151
152/// Assert that a file or directory doesn't exists
153///
154/// ### Examples
155/// ```
156/// use fungus::assert::*;
157///
158/// assert_no_exists!("tests/temp/assert_no_exists");
159/// assert_no_exists!("tests/temp/assert_no_exists/file");
160/// ```
161#[macro_export]
162macro_rules! assert_no_exists {
163    ($path:expr) => {
164        if sys::exists($path) {
165            panic!("\n{}:\n  {} => {}\n", "assert_no_exists!".cyan(), format!("{:?}", $path).red(), "exists".yellow());
166        }
167    };
168}
169
170/// Assert that a file exists
171///
172/// ### Examples
173/// ```
174/// use fungus::assert::*;
175/// create_test_setup_func!();
176///
177/// let tmpdir = assert_setup!("assert_file");
178/// let file = tmpdir.mash("file");
179/// sys::touch(&file).unwrap();
180/// assert_file!(&file);
181/// assert_remove_all!(&tmpdir);
182/// ```
183#[macro_export]
184macro_rules! assert_file {
185    ($path:expr) => {
186        if !sys::is_file($path) {
187            panic!("\n{}:\n  {} => {}\n", "assert_file!".cyan(), format!("{:?}", $path).red(), "doesn't exist or not a file".yellow());
188        }
189    };
190}
191
192/// Assert that a file doesn't exists
193///
194/// ### Examples
195/// ```
196/// use fungus::assert::*;
197///
198/// assert_no_file!("tests/temp/assert_no_file/file");
199/// ```
200#[macro_export]
201macro_rules! assert_no_file {
202    ($path:expr) => {
203        if sys::is_file($path) {
204            panic!("\n{}:\n  {} => {}\n", "assert_no_file!".cyan(), format!("{:?}", $path).red(), "exists".yellow());
205        }
206    };
207}
208
209/// Wraps `sys::remove` in an assertion that the file no longer exists and
210/// provides some nice output if something fails.
211///
212/// ### Examples
213/// ```
214/// use fungus::assert::*;
215/// create_test_setup_func!();
216///
217/// let tmpdir = assert_setup!();
218/// let file = tmpdir.mash("file");
219/// sys::touch(&file).unwrap();
220/// assert_file!(&file);
221/// assert_remove!(&file);
222/// assert_no_file!(&file);
223/// assert_remove_all!(&tmpdir);
224/// ```
225#[macro_export]
226macro_rules! assert_remove {
227    ($path:expr) => {
228        if let Err(err) = sys::remove($path) {
229            panic!("\n{}:\n  {} => {}\n", "assert_remove!".cyan(), format!("{:?}", $path).red(), format!("{}", err).yellow());
230        }
231        if sys::exists($path) {
232            panic!("\n{}:\n  {} => {}\n", "assert_remove!".cyan(), format!("{:?}", $path).red(), "still exists".yellow());
233        }
234    };
235}
236
237/// Wraps `sys::remove_all` in an assertion that the directory no longer exists
238/// and provides some nice output if something fails.
239///
240/// ### Examples
241/// ```
242/// use fungus::assert::*;
243/// create_test_setup_func!();
244///
245/// let tmpdir = assert_setup!();
246/// assert_exists!(&tmpdir);
247/// assert_remove_all!(&tmpdir);
248/// assert_no_exists!(&tmpdir);
249/// ```
250#[macro_export]
251macro_rules! assert_remove_all {
252    ($path:expr) => {
253        if let Err(err) = sys::remove_all($path) {
254            panic!("\n{}:\n  {} => {}\n", "assert_remove_all!".cyan(), format!("{:?}", $path).red(), format!("{}", err).yellow());
255        }
256        if sys::exists($path) {
257            panic!("\n{}:\n  {} => {}\n", "assert_remove_all!".cyan(), format!("{:?}", $path).red(), "still exists".yellow());
258        }
259    };
260}
261
262// Unit tests
263// -------------------------------------------------------------------------------------------------
264#[cfg(test)]
265mod tests {
266    use crate::assert::*;
267    create_test_setup_func!();
268
269    #[test]
270    fn test_assert_setup() {
271        // Defaults
272        {
273            let tmpdir = assert_setup!();
274            assert_dir!(&tmpdir);
275            assert_eq!(&tmpdir, &PathBuf::from(TEST_TEMP_DIR).mash("test_assert_setup"));
276            assert_remove_all!(&tmpdir);
277        }
278
279        // Alternate func name
280        {
281            let func_name = "test_assert_setup_alt_func";
282            let tmpdir = assert_setup!(&func_name);
283            assert_dir!(&tmpdir);
284            assert_eq!(&tmpdir, &PathBuf::from(TEST_TEMP_DIR).mash(&func_name));
285            assert_remove_all!(&tmpdir);
286        }
287
288        // Alternate temp dir name and func name
289        {
290            let root = "tests/temp/test_assert_setup_dir";
291            let func_name = "test_assert_setup_alt_func";
292            let tmpdir = assert_setup!(&root, &func_name);
293            assert_dir!(&tmpdir);
294            assert_eq!(&tmpdir, &PathBuf::from(&root).mash(&func_name));
295            assert_remove_all!(&root);
296        }
297    }
298
299    #[test]
300    fn test_assert_dir() {
301        let tmpdir = assert_setup!();
302
303        let temp_dir = tmpdir.mash("foo");
304        assert_no_dir!(&temp_dir);
305        assert!(!sys::is_dir(&temp_dir));
306        sys::mkdir(&temp_dir).unwrap();
307        assert_dir!(&temp_dir);
308        assert!(sys::is_dir(&temp_dir));
309
310        assert_remove_all!(&tmpdir);
311    }
312
313    #[test]
314    fn test_assert_file() {
315        let tmpdir = assert_setup!();
316
317        let temp_file = tmpdir.mash("foo");
318        assert_no_file!(&temp_file);
319        assert!(!sys::is_file(&temp_file));
320        sys::touch(&temp_file).unwrap();
321        assert_file!(&temp_file);
322        assert!(sys::is_file(&temp_file));
323
324        assert_remove_all!(&tmpdir);
325    }
326
327    #[test]
328    fn test_assert_exists() {
329        let tmpdir = assert_setup!();
330
331        // Test file exists
332        {
333            let file = tmpdir.mash("file");
334            assert_no_exists!(&file);
335            assert!(!sys::exists(&file));
336            sys::touch(&file).unwrap();
337            assert_exists!(&file);
338            assert!(sys::exists(&file));
339
340            sys::remove(&file).unwrap();
341            assert_no_exists!(&file);
342            assert!(!sys::exists(&file));
343        }
344
345        // Test dir exists
346        {
347            let dir = tmpdir.mash("dir");
348            assert_no_exists!(&dir);
349            assert!(!sys::exists(&dir));
350            sys::mkdir(&dir).unwrap();
351            assert_exists!(&dir);
352            assert!(sys::exists(&dir));
353
354            sys::remove_all(&dir).unwrap();
355            assert_no_exists!(&dir);
356            assert!(!sys::exists(&dir));
357        }
358
359        assert_remove_all!(&tmpdir);
360    }
361
362    #[test]
363    fn test_assert_remove() {
364        let tmpdir = assert_setup!();
365
366        let file = tmpdir.mash("foo");
367        sys::touch(&file).unwrap();
368        assert_file!(&file);
369        assert_remove!(&file);
370        assert_no_file!(&file);
371
372        assert_remove_all!(&tmpdir);
373    }
374
375    #[test]
376    fn test_assert_remove_all() {
377        let tmpdir = assert_setup!();
378
379        let file = tmpdir.mash("foo");
380        sys::touch(&file).unwrap();
381        assert_file!(&file);
382        assert_remove!(&file);
383        assert_no_file!(&file);
384        assert_dir!(&tmpdir);
385        assert_remove_all!(&tmpdir);
386        assert_no_dir!(&tmpdir);
387    }
388}