| #[cfg(test)] |
| mod test { |
| use crate::*; |
| use futures::future::join5; |
| use std::cmp::{max, min}; |
| use std::fs::{create_dir, read_to_string, remove_file}; |
| |
| #[test] |
| fn test_branch() { |
| let d: TreeBuilder = TreeBuilder::new(); |
| d.add_leaf("1"); |
| { |
| let _l = d.enter_scoped(); |
| d.add_leaf("1.1"); |
| d.add_leaf("1.2"); |
| } |
| d.add_leaf("2"); |
| d.add_leaf("3"); |
| let _l = d.enter_scoped(); |
| d.add_leaf("3.1"); |
| d.add_leaf("3.2"); |
| d.peek_print(); |
| assert_eq!( |
| "\ |
| 1 |
| ├╼ 1.1 |
| └╼ 1.2 |
| 2 |
| 3 |
| ├╼ 3.1 |
| └╼ 3.2", |
| d.string() |
| ); |
| } |
| |
| #[test] |
| fn test_branch2() { |
| let d = TreeBuilder::new(); |
| d.add_leaf("1"); |
| { |
| let _scope = d.enter_scoped(); |
| d.add_leaf("1.1"); |
| { |
| let _scope = d.enter_scoped(); |
| d.add_leaf("1.1.1"); |
| } |
| } |
| |
| d.add_leaf("2"); |
| d.enter(); |
| d.add_leaf("2.1"); |
| d.enter(); |
| d.add_leaf("2.1.1"); |
| d.peek_print(); |
| assert_eq!( |
| "\ |
| 1 |
| └╼ 1.1 |
| └╼ 1.1.1 |
| 2 |
| └╼ 2.1 |
| └╼ 2.1.1", |
| d.string() |
| ); |
| } |
| |
| #[test] |
| fn simple() { |
| let d = TreeBuilder::new(); |
| d.add_leaf("Hi"); |
| assert_eq!("Hi", d.string()); |
| } |
| |
| #[test] |
| fn depth() { |
| let d = TreeBuilder::new(); |
| assert_eq!(0, d.depth()); |
| d.add_leaf("Hi"); |
| assert_eq!(0, d.depth()); |
| let _b = d.add_branch("Hi"); |
| assert_eq!(1, d.depth()); |
| d.add_leaf("Hi"); |
| assert_eq!(1, d.depth()); |
| } |
| |
| #[test] |
| fn indent() { |
| let d = TreeBuilder::new(); |
| d.add_leaf("1"); |
| add_branch_to!(d); |
| d.add_leaf("1.1"); |
| { |
| add_branch_to!(d); |
| d.add_leaf("1.1.1"); |
| } |
| d.set_config_override(TreeConfig::new().indent(4)); |
| d.peek_print(); |
| assert_eq!( |
| "\ |
| 1 |
| └──╼ 1.1 |
| └──╼ 1.1.1", |
| d.string() |
| ); |
| } |
| |
| #[test] |
| fn macros() { |
| let d = TreeBuilder::new(); |
| add_leaf_to!(d, "1"); |
| { |
| add_branch_to!(d); |
| add_leaf_to!(d, "1.1") |
| } |
| d.peek_print(); |
| assert_eq!( |
| "\ |
| 1 |
| └╼ 1.1", |
| d.string() |
| ); |
| } |
| |
| #[test] |
| fn macros_with_fn() { |
| let d = TreeBuilder::new(); |
| let tree = || d.clone(); |
| add_leaf_to!(tree(), "1"); |
| { |
| add_branch_to!(tree()); |
| add_leaf_to!(tree(), "1.1") |
| } |
| tree().peek_print(); |
| assert_eq!( |
| "\ |
| 1 |
| └╼ 1.1", |
| d.string() |
| ); |
| } |
| |
| #[test] |
| fn leaf_with_value() { |
| let d = TreeBuilder::new(); |
| let value = add_leaf_value_to!(d, 1); |
| d.peek_print(); |
| assert_eq!("1", d.string()); |
| assert_eq!(1, value); |
| } |
| |
| #[test] |
| fn macros2() { |
| let d = TreeBuilder::new(); |
| add_branch_to!(d, "1"); |
| add_leaf_to!(d, "1.1"); |
| d.peek_print(); |
| assert_eq!( |
| "\ |
| 1 |
| └╼ 1.1", |
| d.string() |
| ); |
| } |
| |
| #[test] |
| fn mid() { |
| let d = TreeBuilder::new(); |
| d.add_leaf(&format!("{}{}", "1", "0")); |
| d.enter(); |
| d.add_leaf("10.1"); |
| d.add_leaf("10.2"); |
| d.enter(); |
| d.add_leaf("10.1.1"); |
| d.add_leaf("10.1.2\nNext line"); |
| d.exit(); |
| d.add_leaf(&format!("10.3")); |
| d.peek_print(); |
| assert_eq!( |
| "\ |
| 10 |
| ├╼ 10.1 |
| ├╼ 10.2 |
| │ ├╼ 10.1.1 |
| │ └╼ 10.1.2 |
| │ Next line |
| └╼ 10.3", |
| d.string() |
| ); |
| } |
| |
| fn factors(x: usize) { |
| add_branch!("{}", x); |
| for i in 1..x { |
| if x % i == 0 { |
| factors(i); |
| } |
| } |
| } |
| |
| #[test] |
| fn recursive() { |
| factors(6); |
| default_tree().peek_print(); |
| assert_eq!( |
| "\ |
| 6 |
| ├╼ 1 |
| ├╼ 2 |
| │ └╼ 1 |
| └╼ 3 |
| └╼ 1", |
| default_tree().string() |
| ); |
| } |
| |
| fn a() { |
| add_branch!("a"); |
| b(); |
| c(); |
| } |
| |
| fn b() { |
| add_branch!("b"); |
| c(); |
| } |
| |
| fn c() { |
| add_branch!("c"); |
| add_leaf!("Nothing to see here"); |
| } |
| |
| #[test] |
| fn nested() { |
| a(); |
| default_tree().peek_print(); |
| assert_eq!( |
| "\ |
| a |
| ├╼ b |
| │ └╼ c |
| │ └╼ Nothing to see here |
| └╼ c |
| └╼ Nothing to see here", |
| default_tree().string() |
| ); |
| } |
| |
| #[test] |
| fn disabled_output() { |
| let tree = TreeBuilder::new(); |
| tree.set_enabled(false); |
| add_leaf_to!(tree, "Leaf"); |
| tree.add_leaf("Leaf"); |
| |
| add_branch_to!(tree, "Branch"); |
| tree.add_branch("Branch"); |
| assert_eq!("", tree.string()); |
| } |
| |
| #[test] |
| fn enabled_output() { |
| let tree = TreeBuilder::new(); |
| tree.set_enabled(false); |
| add_branch_to!(tree, "Ignored branch"); |
| add_leaf_to!(tree, "Ignored leaf"); |
| tree.set_enabled(true); |
| add_leaf_to!(tree, "Leaf"); |
| tree.add_leaf("Leaf"); |
| |
| add_branch_to!(tree, "Branch"); |
| tree.add_branch("Branch"); |
| assert_eq!( |
| "Leaf |
| Leaf |
| Branch |
| └╼ Branch", |
| tree.string() |
| ); |
| } |
| |
| #[test] |
| fn tree_by_name() { |
| clear("A"); |
| let b = tree("B"); |
| b.clear(); |
| { |
| add_branch_to!("A", "1"); |
| add_branch_to!(b, "3"); |
| add_leaf_to!("A", "1.1"); |
| add_leaf_to!("B", "3.1"); |
| } |
| add_leaf_to!("A", "2"); |
| peek_print("A"); |
| b.peek_print(); |
| assert_eq!( |
| "1 |
| └╼ 1.1 |
| 2", |
| string("A") |
| ); |
| assert_eq!( |
| "3 |
| └╼ 3.1", |
| b.string() |
| ); |
| } |
| |
| #[test] |
| fn tree_by_name_disabled() { |
| let d = tree("D"); |
| d.clear(); |
| d.set_enabled(true); |
| clear("C"); |
| set_enabled("C", false); |
| { |
| add_branch_to!("C", "1"); |
| set_enabled("C", true); |
| add_branch_to!(d, "3"); |
| add_leaf_to!("C", "1.1"); |
| d.set_enabled(false); |
| add_leaf_to!("D", "3.1"); |
| } |
| add_leaf_to!("C", "2"); |
| peek_print("C"); |
| d.peek_print(); |
| assert_eq!( |
| "1.1 |
| 2", |
| string("C") |
| ); |
| assert_eq!("3", d.string()); |
| } |
| |
| #[test] |
| fn defer_write() { |
| let tree = TreeBuilder::new(); |
| { |
| create_dir("test_out").ok(); |
| remove_file("test_out/defer_write.txt").ok(); |
| File::create("test_out/defer_write.txt").unwrap(); |
| defer_write!(tree, "test_out/defer_write.txt"); |
| tree.add_leaf("Branch"); |
| assert_eq!(read_to_string("test_out/defer_write.txt").unwrap(), ""); |
| assert_eq!(tree.peek_string(), "Branch"); |
| } |
| assert_eq!(tree.peek_string(), ""); |
| assert_eq!( |
| read_to_string("test_out/defer_write.txt").unwrap(), |
| "Branch" |
| ); |
| } |
| |
| #[test] |
| fn defer_peek_write() { |
| let tree = TreeBuilder::new(); |
| { |
| create_dir("test_out").ok(); |
| remove_file("test_out/defer_peek_write.txt").ok(); |
| File::create("test_out/defer_peek_write.txt").unwrap(); |
| defer_peek_write!(tree, "test_out/defer_peek_write.txt"); |
| tree.add_leaf("Branch"); |
| assert_eq!(read_to_string("test_out/defer_peek_write.txt").unwrap(), ""); |
| assert_eq!(tree.peek_string(), "Branch"); |
| } |
| assert_eq!(tree.peek_string(), "Branch"); |
| assert_eq!( |
| read_to_string("test_out/defer_peek_write.txt").unwrap(), |
| "Branch" |
| ); |
| } |
| |
| #[test] |
| #[should_panic] |
| #[allow(unreachable_code)] |
| fn defer_peek_write_panic() { |
| let tree = TreeBuilder::new(); |
| { |
| create_dir("test_out").ok(); |
| remove_file("test_out/defer_peek_write_panic.txt").ok(); |
| File::create("test_out/defer_peek_write_panic.txt").unwrap(); |
| defer_peek_write!(tree, "test_out/defer_peek_write_panic.txt"); |
| tree.add_leaf("This should be the only line in this file"); |
| assert_eq!(read_to_string("test_out/defer_peek_write.txt").unwrap(), ""); |
| assert_eq!( |
| tree.peek_string(), |
| "This should be the only line in this file" |
| ); |
| panic!(); |
| tree.add_leaf("This line should not exist"); |
| } |
| } |
| |
| fn example_tree() -> TreeBuilder { |
| let tree = TreeBuilder::new(); |
| { |
| add_branch_to!(tree, "1"); |
| { |
| add_branch_to!(tree, "1.1"); |
| add_leaf_to!(tree, "1.1.1"); |
| add_leaf_to!(tree, "1.1.2\nWith two\nextra lines"); |
| add_leaf_to!(tree, "1.1.3"); |
| } |
| add_branch_to!(tree, "1.2"); |
| add_leaf_to!(tree, "1.2.1"); |
| } |
| { |
| add_branch_to!(tree, "2"); |
| add_leaf_to!(tree, "2.1"); |
| add_leaf_to!(tree, "2.2"); |
| } |
| add_leaf_to!(tree, "3"); |
| tree |
| } |
| |
| #[test] |
| fn format_output() { |
| let tree = example_tree(); |
| tree.set_config_override( |
| TreeConfig::new() |
| .indent(8) |
| .symbols(TreeSymbols { |
| continued: "| |", |
| join_first: "|A|", |
| join_last: "|Z|", |
| join_inner: "|N|", |
| join_only: "|O|", |
| branch: "123456[NOT SHOWN]", |
| leaf: ")}>", |
| multiline_first: Some(")}MULTI>"), |
| multiline_continued: Some(".. CONTINUED: "), |
| }) |
| .show_first_level(), |
| ); |
| tree.peek_print(); |
| assert_eq!( |
| tree.string(), |
| "\ |
| |A|123456)}>1 |
| | | |A|123456)}>1.1 |
| | | | | |A|123456)}>1.1.1 |
| | | | | |N|123456)}MULTI>1.1.2 |
| | | | | | | .. CONTINUED: With two |
| | | | | | | .. CONTINUED: extra lines |
| | | | | |Z|123456)}>1.1.3 |
| | | |Z|123456)}>1.2 |
| | | |O|123456)}>1.2.1 |
| |N|123456)}>2 |
| | | |A|123456)}>2.1 |
| | | |Z|123456)}>2.2 |
| |Z|123456)}>3" |
| ); |
| } |
| |
| #[test] |
| fn format_output_thick() { |
| let tree = example_tree(); |
| tree.set_config_override( |
| TreeConfig::new() |
| .symbols(TreeSymbols::with_thick()) |
| .indent(4) |
| .show_first_level(), |
| ); |
| tree.peek_print(); |
| assert_eq!( |
| tree.string(), |
| "\ |
| ┣━━╼ 1 |
| ┃ ┣━━╼ 1.1 |
| ┃ ┃ ┣━━╼ 1.1.1 |
| ┃ ┃ ┣━━╼ 1.1.2 |
| ┃ ┃ ┃ With two |
| ┃ ┃ ┃ extra lines |
| ┃ ┃ ┗━━╼ 1.1.3 |
| ┃ ┗━━╼ 1.2 |
| ┃ ┗━━╼ 1.2.1 |
| ┣━━╼ 2 |
| ┃ ┣━━╼ 2.1 |
| ┃ ┗━━╼ 2.2 |
| ┗━━╼ 3" |
| ); |
| } |
| |
| #[test] |
| fn format_output_pipes() { |
| let tree = example_tree(); |
| tree.set_config_override( |
| TreeConfig::new() |
| .symbols(TreeSymbols::with_pipes()) |
| .indent(3) |
| .show_first_level(), |
| ); |
| tree.peek_print(); |
| assert_eq!( |
| tree.string(), |
| "\ |
| ╠═╼ 1 |
| ║ ╠═╼ 1.1 |
| ║ ║ ╠═╼ 1.1.1 |
| ║ ║ ╠═╼ 1.1.2 |
| ║ ║ ║ With two |
| ║ ║ ║ extra lines |
| ║ ║ ╚═╼ 1.1.3 |
| ║ ╚═╼ 1.2 |
| ║ ╚═╼ 1.2.1 |
| ╠═╼ 2 |
| ║ ╠═╼ 2.1 |
| ║ ╚═╼ 2.2 |
| ╚═╼ 3" |
| ); |
| } |
| |
| #[test] |
| fn format_output_dashed() { |
| let tree = example_tree(); |
| tree.set_config_override( |
| TreeConfig::new() |
| .symbols(TreeSymbols::with_dashed().multiline_continued(" > ")) |
| .indent(4) |
| .show_first_level(), |
| ); |
| tree.peek_print(); |
| assert_eq!( |
| tree.string(), |
| "\ |
| ┊╌╌- 1 |
| ┊ ┊╌╌- 1.1 |
| ┊ ┊ ┊╌╌- 1.1.1 |
| ┊ ┊ ┊╌╌- 1.1.2 |
| ┊ ┊ ┊ > With two |
| ┊ ┊ ┊ > extra lines |
| ┊ ┊ '╌╌- 1.1.3 |
| ┊ '╌╌- 1.2 |
| ┊ '╌╌- 1.2.1 |
| ┊╌╌- 2 |
| ┊ ┊╌╌- 2.1 |
| ┊ '╌╌- 2.2 |
| '╌╌- 3" |
| ); |
| } |
| |
| #[test] |
| fn format_output_rounded() { |
| let tree = example_tree(); |
| tree.set_config_override( |
| TreeConfig::new() |
| .symbols(TreeSymbols::with_rounded()) |
| .indent(4), |
| ); |
| tree.peek_print(); |
| assert_eq!( |
| tree.string(), |
| "\ |
| 1 |
| ├──╼ 1.1 |
| │ ├──╼ 1.1.1 |
| │ ├──╼ 1.1.2 |
| │ │ With two |
| │ │ extra lines |
| │ ╰──╼ 1.1.3 |
| ╰──╼ 1.2 |
| ╰──╼ 1.2.1 |
| 2 |
| ├──╼ 2.1 |
| ╰──╼ 2.2 |
| 3" |
| ); |
| } |
| |
| async fn wait_a_bit(tree: TreeBuilder, index: usize) { |
| tree.print(); |
| add_branch_to!(tree, "inside async branch {}", index); |
| tree.print(); |
| add_leaf_to!(tree, "inside async leaf {}", index); |
| tree.print(); |
| } |
| |
| #[tokio::test] |
| async fn async_barrier() { |
| let tree = TreeBuilder::new(); |
| defer_peek_print!(tree); |
| add_branch_to!(tree, "root"); |
| add_leaf_to!(tree, "before async"); |
| |
| let x2 = wait_a_bit(tree.clone(), 4); |
| let x1 = wait_a_bit(tree.clone(), 5); |
| let x3 = wait_a_bit(tree.clone(), 3); |
| let x4 = wait_a_bit(tree.clone(), 2); |
| let x5 = wait_a_bit(tree.clone(), 1); |
| |
| add_leaf_to!(tree, "before join async"); |
| |
| join5(x1, x2, x3, x4, x5).await; |
| add_leaf_to!(tree, "after join async"); |
| assert_eq!(tree.peek_string(), "after join async"); |
| } |
| } |