on 0d2ef02 help sign in
bat/tests/integration_tests.rs
718 lines 15 kB history raw
1use assert_cmd::Command;
2use predicates::{prelude::predicate,str::PredicateStrExt};
3use std::path::Path;
4use std::str::from_utf8;
6const EXAMPLES_DIR: &str = "tests/examples";
8fn bat_with_config() -> Command {
9 let mut cmd = Command::cargo_bin("bat").unwrap();
10 cmd.current_dir("tests/examples");
11 cmd.env_remove("PAGER");
12 cmd.env_remove("BAT_PAGER");
13 cmd.env_remove("BAT_CONFIG_PATH");
14 cmd.env_remove("BAT_STYLE");
15 cmd.env_remove("BAT_THEME");
16 cmd.env_remove("BAT_TABS");
17 cmd
20fn bat() -> Command {
21 let mut cmd = bat_with_config();
22 cmd.arg("--no-config");
23 cmd
26#[test]
27fn basic() {
28 bat()
29 .arg("test.txt")
30 .assert()
31 .success()
32 .stdout("hello world\n")
33 .stderr("");
36#[test]
37fn stdin() {
38 bat()
39 .write_stdin("foo\nbar\n")
40 .assert()
41 .success()
42 .stdout("foo\nbar\n");
45#[test]
46fn concatenate() {
47 bat()
48 .arg("test.txt")
49 .arg("test.txt")
50 .assert()
51 .success()
52 .stdout("hello world\nhello world\n");
55#[test]
56fn concatenate_stdin() {
57 bat()
58 .arg("test.txt")
59 .arg("-")
60 .arg("test.txt")
61 .write_stdin("stdin\n")
62 .assert()
63 .success()
64 .stdout("hello world\nstdin\nhello world\n");
67#[test]
68fn concatenate_empty_first() {
69 bat()
70 .arg("empty.txt")
71 .arg("test.txt")
72 .assert()
73 .success()
74 .stdout("hello world\n");
77#[test]
78fn concatenate_empty_last() {
79 bat()
80 .arg("test.txt")
81 .arg("empty.txt")
82 .assert()
83 .success()
84 .stdout("hello world\n");
87#[test]
88fn concatenate_empty_both() {
89 bat()
90 .arg("empty.txt")
91 .arg("empty.txt")
92 .assert()
93 .success()
94 .stdout("");
97#[test]
98fn concatenate_empty_between() {
99 bat()
100 .arg("test.txt")
101 .arg("empty.txt")
102 .arg("test.txt")
103 .assert()
104 .success()
105 .stdout("hello world\nhello world\n");
108#[test]
109fn concatenate_empty_first_and_last() {
110 bat()
111 .arg("empty.txt")
112 .arg("test.txt")
113 .arg("empty.txt")
114 .assert()
115 .success()
116 .stdout("hello world\n");
119#[test]
120fn concatenate_single_line() {
121 bat()
122 .arg("single-line.txt")
123 .arg("single-line.txt")
124 .assert()
125 .success()
126 .stdout("Single LineSingle Line");
129#[test]
130fn concatenate_single_line_empty() {
131 bat()
132 .arg("single-line.txt")
133 .arg("empty.txt")
134 .arg("single-line.txt")
135 .assert()
136 .success()
137 .stdout("Single LineSingle Line");
140#[test]
141fn line_numbers() {
142 bat()
143 .arg("multiline.txt")
144 .arg("--style=numbers")
145 .arg("--decorations=always")
146 .assert()
147 .success()
148 .stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n");
151#[test]
152fn line_range_2_3() {
153 bat()
154 .arg("multiline.txt")
155 .arg("--line-range=2:3")
156 .assert()
157 .success()
158 .stdout("line 2\nline 3\n");
161#[test]
162fn line_range_first_two() {
163 bat()
164 .arg("multiline.txt")
165 .arg("--line-range=:2")
166 .assert()
167 .success()
168 .stdout("line 1\nline 2\n");
171#[test]
172fn line_range_last_3() {
173 bat()
174 .arg("multiline.txt")
175 .arg("--line-range=2:")
176 .assert()
177 .success()
178 .stdout("line 2\nline 3\nline 4\n");
181#[test]
182fn line_range_multiple() {
183 bat()
184 .arg("multiline.txt")
185 .arg("--line-range=1:2")
186 .arg("--line-range=4:4")
187 .assert()
188 .success()
189 .stdout("line 1\nline 2\nline 4\n");
192#[test]
193fn tabs_numbers() {
194 bat()
195 .arg("tabs.txt")
196 .arg("--tabs=4")
197 .arg("--style=numbers")
198 .arg("--decorations=always")
199 .assert()
200 .success()
201 .stdout(
202 " 1 1 2 3 4
203 2 1 ?
204 3 22 ?
205 4 333 ?
206 5 4444 ?
207 6 55555 ?
208 7 666666 ?
209 8 7777777 ?
210 9 88888888 ?
211",
212 );
215#[test]
216fn tabs_passthrough_wrapped() {
217 bat()
218 .arg("tabs.txt")
219 .arg("--tabs=0")
220 .arg("--style=plain")
221 .arg("--decorations=always")
222 .assert()
223 .success()
224 .stdout(
225 " 1 2 3 4
2261 ?
22722 ?
228333 ?
2294444 ?
23055555 ?
231666666 ?
2327777777 ?
23388888888 ?
234",
235 );
238#[test]
239fn tabs_4_wrapped() {
240 bat()
241 .arg("tabs.txt")
242 .arg("--tabs=4")
243 .arg("--style=plain")
244 .arg("--decorations=always")
245 .assert()
246 .success()
247 .stdout(
248 " 1 2 3 4
2491 ?
25022 ?
251333 ?
2524444 ?
25355555 ?
254666666 ?
2557777777 ?
25688888888 ?
257",
258 );
261#[test]
262fn tabs_8_wrapped() {
263 bat()
264 .arg("tabs.txt")
265 .arg("--tabs=8")
266 .arg("--style=plain")
267 .arg("--decorations=always")
268 .assert()
269 .success()
270 .stdout(
271 " 1 2 3 4
2721 ?
27322 ?
274333 ?
2754444 ?
27655555 ?
277666666 ?
2787777777 ?
27988888888 ?
280",
281 );
284#[test]
285fn tabs_passthrough() {
286 bat()
287 .arg("tabs.txt")
288 .arg("--tabs=0")
289 .arg("--style=plain")
290 .arg("--decorations=always")
291 .assert()
292 .success()
293 .stdout(
294 " 1 2 3 4
2951 ?
29622 ?
297333 ?
2984444 ?
29955555 ?
300666666 ?
3017777777 ?
30288888888 ?
303",
304 );
307#[test]
308fn tabs_4() {
309 bat()
310 .arg("tabs.txt")
311 .arg("--tabs=4")
312 .arg("--style=plain")
313 .arg("--decorations=always")
314 .assert()
315 .success()
316 .stdout(
317 " 1 2 3 4
3181 ?
31922 ?
320333 ?
3214444 ?
32255555 ?
323666666 ?
3247777777 ?
32588888888 ?
326",
327 );
330#[test]
331fn tabs_8() {
332 bat()
333 .arg("tabs.txt")
334 .arg("--tabs=8")
335 .arg("--style=plain")
336 .arg("--decorations=always")
337 .assert()
338 .success()
339 .stdout(
340 " 1 2 3 4
3411 ?
34222 ?
343333 ?
3444444 ?
34555555 ?
346666666 ?
3477777777 ?
34888888888 ?
349",
350 );
353#[test]
354fn fail_non_existing() {
355 bat().arg("non-existing-file").assert().failure();
358#[test]
359fn fail_directory() {
360 bat().arg("sub_directory").assert().failure();
363#[test]
364fn do_not_exit_directory() {
365 bat()
366 .arg("sub_directory")
367 .arg("test.txt")
368 .assert()
369 .stdout("hello world\n")
370 .failure();
373#[test]
374fn pager_basic() {
375 bat()
376 .env("PAGER", "echo pager-output")
377 .arg("--paging=always")
378 .arg("test.txt")
379 .assert()
380 .success()
381 .stdout(predicate::eq("pager-output\n").normalize());
384#[test]
385fn pager_overwrite() {
386 bat()
387 .env("PAGER", "echo other-pager")
388 .env("BAT_PAGER", "echo pager-output")
389 .arg("--paging=always")
390 .arg("test.txt")
391 .assert()
392 .success()
393 .stdout(predicate::eq("pager-output\n").normalize());
396#[test]
397fn pager_disable() {
398 bat()
399 .env("PAGER", "echo other-pager")
400 .env("BAT_PAGER", "")
401 .arg("--paging=always")
402 .arg("test.txt")
403 .assert()
404 .success()
405 .stdout(predicate::eq("hello world\n").normalize());
408#[test]
409fn config_location_test() {
410 bat_with_config()
411 .env("BAT_CONFIG_PATH", "bat.conf")
412 .arg("--config-file")
413 .assert()
414 .success()
415 .stdout("bat.conf\n");
418#[test]
419fn config_read_arguments_from_file() {
420 bat_with_config()
421 .env("BAT_CONFIG_PATH", "bat.conf")
422 .arg("test.txt")
423 .assert()
424 .success()
425 .stdout(predicate::eq("dummy-pager-from-config\n").normalize());
428#[test]
429fn utf16() {
430 // The output will be converted to UTF-8 with a leading UTF-8 BOM
431 bat()
432 .arg("--plain")
433 .arg("--decorations=always")
434 .arg("test_UTF-16LE.txt")
435 .assert()
436 .success()
437 .stdout(std::str::from_utf8(b"\xEF\xBB\xBFhello world\n").unwrap());
440#[test]
441fn can_print_file_named_cache() {
442 bat_with_config()
443 .arg("cache")
444 .assert()
445 .success()
446 .stdout("test\n")
447 .stderr("");
450#[test]
451fn can_print_file_named_cache_with_additional_argument() {
452 bat_with_config()
453 .arg("cache")
454 .arg("test.txt")
455 .assert()
456 .success()
457 .stdout("test\nhello world\n")
458 .stderr("");
461#[test]
462fn can_print_file_starting_with_cache() {
463 bat_with_config()
464 .arg("cache.c")
465 .assert()
466 .success()
467 .stdout("test\n")
468 .stderr("");
471#[test]
472fn does_not_print_unwanted_file_named_cache() {
473 bat_with_config().arg("cach").assert().failure();
476#[test]
477fn unicode_wrap() {
478 bat_with_config()
479 .arg("unicode-wrap.txt")
480 .arg("--style=numbers,snip")
481 .arg("--decorations=always")
482 .arg("--terminal-width=40")
483 .assert()
484 .success()
485 .stdout(
486 " 1 ビタミンA ビタミンD ビタミンE ビ
487 タミンK ビタミンB1 ビタミンB2 ナ
488 イアシン パントテン酸 ビタミンB6
489 ビタミンB12 葉酸 ビオチン ビタ
490 ミンC
491 2
492 3 고양이 고양이 고양이 고양이 고양이
493 고양이 고양이 고양이 고양이 고양이
494 고양이 고양이 고양이 고양이 고양이
495 고양이 고양이 고양이 고양이 고양이
496 고양이 고양이 고양이 고양이 고양이
497 고양이 고양이 고양이 고양이 고양이
498 고양이 고양이 고양이 고양이 고양이
499 고양이 고양이 고양이 고양이 고양이
500 고양이
501 4
502 5 1 บวก 2 บวก 3 บวก 4 บวก 5 บวก 6 บวก
503 7 บวก 8 บวก 9 บวก 10 บวก 11 บวก 12
504 บวก 13 บวก 14 บวก 15 บวก 16 บวก 17
505 บวก 18 บวก 19 บวก 20
506 6
507 7 Бельгия Болгария Чехия Дания Герман
508 ия Эстония Ирландия Греция Испания
509 Франция Хорватия Италия Кипр Латвия
510 Литва Люксембург Венгрия Мальта Ни
511 дерланды Австрия Польша Португалия
512 Румыния Словения Словакия Финляндия
513 Швеция Великобритания
514",
515 );
518#[test]
519fn snip() {
520 bat()
521 .arg("multiline.txt")
522 .arg("--style=numbers,snip")
523 .arg("--decorations=always")
524 .arg("--line-range=1:2")
525 .arg("--line-range=4:")
526 .arg("--terminal-width=80")
527 .assert()
528 .success()
529 .stdout(
530 " 1 line 1
531 2 line 2
532 ...─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ 8< ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
533 4 line 4
534",
535 );
538#[test]
539fn empty_file_leads_to_empty_output_with_grid_enabled() {
540 bat()
541 .arg("empty.txt")
542 .arg("--style=grid")
543 .arg("--decorations=always")
544 .arg("--terminal-width=80")
545 .assert()
546 .success()
547 .stdout("");
550#[test]
551fn filename_basic() {
552 bat()
553 .arg("test.txt")
554 .arg("--decorations=always")
555 .arg("--style=header")
556 .arg("-r=0:0")
557 .arg("--file-name=foo")
558 .assert()
559 .success()
560 .stdout("File: foo\n")
561 .stderr("");
564#[test]
565fn filename_binary() {
566 bat()
567 .arg("test.binary")
568 .arg("--decorations=always")
569 .arg("--style=header")
570 .arg("-r=0:0")
571 .arg("--file-name=foo")
572 .assert()
573 .success()
574 .stdout("File: foo <BINARY>\n")
575 .stderr("");
578#[test]
579fn filename_stdin() {
580 bat()
581 .arg("--decorations=always")
582 .arg("--style=header")
583 .arg("-r=0:0")
584 .arg("-")
585 .write_stdin("stdin\n")
586 .arg("--file-name=foo")
587 .assert()
588 .success()
589 .stdout("File: foo\n")
590 .stderr("");
593#[test]
594fn filename_stdin_binary() {
595 let vec = vec![0; 1];
596 bat_with_config()
597 .arg("--decorations=always")
598 .arg("--style=header")
599 .write_stdin(vec)
600 .arg("--file-name=foo")
601 .assert()
602 .success()
603 .stdout("File: foo <BINARY>\n")
604 .stderr("");
607#[test]
608fn filename_multiple_ok() {
609 bat()
610 .arg("--decorations=always")
611 .arg("--style=header")
612 .arg("-r=0:0")
613 .arg("test.txt")
614 .arg("--file-name=foo")
615 .arg("single-line.txt")
616 .arg("--file-name=bar")
617 .assert()
618 .success()
619 .stdout("File: foo\n\nFile: bar\n")
620 .stderr("");
623#[test]
624fn filename_multiple_err() {
625 bat()
626 .arg("--decorations=always")
627 .arg("--style=header")
628 .arg("-r=0:0")
629 .arg("test.txt")
630 .arg("--file-name=foo")
631 .arg("single-line.txt")
632 .assert()
633 .failure();
636#[test]
637fn header_padding() {
638 bat()
639 .arg("--decorations=always")
640 .arg("--style=header")
641 .arg("test.txt")
642 .arg("single-line.txt")
643 .assert()
644 .stdout("File: test.txt\nhello world\n\nFile: single-line.txt\nSingle Line\n")
645 .stderr("");
648#[cfg(target_os = "linux")]
649#[test]
650fn file_with_invalid_utf8_filename() {
651 use std::ffi::OsStr;
652 use std::fs::File;
653 use std::io::Write;
654 use std::os::unix::ffi::OsStrExt;
656 use tempdir::TempDir;
658 let tmp_dir = TempDir::new("bat_test").expect("can create temporary directory");
659 let file_path = tmp_dir
660 .path()
661 .join(OsStr::from_bytes(b"test-invalid-utf8-\xC3(.rs"));
662 {
663 let mut file = File::create(&file_path).expect("can create temporary file");
664 writeln!(file, "dummy content").expect("can write to file");
665 }
667 bat()
668 .arg(file_path.as_os_str())
669 .assert()
670 .success()
671 .stdout("dummy content\n");
674#[test]
675fn do_not_panic_regression_tests() {
676 for filename in &[
677 "issue_28.md",
678 "issue_190.md",
679 "issue_314.hs",
680 "issue_914.rb",
681 "issue_915.vue",
682 ] {
683 bat()
684 .arg("--color=always")
685 .arg(&format!("regression_tests/{}", filename))
686 .assert()
687 .success();
688 }
691#[test]
692fn do_not_detect_different_syntax_for_stdin_and_files() {
693 let file = "regression_tests/issue_985.js";
695 let cmd_for_file = bat()
696 .arg("--color=always")
697 .arg("--map-syntax=*.js:Markdown")
698 .arg(&format!("--file-name={}", file))
699 .arg("--style=plain")
700 .arg(file)
701 .assert()
702 .success();
704 let cmd_for_stdin = bat()
705 .arg("--color=always")
706 .arg("--map-syntax=*.js:Markdown")
707 .arg("--style=plain")
708 .arg(&format!("--file-name={}", file))
709 .pipe_stdin(Path::new(EXAMPLES_DIR).join(file))
710 .unwrap()
711 .assert()
712 .success();
714 assert_eq!(
715 from_utf8(&cmd_for_file.get_output().stdout).expect("output is valid utf-8"),
716 from_utf8(&cmd_for_stdin.get_output().stdout).expect("output is valid utf-8")
717 );