summaryrefslogtreecommitdiff
path: root/test/system
diff options
context:
space:
mode:
Diffstat (limited to 'test/system')
-rw-r--r--test/system/015-help.bats58
-rw-r--r--test/system/030-run.bats11
-rw-r--r--test/system/060-mount.bats8
-rw-r--r--test/system/065-cp.bats100
-rw-r--r--test/system/120-load.bats2
-rw-r--r--test/system/160-volumes.bats39
-rw-r--r--test/system/170-run-userns.bats39
-rw-r--r--test/system/200-pod.bats21
-rw-r--r--test/system/250-systemd.bats6
-rw-r--r--test/system/255-auto-update.bats12
-rw-r--r--test/system/500-networking.bats4
-rw-r--r--test/system/520-checkpoint.bats30
-rw-r--r--test/system/600-completion.bats102
-rw-r--r--test/system/helpers.bash10
14 files changed, 368 insertions, 74 deletions
diff --git a/test/system/015-help.bats b/test/system/015-help.bats
index 5757d51dc..1356c99a0 100644
--- a/test/system/015-help.bats
+++ b/test/system/015-help.bats
@@ -34,10 +34,16 @@ function check_help() {
# has no ' [options]'
is "$usage " " $command_string .*" "Usage string matches command"
+ # Strip off the leading command string; we no longer need it
+ usage=$(sed -e "s/^ $command_string \?//" <<<"$usage")
+
# If usage ends in '[command]', recurse into subcommands
- if expr "$usage" : '.*\[command\]$' >/dev/null; then
+ if expr "$usage" : '\[command\]' >/dev/null; then
found[subcommands]=1
- check_help "$@" $cmd
+ # (except for 'podman help', which is a special case)
+ if [[ $cmd != "help" ]]; then
+ check_help "$@" $cmd
+ fi
continue
fi
@@ -49,10 +55,26 @@ function check_help() {
assert "$usage" !~ '[A-Z].*\[option' \
"'options' must precede arguments in usage"
+ # Strip off '[options]' but remember if we've seen it.
+ local has_options=
+ if [[ $usage =~ \[options\] ]]; then
+ has_options=1
+ usage=$(sed -e 's/^\[options\] \?//' <<<"$usage")
+ fi
+
+ # From this point on, remaining argument descriptions must be UPPER CASE
+ # e.g., 'podman cmd [options] arg' or 'podman cmd [arg]' are invalid.
+ assert "$usage" !~ '[a-z]' \
+ "$command_string: argument names must be UPPER CASE"
+
+ # It makes no sense to have an optional arg followed by a mandatory one
+ assert "$usage" !~ '\[.*\] [A-Z]' \
+ "$command_string: optional args must be _after_ required ones"
+
# 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 [[ $has_options ]]; then
if ! expr "$full_help" : ".*Options:" >/dev/null; then
die "$command_string: Usage includes '[options]' but has no 'Options:' subsection"
fi
@@ -95,9 +117,7 @@ function check_help() {
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
+ if expr "$usage" : '[A-Z]' >/dev/null; then
# Exceptions: these commands don't work rootless
if is_rootless; then
# "pause is not supported for rootless containers"
@@ -126,25 +146,15 @@ function check_help() {
# 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"
+ local n_args=$(wc -w <<<"$usage")
- found[fixed_args]=1
- fi
+ 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
count=$(expr $count + 1)
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index 283c3aea9..241831257 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -855,4 +855,15 @@ EOF
run_podman rmi $test_image
}
+@test "podman create --security-opt" {
+ run_podman create --security-opt no-new-privileges=true $IMAGE
+ run_podman rm $output
+ run_podman create --security-opt no-new-privileges:true $IMAGE
+ run_podman rm $output
+ run_podman create --security-opt no-new-privileges=false $IMAGE
+ run_podman rm $output
+ run_podman create --security-opt no-new-privileges $IMAGE
+ run_podman rm $output
+}
+
# vim: filetype=sh
diff --git a/test/system/060-mount.bats b/test/system/060-mount.bats
index 7addbd88e..2735d2afd 100644
--- a/test/system/060-mount.bats
+++ b/test/system/060-mount.bats
@@ -50,6 +50,10 @@ load helpers
run_podman image mount $IMAGE
mount_path="$output"
+ # Make sure that `mount -a` prints a table
+ run_podman image mount -a
+ is "$output" "$IMAGE .*$mount_path"
+
test -d $mount_path
# Image is custom-built and has a file containing the YMD tag. Check it.
@@ -62,8 +66,8 @@ load helpers
run_podman image mount
is "$output" "$IMAGE *$mount_path" "podman image mount with no args"
- # Clean up
- run_podman image umount $IMAGE
+ # Clean up: -f since we mounted it twice
+ run_podman image umount -f $IMAGE
is "$output" "$iid" "podman image umount: image ID of what was umounted"
run_podman image umount $IMAGE
diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats
index cfbeff3ae..12c6e1a01 100644
--- a/test/system/065-cp.bats
+++ b/test/system/065-cp.bats
@@ -949,9 +949,107 @@ ${randomcontent[1]}" "$description"
run_podman rm -t 0 -f cpcontainer
}
+@test "podman cp --overwrite file - ctr/ctr" {
+ rand_content_file=$(random_string 50)
+ rand_content_dir=$(random_string 50)
+
+ run_podman run -d --name ctr-file $IMAGE sh -c "echo '$rand_content_file' > /tmp/foo; sleep infinity"
+ run_podman run -d --name ctr-dir $IMAGE sh -c "mkdir /tmp/foo; echo '$rand_content_dir' > /tmp/foo/file.txt; sleep infinity"
+
+ # overwrite a directory with a file
+ run_podman 125 cp ctr-file:/tmp/foo ctr-dir:/tmp
+ if ! is_remote; then # remote just returns a 500
+ is "$output" ".* error creating \"/tmp/foo\": .*: file exists.*"
+ fi
+ run_podman cp --overwrite ctr-file:/tmp/foo ctr-dir:/tmp
+ run_podman exec ctr-dir cat /tmp/foo
+ is "$output" "$rand_content_file"
+
+ # reset the ctr-dir container
+ run_podman exec ctr-dir sh -c "rm -rf /tmp/foo; mkdir /tmp/foo; echo '$rand_content_dir' > /tmp/foo/file.txt"
+
+ # overwrite a file with a directory
+ run_podman 125 cp ctr-dir:/tmp/foo ctr-file:/tmp
+ if ! is_remote; then # remote just returns a 500
+ is "$output" ".* error creating \"/tmp/foo\": .*: file exists.*"
+ fi
+ run_podman cp --overwrite ctr-dir:/tmp/foo ctr-file:/tmp
+ run_podman exec ctr-file cat /tmp/foo/file.txt
+ is "$output" "$rand_content_dir"
+
+ run_podman rm -t 0 -f ctr-file ctr-dir
+}
+
+@test "podman cp --overwrite file - ctr/host" {
+ hostdir=$PODMAN_TMPDIR/cp-test
+ mkdir -p $hostdir
+
+ rand_content_file=$(random_string 50)
+ rand_content_dir=$(random_string 50)
+
+ run_podman run -d --name ctr-file $IMAGE sh -c "echo '$rand_content_file' > /tmp/foo; sleep infinity"
+ run_podman run -d --name ctr-dir $IMAGE sh -c "mkdir /tmp/foo; echo '$rand_content_dir' > /tmp/foo/file.txt; sleep infinity"
+
+ # overwrite a directory with a file
+ mkdir $hostdir/foo
+ run_podman 125 cp ctr-file:/tmp/foo $hostdir
+ if ! is_remote; then # remote just returns a 500
+ is "$output" ".* error creating \"/foo\": .*: file exists.*"
+ fi
+ run_podman cp --overwrite ctr-file:/tmp/foo $hostdir
+ is "$(< $hostdir/foo)" "$rand_content_file"
+
+ # overwrite a file with a directory
+ rm -rf $hostdir/foo
+ touch $hostdir/foo
+ run_podman 125 cp ctr-dir:/tmp/foo $hostdir
+ if ! is_remote; then # remote just returns a 500
+ is "$output" ".* error creating \"/foo\": .*: file exists.*"
+ fi
+ run_podman cp --overwrite ctr-dir:/tmp/foo $hostdir
+ is "$(< $hostdir/foo/file.txt)" "$rand_content_dir"
+
+ run_podman rm -t 0 -f ctr-file ctr-dir
+}
+
+@test "podman cp --overwrite file - host/ctr" {
+ hostdir=$PODMAN_TMPDIR/cp-test
+ mkdir -p $hostdir
+
+ rand_content_file=$(random_string 50)
+ rand_content_dir=$(random_string 50)
+
+ run_podman run -d --name ctr-dir $IMAGE sh -c "mkdir /tmp/foo; sleep infinity"
+ run_podman run -d --name ctr-file $IMAGE sh -c "touch /tmp/foo; sleep infinity"
+
+ # overwrite a directory with a file
+ echo "$rand_content_file" > $hostdir/foo
+ run_podman 125 cp $hostdir/foo ctr-dir:/tmp
+ if ! is_remote; then # remote just returns a 500
+ is "$output" ".* error creating \"/tmp/foo\": .*: file exists.*"
+ fi
+ run_podman cp --overwrite $hostdir/foo ctr-dir:/tmp
+ run_podman exec ctr-dir cat /tmp/foo
+ is "$output" "$rand_content_file"
+
+ # overwrite a file with a directory
+ rm -f $hostdir/foo
+ mkdir $hostdir/foo
+ echo "$rand_content_dir" > $hostdir/foo/file.txt
+ run_podman 125 cp $hostdir/foo ctr-file:/tmp
+ if ! is_remote; then # remote just returns a 500
+ is "$output" ".* error creating \"/tmp/foo\": .*: file exists.*"
+ fi
+ run_podman cp --overwrite $hostdir/foo ctr-file:/tmp
+ run_podman exec ctr-file cat /tmp/foo/file.txt
+ is "$output" "$rand_content_dir"
+
+ run_podman rm -t 0 -f ctr-file ctr-dir
+}
+
function teardown() {
# In case any test fails, clean up the container we left behind
- run_podman rm -t 0 f cpcontainer
+ run_podman rm -t 0 -f --ignore cpcontainer
basic_teardown
}
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index 45e0b3362..5a7f63b43 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -121,7 +121,7 @@ verify_iid_and_name() {
run_podman untag $IMAGE $newname
run_podman image scp -q ${notme}@localhost::$newname
- expect="Loaded image(s): $newname"
+ expect="Loaded image: $newname"
is "$output" "$expect" "-q silences output"
# Confirm that we have it, and that its digest matches our original
diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats
index 5b0460723..797883ec6 100644
--- a/test/system/160-volumes.bats
+++ b/test/system/160-volumes.bats
@@ -411,4 +411,43 @@ NeedsChown | true
fi
}
+@test "podman --image-volume" {
+ tmpdir=$PODMAN_TMPDIR/volume-test
+ mkdir -p $tmpdir
+ containerfile=$tmpdir/Containerfile
+ cat >$containerfile <<EOF
+FROM $IMAGE
+VOLUME /data
+EOF
+ fs=$(stat -f -c %T .)
+ run_podman build -t volume_image $tmpdir
+
+ containersconf=$tmpdir/containers.conf
+ cat >$containersconf <<EOF
+[engine]
+image_volume_mode="tmpfs"
+EOF
+
+ run_podman run --image-volume tmpfs --rm volume_image stat -f -c %T /data
+ is "$output" "tmpfs" "Should be tmpfs"
+
+ run_podman 1 run --image-volume ignore --rm volume_image stat -f -c %T /data
+ is "$output" "stat: can't read file system information for '/data': No such file or directory" "Should fail with /data does not exists"
+
+ CONTAINERS_CONF="$containersconf" run_podman run --rm volume_image stat -f -c %T /data
+ is "$output" "tmpfs" "Should be tmpfs"
+
+ CONTAINERS_CONF="$containersconf" run_podman run --image-volume bind --rm volume_image stat -f -c %T /data
+ assert "$output" != "tmpfs" "Should match hosts $fs"
+
+ CONTAINERS_CONF="$containersconf" run_podman run --image-volume tmpfs --rm volume_image stat -f -c %T /data
+ is "$output" "tmpfs" "Should be tmpfs"
+
+ CONTAINERS_CONF="$containersconf" run_podman 1 run --image-volume ignore --rm volume_image stat -f -c %T /data
+ is "$output" "stat: can't read file system information for '/data': No such file or directory" "Should fail with /data does not exists"
+
+ run_podman rm --all --force -t 0
+ run_podman image rm --force localhost/volume_image
+}
+
# vim: filetype=sh
diff --git a/test/system/170-run-userns.bats b/test/system/170-run-userns.bats
index b80351902..84788a7f4 100644
--- a/test/system/170-run-userns.bats
+++ b/test/system/170-run-userns.bats
@@ -38,10 +38,12 @@ function _require_crun() {
@test "rootful pod with custom ID mapping" {
skip_if_rootless "does not work rootless - rootful feature"
- skip_if_remote "remote --uidmap is broken (see #14233)"
random_pod_name=$(random_string 30)
run_podman pod create --uidmap 0:200000:5000 --name=$random_pod_name
run_podman pod start $random_pod_name
+ run_podman pod inspect --format '{{.InfraContainerID}}' $random_pod_name
+ run podman inspect --format '{{.HostConfig.IDMappings.UIDMap}}' $output
+ is "$output" ".*0:200000:5000" "UID Map Successful"
# Remove the pod and the pause image
run_podman pod rm $random_pod_name
@@ -109,15 +111,30 @@ EOF
}
@test "podman userns=nomap" {
- skip_if_not_rootless "--userns=nomap only works in rootless mode"
- ns_user=$(id -un)
- baseuid=$(egrep "${ns_user}:" /etc/subuid | cut -f2 -d:)
- test ! -z ${baseuid} || skip "no IDs allocated for user ${ns_user}"
+ if is_rootless; then
+ ns_user=$(id -un)
+ baseuid=$(egrep "${ns_user}:" /etc/subuid | cut -f2 -d:)
+ test ! -z ${baseuid} || skip "no IDs allocated for user ${ns_user}"
+
+ test_name="test_$(random_string 12)"
+ run_podman run -d --userns=nomap $IMAGE sleep 100
+ cid=${output}
+ run_podman top ${cid} huser
+ is "${output}" "HUSER.*${baseuid}" "Container should start with baseuid from /etc/subuid not user UID"
+ run_podman rm -t 0 --force ${cid}
+ else
+ run_podman 125 run -d --userns=nomap $IMAGE sleep 100
+ is "${output}" "Error: nomap is only supported in rootless mode" "Container should fail to start since nomap is not suppored in rootful mode"
+ fi
+}
- test_name="test_$(random_string 12)"
- run_podman run -d --userns=nomap $IMAGE sleep 100
- cid=${output}
- run_podman top ${cid} huser
- is "${output}" "HUSER.*${baseuid}" "Container should start with baseuid from /etc/subuid not user UID"
- run_podman rm -t 0 --force ${cid}
+@test "podman userns=keep-id" {
+ if is_rootless; then
+ user=$(id -u)
+ run_podman run --rm --userns=keep-id $IMAGE id -u
+ is "${output}" "$user" "Container should run as the current user"
+ else
+ run_podman 125 run --rm --userns=keep-id $IMAGE id -u
+ is "${output}" "Error: keep-id is only supported in rootless mode" "Container should fail to start since keep-id is not suppored in rootful mode"
+ fi
}
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index 4250f2680..404ad67ec 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -335,8 +335,15 @@ EOF
is "$output" ".*Invalid kernel namespace to share: bogus. Options are: cgroup, ipc, net, pid, uts or none" \
"pod test for bogus --share option"
run_podman pod create --share ipc --name $pod_name
+ run_podman pod inspect $pod_name --format "{{.SharedNamespaces}}"
+ is "$output" "[ipc]"
run_podman run --rm --pod $pod_name --hostname foobar $IMAGE hostname
is "$output" "foobar" "--hostname should work with non share UTS namespace"
+ run_podman pod create --share +pid --replace --name $pod_name
+ run_podman pod inspect $pod_name --format "{{.SharedNamespaces}}"
+ for ns in uts pid ipc net; do
+ is "$output" ".*$ns"
+ done
}
@test "podman pod create --pod new:$POD --hostname" {
@@ -387,20 +394,20 @@ EOF
is "$output" "false" "Default network sharing should be false"
run_podman pod rm test
- run_podman pod create --name test --share ipc --network private
+ run_podman pod create --share ipc --network private test
run_podman pod inspect test --format {{.InfraConfig.HostNetwork}}
is "$output" "false" "Private network sharing with only ipc should be false"
run_podman pod rm test
- run_podman pod create --name test --share net --network private
- run_podman pod inspect test --format {{.InfraConfig.HostNetwork}}
+ local name="$(random_string 10 | tr A-Z a-z)"
+ run_podman pod create --name $name --share net --network private
+ run_podman pod inspect $name --format {{.InfraConfig.HostNetwork}}
is "$output" "false" "Private network sharing with only net should be false"
- run_podman pod rm test
- run_podman pod create --name test --share net --network host
- run_podman pod inspect test --format {{.InfraConfig.HostNetwork}}
+ run_podman pod create --share net --network host --replace $name
+ run_podman pod inspect $name --format {{.InfraConfig.HostNetwork}}
is "$output" "true" "Host network sharing with only net should be true"
- run_podman pod rm test
+ run_podman pod rm $name
run_podman pod create --name test --share ipc --network host
run_podman pod inspect test --format {{.InfraConfig.HostNetwork}}
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index 567fa89c1..110d425d2 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -80,12 +80,6 @@ function service_cleanup() {
run_podman logs $cname
is "$output" ".*WAITING.*" "running is waiting for signal"
- # Exercise `podman auto-update`.
- # TODO: this will at least run auto-update code but won't perform an update
- # since the image didn't change. We need to improve on that and run
- # an image from a local registry instead.
- run_podman auto-update
-
# All good. Stop service, clean up.
# Also make sure the service is in the `inactive` state (see #11304).
service_cleanup inactive
diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats
index 6cdae2ada..6cee939fb 100644
--- a/test/system/255-auto-update.bats
+++ b/test/system/255-auto-update.bats
@@ -135,15 +135,27 @@ function _confirm_update() {
# This test can fail in dev. environment because of SELinux.
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "podman auto-update - label io.containers.autoupdate=image" {
+ since=$(date --iso-8601=seconds)
+ run_podman auto-update
+ is "$output" ""
+ run_podman events --filter type=system --since $since --stream=false
+ is "$output" ""
+
generate_service alpine image
_wait_service_ready container-$cname.service
+ since=$(date --iso-8601=seconds)
run_podman auto-update --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
is "$output" ".*container-$cname.service,quay.io/libpod/alpine:latest,pending,registry.*" "Image update is pending."
+ run_podman events --filter type=system --since $since --stream=false
+ is "$output" ".* system auto-update"
+ since=$(date --iso-8601=seconds)
run_podman auto-update --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
is "$output" "Trying to pull.*" "Image is updated."
is "$output" ".*container-$cname.service,quay.io/libpod/alpine:latest,true,registry.*" "Image is updated."
+ run_podman events --filter type=system --since $since --stream=false
+ is "$output" ".* system auto-update"
_confirm_update $cname $ori_image
}
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index 3db0804d1..92aabae32 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -111,6 +111,10 @@ load helpers
$IMAGE nc -l -n -v -p $myport
cid="$output"
+ # check that podman stores the network info correctly when a userns is used (#14465)
+ run_podman container inspect --format "{{.NetworkSettings.SandboxKey}}" $cid
+ assert "$output" =~ ".*/netns/netns-.*" "Netns path should be set"
+
wait_for_output "listening on .*:$myport .*" $cid
# emit random string, and check it
diff --git a/test/system/520-checkpoint.bats b/test/system/520-checkpoint.bats
index c16a8c35d..7f60f01b3 100644
--- a/test/system/520-checkpoint.bats
+++ b/test/system/520-checkpoint.bats
@@ -170,4 +170,34 @@ function teardown() {
# FIXME: test --leave-running
+@test "podman checkpoint --file-locks" {
+ action='flock test.lock sh -c "while [ -e /wait ];do sleep 0.5;done;for i in 1 2 3;do echo \$i;sleep 0.5;done"'
+ run_podman run -d $IMAGE sh -c "touch /wait; touch test.lock; echo READY; $action & $action & wait"
+ local cid="$output"
+
+ # Wait for container to start emitting output
+ wait_for_ready $cid
+
+ # Checkpoint, and confirm via inspect
+ run_podman container checkpoint --file-locks $cid
+ is "$output" "$cid" "podman container checkpoint"
+
+ run_podman container inspect \
+ --format '{{.State.Status}}:{{.State.Running}}:{{.State.Paused}}:{{.State.Checkpointed}}' $cid
+ is "$output" "exited:false:false:true" "State. Status:Running:Pause:Checkpointed"
+
+ # Restart immediately and confirm state
+ run_podman container restore --file-locks $cid
+ is "$output" "$cid" "podman container restore"
+
+ # Signal the container to continue; this is where the 1-2-3s will come from
+ run_podman exec $cid rm /wait
+
+ # Wait for the container to stop
+ run_podman wait $cid
+
+ run_podman logs $cid
+ trim=$(sed -z -e 's/[\r\n]\+//g' <<<"$output")
+ is "$trim" "READY123123" "File lock restored"
+}
# vim: filetype=sh
diff --git a/test/system/600-completion.bats b/test/system/600-completion.bats
index 018e95e78..cb4a2c5f8 100644
--- a/test/system/600-completion.bats
+++ b/test/system/600-completion.bats
@@ -8,6 +8,16 @@
load helpers
+function setup() {
+ # $PODMAN may be a space-separated string, e.g. if we include a --url.
+ local -a podman_as_array=($PODMAN)
+ # __completeNoDesc must be the first arg if we running the completion cmd
+ # set the var for the run_completion function
+ PODMAN_COMPLETION="${podman_as_array[0]} __completeNoDesc ${podman_as_array[@]:1}"
+
+ basic_setup
+}
+
# Returns true if we are able to podman-pause
function _can_pause() {
# Even though we're just trying completion, not an actual unpause,
@@ -88,8 +98,14 @@ function check_shell_completion() {
continue 2
fi
+ name=$random_container_name
+ # special case podman cp suggest containers names with a colon
+ if [[ $cmd = "cp" ]]; then
+ name="$name:"
+ fi
+
run_completion "$@" $cmd "${extra_args[@]}" ""
- is "$output" ".*-$random_container_name${nl}" \
+ is "$output" ".*-$name${nl}" \
"$* $cmd: actual container listed in suggestions"
match=true
@@ -175,7 +191,7 @@ function check_shell_completion() {
_check_completion_end NoSpace
else
_check_completion_end Default
- assert "${#lines[@]}" -eq 2 "$* $cmd: Suggestions are in the output"
+ _check_no_suggestions
fi
;;
@@ -205,16 +221,7 @@ function check_shell_completion() {
if [[ ! ${args##* } =~ "..." ]]; then
run_completion "$@" $cmd "${extra_args[@]}" ""
_check_completion_end NoFileComp
- if [ ${#lines[@]} -gt 2 ]; then
- # checking for line count is not enough since we may include additional debug output
- # lines starting with [Debug] are allowed
- i=0
- length=$(( ${#lines[@]} - 2 ))
- while [[ i -lt length ]]; do
- assert "${lines[$i]:0:7}" == "[Debug]" "Suggestions are in the output"
- i=$(( i + 1 ))
- done
- fi
+ _check_no_suggestions
fi
done
@@ -231,6 +238,24 @@ function _check_completion_end() {
is "${lines[-1]}" "Completion ended with directive: ShellCompDirective$1" "Completion has wrong ShellCompDirective set"
}
+# Check that there are no suggestions in the output.
+# We could only check stdout and not stderr but this is not possible with bats.
+# By default we always have two extra lines at the end for the ShellCompDirective.
+# Then we could also have other extra lines for debugging, they will always start
+# with [Debug], e.g. `[Debug] [Error] no container with name or ID "t12" found: no such container`.
+function _check_no_suggestions() {
+ if [ ${#lines[@]} -gt 2 ]; then
+ # Checking for line count is not enough since we may include additional debug output.
+ # Lines starting with [Debug] are allowed.
+ local i=0
+ length=$((${#lines[@]} - 2))
+ while [[ i -lt length ]]; do
+ assert "${lines[$i]:0:7}" == "[Debug]" "Unexpected non-Debug output line: ${lines[$i]}"
+ i=$((i + 1))
+ done
+ fi
+}
+
@test "podman shell completion test" {
@@ -280,11 +305,6 @@ function _check_completion_end() {
# create secret
run_podman secret create $random_secret_name $secret_file
- # $PODMAN may be a space-separated string, e.g. if we include a --url.
- local -a podman_as_array=($PODMAN)
- # __completeNoDesc must be the first arg if we running the completion cmd
- PODMAN_COMPLETION="${podman_as_array[0]} __completeNoDesc ${podman_as_array[@]:1}"
-
# Called with no args -- start with 'podman --help'. check_shell_completion() will
# recurse for any subcommands.
check_shell_completion
@@ -316,3 +336,51 @@ function _check_completion_end() {
done <<<"$output"
}
+
+@test "podman shell completion for paths in container/image" {
+ skip_if_remote "mounting via remote does not work"
+ for cmd in create run; do
+ run_completion $cmd $IMAGE ""
+ assert "$output" =~ ".*^/etc/\$.*" "etc directory suggested (cmd: podman $cmd)"
+ assert "$output" =~ ".*^/home/\$.*" "home directory suggested (cmd: podman $cmd)"
+ assert "$output" =~ ".*^/root/\$.*" "root directory suggested (cmd: podman $cmd)"
+
+ # check completion for subdirectory
+ run_completion $cmd $IMAGE "/etc"
+ # It should be safe to assume the os-release file always exists in $IMAGE
+ assert "$output" =~ ".*^/etc/os-release\$.*" "/etc files suggested (cmd: podman $cmd /etc)"
+ # check completion for partial file name
+ run_completion $cmd $IMAGE "/etc/os-"
+ assert "$output" =~ ".*^/etc/os-release\$.*" "/etc files suggested (cmd: podman $cmd /etc/os-)"
+
+ # check completion with relative path components
+ # It is important the we will still use the image root and not escape to the host
+ run_completion $cmd $IMAGE "../../"
+ assert "$output" =~ ".*^../../etc/\$.*" "relative etc directory suggested (cmd: podman $cmd ../../)"
+ assert "$output" =~ ".*^../../home/\$.*" "relative home directory suggested (cmd: podman $cmd ../../)"
+ done
+
+ random_name=$(random_string 30)
+ random_file=$(random_string 30)
+ run_podman run --name $random_name $IMAGE sh -c "touch /tmp/$random_file && touch /tmp/${random_file}2 && mkdir /emptydir"
+
+ # check completion for podman cp
+ run_completion cp ""
+ assert "$output" =~ ".*^$random_name\:\$.*" "podman cp suggest container names"
+
+ run_completion cp "$random_name:"
+ assert "$output" =~ ".*^$random_name\:/etc/\$.*" "podman cp suggest paths in container"
+
+ run_completion cp "$random_name:/tmp"
+ assert "$output" =~ ".*^$random_name\:/tmp/$random_file\$.*" "podman cp suggest custom file in container"
+
+ run_completion cp "$random_name:/tmp/$random_file"
+ assert "$output" =~ ".*^$random_name\:/tmp/$random_file\$.*" "podman cp suggest /tmp/$random_file file in container"
+ assert "$output" =~ ".*^$random_name\:/tmp/${random_file}2\$.*" "podman cp suggest /tmp/${random_file}2 file in container"
+
+ run_completion cp "$random_name:/emptydir"
+ assert "$output" =~ ".*^$random_name\:/emptydir/\$.*ShellCompDirectiveNoSpace" "podman cp suggest empty dir with no space directive (:2)"
+
+ # cleanup container
+ run_podman rm $random_name
+}
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 6868f2691..fe9e971fb 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -397,25 +397,25 @@ function _ensure_pod_state() {
for i in {0..5}; do
run_podman pod inspect $1 --format "{{.State}}"
if [[ $output == "$2" ]]; then
- break
+ return
fi
sleep 0.5
done
- is "$output" "$2" "unexpected pod state"
+ die "Timed out waiting for pod $1 to enter state $2"
}
# Wait for the container's (1st arg) running state (2nd arg)
function _ensure_container_running() {
- for i in {0..5}; do
+ for i in {0..20}; do
run_podman container inspect $1 --format "{{.State.Running}}"
if [[ $output == "$2" ]]; then
- break
+ return
fi
sleep 0.5
done
- is "$output" "$2" "unexpected pod state"
+ die "Timed out waiting for container $1 to enter state running=$2"
}
###########################