diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/apiv2/26-containersWait.at | 4 | ||||
-rw-r--r-- | test/apiv2/python/rest_api/test_v2_0_0_container.py | 2 | ||||
-rw-r--r-- | test/apiv2/python/rest_api/test_v2_0_0_image.py | 6 | ||||
-rw-r--r-- | test/buildah-bud/buildah-tests.diff | 16 | ||||
-rwxr-xr-x | test/compose/test-compose | 6 | ||||
-rw-r--r-- | test/e2e/common_test.go | 18 | ||||
-rw-r--r-- | test/e2e/cp_test.go | 44 | ||||
-rw-r--r-- | test/e2e/info_test.go | 10 | ||||
-rw-r--r-- | test/e2e/manifest_test.go | 8 | ||||
-rw-r--r-- | test/e2e/run_security_labels_test.go | 4 | ||||
-rw-r--r-- | test/system/005-info.bats | 8 | ||||
-rw-r--r-- | test/system/010-images.bats | 2 | ||||
-rw-r--r-- | test/system/030-run.bats | 2 | ||||
-rw-r--r-- | test/system/045-start.bats | 2 | ||||
-rw-r--r-- | test/system/065-cp.bats | 16 | ||||
-rw-r--r-- | test/system/070-build.bats | 28 | ||||
-rw-r--r-- | test/system/090-events.bats | 36 | ||||
-rw-r--r-- | test/system/150-login.bats | 6 | ||||
-rw-r--r-- | test/system/330-corrupt-images.bats | 2 |
19 files changed, 199 insertions, 21 deletions
diff --git a/test/apiv2/26-containersWait.at b/test/apiv2/26-containersWait.at index ec16c35df..55bcd4592 100644 --- a/test/apiv2/26-containersWait.at +++ b/test/apiv2/26-containersWait.at @@ -21,7 +21,9 @@ t POST "containers/${CTR}/wait?condition=non-existent-cond" 400 t POST "containers/${CTR}/wait?condition=not-running" 200 -t POST "containers/${CTR}/wait?condition=next-exit" 200 & +t POST "containers/${CTR}/wait?condition=next-exit" 200 \ + .StatusCode=0 \ + .Error=null & child_pid=$! podman start "${CTR}" wait "${child_pid}" diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py index 70c07d47f..ad096ed38 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_container.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py @@ -99,7 +99,7 @@ class ContainerTestCase(APITestCase): r = requests.post(self.podman_url + f"/v1.40/containers/{create['Id']}/wait") self.assertEqual(r.status_code, 200, r.text) wait = r.json() - self.assertEqual(wait["StatusCode"], 0, wait["Error"]["Message"]) + self.assertEqual(wait["StatusCode"], 0, wait["Error"]) prune = requests.post(self.podman_url + "/v1.40/containers/prune") self.assertEqual(prune.status_code, 200, prune.status_code) diff --git a/test/apiv2/python/rest_api/test_v2_0_0_image.py b/test/apiv2/python/rest_api/test_v2_0_0_image.py index 99f513608..243b1d5f5 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_image.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_image.py @@ -160,6 +160,12 @@ class ImageTestCase(APITestCase): for k in required_keys: self.assertIn(k, change) + def test_tree(self): + r = requests.get(self.uri("/images/alpine/tree")) + self.assertEqual(r.status_code, 200, r.text) + tree = r.json() + self.assertTrue(tree["Tree"].startswith("Image ID:"), r.text) + if __name__ == "__main__": unittest.main() diff --git a/test/buildah-bud/buildah-tests.diff b/test/buildah-bud/buildah-tests.diff index 6cda37723..fb00ddebf 100644 --- a/test/buildah-bud/buildah-tests.diff +++ b/test/buildah-bud/buildah-tests.diff @@ -1,22 +1,23 @@ -From a51192239fafdb59f26c9ddaab1ca9fcac2bb664 Mon Sep 17 00:00:00 2001 +From 90c93048c9f3bdedf39c3c5ce3216ee2518220b4 Mon Sep 17 00:00:00 2001 From: Ed Santiago <santiago@redhat.com> Date: Tue, 9 Feb 2021 17:28:05 -0700 Subject: [PATCH] tweaks for running buildah tests under podman Signed-off-by: Ed Santiago <santiago@redhat.com> --- - tests/helpers.bash | 26 +++++++++++++++++++++++--- - 1 file changed, 23 insertions(+), 3 deletions(-) + tests/helpers.bash | 28 +++++++++++++++++++++++++--- + 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/tests/helpers.bash b/tests/helpers.bash -index 4dc3a7dbda13..003575f48cec 100644 +index b85f99d3..1a827cd7 100644 --- a/tests/helpers.bash +++ b/tests/helpers.bash -@@ -140,15 +140,35 @@ function run_buildah() { +@@ -147,15 +147,37 @@ function run_buildah() { --retry) retry=3; shift;; # retry network flakes esac + local podman_or_buildah=${BUILDAH_BINARY} ++ local registry_opts=${BUILDAH_REGISTRY_OPTS} + if [[ $1 == "bud" || $1 == "build-using-dockerfile" ]]; then + shift + # podman defaults to --layers=true; buildah to --false. @@ -28,6 +29,7 @@ index 4dc3a7dbda13..003575f48cec 100644 + set "build" "--force-rm=false" "--layers=false" "$@" + fi + podman_or_buildah=${PODMAN_BINARY} ++ registry_opts=${PODMAN_REGISTRY_OPTS} + + # podman always exits 125 where buildah exits 1 or 2 + case $expected_rc in @@ -45,9 +47,9 @@ index 4dc3a7dbda13..003575f48cec 100644 # stdout is only emitted upon error; this echo is to help a debugger - echo "\$ $BUILDAH_BINARY $*" -- run timeout --foreground --kill=10 $BUILDAH_TIMEOUT ${BUILDAH_BINARY} ${REGISTRY_OPTS} ${ROOTDIR_OPTS} "$@" +- run timeout --foreground --kill=10 $BUILDAH_TIMEOUT ${BUILDAH_BINARY} ${BUILDAH_REGISTRY_OPTS} ${ROOTDIR_OPTS} "$@" + echo "\$ $cmd_basename $*" -+ run timeout --foreground --kill=10 $BUILDAH_TIMEOUT ${podman_or_buildah} --registries-conf ${TESTSDIR}/registries.conf --root ${TESTDIR}/root --runroot ${TESTDIR}/runroot --storage-driver ${STORAGE_DRIVER} "$@" ++ run timeout --foreground --kill=10 $BUILDAH_TIMEOUT ${podman_or_buildah} ${registry_opts} ${ROOTDIR_OPTS} "$@" # without "quotes", multiple lines are glommed together into one if [ -n "$output" ]; then echo "$output" diff --git a/test/compose/test-compose b/test/compose/test-compose index 46ca80321..981f78a79 100755 --- a/test/compose/test-compose +++ b/test/compose/test-compose @@ -174,12 +174,12 @@ function test_port() { if [ $curl_rc -ne 0 ]; then _show_ok 0 "$testname - curl (port $port) failed with status $curl_rc" echo "# podman ps -a:" - $PODMAN_BIN --root $WORKDIR/root --runroot $WORKDIR/runroot ps -a + $PODMAN_BIN --storage-driver=vfs --root $WORKDIR/root --runroot $WORKDIR/runroot ps -a if type -p ss; then echo "# ss -tulpn:" ss -tulpn echo "# podman unshare --rootless-cni ss -tulpn:" - $PODMAN_BIN --root $WORKDIR/root --runroot $WORKDIR/runroot unshare --rootless-cni ss -tulpn + $PODMAN_BIN --storage-driver=vfs --root $WORKDIR/root --runroot $WORKDIR/runroot unshare --rootless-cni ss -tulpn fi echo "# cat $WORKDIR/server.log:" cat $WORKDIR/server.log @@ -214,6 +214,7 @@ function start_service() { $PODMAN_BIN \ --log-level debug \ + --storage-driver=vfs \ --root $WORKDIR/root \ --runroot $WORKDIR/runroot \ --cgroup-manager=systemd \ @@ -241,6 +242,7 @@ function start_service() { function podman() { echo "\$ podman $*" >>$WORKDIR/output.log output=$($PODMAN_BIN \ + --storage-driver=vfs \ --root $WORKDIR/root \ --runroot $WORKDIR/runroot \ "$@") diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 359345096..7ffee961c 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -408,7 +408,14 @@ func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionInteg podmanArgs = append(podmanArgs, "-d", ALPINE, "ls") session := p.Podman(podmanArgs) session.WaitWithDefaultTimeout() - return session, session.ExitCode(), session.OutputToString() + if session.ExitCode() != 0 { + return session, session.ExitCode(), session.OutputToString() + } + cid := session.OutputToString() + + wsession := p.Podman([]string{"wait", cid}) + wsession.WaitWithDefaultTimeout() + return session, wsession.ExitCode(), cid } // RunNginxWithHealthCheck runs the alpine nginx container with an optional name and adds a healthcheck into it @@ -431,7 +438,14 @@ func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSe podmanArgs = append(podmanArgs, "-d", ALPINE, "ls") session := p.Podman(podmanArgs) session.WaitWithDefaultTimeout() - return session, session.ExitCode(), session.OutputToString() + if session.ExitCode() != 0 { + return session, session.ExitCode(), session.OutputToString() + } + cid := session.OutputToString() + + wsession := p.Podman([]string{"wait", cid}) + wsession.WaitWithDefaultTimeout() + return session, wsession.ExitCode(), cid } // BuildImage uses podman build and buildah to build an image diff --git a/test/e2e/cp_test.go b/test/e2e/cp_test.go index c0fb3f887..be4901833 100644 --- a/test/e2e/cp_test.go +++ b/test/e2e/cp_test.go @@ -91,6 +91,50 @@ var _ = Describe("Podman cp", func() { Expect(roundtripContent).To(Equal(originalContent)) }) + // Copy a file to the container, then back to the host in --pid=host + It("podman cp --pid=host file", func() { + SkipIfRootlessCgroupsV1("Not supported for rootless + CGroupsV1") + srcFile, err := ioutil.TempFile("", "") + Expect(err).To(BeNil()) + defer srcFile.Close() + defer os.Remove(srcFile.Name()) + + originalContent := []byte("podman cp file test") + err = ioutil.WriteFile(srcFile.Name(), originalContent, 0644) + Expect(err).To(BeNil()) + + // Create a container. NOTE that container mustn't be running for copying. + session := podmanTest.Podman([]string{"create", "--pid=host", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + name := session.OutputToString() + + session = podmanTest.Podman([]string{"start", name}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + // The file will now be created (and written to). + session = podmanTest.Podman([]string{"cp", srcFile.Name(), name + ":foo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + // Copy FROM the container. + + destFile, err := ioutil.TempFile("", "") + Expect(err).To(BeNil()) + defer destFile.Close() + defer os.Remove(destFile.Name()) + + session = podmanTest.Podman([]string{"cp", name + ":foo", destFile.Name()}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + // Now make sure the content matches. + roundtripContent, err := ioutil.ReadFile(destFile.Name()) + Expect(err).To(BeNil()) + Expect(roundtripContent).To(Equal(originalContent)) + }) + // Create a symlink in the container, use it as a copy destination and // make sure that the link and the resolved path are accessible and // give the right content. diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index 60136bcc2..f5b70d6bf 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -135,4 +135,14 @@ var _ = Describe("Podman Info", func() { Expect(session.OutputToString()).To(ContainSubstring("false")) } }) + + It("Podman info must contain cgroupControllers with ReleventControllers", func() { + SkipIfRootless("Hard to tell which controllers are going to be enabled for rootless") + SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users") + session := podmanTest.Podman([]string{"info", "--format", "{{.Host.CgroupControllers}}"}) + session.WaitWithDefaultTimeout() + Expect(session).To(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("memory")) + Expect(session.OutputToString()).To(ContainSubstring("pids")) + }) }) diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go index 18be97a89..b2dc4f734 100644 --- a/test/e2e/manifest_test.go +++ b/test/e2e/manifest_test.go @@ -168,6 +168,10 @@ var _ = Describe("Podman manifest", func() { session = podmanTest.Podman([]string{"manifest", "remove", "foo", "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Not(Equal(0))) + + session = podmanTest.Podman([]string{"manifest", "rm", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) }) It("podman manifest push", func() { @@ -250,6 +254,10 @@ var _ = Describe("Podman manifest", func() { session = podmanTest.Podman([]string{"manifest", "inspect", "foo"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Not(Equal(0))) + + session = podmanTest.Podman([]string{"manifest", "rm", "foo1", "foo2"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Not(Equal(0))) }) It("podman manifest exists", func() { diff --git a/test/e2e/run_security_labels_test.go b/test/e2e/run_security_labels_test.go index b714df323..ae86bb690 100644 --- a/test/e2e/run_security_labels_test.go +++ b/test/e2e/run_security_labels_test.go @@ -45,7 +45,7 @@ var _ = Describe("Podman generate kube", func() { ctr := inspect.InspectContainerToJSON() caps := strings.Join(ctr[0].EffectiveCaps, ",") - Expect(caps).To(Equal("CAP_SETUID,CAP_SETGID")) + Expect(caps).To(Equal("CAP_SETGID,CAP_SETUID")) }) It("podman bad security labels", func() { @@ -109,7 +109,7 @@ var _ = Describe("Podman generate kube", func() { ctr := inspect.InspectContainerToJSON() caps := strings.Join(ctr[0].EffectiveCaps, ",") - Expect(caps).To(Equal("CAP_SYS_CHROOT,CAP_SETUID")) + Expect(caps).To(Equal("CAP_SETUID,CAP_SYS_CHROOT")) }) diff --git a/test/system/005-info.bats b/test/system/005-info.bats index 83d79221a..4b419841e 100644 --- a/test/system/005-info.bats +++ b/test/system/005-info.bats @@ -82,4 +82,12 @@ store.imageStore.number | 1 # mounts. is "$output" ".*graphOptions: {}" "output includes graphOptions: {}" } + +@test "podman --root PATH info - basic output" { + if ! is_remote; then + run_podman --storage-driver=vfs --root ${PODMAN_TMPDIR}/nothing-here-move-along info --format '{{ .Store.GraphOptions }}' + is "$output" "map\[\]" "'podman --root should reset Graphoptions to []" + fi +} + # vim: filetype=sh diff --git a/test/system/010-images.bats b/test/system/010-images.bats index bda331e6b..2d7ac1e0c 100644 --- a/test/system/010-images.bats +++ b/test/system/010-images.bats @@ -12,7 +12,7 @@ load helpers # 'podman images' should emit headings even if there are no images # (but --root only works locally) if ! is_remote; then - run_podman --root ${PODMAN_TMPDIR}/nothing-here-move-along images + run_podman --storage-driver=vfs --root ${PODMAN_TMPDIR}/nothing-here-move-along images is "$output" "$headings" "'podman images' emits headings even w/o images" fi } diff --git a/test/system/030-run.bats b/test/system/030-run.bats index e12c32ef5..2ea981a85 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -14,7 +14,7 @@ load helpers # ...but check the configured runtime engine, and switch to crun as needed run_podman info --format '{{ .Host.OCIRuntime.Path }}' if expr "$output" : ".*/crun"; then - err_no_such_cmd="Error: executable file.* not found in \$PATH: No such file or directory: OCI not found" + err_no_such_cmd="Error: executable file.* not found in \$PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found" err_no_exec_dir="Error: open executable: Operation not permitted: OCI permission denied" fi diff --git a/test/system/045-start.bats b/test/system/045-start.bats index 542f9d1c2..3e0118dba 100644 --- a/test/system/045-start.bats +++ b/test/system/045-start.bats @@ -25,6 +25,8 @@ load helpers die "podman start --all restarted a running container" fi + run_podman wait $cid_none_implicit $cid_none_explicit $cid_on_failure + run_podman rm $cid_none_implicit $cid_none_explicit $cid_on_failure run_podman stop -t 1 $cid_always run_podman rm $cid_always diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats index 679cdc209..24ac8118e 100644 --- a/test/system/065-cp.bats +++ b/test/system/065-cp.bats @@ -130,6 +130,22 @@ load helpers } +@test "podman cp file from/to host while --pid=host" { + if is_rootless && ! is_cgroupsv2; then + skip "'podman cp --pid=host' (rootless) only works with cgroups v2" + fi + + srcdir=$PODMAN_TMPDIR/cp-pid-equals-host + mkdir -p $srcdir + touch $srcdir/hostfile + + run_podman run --pid=host -d --name cpcontainer $IMAGE sleep infinity + run_podman cp $srcdir/hostfile cpcontainer:/tmp/hostfile + run_podman cp cpcontainer:/tmp/hostfile $srcdir/hostfile1 + run_podman kill cpcontainer + run_podman rm -f cpcontainer +} + @test "podman cp file from container to host" { srcdir=$PODMAN_TMPDIR/cp-test-file-ctr-to-host mkdir -p $srcdir diff --git a/test/system/070-build.bats b/test/system/070-build.bats index d2d56c051..0f3f3fa7f 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -766,6 +766,34 @@ EOF is "$output" ".*/tmp/bogus: no such file or directory" } +@test "podman build COPY hardlinks " { + tmpdir=$PODMAN_TMPDIR/build-test + subdir=$tmpdir/subdir + subsubdir=$subdir/subsubdir + mkdir -p $subsubdir + + dockerfile=$tmpdir/Dockerfile + cat >$dockerfile <<EOF +FROM $IMAGE +COPY . /test +EOF + ln $dockerfile $tmpdir/hardlink1 + ln $dockerfile $subdir/hardlink2 + ln $dockerfile $subsubdir/hardlink3 + + run_podman build -t build_test $tmpdir + run_podman run --rm build_test stat -c '%i' /test/Dockerfile + dinode=$output + run_podman run --rm build_test stat -c '%i' /test/hardlink1 + is "$output" "$dinode" "COPY hardlinks work" + run_podman run --rm build_test stat -c '%i' /test/subdir/hardlink2 + is "$output" "$dinode" "COPY hardlinks work" + run_podman run --rm build_test stat -c '%i' /test/subdir/subsubdir/hardlink3 + is "$output" "$dinode" "COPY hardlinks work" + + run_podman rmi -f build_test +} + function teardown() { # A timeout or other error in 'build' can leave behind stale images # that podman can't even see and which will cascade into subsequent diff --git a/test/system/090-events.bats b/test/system/090-events.bats index 8a9db41fa..19bee5506 100644 --- a/test/system/090-events.bats +++ b/test/system/090-events.bats @@ -25,3 +25,39 @@ load helpers run_podman events --filter type=container --filter container=$cname --filter event=start --stream=false is "$output" "$expect" "filtering just by label" } + +@test "image events" { + skip_if_remote "FIXME: remove events on podman-remote seem to be broken" + pushedDir=$PODMAN_TMPDIR/dir + mkdir -p $pushedDir + + tarball=$PODMAN_TMPDIR/ball.tar + + run_podman image inspect --format "{{.ID}}" $IMAGE + imageID="$output" + + t0=$(date --iso-8601=seconds) + tag=registry.com/$(random_string 10 | tr A-Z a-z) + + # Force using the file backend since the journal backend is eating events + # (see containers/podman/pull/10219#issuecomment-842325032). + run_podman --events-backend=file push $IMAGE dir:$pushedDir + run_podman --events-backend=file save $IMAGE -o $tarball + run_podman --events-backend=file load -i $tarball + run_podman --events-backend=file pull docker-archive:$tarball + run_podman --events-backend=file tag $IMAGE $tag + run_podman --events-backend=file untag $IMAGE $tag + run_podman --events-backend=file tag $IMAGE $tag + run_podman --events-backend=file rmi $tag + + run_podman --events-backend=file events --stream=false --filter type=image --since $t0 + is "$output" ".*image push $imageID dir:$pushedDir +.*image save $imageID $tarball +.*image loadfromarchive *$tarball +.*image pull *docker-archive:$tarball +.*image tag $imageID $tag +.*image untag $imageID $tag:latest +.*image tag $imageID $tag +.*image remove $imageID $tag.*" \ + "podman events" +} diff --git a/test/system/150-login.bats b/test/system/150-login.bats index c3af63348..b6c04db08 100644 --- a/test/system/150-login.bats +++ b/test/system/150-login.bats @@ -62,7 +62,7 @@ function setup() { # Pull registry image, but into a separate container storage mkdir -p ${PODMAN_LOGIN_WORKDIR}/root mkdir -p ${PODMAN_LOGIN_WORKDIR}/runroot - PODMAN_LOGIN_ARGS="--root ${PODMAN_LOGIN_WORKDIR}/root --runroot ${PODMAN_LOGIN_WORKDIR}/runroot" + PODMAN_LOGIN_ARGS="--storage-driver=vfs --root ${PODMAN_LOGIN_WORKDIR}/root --runroot ${PODMAN_LOGIN_WORKDIR}/runroot" # Give it three tries, to compensate for flakes run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE || run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE || @@ -306,10 +306,10 @@ function _test_skopeo_credential_sharing() { skip "[leaving registry running by request]" fi - run_podman --root ${PODMAN_LOGIN_WORKDIR}/root \ + run_podman --storage-driver=vfs --root ${PODMAN_LOGIN_WORKDIR}/root \ --runroot ${PODMAN_LOGIN_WORKDIR}/runroot \ rm -f registry - run_podman --root ${PODMAN_LOGIN_WORKDIR}/root \ + run_podman --storage-driver=vfs --root ${PODMAN_LOGIN_WORKDIR}/root \ --runroot ${PODMAN_LOGIN_WORKDIR}/runroot \ rmi -a diff --git a/test/system/330-corrupt-images.bats b/test/system/330-corrupt-images.bats index c51cc8d46..2ee5eee9c 100644 --- a/test/system/330-corrupt-images.bats +++ b/test/system/330-corrupt-images.bats @@ -19,7 +19,7 @@ PODMAN_CORRUPT_TEST_IMAGE_ID=961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364b # All tests in this file (and ONLY in this file) run with a custom rootdir function setup() { skip_if_remote "none of these tests run under podman-remote" - _PODMAN_TEST_OPTS="--root ${PODMAN_CORRUPT_TEST_WORKDIR}/root" + _PODMAN_TEST_OPTS="--storage-driver=vfs --root ${PODMAN_CORRUPT_TEST_WORKDIR}/root" } function teardown() { |