mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-09-09 17:17:53 +00:00
Problem: the system test 'is()' checker was poorly thought out. For example, there is no way to check for inequality or for absence of a substring. Solution, step 1: introduce new assert(), copied almost verbatim from buildah, where it has been successful in addressing the gaps in is(). The logical next step is to search the tests for 'die' and for 'run', looking for negative assertions which we can replace with assert(). There were a lot, and in the process I found a number of ugly bugs in the tests themselves. I've taken the liberty of fixing these. Important note: at this time we have both assert() and is(). Replacing all instances of is() would be impossible to review. Signed-off-by: Ed Santiago <santiago@redhat.com>
200 lines
9.1 KiB
Bash
200 lines
9.1 KiB
Bash
#!/usr/bin/env bats
|
|
#
|
|
# Tests based on 'podman help'
|
|
#
|
|
# Find all commands listed by 'podman --help'. Run each one, make sure it
|
|
# provides its own --help output. If the usage message ends in '[command]',
|
|
# treat it as a subcommand, and recurse into its own list of sub-subcommands.
|
|
#
|
|
# Any usage message that ends in '[options]' is interpreted as a command
|
|
# that takes no further arguments; we confirm by running with 'invalid-arg'
|
|
# and confirming that it exits with error status and message.
|
|
#
|
|
load helpers
|
|
|
|
function check_help() {
|
|
local count=0
|
|
local -A found
|
|
|
|
for cmd in $(_podman_commands "$@"); do
|
|
# Human-readable podman command string, with multiple spaces collapsed
|
|
command_string="podman $* $cmd"
|
|
command_string=${command_string// / } # 'podman x' -> 'podman x'
|
|
|
|
dprint "$command_string --help"
|
|
run_podman "$@" $cmd --help
|
|
local full_help="$output"
|
|
|
|
# The line immediately after 'Usage:' gives us a 1-line synopsis
|
|
usage=$(echo "$full_help" | grep -A1 '^Usage:' | tail -1)
|
|
assert "$usage" != "" "podman $cmd: no Usage message found"
|
|
|
|
# e.g. 'podman ps' should not show 'podman container ps' in usage
|
|
# Trailing space in usage handles 'podman system renumber' which
|
|
# has no ' [options]'
|
|
is "$usage " " $command_string .*" "Usage string matches command"
|
|
|
|
# If usage ends in '[command]', recurse into subcommands
|
|
if expr "$usage" : '.*\[command\]$' >/dev/null; then
|
|
found[subcommands]=1
|
|
check_help "$@" $cmd
|
|
continue
|
|
fi
|
|
|
|
# We had someone write upper-case '[OPTIONS]' once. Prevent it.
|
|
assert "$usage" !~ '\[OPTION' \
|
|
"'options' string must be lower-case in usage"
|
|
|
|
# We had someone do 'podman foo ARG [options]' one time. Yeah, no.
|
|
assert "$usage" !~ '[A-Z].*\[option' \
|
|
"'options' must precede arguments in usage"
|
|
|
|
# Cross-check: if usage includes '[options]', there must be a
|
|
# longer 'Options:' section in the full --help output; vice-versa,
|
|
# if 'Options:' is in full output, usage line must have '[options]'.
|
|
if expr "$usage" : '.*\[option' >/dev/null; then
|
|
if ! expr "$full_help" : ".*Options:" >/dev/null; then
|
|
die "$command_string: Usage includes '[options]' but has no 'Options:' subsection"
|
|
fi
|
|
elif expr "$full_help" : ".*Options:" >/dev/null; then
|
|
die "$command_string: --help has 'Options:' section but no '[options]' in synopsis"
|
|
fi
|
|
|
|
# If usage lists no arguments (strings in ALL CAPS), confirm
|
|
# by running with 'invalid-arg' and expecting failure.
|
|
if ! expr "$usage" : '.*[A-Z]' >/dev/null; then
|
|
if [ "$cmd" != "help" ]; then
|
|
dprint "$command_string invalid-arg"
|
|
run_podman '?' "$@" $cmd invalid-arg
|
|
is "$status" 125 \
|
|
"'$usage' indicates that the command takes no arguments. I invoked it with 'invalid-arg' and expected an error status"
|
|
is "$output" "Error: .* takes no arguments" \
|
|
"'$usage' indicates that the command takes no arguments. I invoked it with 'invalid-arg' and expected the following error message"
|
|
fi
|
|
found[takes_no_args]=1
|
|
fi
|
|
|
|
# If command lists "-l, --latest" in help output, combine -l with arg.
|
|
# This should be disallowed with a clear message.
|
|
if expr "$full_help" : ".*-l, --latest" >/dev/null; then
|
|
local nope="exec list port ps top" # these can't be tested
|
|
if is_rootless; then
|
|
nope="$nope mount restore" # these don't work rootless
|
|
fi
|
|
if ! grep -wq "$cmd" <<<$nope; then
|
|
run_podman 125 "$@" $cmd -l nonexistent-container
|
|
is "$output" "Error: .*--latest and \(containers\|pods\|arguments\) cannot be used together" \
|
|
"'$command_string' with both -l and container"
|
|
|
|
# Combine -l and -a, too (but spell it as --all, because "-a"
|
|
# means "attach" in podman container start)
|
|
run_podman 125 "$@" $cmd --all --latest
|
|
is "$output" "Error: \(--all and --latest cannot be used together\|--all, --latest and containers cannot be used together\|--all, --latest and arguments cannot be used together\|unknown flag\)" \
|
|
"'$command_string' with both --all and --latest"
|
|
fi
|
|
fi
|
|
|
|
# If usage has required arguments, try running without them.
|
|
# The expression here is 'first capital letter is not in [BRACKETS]'.
|
|
# It is intended to handle 'podman foo [options] ARG' but not ' [ARG]'.
|
|
if expr "$usage" : '[^A-Z]\+ [A-Z]' >/dev/null; then
|
|
# Exceptions: these commands don't work rootless
|
|
if is_rootless; then
|
|
# "pause is not supported for rootless containers"
|
|
if [ "$cmd" = "pause" -o "$cmd" = "unpause" ]; then
|
|
continue
|
|
fi
|
|
# "network rm" too
|
|
if [ "$@" = "network" -a "$cmd" = "rm" ]; then
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
# The </dev/null protects us from 'podman login' which will
|
|
# try to read username/password from stdin.
|
|
dprint "$command_string (without required args)"
|
|
run_podman '?' "$@" $cmd </dev/null
|
|
is "$status" 125 \
|
|
"'$usage' indicates at least one required arg. I invoked it with no args and expected an error exit code"
|
|
is "$output" "Error:.* \(require\|specif\|must\|provide\|need\|choose\|accepts\)" \
|
|
"'$usage' indicates at least one required arg. I invoked it with no args and expected one of these error messages"
|
|
|
|
found[required_args]=1
|
|
fi
|
|
|
|
# Commands with fixed number of arguments (i.e. no ellipsis): count
|
|
# the required args, then invoke with one extra. We should get a
|
|
# usage error.
|
|
if ! expr "$usage" : ".*\.\.\."; then
|
|
# "podman help" can take infinite args, so skip that one
|
|
if [ "$cmd" != "help" ]; then
|
|
# Get the args part of the command line; this should be
|
|
# everything from the first CAPITAL LETTER onward. We
|
|
# don't actually care about the letter itself, so just
|
|
# make it 'X'. And we don't care about [OPTIONAL] brackets
|
|
# either. What we do care about is stuff like 'IMAGE | CTR'
|
|
# which is actually one argument; convert to 'IMAGE-or-CTR'
|
|
local rhs=$(sed -e 's/^[^A-Z]\+[A-Z]/X/' -e 's/ | /-or-/g' <<<"$usage")
|
|
local n_args=$(wc -w <<<"$rhs")
|
|
|
|
run_podman '?' "$@" $cmd $(seq --format='x%g' 0 $n_args)
|
|
is "$status" 125 \
|
|
"'$usage' indicates a maximum of $n_args args. I invoked it with more, and expected this exit status"
|
|
is "$output" "Error:.* \(takes no arguments\|requires exactly $n_args arg\|accepts at most\|too many arguments\|accepts $n_args arg(s), received\|accepts between .* and .* arg(s), received \)" \
|
|
"'$usage' indicates a maximum of $n_args args. I invoked it with more, and expected one of these error messages"
|
|
|
|
found[fixed_args]=1
|
|
fi
|
|
fi
|
|
|
|
count=$(expr $count + 1)
|
|
done
|
|
|
|
# Any command that takes subcommands, prints its help and errors if called
|
|
# without one.
|
|
dprint "podman $@"
|
|
run_podman '?' "$@"
|
|
is "$status" 125 "'podman $*' without any subcommand - exit status"
|
|
is "$output" ".*Usage:.*Error: missing command '.*$@ COMMAND'" \
|
|
"'podman $*' without any subcommand - expected error message"
|
|
|
|
# Assume that 'NoSuchCommand' is not a command
|
|
dprint "podman $@ NoSuchCommand"
|
|
run_podman '?' "$@" NoSuchCommand
|
|
is "$status" 125 "'podman $* NoSuchCommand' - exit status"
|
|
is "$output" "Error: unrecognized command .*$@ NoSuchCommand" \
|
|
"'podman $* NoSuchCommand' - expected error message"
|
|
|
|
# This can happen if the output of --help changes, such as between
|
|
# the old command parser and cobra.
|
|
assert "$count" -gt 0 \
|
|
"Internal error: no commands found in 'podman help $*' list"
|
|
|
|
# Sanity check: make sure the special loops above triggered at least once.
|
|
# (We've had situations where a typo makes the conditional never run)
|
|
if [ -z "$*" ]; then
|
|
for i in subcommands required_args takes_no_args fixed_args; do
|
|
assert "${found[$i]}" != "" \
|
|
"Internal error: '$i' subtest did not trigger"
|
|
done
|
|
fi
|
|
}
|
|
|
|
|
|
@test "podman help - basic tests" {
|
|
skip_if_remote
|
|
|
|
# Called with no args -- start with 'podman --help'. check_help() will
|
|
# recurse for any subcommands.
|
|
check_help
|
|
|
|
# Test for regression of #7273 (spurious "--remote" help on output)
|
|
for helpopt in help --help; do
|
|
run_podman $helpopt
|
|
is "${lines[0]}" "Manage pods, containers and images" \
|
|
"podman $helpopt: first line of output"
|
|
done
|
|
|
|
}
|
|
|
|
# vim: filetype=sh
|