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}