diff options
33 files changed, 344 insertions, 310 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index c984c8859..cf97f4467 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -101,6 +101,10 @@ ext_svc_check_task: else git reset --hard $CIRRUS_CHANGE_IN_REPO fi + # Some test operations & checks require a git "identity" + _gc='git config --file /root/.gitconfig' + $_gc user.email "TMcTestFace@example.com" + $_gc user.name "Testy McTestface" make install.tools setup_script: &setup '$GOSRC/$SCRIPT_BASE/setup_environment.sh' diff --git a/cmd/podman/containers/clone.go b/cmd/podman/containers/clone.go index 8a1473608..6912da1fc 100644 --- a/cmd/podman/containers/clone.go +++ b/cmd/podman/containers/clone.go @@ -38,6 +38,9 @@ func cloneFlags(cmd *cobra.Command) { runFlagName := "run" flags.BoolVar(&ctrClone.Run, runFlagName, false, "run the new container") + forceFlagName := "force" + flags.BoolVarP(&ctrClone.Force, forceFlagName, "f", false, "force the existing container to be destroyed") + common.DefineCreateFlags(cmd, &ctrClone.CreateOpts, false, true) } func init() { @@ -52,7 +55,7 @@ func init() { func clone(cmd *cobra.Command, args []string) error { switch len(args) { case 0: - return errors.Wrapf(define.ErrInvalidArg, "Must Specify at least 1 argument") + return errors.Wrapf(define.ErrInvalidArg, "must specify at least 1 argument") case 2: ctrClone.CreateOpts.Name = args[1] case 3: @@ -68,6 +71,10 @@ func clone(cmd *cobra.Command, args []string) error { ctrClone.RawImageName = rawImageName } } + if ctrClone.Force && !ctrClone.Destroy { + return errors.Wrapf(define.ErrInvalidArg, "cannot set --force without --destroy") + } + ctrClone.ID = args[0] ctrClone.CreateOpts.IsClone = true rep, err := registry.ContainerEngine().ContainerClone(registry.GetContext(), ctrClone) diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 906a898b2..a7d0f7fa1 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -41,6 +41,11 @@ cp hack/podman-registry /bin # Make sure cni network plugins directory exists mkdir -p /etc/cni/net.d +# Some test operations & checks require a git "identity" +_gc='git config --file /root/.gitconfig' +$_gc user.email "TMcTestFace@example.com" +$_gc user.name "Testy McTestface" + # Ensure that all lower-level contexts and child-processes have # ready access to higher level orchestration (e.g Cirrus-CI) # variables. diff --git a/docs/source/markdown/podman-container-clone.1.md b/docs/source/markdown/podman-container-clone.1.md index 7d5e1c262..69423113d 100644 --- a/docs/source/markdown/podman-container-clone.1.md +++ b/docs/source/markdown/podman-container-clone.1.md @@ -125,6 +125,10 @@ If none are specified, the original container's CPU memory nodes are used. Remove the original container that we are cloning once used to mimic the configuration. +#### **--force**, **-f** + +Force removal of the original container that we are cloning. Can only be used in conjunction with **--destroy**. + #### **--memory**, **-m**=*limit* Memory limit (format: `<number>[<unit>]`, where unit = b (bytes), k (kilobytes), m (megabytes), or g (gigabytes)) diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index 3d1d7a6d2..ae60e5b96 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -477,4 +477,5 @@ type ContainerCloneOptions struct { Image string RawImageName string Run bool + Force bool } diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 46ef01b80..b56c36015 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -1630,7 +1630,7 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti if ctrCloneOpts.Destroy { var time *uint - err := ic.Libpod.RemoveContainer(context.Background(), c, false, false, time) + err = ic.Libpod.RemoveContainer(context.Background(), c, ctrCloneOpts.Force, false, time) if err != nil { return nil, err } diff --git a/test/e2e/container_clone_test.go b/test/e2e/container_clone_test.go index 1d5944d1a..1ff4b3b5f 100644 --- a/test/e2e/container_clone_test.go +++ b/test/e2e/container_clone_test.go @@ -235,4 +235,36 @@ var _ = Describe("Podman container clone", func() { Expect(ctrInspect.InspectContainerToJSON()[0].HostConfig.NetworkMode).Should(ContainSubstring("container:")) }) + + It("podman container clone --destroy --force test", func() { + create := podmanTest.Podman([]string{"create", ALPINE}) + create.WaitWithDefaultTimeout() + Expect(create).To(Exit(0)) + clone := podmanTest.Podman([]string{"container", "clone", "--destroy", create.OutputToString()}) + clone.WaitWithDefaultTimeout() + Expect(clone).To(Exit(0)) + + inspect := podmanTest.Podman([]string{"inspect", create.OutputToString()}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).ToNot(Exit(0)) + + run := podmanTest.Podman([]string{"run", "-dt", ALPINE}) + run.WaitWithDefaultTimeout() + Expect(run).To(Exit(0)) + clone = podmanTest.Podman([]string{"container", "clone", "--destroy", "-f", run.OutputToString()}) + clone.WaitWithDefaultTimeout() + Expect(clone).To(Exit(0)) + + inspect = podmanTest.Podman([]string{"inspect", run.OutputToString()}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).ToNot(Exit(0)) + + run = podmanTest.Podman([]string{"run", "-dt", ALPINE}) + run.WaitWithDefaultTimeout() + Expect(run).To(Exit(0)) + clone = podmanTest.Podman([]string{"container", "clone", "-f", run.OutputToString()}) + clone.WaitWithDefaultTimeout() + Expect(clone).ToNot(Exit(0)) + + }) }) diff --git a/test/system/000-TEMPLATE b/test/system/000-TEMPLATE index 85e25e921..a6a9ca141 100644 --- a/test/system/000-TEMPLATE +++ b/test/system/000-TEMPLATE @@ -10,7 +10,7 @@ load helpers @test "podman subcmd - description of this particular test" { args="some sort of argument list" run_podman subcmd $args - is "$output" "what we expect" "output from 'podman subcmd $args'" + assert "$output" == "what we expect" "output from 'podman subcmd $args'" } # vim: filetype=sh @@ -66,7 +66,7 @@ function teardown() { # FIXME: example of dprint. This will trigger if PODMAN_TEST_DEBUG=FOO # FIXME: ...or anything that matches the name assigned in the @test line. dprint "podman logs $cid -> '$output'" - is "$output" "what are we expecting?" "description of this check" + assert "$output" == "what are we expecting?" "description of this check" # Clean up run_podman rm $cid @@ -90,7 +90,7 @@ size | -\\\?[0-9]\\\+ run_podman history --format json $IMAGE # FIXME: parse_table is what does all the work, giving us test cases. - parse_table "$tests" | while read field expect; do + while read field expect; do # FIXME: this shows a drawback of BATS and bash: we can't include '|' # FIXME: in the table, but we need to because some images don't # FIXME: have a CID. So, yeah, this is ugly -- but rare. @@ -104,10 +104,10 @@ size | -\\\?[0-9]\\\+ # FIXME: please be sure to note the third field! # FIXME: that's the test name. Make it something useful! Include # FIXME: loop variables whenever possible. Don't just say "my test" - is "$actual" "$expect\$" "jq .[$i].$field" + assert "$actual" =~ "$expect\$" "jq .[$i].$field" i=$(expr $i + 1) done - done + done < <(parse_table "$tests") } diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats index 582efa058..0d2a99d4b 100644 --- a/test/system/001-basic.bats +++ b/test/system/001-basic.bats @@ -28,9 +28,7 @@ function setup() { # Test that build date is reasonable, e.g. after 2019-01-01 local built=$(expr "$output" : ".*Built: \+\(.*\)" | head -n1) local built_t=$(date --date="$built" +%s) - if [ $built_t -lt 1546300800 ]; then - die "Preposterous 'Built' time in podman version: '$built'" - fi + assert "$built_t" -gt 1546300800 "Preposterous 'Built' time in podman version" } @test "podman info" { @@ -114,29 +112,25 @@ See 'podman version --help'" "podman version --remote" # By default, podman should include '--remote' in its help output run_podman --help - is "$output" ".* --remote " "podman --help includes the --remote option" + assert "$output" =~ " --remote " "podman --help includes the --remote option" # When it detects CONTAINER_HOST or _CONNECTION, --remote is not an option CONTAINER_HOST=foobar run_podman --help - if grep -- " --remote " <<<"$output"; then - die "podman --help, with CONTAINER_HOST set, is showing --remote" - fi + assert "$output" !~ " --remote " \ + "podman --help, with CONTAINER_HOST set, should not show --remote" CONTAINER_CONNECTION=foobar run_podman --help - if grep -- " --remote " <<<"$output"; then - die "podman --help, with CONTAINER_CONNECTION set, is showing --remote" - fi + assert "$output" !~ " --remote " \ + "podman --help, with CONTAINER_CONNECTION set, should not show --remote" # When it detects --url or --connection, --remote is not an option run_podman --url foobar --help - if grep -- " --remote " <<<"$output"; then - die "podman --help, with --url set, is showing --remote" - fi + assert "$output" !~ " --remote " \ + "podman --help, with --url set, should not show --remote" run_podman --connection foobar --help - if grep -- " --remote " <<<"$output"; then - die "podman --help, with --connection set, is showing --remote" - fi + assert "$output" !~ " --remote " \ + "podman --help, with --connection set, should not show --remote" } # Check that just calling "podman-remote" prints the usage message even diff --git a/test/system/015-help.bats b/test/system/015-help.bats index 4eeea85bf..5757d51dc 100644 --- a/test/system/015-help.bats +++ b/test/system/015-help.bats @@ -27,7 +27,7 @@ function check_help() { # The line immediately after 'Usage:' gives us a 1-line synopsis usage=$(echo "$full_help" | grep -A1 '^Usage:' | tail -1) - [ -n "$usage" ] || die "podman $cmd: no Usage message found" + 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 @@ -42,14 +42,12 @@ function check_help() { fi # We had someone write upper-case '[OPTIONS]' once. Prevent it. - if expr "$usage" : '.*\[OPTION' >/dev/null; then - die "'options' string must be lower-case in usage: $usage" - fi + assert "$usage" !~ '\[OPTION' \ + "'options' string must be lower-case in usage" # We had someone do 'podman foo ARG [options]' one time. Yeah, no. - if expr "$usage" : '.*[A-Z].*\[option' >/dev/null; then - die "'options' must precede arguments in usage: $usage" - fi + 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, @@ -169,16 +167,15 @@ function check_help() { # This can happen if the output of --help changes, such as between # the old command parser and cobra. - [ $count -gt 0 ] || \ - die "Internal error: no commands found in 'podman help $@' list" + 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 - if [[ -z ${found[$i]} ]]; then - die "Internal error: '$i' subtest did not trigger" - fi + assert "${found[$i]}" != "" \ + "Internal error: '$i' subtest did not trigger" done fi } diff --git a/test/system/030-run.bats b/test/system/030-run.bats index aba18badb..526003c2d 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -78,12 +78,11 @@ echo $rand | 0 | $rand skip_if_remote "TODO Fix this for remote case" run_podman run --rm --uidmap 0:100:10000 $IMAGE mount - run grep /sys/kernel <(echo "$output") - is "$output" "" "unwanted /sys/kernel in 'mount' output" + assert "$output" !~ /sys/kernel "unwanted /sys/kernel in 'mount' output" run_podman run --rm --net host --uidmap 0:100:10000 $IMAGE mount - run grep /sys/kernel <(echo "$output") - is "$output" "" "unwanted /sys/kernel in 'mount' output (with --net=host)" + assert "$output" !~ /sys/kernel \ + "unwanted /sys/kernel in 'mount' output (with --net=host)" } # 'run --rm' goes through different code paths and may lose exit status. @@ -692,10 +691,8 @@ json-file | f # This operation should take # exactly 10 seconds. Give it some leeway. delta_t=$(( $t1 - $t0 )) - [ $delta_t -gt 8 ] ||\ - die "podman stop: ran too quickly! ($delta_t seconds; expected >= 10)" - [ $delta_t -le 14 ] ||\ - die "podman stop: took too long ($delta_t seconds; expected ~10)" + assert "$delta_t" -gt 8 "podman stop: ran too quickly!" + assert "$delta_t" -le 14 "podman stop: took too long" run_podman rm $cid } @@ -753,34 +750,40 @@ EOF @test "podman run defaultenv" { run_podman run --rm $IMAGE printenv - is "$output" ".*TERM=xterm" "output matches TERM" - is "$output" ".*container=podman" "output matches container=podman" + assert "$output" =~ "TERM=xterm" "env includes TERM" + assert "$output" =~ "container=podman" "env includes container=podman" run_podman run --unsetenv=TERM --rm $IMAGE printenv - is "$output" ".*container=podman" "output matches container=podman" - run grep TERM <<<$output - is "$output" "" "unwanted TERM environment variable despite --unsetenv=TERM" + assert "$output" =~ "container=podman" "env includes container=podman" + assert "$output" != "TERM" "unwanted TERM environment variable despite --unsetenv=TERM" run_podman run --unsetenv-all --rm $IMAGE /bin/printenv - run grep TERM <<<$output - is "$output" "" "unwanted TERM environment variable despite --unsetenv-all" - run grep container <<<$output - is "$output" "" "unwanted container environment variable despite --unsetenv-all" - run grep PATH <<<$output - is "$output" "" "unwanted PATH environment variable despite --unsetenv-all" + for v in TERM container PATH; do + assert "$output" !~ "$v" "variable present despite --unsetenv-all" + done run_podman run --unsetenv-all --env TERM=abc --rm $IMAGE /bin/printenv - is "$output" ".*TERM=abc" "missing TERM environment variable despite TERM being set on commandline" + assert "$output" =~ "TERM=abc" \ + "missing TERM environment variable despite TERM being set on commandline" } @test "podman run - no /etc/hosts" { + if [[ -z "$container" ]]; then + skip "Test is too dangerous to run in a non-container environment" + fi skip_if_rootless "cannot move /etc/hosts file as a rootless user" - tmpfile=$PODMAN_TMPDIR/hosts - mv /etc/hosts $tmpfile + + local hosts_tmp=/etc/hosts.RENAME-ME-BACK-TO-JUST-HOSTS + if [[ -e $hosts_tmp ]]; then + die "Internal error: leftover backup hosts file: $hosts_tmp" + fi + mv /etc/hosts $hosts_tmp run_podman '?' run --rm --add-host "foo.com:1.2.3.4" $IMAGE cat "/etc/hosts" - mv $tmpfile /etc/hosts - is "$status" 0 "podman run without /etc/hosts file should work" - is "$output" "1.2.3.4 foo.com.*" "users can add hosts even without /etc/hosts" + mv $hosts_tmp /etc/hosts + assert "$status" = 0 \ + "podman run without /etc/hosts file should work" + assert "$output" =~ "^1\.2\.3\.4 foo.com.*" \ + "users can add hosts even without /etc/hosts" } # rhbz#1854566 : $IMAGE has incorrect permission 555 on the root '/' filesystem diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats index e38cdb383..97d984ef1 100644 --- a/test/system/035-logs.bats +++ b/test/system/035-logs.bats @@ -224,9 +224,8 @@ $s_after" retries=$((retries - 1)) sleep 0.1 done - if [[ $retries -eq 0 ]]; then - die "Timed out waiting for before&after in podman logs: $output" - fi + assert $retries -gt 0 \ + "Timed out waiting for before&after in podman logs: $output" run_podman logs --until $before test is "$output" "" "podman logs --until before" diff --git a/test/system/040-ps.bats b/test/system/040-ps.bats index 6fc0b9b6e..f450caf7c 100644 --- a/test/system/040-ps.bats +++ b/test/system/040-ps.bats @@ -98,9 +98,8 @@ RUN sleep 30 EOF local t1=$SECONDS local delta_t=$((t1 - t0)) - if [[ $delta_t -gt 10 ]]; then - die "podman build did not get killed within 10 seconds (actual time: $delta_t seconds)" - fi + assert $delta_t -le 10 \ + "podman build did not get killed within 10 seconds" run_podman ps -a is "${#lines[@]}" "1" "podman ps -a does not see buildah containers" diff --git a/test/system/045-start.bats b/test/system/045-start.bats index 31e924ca5..ad8483bba 100644 --- a/test/system/045-start.bats +++ b/test/system/045-start.bats @@ -21,9 +21,8 @@ load helpers is "$output" ".*$cid_none_implicit" "started: container with no --restart" is "$output" ".*$cid_none_explicit" "started: container with --restart=no" is "$output" ".*$cid_on_failure" "started: container with --restart=on-failure" - if [[ $output =~ $cid_always ]]; then - die "podman start --all restarted a running container" - fi + assert "$output" !~ "$cid_always" \ + "podman start --all should not restart a running container" run_podman wait $cid_none_implicit $cid_none_explicit $cid_on_failure diff --git a/test/system/050-stop.bats b/test/system/050-stop.bats index 7dd8f98e8..c2dfba84d 100644 --- a/test/system/050-stop.bats +++ b/test/system/050-stop.bats @@ -22,10 +22,8 @@ load helpers # The initial SIGTERM is ignored, so this operation should take # exactly 10 seconds. Give it some leeway. delta_t=$(( $t1 - $t0 )) - [ $delta_t -gt 8 ] ||\ - die "podman stop: ran too quickly! ($delta_t seconds; expected >= 10)" - [ $delta_t -le 14 ] ||\ - die "podman stop: took too long ($delta_t seconds; expected ~10)" + assert $delta_t -gt 8 "podman stop: ran too quickly!" + assert $delta_t -le 14 "podman stop: took too long" run_podman rm $cid } @@ -103,8 +101,7 @@ load helpers # The 'stop' command should return almost instantaneously delta_t=$(( $t1 - $t0 )) - [ $delta_t -le 2 ] ||\ - die "podman stop: took too long ($delta_t seconds; expected <= 2)" + assert $delta_t -le 2 "podman stop: took too long" run_podman rm $cid done @@ -138,9 +135,7 @@ load helpers break fi timeout=$((timeout - 1)) - if [[ $timeout -eq 0 ]]; then - die "Timed out waiting for container to receive SIGERM" - fi + assert $timeout -gt 0 "Timed out waiting for container to receive SIGTERM" sleep 0.5 done @@ -154,9 +149,7 @@ load helpers # Time check: make sure we were able to run 'ps' before the container # exited. If this takes too long, it means ps had to wait for lock. local delta_t=$(( $SECONDS - t0 )) - if [[ $delta_t -gt 5 ]]; then - die "Operations took too long ($delta_t seconds)" - fi + assert $delta_t -le 5 "Operations took too long" run_podman kill stopme run_podman wait stopme diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats index 780fc6737..fe9292fd0 100644 --- a/test/system/065-cp.bats +++ b/test/system/065-cp.bats @@ -589,20 +589,22 @@ ${randomcontent[1]}" "$description" # RUNNING container # NOTE: /dest does not exist yet but is expected to be created during copy run_podman cp cpcontainer:/tmp/sub/weirdlink $destdir/dest - run cat $destdir/dest/containerfile0 $destdir/dest/containerfile1 - is "${lines[0]}" "${randomcontent[0]}" "eval symlink - running container" - is "${lines[1]}" "${randomcontent[1]}" "eval symlink - running container" + for i in 0 1; do + assert "$(< $destdir/dest/containerfile$i)" = "${randomcontent[$i]}" \ + "eval symlink - running container - file $i/1" + done run_podman kill cpcontainer run_podman rm -t 0 -f cpcontainer - run rm -rf $srcdir/dest + rm -rf $srcdir/dest # CREATED container run_podman create --name cpcontainer $cpimage run_podman cp cpcontainer:/tmp/sub/weirdlink $destdir/dest - run cat $destdir/dest/containerfile0 $destdir/dest/containerfile1 - is "${lines[0]}" "${randomcontent[0]}" "eval symlink - created container" - is "${lines[1]}" "${randomcontent[1]}" "eval symlink - created container" + for i in 0 1; do + assert "$(< $destdir/dest/containerfile$i)" = "${randomcontent[$i]}" \ + "eval symlink - created container - file $i/1" + done run_podman rm -t 0 -f cpcontainer run_podman rmi $cpimage } @@ -924,20 +926,16 @@ ${randomcontent[1]}" "$description" # Copy file. $PODMAN cp cpcontainer:/tmp/file.txt - > $srcdir/stdout.tar - if [ $? -ne 0 ]; then - die "Command failed: podman cp ... - | cat" - fi tar xvf $srcdir/stdout.tar -C $srcdir - is "$(< $srcdir/file.txt)" "$rand_content" - run 1 ls $srcdir/empty.txt + is "$(< $srcdir/file.txt)" "$rand_content" "File contents: file.txt" + if [[ -e "$srcdir/empty.txt" ]]; then + die "File should not exist, but does: empty.txt" + fi rm -f $srcdir/* # Copy directory. $PODMAN cp cpcontainer:/tmp - > $srcdir/stdout.tar - if [ $? -ne 0 ]; then - die "Command failed: podman cp ... - | cat : $output" - fi tar xvf $srcdir/stdout.tar -C $srcdir is "$(< $srcdir/tmp/file.txt)" "$rand_content" diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 7466c3b74..b7e0ab447 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -60,21 +60,18 @@ EOF # Now confirm that each volume got a unique device ID run_podman run --rm build_test stat -c '%D' / /a /a/b /a/b/c /\[ /\[/etc /\[/etc/foo, /etc /etc/bar\] # First, the non-volumes should all be the same... - is "${lines[0]}" "${lines[1]}" "devnum( / ) = devnum( /a )" - is "${lines[0]}" "${lines[2]}" "devnum( / ) = devnum( /a/b )" - is "${lines[0]}" "${lines[4]}" "devnum( / ) = devnum( /[ )" - is "${lines[0]}" "${lines[5]}" "devnum( / ) = devnum( /[etc )" - is "${lines[0]}" "${lines[7]}" "devnum( / ) = devnum( /etc )" - is "${lines[6]}" "${lines[8]}" "devnum( /[etc/foo, ) = devnum( /etc/bar] )" + assert "${lines[0]}" = "${lines[1]}" "devnum( / ) = devnum( /a )" + assert "${lines[0]}" = "${lines[2]}" "devnum( / ) = devnum( /a/b )" + assert "${lines[0]}" = "${lines[4]}" "devnum( / ) = devnum( /[ )" + assert "${lines[0]}" = "${lines[5]}" "devnum( / ) = devnum( /[etc )" + assert "${lines[0]}" = "${lines[7]}" "devnum( / ) = devnum( /etc )" + assert "${lines[6]}" = "${lines[8]}" "devnum( /[etc/foo, ) = devnum( /etc/bar] )" # ...then, each volume should be different - if [[ "${lines[0]}" = "${lines[3]}" ]]; then - die "devnum( / ) (${lines[0]}) = devnum( volume0 ) (${lines[3]}) -- they should differ" - fi - if [[ "${lines[0]}" = "${lines[6]}" ]]; then - die "devnum( / ) (${lines[0]}) = devnum( volume1 ) (${lines[6]}) -- they should differ" - fi + assert "${lines[0]}" != "${lines[3]}" "devnum( / ) != devnum( volume0 )" + assert "${lines[0]}" != "${lines[6]}" "devnum( / ) != devnum( volume1 )" + # FIXME: is this expected? I thought /a/b/c and /[etc/foo, would differ - is "${lines[3]}" "${lines[6]}" "devnum( volume0 ) = devnum( volume1 )" + assert "${lines[3]}" = "${lines[6]}" "devnum( volume0 ) = devnum( volume1 )" run_podman rmi -f build_test } @@ -106,7 +103,7 @@ EOF rand_content=$(random_string 50) tmpdir=$PODMAN_TMPDIR/build-test - run mkdir -p $tmpdir + mkdir -p $tmpdir containerfile=$tmpdir/Containerfile cat >$containerfile <<EOF FROM $IMAGE @@ -122,7 +119,7 @@ EOF # Test on the CLI and via containers.conf tmpdir=$PODMAN_TMPDIR/build-test - run mkdir -p $tmpdir + mkdir -p $tmpdir containerfile=$tmpdir/Containerfile cat >$containerfile <<EOF FROM $IMAGE @@ -146,10 +143,10 @@ EOF @test "podman build - cache (#3920)" { # Make an empty test directory, with a subdirectory used for tar tmpdir=$PODMAN_TMPDIR/build-test - mkdir -p $tmpdir/subtest || die "Could not mkdir $tmpdir/subtest" + mkdir -p $tmpdir/subtest echo "This is the ORIGINAL file" > $tmpdir/subtest/myfile1 - run tar -C $tmpdir -cJf $tmpdir/myfile.tar.xz subtest + tar -C $tmpdir -cJf $tmpdir/myfile.tar.xz subtest cat >$tmpdir/Dockerfile <<EOF FROM $IMAGE @@ -169,7 +166,7 @@ EOF # Step 2: Recreate the tarfile, with new content. Rerun podman build. echo "This is a NEW file" >| $tmpdir/subtest/myfile2 - run tar -C $tmpdir -cJf $tmpdir/myfile.tar.xz subtest + tar -C $tmpdir -cJf $tmpdir/myfile.tar.xz subtest run_podman build -t build_test -f $tmpdir/Dockerfile $tmpdir is "$output" ".*COMMIT" "COMMIT seen in log" @@ -371,9 +368,8 @@ EOF -t build_test -f build-test/Containerfile build-test local iid="${lines[-1]}" - if [[ $output =~ missing.*build.argument ]]; then - die "podman did not see the given --build-arg(s)" - fi + assert "$output" !~ "missing.*build.argument" \ + "podman did not see the given --build-arg(s)" # Make sure 'podman build' had the secret mounted is "$output" ".*$secret_contents.*" "podman build has /run/secrets mounted" @@ -449,9 +445,7 @@ EOF run_podman image inspect build_test # (Assert that output is formatted, not a one-line blob: #8011) - if [[ "${#lines[*]}" -lt 10 ]]; then - die "Output from 'image inspect' is only ${#lines[*]} lines; see #8011" - fi + assert "${#lines[*]}" -ge 10 "Output from 'image inspect'; see #8011" tests=" Env[1] | MYENV1=$s_env1 @@ -591,12 +585,11 @@ EOF for f in ${files[@]}; do if [[ $f =~ ^- ]]; then f=${f##-} - if [[ $output =~ $f ]]; then - die "File '$f' found in image; it should have been ignored via $ignorefile" - fi + assert "$output" !~ "$f" \ + "File '$f' should have been ignored via $ignorefile" else - is "$output" ".*$newdir/$f" \ - "File '$f' should exist in container (no match in $ignorefile)" + assert "$output" =~ "$newdir/$f" \ + "File '$f' should exist in container (no match in $ignorefile)" fi done @@ -727,7 +720,7 @@ a${random3}z" @test "podman build --layers test" { rand_content=$(random_string 50) tmpdir=$PODMAN_TMPDIR/build-test - run mkdir -p $tmpdir + mkdir -p $tmpdir containerfile=$tmpdir/Containerfile cat >$containerfile <<EOF FROM $IMAGE @@ -870,8 +863,7 @@ FROM $IMAGE EOF run_podman build -t build_test --format=docker --logfile=$tmpdir/logfile $tmpbuilddir - run cat $tmpdir/logfile - is "$output" ".*COMMIT" "COMMIT seen in log" + assert "$(< $tmpdir/logfile)" =~ "COMMIT" "COMMIT seen in log" run_podman rmi -f build_test } diff --git a/test/system/090-events.bats b/test/system/090-events.bats index dcbe62da7..128802360 100644 --- a/test/system/090-events.bats +++ b/test/system/090-events.bats @@ -126,8 +126,7 @@ function _events_disjunctive_filters() { events_logfile_path="$events_file" EOF CONTAINERS_CONF="$containersconf" run_podman --events-backend=file pull $IMAGE - run cat $events_file - is "$output" ".*\"Name\":\"$IMAGE" "test" + assert "$(< $events_file)" =~ "\"Name\":\"$IMAGE\"" "Image found in events" } function _populate_events_file() { diff --git a/test/system/120-load.bats b/test/system/120-load.bats index 8bf785081..45e0b3362 100644 --- a/test/system/120-load.bats +++ b/test/system/120-load.bats @@ -52,9 +52,7 @@ verify_iid_and_name() { # which redirects stdout and stderr. Here we need to guarantee # that podman's stdout is a pipe, not any other form of redirection $PODMAN save --format oci-archive $fqin | cat >$archive - if [ "$status" -ne 0 ]; then - die "Command failed: podman save ... | cat" - fi + assert "$?" -eq 0 "Command failed: podman save ... | cat" # Make sure we can reload it run_podman rmi $fqin @@ -265,9 +263,7 @@ verify_iid_and_name() { # which redirects stdout and stderr. Here we need to guarantee # that podman's stdout is a pipe, not any other form of redirection $PODMAN save -m $img1 $img2 | cat >$archive - if [ "$status" -ne 0 ]; then - die "Command failed: podman save ... | cat" - fi + assert "$?" -eq 0 "Command failed: podman save ... | cat" run_podman rmi -f $img1 $img2 run_podman load -i $archive @@ -284,7 +280,7 @@ verify_iid_and_name() { # Create a tarball, unpack it and make sure the layers are uncompressed. run_podman save -o $archive --format oci-archive --uncompressed $IMAGE - run tar -C $untar -xvf $archive + tar -C $untar -xvf $archive run file $untar/blobs/sha256/* is "$output" ".*POSIX tar archive" "layers are uncompressed" } diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats index d0088b994..571d8767e 100644 --- a/test/system/160-volumes.bats +++ b/test/system/160-volumes.bats @@ -282,9 +282,7 @@ EOF # (Assert that output is formatted, not a one-line blob: #8011) run_podman volume inspect ${v[1]} - if [[ "${#lines[*]}" -lt 10 ]]; then - die "Output from 'volume inspect' is only ${#lines[*]} lines; see #8011" - fi + assert "${#lines[*]}" -ge 10 "Output from 'volume inspect'; see #8011" # Run two containers: one mounting v1, one mounting v2 & v3 run_podman run --name c1 --volume ${v[1]}:/vol1 $IMAGE date diff --git a/test/system/180-blkio.bats b/test/system/180-blkio.bats index 7999c9ec5..7b7fb0201 100644 --- a/test/system/180-blkio.bats +++ b/test/system/180-blkio.bats @@ -31,7 +31,8 @@ function teardown() { losetup -f ${lofile} run losetup -l --noheadings --output BACK-FILE,NAME,MAJ:MIN - is "$output" ".\+" "Empty output from losetup" + assert "$status" -eq 0 "losetup: status" + assert "$output" != "" "losetup: output" lodevice=$(awk "\$1 == \"$lofile\" { print \$2 }" <<<"$output") lomajmin=$(awk "\$1 == \"$lofile\" { print \$3 }" <<<"$output") diff --git a/test/system/190-run-ipcns.bats b/test/system/190-run-ipcns.bats index 9327d8ec7..db1d716d7 100644 --- a/test/system/190-run-ipcns.bats +++ b/test/system/190-run-ipcns.bats @@ -7,30 +7,25 @@ load helpers @test "podman --ipc=host" { - run readlink /proc/self/ns/ipc - hostipc=$output + hostipc="$(readlink /proc/self/ns/ipc)" run_podman run --rm --ipc=host $IMAGE readlink /proc/self/ns/ipc is "$output" "$hostipc" "HostIPC and container IPC should be same" } @test "podman --ipc=none" { - run readlink /proc/self/ns/ipc - hostipc=$output + hostipc="$(readlink /proc/self/ns/ipc)" run_podman run --rm --ipc=none $IMAGE readlink /proc/self/ns/ipc - if [[ $output == "$hostipc" ]]; then - die "hostipc and containeripc should be different" - fi + assert "$output" != "$hostipc" "containeripc should != hostipc" + run_podman 1 run --rm --ipc=none $IMAGE ls /dev/shm is "$output" "ls: /dev/shm: No such file or directory" "Should fail with missing /dev/shm" } @test "podman --ipc=private" { - run readlink /proc/self/ns/ipc - hostipc=$output + hostipc="$(readlink /proc/self/ns/ipc)" run_podman run -d --ipc=private --name test $IMAGE sleep 100 - if [[ $output == "$hostipc" ]]; then - die "hostipc and containeripc should be different" - fi + assert "$output" != "$hostipc" "containeripc should != hostipc" + run_podman 125 run --ipc=container:test --rm $IMAGE readlink /proc/self/ns/ipc is "$output" ".*is not allowed: non-shareable IPC (hint: use IpcMode:shareable for the donor container)" "Containers should not share private ipc namespace" run_podman stop -t 0 test @@ -38,31 +33,26 @@ load helpers } @test "podman --ipc=shareable" { - run readlink /proc/self/ns/ipc - hostipc=$output + hostipc="$(readlink /proc/self/ns/ipc)" run_podman run -d --ipc=shareable --name test $IMAGE sleep 100 - if [[ $output == "$hostipc" ]]; then - die "hostipc and containeripc should be different" - fi + assert "$output" != "$hostipc" "containeripc(shareable) should != hostipc" + run_podman run --ipc=container:test --rm $IMAGE readlink /proc/self/ns/ipc - if [[ $output == "$hostipc" ]]; then - die "hostipc and containeripc should be different" - fi + assert "$output" != "$hostipc" "containeripc(:test) should != hostipc" + run_podman stop -t 0 test run_podman rm test } @test "podman --ipc=container@test" { - run readlink /proc/self/ns/ipc - hostipc=$output + hostipc="$(readlink /proc/self/ns/ipc)" run_podman run -d --name test $IMAGE sleep 100 run_podman exec test readlink /proc/self/ns/ipc - if [[ $output == "$hostipc" ]]; then - die "hostipc and containeripc should be different" - fi + assert "$output" != "$hostipc" "containeripc(exec) should != hostipc" + testipc=$output run_podman run --ipc=container:test --rm $IMAGE readlink /proc/self/ns/ipc - is "$output" "$testipc" "Containers should share ipc namespace" + assert "$output" = "$testipc" "Containers should share ipc namespace" run_podman stop -t 0 test run_podman rm test } diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index f5fe41924..56449dcad 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -59,7 +59,7 @@ function teardown() { skip_if_remote "CONTAINERS_CONF only effects server side" image="i.do/not/exist:image" tmpdir=$PODMAN_TMPDIR/pod-test - run mkdir -p $tmpdir + mkdir -p $tmpdir containersconf=$tmpdir/containers.conf cat >$containersconf <<EOF [engine] @@ -86,9 +86,7 @@ EOF # (Assert that output is formatted, not a one-line blob: #8021) run_podman pod inspect $podname - if [[ "${#lines[*]}" -lt 10 ]]; then - die "Output from 'pod inspect' is only ${#lines[*]} lines; see #8011" - fi + assert "${#lines[*]}" -ge 10 "Output from 'pod inspect'; see #8011" # Randomly-assigned port in the 5xxx range port=$(random_free_port) @@ -322,10 +320,11 @@ EOF run_podman --noout pod create --name $pod_name --infra-name "$infra_name" --infra-image "$infra_image" is "$output" "" "output from pod create should be empty" - run_podman '?' pod create --infra-name "$infra_name" - if [ $status -eq 0 ]; then - die "Podman should fail when user try to create two pods with the same infra-name value" - fi + + run_podman 125 pod create --infra-name "$infra_name" + assert "$output" =~ "^Error: .*: the container name \"$infra_name\" is already in use by .* You have to remove that container to be able to reuse that name.: that name is already in use" \ + "Trying to create two pods with same infra-name" + run_podman pod rm -f $pod_name run_podman rmi $infra_image } diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats index 6c72e14e8..d0da654ad 100644 --- a/test/system/250-systemd.bats +++ b/test/system/250-systemd.bats @@ -18,9 +18,15 @@ function setup() { } function teardown() { - run '?' systemctl stop "$SERVICE_NAME" - rm -f "$UNIT_FILE" - systemctl daemon-reload + if [[ -e "$UNIT_FILE" ]]; then + run systemctl stop "$SERVICE_NAME" + if [ $status -ne 0 ]; then + echo "# WARNING: systemctl stop failed in teardown: $output" >&3 + fi + + rm -f "$UNIT_FILE" + systemctl daemon-reload + fi run_podman rmi -a basic_teardown @@ -36,41 +42,23 @@ function service_setup() { # Also test enabling services (see #12438). run systemctl enable "$SERVICE_NAME" - if [ $status -ne 0 ]; then - die "Error enabling systemd unit $SERVICE_NAME, output: $output" - fi + assert $status -eq 0 "Error enabling systemd unit $SERVICE_NAME: $output" run systemctl start "$SERVICE_NAME" - if [ $status -ne 0 ]; then - die "Error starting systemd unit $SERVICE_NAME, output: $output" - fi + assert $status -eq 0 "Error starting systemd unit $SERVICE_NAME: $output" run systemctl status "$SERVICE_NAME" - if [ $status -ne 0 ]; then - die "Non-zero status of systemd unit $SERVICE_NAME, output: $output" - fi + assert $status -eq 0 "systemctl status $SERVICE_NAME: $output" } # Helper to stop a systemd service running a container function service_cleanup() { local status=$1 run systemctl stop "$SERVICE_NAME" - if [ $status -ne 0 ]; then - die "Error stopping systemd unit $SERVICE_NAME, output: $output" - fi + assert $status -eq 0 "Error stopping systemd unit $SERVICE_NAME: $output" run systemctl disable "$SERVICE_NAME" - if [ $status -ne 0 ]; then - die "Error disbling systemd unit $SERVICE_NAME, output: $output" - fi - - if [[ -z "$status" ]]; then - run systemctl is-active "$SERVICE_NAME" - if [ $status -ne 0 ]; then - die "Error checking stauts of systemd unit $SERVICE_NAME, output: $output" - fi - is "$output" "$status" "$SERVICE_NAME not in expected state" - fi + assert $status -eq 0 "Error disabling systemd unit $SERVICE_NAME: $output" rm -f "$UNIT_FILE" systemctl daemon-reload @@ -230,27 +218,13 @@ LISTEN_FDNAMES=listen_fdnames" | sort) INSTANCE="$SERVICE_NAME@1.service" run systemctl start "$INSTANCE" - if [ $status -ne 0 ]; then - die "Error starting systemd unit $INSTANCE, output: $output" - fi + assert $status -eq 0 "Error starting systemd unit $INSTANCE: $output" run systemctl status "$INSTANCE" - if [ $status -ne 0 ]; then - die "Non-zero status of systemd unit $INSTANCE, output: $output" - fi + assert $status -eq 0 "systemctl status $INSTANCE: $output" run systemctl stop "$INSTANCE" - if [ $status -ne 0 ]; then - die "Error stopping systemd unit $INSTANCE, output: $output" - fi - - if [[ -z "$status" ]]; then - run systemctl is-active "$INSTANCE" - if [ $status -ne 0 ]; then - die "Error checking stauts of systemd unit $INSTANCE, output: $output" - fi - is "$output" "$status" "$INSTANCE not in expected state" - fi + assert $status -eq 0 "Error stopping systemd unit $INSTANCE: $output" rm -f "$TEMPLATE_FILE_PREFIX@.service" systemctl daemon-reload diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats index 5a8bf4218..6cdae2ada 100644 --- a/test/system/255-auto-update.bats +++ b/test/system/255-auto-update.bats @@ -178,9 +178,8 @@ function _confirm_update() { is "$output" "$oldID" "container rolled back to previous image" run_podman container inspect --format "{{.ID}}" $cname - if [[ $output == $containerID ]]; then - die "container has not been restarted during rollback (previous id: $containerID, current id: $output)" - fi + assert "$output" != "$containerID" \ + "container has not been restarted during rollback" } @test "podman auto-update - label io.containers.autoupdate=disabled" { @@ -329,11 +328,9 @@ EOF for cname in "${cnames[@]}"; do run_podman inspect --format "{{.Image}}" $cname if [[ -n "${expect_update[$cname]}" ]]; then - if [[ "$output" == "$img_id" ]]; then - die "$cname: image ID ($output) did not change" - fi + assert "$output" != "$img_id" "$cname: image ID did not change" else - is "$output" "$img_id" "Image should not be changed." + assert "$output" = "$img_id" "Image ID should not be changed." fi done } diff --git a/test/system/400-unprivileged-access.bats b/test/system/400-unprivileged-access.bats index cf0d0e6bf..710ff066c 100644 --- a/test/system/400-unprivileged-access.bats +++ b/test/system/400-unprivileged-access.bats @@ -128,9 +128,7 @@ EOF # number of links, major, and minor (see below for why). Do it all # in one go, to avoid multiple podman-runs run_podman '?' run --rm $IMAGE stat -c'%n:%F:%h:%T:%t' /dev/null ${subset[@]} - if [[ $status -gt 1 ]]; then - die "Unexpected exit status $status: expected 0 or 1" - fi + assert $status -le 1 "stat exit status: expected 0 or 1" local devnull= for result in "${lines[@]}"; do diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats index 056a056f6..21ac4cb8f 100644 --- a/test/system/410-selinux.bats +++ b/test/system/410-selinux.bats @@ -135,9 +135,8 @@ function check_label() { # net NS: do not share context run_podman run --rm --net container:myctr $IMAGE cat -v /proc/self/attr/current - if [[ "$output" = "$context_c1" ]]; then - die "run --net : context ($output) is same as running container (it should not be)" - fi + assert "$output" != "$context_c1" \ + "run --net : context should != context of running container" # The 'myctr2' above was not run with --rm, so it still exists, and # we can't remove the original container until this one is gone. @@ -189,9 +188,8 @@ function check_label() { # Even after #7902, labels (':c123,c456') should be different run_podman run --rm --pod myselinuxpod $IMAGE cat -v /proc/self/attr/current - if [[ "$output" = "$context_c1" ]]; then - die "context ($output) is the same on two separate containers, it should have been different" - fi + assert "$output" != "$context_c1" \ + "context of two separate containers should be different" run_podman pod rm myselinuxpod } diff --git a/test/system/450-interactive.bats b/test/system/450-interactive.bats index b817fe1a7..a642a2e95 100644 --- a/test/system/450-interactive.bats +++ b/test/system/450-interactive.bats @@ -27,9 +27,7 @@ function setup() { retries=5 while [[ ! -e $PODMAN_TEST_PTY ]]; do retries=$(( retries - 1 )) - if [[ $retries -eq 0 ]]; then - die "Timed out waiting for $PODMAN_TEST_PTY" - fi + assert $retries -gt 0 "Timed out waiting for $PODMAN_TEST_PTY" sleep 0.5 done } diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index 78ad3fe04..3bfc58a07 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -6,16 +6,12 @@ load helpers @test "podman network - basic tests" { - heading="*NETWORK*ID*NAME*DRIVER*" + heading="NETWORK *ID *NAME *DRIVER" run_podman network ls - if [[ ${output} != ${heading} ]]; then - die "network ls expected heading is not available" - fi + assert "${lines[0]}" =~ "^$heading\$" "network ls header missing" run_podman network ls --noheading - if [[ ${output} = ${heading} ]]; then - die "network ls --noheading did not remove heading: $output" - fi + assert "$output" !~ "$heading" "network ls --noheading shows header anyway" # check deterministic list order local net1=a-$(random_string 10) @@ -174,9 +170,7 @@ load helpers # (Assert that output is formatted, not a one-line blob: #8011) run_podman network inspect $mynetname - if [[ "${#lines[*]}" -lt 5 ]]; then - die "Output from 'pod inspect' is only ${#lines[*]} lines; see #8011" - fi + assert "${#lines[*]}" -ge 5 "Output from 'pod inspect'; see #8011" run_podman run --rm --network $mynetname $IMAGE ip a is "$output" ".* inet ${mysubnet}\.2/24 brd ${mysubnet}\.255 " \ @@ -265,9 +259,7 @@ load helpers # check that we cannot curl (timeout after 5 sec) run timeout 5 curl -s $SERVER/index.txt - if [ "$status" -ne 124 ]; then - die "curl did not timeout, status code: $status" - fi + assert $status -eq 124 "curl did not time out" fi # reload the network to recreate the iptables rules @@ -366,16 +358,11 @@ load helpers # ipv4 slirp run_podman run --rm --network slirp4netns:enable_ipv6=false $IMAGE cat /etc/resolv.conf - if grep -E "$ipv6_regex" <<< $output; then - die "resolv.conf contains a ipv6 nameserver" - fi + assert "$output" !~ "$ipv6_regex" "resolv.conf should not contain ipv6 nameserver" # ipv6 slirp run_podman run --rm --network slirp4netns:enable_ipv6=true $IMAGE cat /etc/resolv.conf - # "is" does not like the ipv6 regex - if ! grep -E "$ipv6_regex" <<< $output; then - die "resolv.conf does not contain a ipv6 nameserver" - fi + assert "$output" =~ "$ipv6_regex" "resolv.conf should contain ipv6 nameserver" # ipv4 cni local mysubnet=$(random_rfc1918_subnet) @@ -385,9 +372,7 @@ load helpers is "$output" "$netname" "output of 'network create'" run_podman run --rm --network $netname $IMAGE cat /etc/resolv.conf - if grep -E "$ipv6_regex" <<< $output; then - die "resolv.conf contains a ipv6 nameserver" - fi + assert "$output" !~ "$ipv6_regex" "resolv.conf should not contain ipv6 nameserver" run_podman network rm -t 0 -f $netname @@ -399,10 +384,7 @@ load helpers is "$output" "$netname" "output of 'network create'" run_podman run --rm --network $netname $IMAGE cat /etc/resolv.conf - # "is" does not like the ipv6 regex - if ! grep -E "$ipv6_regex" <<< $output; then - die "resolv.conf does not contain a ipv6 nameserver" - fi + assert "$output" =~ "$ipv6_regex" "resolv.conf should contain ipv6 nameserver" run_podman network rm -t 0 -f $netname } @@ -456,9 +438,8 @@ load helpers # check that we cannot curl (timeout after 3 sec) run curl --max-time 3 -s $SERVER/index.txt - if [ "$status" -eq 0 ]; then - die "curl did not fail, it should have timed out or failed with non zero exit code" - fi + assert $status -ne 0 \ + "curl did not fail, it should have timed out or failed with non zero exit code" run_podman network connect $netname $cid is "$output" "" "Output should be empty (no errors)" @@ -470,13 +451,12 @@ load helpers # check that we have a new ip and mac # if the ip is still the same this whole test turns into a nop run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").IPAddress}}" - if [[ "$output" == "$ip" ]]; then - die "IP address did not change after podman network disconnect/connect" - fi + assert "$output" != "$ip" \ + "IP address did not change after podman network disconnect/connect" + run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").MacAddress}}" - if [[ "$output" == "$mac" ]]; then - die "MAC address did not change after podman network disconnect/connect" - fi + assert "$output" != "$mac" \ + "MAC address did not change after podman network disconnect/connect" # Disconnect/reconnect of a container *with no ports* should succeed quietly run_podman network disconnect $netname $background_cid @@ -552,9 +532,7 @@ load helpers while kill -0 $pid; do sleep 0.5 retries=$((retries - 1)) - if [[ $retries -eq 0 ]]; then - die "Process $pid (container $cid) refused to die" - fi + assert $retries -gt 0 "Process $pid (container $cid) refused to die" done # Wait for container to restart @@ -563,16 +541,13 @@ load helpers run_podman container inspect --format "{{.State.Pid}}" $cid # pid is 0 as long as the container is not running if [[ $output -ne 0 ]]; then - if [[ $output == $pid ]]; then - die "This should never happen! Restarted container has same PID ($output) as killed one!" - fi + assert "$output" != "$pid" \ + "This should never happen! Restarted container has same PID as killed one!" break fi sleep 0.5 retries=$((retries - 1)) - if [[ $retries -eq 0 ]]; then - die "Timed out waiting for container to restart" - fi + assert $retries -gt 0 "Timed out waiting for container to restart" done # Verify http contents again: curl from localhost diff --git a/test/system/520-checkpoint.bats b/test/system/520-checkpoint.bats index b41d460a4..c16a8c35d 100644 --- a/test/system/520-checkpoint.bats +++ b/test/system/520-checkpoint.bats @@ -80,9 +80,8 @@ function teardown() { # Get full logs, and make sure something changed run_podman logs $cid local nlines_after="${#lines[*]}" - if [[ $nlines_after -eq $nlines_before ]]; then - die "Container failed to output new lines after first restore" - fi + assert $nlines_after -gt $nlines_before \ + "Container failed to output new lines after first restore" # Same thing again: test for https://github.com/containers/crun/issues/756 # in which, after second checkpoint/restore, we lose logs @@ -96,9 +95,8 @@ function teardown() { sleep 0.3 run_podman container logs $cid nlines_after="${#lines[*]}" - if [[ $nlines_after -eq $nlines_before ]]; then - die "stdout went away after second restore (crun issue 756)" - fi + assert $nlines_after -gt $nlines_before \ + "stdout went away after second restore (crun issue 756)" run_podman rm -t 0 -f $cid } @@ -160,9 +158,8 @@ function teardown() { sleep .3 run curl --max-time 3 -s $server/mydate local date_newroot="$output" - if [[ $date_newroot = $date_oldroot ]]; then - die "Restored container did not update the timestamp file" - fi + assert "$date_newroot" != "$date_oldroot" \ + "Restored container did not update the timestamp file" run_podman exec $cid cat /myvol/cname is "$output" "$cname" "volume transferred fine" diff --git a/test/system/600-completion.bats b/test/system/600-completion.bats index 9fdd42332..018e95e78 100644 --- a/test/system/600-completion.bats +++ b/test/system/600-completion.bats @@ -40,7 +40,7 @@ function check_shell_completion() { # The line immediately after 'Usage:' gives us a 1-line synopsis usage=$(echo "$full_help" | grep -A1 '^Usage:' | tail -1) - [ -n "$usage" ] || die "podman $cmd: no Usage message found" + assert "$usage" != "" "podman $cmd: no Usage message found" # If usage ends in '[command]', recurse into subcommands if expr "$usage" : '.*\[command\]$' >/dev/null; then @@ -74,7 +74,8 @@ function check_shell_completion() { # If this fails there is most likely a problem with the cobra library is "${lines[0]}" "--.*" \ "$* $cmd: flag(s) listed in suggestions" - [ ${#lines[@]} -gt 2 ] || die "$* $cmd: No flag suggestions" + assert "${#lines[@]}" -gt 2 \ + "$* $cmd: No flag suggestions" _check_completion_end NoFileComp fi # continue the outer for args loop @@ -149,7 +150,7 @@ function check_shell_completion() { ### FIXME how can we get the configured registries? _check_completion_end NoFileComp ### FIXME this fails if no registries are configured - [[ ${#lines[@]} -gt 2 ]] || die "$* $cmd: No REGISTRIES found in suggestions" + assert "${#lines[@]}" -gt 2 "$* $cmd: No REGISTRIES found in suggestions" match=true # resume @@ -174,7 +175,7 @@ function check_shell_completion() { _check_completion_end NoSpace else _check_completion_end Default - [[ ${#lines[@]} -eq 2 ]] || die "$* $cmd: Suggestions are in the output" + assert "${#lines[@]}" -eq 2 "$* $cmd: Suggestions are in the output" fi ;; @@ -210,7 +211,7 @@ function check_shell_completion() { i=0 length=$(( ${#lines[@]} - 2 )) while [[ i -lt length ]]; do - [[ "${lines[$i]:0:7}" == "[Debug]" ]] || die "Suggestions are in the output" + assert "${lines[$i]:0:7}" == "[Debug]" "Suggestions are in the output" i=$(( i + 1 )) done fi diff --git a/test/system/750-trust.bats b/test/system/750-trust.bats index f06df35e7..0d04c33dc 100644 --- a/test/system/750-trust.bats +++ b/test/system/750-trust.bats @@ -37,8 +37,7 @@ load helpers subset=$(jq -r '.[1] | .repo_name, .type' <<<"$output" | fmt) is "$subset" "docker.io accept" "--json, docker.io should now be accept" - run cat $policypath - policy=$output + policy="$(< $policypath)" run_podman image trust show --policypath=$policypath --raw is "$output" "$policy" "output should show match content of policy.json" } diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 0d336592f..b41be53bc 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -500,19 +500,107 @@ function die() { false } - -######## -# is # Compare actual vs expected string; fail w/diagnostic if mismatch -######## +############ +# assert # Compare actual vs expected string; fail if mismatch +############ # -# Compares given string against expectations, using 'expr' to allow patterns. +# Compares string (default: $output) against the given string argument. +# By default we do an exact-match comparison against $output, but there +# are two different ways to invoke us, each with an optional description: +# +# assert "EXPECT" [DESCRIPTION] +# assert "RESULT" "OP" "EXPECT" [DESCRIPTION] +# +# The first form (one or two arguments) does an exact-match comparison +# of "$output" against "EXPECT". The second (three or four args) compares +# the first parameter against EXPECT, using the given OPerator. If present, +# DESCRIPTION will be displayed on test failure. # # Examples: # -# is "$actual" "$expected" "descriptive test name" -# is "apple" "orange" "name of a test that will fail in most universes" -# is "apple" "[a-z]\+" "this time it should pass" +# assert "this is exactly what we expect" +# assert "${lines[0]}" =~ "^abc" "first line begins with abc" # +function assert() { + local actual_string="$output" + local operator='==' + local expect_string="$1" + local testname="$2" + + case "${#*}" in + 0) die "Internal error: 'assert' requires one or more arguments" ;; + 1|2) ;; + 3|4) actual_string="$1" + operator="$2" + expect_string="$3" + testname="$4" + ;; + *) die "Internal error: too many arguments to 'assert'" ;; + esac + + # Comparisons. + # Special case: there is no !~ operator, so fake it via '! x =~ y' + local not= + local actual_op="$operator" + if [[ $operator == '!~' ]]; then + not='!' + actual_op='=~' + fi + if [[ $operator == '=' || $operator == '==' ]]; then + # Special case: we can't use '=' or '==' inside [[ ... ]] because + # the right-hand side is treated as a pattern... and '[xy]' will + # not compare literally. There seems to be no way to turn that off. + if [ "$actual_string" = "$expect_string" ]; then + return + fi + elif [[ $operator == '!=' ]]; then + # Same special case as above + if [ "$actual_string" != "$expect_string" ]; then + return + fi + else + if eval "[[ $not \$actual_string $actual_op \$expect_string ]]"; then + return + elif [ $? -gt 1 ]; then + die "Internal error: could not process 'actual' $operator 'expect'" + fi + fi + + # Test has failed. Get a descriptive test name. + if [ -z "$testname" ]; then + testname="${MOST_RECENT_PODMAN_COMMAND:-[no test name given]}" + fi + + # Display optimization: the typical case for 'expect' is an + # exact match ('='), but there are also '=~' or '!~' or '-ge' + # and the like. Omit the '=' but show the others; and always + # align subsequent output lines for ease of comparison. + local op='' + local ws='' + if [ "$operator" != '==' ]; then + op="$operator " + ws=$(printf "%*s" ${#op} "") + fi + + # This is a multi-line message, which may in turn contain multi-line + # output, so let's format it ourself, readably + local actual_split + IFS=$'\n' read -rd '' -a actual_split <<<"$actual_string" || true + printf "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" >&2 + printf "#| FAIL: %s\n" "$testname" >&2 + printf "#| expected: %s'%s'\n" "$op" "$expect_string" >&2 + printf "#| actual: %s'%s'\n" "$ws" "${actual_split[0]}" >&2 + local line + for line in "${actual_split[@]:1}"; do + printf "#| > %s'%s'\n" "$ws" "$line" >&2 + done + printf "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" >&2 + false +} + +######## +# is # **DEPRECATED**; see assert() above +######## function is() { local actual="$1" local expect="$2" @@ -716,10 +804,9 @@ function remove_same_dev_warning() { # return that list. function _podman_commands() { dprint "$@" - run_podman help "$@" | - awk '/^Available Commands:/{ok=1;next}/^Options:/{ok=0}ok { print $1 }' | - grep . - "$output" + # &>/dev/null prevents duplicate output + run_podman help "$@" &>/dev/null + awk '/^Available Commands:/{ok=1;next}/^Options:/{ok=0}ok { print $1 }' <<<"$output" | grep . } # END miscellaneous tools |