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