Merge branch 'specsheet'

This commit is contained in:
Benjamin Sago 2020-10-18 22:48:02 +01:00
commit 63ddab6958
155 changed files with 1574 additions and 448 deletions

12
Cargo.lock generated
View File

@ -152,9 +152,9 @@ checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
[[package]]
name = "libgit2-sys"
version = "0.12.13+1.0.1"
version = "0.12.14+1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "069eea34f76ec15f2822ccf78fe0cdb8c9016764d0a12865278585a74dbdeae5"
checksum = "8f25af58e6495f7caf2919d08f212de550cfa3ed2f5e744988938ea292b9f549"
dependencies = [
"cc",
"libc",
@ -247,9 +247,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "openssl-src"
version = "111.11.0+1.1.1h"
version = "111.12.0+1.1.1h"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380fe324132bea01f45239fadfec9343adb044615f29930d039bec1ae7b9fa5b"
checksum = "858a4132194f8570a7ee9eb8629e85b23cbc4565f2d4a162e87556e5956abf61"
dependencies = [
"cc",
]
@ -285,9 +285,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pkg-config"
version = "0.3.18"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "redox_syscall"

View File

@ -1,5 +1,5 @@
all: build test
all-release: build-release test-release
all: build test xtests
all-release: build-release test-release xtests-release
# compiles the exa binary
@ -28,6 +28,15 @@ all-release: build-release test-release
cargo hack test --feature-powerset -- --quiet
# runs extended tests
@xtests:
xtests/run.sh
# runs extended tests (using the release mode exa)
@xtests-release:
xtests/run.sh --release
# lints the code
@clippy:
touch src/main.rs

72
Vagrantfile vendored
View File

@ -1,5 +1,3 @@
require 'date'
Vagrant.configure(2) do |config|
# We use Ubuntu instead of Debian because the image comes with two-way
@ -31,20 +29,19 @@ Vagrant.configure(2) do |config|
# Install the dependencies needed for exa to build, as quietly as
# apt can do.
config.vm.provision :shell, privileged: true, inline: <<-EOF
trap 'exit' ERR
apt-get update
apt-get install -qq -o=Dpkg::Use-Pty=0 -y \
git cmake curl attr libgit2-dev zip \
fish zsh bash bash-completion
if hash fish &>/dev/null; then
echo "Tools are already installed"
else
trap 'exit' ERR
echo "Installing tools"
apt-get update -qq
apt-get install -qq -o=Dpkg::Use-Pty=0 \
git gcc curl attr libgit2-dev zip \
fish zsh bash bash-completion
fi
EOF
# Guarantee that the timezone is UTC -- some of the tests
# depend on this (for now).
config.vm.provision :shell, privileged: true, inline:
%[timedatectl set-timezone UTC]
# Install Rust.
# This is done as vagrant, not root, because its vagrant
# who actually uses it. Sent to /dev/null because the progress
@ -54,38 +51,43 @@ Vagrant.configure(2) do |config|
echo "Rust is already installed"
else
trap 'exit' ERR
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "Installing Rust"
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --profile minimal --component rustc,rust-std,cargo,clippy -y
source $HOME/.cargo/env
cargo install cargo-hack
cargo install -q cargo-hack
fi
EOF
# Install Just, the command runner.
# Privileged installation and setup scripts.
config.vm.provision :shell, privileged: true, inline: <<-EOF
# Install Just, the command runner.
if hash just &>/dev/null; then
echo "just is already installed"
else
wget "https://github.com/casey/just/releases/download/v0.8.0/just-v0.8.0-x86_64-unknown-linux-musl.tar.gz"
trap 'exit' ERR
echo "Installing just"
wget -q "https://github.com/casey/just/releases/download/v0.8.0/just-v0.8.0-x86_64-unknown-linux-musl.tar.gz"
tar -xf "just-v0.8.0-x86_64-unknown-linux-musl.tar.gz"
cp just /usr/local/bin
fi
EOF
# Use a different target directory on the VM than on the host.
# By default it just uses the one in /vagrant/target, which can
# cause problems if it has different permissions than the other
# directories, or contains object files compiled for the host.
config.vm.provision :shell, privileged: true, inline: <<-EOF
# Guarantee that the timezone is UTC — some of the tests
# depend on this (for now).
timedatectl set-timezone UTC
# Use a different target directory on the VM than on the host.
# By default it just uses the one in /vagrant/target, which can
# cause problems if it has different permissions than the other
# directories, or contains object files compiled for the host.
echo 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/#{developer}/.cargo/bin"' > /etc/environment
echo 'CARGO_TARGET_DIR="/home/#{developer}/target"' >> /etc/environment
EOF
# Create a variety of misc scripts.
config.vm.provision :shell, privileged: true, inline: <<-EOF
trap 'exit' ERR
# Create a variety of misc scripts.
ln -sf /vagrant/devtools/dev-run-debug.sh /usr/bin/exa
ln -sf /vagrant/devtools/dev-run-release.sh /usr/bin/rexa
@ -106,16 +108,12 @@ Vagrant.configure(2) do |config|
echo -e "#!/bin/sh\ncat /etc/motd" > /usr/bin/halp
chmod +x /usr/bin/{exa,rexa,b,t,x,c,build-exa,test-exa,run-xtests,compile-exa,package-exa,halp}
EOF
# Configure the welcoming text that gets shown.
config.vm.provision :shell, privileged: true, inline: <<-EOF
trap 'exit' ERR
rm -f /etc/update-motd.d/*
# Configure the welcoming text that gets shown:
# Capture the help text so it gets displayed first
rm -f /etc/update-motd.d/*
bash /vagrant/devtools/dev-help.sh > /etc/motd
# Tell bash to execute a bunch of stuff when a session starts
@ -125,19 +123,19 @@ Vagrant.configure(2) do |config|
# Disable last login date in sshd
sed -i '/PrintLastLog yes/c\PrintLastLog no' /etc/ssh/sshd_config
systemctl restart sshd
EOF
# Link the completion files so theyre “installed”.
config.vm.provision :shell, privileged: true, inline: <<-EOF
trap 'exit' ERR
# Link the completion files so theyre “installed”:
# bash
test -h /etc/bash_completion.d/exa \
|| ln -s /vagrant/contrib/completions.bash /etc/bash_completion.d/exa
# zsh
test -h /usr/share/zsh/vendor-completions/_exa \
|| ln -s /vagrant/contrib/completions.zsh /usr/share/zsh/vendor-completions/_exa
# fish
test -h /usr/share/fish/completions/exa.fish \
|| ln -s /vagrant/contrib/completions.fish /usr/share/fish/completions/exa.fish
EOF

View File

@ -20,6 +20,7 @@ fi
sudo mkdir "$TEST_ROOT"
sudo chmod 777 "$TEST_ROOT"
sudo mkdir "$TEST_ROOT/empty"
# Awkward file size testcases.
@ -189,22 +190,26 @@ echo -e "\033[1m[ 8/13]\033[0m Creating date and time testcases"
# theres no way to touch the created date of a file...
# so we have to do this the old-fashioned way!
# (and make sure these don't actually get listed)
touch -t $OLD_DATE "$TEST_ROOT/dates/peach"; sleep 1
touch -t $MED_DATE "$TEST_ROOT/dates/plum"; sleep 1
touch -t $NEW_DATE "$TEST_ROOT/dates/pear"
touch -t $FIXED_OLD_DATE "$TEST_ROOT/dates/peach"; sleep 1
touch -t $FIXED_MED_DATE "$TEST_ROOT/dates/plum"; sleep 1
touch -t $FIXED_NEW_DATE "$TEST_ROOT/dates/pear"
# modified dates
touch -t $OLD_DATE -m "$TEST_ROOT/dates/pear"
touch -t $MED_DATE -m "$TEST_ROOT/dates/peach"
touch -t $NEW_DATE -m "$TEST_ROOT/dates/plum"
touch -t $FIXED_OLD_DATE -m "$TEST_ROOT/dates/pear"
touch -t $FIXED_MED_DATE -m "$TEST_ROOT/dates/peach"
touch -t $FIXED_NEW_DATE -m "$TEST_ROOT/dates/plum"
# accessed dates
touch -t $OLD_DATE -a "$TEST_ROOT/dates/plum"
touch -t $MED_DATE -a "$TEST_ROOT/dates/pear"
touch -t $NEW_DATE -a "$TEST_ROOT/dates/peach"
touch -t $FIXED_OLD_DATE -a "$TEST_ROOT/dates/plum"
touch -t $FIXED_MED_DATE -a "$TEST_ROOT/dates/pear"
touch -t $FIXED_NEW_DATE -a "$TEST_ROOT/dates/peach"
sudo chown $FIXED_USER:$FIXED_USER -R "$TEST_ROOT/dates"
mkdir "$TEST_ROOT/far-dates"
touch -t $FIXED_PAST_DATE "$TEST_ROOT/far-dates/the-distant-past"
touch -t $FIXED_FUTURE_DATE "$TEST_ROOT/far-dates/beyond-the-future"
# Awkward extended attribute testcases.
# We need to test combinations of various numbers of files *and*
@ -302,6 +307,10 @@ mkdir "deeply/nested/repository"
cd "deeply/nested/repository"
git init >/dev/null
touch subfile
# This file, subfile, should _not_ be marked as a new file by exa, because
# its in the sub-repository but hasnt been added to it. Were the sub-repo not
# present, it would be marked as a new file, as the top-level repo knows about
# the deeply directory.
find "$TEST_ROOT/git2" -exec touch {} -t $FIXED_DATE \;
sudo chown $FIXED_USER:$FIXED_USER -R "$TEST_ROOT/git2"
@ -318,9 +327,7 @@ git init >/dev/null
ln -s aaa/aaa/a b
# This normally fails with:
# touch: cannot touch '/testcases/git3/b': No such file or directory
# but thats expected (the file deliberately does not exist)
find "$TEST_ROOT/git3" -exec touch {} -t $FIXED_DATE \; 2>/dev/null
find "$TEST_ROOT/git3" -exec touch {} -h -t $FIXED_DATE \;
sudo chown $FIXED_USER:$FIXED_USER -R "$TEST_ROOT/git3"
@ -332,6 +339,7 @@ shopt -u dotglob
GLOBIGNORE=".:.."
mkdir "$TEST_ROOT/hiddens"
cd "$TEST_ROOT/hiddens"
touch "$TEST_ROOT/hiddens/visible"
touch "$TEST_ROOT/hiddens/.hidden"
touch "$TEST_ROOT/hiddens/..extra-hidden"

View File

@ -34,6 +34,10 @@ export FIXED_LONG_USER="antidisestablishmentarienism"
# A couple of dates, for date-time testing.
export OLD_DATE='200303030000.00'
export MED_DATE='200606152314.29' # the june gets used for fr_FR locale tests
export NEW_DATE='200912221038.53' # and the december for ja_JP local tests
export FIXED_OLD_DATE='200303030000.00'
export FIXED_MED_DATE='200606152314.29' # the june gets used for fr_FR locale tests
export FIXED_NEW_DATE='200912221038.53' # and the december for ja_JP local tests
# Dates that extend beyond 32-bit timespace.
export FIXED_PAST_DATE='170001010000.00'
export FIXED_FUTURE_DATE='230001010000.00'

View File

@ -30,10 +30,26 @@ else
fi
# set up locales
# locale generation
# remove most of this file, it slows down locale-gen
if grep -F -q "en_GB.UTF-8 UTF-8" /var/lib/locales/supported.d/en; then
echo "Removing existing locales"
echo "en_US.UTF-8 UTF-8" > /var/lib/locales/supported.d/en
fi
# uncomment these from the config file
sudo sed -i '/fr_FR.UTF-8/s/^# //g' /etc/locale.gen
sudo sed -i '/ja_JP.UTF-8/s/^# //g' /etc/locale.gen
if grep -F -q "# fr_FR.UTF-8" /etc/locale.gen; then
sed -i '/fr_FR.UTF-8/s/^# //g' /etc/locale.gen
fi
if grep -F -q "# ja_JP.UTF-8" /etc/locale.gen; then
sed -i '/ja_JP.UTF-8/s/^# //g' /etc/locale.gen
fi
sudo locale-gen
# only regenerate locales if the config files are newer than the locale archive
if [[ ( /var/lib/locales/supported.d/en -nt /usr/lib/locale/locale-archive ) || \
( /etc/locale_gen -nt /usr/lib/locale/locale-archive ) ]]; then
locale-gen
else
echo "Locales already generated"
fi

View File

@ -1,4 +1,47 @@
## Extra tests
# exa xtests
These extra tests are intended to be run from a Vagrant VM that has already had its environment set up -- see the section in the README for more details.
These are the **extended tests**. They are integration tests: they run the `exa` binary with select configurations of parameters and environment variables, and assert that the program prints the correct text to standard output and error, and exits with the correct status code.
They test things like:
- broken symlinks
- extended attributes
- file names with weird stuff like newlines or escapes in
- invalid UTF-8
- missing users and groups
- nested Git repositories
They are intended to be run from the Vagrant VM that has already had its environment set up — see the `devtools/dev-create-test-filesystem.sh` script for how the files are generated.
## Anatomy of the tests
The tests are run using [Specsheet](https://specsheet.software/). The TOML files define the tests, and the files in `output/` contain the output that exa should produce.
For example, lets look at one of the tests in `lines-view.toml`. This test checks that running exa does the right thing when running with the `-1` argument, and a directory full of files:
```toml
[[cmd]]
name = "exa -1 displays file names, one on each line"
shell = "exa -1 /testcases/file-names"
stdout = { file = "outputs/names_lines.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'oneline' ]
```
Heres an explanation of each line:
1. The `[[cmd]]` line marks this test as a [cmd](https://specsheet.software/checks/command/cmd) check, which can run arbitrary commands. In this case, the commad is exa with some arguments.
2. The `name` field is a human-readable description of the feature of exa thats under test. It gets printed to the screen as tests are run.
3. The `shell` field contains the shell script to execute. It should have `exa` in there somewhere.
4. The `stdout` field describes the [content](https://specsheet.software/docs/check-file-schema#content) that exa should print to standard output. In this case, the test asserts that the output of running the program should be identical to the contents of the file.
5. The `stderr` field describes the content of standard error. In this case, it asserts that nothing is printed to stderr.
6. The `status` field asserts that exa should exit with a status code of 0.
7. The `tags` field does not change the test at all, but can be used to filter which tests are run, instead of running all of them each time.

42
xtests/attributes.toml Normal file
View File

@ -0,0 +1,42 @@
[[cmd]]
name = "exa -@lT produces a tree view with metadata and attribute entries"
shell = "exa -@lT /testcases/attributes"
stdout = { file = "outputs/attributes_xattrs_long_tree.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'xattrs', 'long', 'tree' ]
[[cmd]]
name = "exa -@T produces a tree view with attribute entries"
shell = "exa -@T /testcases/attributes"
stdout = { file = "outputs/attributes_xattrs_tree.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'xattrs', 'tree' ]
[[cmd]]
name = "exa -@T with file arguments produces a tree view with attribute entries"
shell = "exa -@T /testcases/attributes/*"
stdout = { file = "outputs/attributes_files_xattrs_tree.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'xattrs', 'tree' ]
[[cmd]]
name = "exa -@T produces a tree view with attribute entries of symlinks"
shell = "exa -@T /testcases/links"
stdout = { file = "outputs/links_xattrs_tree.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'xattrs', 'tree' ]
# permission errors tests
[[cmd]]
name = "exa -@T displays an inaccessible directory with errors"
shell = "exa -@T /proc/1/root"
stdout = { file = "outputs/proc_1_root_xattrs.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'tree' ]

57
xtests/colour-term.toml Normal file
View File

@ -0,0 +1,57 @@
# details view (check the argument works)
[[cmd]]
name = "exa -l --colour=always always uses colours for metadata"
shell = "exa -l --colour=always /testcases/files"
stdout = { file = "outputs/files_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'colour-term' ]
[[cmd]]
name = "exa -l --colour=never never uses colours for metadata"
shell = "exa -l --colour=never /testcases/files"
stdout = { file = "outputs/files_long_monochrome.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'colour-term' ]
[[cmd]]
name = "exa -l --colour=automatic uses colours dependently for metadata"
shell = "exa -l --colour=automatic /testcases/files"
stdout = { file = "outputs/files_long_monochrome.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'colour-term' ]
# grid view (check that all colours are turned off)
[[cmd]]
name = "exa --colour=never never uses colours for file names"
shell = "exa --colour=never /testcases/file-names"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/files_grid_monochrome.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'grid', 'colour-term' ]
[[cmd]]
name = "exa --colour=never never uses colours for files based on their extensions"
shell = "exa --colour=never /testcases/file-names-exts"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/exts_grid_monochrome.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'grid', 'colour-term' ]
# tree view (check that all colours are turned off)
[[cmd]]
name = "exa -T --colour=never never uses colours for punctuation and symlink targets"
shell = "exa -T --colour=never /testcases/file-names/links"
stdout = { file = "outputs/links_grid_monochrome.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'tree', 'colour-term' ]

View File

@ -1,4 +0,0 @@
Permissions Size User Date Modified Name
.rw-rw-r-- 0 cassowary  3 Mar 2003 pear
.rw-rw-r-- 0 cassowary 15 Jun 2006 peach
.rw-rw-r-- 0 cassowary 22 Dec 2009 plum

17
xtests/debug-logging.toml Normal file
View File

@ -0,0 +1,17 @@
[[cmd]]
name = "EXA_DEBUG=1 exa produces debug output"
shell = "exa --long /testcases"
environment = { EXA_DEBUG = "1" }
stdout = { empty = false }
stderr = { string = "DEBUG" }
status = 0
tags = [ 'debug', 'env', 'long' ]
[[cmd]]
name = "EXA_DEBUG=trace exa produces trace-level debug output"
shell = "exa --long /testcases"
environment = { EXA_DEBUG = "trace" }
stdout = { empty = false }
stderr = { string = "TRACE" }
status = 0
tags = [ 'debug', 'env', 'long' ]

View File

@ -0,0 +1,84 @@
# various date fields
[[cmd]]
name = "exa -lh produces a table using the modified time field"
shell = "exa -lh /testcases/dates"
stdout = { file = "outputs/dates_long_time_modified.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'header', 'time' ]
[[cmd]]
name = "exa -lh --time=modified produces a table using the modified time field"
shell = "exa -lh --time=modified /testcases/dates"
stdout = { file = "outputs/dates_long_time_modified.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'header', 'time' ]
[[cmd]]
name = "exa -lh --time=accessed produces a table using the accessed time field"
shell = "exa -lh --time=accessed /testcases/dates"
stdout = { file = "outputs/dates_long_time_accessed.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'header', 'time' ]
# distant past and far future dates
[[cmd]]
name = "exa -l handles dates far past and future dates"
shell = "exa -l /testcases/far-dates"
stdout = { file = "outputs/far_dates_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'time' ]
# alternate date formats
[[cmd]]
name = "exa -l --time-style=long-iso produces a table using the long-iso date format"
shell = "exa -l --time-style=long-iso /testcases/dates"
stdout = { file = "outputs/dates_long_timestyle_longiso.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'time-style' ]
[[cmd]]
name = "exa -l --time-style=full-iso produces a table using the full-iso date format"
shell = "exa -l --time-style=full-iso /testcases/dates"
stdout = { file = "outputs/dates_long_timestyle_fulliso.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'time-style' ]
[[cmd]]
name = "exa -l --time-style=iso produces a table using the iso date format"
shell = "exa -l --time-style=iso /testcases/dates"
stdout = { file = "outputs/dates_long_timestyle_iso.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'time-style' ]
# locales
[[cmd]]
name = "exa -l using a locale with 4-character-long month abbreviations (ja_JP) sizes the date column correctly"
shell = "exa -l /testcases/dates"
environment = { LC_ALL = "ja_JP.UTF-8", LANG = "ja_JP.UTF-8" }
stdout = { file = "outputs/dates_long_localejp.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'locales' ]
[[cmd]]
name = "exa -l using a locale with 5-character-long month abbreviations (fr_FR) sizes the date column correctly"
shell = "exa -l /testcases/dates"
environment = { LC_ALL = "fr_FR.UTF-8", LANG = "fr_FR.UTF-8" }
stdout = { file = "outputs/dates_long_localefr.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'locales' ]

View File

@ -0,0 +1,63 @@
[[cmd]]
name = "exa -lb produces a details table with binary file sizes"
shell = "exa -lb /testcases/files"
stdout = { file = "outputs/files_long_binary.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'binary' ]
[[cmd]]
name = "exa -lB produces a details table with bytes file sizes"
shell = "exa -lB /testcases/files"
stdout = { file = "outputs/files_long_bytes.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'bytes' ]
[[cmd]]
name = "exa -lhb produces a details table with a header and binary file sizes"
shell = "exa -lhb /testcases/files"
stdout = { file = "outputs/files_long_header_binary.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'header', 'binary' ]
[[cmd]]
name = "exa -lhB produces a details table with a header and bytes file sizes"
shell = "exa -lhB /testcases/files"
stdout = { file = "outputs/files_long_header_bytes.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'header', 'bytes' ]
[[cmd]]
name = "exa -l --color-scale (US spelling) produces a details table using a file size colour scale"
shell = "exa -l --color-scale /testcases/files"
stdout = { file = "outputs/files_long_colourscale.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'colour-scale' ]
[[cmd]]
name = "exa -l --colour-scale (UK spelling) produces a details table using a file size colour scale"
shell = "exa -l --colour-scale /testcases/files"
stdout = { file = "outputs/files_long_colourscale.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'colour-scale' ]
[[cmd]]
name = "exa -l --colour-scale --binary produces a details table using a file size colour scale and binary sizes"
shell = "exa -l --colour-scale --binary /testcases/files"
stdout = { file = "outputs/files_long_colourscale_binary.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'colour-scale', 'binary' ]
[[cmd]]
name = "exa -l --colour-scale --bytes produces a details table using a file size colour scale and byte sizes"
shell = "exa -l --colour-scale --bytes /testcases/files"
stdout = { file = "outputs/files_long_colourscale_bytes.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'colour-scale', 'bytes' ]

View File

@ -0,0 +1,7 @@
[[cmd]]
name = "exa -lgh produces a tree view with attribute entries"
shell = "exa -lgh /testcases/passwd"
stdout = { file = "outputs/passwd_long_group_header.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'group', 'header' ]

View File

@ -0,0 +1,15 @@
[[cmd]]
name = "exa -lghR (not as the user) produces a tree view with attribute entries"
shell = "exa -lghR /testcases/permissions"
stdout = { file = "outputs/permissions_long_group_header.ansitxt" }
stderr = { string = "/testcases/permissions/forbidden-directory: Permission denied (os error 13)" }
status = 0
tags = [ 'long', 'group', 'header', 'xattrs' ]
[[cmd]]
name = "exa -lghR (as the user) produces a tree view with attribute entries"
shell = "sudo -u cassowary exa -lghR /testcases/permissions"
stdout = { file = "outputs/permissions_long_group_header_sudo.ansitxt" }
stderr = { string = "/testcases/permissions/forbidden-directory: Permission denied (os error 13)" }
status = 0
tags = [ 'long', 'group', 'header', 'xattrs', 'sudo' ]

45
xtests/details-view.toml Normal file
View File

@ -0,0 +1,45 @@
[[cmd]]
name = "exa -l produces a details table"
shell = "exa -l /testcases/files"
stdout = { file = "outputs/files_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long' ]
# header tests
[[cmd]]
name = "exa -lh produces a details table with a header"
shell = "exa -lh /testcases/files"
stdout = { file = "outputs/files_long_header.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'header' ]
[[cmd]]
name = "exa -lh with an empty directory skips the header"
shell = "exa -lh /testcases/empty"
stdout = { empty = true }
stderr = { empty = true }
status = 0
tags = [ 'long', 'header' ]
# file kinds
[[cmd]]
name = "exa -l handles file kinds"
shell = "exa -l /testcases/specials"
stdout = { file = "outputs/specials_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long' ]
[[cmd]]
name = "exa -lF handles and classifies file kinds"
shell = "exa -lF /testcases/specials"
stdout = { file = "outputs/specials_long_classify.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'classify' ]

View File

@ -1,3 +0,0 @@
target
target/debug
target/debug/build

58
xtests/dotfiles.toml Normal file
View File

@ -0,0 +1,58 @@
# hidden files in grid view
[[cmd]]
name = "exa does not show hidden files (in grid view)"
shell = "exa /testcases/hiddens"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/hiddens_grid.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'all', 'grid' ]
[[cmd]]
name = "exa -a shows hidden files (in grid view)"
shell = "exa -a /testcases/hiddens"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/hiddens_grid_all.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'all', 'grid' ]
[[cmd]]
name = "exa -aa shows hidden files, ., and .. (in grid view)"
shell = "exa -aa /testcases/hiddens"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/hiddens_grid_all_all.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'all', 'grid' ]
# hidden files in long view
[[cmd]]
name = "exa -l does not show hidden files (in details view)"
shell = "exa -l /testcases/hiddens"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/hiddens_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'all', 'long' ]
[[cmd]]
name = "exa -la shows hidden files (in details view)"
shell = "exa -la /testcases/hiddens"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/hiddens_long_all.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'all', 'long' ]
[[cmd]]
name = "exa -laa shows hidden files, ., and .. (in details view)"
shell = "exa -laa /testcases/hiddens"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/hiddens_long_all_all.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'all', 'long' ]

View File

View File

@ -1 +0,0 @@
Flag -l conflicts with flag --long

View File

@ -1 +0,0 @@
Unknown argument --ternary

View File

@ -1,2 +0,0 @@
Flag -t needs a value (choices: modified, changed, accessed, created)
To sort newest files last, try "--sort newest", or just "-snew"

View File

@ -1,2 +0,0 @@
Option --time (-t) has no "r" setting (choices: modified, changed, accessed, created)
To sort oldest files last, try "--sort oldest", or just "-sold"

View File

@ -1 +0,0 @@
Flag --long cannot take a value

View File

@ -1 +0,0 @@
Option --time-style has no "24" setting (choices: default, long-iso, full-iso, iso)

View File

@ -1 +0,0 @@
Unknown argument -4

View File

@ -1 +0,0 @@
Flag -l was given twice

View File

@ -1 +0,0 @@
Option --binary (-b) is useless without option --long (-l)

View File

@ -1 +0,0 @@
Flag --time needs a value (choices: modified, changed, accessed, created)

17
xtests/errors.toml Normal file
View File

@ -0,0 +1,17 @@
# Error suggestions
[[cmd]]
name = "exa -ltr offers a suggestion"
shell = "exa -ltr"
stdout = { empty = true }
stderr = { string = "To sort oldest files last, try \"--sort oldest\", or just \"-sold\""}
status = 3
tags = [ 'error', 'long', 'sort' ]
[[cmd]]
name = "exa -lt offers a suggestion"
shell = "exa -lt"
stdout = { empty = true }
stderr = { string = "To sort newest files last, try \"--sort newest\", or just \"-snew\""}
status = 3
tags = [ 'error', 'long', 'sort' ]

View File

@ -1,29 +0,0 @@
/testcases/file-names
├── ansi: [\u{1b}[34mblue\u{1b}[0m]
├── ascii: hello
├── backspace: [\u{8}]
├── bell: [\u{7}]
├── emoji: [🆒]
├── escape: [\u{1b}]
├── form-feed: [\u{c}]
├── invalid-utf8-1: [<5B>]
│ └── <Error: path somehow contained a NUL?>
├── invalid-utf8-2: [<5B>(]
│ └── <Error: path somehow contained a NUL?>
├── invalid-utf8-3: [<5B>(]
│ └── <Error: path somehow contained a NUL?>
├── invalid-utf8-4: [<5B>(<28>(]
│ └── <Error: path somehow contained a NUL?>
├── links
│ ├── another: [\n] -> /testcases/file-names/new-line-dir: [\n]/another: [\n]
│ ├── broken -> /testcases/file-names/new-line-dir: [\n]/broken
│ │ └── <No such file or directory (os error 2)>
│ └── subfile -> /testcases/file-names/new-line-dir: [\n]/subfile
├── new-line-dir: [\n]
│ ├── another: [\n]
│ └── subfile
├── new-line: [\n]
├── return: [\r]
├── tab: [\t]
├── utf-8: pâté
└── vertical-tab: [\u{b}]

View File

@ -1,3 +0,0 @@
1_bytes 2_bytes 3_bytes 4_bytes 5_bytes 6_bytes 7_bytes 8_bytes 9_bytes 10_bytes 11_bytes 12_bytes 13_bytes
1_KiB 2_KiB 3_KiB 4_KiB 5_KiB 6_KiB 7_KiB 8_KiB 9_KiB 10_KiB 11_KiB 12_KiB 13_KiB
1_MiB 2_MiB 3_MiB 4_MiB 5_MiB 6_MiB 7_MiB 8_MiB 9_MiB 10_MiB 11_MiB 12_MiB 13_MiB

View File

@ -1,3 +0,0 @@
1_bytes 2_bytes 3_bytes 4_bytes 5_bytes 6_bytes 7_bytes 8_bytes 9_bytes 10_bytes 11_bytes 12_bytes 13_bytes
1_KiB 2_KiB 3_KiB 4_KiB 5_KiB 6_KiB 7_KiB 8_KiB 9_KiB 10_KiB 11_KiB 12_KiB 13_KiB
1_MiB 2_MiB 3_MiB 4_MiB 5_MiB 6_MiB 7_MiB 8_MiB 9_MiB 10_MiB 11_MiB 12_MiB 13_MiB

View File

@ -1,39 +0,0 @@
.rw-r--r-- 1 cassowary  1 Jan 12:34 1_bytes
.rw-r--r-- 1.0k cassowary  1 Jan 12:34 1_KiB
.rw-r--r-- 1.0M cassowary  1 Jan 12:34 1_MiB
.rw-r--r-- 2 cassowary  1 Jan 12:34 2_bytes
.rw-r--r-- 2.0k cassowary  1 Jan 12:34 2_KiB
.rw-r--r-- 2.1M cassowary  1 Jan 12:34 2_MiB
.rw-r--r-- 3 cassowary  1 Jan 12:34 3_bytes
.rw-r--r-- 3.1k cassowary  1 Jan 12:34 3_KiB
.rw-r--r-- 3.1M cassowary  1 Jan 12:34 3_MiB
.rw-r--r-- 4 cassowary  1 Jan 12:34 4_bytes
.rw-r--r-- 4.1k cassowary  1 Jan 12:34 4_KiB
.rw-r--r-- 4.2M cassowary  1 Jan 12:34 4_MiB
.rw-r--r-- 5 cassowary  1 Jan 12:34 5_bytes
.rw-r--r-- 5.1k cassowary  1 Jan 12:34 5_KiB
.rw-r--r-- 5.2M cassowary  1 Jan 12:34 5_MiB
.rw-r--r-- 6 cassowary  1 Jan 12:34 6_bytes
.rw-r--r-- 6.1k cassowary  1 Jan 12:34 6_KiB
.rw-r--r-- 6.3M cassowary  1 Jan 12:34 6_MiB
.rw-r--r-- 7 cassowary  1 Jan 12:34 7_bytes
.rw-r--r-- 7.2k cassowary  1 Jan 12:34 7_KiB
.rw-r--r-- 7.3M cassowary  1 Jan 12:34 7_MiB
.rw-r--r-- 8 cassowary  1 Jan 12:34 8_bytes
.rw-r--r-- 8.2k cassowary  1 Jan 12:34 8_KiB
.rw-r--r-- 8.4M cassowary  1 Jan 12:34 8_MiB
.rw-r--r-- 9 cassowary  1 Jan 12:34 9_bytes
.rw-r--r-- 9.2k cassowary  1 Jan 12:34 9_KiB
.rw-r--r-- 9.4M cassowary  1 Jan 12:34 9_MiB
.rw-r--r-- 10 cassowary  1 Jan 12:34 10_bytes
.rw-r--r-- 10k cassowary  1 Jan 12:34 10_KiB
.rw-r--r-- 10M cassowary  1 Jan 12:34 10_MiB
.rw-r--r-- 11 cassowary  1 Jan 12:34 11_bytes
.rw-r--r-- 11k cassowary  1 Jan 12:34 11_KiB
.rw-r--r-- 11M cassowary  1 Jan 12:34 11_MiB
.rw-r--r-- 12 cassowary  1 Jan 12:34 12_bytes
.rw-r--r-- 12k cassowary  1 Jan 12:34 12_KiB
.rw-r--r-- 12M cassowary  1 Jan 12:34 12_MiB
.rw-r--r-- 13 cassowary  1 Jan 12:34 13_bytes
.rw-r--r-- 13k cassowary  1 Jan 12:34 13_KiB
.rw-r--r-- 13M cassowary  1 Jan 12:34 13_MiB

86
xtests/git-ignore.toml Normal file
View File

@ -0,0 +1,86 @@
# Git-ignoring
[[cmd]]
name = "exa --git-ignore skips Git-ignored files"
shell = "exa --git-ignore /testcases/git2/ignoreds"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/git2_ignoreds_grid_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid', 'git-ignore' ]
[[cmd]]
name = "exa --git-ignore -1 skips Git-ignored files"
shell = "exa --git-ignore -1 /testcases/git2/ignoreds"
stdout = { file = "outputs/git2_ignoreds_lines_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'oneline', 'git-ignore' ]
[[cmd]]
name = "exa --git-ignore -l skips Git-ignored files"
shell = "exa --git-ignore -l /testcases/git2/ignoreds"
stdout = { file = "outputs/git2_ignoreds_long_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git-ignore' ]
[[cmd]]
name = "exa --git-ignore -lG skips Git-ignored files"
shell = "exa --git-ignore -lG /testcases/git2/ignoreds"
environment = { COLUMNS = "150" }
stdout = { file = "outputs/git2_ignoreds_long_grid_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid', 'git-ignore' ]
[[cmd]]
name = "exa --git-ignore -lR skips Git-ignored files"
shell = "exa --git-ignore -lR /testcases/git2/ignoreds"
stdout = { file = "outputs/git2_ignoreds_long_recurse_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'recurse', 'git-ignore' ]
[[cmd]]
name = "exa --git-ignore -lT skips Git-ignored files"
shell = "exa --git-ignore -lT /testcases/git2/ignoreds"
stdout = { file = "outputs/git2_ignoreds_long_tree_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'tree', 'git-ignore' ]
[[cmd]]
name = "exa --git-ignore -T skips Git-ignored files"
shell = "exa --git-ignore -T /testcases/git2/ignoreds"
stdout = { file = "outputs/git2_ignoreds_tree_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'tree', 'git-ignore' ]
# Recursive git-ignoring
[[cmd]]
name = "exa --git-ignore -lR skips Git-ignored files in subfolders"
shell = "exa --git-ignore -lR /testcases/git2"
stdout = { file = "outputs/git2_long_recurse_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'recurse', 'git-ignore' ]
[[cmd]]
name = "exa --git-ignore -lT skips Git-ignored files in subfolders"
shell = "exa --git-ignore -lT /testcases/git2"
stdout = { file = "outputs/git2_long_tree_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'tree', 'git-ignore' ]
[[cmd]]
name = "exa --git-ignore -T skips Git-ignored files in subfolders"
shell = "exa --git-ignore -T /testcases/git2"
stdout = { file = "outputs/git2_tree_gitignore.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'tree', 'git-ignore' ]

183
xtests/git.toml Normal file
View File

@ -0,0 +1,183 @@
# The first Git repo: additions and modifications
[[cmd]]
name = "exa --git -l shows a Git status column"
shell = "exa --git -l /testcases/git"
stdout = { file = "outputs/git1_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -lR shows a Git status column in every table"
shell = "exa --git -lR /testcases/git"
stdout = { file = "outputs/git1_long_recurse.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -lT shows a Git status column alongside the tree"
shell = "exa --git -lT /testcases/git"
stdout = { file = "outputs/git1_long_tree.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l with a directory argument shows the combined Git status column"
shell = "exa --git -l /testcases/git/moves/thither"
stdout = { file = "outputs/git1_long_moves.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l shows a Git status column containing new files"
shell = "exa --git -l /testcases/git/additions"
stdout = { file = "outputs/git1_long_additions.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l shows a Git status column containing modified files"
shell = "exa --git -l /testcases/git/edits"
stdout = { file = "outputs/git1_long_edits.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l shows a Git status column containing multiple statuses"
shell = "exa --git -l /testcases/git/{additions,edits}"
stdout = { file = "outputs/git1_long_multiple.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -lGd with file arguments shows a Git status column"
shell = "exa --git -lGd /testcases/git/**/* /testcases"
environment = { COLUMNS = "150" }
stdout = { file = "outputs/git1_paths_long_grid.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'grid', 'git', 'list-dirs' ]
# The second Git repo: nested repositories and file ignoring
[[cmd]]
name = "exa --git -l shows a Git status column with ignored statuses"
shell = "exa --git -l /testcases/git2"
stdout = { file = "outputs/git2_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -lR shows a Git status column in every table, handling ignored files and nested repositories"
shell = "exa --git -lR /testcases/git2"
stdout = { file = "outputs/git2_long_recurse.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -lT shows a Git status column alongside the tree, handling ignored files and nested repositories"
shell = "exa --git -lT /testcases/git2"
stdout = { file = "outputs/git2_long_tree.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l with a directory argument shows ignored flags inside a directory"
shell = "exa --git -l /testcases/git2/ignoreds"
stdout = { file = "outputs/git2_long_ignorednested.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l with an ignored directory argument does not flag the contents as ignored"
shell = "exa --git -l /testcases/git2/target"
stdout = { file = "outputs/git2_long_ignoreddir.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l with a nested repository argument uses the sub-repository rules"
shell = "exa --git -l /testcases/git2/deeply/nested/repository"
stdout = { file = "outputs/git2_long_nested.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l with multiple directory arguments still gets the flags correct"
shell = "exa --git -l /testcases/git2/{deeply,ignoreds,target}"
stdout = { file = "outputs/git2_long_multiple.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
# The third Git repo: broken symlinks
[[cmd]]
name = "exa --git -l handles broken symlinks in Git repositories"
shell = "exa --git -l /testcases/git3"
stdout = { file = "outputs/git3_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
# Both repositories 1 and 2 at once
[[cmd]]
name = "exa --git -l shows a Git status column for multiple repositories"
shell = "exa --git -l /testcases/git /testcases/git2"
stdout = { file = "outputs/git1+2_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l shows a Git status column for multiple repositories across multiple directories"
shell = "exa --git -l /testcases/{git/additions,git2/deeply,git/edits,git2/deeply/nested}"
stdout = { file = "outputs/git1+2_long_directories.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l shows a Git status column for multiple repositories across multiple directories"
shell = "exa --git -l /testcases/{git2/deeply/nested/directory,git/edits,git2/target,git2/deeply,git}"
stdout = { file = "outputs/git1+2_long_nested.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
# No repository present
[[cmd]]
name = "exa --git -l shows an empty status for no repository"
shell = "exa --git -l /testcases/files"
stdout = { file = "outputs/files_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -lG shows an empty status for no repository"
shell = "exa --git -lG /testcases/files"
environment = { COLUMNS = "40" }
stdout = { file = "outputs/files_long_grid_1col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid', 'git' ]

View File

@ -1,3 +0,0 @@
drwxrwxr-x - cassowary  1 Jan 12:34 additions
drwxrwxr-x - cassowary  1 Jan 12:34 edits
drwxrwxr-x - cassowary  1 Jan 12:34 moves

View File

@ -1,3 +0,0 @@
drwxrwxr-x - cassowary  1 Jan 12:34 deeply
drwxrwxr-x - cassowary  1 Jan 12:34 ignoreds
drwxrwxr-x - cassowary  1 Jan 12:34 target

View File

@ -0,0 +1,78 @@
# listing directory tests
[[cmd]]
name = "COLUMNS=40 exa -lG produces a grid with details of 1 column"
shell = "exa -lG /testcases/files"
environment = { COLUMNS = "40" }
stdout = { file = "outputs/files_long_grid_1col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
[[cmd]]
name = "COLUMNS=80 exa -lG produces a grid with details of 1 column"
shell = "exa -lG /testcases/files"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/files_long_grid_1col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
[[cmd]]
name = "COLUMNS=120 exa -lG produces a grid with details of 2 columns"
shell = "exa -lG /testcases/files"
environment = { COLUMNS = "120" }
stdout = { file = "outputs/files_long_grid_2col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
[[cmd]]
name = "COLUMNS=160 exa -lG produces a grid with details of 3 columns"
shell = "exa -lG /testcases/files"
environment = { COLUMNS = "160" }
stdout = { file = "outputs/files_long_grid_3col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
[[cmd]]
name = "COLUMNS=200 exa -lG produces a grid with details of 4 columns"
shell = "exa -lG /testcases/files"
environment = { COLUMNS = "200" }
stdout = { file = "outputs/files_long_grid_4col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
# listing files tests
# (these rely on bashs glob sort order)
# (some of the output files also have trailing whitespace)
[[cmd]]
name = "COLUMNS=100 exa -lG with file arguments produces a grid with details of 1 column, with full paths"
shell = "exa -lG /testcases/files/*"
environment = { COLUMNS = "100" }
stdout = { file = "outputs/files_paths_long_grid_1col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
[[cmd]]
name = "COLUMNS=150 exa -lG with file arguments produces a grid with details of 2 columns, with full paths"
shell = "exa -lG /testcases/files/*"
environment = { COLUMNS = "150" }
stdout = { file = "outputs/files_paths_long_grid_2col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
[[cmd]]
name = "COLUMNS=200 exa -lG with file arguments produces a grid with details of 3 columns, with full paths"
shell = "exa -lG /testcases/files/*"
environment = { COLUMNS = "200" }
stdout = { file = "outputs/files_paths_long_grid_3col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]

133
xtests/grid-view.toml Normal file
View File

@ -0,0 +1,133 @@
# file name tests
[[cmd]]
name = "exa produces a grid of file names"
shell = "exa /testcases/file-names"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/names_grid.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]
[[cmd]]
name = "exa -x produces an across grid of file names"
shell = "exa -x /testcases/file-names"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/names_grid_across.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid', 'across' ]
[[cmd]]
name = "exa -d displays, ., .., and / correctly"
shell = "exa -d . .. /"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/dirs_grid.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid', 'list-dirs' ]
# recurse tests
[[cmd]]
name = "exa -R produces several grids of file names"
shell = "exa -R /testcases/file-names"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/names_grid_recurse.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid', 'recurse' ]
# symlink tests
[[cmd]]
name = "exa highlights symlinks and broken symlinks"
shell = "exa /testcases/links"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/links_grid.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]
# columns and width tests
[[cmd]]
name = "COLUMNS=40 exa produces a grid of 4 columns"
shell = "exa /testcases/files"
environment = { COLUMNS = "40" }
stdout = { file = "outputs/files_grid_4col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]
[[cmd]]
name = "COLUMNS=80 exa produces a grid of 8 columns"
shell = "exa /testcases/files"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/files_grid_8col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]
[[cmd]]
name = "COLUMNS=120 exa produces a grid of 13 columns"
shell = "exa /testcases/files"
environment = { COLUMNS = "120" }
stdout = { file = "outputs/files_grid_13col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]
[[cmd]]
name = "COLUMNS=160 exa produces a grid of 13 columns"
shell = "exa /testcases/files"
environment = { COLUMNS = "160" }
stdout = { file = "outputs/files_grid_13col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]
[[cmd]]
name = "COLUMNS=200 exa produces a grid of 20 columns"
shell = "exa /testcases/files"
environment = { COLUMNS = "200" }
stdout = { file = "outputs/files_grid_20col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]
# columns and width tests with files
# (these rely on bashs glob sort order)
# (some of the output files also have trailing whitespace)
[[cmd]]
name = "COLUMNS=100 exa with file arguments produces a grid of 3 columns, with full paths"
shell = "exa /testcases/files/*"
environment = { COLUMNS = "100" }
stdout = { file = "outputs/files_paths_grid_3col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]
[[cmd]]
name = "COLUMNS=150 exa with file arguments produces a grid of 5 columns, with full paths"
shell = "exa /testcases/files/*"
environment = { COLUMNS = "150" }
stdout = { file = "outputs/files_paths_grid_5col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]
[[cmd]]
name = "COLUMNS=200 exa with file arguments produces a grid of 7 columns, with full paths"
shell = "exa /testcases/files/*"
environment = { COLUMNS = "200" }
stdout = { file = "outputs/files_paths_grid_7col.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'grid' ]

7
xtests/help.toml Normal file
View File

@ -0,0 +1,7 @@
[[cmd]]
name = "exa --help produces the correct help text"
shell = "exa --help"
stdout = { file = "outputs/help.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'help ']

15
xtests/ignore-glob.toml Normal file
View File

@ -0,0 +1,15 @@
[[cmd]]
name = "exa -1 -I ignores based on a glob"
shell = "exa -1 -I '*.OGG' /testcases/file-names-exts/music.*"
stdout = { string = "music.mp3" }
stderr = { empty = true }
status = 0
tags = [ 'oneline', 'ignore' ]
[[cmd]]
name = "exa -1 -I ignores based on multiple globs"
shell = "exa -1 -I '*.OGG|*.mp3' /testcases/file-names-exts/music.*"
stdout = { empty = true }
stderr = { empty = true }
status = 0
tags = [ 'oneline', 'ignore' ]

View File

@ -1 +0,0 @@
/testcases/file-names-exts/music.mp3

77
xtests/input-options.toml Normal file
View File

@ -0,0 +1,77 @@
[[cmd]]
name = "exa can handle invalid UTF-8 in command-line arguments"
shell = "exa /testcases/file-names/*"
stdout = { empty = false }
stderr = { empty = true }
status = 0
tags = [ 'options' ]
[[cmd]]
name = "exa displays an error for an unknown short option"
shell = "exa -4"
stdout = { empty = true }
stderr = { string = "Unknown argument -4" }
status = 3
tags = [ 'options' ]
[[cmd]]
name = "exa displays an error for an unknown long option"
shell = "exa --ternary"
stdout = { empty = true }
stderr = { string = "Unknown argument --ternary" }
status = 3
tags = [ 'options' ]
[[cmd]]
name = "exa displays an error for an option missing a parameter"
shell = "exa --time"
stdout = { empty = true }
stderr = { string = "Flag --time needs a value (choices: modified, changed, accessed, created)" }
status = 3
tags = [ 'options' ]
[[cmd]]
name = "exa displays an error for an option that cannot take a parameter has one"
shell = "exa --long=time"
stdout = { empty = true }
stderr = { string = "Flag --long cannot take a value" }
status = 3
tags = [ 'options' ]
[[cmd]]
name = "exa displays an error for option that takes the wrong parameter"
shell = "exa -l --time-style=24"
stdout = { empty = true }
stderr = { string = "Option --time-style has no \"24\" setting (choices: default, long-iso, full-iso, iso)" }
status = 3
tags = [ 'options' ]
# strict mode settings
[[cmd]]
name = "exa displays a warning for a useless option in strict mode"
shell = "exa --binary"
environment = { EXA_STRICT = "1" }
stdout = { empty = true }
stderr = { string = "Option --binary (-b) is useless without option --long (-l)" }
status = 3
tags = [ 'options' ]
[[cmd]]
name = "exa displays a warning for a short option given twice in strict mode"
shell = "exa -ll"
environment = { EXA_STRICT = "1" }
stdout = { empty = true }
stderr = { string = "Flag -l was given twice" }
status = 3
tags = [ 'options' ]
[[cmd]]
name = "exa displays a warning for a short option also given as long in strict mode"
shell = "exa -l --long"
environment = { EXA_STRICT = "1" }
stdout = { empty = true }
stderr = { string = "Flag -l conflicts with flag --long" }
status = 3
tags = [ 'options' ]

36
xtests/lines-view.toml Normal file
View File

@ -0,0 +1,36 @@
# file name tests
[[cmd]]
name = "exa -1 displays file names, one on each line"
shell = "exa -1 /testcases/file-names"
stdout = { file = "outputs/names_lines.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'oneline' ]
[[cmd]]
name = "exa -1d displays, ., .., and / correctly"
shell = "exa -1d . .. /"
stdout = { file = "outputs/dirs_oneline.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'oneline', 'list-dirs' ]
# symlinks tests
[[cmd]]
name = "exa -1 lists the destination of symlinks"
shell = "exa -1 /testcases/links"
stdout = { file = "outputs/links_lines.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'oneline' ]
[[cmd]]
name = "exa -1d with file arguments lists the destination of symlinks"
shell = "exa -1d /testcases/links/*"
stdout = { file = "outputs/links_paths_lines.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'oneline', 'list-dirs' ]

View File

@ -1,4 +1,4 @@
Permissions Size User Date Accessed Name
.rw-rw-r-- 0 cassowary  3 Mar 2003 plum
.rw-rw-r-- 0 cassowary 15 Jun 2006 pear
.rw-rw-r-- 0 cassowary 22 Dec 2009 peach
.rw-rw-r-- 0 cassowary 15 Jun 2006 pear
.rw-rw-r-- 0 cassowary  3 Mar 2003 plum

View File

@ -0,0 +1,4 @@
Permissions Size User Date Created Name
.rw-rw-r-- 0 cassowary 17 Oct 14:27 peach
.rw-rw-r-- 0 cassowary 17 Oct 14:27 pear
.rw-rw-r-- 0 cassowary 17 Oct 14:27 plum

View File

@ -1,4 +1,4 @@
Permissions Size User Date Modified Name
.rw-rw-r-- 0 cassowary 22 Dec 2009 plum
.rw-rw-r-- 0 cassowary 15 Jun 2006 peach
.rw-rw-r-- 0 cassowary  3 Mar 2003 pear
.rw-rw-r-- 0 cassowary 22 Dec 2009 plum

View File

@ -0,0 +1 @@
. .. /

View File

@ -0,0 +1,2 @@
.rw-rw-r-- 0 vagrant  1 Jan 2300 beyond-the-future
.rw-rw-r-- 0 vagrant  1 Jan 1700 the-distant-past

View File

@ -0,0 +1,39 @@
.rw-r--r-- 1 cassowary  1 Jan 12:34 1_bytes
.rw-r--r-- 1.0Ki cassowary  1 Jan 12:34 1_KiB
.rw-r--r-- 1.0Mi cassowary  1 Jan 12:34 1_MiB
.rw-r--r-- 2 cassowary  1 Jan 12:34 2_bytes
.rw-r--r-- 2.0Ki cassowary  1 Jan 12:34 2_KiB
.rw-r--r-- 2.0Mi cassowary  1 Jan 12:34 2_MiB
.rw-r--r-- 3 cassowary  1 Jan 12:34 3_bytes
.rw-r--r-- 3.0Ki cassowary  1 Jan 12:34 3_KiB
.rw-r--r-- 3.0Mi cassowary  1 Jan 12:34 3_MiB
.rw-r--r-- 4 cassowary  1 Jan 12:34 4_bytes
.rw-r--r-- 4.0Ki cassowary  1 Jan 12:34 4_KiB
.rw-r--r-- 4.0Mi cassowary  1 Jan 12:34 4_MiB
.rw-r--r-- 5 cassowary  1 Jan 12:34 5_bytes
.rw-r--r-- 5.0Ki cassowary  1 Jan 12:34 5_KiB
.rw-r--r-- 5.0Mi cassowary  1 Jan 12:34 5_MiB
.rw-r--r-- 6 cassowary  1 Jan 12:34 6_bytes
.rw-r--r-- 6.0Ki cassowary  1 Jan 12:34 6_KiB
.rw-r--r-- 6.0Mi cassowary  1 Jan 12:34 6_MiB
.rw-r--r-- 7 cassowary  1 Jan 12:34 7_bytes
.rw-r--r-- 7.0Ki cassowary  1 Jan 12:34 7_KiB
.rw-r--r-- 7.0Mi cassowary  1 Jan 12:34 7_MiB
.rw-r--r-- 8 cassowary  1 Jan 12:34 8_bytes
.rw-r--r-- 8.0Ki cassowary  1 Jan 12:34 8_KiB
.rw-r--r-- 8.0Mi cassowary  1 Jan 12:34 8_MiB
.rw-r--r-- 9 cassowary  1 Jan 12:34 9_bytes
.rw-r--r-- 9.0Ki cassowary  1 Jan 12:34 9_KiB
.rw-r--r-- 9.0Mi cassowary  1 Jan 12:34 9_MiB
.rw-r--r-- 10 cassowary  1 Jan 12:34 10_bytes
.rw-r--r-- 10Ki cassowary  1 Jan 12:34 10_KiB
.rw-r--r-- 10Mi cassowary  1 Jan 12:34 10_MiB
.rw-r--r-- 11 cassowary  1 Jan 12:34 11_bytes
.rw-r--r-- 11Ki cassowary  1 Jan 12:34 11_KiB
.rw-r--r-- 11Mi cassowary  1 Jan 12:34 11_MiB
.rw-r--r-- 12 cassowary  1 Jan 12:34 12_bytes
.rw-r--r-- 12Ki cassowary  1 Jan 12:34 12_KiB
.rw-r--r-- 12Mi cassowary  1 Jan 12:34 12_MiB
.rw-r--r-- 13 cassowary  1 Jan 12:34 13_bytes
.rw-r--r-- 13Ki cassowary  1 Jan 12:34 13_KiB
.rw-r--r-- 13Mi cassowary  1 Jan 12:34 13_MiB

View File

@ -0,0 +1,39 @@
.rw-r--r-- 1 cassowary  1 Jan 12:34 1_bytes
.rw-r--r-- 1,024 cassowary  1 Jan 12:34 1_KiB
.rw-r--r-- 1,048,576 cassowary  1 Jan 12:34 1_MiB
.rw-r--r-- 2 cassowary  1 Jan 12:34 2_bytes
.rw-r--r-- 2,048 cassowary  1 Jan 12:34 2_KiB
.rw-r--r-- 2,097,152 cassowary  1 Jan 12:34 2_MiB
.rw-r--r-- 3 cassowary  1 Jan 12:34 3_bytes
.rw-r--r-- 3,072 cassowary  1 Jan 12:34 3_KiB
.rw-r--r-- 3,145,728 cassowary  1 Jan 12:34 3_MiB
.rw-r--r-- 4 cassowary  1 Jan 12:34 4_bytes
.rw-r--r-- 4,096 cassowary  1 Jan 12:34 4_KiB
.rw-r--r-- 4,194,304 cassowary  1 Jan 12:34 4_MiB
.rw-r--r-- 5 cassowary  1 Jan 12:34 5_bytes
.rw-r--r-- 5,120 cassowary  1 Jan 12:34 5_KiB
.rw-r--r-- 5,242,880 cassowary  1 Jan 12:34 5_MiB
.rw-r--r-- 6 cassowary  1 Jan 12:34 6_bytes
.rw-r--r-- 6,144 cassowary  1 Jan 12:34 6_KiB
.rw-r--r-- 6,291,456 cassowary  1 Jan 12:34 6_MiB
.rw-r--r-- 7 cassowary  1 Jan 12:34 7_bytes
.rw-r--r-- 7,168 cassowary  1 Jan 12:34 7_KiB
.rw-r--r-- 7,340,032 cassowary  1 Jan 12:34 7_MiB
.rw-r--r-- 8 cassowary  1 Jan 12:34 8_bytes
.rw-r--r-- 8,192 cassowary  1 Jan 12:34 8_KiB
.rw-r--r-- 8,388,608 cassowary  1 Jan 12:34 8_MiB
.rw-r--r-- 9 cassowary  1 Jan 12:34 9_bytes
.rw-r--r-- 9,216 cassowary  1 Jan 12:34 9_KiB
.rw-r--r-- 9,437,184 cassowary  1 Jan 12:34 9_MiB
.rw-r--r-- 10 cassowary  1 Jan 12:34 10_bytes
.rw-r--r-- 10,240 cassowary  1 Jan 12:34 10_KiB
.rw-r--r-- 10,485,760 cassowary  1 Jan 12:34 10_MiB
.rw-r--r-- 11 cassowary  1 Jan 12:34 11_bytes
.rw-r--r-- 11,264 cassowary  1 Jan 12:34 11_KiB
.rw-r--r-- 11,534,336 cassowary  1 Jan 12:34 11_MiB
.rw-r--r-- 12 cassowary  1 Jan 12:34 12_bytes
.rw-r--r-- 12,288 cassowary  1 Jan 12:34 12_KiB
.rw-r--r-- 12,582,912 cassowary  1 Jan 12:34 12_MiB
.rw-r--r-- 13 cassowary  1 Jan 12:34 13_bytes
.rw-r--r-- 13,312 cassowary  1 Jan 12:34 13_KiB
.rw-r--r-- 13,631,488 cassowary  1 Jan 12:34 13_MiB

Some files were not shown because too many files have changed in this diff Show More