fish-shell/tests/checks/path.fish
Johannes Altmanninger 8bf8b10f68 Extended & human-friendly keys
See the changelog additions for user-visible changes.

Since we enable/disable terminal protocols whenever we pass terminal ownership,
tests can no longer run in parallel on the same terminal.

For the same reason, readline shortcuts in the gdb REPL will not work anymore.
As a remedy, use gdbserver, or lobby for CSI u support in libreadline.

Add sleep to some tests, otherwise they fall (both in CI and locally).

There are two weird failures on FreeBSD remaining, disable them for now
https://github.com/fish-shell/fish-shell/pull/10359/checks?check_run_id=23330096362

Design and implementation borrows heavily from Kakoune.

In future, we should try to implement more of the kitty progressive
enhancements.

Closes #10359
2024-04-02 14:35:16 +02:00

322 lines
7.2 KiB
Fish

#RUN: %fish %s | %filter-ctrlseqs
# The "path" builtin for dealing with paths
# Extension - for figuring out the file extension of a given path.
path extension /
or echo None
# CHECK:
# CHECK: None
# No extension
path extension /.
or echo Filename is just a dot, no extension
# CHECK:
# CHECK: Filename is just a dot, no extension
# No extension - ".foo" is the filename
path extension /.foo
or echo None again
# CHECK:
# CHECK: None again
path extension /foo
or echo None once more
# CHECK:
# CHECK: None once more
path extension /foo.txt
and echo Success
# CHECK: .txt
# CHECK: Success
path extension /foo.txt/bar
or echo Not even here
# CHECK:
# CHECK: Not even here
path extension . ..
or echo No extension
# CHECK:
# CHECK: No extension
path extension ./foo.mp4
# CHECK: .mp4
path extension ../banana
# CHECK:
# nothing, status 1
echo $status
# CHECK: 1
path extension ~/.config
# CHECK:
# nothing, status 1
echo $status
# CHECK: 1
path extension ~/.config.d
# CHECK: .d
path extension ~/.config.
echo $status
# status 0
# CHECK: .
# CHECK: 0
path change-extension '' ./foo.mp4
# CHECK: ./foo
path change-extension wmv ./foo.mp4
# CHECK: ./foo.wmv
path change-extension .wmv ./foo.mp4
# CHECK: ./foo.wmv
path change-extension '' ../banana
# CHECK: ../banana
# still status 0, because there was an argument
echo $status
# CHECK: 0
path change-extension '' ~/.config
# CHECK: {{.*}}/.config
echo $status
# CHECK: 0
path basename ./foo.mp4
# CHECK: foo.mp4
path basename ../banana
# CHECK: banana
path basename /usr/bin/
# CHECK: bin
path dirname ./foo.mp4
# CHECK: .
path basename ../banana
# CHECK: banana
path basename /usr/bin/
# CHECK: bin
cd $TMPDIR
mkdir -p bin
touch bin/{bash,bssh,chsh,dash,fish,slsh,ssh,zsh}
ln -s $TMPDIR/bin/bash bin/sh
chmod +x bin/*
# We need files from here on
path filter bin argagagji
# The (hopefully) nonexistent argagagji is filtered implicitly:
# CHECK: bin
# With --invert, the existing bin is filtered
path filter --invert bin argagagji
# CHECK: argagagji
# With --invert and a type, bin fails the type,
# and argagagji doesn't exist, so both are printed.
path filter -vf bin argagagji
# CHECK: bin
# CHECK: argagagji
path filter --type file bin bin/fish
# Only fish is a file
# CHECK: bin/fish
chmod 500 bin/fish
path filter --type file,dir --perm exec,write bin/fish .
# fish is a file, which passes, and executable, which passes,
# but not writable, which fails.
#
# . is a directory and both writable and executable, typically.
# So it passes.
# CHECK: .
mkdir -p sbin
touch sbin/setuid-exe sbin/setgid-exe
chmod u+s,a+x sbin/setuid-exe
path filter --perm suid sbin/*
# CHECK: sbin/setuid-exe
# On at least FreeBSD on our CI this fails with "permission denied".
# So we can't test it, and we fake the output instead.
if chmod g+s,a+x sbin/setgid-exe 2>/dev/null
path filter --perm sgid sbin/*
else
echo sbin/setgid-exe
end
# CHECK: sbin/setgid-exe
mkdir stuff
touch stuff/{read,write,exec,readwrite,readexec,writeexec,all,none}
chmod 400 stuff/read
chmod 200 stuff/write
chmod 100 stuff/exec
chmod 600 stuff/readwrite
chmod 500 stuff/readexec
chmod 300 stuff/writeexec
chmod 700 stuff/all
chmod 000 stuff/none
# Validate that globs are sorted.
test (path filter stuff/* | path sort | string join ",") = (path filter stuff/* | string join ",")
path filter --perm read stuff/*
# CHECK: stuff/all
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
path filter -r stuff/*
# CHECK: stuff/all
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
path filter --perm write stuff/*
# CHECK: stuff/all
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
path filter -w stuff/*
# CHECK: stuff/all
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
path filter --perm exec stuff/*
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/readexec
# CHECK: stuff/writeexec
path filter -x stuff/*
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/readexec
# CHECK: stuff/writeexec
path filter --perm read,write stuff/*
# CHECK: stuff/all
# CHECK: stuff/readwrite
path filter --perm read,exec stuff/*
# CHECK: stuff/all
# CHECK: stuff/readexec
path filter --perm write,exec stuff/*
# CHECK: stuff/all
# CHECK: stuff/writeexec
path filter --perm read,write,exec stuff/*
# CHECK: stuff/all
path filter stuff/*
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/none
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
path normalize /usr/bin//../../etc/fish
# The "//" is squashed and the ".." components neutralize the components before
# CHECK: /etc/fish
path normalize /bin//bash
# The "//" is squashed, but /bin isn't resolved even if your system links it to /usr/bin.
# CHECK: /bin/bash
# Paths with "-" get a "./":
path normalize -- -/foo -foo/foo
# CHECK: ./-/foo
# CHECK: ./-foo/foo
path normalize -- ../-foo
# CHECK: ../-foo
# This goes for filter as well
touch -- -foo
path filter -f -- -foo
# CHECK: ./-foo
# We need to remove the rest of the path because we have no idea what its value looks like.
path resolve bin//sh | string match -r -- 'bin/bash$'
# The "//" is squashed, and the symlink is resolved.
# sh here is bash
# CHECK: bin/bash
# "../" cancels out even files.
path resolve bin//sh/../ | string match -r -- 'bin$'
# CHECK: bin
# `path resolve` with nonexistent paths
set -l path (path resolve foo/bar)
string match -rq "^"(pwd -P | string escape --style=regex)'/' -- $path
and echo It matches pwd!
or echo pwd is \'$PWD\' resolved path is \'$path\'
# CHECK: It matches pwd!
string replace -r "^"(pwd -P | string escape --style=regex)'/' "" -- $path
# CHECK: foo/bar
path resolve /banana//terracota/terracota/booooo/../pie
# CHECK: /banana/terracota/terracota/pie
path sort --key=basename {def,abc}/{456,123,789,abc,def,0} | path sort --key=dirname -r
# CHECK: def/0
# CHECK: def/123
# CHECK: def/456
# CHECK: def/789
# CHECK: def/abc
# CHECK: def/def
# CHECK: abc/0
# CHECK: abc/123
# CHECK: abc/456
# CHECK: abc/789
# CHECK: abc/abc
# CHECK: abc/def
path sort --unique --key=basename {def,abc}/{456,123,789} def/{abc,def,0} abc/{foo,bar,baz}
# CHECK: def/0
# CHECK: def/123
# CHECK: def/456
# CHECK: def/789
# CHECK: def/abc
# CHECK: abc/bar
# CHECK: abc/baz
# CHECK: def/def
# CHECK: abc/foo
# Symlink loop.
# It goes brrr.
ln -s target link
ln -s link target
test (path resolve target) = (pwd -P)/target
and echo target resolves to target
# CHECK: target resolves to target
test (path resolve link) = (pwd -P)/link
and echo link resolves to link
# CHECK: link resolves to link
# path mtime
# These tests deal with *time*, so we have to account
# for slow systems (like CI).
# So we should only test with a lot of slack.
echo bananana >> foo
test (math abs (date +%s) - (path mtime foo)) -lt 20
or echo MTIME IS BOGUS
sleep 2
set -l mtime (path mtime --relative foo)
test $mtime -ge 1
or echo mtime is too small
test $mtime -lt 20
or echo mtime is too large
touch -m -t 197001020000 epoch
set -l epochtime (path mtime epoch)
# Allow for timezone shenanigans
test $epochtime -gt 0 -a $epochtime -lt 180000
or echo Oops not mtime
path basename -Z foo bar baz | path sort
# CHECK: bar
# CHECK: baz
# CHECK: foo
path basename --null-out bar baz | string escape
# CHECK: bar\x00baz\x00