Skip to content

Commit

Permalink
Add GNU ls compatibility tests
Browse files Browse the repository at this point in the history
This adds an initial set of integration tests that make sure that we
generate the same styles as GNU `ls`.

Related: #48
  • Loading branch information
sharkdp committed Apr 1, 2023
1 parent 56c077d commit 784c6df
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 2 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/CICD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ jobs:
shell: bash
run: |
# test only library unit tests and binary for arm-type targets
unset CARGO_TEST_OPTIONS
unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--all-features --lib --bin ${{ needs.crate_metadata.outputs.name }}" ;; esac;
CARGO_TEST_OPTIONS="--all-features"
case ${{ matrix.job.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--all-features --lib --bin ${{ needs.crate_metadata.outputs.name }}" ;; esac;
echo "CARGO_TEST_OPTIONS=${CARGO_TEST_OPTIONS}" >> $GITHUB_OUTPUT
- name: Run tests
Expand Down
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,8 @@ required-features = ["nu-ansi-term"]
lto = true
strip = true
codegen-units = 1

[[test]]
name = "integration_tests"
path = "tests/integration_tests.rs"
required-features = ["nu-ansi-term"]
79 changes: 79 additions & 0 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use lscolors::LsColors;
use lscolors::Style;

use std::process::Command;

fn get_ls_style(ls_colors_env: Option<&str>, path: &str) -> Option<Style> {
let output_gnu_ls = {
let mut cmd = Command::new("ls");

cmd.arg("--color=always").arg("--directory").arg(path);

if let Some(ls_colors_env) = ls_colors_env {
cmd.env("LS_COLORS", ls_colors_env);
} else {
cmd.env_remove("LS_COLORS");
}

cmd.output().unwrap().stdout
};

let output_gnu_ls = String::from_utf8(output_gnu_ls).expect("valid UTF-8 output from ls");

let style_str = output_gnu_ls.trim().trim_start_matches("\x1b[0m\x1b[");

let end_of_ansi_code = style_str.find(&format!("m{path}", path = path))?;
let style_str = &style_str[0..end_of_ansi_code];

// For a proper integration test, we would ideally compare the output on an ANSI-escape-sequence level.
// Unfortunately, those are not unambiguous. Both \x1b[1m as well as \x1b[01m render something in bold.
// So instead, we trust our escape sequence parser (and its tests) and compare the output on a `Style`
// level.
Style::from_ansi_sequence(&style_str)
}

fn assert_style_matches_ls(lscolors: &LsColors, ls_colors_env: Option<&str>, path: &str) {
let lscolors_style = lscolors.style_for_path(path);
let ls_style = get_ls_style(ls_colors_env, path);

assert_eq!(lscolors_style, ls_style.as_ref());
}

#[cfg(unix)]
#[test]
fn gnu_ls_compatibility_no_ls_colors() {
let lscolors = LsColors::default();

assert_style_matches_ls(&lscolors, None, "tests/");
assert_style_matches_ls(&lscolors, None, "Cargo.toml");
}

#[cfg(unix)]
#[test]
fn gnu_ls_compatibility_custom_ls_colors() {
{
let ls_colors_env = "*.toml=01;31";
let lscolors = LsColors::from_string(ls_colors_env);

assert_style_matches_ls(&lscolors, Some(ls_colors_env), "tests/");
assert_style_matches_ls(&lscolors, Some(ls_colors_env), "Cargo.toml");
}
{
let ls_colors_env = "*.toml=01;31:di=32";
let lscolors = LsColors::from_string(ls_colors_env);

assert_style_matches_ls(&lscolors, Some(ls_colors_env), "tests/");
assert_style_matches_ls(&lscolors, Some(ls_colors_env), "Cargo.toml");
}
}

#[cfg(unix)]
#[test]
fn gnu_ls_compatibility_duplicate_entries() {
{
let ls_colors_env = "*.toml=31:*.toml=32";
let lscolors = LsColors::from_string(ls_colors_env);

assert_style_matches_ls(&lscolors, Some(ls_colors_env), "Cargo.toml");
}
}

0 comments on commit 784c6df

Please sign in to comment.