on 5ebf021 help sign in
bat/tests/integration_tests.rs
717 lines 15 kB history raw
1use assert_cmd::Command;
2use std::path::Path;
3use std::str::from_utf8;
5const EXAMPLES_DIR: &str = "tests/examples";
7fn bat_with_config() -> Command {
8 let mut cmd = Command::cargo_bin("bat").unwrap();
9 cmd.current_dir("tests/examples");
10 cmd.env_remove("PAGER");
11 cmd.env_remove("BAT_PAGER");
12 cmd.env_remove("BAT_CONFIG_PATH");
13 cmd.env_remove("BAT_STYLE");
14 cmd.env_remove("BAT_THEME");
15 cmd.env_remove("BAT_TABS");
16 cmd
19fn bat() -> Command {
20 let mut cmd = bat_with_config();
21 cmd.arg("--no-config");
22 cmd
25#[test]
26fn basic() {
27 bat()
28 .arg("test.txt")
29 .assert()
30 .success()
31 .stdout("hello world\n")
32 .stderr("");
35#[test]
36fn stdin() {
37 bat()
38 .write_stdin("foo\nbar\n")
39 .assert()
40 .success()
41 .stdout("foo\nbar\n");
44#[test]
45fn concatenate() {
46 bat()
47 .arg("test.txt")
48 .arg("test.txt")
49 .assert()
50 .success()
51 .stdout("hello world\nhello world\n");
54#[test]
55fn concatenate_stdin() {
56 bat()
57 .arg("test.txt")
58 .arg("-")
59 .arg("test.txt")
60 .write_stdin("stdin\n")
61 .assert()
62 .success()
63 .stdout("hello world\nstdin\nhello world\n");
66#[test]
67fn concatenate_empty_first() {
68 bat()
69 .arg("empty.txt")
70 .arg("test.txt")
71 .assert()
72 .success()
73 .stdout("hello world\n");
76#[test]
77fn concatenate_empty_last() {
78 bat()
79 .arg("test.txt")
80 .arg("empty.txt")
81 .assert()
82 .success()
83 .stdout("hello world\n");
86#[test]
87fn concatenate_empty_both() {
88 bat()
89 .arg("empty.txt")
90 .arg("empty.txt")
91 .assert()
92 .success()
93 .stdout("");
96#[test]
97fn concatenate_empty_between() {
98 bat()
99 .arg("test.txt")
100 .arg("empty.txt")
101 .arg("test.txt")
102 .assert()
103 .success()
104 .stdout("hello world\nhello world\n");
107#[test]
108fn concatenate_empty_first_and_last() {
109 bat()
110 .arg("empty.txt")
111 .arg("test.txt")
112 .arg("empty.txt")
113 .assert()
114 .success()
115 .stdout("hello world\n");
118#[test]
119fn concatenate_single_line() {
120 bat()
121 .arg("single-line.txt")
122 .arg("single-line.txt")
123 .assert()
124 .success()
125 .stdout("Single LineSingle Line");
128#[test]
129fn concatenate_single_line_empty() {
130 bat()
131 .arg("single-line.txt")
132 .arg("empty.txt")
133 .arg("single-line.txt")
134 .assert()
135 .success()
136 .stdout("Single LineSingle Line");
139#[test]
140fn line_numbers() {
141 bat()
142 .arg("multiline.txt")
143 .arg("--style=numbers")
144 .arg("--decorations=always")
145 .assert()
146 .success()
147 .stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n");
150#[test]
151fn line_range_2_3() {
152 bat()
153 .arg("multiline.txt")
154 .arg("--line-range=2:3")
155 .assert()
156 .success()
157 .stdout("line 2\nline 3\n");
160#[test]
161fn line_range_first_two() {
162 bat()
163 .arg("multiline.txt")
164 .arg("--line-range=:2")
165 .assert()
166 .success()
167 .stdout("line 1\nline 2\n");
170#[test]
171fn line_range_last_3() {
172 bat()
173 .arg("multiline.txt")
174 .arg("--line-range=2:")
175 .assert()
176 .success()
177 .stdout("line 2\nline 3\nline 4\n");
180#[test]
181fn line_range_multiple() {
182 bat()
183 .arg("multiline.txt")
184 .arg("--line-range=1:2")
185 .arg("--line-range=4:4")
186 .assert()
187 .success()
188 .stdout("line 1\nline 2\nline 4\n");
191#[test]
192fn tabs_numbers() {
193 bat()
194 .arg("tabs.txt")
195 .arg("--tabs=4")
196 .arg("--style=numbers")
197 .arg("--decorations=always")
198 .assert()
199 .success()
200 .stdout(
201 " 1 1 2 3 4
202 2 1 ?
203 3 22 ?
204 4 333 ?
205 5 4444 ?
206 6 55555 ?
207 7 666666 ?
208 8 7777777 ?
209 9 88888888 ?
210",
211 );
214#[test]
215fn tabs_passthrough_wrapped() {
216 bat()
217 .arg("tabs.txt")
218 .arg("--tabs=0")
219 .arg("--style=plain")
220 .arg("--decorations=always")
221 .assert()
222 .success()
223 .stdout(
224 " 1 2 3 4
2251 ?
22622 ?
227333 ?
2284444 ?
22955555 ?
230666666 ?
2317777777 ?
23288888888 ?
233",
234 );
237#[test]
238fn tabs_4_wrapped() {
239 bat()
240 .arg("tabs.txt")
241 .arg("--tabs=4")
242 .arg("--style=plain")
243 .arg("--decorations=always")
244 .assert()
245 .success()
246 .stdout(
247 " 1 2 3 4
2481 ?
24922 ?
250333 ?
2514444 ?
25255555 ?
253666666 ?
2547777777 ?
25588888888 ?
256",
257 );
260#[test]
261fn tabs_8_wrapped() {
262 bat()
263 .arg("tabs.txt")
264 .arg("--tabs=8")
265 .arg("--style=plain")
266 .arg("--decorations=always")
267 .assert()
268 .success()
269 .stdout(
270 " 1 2 3 4
2711 ?
27222 ?
273333 ?
2744444 ?
27555555 ?
276666666 ?
2777777777 ?
27888888888 ?
279",
280 );
283#[test]
284fn tabs_passthrough() {
285 bat()
286 .arg("tabs.txt")
287 .arg("--tabs=0")
288 .arg("--style=plain")
289 .arg("--decorations=always")
290 .assert()
291 .success()
292 .stdout(
293 " 1 2 3 4
2941 ?
29522 ?
296333 ?
2974444 ?
29855555 ?
299666666 ?
3007777777 ?
30188888888 ?
302",
303 );
306#[test]
307fn tabs_4() {
308 bat()
309 .arg("tabs.txt")
310 .arg("--tabs=4")
311 .arg("--style=plain")
312 .arg("--decorations=always")
313 .assert()
314 .success()
315 .stdout(
316 " 1 2 3 4
3171 ?
31822 ?
319333 ?
3204444 ?
32155555 ?
322666666 ?
3237777777 ?
32488888888 ?
325",
326 );
329#[test]
330fn tabs_8() {
331 bat()
332 .arg("tabs.txt")
333 .arg("--tabs=8")
334 .arg("--style=plain")
335 .arg("--decorations=always")
336 .assert()
337 .success()
338 .stdout(
339 " 1 2 3 4
3401 ?
34122 ?
342333 ?
3434444 ?
34455555 ?
345666666 ?
3467777777 ?
34788888888 ?
348",
349 );
352#[test]
353fn fail_non_existing() {
354 bat().arg("non-existing-file").assert().failure();
357#[test]
358fn fail_directory() {
359 bat().arg("sub_directory").assert().failure();
362#[test]
363fn do_not_exit_directory() {
364 bat()
365 .arg("sub_directory")
366 .arg("test.txt")
367 .assert()
368 .stdout("hello world\n")
369 .failure();
372#[test]
373fn pager_basic() {
374 bat()
375 .env("PAGER", "echo pager-output")
376 .arg("--paging=always")
377 .arg("test.txt")
378 .assert()
379 .success()
380 .stdout("pager-output\n");
383#[test]
384fn pager_overwrite() {
385 bat()
386 .env("PAGER", "echo other-pager")
387 .env("BAT_PAGER", "echo pager-output")
388 .arg("--paging=always")
389 .arg("test.txt")
390 .assert()
391 .success()
392 .stdout("pager-output\n");
395#[test]
396fn pager_disable() {
397 bat()
398 .env("PAGER", "echo other-pager")
399 .env("BAT_PAGER", "")
400 .arg("--paging=always")
401 .arg("test.txt")
402 .assert()
403 .success()
404 .stdout("hello world\n");
407#[test]
408fn config_location_test() {
409 bat_with_config()
410 .env("BAT_CONFIG_PATH", "bat.conf")
411 .arg("--config-file")
412 .assert()
413 .success()
414 .stdout("bat.conf\n");
417#[test]
418fn config_read_arguments_from_file() {
419 bat_with_config()
420 .env("BAT_CONFIG_PATH", "bat.conf")
421 .arg("test.txt")
422 .assert()
423 .success()
424 .stdout("dummy-pager-from-config\n");
427#[test]
428fn utf16() {
429 // The output will be converted to UTF-8 with a leading UTF-8 BOM
430 bat()
431 .arg("--plain")
432 .arg("--decorations=always")
433 .arg("test_UTF-16LE.txt")
434 .assert()
435 .success()
436 .stdout(std::str::from_utf8(b"\xEF\xBB\xBFhello world\n").unwrap());
439#[test]
440fn can_print_file_named_cache() {
441 bat_with_config()
442 .arg("cache")
443 .assert()
444 .success()
445 .stdout("test\n")
446 .stderr("");
449#[test]
450fn can_print_file_named_cache_with_additional_argument() {
451 bat_with_config()
452 .arg("cache")
453 .arg("test.txt")
454 .assert()
455 .success()
456 .stdout("test\nhello world\n")
457 .stderr("");
460#[test]
461fn can_print_file_starting_with_cache() {
462 bat_with_config()
463 .arg("cache.c")
464 .assert()
465 .success()
466 .stdout("test\n")
467 .stderr("");
470#[test]
471fn does_not_print_unwanted_file_named_cache() {
472 bat_with_config().arg("cach").assert().failure();
475#[test]
476fn unicode_wrap() {
477 bat_with_config()
478 .arg("unicode-wrap.txt")
479 .arg("--style=numbers,snip")
480 .arg("--decorations=always")
481 .arg("--terminal-width=40")
482 .assert()
483 .success()
484 .stdout(
485 " 1 ビタミンA ビタミンD ビタミンE ビ
486 タミンK ビタミンB1 ビタミンB2 ナ
487 イアシン パントテン酸 ビタミンB6
488 ビタミンB12 葉酸 ビオチン ビタ
489 ミンC
490 2
491 3 고양이 고양이 고양이 고양이 고양이
492 고양이 고양이 고양이 고양이 고양이
493 고양이 고양이 고양이 고양이 고양이
494 고양이 고양이 고양이 고양이 고양이
495 고양이 고양이 고양이 고양이 고양이
496 고양이 고양이 고양이 고양이 고양이
497 고양이 고양이 고양이 고양이 고양이
498 고양이 고양이 고양이 고양이 고양이
499 고양이
500 4
501 5 1 บวก 2 บวก 3 บวก 4 บวก 5 บวก 6 บวก
502 7 บวก 8 บวก 9 บวก 10 บวก 11 บวก 12
503 บวก 13 บวก 14 บวก 15 บวก 16 บวก 17
504 บวก 18 บวก 19 บวก 20
505 6
506 7 Бельгия Болгария Чехия Дания Герман
507 ия Эстония Ирландия Греция Испания
508 Франция Хорватия Италия Кипр Латвия
509 Литва Люксембург Венгрия Мальта Ни
510 дерланды Австрия Польша Португалия
511 Румыния Словения Словакия Финляндия
512 Швеция Великобритания
513",
514 );
517#[test]
518fn snip() {
519 bat()
520 .arg("multiline.txt")
521 .arg("--style=numbers,snip")
522 .arg("--decorations=always")
523 .arg("--line-range=1:2")
524 .arg("--line-range=4:")
525 .arg("--terminal-width=80")
526 .assert()
527 .success()
528 .stdout(
529 " 1 line 1
530 2 line 2
531 ...─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ 8< ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
532 4 line 4
533",
534 );
537#[test]
538fn empty_file_leads_to_empty_output_with_grid_enabled() {
539 bat()
540 .arg("empty.txt")
541 .arg("--style=grid")
542 .arg("--decorations=always")
543 .arg("--terminal-width=80")
544 .assert()
545 .success()
546 .stdout("");
549#[test]
550fn filename_basic() {
551 bat()
552 .arg("test.txt")
553 .arg("--decorations=always")
554 .arg("--style=header")
555 .arg("-r=0:0")
556 .arg("--file-name=foo")
557 .assert()
558 .success()
559 .stdout("File: foo\n")
560 .stderr("");
563#[test]
564fn filename_binary() {
565 bat()
566 .arg("test.binary")
567 .arg("--decorations=always")
568 .arg("--style=header")
569 .arg("-r=0:0")
570 .arg("--file-name=foo")
571 .assert()
572 .success()
573 .stdout("File: foo <BINARY>\n")
574 .stderr("");
577#[test]
578fn filename_stdin() {
579 bat()
580 .arg("--decorations=always")
581 .arg("--style=header")
582 .arg("-r=0:0")
583 .arg("-")
584 .write_stdin("stdin\n")
585 .arg("--file-name=foo")
586 .assert()
587 .success()
588 .stdout("File: foo\n")
589 .stderr("");
592#[test]
593fn filename_stdin_binary() {
594 let vec = vec![0; 1];
595 bat_with_config()
596 .arg("--decorations=always")
597 .arg("--style=header")
598 .write_stdin(vec)
599 .arg("--file-name=foo")
600 .assert()
601 .success()
602 .stdout("File: foo <BINARY>\n")
603 .stderr("");
606#[test]
607fn filename_multiple_ok() {
608 bat()
609 .arg("--decorations=always")
610 .arg("--style=header")
611 .arg("-r=0:0")
612 .arg("test.txt")
613 .arg("--file-name=foo")
614 .arg("single-line.txt")
615 .arg("--file-name=bar")
616 .assert()
617 .success()
618 .stdout("File: foo\n\nFile: bar\n")
619 .stderr("");
622#[test]
623fn filename_multiple_err() {
624 bat()
625 .arg("--decorations=always")
626 .arg("--style=header")
627 .arg("-r=0:0")
628 .arg("test.txt")
629 .arg("--file-name=foo")
630 .arg("single-line.txt")
631 .assert()
632 .failure();
635#[test]
636fn header_padding() {
637 bat()
638 .arg("--decorations=always")
639 .arg("--style=header")
640 .arg("test.txt")
641 .arg("single-line.txt")
642 .assert()
643 .stdout("File: test.txt\nhello world\n\nFile: single-line.txt\nSingle Line\n")
644 .stderr("");
647#[cfg(target_os = "linux")]
648#[test]
649fn file_with_invalid_utf8_filename() {
650 use std::ffi::OsStr;
651 use std::fs::File;
652 use std::io::Write;
653 use std::os::unix::ffi::OsStrExt;
655 use tempdir::TempDir;
657 let tmp_dir = TempDir::new("bat_test").expect("can create temporary directory");
658 let file_path = tmp_dir
659 .path()
660 .join(OsStr::from_bytes(b"test-invalid-utf8-\xC3(.rs"));
661 {
662 let mut file = File::create(&file_path).expect("can create temporary file");
663 writeln!(file, "dummy content").expect("can write to file");
664 }
666 bat()
667 .arg(file_path.as_os_str())
668 .assert()
669 .success()
670 .stdout("dummy content\n");
673#[test]
674fn do_not_panic_regression_tests() {
675 for filename in &[
676 "issue_28.md",
677 "issue_190.md",
678 "issue_314.hs",
679 "issue_914.rb",
680 "issue_915.vue",
681 ] {
682 bat()
683 .arg("--color=always")
684 .arg(&format!("regression_tests/{}", filename))
685 .assert()
686 .success();
687 }
690#[test]
691fn do_not_detect_different_syntax_for_stdin_and_files() {
692 let file = "regression_tests/issue_985.js";
694 let cmd_for_file = bat()
695 .arg("--color=always")
696 .arg("--map-syntax=*.js:Markdown")
697 .arg(&format!("--file-name={}", file))
698 .arg("--style=plain")
699 .arg(file)
700 .assert()
701 .success();
703 let cmd_for_stdin = bat()
704 .arg("--color=always")
705 .arg("--map-syntax=*.js:Markdown")
706 .arg("--style=plain")
707 .arg(&format!("--file-name={}", file))
708 .pipe_stdin(Path::new(EXAMPLES_DIR).join(file))
709 .unwrap()
710 .assert()
711 .success();
713 assert_eq!(
714 from_utf8(&cmd_for_file.get_output().stdout).expect("output is valid utf-8"),
715 from_utf8(&cmd_for_stdin.get_output().stdout).expect("output is valid utf-8")
716 );