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

227 lines
7.1 KiB
YAML

name: "Builtins: hash"
cases:
- name: "Non-existent program"
ignore_stderr: true
stdin: |
hash non-existent-program
echo "Result: $?"
- name: "Re-hash non-existent program"
ignore_stderr: true
stdin: |
hash -p /some/path non-existent-program
hash -t non-existent-program && echo "1. Result: $?"
hash non-existent-program && echo "2. Result: $?"
hash -t non-existent-program && echo "3. Result: $?"
- name: "Existent program"
stdin: |
hash ls
echo "Result: $?"
- name: "Display not-yet-hashed program"
ignore_stderr: true
stdin: |
hash -t ls
echo "1. Result: $?"
ls >/dev/null 2>&1
hash -t ls
echo "2. Result: $?"
- name: "Display hashed program"
stdin: |
hash -p /some/path somecmd && echo "1. Result: $?"
hash -t somecmd && echo "2. Result: $?"
- name: "Display multiple hashed programs"
stdin: |
hash -p /some/path somecmd1 && echo "1. Result: $?"
hash -p /some/path somecmd2 && echo "2. Result: $?"
hash -t somecmd1 somecmd2 && echo "3. Result: $?"
- name: "Display -l path"
stdin: |
hash -p "/some/spaces path" somecmd && echo "1. Result: $?"
hash -t somecmd && echo "2. Result: $?"
hash -t -l somecmd && echo "3. Result: $?"
- name: "Remove"
ignore_stderr: true
stdin: |
hash -p /some/path somecmd && echo "1. Result: $?"
hash -t somecmd && echo "2. Result: $?"
hash -d somecmd && echo "3. Result: $?"
hash -t somecmd && echo "4. Result: $?"
- name: "Remove all"
ignore_stderr: true
stdin: |
hash -p /some/path somecmd1 && echo "1. Result: $?"
hash -p /some/path somecmd2 && echo "2. Result: $?"
hash -r && echo "3. Result: $?"
hash -t somecmd1 && echo "4. Result: $?"
hash -t somecmd2 && echo "5. Result: $?"
- name: "Hash file path"
ignore_stderr: true
stdin: |
hash /dev/null && echo "1. Result: $?"
hash /dev/nulll && echo "2. Result: $?"
- name: "hash -p refuses a directory"
stdin: |
# Normalize away the leading "shell: line N:" that the oracle prefixes onto diagnostics.
strip() { sed 's/^.*hash:/hash:/'; }
mkdir -p adir
touch afile
echo "[a directory is refused]"
hash -p adir z1 2>&1 | strip; echo "rc=${PIPESTATUS[0]}"
# The pipeline above ran in a subshell, so re-run it here to check the table itself.
hash -p adir z1 2>/dev/null; echo "rc=$?"
hash -t z1 2>&1 | strip; echo "rc=${PIPESTATUS[0]}"
echo "[any other path is taken at face value]"
hash -p afile z2; echo "rc=$?"
hash -p /nonexistent/x z3; echo "rc=$?"
hash -t z2 z3; echo "rc=$?"
echo "[refused once per name]"
hash -p adir bad1 bad2 2>&1 | strip; echo "rc=${PIPESTATUS[0]}"
echo "[a relative path resolves against the shell's working directory]"
mkdir -p sub/reldir sub2
cd sub
hash -p reldir z4 2>&1 | strip; echo "rc=${PIPESTATUS[0]}"
cd ../sub2
# ../sub/reldir exists, but 'reldir' does not from here, so this is just a path.
hash -p reldir z5 2>/dev/null; echo "rc=$?"
hash -t z5; echo "rc=$?"
cd ..
echo "[hash NAME stays strict about executables]"
mkdir -p d1; touch d1/only
PATH="d1:$PATH"
hash only 2>&1 | strip; echo "rc=${PIPESTATUS[0]}"
#
# `hash` with no names lists the table. brush prints nothing for any such listing,
# whether the table is empty or populated, so these are marked `known_failure`. Hit
# counts get their own case: they can only be observed through the listing, but they
# are a separate gap and a fix for one need not be a fix for the other.
#
- name: "Display the whole table"
known_failure: true # TODO(hash): `hash` with no names should list the table
stdin: |
echo "[empty]"
hash; echo "rc=$?"
echo "[populated, in insertion order]"
hash -p /some/path sc1
hash -p /other/path sc2
hash; echo "rc=$?"
echo "[emptied again]"
hash -r
hash; echo "rc=$?"
- name: "Display the whole table in reusable form"
known_failure: true # TODO(hash): `hash -l` with no names should list the table
stdin: |
hash -p /some/path sc1
hash -p "/some/spaces path" sc2
hash -l; echo "rc=$?"
- name: "Count hits per hashed command"
known_failure: true # TODO(hash): hit counts are not tracked
stdin: |
# Normalize away the temporary directory the test runs in.
scrub() { sed -E "s|$PWD|<TMPDIR>|g"; }
printf '#!/bin/sh\n:\n' > prog
chmod +x prog
PATH="$PWD:$PATH"
prog
prog
hash | scrub; echo "rc=${PIPESTATUS[0]}"
- name: "Assigning PATH empties the table"
known_failure: true # TODO(hash): assigning PATH doesn't empty the table, so a command keeps being run from a directory no longer in PATH
ignore_stderr: true # How shells word what's not found differs
test_files:
- path: "x/prog"
executable: true
contents: |
#!/bin/sh
echo "prog in x"
- path: "y/.keep"
stdin: |
PATH="${PWD}/x"
prog
PATH="${PWD}/y"
prog; echo "status: $?"
- name: "Hash a path starting with a dot"
stdin: |
hash -p .nosuch foo
hash -t foo; echo "status: $?"
- name: "Hash paths starting with a dot, as given"
test_files:
- path: "sub/prog"
executable: true
contents: |
#!/bin/sh
echo "0=$0"
stdin: |
cd sub
for path in ./././prog .//prog; do
hash -p "${path}" p
p
hash -t p
done
for path in ./nosuch/ ./nosuch//; do
hash -p "${path}" foo
hash -t foo; echo "status: $?"
done
- name: "Hash a builtin or function"
known_failure: true # TODO(hash): hashing a builtin's name hashes a program of that name, and a function's fails, where bash does neither
ignore_stderr: true # How shells word what's not found differs
stdin: |
f() { :; }
hash echo; echo "echo: $?"
hash f; echo "f: $?"
hash -t echo; echo "hashed: $?"
- name: "command -p hashes what it finds"
known_failure: true # TODO(hash): `command -p` doesn't hash the program it finds
stdin: |
command -p cat </dev/null
hash -t cat; echo "status: $?"
- name: "Run a hashed path that doesn't exist"
known_failure: true # TODO(hash): running a hashed path that doesn't exist reports the command as not found, not the path as missing
ignore_stderr: true
stdin: |
hash -p /no/such/prog prog
prog; echo "status: $?"
prog 2>&1 | grep -q 'No such file' && echo "says no such file" || echo "says something else"
- name: "hash -t with no names fails with status 1"
known_failure: true # TODO(hash): succeeds
ignore_stderr: true
stdin: |
hash -t; echo "rc=$?"
- name: "hash -r -p empties the table, then adds the path"
known_failure: true # TODO(hash): the table is emptied after the path is added
stdin: |
hash -p /bin/true seeded
hash -r -p /bin/sh foo
hash -t foo
hash -t seeded 2>/dev/null; echo "seeded: $?"