1 #[cfg(test)]
2 mod test {
3     use crate::*;
4     use futures::future::join5;
5     use std::cmp::{max, min};
6     use std::fs::{create_dir, read_to_string, remove_file};
7 
8     #[test]
test_branch()9     fn test_branch() {
10         let d: TreeBuilder = TreeBuilder::new();
11         d.add_leaf("1");
12         {
13             let _l = d.enter_scoped();
14             d.add_leaf("1.1");
15             d.add_leaf("1.2");
16         }
17         d.add_leaf("2");
18         d.add_leaf("3");
19         let _l = d.enter_scoped();
20         d.add_leaf("3.1");
21         d.add_leaf("3.2");
22         d.peek_print();
23         assert_eq!(
24             "\
25 1
26 ├╼ 1.1
27 └╼ 1.2
28 2
29 3
30 ├╼ 3.1
31 └╼ 3.2",
32             d.string()
33         );
34     }
35 
36     #[test]
test_branch2()37     fn test_branch2() {
38         let d = TreeBuilder::new();
39         d.add_leaf("1");
40         {
41             let _scope = d.enter_scoped();
42             d.add_leaf("1.1");
43             {
44                 let _scope = d.enter_scoped();
45                 d.add_leaf("1.1.1");
46             }
47         }
48 
49         d.add_leaf("2");
50         d.enter();
51         d.add_leaf("2.1");
52         d.enter();
53         d.add_leaf("2.1.1");
54         d.peek_print();
55         assert_eq!(
56             "\
57 1
58 └╼ 1.1
59   └╼ 1.1.1
60 2
61 └╼ 2.1
62   └╼ 2.1.1",
63             d.string()
64         );
65     }
66 
67     #[test]
simple()68     fn simple() {
69         let d = TreeBuilder::new();
70         d.add_leaf("Hi");
71         assert_eq!("Hi", d.string());
72     }
73 
74     #[test]
depth()75     fn depth() {
76         let d = TreeBuilder::new();
77         assert_eq!(0, d.depth());
78         d.add_leaf("Hi");
79         assert_eq!(0, d.depth());
80         let _b = d.add_branch("Hi");
81         assert_eq!(1, d.depth());
82         d.add_leaf("Hi");
83         assert_eq!(1, d.depth());
84     }
85 
86     #[test]
indent()87     fn indent() {
88         let d = TreeBuilder::new();
89         d.add_leaf("1");
90         add_branch_to!(d);
91         d.add_leaf("1.1");
92         {
93             add_branch_to!(d);
94             d.add_leaf("1.1.1");
95         }
96         d.set_config_override(TreeConfig::new().indent(4));
97         d.peek_print();
98         assert_eq!(
99             "\
100 1
101 └──╼ 1.1
102     └──╼ 1.1.1",
103             d.string()
104         );
105     }
106 
107     #[test]
macros()108     fn macros() {
109         let d = TreeBuilder::new();
110         add_leaf_to!(d, "1");
111         {
112             add_branch_to!(d);
113             add_leaf_to!(d, "1.1")
114         }
115         d.peek_print();
116         assert_eq!(
117             "\
118 1
119 └╼ 1.1",
120             d.string()
121         );
122     }
123 
124     #[test]
macros_with_fn()125     fn macros_with_fn() {
126         let d = TreeBuilder::new();
127         let tree = || d.clone();
128         add_leaf_to!(tree(), "1");
129         {
130             add_branch_to!(tree());
131             add_leaf_to!(tree(), "1.1")
132         }
133         tree().peek_print();
134         assert_eq!(
135             "\
136 1
137 └╼ 1.1",
138             d.string()
139         );
140     }
141 
142     #[test]
leaf_with_value()143     fn leaf_with_value() {
144         let d = TreeBuilder::new();
145         let value = add_leaf_value_to!(d, 1);
146         d.peek_print();
147         assert_eq!("1", d.string());
148         assert_eq!(1, value);
149     }
150 
151     #[test]
macros2()152     fn macros2() {
153         let d = TreeBuilder::new();
154         add_branch_to!(d, "1");
155         add_leaf_to!(d, "1.1");
156         d.peek_print();
157         assert_eq!(
158             "\
159 1
160 └╼ 1.1",
161             d.string()
162         );
163     }
164 
165     #[test]
mid()166     fn mid() {
167         let d = TreeBuilder::new();
168         d.add_leaf(&format!("{}{}", "1", "0"));
169         d.enter();
170         d.add_leaf("10.1");
171         d.add_leaf("10.2");
172         d.enter();
173         d.add_leaf("10.1.1");
174         d.add_leaf("10.1.2\nNext line");
175         d.exit();
176         d.add_leaf(&format!("10.3"));
177         d.peek_print();
178         assert_eq!(
179             "\
180 10
181 ├╼ 10.1
182 ├╼ 10.2
183 │ ├╼ 10.1.1
184 │ └╼ 10.1.2
185 │    Next line
186 └╼ 10.3",
187             d.string()
188         );
189     }
190 
factors(x: usize)191     fn factors(x: usize) {
192         add_branch!("{}", x);
193         for i in 1..x {
194             if x % i == 0 {
195                 factors(i);
196             }
197         }
198     }
199 
200     #[test]
recursive()201     fn recursive() {
202         factors(6);
203         default_tree().peek_print();
204         assert_eq!(
205             "\
206 6
207 ├╼ 1
208 ├╼ 2
209 │ └╼ 1
210 └╼ 3
211   └╼ 1",
212             default_tree().string()
213         );
214     }
215 
a()216     fn a() {
217         add_branch!("a");
218         b();
219         c();
220     }
221 
b()222     fn b() {
223         add_branch!("b");
224         c();
225     }
226 
c()227     fn c() {
228         add_branch!("c");
229         add_leaf!("Nothing to see here");
230     }
231 
232     #[test]
nested()233     fn nested() {
234         a();
235         default_tree().peek_print();
236         assert_eq!(
237             "\
238 a
239 ├╼ b
240 │ └╼ c
241 │   └╼ Nothing to see here
242 └╼ c
243   └╼ Nothing to see here",
244             default_tree().string()
245         );
246     }
247 
248     #[test]
disabled_output()249     fn disabled_output() {
250         let tree = TreeBuilder::new();
251         tree.set_enabled(false);
252         add_leaf_to!(tree, "Leaf");
253         tree.add_leaf("Leaf");
254 
255         add_branch_to!(tree, "Branch");
256         tree.add_branch("Branch");
257         assert_eq!("", tree.string());
258     }
259 
260     #[test]
enabled_output()261     fn enabled_output() {
262         let tree = TreeBuilder::new();
263         tree.set_enabled(false);
264         add_branch_to!(tree, "Ignored branch");
265         add_leaf_to!(tree, "Ignored leaf");
266         tree.set_enabled(true);
267         add_leaf_to!(tree, "Leaf");
268         tree.add_leaf("Leaf");
269 
270         add_branch_to!(tree, "Branch");
271         tree.add_branch("Branch");
272         assert_eq!(
273             "Leaf
274 Leaf
275 Branch
276 └╼ Branch",
277             tree.string()
278         );
279     }
280 
281     #[test]
tree_by_name()282     fn tree_by_name() {
283         clear("A");
284         let b = tree("B");
285         b.clear();
286         {
287             add_branch_to!("A", "1");
288             add_branch_to!(b, "3");
289             add_leaf_to!("A", "1.1");
290             add_leaf_to!("B", "3.1");
291         }
292         add_leaf_to!("A", "2");
293         peek_print("A");
294         b.peek_print();
295         assert_eq!(
296             "1
297 └╼ 1.1
298 2",
299             string("A")
300         );
301         assert_eq!(
302             "3
303 └╼ 3.1",
304             b.string()
305         );
306     }
307 
308     #[test]
tree_by_name_disabled()309     fn tree_by_name_disabled() {
310         let d = tree("D");
311         d.clear();
312         d.set_enabled(true);
313         clear("C");
314         set_enabled("C", false);
315         {
316             add_branch_to!("C", "1");
317             set_enabled("C", true);
318             add_branch_to!(d, "3");
319             add_leaf_to!("C", "1.1");
320             d.set_enabled(false);
321             add_leaf_to!("D", "3.1");
322         }
323         add_leaf_to!("C", "2");
324         peek_print("C");
325         d.peek_print();
326         assert_eq!(
327             "1.1
328 2",
329             string("C")
330         );
331         assert_eq!("3", d.string());
332     }
333 
334     #[test]
defer_write()335     fn defer_write() {
336         let tree = TreeBuilder::new();
337         {
338             create_dir("test_out").ok();
339             remove_file("test_out/defer_write.txt").ok();
340             File::create("test_out/defer_write.txt").unwrap();
341             defer_write!(tree, "test_out/defer_write.txt");
342             tree.add_leaf("Branch");
343             assert_eq!(read_to_string("test_out/defer_write.txt").unwrap(), "");
344             assert_eq!(tree.peek_string(), "Branch");
345         }
346         assert_eq!(tree.peek_string(), "");
347         assert_eq!(
348             read_to_string("test_out/defer_write.txt").unwrap(),
349             "Branch"
350         );
351     }
352 
353     #[test]
defer_peek_write()354     fn defer_peek_write() {
355         let tree = TreeBuilder::new();
356         {
357             create_dir("test_out").ok();
358             remove_file("test_out/defer_peek_write.txt").ok();
359             File::create("test_out/defer_peek_write.txt").unwrap();
360             defer_peek_write!(tree, "test_out/defer_peek_write.txt");
361             tree.add_leaf("Branch");
362             assert_eq!(read_to_string("test_out/defer_peek_write.txt").unwrap(), "");
363             assert_eq!(tree.peek_string(), "Branch");
364         }
365         assert_eq!(tree.peek_string(), "Branch");
366         assert_eq!(
367             read_to_string("test_out/defer_peek_write.txt").unwrap(),
368             "Branch"
369         );
370     }
371 
372     #[test]
373     #[should_panic]
374     #[allow(unreachable_code)]
defer_peek_write_panic()375     fn defer_peek_write_panic() {
376         let tree = TreeBuilder::new();
377         {
378             create_dir("test_out").ok();
379             remove_file("test_out/defer_peek_write_panic.txt").ok();
380             File::create("test_out/defer_peek_write_panic.txt").unwrap();
381             defer_peek_write!(tree, "test_out/defer_peek_write_panic.txt");
382             tree.add_leaf("This should be the only line in this file");
383             assert_eq!(read_to_string("test_out/defer_peek_write.txt").unwrap(), "");
384             assert_eq!(
385                 tree.peek_string(),
386                 "This should be the only line in this file"
387             );
388             panic!();
389             tree.add_leaf("This line should not exist");
390         }
391     }
392 
example_tree() -> TreeBuilder393     fn example_tree() -> TreeBuilder {
394         let tree = TreeBuilder::new();
395         {
396             add_branch_to!(tree, "1");
397             {
398                 add_branch_to!(tree, "1.1");
399                 add_leaf_to!(tree, "1.1.1");
400                 add_leaf_to!(tree, "1.1.2\nWith two\nextra lines");
401                 add_leaf_to!(tree, "1.1.3");
402             }
403             add_branch_to!(tree, "1.2");
404             add_leaf_to!(tree, "1.2.1");
405         }
406         {
407             add_branch_to!(tree, "2");
408             add_leaf_to!(tree, "2.1");
409             add_leaf_to!(tree, "2.2");
410         }
411         add_leaf_to!(tree, "3");
412         tree
413     }
414 
415     #[test]
format_output()416     fn format_output() {
417         let tree = example_tree();
418         tree.set_config_override(
419             TreeConfig::new()
420                 .indent(8)
421                 .symbols(TreeSymbols {
422                     continued: "| |",
423                     join_first: "|A|",
424                     join_last: "|Z|",
425                     join_inner: "|N|",
426                     join_only: "|O|",
427                     branch: "123456[NOT SHOWN]",
428                     leaf: ")}>",
429                     multiline_first: Some(")}MULTI>"),
430                     multiline_continued: Some(".. CONTINUED: "),
431                 })
432                 .show_first_level(),
433         );
434         tree.peek_print();
435         assert_eq!(
436             tree.string(),
437             "\
438 |A|123456)}>1
439 | |       |A|123456)}>1.1
440 | |       | |       |A|123456)}>1.1.1
441 | |       | |       |N|123456)}MULTI>1.1.2
442 | |       | |       | |      .. CONTINUED: With two
443 | |       | |       | |      .. CONTINUED: extra lines
444 | |       | |       |Z|123456)}>1.1.3
445 | |       |Z|123456)}>1.2
446 | |               |O|123456)}>1.2.1
447 |N|123456)}>2
448 | |       |A|123456)}>2.1
449 | |       |Z|123456)}>2.2
450 |Z|123456)}>3"
451         );
452     }
453 
454     #[test]
format_output_thick()455     fn format_output_thick() {
456         let tree = example_tree();
457         tree.set_config_override(
458             TreeConfig::new()
459                 .symbols(TreeSymbols::with_thick())
460                 .indent(4)
461                 .show_first_level(),
462         );
463         tree.peek_print();
464         assert_eq!(
465             tree.string(),
466             "\
467 ┣━━╼ 1
468 ┃   ┣━━╼ 1.1
469 ┃   ┃   ┣━━╼ 1.1.1
470 ┃   ┃   ┣━━╼ 1.1.2
471 ┃   ┃   ┃    With two
472 ┃   ┃   ┃    extra lines
473 ┃   ┃   ┗━━╼ 1.1.3
474 ┃   ┗━━╼ 1.2
475 ┃       ┗━━╼ 1.2.1
476 ┣━━╼ 2
477 ┃   ┣━━╼ 2.1
478 ┃   ┗━━╼ 2.2
479 ┗━━╼ 3"
480         );
481     }
482 
483     #[test]
format_output_pipes()484     fn format_output_pipes() {
485         let tree = example_tree();
486         tree.set_config_override(
487             TreeConfig::new()
488                 .symbols(TreeSymbols::with_pipes())
489                 .indent(3)
490                 .show_first_level(),
491         );
492         tree.peek_print();
493         assert_eq!(
494             tree.string(),
495             "\
496 ╠═╼ 1
497 ║  ╠═╼ 1.1
498 ║  ║  ╠═╼ 1.1.1
499 ║  ║  ╠═╼ 1.1.2
500 ║  ║  ║   With two
501 ║  ║  ║   extra lines
502 ║  ║  ╚═╼ 1.1.3
503 ║  ╚═╼ 1.2
504 ║     ╚═╼ 1.2.1
505 ╠═╼ 2
506 ║  ╠═╼ 2.1
507 ║  ╚═╼ 2.2
508 ╚═╼ 3"
509         );
510     }
511 
512     #[test]
format_output_dashed()513     fn format_output_dashed() {
514         let tree = example_tree();
515         tree.set_config_override(
516             TreeConfig::new()
517                 .symbols(TreeSymbols::with_dashed().multiline_continued("  > "))
518                 .indent(4)
519                 .show_first_level(),
520         );
521         tree.peek_print();
522         assert_eq!(
523             tree.string(),
524             "\
525 ┊╌╌- 1
526 ┊   ┊╌╌- 1.1
527 ┊   ┊   ┊╌╌- 1.1.1
528 ┊   ┊   ┊╌╌- 1.1.2
529 ┊   ┊   ┊    > With two
530 ┊   ┊   ┊    > extra lines
531 ┊   ┊   '╌╌- 1.1.3
532 ┊   '╌╌- 1.2
533 ┊       '╌╌- 1.2.1
534 ┊╌╌- 2
535 ┊   ┊╌╌- 2.1
536 ┊   '╌╌- 2.2
537 '╌╌- 3"
538         );
539     }
540 
541     #[test]
format_output_rounded()542     fn format_output_rounded() {
543         let tree = example_tree();
544         tree.set_config_override(
545             TreeConfig::new()
546                 .symbols(TreeSymbols::with_rounded())
547                 .indent(4),
548         );
549         tree.peek_print();
550         assert_eq!(
551             tree.string(),
552             "\
553 1
554 ├──╼ 1.1
555 │   ├──╼ 1.1.1
556 │   ├──╼ 1.1.2
557 │   │    With two
558 │   │    extra lines
559 │   ╰──╼ 1.1.3
560 ╰──╼ 1.2
561     ╰──╼ 1.2.1
562 2
563 ├──╼ 2.1
564 ╰──╼ 2.2
565 3"
566         );
567     }
568 
wait_a_bit(tree: TreeBuilder, index: usize)569     async fn wait_a_bit(tree: TreeBuilder, index: usize) {
570         tree.print();
571         add_branch_to!(tree, "inside async branch {}", index);
572         tree.print();
573         add_leaf_to!(tree, "inside async leaf {}", index);
574         tree.print();
575     }
576 
577     #[tokio::test]
async_barrier()578     async fn async_barrier() {
579         let tree = TreeBuilder::new();
580         defer_peek_print!(tree);
581         add_branch_to!(tree, "root");
582         add_leaf_to!(tree, "before async");
583 
584         let x2 = wait_a_bit(tree.clone(), 4);
585         let x1 = wait_a_bit(tree.clone(), 5);
586         let x3 = wait_a_bit(tree.clone(), 3);
587         let x4 = wait_a_bit(tree.clone(), 2);
588         let x5 = wait_a_bit(tree.clone(), 1);
589 
590         add_leaf_to!(tree, "before join async");
591 
592         join5(x1, x2, x3, x4, x5).await;
593         add_leaf_to!(tree, "after join async");
594         assert_eq!(tree.peek_string(), "after join async");
595     }
596 }
597