Files
sausage/userland/brush/source/brush-shell/tests/cases/compat/path_search.yaml
T
2026-11-11 22:04:16 +00:00

292 lines
8.5 KiB
YAML

name: "PATH search"
#
# An empty entry in PATH names the working directory, so a command found through one is
# reported with a leading "./". brush finds the command but reports the bare name; the
# `known_failure` cases below cover each surface that exposes the difference. They share
# one root cause in the path search, so they should be retired together.
#
cases:
- name: "empty PATH entry is reported as the working directory"
known_failure: true # TODO(path): an empty PATH entry should resolve as "."
stdin: |
printf '#!/bin/sh\necho ran\n' > prog
chmod +x prog
PATH=":$PATH"
echo "[type]"
type prog; echo "rc=$?"
echo "[type -p]"
type -p prog; echo "rc=$?"
echo "[type -P]"
type -P prog; echo "rc=$?"
echo "[type -a]"
type -a prog; echo "rc=$?"
echo "[command -v]"
command -v prog; echo "rc=$?"
- name: "empty PATH entry is reported the same wherever it appears"
known_failure: true # TODO(path): an empty PATH entry should resolve as "."
stdin: |
printf '#!/bin/sh\necho ran\n' > prog
chmod +x prog
original=$PATH
# Each of these keeps the rest of PATH reachable, so only the empty entry can
# account for finding `prog`, which exists solely in the working directory.
echo "[leading]"
PATH=":$original"; hash -r
command -v prog; echo "rc=$?"
echo "[trailing]"
PATH="$original:"; hash -r
command -v prog; echo "rc=$?"
echo "[middle]"
PATH="/nonexistent::$original"; hash -r
command -v prog; echo "rc=$?"
- name: "empty PATH entry is hashed as the working directory"
known_failure: true # TODO(path): an empty PATH entry should resolve as "."
stdin: |
printf '#!/bin/sh\necho ran\n' > prog
chmod +x prog
PATH=":$PATH"
hash -r
hash prog; echo "rc=$?"
hash -t prog; echo "rc=$?"
- name: "empty PATH entry is passed to the command as the working directory"
known_failure: true # TODO(path): an empty PATH entry should resolve as "."
stdin: |
# A copy of env, found through the empty entry before the real one, reports the _
# it's started with: the path the shell ran it by. (It keeps env's name, which a
# multi-call binary such as NixOS's coreutils goes by.)
cp "$(command -v env)" env
PATH=":$PATH"
env | grep '^_='
- name: "relative PATH entry is relative to the working directory"
known_failure: true # TODO(path): a relative PATH entry is searched relative to the directory brush started in, not the shell's working directory
test_files:
- path: "sub/bin/prog"
executable: true
contents: |
#!/bin/sh
echo "ran prog"
stdin: |
cd sub
PATH=bin
type prog
type -a prog
command -v prog
hash prog; echo "hash: $?"
prog; echo "command: $?"
(exec prog); echo "exec in a subshell: $?"
exec prog
- name: "script run by a relative path sees that path as its $0"
known_failure: true # TODO(path): a relative PATH entry is searched relative to the directory brush started in, not the shell's working directory
test_files:
- path: "sub/prog"
executable: true
contents: |
#!/bin/sh
echo "0=$0"
- path: "sub/bin/prog"
executable: true
contents: |
#!/bin/sh
echo "0=$0"
stdin: |
cd sub
./prog
PATH=bin
prog
- name: "empty PATH entry runs the program in the working directory"
known_failure: true # TODO(path): an empty PATH entry should resolve as "."
test_files:
- path: "sub/id"
executable: true
contents: |
#!/bin/sh
echo "id in the working directory"
- path: "sub/only-here"
executable: true
contents: |
#!/bin/sh
echo "only here"
stdin: |
# Unexported, so that the program can't be found again through the PATH a
# process is given, only as the shell found it.
cd sub
export -n PATH
PATH=":$PATH"
id
only-here
type only-here
- name: "command found through an empty PATH entry is searched for again after cd"
known_failure: true # TODO(hash): a command hashed as found in the working directory isn't searched for again after cd
test_files:
- path: "a/prog"
executable: true
contents: |
#!/bin/sh
echo "prog in a"
- path: "b/.keep"
- path: "fallback/prog"
executable: true
contents: |
#!/bin/sh
echo "prog in fallback"
stdin: |
for first in "" "."; do
export PATH="${first}:${PWD}/fallback:${PATH}"
cd a
prog
hash -t prog; type prog
cd ../b
prog; echo "status: $?"
cd ../a
prog
hash -t prog; type prog
cd ..
export PATH="${PATH#"${first}:${PWD}/fallback:"}"
done
- name: "PATH entry for the working directory written another way"
known_failure: true # TODO(path): a PATH entry such as `./` or `../dir` isn't taken to be the working directory
test_files:
- path: "a/prog"
executable: true
contents: |
#!/bin/sh
echo "prog in a"
- path: "b/.keep"
- path: "fallback/prog"
executable: true
contents: |
#!/bin/sh
echo "prog in fallback"
stdin: |
fallback="${PWD}/fallback"
for first in ./ ./. .// ../b; do
PATH="${first}:${fallback}"
hash -r
cd b
prog
cd ../a
prog
hash -t prog
cd ..
done
- name: "command found through a PATH entry is run by the path that entry gives it"
test_files:
- path: "bin/prog"
executable: true
contents: |
#!/bin/sh
echo "0=$0"
stdin: |
PATH=./bin//
prog
PATH=.//bin
hash -r
prog
- name: "PATH entry starting with a dot is the working directory only if it's the same"
known_failure: true # TODO(path): a PATH entry that's the working directory under another name isn't taken to be it
test_files:
- path: "a/prog"
executable: true
contents: |
#!/bin/sh
echo "prog in a"
- path: "b/sub/.keep"
- path: "b/.hidden/.keep"
- path: "fallback/prog"
executable: true
contents: |
#!/bin/sh
echo "prog in fallback"
stdin: |
fallback="${PWD}/fallback"
ln -s . b/self
for first in ./sub .hidden .nosuch ./self; do
echo "[${first}]"
PATH="${first}:${fallback}"
hash -r
cd b
prog
cd ../a
prog
cd ..
done
- name: "command hashed with hash -p is kept with an empty PATH entry"
test_files:
- path: "prog"
executable: true
contents: |
#!/bin/sh
echo "prog in the working directory"
stdin: |
true_path=$(type -P true)
PATH=":$PATH"
hash -p "${true_path}" prog
prog; echo "status: $?"
- name: "with PATH unset, a command in the working directory is run by its name"
known_failure: true # TODO(path): with PATH unset, a command in the working directory is run as ./name, not by its bare name
test_files:
- path: "prog"
executable: true
contents: |
#!/bin/sh
echo "0=$0"
stdin: |
unset PATH
prog
- name: "relative PATH entry is hashed as bash hashes it"
known_failure: true # TODO(hash): bash hashes a command found through a relative PATH entry as ./entry/name
test_files:
- path: "sub/bin/prog"
executable: true
contents: |
#!/bin/sh
echo "ran prog"
stdin: |
cd sub
PATH=bin
prog
hash -t prog
#
# These two surfaces already agree with the oracle; they guard the parts of the
# behavior that work, so that a fix for the cases above doesn't regress them.
#
- name: "a command found through an empty PATH entry is runnable"
stdin: |
printf '#!/bin/sh\necho ran\n' > prog
chmod +x prog
PATH=":$PATH"
prog; echo "rc=$?"
- name: "command -V absolutizes a command found through an empty PATH entry"
stdin: |
# Normalize away the temporary directory the test runs in.
scrub() { sed -E "s|$PWD|<TMPDIR>|g"; }
printf '#!/bin/sh\necho ran\n' > prog
chmod +x prog
PATH=":$PATH"
command -V prog | scrub; echo "rc=${PIPESTATUS[0]}"