diff options
Diffstat (limited to 'test')
119 files changed, 3237 insertions, 554 deletions
diff --git a/test/README.md b/test/README.md index ef3bfbcf9..4e61a0774 100644 --- a/test/README.md +++ b/test/README.md @@ -43,6 +43,11 @@ Build ginkgo and install it under $GOPATH/bin with the following command: ``` GOPATH=~/go make .install.ginkgo ``` +If your PATH does not include $GOPATH/bin, you might consider adding it. + +``` +PATH=$PATH:$GOPATH/bin +``` # Integration Tests Test suite for integration test for podman command line. It has its own structs: @@ -63,21 +68,38 @@ GOPATH=~/go ginkgo -v test/e2e/. Note the trailing period on the command above. Also, **-v** invokes verbose mode. That switch is optional. + +### Running a single file of integration tests You can run a single file of integration tests using the go test command: ``` GOPATH=~/go go test -v test/e2e/libpod_suite_test.go test/e2e/common_test.go test/e2e/config.go test/e2e/config_amd64.go test/e2e/your_test.go ``` -#### Run all tests like PAPR -You can closely emulate the PAPR run for Fedora with the following command: +### Running a single integration test +Before running the test suite, you have to declare which test you want run in the test +file itself. Consider the following actual test: +``` +It("podman inspect bogus pod", func() { + session := podmanTest.Podman([]string{"pod", "inspect", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Not(Equal(0))) + }) +``` + +To mark this as the test you want run, you simply change the *It* description to *FIt*. Please note how +both the `F` and `I` are capitalized. + +You can run a single integration test using the same command we used to run all the tests in a single +file. ``` -make integration.fedora +GOPATH=~/go go test -v test/e2e/libpod_suite_test.go test/e2e/common_test.go test/e2e/config.go test/e2e/config_amd64.go test/e2e/your_test.go ``` -This will run lint, git-validation, and gofmt tests and then execute unit and integration -tests as well. +*Note*: Be sure you remove the `F` from the tests before committing your changes or you will skip all tests +in that file except the one with the `FIt` denotation. + ### Run tests in a container In case you have issue running the tests locally on your machine, you can run @@ -105,3 +127,7 @@ You can run the test with following command: ``` make localsystem ``` + +## Contributing to system tests + +Please see [the TODO list of needed workflows/tests](system/TODO.md). diff --git a/test/certs/README.md b/test/certs/README.md new file mode 100644 index 000000000..3aab01440 --- /dev/null +++ b/test/certs/README.md @@ -0,0 +1,9 @@ +# How to generate key and cert: + +## Make private key without a password + +certtool --rsa --generate-privkey --null-password --outfile=domain.key + +## Use ``domain.cfg`` template to make self-signed cert + +certtool --generate-self-signed --load-privkey=domain.key --template=domain.cfg --outfile=domain.crt --load-ca-privkey=domain.key --null-password --no-text diff --git a/test/certs/domain.cfg b/test/certs/domain.cfg new file mode 100644 index 000000000..5baeb5631 --- /dev/null +++ b/test/certs/domain.cfg @@ -0,0 +1,30 @@ +# X.509 Certificate options +organization = "Koko inc." +unit = "sleeping dept." +locality = "foobar" +state = "Attiki" +country = GR +cn = "Cindy Lauper" +uid = "clauper" +dc = "name" +dc = "domain" +serial = 1234 +dns_name = "localhost" +# Use -1 if there is no expiration date. +expiration_days = -1 +email = "none@none.org" +signing_key +encryption_key +cert_signing_key +crl_signing_key +data_encipherment +non_repudiation +tls_www_client +tls_www_server +code_signing_key +ocsp_signing_key +time_stamping_key +email_protection_key +ipsec_ike_key +# for any purpose (must not be used in intermediate CA certificates) +key_purpose_oid = 2.5.29.37.0 diff --git a/test/certs/domain.crt b/test/certs/domain.crt index 881fc124d..8a697d7b2 100644 --- a/test/certs/domain.crt +++ b/test/certs/domain.crt @@ -1,18 +1,33 @@ -----BEGIN CERTIFICATE----- -MIIC3zCCAmSgAwIBAgIUdbnvx7lLf8OANP37QTKoxfNAl5EwCgYIKoZIzj0EAwMw -gawxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T -YW4gRnJhbmNpc2NvMSowKAYDVQQKEyFIb25lc3QgQWNobWVkJ3MgVXNlZCBDZXJ0 -aWZpY2F0ZXMxKTAnBgNVBAsTIEhhc3RpbHktR2VuZXJhdGVkIFZhbHVlcyBEaXZp -c29uMRkwFwYDVQQDExBBdXRvZ2VuZXJhdGVkIENBMB4XDTE4MDMyMDExMDUwMFoX -DTE5MDMyMDExMDUwMFowWzEVMBMGA1UEBxMMdGhlIGludGVybmV0MRYwFAYDVQQK -Ew1hdXRvZ2VuZXJhdGVkMRQwEgYDVQQLEwtwb2RtYW4gdGVzdDEUMBIGA1UEAxML -cG9kbWFuLXRlc3QwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATA65F+T8sreSnTm+I2 -IjeKN8rb5W2j3QKXz8n9JkPWiWX16HGIWso1JWPhhjvpmVkfSzD91niQwrsm6PhP -ypZUzkX5iL7JE8jVjflEiUbflSzc+fgT/scqRUUQ3evmqUCjgZYwgZMwDgYDVR0P -AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMB -Af8EAjAAMB0GA1UdDgQWBBQCgkUh4aBOTl5KHettBluuE7rccDAfBgNVHSMEGDAW -gBTPyUqMxUVdwC4K+kh9jHtnf7GrETAUBgNVHREEDTALgglsb2NhbGhvc3QwCgYI -KoZIzj0EAwMDaQAwZgIxAKsrYLbXSJs473tlfX3OF/BmfTvDwBO5TfPoZ1yNDhVk -UvoYn2szSEVMwR7uX1gKWgIxALz00G6umVkSh0MgIwSaYpJU/N1eVNgbIXRFV+5+ -lK/0jLWm4aAFkVhqUkkueTzG2g== +MIIFozCCBAugAwIBAgICBNIwDQYJKoZIhvcNAQELBQAwgboxFTATBgNVBAMTDENp +bmR5IExhdXBlcjEXMBUGCgmSJomT8ixkAQETB2NsYXVwZXIxFzAVBgNVBAsTDnNs +ZWVwaW5nIGRlcHQuMRIwEAYDVQQKEwlLb2tvIGluYy4xDzANBgNVBAcTBmZvb2Jh +cjEPMA0GA1UECBMGQXR0aWtpMQswCQYDVQQGEwJHUjEUMBIGCgmSJomT8ixkARkW +BG5hbWUxFjAUBgoJkiaJk/IsZAEZFgZkb21haW4wIBcNMTkwMzIwMTcyNjI4WhgP +OTk5OTEyMzEyMzU5NTlaMIG6MRUwEwYDVQQDEwxDaW5keSBMYXVwZXIxFzAVBgoJ +kiaJk/IsZAEBEwdjbGF1cGVyMRcwFQYDVQQLEw5zbGVlcGluZyBkZXB0LjESMBAG +A1UEChMJS29rbyBpbmMuMQ8wDQYDVQQHEwZmb29iYXIxDzANBgNVBAgTBkF0dGlr +aTELMAkGA1UEBhMCR1IxFDASBgoJkiaJk/IsZAEZFgRuYW1lMRYwFAYKCZImiZPy +LGQBGRYGZG9tYWluMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAsegi +5zWmOYejptJSm32ZV7ttJxSycbCIF8/dGTigFwE9IWMitWWz5VyohVYKYYV0ZZTI +SZOZFfL8ElQ6jTnHHxewWi/w1qINyTESGS2jOSBj3uXyGj94gXv9guzbWLNKAD8v +4iUHYq/7zZPyLqtzFGep3kuKFlrTxsdjgho2NyiuCCLcm+H3dpBoI24QIp1vCIX/ +LCqaAfkxzMyF5sawL7H82gAfYhvGTFoLb5Dy3HdUwlhelTW746HSqtTb9fEqUjNZ +MmBrCGexW8hN2WheIAoKOGc3UGZgpFj9q6LgWkVKsosZ9PhdxtOKH5XZrT6d5ZFb +HSfpsxZ0LMLDUK/H+kJaFJaSl0HyxbyZMDExtjCjLzk81+A9t9jkh8Jnag9Ylpec +ZHxKKl3K7lJuq7s69uKbN9XbTTUkmw4AMa7WdNadj/t8SfpM3ZxZWzX6U81wQg0Z +Zb/fKxu8lAMZNxfgW7bnaIUBAFzNd4AE/mCOO941v8cizXCNBZ5EyZGVIhxtAgMB +AAGjga4wgaswVQYDVR0lBE4wTAYEVR0lAAYIKwYBBQUHAwIGCCsGAQUFBwMBBggr +BgEFBQcDEQYIKwYBBQUHAwkGCCsGAQUFBwMDBggrBgEFBQcDCAYIKwYBBQUHAwQw +DAYDVR0TAQH/BAIwADAUBgNVHREEDTALgglsb2NhbGhvc3QwDwYDVR0PAQH/BAUD +AwfwADAdBgNVHQ4EFgQU28OkcdKIoWfHK19QXiFCYud345YwDQYJKoZIhvcNAQEL +BQADggGBAJyA0YiSiCzVS6M+/2hEvKamlYUz6L7pb5fdlQ3dPL/KlbUPc31bLD7b +G3Su9iz1bL1qVGebgoJTEDOD/6F9DbMY4Nsh4oe1rS+eBZe6fG6VnaxE4U2XIWKD +0aijGGfUvEB8W66BtCrtjY3bAb9v1OLvLxktd9do4ACjskq+q+CE/8ID9tCkAn8J +q0aHv5a5H3bPu3WGuiifZHER+08OwEsO7jsnZAJdgrAK8D0Rodd1rbdIFh2klu1p +LOCCMhgrQtCFVhoqWA2XaGexqmlTTXjabFDyMA8RvdKozwLSpyMMHJX6Q38Wdr8Z +nAXfqkCAcXuVwk2llAW7f073Ze3xFWUiW6gH0w7H1KvHHkglBM4H3HyG2T2pu9lb +mrqRRnfx2AuQplUrFVvz5V7sKmTwZCPueXkfcv/+6bxcLA0N0p3Dk+LGc2JzBLFb +n6AzrjKwiEg5ri4dQEuaYnJAYDvp+/vo4AEPrUc9nKwOo1h+3rAY2ZkuCy06/3cj +nzp56Tpaaw== -----END CERTIFICATE----- diff --git a/test/certs/domain.key b/test/certs/domain.key index b0f15eb75..4fe293cac 100644 --- a/test/certs/domain.key +++ b/test/certs/domain.key @@ -1,6 +1,39 @@ ------BEGIN EC PRIVATE KEY----- -MIGkAgEBBDB7ZI5Q6dOSwOqpJ2FVlFuDJN/sJB3epR2S+rOvCPua+rQ8uv6lpZDx -CQ4ioUMFo6agBwYFK4EEACKhZANiAATA65F+T8sreSnTm+I2IjeKN8rb5W2j3QKX -z8n9JkPWiWX16HGIWso1JWPhhjvpmVkfSzD91niQwrsm6PhPypZUzkX5iL7JE8jV -jflEiUbflSzc+fgT/scqRUUQ3evmqUA= ------END EC PRIVATE KEY----- +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAsegi5zWmOYejptJSm32ZV7ttJxSycbCIF8/dGTigFwE9IWMi +tWWz5VyohVYKYYV0ZZTISZOZFfL8ElQ6jTnHHxewWi/w1qINyTESGS2jOSBj3uXy +Gj94gXv9guzbWLNKAD8v4iUHYq/7zZPyLqtzFGep3kuKFlrTxsdjgho2NyiuCCLc +m+H3dpBoI24QIp1vCIX/LCqaAfkxzMyF5sawL7H82gAfYhvGTFoLb5Dy3HdUwlhe +lTW746HSqtTb9fEqUjNZMmBrCGexW8hN2WheIAoKOGc3UGZgpFj9q6LgWkVKsosZ +9PhdxtOKH5XZrT6d5ZFbHSfpsxZ0LMLDUK/H+kJaFJaSl0HyxbyZMDExtjCjLzk8 +1+A9t9jkh8Jnag9YlpecZHxKKl3K7lJuq7s69uKbN9XbTTUkmw4AMa7WdNadj/t8 +SfpM3ZxZWzX6U81wQg0ZZb/fKxu8lAMZNxfgW7bnaIUBAFzNd4AE/mCOO941v8ci +zXCNBZ5EyZGVIhxtAgMBAAECggGAfvporw2jrrwZGiBTxZdHs06bAaHMG0kcWaKK +9E1uNf00XHgddcs5MyOHRGO81Q4jnb0rlxg502iycYKcp9/tN0v5GuXMx+SyYj8b +48ynC0cLATSuL/3NTN3qe2ACzrRoxPRUgNxdARsKZhiKarUEVjQHEhpoXLxHG0GE +zH9Y4tWuITCAtOH7dixrp54O9iXX8gVxs1xUv8PUv4/aonR9nA01o4Mi4ytfxW8f +amnSbXjejjf0ihroF/iQHE4BEPEnSw/noudboZqW1fX30QJsbk13VH9BGIN2zQ06 +vnDU/VrUYfgKNGSjaeECaN7iZQ7nekzSomKFGm8yoLpgsFYjpqnGhyplDY1jE/J3 +BL4r7PVeUWiQdLqkjLxeAhcySUjGvt79UsX0N8Oa3dgOGUHz3H986l3G9Hlcgvnc +L18qzsyIo4WNFrLAWt3nwiWM8Olj3Y6S3S8EiBeXVe1g+nuYBFwLFDCkw26WhtJ0 +sy90q6pRvL1MXOq2etcT5RcNfichAoHBANXES2CtpE7GdgAnVpYoBUng0n8qieTG +qLkkPx5E9pr64c3pUqXVGjFY0XvZ16x0UMOC2+V1DuLea2WyPO0FmitWEXH7xfVN +KM+3ORT5afSG0fhaIDvkPdG3QwfGZCib9g5ZOR0rxnDHVAzCx242YITUa8rn8158 +tpH0nDsvvAnVeUIMHOq5DO7zx1jcPQtcWP4vF3a37j2dOgBe4c7CCMOpP8gCGVlX +Okr6HtNoKiKA4n5NbJNo+BKAJ8o7NrHdNwKBwQDVDiWqYve2kyGcRSowJk9gHH1f +Ls+0MP6gLvdRoIhAihrNLws8fhI/mLBxHTBCogoumU5nWavZyKqDTf0dRJSKgQfJ +hdkRPVWIy6crshtSRZ+dX7yFKAnXU+D+cgcximonA4Uza0WFh9OP4702VpcdlFQ8 +qmKZvFI1orLw37h8ej/Bk4MeocDBWjpa5Q/0Nk7JsuwyW/OadXM48NfJM88ZrEi/ +ZuDjNIshynG3tddoIs0nNfkoslFGOzxpMFnbRXsCgcBpEkwOoCsUAV684pkfw1oe +HyC4GtuelLsYDaXspe8k7E4THS1fj6iJOuP04XWuMZoFD4wwc+I2Ryc43GwwAMHv +rSV0BlIeKaf2uVOYaKPY6m/Ih9wyNBTiwRZ0euJ+R3KhSN/W485tXryEbTUDijzU +7WhyWqJ3/grrIPWt7d+aYdBxU2zfPsgJp8+DcPWcYO7pOZJp6yxyIpcA2aJaM2uF +aOqNz+JP1J01f02pkhirzvgFJt9IcZ8F0PI95+8Ra+8CgcAD6tesc1dkpv3mNqtY +6UtqU/vGJUEyafg0j8iCWrZGoYNupF/Lg/Hn83HDEqtRflM7mhwD8HUlcvgXo/Z0 +dE9a4JZ5ERn1pDAPbNctCYBRGfCeXyVDOYI80FEBvKz/LzFWeE0Zre5AT0gHjENt +XVg39gM6flODyh+k1tH9dc+ZklHbyE+P35+Arp0GENIjRmBaewy2vFQVUfWFZYBC +Nc6oBS/tPQIDi3LHc0Z1/0TvqDwnbWmgYu71oJ8yu+3bB0MCgcB0katYynavMg3W +w15sH/1+be5dFTXZoiajjqXmYDNkZzyLoghteu/eyxqFw8Au4hyVy5koYHN/jrzf +1ZfXFCs3P5asCAptTH3kwgT/ER58KPOoq7cGEaut9eQ1UAc8E34b/ZISbTl/Zw05 +swOMC6ipzn70kNoPcjJN2ujSUCD9t0NKyyCAKokjFICGpCHDOdOwqtZRbKFVFSix +/T4HAV9puGT6kDMCtjLyZ+fUOf9hgCHK3sBkBt5XrU8j6Wf/zyg= +-----END RSA PRIVATE KEY----- diff --git a/test/e2e/attach_test.go b/test/e2e/attach_test.go index 42866d5a1..a843fe7ff 100644 --- a/test/e2e/attach_test.go +++ b/test/e2e/attach_test.go @@ -3,8 +3,9 @@ package integration import ( - "fmt" "os" + "syscall" + "time" . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" @@ -24,14 +25,14 @@ var _ = Describe("Podman attach", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) @@ -51,6 +52,16 @@ var _ = Describe("Podman attach", func() { Expect(results.ExitCode()).To(Equal(125)) }) + It("podman container attach to non-running container", func() { + session := podmanTest.Podman([]string{"container", "create", "--name", "test1", "-d", "-i", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + results := podmanTest.Podman([]string{"container", "attach", "test1"}) + results.WaitWithDefaultTimeout() + Expect(results.ExitCode()).To(Equal(125)) + }) + It("podman attach to multiple containers", func() { session := podmanTest.RunTopContainer("test1") session.WaitWithDefaultTimeout() @@ -64,4 +75,44 @@ var _ = Describe("Podman attach", func() { results.WaitWithDefaultTimeout() Expect(results.ExitCode()).To(Equal(125)) }) + + It("podman attach to a running container", func() { + session := podmanTest.Podman([]string{"run", "-d", "--name", "test", ALPINE, "/bin/sh", "-c", "while true; do echo test; sleep 1; done"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + results := podmanTest.Podman([]string{"attach", "test"}) + time.Sleep(2 * time.Second) + results.Signal(syscall.SIGTSTP) + Expect(results.OutputToString()).To(ContainSubstring("test")) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + }) + It("podman attach to the latest container", func() { + session := podmanTest.Podman([]string{"run", "-d", "--name", "test1", ALPINE, "/bin/sh", "-c", "while true; do echo test1; sleep 1; done"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"run", "-d", "--name", "test2", ALPINE, "/bin/sh", "-c", "while true; do echo test2; sleep 1; done"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + results := podmanTest.Podman([]string{"attach", "-l"}) + time.Sleep(2 * time.Second) + results.Signal(syscall.SIGTSTP) + Expect(results.OutputToString()).To(ContainSubstring("test2")) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) + }) + + It("podman attach to a container with --sig-proxy set to false", func() { + session := podmanTest.Podman([]string{"run", "-d", "--name", "test", ALPINE, "/bin/sh", "-c", "while true; do echo test; sleep 1; done"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + results := podmanTest.Podman([]string{"attach", "--sig-proxy=false", "test"}) + time.Sleep(2 * time.Second) + results.Signal(syscall.SIGTERM) + results.WaitWithDefaultTimeout() + Expect(results.OutputToString()).To(ContainSubstring("test")) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + }) }) diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go index 11332708b..5b549755e 100644 --- a/test/e2e/checkpoint_test.go +++ b/test/e2e/checkpoint_test.go @@ -3,9 +3,9 @@ package integration import ( - "fmt" "net" "os" + "os/exec" "github.com/containers/libpod/pkg/criu" . "github.com/containers/libpod/test/utils" @@ -26,7 +26,18 @@ var _ = Describe("Podman checkpoint", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() + // Check if the runtime implements checkpointing. Currently only + // runc's checkpoint/restore implementation is supported. + cmd := exec.Command(podmanTest.OCIRuntime, "checkpoint", "-h") + if err := cmd.Start(); err != nil { + Skip("OCI runtime does not support checkpoint/restore") + } + if err := cmd.Wait(); err != nil { + Skip("OCI runtime does not support checkpoint/restore") + } + if !criu.CheckForCriu() { Skip("CRIU is missing or too old.") } @@ -42,8 +53,8 @@ var _ = Describe("Podman checkpoint", func() { AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman checkpoint bogus container", func() { diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go index 34b218621..bf9c88de5 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,14 @@ var _ = Describe("Podman commit", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) @@ -50,6 +49,21 @@ var _ = Describe("Podman commit", func() { Expect(StringInSlice("foobar.com/test1-image:latest", data[0].RepoTags)).To(BeTrue()) }) + It("podman container commit container", func() { + _, ec, _ := podmanTest.RunLsContainer("test1") + Expect(ec).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + + session := podmanTest.Podman([]string{"container", "commit", "test1", "foobar.com/test1-image:latest"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + check := podmanTest.Podman([]string{"image", "inspect", "foobar.com/test1-image:latest"}) + check.WaitWithDefaultTimeout() + data := check.InspectImageJSON() + Expect(StringInSlice("foobar.com/test1-image:latest", data[0].RepoTags)).To(BeTrue()) + }) + It("podman commit container with message", func() { _, ec, _ := podmanTest.RunLsContainer("test1") Expect(ec).To(Equal(0)) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index b22ead3fa..b20b3b37e 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -3,12 +3,17 @@ package integration import ( "encoding/json" "fmt" + "github.com/containers/libpod/pkg/rootless" + "io/ioutil" "os" "os/exec" "path/filepath" + "sort" "strings" "testing" + "github.com/containers/storage" + "github.com/containers/libpod/pkg/inspect" . "github.com/containers/libpod/test/utils" "github.com/containers/storage/pkg/reexec" @@ -40,13 +45,33 @@ type PodmanTestIntegration struct { SignaturePolicyPath string CgroupManager string Host HostOS + Timings []string + TmpDir string } +var LockTmpDir string + // PodmanSessionIntegration sturct for command line session type PodmanSessionIntegration struct { *PodmanSession } +type testResult struct { + name string + length float64 +} + +type testResultsSorted []testResult + +func (a testResultsSorted) Len() int { return len(a) } +func (a testResultsSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +type testResultsSortedLength struct{ testResultsSorted } + +func (a testResultsSorted) Less(i, j int) bool { return a[i].length < a[j].length } + +var testResults []testResult + // TestLibpod ginkgo master function func TestLibpod(t *testing.T) { if reexec.Init() { @@ -60,7 +85,7 @@ func TestLibpod(t *testing.T) { RunSpecs(t, "Libpod Suite") } -var _ = BeforeSuite(func() { +var _ = SynchronizedBeforeSuite(func() []byte { //Cache images cwd, _ := os.Getwd() INTEGRATION_ROOT = filepath.Join(cwd, "../../") @@ -72,6 +97,7 @@ var _ = BeforeSuite(func() { os.Exit(1) } } + for _, image := range CACHE_IMAGES { if err := podman.CreateArtifact(image); err != nil { fmt.Printf("%q\n", err) @@ -92,6 +118,68 @@ var _ = BeforeSuite(func() { } f.Close() } + path, err := ioutil.TempDir("", "libpodlock") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return []byte(path) +}, func(data []byte) { + LockTmpDir = string(data) +}) + +func (p *PodmanTestIntegration) Setup() { + cwd, _ := os.Getwd() + INTEGRATION_ROOT = filepath.Join(cwd, "../../") + p.ArtifactPath = ARTIFACT_DIR +} + +//var _ = BeforeSuite(func() { +// cwd, _ := os.Getwd() +// INTEGRATION_ROOT = filepath.Join(cwd, "../../") +// podman := PodmanTestCreate("/tmp") +// podman.ArtifactPath = ARTIFACT_DIR +// if _, err := os.Stat(ARTIFACT_DIR); os.IsNotExist(err) { +// if err = os.Mkdir(ARTIFACT_DIR, 0777); err != nil { +// fmt.Printf("%q\n", err) +// os.Exit(1) +// } +// } +//}) +// for _, image := range CACHE_IMAGES { +// if err := podman.CreateArtifact(image); err != nil { +// fmt.Printf("%q\n", err) +// os.Exit(1) +// } +// } +// host := GetHostDistributionInfo() +// if host.Distribution == "rhel" && strings.HasPrefix(host.Version, "7") { +// f, err := os.OpenFile("/proc/sys/user/max_user_namespaces", os.O_WRONLY, 0644) +// if err != nil { +// fmt.Println("Unable to enable userspace on RHEL 7") +// os.Exit(1) +// } +// _, err = f.WriteString("15000") +// if err != nil { +// fmt.Println("Unable to enable userspace on RHEL 7") +// os.Exit(1) +// } +// f.Close() +// } +// path, err := ioutil.TempDir("", "libpodlock") +// if err != nil { +// fmt.Println(err) +// os.Exit(1) +// } +// LockTmpDir = path +//}) + +var _ = AfterSuite(func() { + sort.Sort(testResultsSortedLength{testResults}) + fmt.Println("integration timing results") + for _, result := range testResults { + fmt.Printf("%s\t\t%f\n", result.name, result.length) + } }) // PodmanTestCreate creates a PodmanTestIntegration instance for the tests @@ -126,7 +214,11 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { if os.Getenv("STORAGE_OPTIONS") != "" { storageOptions = os.Getenv("STORAGE_OPTIONS") } + cgroupManager := CGROUP_MANAGER + if rootless.IsRootless() { + cgroupManager = "cgroupfs" + } if os.Getenv("CGROUP_MANAGER") != "" { cgroupManager = os.Getenv("CGROUP_MANAGER") } @@ -147,7 +239,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { ociRuntime = "/usr/bin/runc" } } - + os.Setenv("DISABLE_HC_SYSTEMD", "true") CNIConfigDir := "/etc/cni/net.d" p := &PodmanTestIntegration{ @@ -159,6 +251,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { }, ConmonBinary: conmonBinary, CrioRoot: filepath.Join(tempDir, "crio"), + TmpDir: tempDir, CNIConfigDir: CNIConfigDir, OCIRuntime: ociRuntime, RunRoot: filepath.Join(tempDir, "crio-run"), @@ -220,3 +313,27 @@ func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData { Expect(err).To(BeNil()) return i } + +// InspectContainer returns a container's inspect data in JSON format +func (p *PodmanTestIntegration) InspectContainer(name string) []inspect.ContainerData { + cmd := []string{"inspect", name} + session := p.Podman(cmd) + session.WaitWithDefaultTimeout() + return session.InspectContainerToJSON() +} + +func processTestResult(f GinkgoTestDescription) { + tr := testResult{length: f.Duration.Seconds(), name: f.TestText} + testResults = append(testResults, tr) +} + +func GetPortLock(port string) storage.Locker { + lockFile := filepath.Join(LockTmpDir, port) + lock, err := storage.GetLockfile(lockFile) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + lock.Lock() + return lock +} diff --git a/test/e2e/config.go b/test/e2e/config.go index 8116d993b..3fdb9e116 100644 --- a/test/e2e/config.go +++ b/test/e2e/config.go @@ -6,4 +6,5 @@ var ( ALPINE = "docker.io/library/alpine:latest" infra = "k8s.gcr.io/pause:3.1" BB = "docker.io/library/busybox:latest" + healthcheck = "docker.io/libpod/alpine_healthcheck:latest" ) diff --git a/test/e2e/config_amd64.go b/test/e2e/config_amd64.go index 3459bea6d..d02de7a6e 100644 --- a/test/e2e/config_amd64.go +++ b/test/e2e/config_amd64.go @@ -3,7 +3,7 @@ package integration var ( STORAGE_OPTIONS = "--storage-driver vfs" ROOTLESS_STORAGE_OPTIONS = "--storage-driver vfs" - CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, nginx, redis, registry, infra, labels} + CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, nginx, redis, registry, infra, labels, healthcheck} nginx = "quay.io/libpod/alpine_nginx:latest" BB_GLIBC = "docker.io/library/busybox:glibc" registry = "docker.io/library/registry:2" diff --git a/test/e2e/cp_test.go b/test/e2e/cp_test.go index e1e760ee0..f89865264 100644 --- a/test/e2e/cp_test.go +++ b/test/e2e/cp_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "io/ioutil" "os" "os/exec" @@ -27,14 +26,15 @@ var _ = Describe("Podman cp", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman cp file", func() { diff --git a/test/e2e/create_staticip_test.go b/test/e2e/create_staticip_test.go index 9bdc30342..6c4ca1cb8 100644 --- a/test/e2e/create_staticip_test.go +++ b/test/e2e/create_staticip_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -19,11 +18,13 @@ var _ = Describe("Podman create with --ip flag", func() { ) BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() // Cleanup the CNI networks used by the tests os.RemoveAll("/var/lib/cni/networks/podman") @@ -32,8 +33,8 @@ var _ = Describe("Podman create with --ip flag", func() { AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("Podman create --ip with garbage address", func() { diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index 9a526b778..6ed5ad2d8 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -25,14 +25,14 @@ var _ = Describe("Podman create", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) @@ -56,6 +56,13 @@ var _ = Describe("Podman create", func() { Expect(podmanTest.NumberOfContainers()).To(Equal(1)) }) + It("podman container create container based on a remote image", func() { + session := podmanTest.Podman([]string{"container", "create", BB_GLIBC, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + }) + It("podman create using short options", func() { session := podmanTest.Podman([]string{"create", ALPINE, "ls"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/diff_test.go b/test/e2e/diff_test.go index 94e150467..fba65823e 100644 --- a/test/e2e/diff_test.go +++ b/test/e2e/diff_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" "sort" @@ -25,14 +24,14 @@ var _ = Describe("Podman diff", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) @@ -43,6 +42,13 @@ var _ = Describe("Podman diff", func() { Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 0)) }) + It("podman container diff of image", func() { + session := podmanTest.Podman([]string{"container", "diff", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 0)) + }) + It("podman diff bogus image", func() { session := podmanTest.Podman([]string{"diff", "1234"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/e2e.coverprofile b/test/e2e/e2e.coverprofile index b5382604f..d413679ea 100644 --- a/test/e2e/e2e.coverprofile +++ b/test/e2e/e2e.coverprofile @@ -1,11 +1,11 @@ mode: atomic -github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:14.46,21.20 2 1 -github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:31.2,31.19 1 1 -github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:38.2,38.53 1 1 -github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:65.2,65.52 1 1 -github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:21.20,23.17 2 2 -github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:26.3,28.36 3 2 +github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:14.46,21.20 2 3 +github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:32.2,32.19 1 3 +github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:39.2,39.53 1 3 +github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:66.2,66.52 1 3 +github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:21.20,23.17 2 6 +github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:26.3,29.36 4 6 github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:23.17,25.4 1 0 -github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:31.19,36.3 4 2 -github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:38.53,63.3 20 1 -github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:65.52,90.3 20 1 +github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:32.19,37.3 3 6 +github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:39.53,64.3 20 3 +github.com/containers/libpod/test/e2e/pod_pod_namespaces.go:66.52,91.3 20 3
\ No newline at end of file diff --git a/test/e2e/events_test.go b/test/e2e/events_test.go new file mode 100644 index 000000000..321d93757 --- /dev/null +++ b/test/e2e/events_test.go @@ -0,0 +1,116 @@ +package integration + +import ( + "fmt" + "os" + "strings" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman events", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.RestoreAllArtifacts() + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) + GinkgoWriter.Write([]byte(timedResult)) + + }) + + // For most, all, of these tests we do not "live" test following a log because it may make a fragile test + // system more complex. Instead we run the "events" and then verify that the events are processed correctly. + // Perhaps a future version of this test would put events in a go func and send output back over a channel + // while events occur. + It("podman events", func() { + _, ec, _ := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + result := podmanTest.Podman([]string{"events", "--stream=false"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(BeZero()) + }) + + It("podman events with an event filter", func() { + SkipIfRemote() + _, ec, _ := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=start"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(len(result.OutputToStringArray())).To(Equal(1)) + }) + + It("podman events with an event filter and container=cid", func() { + SkipIfRemote() + _, ec, cid := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + _, ec2, cid2 := podmanTest.RunLsContainer("") + Expect(ec2).To(Equal(0)) + result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=start", "--filter", fmt.Sprintf("container=%s", cid)}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(len(result.OutputToStringArray())).To(Equal(1)) + Expect(!strings.Contains(result.OutputToString(), cid2)) + }) + + It("podman events with a type", func() { + SkipIfRemote() + _, ec, _ := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "type=pod"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(len(result.OutputToStringArray())).To(Equal(0)) + }) + + It("podman events with a type", func() { + SkipIfRemote() + setup := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:foobar", ALPINE, "top"}) + setup.WaitWithDefaultTimeout() + stop := podmanTest.Podman([]string{"pod", "stop", "foobar"}) + stop.WaitWithDefaultTimeout() + Expect(stop.ExitCode()).To(Equal(0)) + Expect(setup.ExitCode()).To(Equal(0)) + result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "type=pod"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + fmt.Println(result.OutputToStringArray()) + Expect(len(result.OutputToStringArray())).To(Equal(2)) + }) + + It("podman events --since", func() { + _, ec, _ := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + result := podmanTest.Podman([]string{"events", "--stream=false", "--since", "1m"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(BeZero()) + }) + + It("podman events --until", func() { + _, ec, _ := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + test := podmanTest.Podman([]string{"events", "--help"}) + test.WaitWithDefaultTimeout() + fmt.Println(test.OutputToStringArray()) + result := podmanTest.Podman([]string{"events", "--stream=false", "--since", "1h"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(BeZero()) + }) + +}) diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go index 5839b364d..2a10e52b1 100644 --- a/test/e2e/exec_test.go +++ b/test/e2e/exec_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,14 @@ var _ = Describe("Podman exec", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) @@ -57,6 +56,16 @@ var _ = Describe("Podman exec", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman container exec simple command", func() { + setup := podmanTest.RunTopContainer("test1") + setup.WaitWithDefaultTimeout() + Expect(setup.ExitCode()).To(Equal(0)) + + session := podmanTest.Podman([]string{"container", "exec", "test1", "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman exec simple command using latest", func() { setup := podmanTest.RunTopContainer("test1") setup.WaitWithDefaultTimeout() diff --git a/test/e2e/exists_test.go b/test/e2e/exists_test.go index c4b5e4968..71c6c1820 100644 --- a/test/e2e/exists_test.go +++ b/test/e2e/exists_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -22,14 +21,14 @@ var _ = Describe("Podman image|container exists", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) diff --git a/test/e2e/export_test.go b/test/e2e/export_test.go index dba0a2255..71ddb518a 100644 --- a/test/e2e/export_test.go +++ b/test/e2e/export_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" "path/filepath" @@ -23,14 +22,14 @@ var _ = Describe("Podman export", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) @@ -50,6 +49,22 @@ var _ = Describe("Podman export", func() { Expect(err).To(BeNil()) }) + It("podman container export output flag", func() { + SkipIfRemote() + _, ec, cid := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + + outfile := filepath.Join(podmanTest.TempDir, "container.tar") + result := podmanTest.Podman([]string{"container", "export", "-o", outfile, cid}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + _, err := os.Stat(outfile) + Expect(err).To(BeNil()) + + err = os.Remove(outfile) + Expect(err).To(BeNil()) + }) + It("podman export bad filename", func() { _, ec, cid := podmanTest.RunLsContainer("") Expect(ec).To(Equal(0)) diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index 94e02dc55..5bcf3b347 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -25,14 +24,14 @@ var _ = Describe("Podman generate kube", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) @@ -49,6 +48,7 @@ var _ = Describe("Podman generate kube", func() { }) It("podman generate kube on container", func() { + SkipIfRootless() session := podmanTest.RunTopContainer("top") session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -62,6 +62,7 @@ var _ = Describe("Podman generate kube", func() { }) It("podman generate service kube on container", func() { + SkipIfRootless() session := podmanTest.RunTopContainer("top") session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -75,6 +76,7 @@ var _ = Describe("Podman generate kube", func() { }) It("podman generate kube on pod", func() { + SkipIfRootless() _, rc, _ := podmanTest.CreatePod("toppod") Expect(rc).To(Equal(0)) @@ -91,6 +93,7 @@ var _ = Describe("Podman generate kube", func() { }) It("podman generate service kube on pod", func() { + SkipIfRootless() _, rc, _ := podmanTest.CreatePod("toppod") Expect(rc).To(Equal(0)) diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go new file mode 100644 index 000000000..cd2365ce7 --- /dev/null +++ b/test/e2e/healthcheck_run_test.go @@ -0,0 +1,182 @@ +// +build !remoteclient + +package integration + +import ( + "fmt" + "os" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman healthcheck run", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.RestoreAllArtifacts() + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) + GinkgoWriter.Write([]byte(timedResult)) + + }) + + It("podman healthcheck run bogus container", func() { + session := podmanTest.Podman([]string{"healthcheck", "run", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Not(Equal(0))) + }) + + It("podman healthcheck on valid container", func() { + SkipIfRootless() + podmanTest.RestoreArtifact(healthcheck) + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", healthcheck}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(0)) + }) + + It("podman healthcheck that should fail", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "docker.io/libpod/badhealthcheck:latest"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(1)) + }) + + It("podman healthcheck on stopped container", func() { + podmanTest.RestoreArtifact(healthcheck) + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", healthcheck, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(125)) + }) + + It("podman healthcheck on container without healthcheck", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(125)) + }) + + It("podman healthcheck should be starting", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--healthcheck-retries", "2", "--healthcheck-command", "\"CMD-SHELL ls /foo || exit 1\"", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + inspect := podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting")) + }) + + It("podman healthcheck failed checks in start-period should not change status", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--healthcheck-start-period", "2m", "--healthcheck-retries", "2", "--healthcheck-command", "\"CMD-SHELL ls /foo || exit 1\"", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(1)) + + hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(1)) + + hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(1)) + + inspect := podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting")) + }) + + It("podman healthcheck failed checks must reach retries before unhealthy ", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--healthcheck-retries", "2", "--healthcheck-command", "\"CMD-SHELL ls /foo || exit 1\"", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(1)) + + inspect := podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting")) + + hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(1)) + + inspect = podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Healthcheck.Status).To(Equal("unhealthy")) + + }) + + It("podman healthcheck good check results in healthy even in start-period", func() { + SkipIfRootless() + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--healthcheck-start-period", "2m", "--healthcheck-retries", "2", "--healthcheck-command", "\"CMD-SHELL\" \"ls\" \"||\" \"exit\" \"1\"", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(0)) + + inspect := podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Healthcheck.Status).To(Equal("healthy")) + }) + + It("podman healthcheck single healthy result changes failed to healthy", func() { + SkipIfRootless() + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", "--healthcheck-retries", "2", "--healthcheck-command", "\"CMD-SHELL\" \"ls\" \"/foo\" \"||\" \"exit\" \"1\"", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(1)) + + inspect := podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting")) + + hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(1)) + + inspect = podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Healthcheck.Status).To(Equal("unhealthy")) + + foo := podmanTest.Podman([]string{"exec", "hc", "touch", "/foo"}) + foo.WaitWithDefaultTimeout() + Expect(foo.ExitCode()).To(BeZero()) + + hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc.ExitCode()).To(Equal(0)) + + inspect = podmanTest.InspectContainer("hc") + Expect(inspect[0].State.Healthcheck.Status).To(Equal("healthy")) + }) +}) diff --git a/test/e2e/history_test.go b/test/e2e/history_test.go index 9bec9ad13..9e519dd9c 100644 --- a/test/e2e/history_test.go +++ b/test/e2e/history_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -22,14 +21,14 @@ var _ = Describe("Podman history", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go index 595084403..a253dff63 100644 --- a/test/e2e/images_test.go +++ b/test/e2e/images_test.go @@ -24,14 +24,14 @@ var _ = Describe("Podman images", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) It("podman images", func() { @@ -43,6 +43,15 @@ var _ = Describe("Podman images", func() { Expect(session.LineInOuputStartsWith("docker.io/library/busybox")).To(BeTrue()) }) + It("podman image List", func() { + session := podmanTest.Podman([]string{"image", "list"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 2)) + Expect(session.LineInOuputStartsWith("docker.io/library/alpine")).To(BeTrue()) + Expect(session.LineInOuputStartsWith("docker.io/library/busybox")).To(BeTrue()) + }) + It("podman images with multiple tags", func() { // tag "docker.io/library/alpine:latest" to "foo:{a,b,c}" session := podmanTest.Podman([]string{"tag", ALPINE, "foo:a", "foo:b", "foo:c"}) @@ -103,6 +112,45 @@ var _ = Describe("Podman images", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) Expect(len(session.OutputToStringArray())).To(Equal(1)) + + session = podmanTest.Podman([]string{"tag", ALPINE, "foo:a"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.Podman([]string{"tag", BB, "foo:b"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"images", "-q", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(Equal(2)) + }) + + It("podman images filter reference", func() { + if podmanTest.RemoteTest { + Skip("Does not work on remote client") + } + result := podmanTest.Podman([]string{"images", "-q", "-f", "reference=docker.io*"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(len(result.OutputToStringArray())).To(Equal(2)) + + retapline := podmanTest.Podman([]string{"images", "-f", "reference=a*pine"}) + retapline.WaitWithDefaultTimeout() + Expect(retapline.ExitCode()).To(Equal(0)) + Expect(len(retapline.OutputToStringArray())).To(Equal(2)) + Expect(retapline.LineInOutputContains("alpine")) + + retapline = podmanTest.Podman([]string{"images", "-f", "reference=alpine"}) + retapline.WaitWithDefaultTimeout() + Expect(retapline.ExitCode()).To(Equal(0)) + Expect(len(retapline.OutputToStringArray())).To(Equal(2)) + Expect(retapline.LineInOutputContains("alpine")) + + retnone := podmanTest.Podman([]string{"images", "-q", "-f", "reference=bogus"}) + retnone.WaitWithDefaultTimeout() + Expect(retnone.ExitCode()).To(Equal(0)) + Expect(len(retnone.OutputToStringArray())).To(Equal(0)) }) It("podman images filter before image", func() { @@ -135,6 +183,23 @@ var _ = Describe("Podman images", func() { Expect(len(result.OutputToStringArray())).To(Equal(1)) }) + It("podman image list filter after image", func() { + if podmanTest.RemoteTest { + Skip("Does not work on remote client") + } + rmi := podmanTest.Podman([]string{"image", "rm", "busybox"}) + rmi.WaitWithDefaultTimeout() + Expect(rmi.ExitCode()).To(Equal(0)) + + dockerfile := `FROM docker.io/library/alpine:latest +` + podmanTest.BuildImage(dockerfile, "foobar.com/before:latest", "false") + result := podmanTest.Podman([]string{"image", "list", "-q", "-f", "after=docker.io/library/alpine:latest"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(len(result.OutputToStringArray())).To(Equal(1)) + }) + It("podman images filter dangling", func() { if podmanTest.RemoteTest { Skip("Does not work on remote client") @@ -164,6 +229,21 @@ var _ = Describe("Podman images", func() { Expect(result.ExitCode()).To(Equal(0)) }) + It("podman check for image with sha256: prefix", func() { + if podmanTest.RemoteTest { + Skip("Does not work on remote client") + } + session := podmanTest.Podman([]string{"image", "inspect", "--format=json", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.IsJSONOutputValid()).To(BeTrue()) + imageData := session.InspectImageJSON() + + result := podmanTest.Podman([]string{"image", "ls", fmt.Sprintf("sha256:%s", imageData[0].ID)}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + }) + It("podman images sort by tag", func() { session := podmanTest.Podman([]string{"images", "--sort", "tag", "--format={{.Tag}}"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/import_test.go b/test/e2e/import_test.go index dc7451f7b..e819d819c 100644 --- a/test/e2e/import_test.go +++ b/test/e2e/import_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" "path/filepath" @@ -25,14 +24,15 @@ var _ = Describe("Podman import", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman import with source and reference", func() { diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index a50c27dda..c960fb311 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,13 +23,14 @@ var _ = Describe("Podman Info", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman info json output", func() { @@ -41,7 +41,7 @@ var _ = Describe("Podman Info", func() { }) It("podman system info json output", func() { session := podmanTest.Podman([]string{"system", "info", "--format=json"}) - session.Wait() + session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) }) diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go index e5c471bf9..34328828f 100644 --- a/test/e2e/inspect_test.go +++ b/test/e2e/inspect_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" "strings" @@ -23,14 +22,15 @@ var _ = Describe("Podman inspect", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman inspect alpine image", func() { @@ -57,7 +57,7 @@ var _ = Describe("Podman inspect", func() { result := podmanTest.Podman([]string{"images", "-q", "--no-trunc", ALPINE}) result.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - Expect(strings.Trim(result.OutputToString(), "sha256:")).To(Equal(session.OutputToString())) + Expect(strings.Contains(result.OutputToString(), session.OutputToString())) }) It("podman inspect specified type", func() { @@ -66,6 +66,16 @@ var _ = Describe("Podman inspect", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman inspect container with GO format for ConmonPidFile", func() { + SkipIfRemote() + session, ec, _ := podmanTest.RunLsContainer("test1") + Expect(ec).To(Equal(0)) + + session = podmanTest.Podman([]string{"inspect", "--format", "{{.ConmonPidFile}}", "test1"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman inspect container with size", func() { SkipIfRemote() _, ec, _ := podmanTest.RunLsContainer("") diff --git a/test/e2e/kill_test.go b/test/e2e/kill_test.go index 5f1f5f4c1..618ca5aa0 100644 --- a/test/e2e/kill_test.go +++ b/test/e2e/kill_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,14 @@ var _ = Describe("Podman kill", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) @@ -41,6 +40,19 @@ var _ = Describe("Podman kill", func() { Expect(session.ExitCode()).To(Not(Equal(0))) }) + It("podman container kill a running container by id", func() { + session := podmanTest.RunTopContainer("") + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid := session.OutputToString() + + result := podmanTest.Podman([]string{"container", "kill", cid}) + result.WaitWithDefaultTimeout() + + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + }) + It("podman kill a running container by id", func() { session := podmanTest.RunTopContainer("") session.WaitWithDefaultTimeout() diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go index e6bc00397..44c5edf07 100644 --- a/test/e2e/libpod_suite_remoteclient_test.go +++ b/test/e2e/libpod_suite_remoteclient_test.go @@ -18,6 +18,12 @@ func SkipIfRemote() { ginkgo.Skip("This function is not enabled for remote podman") } +func SkipIfRootless() { + if os.Geteuid() != 0 { + ginkgo.Skip("This function is not enabled for remote podman") + } +} + // Cleanup cleans up the temporary store func (p *PodmanTestIntegration) Cleanup() { p.StopVarlink() @@ -133,6 +139,9 @@ func (p *PodmanTestIntegration) CleanupVolume() { } func PodmanTestCreate(tempDir string) *PodmanTestIntegration { + if os.Geteuid() != 0 { + ginkgo.Skip("This function is not enabled for rootless podman") + } pti := PodmanTestCreateUtil(tempDir, true) pti.StartVarlink() return pti diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index 33e05b872..685a08340 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -14,12 +14,23 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/inspect" . "github.com/containers/libpod/test/utils" + "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/gexec" ) -func SkipIfRemote() {} +func SkipIfRemote() { + if os.Geteuid() != 0 { + ginkgo.Skip("This function is not enabled for rootless podman") + } +} + +func SkipIfRootless() { + if os.Geteuid() != 0 { + ginkgo.Skip("This function is not enabled for rootless podman") + } +} // Podman is the exec call to podman on the filesystem func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { @@ -206,8 +217,8 @@ func PodmanTestCreate(tempDir string) *PodmanTestIntegration { //MakeOptions assembles all the podman main options func (p *PodmanTestIntegration) makeOptions(args []string) []string { - podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s", - p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ") + podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s", + p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir), " ") if os.Getenv("HOOK_OPTION") != "" { podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION")) } diff --git a/test/e2e/load_test.go b/test/e2e/load_test.go index 571754347..0e193640e 100644 --- a/test/e2e/load_test.go +++ b/test/e2e/load_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" "path/filepath" @@ -25,14 +24,15 @@ var _ = Describe("Podman load", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman load input flag", func() { @@ -190,7 +190,7 @@ var _ = Describe("Podman load", func() { load.WaitWithDefaultTimeout() Expect(load.ExitCode()).To(Equal(0)) - result := podmanTest.Podman([]string{"images", "-f", "label", "hello:world"}) + result := podmanTest.Podman([]string{"images", "hello:world"}) result.WaitWithDefaultTimeout() Expect(result.LineInOutputContains("docker")).To(Not(BeTrue())) Expect(result.LineInOutputContains("localhost")).To(BeTrue()) @@ -216,7 +216,7 @@ var _ = Describe("Podman load", func() { load.WaitWithDefaultTimeout() Expect(load.ExitCode()).To(Equal(0)) - result := podmanTest.Podman([]string{"images", "-f", "label", "hello:latest"}) + result := podmanTest.Podman([]string{"images", "hello:latest"}) result.WaitWithDefaultTimeout() Expect(result.LineInOutputContains("docker")).To(Not(BeTrue())) Expect(result.LineInOutputContains("localhost")).To(BeTrue()) @@ -241,7 +241,7 @@ var _ = Describe("Podman load", func() { load.WaitWithDefaultTimeout() Expect(load.ExitCode()).To(Equal(0)) - result := podmanTest.Podman([]string{"images", "-f", "label", "load:latest"}) + result := podmanTest.Podman([]string{"images", "load:latest"}) result.WaitWithDefaultTimeout() Expect(result.LineInOutputContains("docker")).To(Not(BeTrue())) Expect(result.LineInOutputContains("localhost")).To(BeTrue()) diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go index d3c4fb802..d051e3dba 100644 --- a/test/e2e/logs_test.go +++ b/test/e2e/logs_test.go @@ -3,8 +3,8 @@ package integration import ( - "fmt" "os" + "strings" . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" @@ -24,17 +24,17 @@ var _ = Describe("Podman logs", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) - //sudo bin/podman run -it --rm fedora-minimal bash -c 'for a in `seq 5`; do echo hello; done' It("podman logs for container", func() { logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"}) logc.WaitWithDefaultTimeout() @@ -106,4 +106,40 @@ var _ = Describe("Podman logs", func() { Expect(results.ExitCode()).To(Equal(0)) Expect(len(results.OutputToStringArray())).To(Equal(3)) }) + + It("podman logs latest and container name should fail", func() { + results := podmanTest.Podman([]string{"logs", "-l", "foobar"}) + results.WaitWithDefaultTimeout() + Expect(results.ExitCode()).ToNot(Equal(0)) + }) + + It("podman logs two containers and should display short container IDs", func() { + log1 := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"}) + log1.WaitWithDefaultTimeout() + Expect(log1.ExitCode()).To(Equal(0)) + cid1 := log1.OutputToString() + + log2 := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"}) + log2.WaitWithDefaultTimeout() + Expect(log2.ExitCode()).To(Equal(0)) + cid2 := log2.OutputToString() + + results := podmanTest.Podman([]string{"logs", cid1, cid2}) + results.WaitWithDefaultTimeout() + Expect(results.ExitCode()).To(Equal(0)) + + output := results.OutputToStringArray() + Expect(len(output)).To(Equal(6)) + Expect(strings.Contains(output[0], cid1[:12]) || strings.Contains(output[0], cid2[:12])).To(BeTrue()) + }) + + It("podman logs on a created container should result in 0 exit code", func() { + session := podmanTest.Podman([]string{"create", "-dt", "--name", "log", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(BeZero()) + + results := podmanTest.Podman([]string{"logs", "log"}) + results.WaitWithDefaultTimeout() + Expect(results.ExitCode()).To(BeZero()) + }) }) diff --git a/test/e2e/mount_test.go b/test/e2e/mount_test.go index 94218e6a9..b361e0057 100644 --- a/test/e2e/mount_test.go +++ b/test/e2e/mount_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman mount", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman mount", func() { @@ -49,6 +49,21 @@ var _ = Describe("Podman mount", func() { Expect(umount.ExitCode()).To(Equal(0)) }) + It("podman container mount", func() { + setup := podmanTest.Podman([]string{"container", "create", ALPINE, "ls"}) + setup.WaitWithDefaultTimeout() + Expect(setup.ExitCode()).To(Equal(0)) + cid := setup.OutputToString() + + mount := podmanTest.Podman([]string{"container", "mount", cid}) + mount.WaitWithDefaultTimeout() + Expect(mount.ExitCode()).To(Equal(0)) + + umount := podmanTest.Podman([]string{"container", "umount", cid}) + umount.WaitWithDefaultTimeout() + Expect(umount.ExitCode()).To(Equal(0)) + }) + It("podman mount with json format", func() { setup := podmanTest.Podman([]string{"create", ALPINE, "ls"}) setup.WaitWithDefaultTimeout() diff --git a/test/e2e/namespace_test.go b/test/e2e/namespace_test.go index a0b6e6187..28d050be3 100644 --- a/test/e2e/namespace_test.go +++ b/test/e2e/namespace_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman namespaces", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman namespace test", func() { diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go index f1ea17ead..e28c31c3a 100644 --- a/test/e2e/pause_test.go +++ b/test/e2e/pause_test.go @@ -22,19 +22,21 @@ var _ = Describe("Podman pause", func() { createdState := "Created" BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pause bogus container", func() { @@ -80,6 +82,23 @@ var _ = Describe("Podman pause", func() { result.WaitWithDefaultTimeout() }) + It("podman container pause a running container by id", func() { + session := podmanTest.RunTopContainer("") + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid := session.OutputToString() + + result := podmanTest.Podman([]string{"container", "pause", cid}) + result.WaitWithDefaultTimeout() + + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring(pausedState)) + + result = podmanTest.Podman([]string{"container", "unpause", cid}) + result.WaitWithDefaultTimeout() + }) + It("podman unpause a running container by id", func() { session := podmanTest.RunTopContainer("") session.WaitWithDefaultTimeout() diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index 4717267a1..de0734e9f 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman pod create", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman create pod", func() { @@ -100,7 +100,7 @@ var _ = Describe("Podman pod create", func() { It("podman create pod with network portbindings", func() { name := "test" - session := podmanTest.Podman([]string{"pod", "create", "--name", name, "-p", "80:80"}) + session := podmanTest.Podman([]string{"pod", "create", "--name", name, "-p", "8080:80"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) pod := session.OutputToString() @@ -109,7 +109,7 @@ var _ = Describe("Podman pod create", func() { webserver.WaitWithDefaultTimeout() Expect(webserver.ExitCode()).To(Equal(0)) - check := SystemExec("nc", []string{"-z", "localhost", "80"}) + check := SystemExec("nc", []string{"-z", "localhost", "8080"}) Expect(check.ExitCode()).To(Equal(0)) }) diff --git a/test/e2e/pod_infra_container_test.go b/test/e2e/pod_infra_container_test.go index ed5002ca7..82f35999c 100644 --- a/test/e2e/pod_infra_container_test.go +++ b/test/e2e/pod_infra_container_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" "strconv" @@ -25,6 +24,7 @@ var _ = Describe("Podman pod create", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() podmanTest.RestoreArtifact(infra) }) @@ -32,8 +32,8 @@ var _ = Describe("Podman pod create", func() { AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman create infra container", func() { @@ -69,6 +69,18 @@ var _ = Describe("Podman pod create", func() { Expect(len(check.OutputToStringArray())).To(Equal(1)) }) + It("podman start infra container different image", func() { + session := podmanTest.Podman([]string{"pod", "create", "--infra-image", BB}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + podID := session.OutputToString() + + session = podmanTest.Podman([]string{"pod", "start", podID}) + session.WaitWithDefaultTimeout() + // If we use the default entry point, we should exit with no error + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman infra container namespaces", func() { session := podmanTest.Podman([]string{"pod", "create"}) session.WaitWithDefaultTimeout() @@ -209,8 +221,7 @@ var _ = Describe("Podman pod create", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - podmanTest.RestoreArtifact(fedoraMinimal) - session = podmanTest.Podman([]string{"run", "--pod", podID, "--network", "bridge", fedoraMinimal, "curl", "localhost"}) + session = podmanTest.Podman([]string{"run", "--pod", podID, "--network", "bridge", nginx, "curl", "localhost"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Not(Equal(0))) }) @@ -360,4 +371,21 @@ var _ = Describe("Podman pod create", func() { Expect(result.OutputToString()).To(ContainSubstring(infraID)) }) + + It("podman run --add-host in pod", func() { + session := podmanTest.Podman([]string{"pod", "create"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + podID := session.OutputToString() + + // verify we can add a host to the infra's /etc/hosts + session = podmanTest.Podman([]string{"run", "--pod", podID, "--add-host", "foobar:127.0.0.1", BB, "ping", "-c", "1", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + // verify we can see the other hosts of infra's /etc/hosts + session = podmanTest.Podman([]string{"run", "--pod", podID, BB, "ping", "-c", "1", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) }) diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go index 457acb373..671d203a6 100644 --- a/test/e2e/pod_inspect_test.go +++ b/test/e2e/pod_inspect_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman pod inspect", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman inspect bogus pod", func() { diff --git a/test/e2e/pod_kill_test.go b/test/e2e/pod_kill_test.go index 419a3a777..c1f7503e3 100644 --- a/test/e2e/pod_kill_test.go +++ b/test/e2e/pod_kill_test.go @@ -24,14 +24,15 @@ var _ = Describe("Podman pod kill", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pod kill bogus", func() { diff --git a/test/e2e/pod_pause_test.go b/test/e2e/pod_pause_test.go index a5192f84b..59a4da176 100644 --- a/test/e2e/pod_pause_test.go +++ b/test/e2e/pod_pause_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -21,19 +20,21 @@ var _ = Describe("Podman pod pause", func() { pausedState := "Paused" BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pod pause bogus pod", func() { diff --git a/test/e2e/pod_pod_namespaces.go b/test/e2e/pod_pod_namespaces.go index 9815e37ef..9d6321c0e 100644 --- a/test/e2e/pod_pod_namespaces.go +++ b/test/e2e/pod_pod_namespaces.go @@ -24,6 +24,7 @@ var _ = Describe("Podman pod create", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() podmanTest.RestoreArtifact(infra) }) @@ -31,8 +32,8 @@ var _ = Describe("Podman pod create", func() { AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pod container share Namespaces", func() { diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go index 3b7198861..2fa26d7ad 100644 --- a/test/e2e/pod_ps_test.go +++ b/test/e2e/pod_ps_test.go @@ -25,14 +25,15 @@ var _ = Describe("Podman ps", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pod ps no pods", func() { diff --git a/test/e2e/pod_restart_test.go b/test/e2e/pod_restart_test.go index e8acfd2ec..ffb6cb94c 100644 --- a/test/e2e/pod_restart_test.go +++ b/test/e2e/pod_restart_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman pod restart", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pod restart bogus pod", func() { diff --git a/test/e2e/pod_rm_test.go b/test/e2e/pod_rm_test.go index f63d2c8aa..f9d7abe8f 100644 --- a/test/e2e/pod_rm_test.go +++ b/test/e2e/pod_rm_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman pod rm", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pod rm empty pod", func() { diff --git a/test/e2e/pod_start_test.go b/test/e2e/pod_start_test.go index ce693012d..de52af2a0 100644 --- a/test/e2e/pod_start_test.go +++ b/test/e2e/pod_start_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman pod start", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pod start bogus pod", func() { diff --git a/test/e2e/pod_stats_test.go b/test/e2e/pod_stats_test.go index e330c3a39..6018b4494 100644 --- a/test/e2e/pod_stats_test.go +++ b/test/e2e/pod_stats_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -19,19 +18,21 @@ var _ = Describe("Podman pod stats", func() { ) BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman stats should run with no pods", func() { session := podmanTest.Podman([]string{"pod", "stats", "--no-stream"}) diff --git a/test/e2e/pod_stop_test.go b/test/e2e/pod_stop_test.go index 38f118964..fa285fa80 100644 --- a/test/e2e/pod_stop_test.go +++ b/test/e2e/pod_stop_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman pod stop", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pod stop bogus pod", func() { diff --git a/test/e2e/pod_top_test.go b/test/e2e/pod_top_test.go index 507d723b4..964ee075f 100644 --- a/test/e2e/pod_top_test.go +++ b/test/e2e/pod_top_test.go @@ -5,6 +5,7 @@ package integration import ( "fmt" "os" + "time" . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" @@ -24,14 +25,15 @@ var _ = Describe("Podman top", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupPod() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pod top without pod name or id", func() { @@ -127,6 +129,13 @@ var _ = Describe("Podman top", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) + for i := 0; i < 10; i++ { + fmt.Println("Waiting for containers to be running .... ") + if podmanTest.NumberOfContainersRunning() == 2 { + break + } + time.Sleep(1 * time.Second) + } result := podmanTest.Podman([]string{"pod", "top", podid}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) diff --git a/test/e2e/port_test.go b/test/e2e/port_test.go index fa633c379..7cf3e16bf 100644 --- a/test/e2e/port_test.go +++ b/test/e2e/port_test.go @@ -25,14 +25,15 @@ var _ = Describe("Podman port", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman port all and latest", func() { @@ -60,6 +61,19 @@ var _ = Describe("Podman port", func() { Expect(result.LineInOuputStartsWith(fmt.Sprintf("80/tcp -> 0.0.0.0:%s", port))).To(BeTrue()) }) + It("podman container port -l nginx", func() { + podmanTest.RestoreArtifact(nginx) + session := podmanTest.Podman([]string{"container", "run", "-dt", "-P", nginx}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + result := podmanTest.Podman([]string{"container", "port", "-l"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + port := strings.Split(result.OutputToStringArray()[0], ":")[1] + Expect(result.LineInOuputStartsWith(fmt.Sprintf("80/tcp -> 0.0.0.0:%s", port))).To(BeTrue()) + }) + It("podman port -l port nginx", func() { podmanTest.RestoreArtifact(nginx) session := podmanTest.Podman([]string{"run", "-dt", "-P", nginx}) diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go index 74cdc126f..869ca3289 100644 --- a/test/e2e/prune_test.go +++ b/test/e2e/prune_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -28,14 +27,15 @@ var _ = Describe("Podman rm", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman container prune containers", func() { diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go index 9b1c55bb4..957c69aa8 100644 --- a/test/e2e/ps_test.go +++ b/test/e2e/ps_test.go @@ -28,14 +28,15 @@ var _ = Describe("Podman ps", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman ps no containers", func() { @@ -65,7 +66,24 @@ var _ = Describe("Podman ps", func() { Expect(len(result.OutputToStringArray())).Should(BeNumerically(">", 0)) }) + It("podman container list all", func() { + _, ec, _ := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + + result := podmanTest.Podman([]string{"container", "list", "-a"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(len(result.OutputToStringArray())).Should(BeNumerically(">", 0)) + + result = podmanTest.Podman([]string{"container", "ls", "-a"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(len(result.OutputToStringArray())).Should(BeNumerically(">", 0)) + }) + It("podman ps size flag", func() { + SkipIfRootless() + _, ec, _ := podmanTest.RunLsContainer("") Expect(ec).To(Equal(0)) @@ -217,6 +235,8 @@ var _ = Describe("Podman ps", func() { }) It("podman --sort by size", func() { + SkipIfRootless() + session := podmanTest.Podman([]string{"create", "busybox", "ls"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -256,8 +276,7 @@ var _ = Describe("Podman ps", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - podmanTest.RestoreArtifact(fedoraMinimal) - session = podmanTest.Podman([]string{"run", "-d", fedoraMinimal, "pwd"}) + session = podmanTest.Podman([]string{"run", "-d", ALPINE, "pwd"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -288,4 +307,19 @@ var _ = Describe("Podman ps", func() { Expect(session.OutputToString()).To(ContainSubstring(podid)) }) + + It("podman ps test with port range", func() { + SkipIfRootless() + session := podmanTest.RunTopContainer("") + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"run", "-dt", "-p", "1000-1006:1000-1006", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"ps", "--format", "{{.Ports}}"}) + session.WaitWithDefaultTimeout() + Expect(session.OutputToString()).To(ContainSubstring("0.0.0.0:1000-1006")) + }) }) diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go index d9b9c7213..de6d4ea09 100644 --- a/test/e2e/pull_test.go +++ b/test/e2e/pull_test.go @@ -27,14 +27,15 @@ var _ = Describe("Podman pull", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman pull from docker with tag", func() { diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go index fee117783..009067482 100644 --- a/test/e2e/push_test.go +++ b/test/e2e/push_test.go @@ -26,14 +26,15 @@ var _ = Describe("Podman push", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman push to containers/storage", func() { @@ -62,6 +63,8 @@ var _ = Describe("Podman push", func() { if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } + lock := GetPortLock("5000") + defer lock.Unlock() podmanTest.RestoreArtifact(registry) session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5000:5000", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) session.WaitWithDefaultTimeout() @@ -77,6 +80,7 @@ var _ = Describe("Podman push", func() { }) It("podman push to local registry with authorization", func() { + SkipIfRootless() if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } @@ -100,6 +104,8 @@ var _ = Describe("Podman push", func() { }() } } + lock := GetPortLock("5000") + defer lock.Unlock() podmanTest.RestoreArtifact(registry) session := podmanTest.Podman([]string{"run", "--entrypoint", "htpasswd", registry, "-Bbn", "podmantest", "test"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/refresh_test.go b/test/e2e/refresh_test.go index de331bf88..56c1d255e 100644 --- a/test/e2e/refresh_test.go +++ b/test/e2e/refresh_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" "time" @@ -25,14 +24,15 @@ var _ = Describe("Podman refresh", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tmpdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) Specify("Refresh with no containers succeeds", func() { diff --git a/test/e2e/restart_test.go b/test/e2e/restart_test.go index 5c914a367..1daf63a0e 100644 --- a/test/e2e/restart_test.go +++ b/test/e2e/restart_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" "time" @@ -25,14 +24,15 @@ var _ = Describe("Podman restart", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("Podman restart bogus container", func() { @@ -90,6 +90,21 @@ var _ = Describe("Podman restart", func() { Expect(restartTime.OutputToString()).To(Not(Equal(startTime.OutputToString()))) }) + It("Podman container restart running container", func() { + _ = podmanTest.RunTopContainer("test1") + ok := WaitForContainer(podmanTest) + Expect(ok).To(BeTrue()) + startTime := podmanTest.Podman([]string{"container", "inspect", "--format='{{.State.StartedAt}}'", "test1"}) + startTime.WaitWithDefaultTimeout() + + session := podmanTest.Podman([]string{"container", "restart", "test1"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + restartTime := podmanTest.Podman([]string{"container", "inspect", "--format='{{.State.StartedAt}}'", "test1"}) + restartTime.WaitWithDefaultTimeout() + Expect(restartTime.OutputToString()).To(Not(Equal(startTime.OutputToString()))) + }) + It("Podman restart multiple containers", func() { _, exitCode, _ := podmanTest.RunLsContainer("test1") Expect(exitCode).To(Equal(0)) diff --git a/test/e2e/rm_test.go b/test/e2e/rm_test.go index 71dacfa80..9bf742a63 100644 --- a/test/e2e/rm_test.go +++ b/test/e2e/rm_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman rm", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman rm stopped container", func() { @@ -65,6 +65,17 @@ var _ = Describe("Podman rm", func() { Expect(result.ExitCode()).To(Equal(0)) }) + It("podman container rm created container", func() { + session := podmanTest.Podman([]string{"container", "create", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid := session.OutputToString() + + result := podmanTest.Podman([]string{"container", "rm", cid}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + }) + It("podman rm running container with -f", func() { session := podmanTest.RunTopContainer("") session.WaitWithDefaultTimeout() @@ -128,9 +139,23 @@ var _ = Describe("Podman rm", func() { Expect(podmanTest.NumberOfContainers()).To(Equal(1)) }) + It("podman rm bogus container", func() { session := podmanTest.Podman([]string{"rm", "bogus"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(1)) }) + It("podman rm bogus container and a running container", func() { + session := podmanTest.RunTopContainer("test1") + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"rm", "bogus", "test1"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(125)) + + session = podmanTest.Podman([]string{"rm", "test1", "bogus"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(125)) + }) }) diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go index dcbda2df4..78d175637 100644 --- a/test/e2e/rmi_test.go +++ b/test/e2e/rmi_test.go @@ -22,14 +22,14 @@ var _ = Describe("Podman rmi", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) @@ -275,4 +275,13 @@ RUN find $LOCAL Expect(images.ExitCode()).To(Equal(0)) Expect(len(images.OutputToStringArray())).To(Equal(0)) }) + + // Don't rerun all tests; just assume that if we get that diagnostic, + // we're getting rmi + It("podman image rm is the same as rmi", func() { + session := podmanTest.Podman([]string{"image", "rm"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(125)) + Expect(session.LineInOutputContains("image name or ID must be specified")) + }) }) diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go index aa8ed6faa..51544ff8b 100644 --- a/test/e2e/rootless_test.go +++ b/test/e2e/rootless_test.go @@ -38,6 +38,7 @@ var _ = Describe("Podman rootless", func() { ) BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) @@ -45,14 +46,15 @@ var _ = Describe("Podman rootless", func() { podmanTest = PodmanTestCreate(tempdir) podmanTest.CgroupManager = "cgroupfs" podmanTest.StorageOptions = ROOTLESS_STORAGE_OPTIONS + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman rootless help|version", func() { @@ -125,7 +127,6 @@ var _ = Describe("Podman rootless", func() { env := os.Environ() env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir)) env = append(env, fmt.Sprintf("HOME=%s", home)) - env = append(env, "PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS=1") env = append(env, "USER=foo") cmd := rootlessTest.PodmanAsUser([]string{"pod", "create", "--infra=false"}, 1000, 1000, "", env) @@ -138,6 +139,21 @@ var _ = Describe("Podman rootless", func() { cmd.WaitWithDefaultTimeout() Expect(cmd.ExitCode()).To(Equal(0)) Expect(cmd.LineInOutputContains("hello")).To(BeTrue()) + + args = []string{"pod", "top", podId} + cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env) + cmd.WaitWithDefaultTimeout() + Expect(cmd.ExitCode()).To(Not(Equal(0))) + + args = []string{"run", "--pod", podId, "-d", "--rootfs", mountPath, "sleep", "100"} + cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env) + cmd.WaitWithDefaultTimeout() + Expect(cmd.ExitCode()).To(Equal(0)) + + args = []string{"pod", "top", podId} + cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env) + cmd.WaitWithDefaultTimeout() + Expect(cmd.ExitCode()).To(Equal(0)) } runInRootlessContext(f) }) @@ -170,7 +186,6 @@ var _ = Describe("Podman rootless", func() { env := os.Environ() env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir)) env = append(env, fmt.Sprintf("HOME=%s", home)) - env = append(env, "PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS=1") env = append(env, "USER=foo") allArgs := append([]string{"run"}, args...) diff --git a/test/e2e/run_cgroup_parent_test.go b/test/e2e/run_cgroup_parent_test.go index efc9a7009..0d04c5f03 100644 --- a/test/e2e/run_cgroup_parent_test.go +++ b/test/e2e/run_cgroup_parent_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -19,19 +18,21 @@ var _ = Describe("Podman run with --cgroup-parent", func() { ) BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreArtifact(fedoraMinimal) }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) Specify("valid --cgroup-parent using cgroupfs", func() { diff --git a/test/e2e/run_cleanup_test.go b/test/e2e/run_cleanup_test.go index 1f2a4085d..b20e37794 100644 --- a/test/e2e/run_cleanup_test.go +++ b/test/e2e/run_cleanup_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman run exit", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run -d mount cleanup test", func() { diff --git a/test/e2e/run_cpu_test.go b/test/e2e/run_cpu_test.go index f74d3ed84..42a66865c 100644 --- a/test/e2e/run_cpu_test.go +++ b/test/e2e/run_cpu_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,17 +23,19 @@ var _ = Describe("Podman run cpu", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run cpu-period", func() { + SkipIfRootless() result := podmanTest.Podman([]string{"run", "--rm", "--cpu-period=5000", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_period_us"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -42,6 +43,7 @@ var _ = Describe("Podman run cpu", func() { }) It("podman run cpu-quota", func() { + SkipIfRootless() result := podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -49,6 +51,7 @@ var _ = Describe("Podman run cpu", func() { }) It("podman run cpus", func() { + SkipIfRootless() result := podmanTest.Podman([]string{"run", "--rm", "--cpus=0.5", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_period_us"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -61,6 +64,7 @@ var _ = Describe("Podman run cpu", func() { }) It("podman run cpu-shares", func() { + SkipIfRootless() result := podmanTest.Podman([]string{"run", "--rm", "--cpu-shares=2", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.shares"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -68,6 +72,7 @@ var _ = Describe("Podman run cpu", func() { }) It("podman run cpuset-cpus", func() { + SkipIfRootless() result := podmanTest.Podman([]string{"run", "--rm", "--cpuset-cpus=0", ALPINE, "cat", "/sys/fs/cgroup/cpuset/cpuset.cpus"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -75,6 +80,7 @@ var _ = Describe("Podman run cpu", func() { }) It("podman run cpuset-mems", func() { + SkipIfRootless() result := podmanTest.Podman([]string{"run", "--rm", "--cpuset-mems=0", ALPINE, "cat", "/sys/fs/cgroup/cpuset/cpuset.mems"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) diff --git a/test/e2e/run_device_test.go b/test/e2e/run_device_test.go index 4f26ac8ee..fac09b78d 100644 --- a/test/e2e/run_device_test.go +++ b/test/e2e/run_device_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman run device", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run bad device test", func() { @@ -41,6 +41,7 @@ var _ = Describe("Podman run device", func() { }) It("podman run device test", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/kmsg", ALPINE, "ls", "--color=never", "/dev/kmsg"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -48,6 +49,7 @@ var _ = Describe("Podman run device", func() { }) It("podman run device rename test", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/kmsg:/dev/kmsg1", ALPINE, "ls", "--color=never", "/dev/kmsg1"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -55,6 +57,7 @@ var _ = Describe("Podman run device", func() { }) It("podman run device permission test", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/kmsg:r", ALPINE, "ls", "--color=never", "/dev/kmsg"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -62,6 +65,7 @@ var _ = Describe("Podman run device", func() { }) It("podman run device rename and permission test", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/kmsg:/dev/kmsg1:r", ALPINE, "ls", "--color=never", "/dev/kmsg1"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -72,4 +76,13 @@ var _ = Describe("Podman run device", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Not(Equal(0))) }) + + It("podman run device host device and container device parameter are directories", func() { + SkipIfRootless() + SystemExec("mkdir", []string{"/dev/foodevdir"}) + SystemExec("mknod", []string{"/dev/foodevdir/null", "c", "1", "3"}) + session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/foodevdir:/dev/bar", ALPINE, "ls", "/dev/bar/null"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) }) diff --git a/test/e2e/run_dns_test.go b/test/e2e/run_dns_test.go index 6c649cdbc..0f4dd6742 100644 --- a/test/e2e/run_dns_test.go +++ b/test/e2e/run_dns_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman run dns", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run add search domain", func() { @@ -88,6 +88,7 @@ var _ = Describe("Podman run dns", func() { }) It("podman run add hostname sets /etc/hosts", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "-t", "-i", "--hostname=foobar", ALPINE, "cat", "/etc/hosts"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) diff --git a/test/e2e/run_entrypoint_test.go b/test/e2e/run_entrypoint_test.go index a33e16b63..ee9fd1263 100644 --- a/test/e2e/run_entrypoint_test.go +++ b/test/e2e/run_entrypoint_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman run entrypoint", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreArtifact(ALPINE) }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run no command, entrypoint, or cmd", func() { diff --git a/test/e2e/run_exit_test.go b/test/e2e/run_exit_test.go index 03072f598..da4cf7ee7 100644 --- a/test/e2e/run_exit_test.go +++ b/test/e2e/run_exit_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman run exit", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run exit 125", func() { @@ -59,8 +59,7 @@ var _ = Describe("Podman run exit", func() { }) It("podman run exit 50", func() { - podmanTest.RestoreArtifact(fedoraMinimal) - result := podmanTest.Podman([]string{"run", "registry.fedoraproject.org/fedora-minimal", "bash", "-c", "exit 50"}) + result := podmanTest.Podman([]string{"run", ALPINE, "sh", "-c", "exit 50"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(50)) }) diff --git a/test/e2e/run_memory_test.go b/test/e2e/run_memory_test.go index e9262d4f0..05d0b7a18 100644 --- a/test/e2e/run_memory_test.go +++ b/test/e2e/run_memory_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -19,19 +18,21 @@ var _ = Describe("Podman run memory", func() { ) BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run memory test", func() { diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index c89a4f487..93919925c 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -25,14 +24,15 @@ var _ = Describe("Podman run networking", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run network connection with default bridge", func() { @@ -54,6 +54,7 @@ var _ = Describe("Podman run networking", func() { }) It("podman run network expose port 222", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "-dt", "--expose", "222-223", "-P", ALPINE, "/bin/sh"}) session.Wait(30) Expect(session.ExitCode()).To(Equal(0)) @@ -64,6 +65,7 @@ var _ = Describe("Podman run networking", func() { }) It("podman run network expose host port 80 to container port 8000", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "-dt", "-p", "80:8000", ALPINE, "/bin/sh"}) session.Wait(30) Expect(session.ExitCode()).To(Equal(0)) @@ -146,6 +148,7 @@ var _ = Describe("Podman run networking", func() { }) It("podman run --net container: copies hosts and resolv", func() { + SkipIfRootless() ctrName := "ctr1" ctr1 := podmanTest.RunTopContainer(ctrName) ctr1.WaitWithDefaultTimeout() @@ -177,6 +180,7 @@ var _ = Describe("Podman run networking", func() { }) It("podman run network in user created network namespace", func() { + SkipIfRootless() if Containerized() { Skip("Can not be run within a container.") } @@ -193,6 +197,7 @@ var _ = Describe("Podman run networking", func() { }) It("podman run n user created network namespace with resolv.conf", func() { + SkipIfRootless() if Containerized() { Skip("Can not be run within a container.") } diff --git a/test/e2e/run_ns_test.go b/test/e2e/run_ns_test.go index 3d95c3a0b..5236e6584 100644 --- a/test/e2e/run_ns_test.go +++ b/test/e2e/run_ns_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" "strings" @@ -25,14 +24,15 @@ var _ = Describe("Podman run ns", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreArtifact(fedoraMinimal) }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run pidns test", func() { @@ -63,6 +63,7 @@ var _ = Describe("Podman run ns", func() { }) It("podman run ipcns ipcmk host test", func() { + SkipIfRootless() setup := SystemExec("ipcmk", []string{"-M", "1024"}) Expect(setup.ExitCode()).To(Equal(0)) output := strings.Split(setup.OutputToString(), " ") @@ -76,6 +77,7 @@ var _ = Describe("Podman run ns", func() { }) It("podman run ipcns ipcmk container test", func() { + SkipIfRootless() setup := podmanTest.Podman([]string{"run", "-d", "--name", "test1", fedoraMinimal, "sleep", "999"}) setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) diff --git a/test/e2e/run_passwd_test.go b/test/e2e/run_passwd_test.go index fcb81fb77..becbc5bfa 100644 --- a/test/e2e/run_passwd_test.go +++ b/test/e2e/run_passwd_test.go @@ -5,7 +5,6 @@ package integration import ( "os" - "fmt" . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -24,14 +23,15 @@ var _ = Describe("Podman run passwd", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run no user specified ", func() { diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go index ee6e8e950..16011b2fd 100644 --- a/test/e2e/run_privileged_test.go +++ b/test/e2e/run_privileged_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" "strings" @@ -25,14 +24,15 @@ var _ = Describe("Podman privileged container tests", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman privileged make sure sys is mounted rw", func() { @@ -45,6 +45,7 @@ var _ = Describe("Podman privileged container tests", func() { }) It("podman privileged CapEff", func() { + SkipIfRootless() cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"}) Expect(cap.ExitCode()).To(Equal(0)) @@ -55,6 +56,7 @@ var _ = Describe("Podman privileged container tests", func() { }) It("podman cap-add CapEff", func() { + SkipIfRootless() cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"}) Expect(cap.ExitCode()).To(Equal(0)) @@ -80,6 +82,7 @@ var _ = Describe("Podman privileged container tests", func() { }) It("podman privileged should inherit host devices", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--privileged", ALPINE, "ls", "-l", "/dev"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) diff --git a/test/e2e/run_restart_test.go b/test/e2e/run_restart_test.go index 2659d2b11..9976b45e8 100644 --- a/test/e2e/run_restart_test.go +++ b/test/e2e/run_restart_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman run restart containers", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("Podman start after successful run", func() { diff --git a/test/e2e/run_selinux_test.go b/test/e2e/run_selinux_test.go index 57e488abc..4d2bad49c 100644 --- a/test/e2e/run_selinux_test.go +++ b/test/e2e/run_selinux_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -25,6 +24,7 @@ var _ = Describe("Podman run", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() if !selinux.GetEnabled() { Skip("SELinux not enabled") @@ -34,8 +34,8 @@ var _ = Describe("Podman run", func() { AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run selinux", func() { @@ -112,6 +112,7 @@ var _ = Describe("Podman run", func() { }) It("podman test selinux label /run/secrets", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", fedoraMinimal, "ls", "-dZ", "/run/secrets"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -144,6 +145,7 @@ var _ = Describe("Podman run", func() { }) It("podman test selinux --privileged label /run/secrets", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--privileged", fedoraMinimal, "ls", "-dZ", "/run/secrets"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) diff --git a/test/e2e/run_signal_test.go b/test/e2e/run_signal_test.go index 51c14602e..e482adb84 100644 --- a/test/e2e/run_signal_test.go +++ b/test/e2e/run_signal_test.go @@ -32,14 +32,15 @@ var _ = Describe("Podman run with --sig-proxy", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tmpdir) + podmanTest.Setup() podmanTest.RestoreArtifact(fedoraMinimal) }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) Specify("signals are forwarded to container using sig-proxy", func() { diff --git a/test/e2e/run_staticip_test.go b/test/e2e/run_staticip_test.go index bf50e5eb7..318a7a62d 100644 --- a/test/e2e/run_staticip_test.go +++ b/test/e2e/run_staticip_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -19,11 +18,13 @@ var _ = Describe("Podman run with --ip flag", func() { ) BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() // Cleanup the CNI networks used by the tests os.RemoveAll("/var/lib/cni/networks/podman") @@ -32,8 +33,8 @@ var _ = Describe("Podman run with --ip flag", func() { AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("Podman run --ip with garbage address", func() { diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 93ee5036f..b0dc66707 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -29,14 +29,15 @@ var _ = Describe("Podman run", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman run a container based on local image", func() { @@ -46,6 +47,7 @@ var _ = Describe("Podman run", func() { }) It("podman run a container based on a complex local image name", func() { + SkipIfRootless() imageName := strings.TrimPrefix(nginx, "quay.io/") podmanTest.RestoreArtifact(nginx) session := podmanTest.Podman([]string{"run", imageName, "ls"}) @@ -68,6 +70,20 @@ var _ = Describe("Podman run", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman container run a container based on on a short name with localhost", func() { + podmanTest.RestoreArtifact(nginx) + tag := podmanTest.Podman([]string{"image", "tag", nginx, "localhost/libpod/alpine_nginx:latest"}) + tag.WaitWithDefaultTimeout() + + rmi := podmanTest.Podman([]string{"image", "rm", nginx}) + rmi.WaitWithDefaultTimeout() + + session := podmanTest.Podman([]string{"container", "run", "libpod/alpine_nginx:latest", "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull")) + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman run a container based on local image with short options", func() { session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "ls"}) session.WaitWithDefaultTimeout() @@ -136,10 +152,10 @@ var _ = Describe("Podman run", func() { }) It("podman run environment test", func() { - session := podmanTest.Podman([]string{"run", "--rm", "--env", "FOO=BAR", ALPINE, "printenv", "FOO"}) + session := podmanTest.Podman([]string{"run", "--rm", "--env", "FOO=BAR,BAZ", ALPINE, "printenv", "FOO"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - match, _ := session.GrepString("BAR") + match, _ := session.GrepString("BAR,BAZ") Expect(match).Should(BeTrue()) session = podmanTest.Podman([]string{"run", "--rm", "--env", "PATH=/bin", ALPINE, "printenv", "PATH"}) @@ -170,6 +186,7 @@ var _ = Describe("Podman run", func() { }) It("podman run limits test", func() { + SkipIfRootless() podmanTest.RestoreArtifact(fedoraMinimal) session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "rtprio=99", "--cap-add=sys_nice", fedoraMinimal, "cat", "/proc/self/sched"}) session.WaitWithDefaultTimeout() @@ -196,6 +213,7 @@ var _ = Describe("Podman run", func() { }) It("podman run with volume flag", func() { + SkipIfRootless() Skip("Skip until we diagnose the regression of volume mounts") mountPath := filepath.Join(podmanTest.TempDir, "secrets") os.Mkdir(mountPath, 0755) @@ -260,6 +278,7 @@ var _ = Describe("Podman run", func() { }) It("podman run sysctl test", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", "--sysctl", "net.core.somaxconn=65535", ALPINE, "sysctl", "net.core.somaxconn"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -267,6 +286,7 @@ var _ = Describe("Podman run", func() { }) It("podman run blkio-weight test", func() { + SkipIfRootless() if _, err := os.Stat("/sys/fs/cgroup/blkio/blkio.weight"); os.IsNotExist(err) { Skip("Kernel does not support blkio.weight") } @@ -277,6 +297,7 @@ var _ = Describe("Podman run", func() { }) It("podman run device-read-bps test", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -284,6 +305,7 @@ var _ = Describe("Podman run", func() { }) It("podman run device-write-bps test", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -291,6 +313,7 @@ var _ = Describe("Podman run", func() { }) It("podman run device-read-iops test", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -298,6 +321,7 @@ var _ = Describe("Podman run", func() { }) It("podman run device-write-iops test", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -401,6 +425,7 @@ var _ = Describe("Podman run", func() { }) It("podman run with FIPS mode secrets", func() { + SkipIfRootless() fipsFile := "/etc/system-fips" err = ioutil.WriteFile(fipsFile, []byte{}, 0755) Expect(err).To(BeNil()) @@ -415,6 +440,7 @@ var _ = Describe("Podman run", func() { }) It("podman run without group-add", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -422,6 +448,7 @@ var _ = Describe("Podman run", func() { }) It("podman run with group-add", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", "--group-add=audio", "--group-add=nogroup", "--group-add=777", ALPINE, "id"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -429,6 +456,7 @@ var _ = Describe("Podman run", func() { }) It("podman run with user (default)", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -443,6 +471,7 @@ var _ = Describe("Podman run", func() { }) It("podman run with user (integer, in /etc/passwd)", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", "--user=8", ALPINE, "id"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -450,6 +479,7 @@ var _ = Describe("Podman run", func() { }) It("podman run with user (username)", func() { + SkipIfRootless() session := podmanTest.Podman([]string{"run", "--rm", "--user=mail", ALPINE, "id"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -704,4 +734,28 @@ USER mail` Expect(session.OutputToString()).To(Not(ContainSubstring("/dev/shm type tmpfs (ro,"))) }) + + It("podman run with bad healthcheck interval", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--healthcheck-cmd", "foo", "--healthcheck-interval", "0.5s", ALPINE, "top"}) + session.Wait() + Expect(session.ExitCode()).ToNot(Equal(0)) + }) + + It("podman run with bad healthcheck retries", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--healthcheck-cmd", "foo", "--healthcheck-retries", "0", ALPINE, "top"}) + session.Wait() + Expect(session.ExitCode()).ToNot(Equal(0)) + }) + + It("podman run with bad healthcheck timeout", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--healthcheck-cmd", "foo", "--healthcheck-timeout", "0s", ALPINE, "top"}) + session.Wait() + Expect(session.ExitCode()).ToNot(Equal(0)) + }) + + It("podman run with bad healthcheck start-period", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--healthcheck-cmd", "foo", "--healthcheck-start-period", "-1s", ALPINE, "top"}) + session.Wait() + Expect(session.ExitCode()).ToNot(Equal(0)) + }) }) diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go index 254897e70..5c38a8950 100644 --- a/test/e2e/run_userns_test.go +++ b/test/e2e/run_userns_test.go @@ -5,7 +5,6 @@ package integration import ( "os" - "fmt" . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -19,19 +18,21 @@ var _ = Describe("Podman UserNS support", func() { ) BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman uidmapping and gidmapping", func() { @@ -68,6 +69,21 @@ var _ = Describe("Podman UserNS support", func() { Expect(ok).To(BeTrue()) }) + It("podman uidmapping and gidmapping with a volume", func() { + if os.Getenv("SKIP_USERNS") != "" { + Skip("Skip userns tests.") + } + if _, err := os.Stat("/proc/self/uid_map"); err != nil { + Skip("User namespaces not supported.") + } + + session := podmanTest.Podman([]string{"run", "--uidmap=0:1:70000", "--gidmap=0:20000:70000", "-v", "my-foo-volume:/foo:Z", "busybox", "echo", "hello"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + ok, _ := session.GrepString("hello") + Expect(ok).To(BeTrue()) + }) + It("podman uidmapping and gidmapping --net=host", func() { if os.Getenv("SKIP_USERNS") != "" { Skip("Skip userns tests.") diff --git a/test/e2e/runlabel_test.go b/test/e2e/runlabel_test.go index 49b9e13d8..b1d057bfd 100644 --- a/test/e2e/runlabel_test.go +++ b/test/e2e/runlabel_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -32,14 +31,14 @@ var _ = Describe("podman container runlabel", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) }) diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go index 9f64e49a7..c3edc7c7e 100644 --- a/test/e2e/save_test.go +++ b/test/e2e/save_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" "path/filepath" @@ -23,14 +22,15 @@ var _ = Describe("Podman save", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman save output flag", func() { diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go index 167f8fa25..589389b3b 100644 --- a/test/e2e/search_test.go +++ b/test/e2e/search_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" "strconv" @@ -44,14 +43,15 @@ var _ = Describe("Podman search", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman search", func() { @@ -134,6 +134,9 @@ var _ = Describe("Podman search", func() { if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } + lock := GetPortLock("5000") + defer lock.Unlock() + podmanTest.RestoreArtifact(registry) fakereg := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5000:5000", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) fakereg.WaitWithDefaultTimeout() @@ -157,6 +160,8 @@ var _ = Describe("Podman search", func() { if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } + lock := GetPortLock("5000") + defer lock.Unlock() podmanTest.RestoreArtifact(registry) registry := podmanTest.Podman([]string{"run", "-d", "--name", "registry3", "-p", "5000:5000", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) registry.WaitWithDefaultTimeout() @@ -180,6 +185,8 @@ var _ = Describe("Podman search", func() { if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } + lock := GetPortLock("5000") + defer lock.Unlock() podmanTest.RestoreArtifact(registry) registry := podmanTest.Podman([]string{"run", "-d", "--name", "registry4", "-p", "5000:5000", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) registry.WaitWithDefaultTimeout() @@ -212,6 +219,8 @@ var _ = Describe("Podman search", func() { if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } + lock := GetPortLock("5000") + defer lock.Unlock() podmanTest.RestoreArtifact(registry) registry := podmanTest.Podman([]string{"run", "-d", "-p", "5000:5000", "--name", "registry5", registry}) registry.WaitWithDefaultTimeout() @@ -243,6 +252,8 @@ var _ = Describe("Podman search", func() { if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } + lock := GetPortLock("5000") + defer lock.Unlock() podmanTest.RestoreArtifact(registry) registry := podmanTest.Podman([]string{"run", "-d", "-p", "5000:5000", "--name", "registry6", registry}) registry.WaitWithDefaultTimeout() @@ -274,6 +285,8 @@ var _ = Describe("Podman search", func() { if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } + lock := GetPortLock("5000") + defer lock.Unlock() podmanTest.RestoreArtifact(registry) registryLocal := podmanTest.Podman([]string{"run", "-d", "-p", "5000:5000", "--name", "registry7", registry}) registryLocal.WaitWithDefaultTimeout() diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go index c4ed6f545..28f1c2393 100644 --- a/test/e2e/start_test.go +++ b/test/e2e/start_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman start", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman start bogus container", func() { @@ -50,6 +50,16 @@ var _ = Describe("Podman start", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman container start single container by id", func() { + session := podmanTest.Podman([]string{"container", "create", "-d", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid := session.OutputToString() + session = podmanTest.Podman([]string{"container", "start", cid}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman start single container by name", func() { session := podmanTest.Podman([]string{"create", "-d", "--name", "foobar99", ALPINE, "ls"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go index e7b0b5f6e..05f24539f 100644 --- a/test/e2e/stats_test.go +++ b/test/e2e/stats_test.go @@ -19,19 +19,21 @@ var _ = Describe("Podman stats", func() { ) BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman stats with bogus container", func() { diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go index 8fffedbb9..97c9287b9 100644 --- a/test/e2e/stop_test.go +++ b/test/e2e/stop_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman stop", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman stop bogus container", func() { @@ -59,6 +59,15 @@ var _ = Describe("Podman stop", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman stop container by name", func() { + session := podmanTest.RunTopContainer("test1") + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.Podman([]string{"container", "stop", "test1"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman stop stopped container", func() { session := podmanTest.RunTopContainer("test1") session.WaitWithDefaultTimeout() @@ -73,7 +82,7 @@ var _ = Describe("Podman stop", func() { Expect(session3.ExitCode()).To(Equal(0)) }) - It("podman stop all containers", func() { + It("podman stop all containers -t", func() { session := podmanTest.RunTopContainer("test1") session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -98,6 +107,32 @@ var _ = Describe("Podman stop", func() { Expect(output).To(ContainSubstring(cid3)) }) + It("podman stop container --time", func() { + session := podmanTest.RunTopContainer("test4") + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid1 := session.OutputToString() + + session = podmanTest.Podman([]string{"stop", "--time", "1", "test4"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + output := session.OutputToString() + Expect(output).To(ContainSubstring(cid1)) + }) + + It("podman stop container --timeout", func() { + session := podmanTest.RunTopContainer("test5") + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid1 := session.OutputToString() + + session = podmanTest.Podman([]string{"stop", "--timeout", "1", "test5"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + output := session.OutputToString() + Expect(output).To(ContainSubstring(cid1)) + }) + It("podman stop latest containers", func() { session := podmanTest.RunTopContainer("test1") session.WaitWithDefaultTimeout() diff --git a/test/e2e/system_df_test.go b/test/e2e/system_df_test.go new file mode 100644 index 000000000..92787f17c --- /dev/null +++ b/test/e2e/system_df_test.go @@ -0,0 +1,62 @@ +// +build !remoteclient + +package integration + +import ( + "fmt" + "os" + "strings" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("podman system df", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.RestoreAllArtifacts() + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) + GinkgoWriter.Write([]byte(timedResult)) + }) + + It("podman system df", func() { + session := podmanTest.Podman([]string{"create", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"volume", "create", "data"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"create", "-v", "data:/data", "--name", "container1", "busybox"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"system", "df"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(Equal(4)) + images := strings.Fields(session.OutputToStringArray()[1]) + containers := strings.Fields(session.OutputToStringArray()[2]) + volumes := strings.Fields(session.OutputToStringArray()[3]) + Expect(images[1]).To(Equal("2")) + Expect(containers[1]).To(Equal("2")) + Expect(volumes[2]).To(Equal("1")) + }) +}) diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index 252361288..52efc9fca 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "io/ioutil" "os" @@ -21,11 +20,13 @@ var _ = Describe("Podman systemd", func() { ) BeforeEach(func() { + SkipIfRootless() tempdir, err = CreateTempDirInTempDir() if err != nil { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() systemd_unit_file = `[Unit] Description=redis container @@ -42,8 +43,8 @@ WantedBy=multi-user.target AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman start container by systemd", func() { diff --git a/test/e2e/tag_test.go b/test/e2e/tag_test.go index 9f67eaf80..ff0ac31c4 100644 --- a/test/e2e/tag_test.go +++ b/test/e2e/tag_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman tag", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman tag shortname:latest", func() { diff --git a/test/e2e/top_test.go b/test/e2e/top_test.go index 067358468..2d3a5629c 100644 --- a/test/e2e/top_test.go +++ b/test/e2e/top_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman top", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman top without container name or id", func() { @@ -65,6 +65,17 @@ var _ = Describe("Podman top", func() { Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1)) }) + It("podman container top on container", func() { + session := podmanTest.Podman([]string{"container", "run", "-d", ALPINE, "top", "-d", "2"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + result := podmanTest.Podman([]string{"container", "top", "-l"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1)) + }) + It("podman top with options", func() { session := podmanTest.Podman([]string{"run", "-d", ALPINE, "top", "-d", "2"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/tree_test.go b/test/e2e/tree_test.go new file mode 100644 index 000000000..9740adada --- /dev/null +++ b/test/e2e/tree_test.go @@ -0,0 +1,64 @@ +package integration + +import ( + "fmt" + "os" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman image tree", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.RestoreAllArtifacts() + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) + GinkgoWriter.Write([]byte(timedResult)) + }) + + It("podman image tree", func() { + if podmanTest.RemoteTest { + Skip("Does not work on remote client") + } + session := podmanTest.Podman([]string{"pull", "docker.io/library/busybox:latest"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + dockerfile := `FROM docker.io/library/busybox:latest +RUN mkdir hello +RUN touch test.txt +ENV foo=bar +` + podmanTest.BuildImage(dockerfile, "test:latest", "true") + + session = podmanTest.Podman([]string{"image", "tree", "test:latest"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.Podman([]string{"image", "tree", "--whatrequires", "docker.io/library/busybox:latest"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"rmi", "test:latest"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.Podman([]string{"rmi", "docker.io/library/busybox:latest"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) +}) diff --git a/test/e2e/trust_test.go b/test/e2e/trust_test.go index 0d36266f6..493c4a7d5 100644 --- a/test/e2e/trust_test.go +++ b/test/e2e/trust_test.go @@ -4,7 +4,6 @@ package integration import ( "encoding/json" - "fmt" "io/ioutil" "os" "path/filepath" @@ -27,14 +26,15 @@ var _ = Describe("Podman trust", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman image trust show", func() { diff --git a/test/e2e/version_test.go b/test/e2e/version_test.go index 68a462bdb..f546158a9 100644 --- a/test/e2e/version_test.go +++ b/test/e2e/version_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -27,8 +26,8 @@ var _ = Describe("Podman version", func() { AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman version", func() { @@ -37,4 +36,24 @@ var _ = Describe("Podman version", func() { Expect(session.ExitCode()).To(Equal(0)) Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 2)) }) + + It("podman version --format json", func() { + session := podmanTest.Podman([]string{"version", "--format", "json"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.IsJSONOutputValid()).To(BeTrue()) + }) + + It("podman version --format json", func() { + session := podmanTest.Podman([]string{"version", "--format", "{{ json .}}"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.IsJSONOutputValid()).To(BeTrue()) + }) + + It("podman version --format GO template", func() { + session := podmanTest.Podman([]string{"version", "--format", "{{ .Version }}"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) }) diff --git a/test/e2e/volume_create_test.go b/test/e2e/volume_create_test.go index 50ee63f2a..dccecd457 100644 --- a/test/e2e/volume_create_test.go +++ b/test/e2e/volume_create_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -22,14 +21,15 @@ var _ = Describe("Podman volume create", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupVolume() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman create volume", func() { diff --git a/test/e2e/volume_inspect_test.go b/test/e2e/volume_inspect_test.go index d0d5a601e..e7f20ce7b 100644 --- a/test/e2e/volume_inspect_test.go +++ b/test/e2e/volume_inspect_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -22,14 +21,15 @@ var _ = Describe("Podman volume inspect", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupVolume() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman inspect volume", func() { diff --git a/test/e2e/volume_ls_test.go b/test/e2e/volume_ls_test.go index 119d29d9b..1f0177def 100644 --- a/test/e2e/volume_ls_test.go +++ b/test/e2e/volume_ls_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -22,14 +21,15 @@ var _ = Describe("Podman volume ls", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupVolume() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman ls volume", func() { diff --git a/test/e2e/volume_prune_test.go b/test/e2e/volume_prune_test.go index 802f3fc4a..55a95c8c9 100644 --- a/test/e2e/volume_prune_test.go +++ b/test/e2e/volume_prune_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman volume prune", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupVolume() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman prune volume", func() { diff --git a/test/e2e/volume_rm_test.go b/test/e2e/volume_rm_test.go index 6a1e7d0e8..888474670 100644 --- a/test/e2e/volume_rm_test.go +++ b/test/e2e/volume_rm_test.go @@ -1,7 +1,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -22,14 +21,15 @@ var _ = Describe("Podman volume rm", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.CleanupVolume() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman rm volume", func() { diff --git a/test/e2e/wait_test.go b/test/e2e/wait_test.go index 08da97aa0..5bf0331e5 100644 --- a/test/e2e/wait_test.go +++ b/test/e2e/wait_test.go @@ -3,7 +3,6 @@ package integration import ( - "fmt" "os" . "github.com/containers/libpod/test/utils" @@ -24,14 +23,15 @@ var _ = Describe("Podman wait", func() { os.Exit(1) } podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() podmanTest.RestoreAllArtifacts() }) AfterEach(func() { podmanTest.Cleanup() f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) + processTestResult(f) + }) It("podman wait on bogus container", func() { @@ -66,4 +66,11 @@ var _ = Describe("Podman wait", func() { session = podmanTest.Podman([]string{"wait", "-l"}) session.Wait(20) }) + It("podman container wait on latest container", func() { + session := podmanTest.Podman([]string{"container", "run", "-d", ALPINE, "sleep", "1"}) + session.Wait(20) + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.Podman([]string{"container", "wait", "-l"}) + session.Wait(20) + }) }) diff --git a/test/system/000-TEMPLATE b/test/system/000-TEMPLATE new file mode 100644 index 000000000..85e25e921 --- /dev/null +++ b/test/system/000-TEMPLATE @@ -0,0 +1,114 @@ +#!/usr/bin/env bats -*- bats -*- +# +# FIXME: short description of the purpose of this module +# +# FIXME: copy this file to 'NNN-yourtestname.bats' and edit as needed. +# + +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'" +} + +# vim: filetype=sh + +############################################################################### +# +# FIXME FIXME FIXME: Most of the time you can cut from here on down. +# FIXME FIXME FIXME: The above template is probably enough for many tests. +# FIXME FIXME FIXME: +# FIXME FIXME FIXME: If you need anything more complicated, read on. +# +# FIXME: This is a bloated test template. It provides mostly stuff for you +# FIXME: to remove, plus stuff for you to base your tests on. +# FIXME: +# FIXME: copy this file to 'NNN-yourtestname.bats' and edit as needed. +# FIXME: Read all FIXMEs, act on them as needed, then remove them. +# FIXME: test w/ $ PODMAN=./bin/podman bats test/system/NNN-yourtestname.bats +# + +load helpers + +# FIXME: DELETE THESE LINES UNLESS YOU ABSOLUTELY NEED THEM. +# FIXME: Most tests will not need a custom setup/teardown: they are +# FIXME: provided by helpers.bash. +# FIXME: But if you have to do anything special, these give you the +# FIXME: names of the standard setup/teardown so you can call them +# FIXME: before or after your own additions. +function setup() { + basic_setup + # FIXME: you almost certainly want to do your own setup _after_ basic. +} +function teardown() { + # FIXME: you almost certainly want to do your own teardown _before_ basic. + basic_teardown +} + + +# FIXME: very basic one-pass example +@test "podman FOO - description of test" { + # FIXME: please try to remove this line; that is, try to write tests + # that will pass as both root and rootless. + skip_if_rootless "Short explanation of why this doesn't work rootless" + + # FIXME: template for run commands. Always use 'run_podman'! + # FIXME: The '?' means 'ignore exit status'; use a number if you + # FIXME: expect a precise nonzero code, or omit for 0 (usual case). + # FIXME: NEVER EVER RUN 'podman' DIRECTLY. See helpers.bash for why. + run_podman '?' run -d $IMAGE sh -c 'prep..; echo READY' + cid="$output" + wait_for_ready $cid + + run_podman logs $cid + # 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" + + # Clean up + run_podman rm $cid +} + + +# FIXME: another example, this time with a test table loop +@test "podman FOO - json - template for playing with json output" { + # FIXME: Define a multiline string in tabular form, using '|' as separator. + # FIXME: Each row defines one test. Each column (there may be as many as + # FIXME: you want) is one field. In the case below we have two, a + # FIXME: json field descriptor and an expected value. + tests=" +id | [0-9a-f]\\\{64\\\} +created | [0-9-]\\\+T[0-9:]\\\+\\\.[0-9]\\\+Z +size | -\\\?[0-9]\\\+ +" + + # FIXME: Run a basic podman command. We'll check $output multiple times + # FIXME: in the while loop below. + 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 + # 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. + if [ "$field" = "id" ]; then expect="$expect\|<missing>";fi + + # output is an array of dicts; check each one + count=$(echo "$output" | jq '. | length') + i=0 + while [ $i -lt $count ]; do + actual=$(echo "$output" | jq -r ".[$i].$field") + # 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" + i=$(expr $i + 1) + done + done +} + + +# vim: filetype=sh diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats new file mode 100644 index 000000000..85b9bc1ca --- /dev/null +++ b/test/system/001-basic.bats @@ -0,0 +1,50 @@ +#!/usr/bin/env bats +# +# Simplest set of podman tests. If any of these fail, we have serious problems. +# + +load helpers + +# Override standard setup! We don't yet trust podman-images or podman-rm +function setup() { + : +} + +@test "podman version emits reasonable output" { + run_podman version + + is "${lines[0]}" "Version:[ ]\+[1-9][0-9.]\+" "Version line 1" + is "$output" ".*Go Version: \+" "'Go Version' in output" + is "$output" ".*RemoteAPI Version: \+" "API version in output" +} + + +@test "podman can pull an image" { + run_podman pull $IMAGE +} + +# This is for development only; it's intended to make sure our timeout +# in run_podman continues to work. This test should never run in production +# because it will, by definition, fail. +@test "timeout" { + if [ -z "$PODMAN_RUN_TIMEOUT_TEST" ]; then + skip "define \$PODMAN_RUN_TIMEOUT_TEST to enable this test" + fi + PODMAN_TIMEOUT=10 run_podman run $IMAGE sleep 90 + echo "*** SHOULD NEVER GET HERE" +} + + +# Too many tests rely on jq for parsing JSON. +# +# If absolutely necessary, one could establish a convention such as +# defining PODMAN_TEST_SKIP_JQ=1 and adding a skip_if_no_jq() helper. +# For now, let's assume this is not absolutely necessary. +@test "jq is installed and produces reasonable output" { + type -path jq >/dev/null || die "FATAL: 'jq' tool not found." + + run jq -r .a.b < <(echo '{ "a": { "b" : "you found me" } }') + is "$output" "you found me" "sample invocation of 'jq'" +} + +# vim: filetype=sh diff --git a/test/system/005-info.bats b/test/system/005-info.bats new file mode 100644 index 000000000..7dcc78838 --- /dev/null +++ b/test/system/005-info.bats @@ -0,0 +1,54 @@ +#!/usr/bin/env bats + +load helpers + +@test "podman info - basic test" { + run_podman info + + expected_keys=" +BuildahVersion: *[0-9.]\\\+ +Conmon:\\\s\\\+package: +Distribution: +OCIRuntime:\\\s\\\+package: +os: +rootless: +insecure registries: +store: +GraphDriverName: +GraphRoot: +GraphStatus: +ImageStore:\\\s\\\+number: 1 +RunRoot: +" + while read expect; do + is "$output" ".*$expect" "output includes '$expect'" + done < <(parse_table "$expected_keys") +} + +@test "podman info - json" { + run_podman info --format=json + + expr_nvr="[a-z0-9-]\\\+-[a-z0-9.]\\\+-[a-z0-9]\\\+\." + expr_path="/[a-z0-9\\\/.]\\\+\\\$" + + tests=" +host.BuildahVersion | [0-9.] +host.Conmon.package | $expr_nvr +host.Conmon.path | $expr_path +host.OCIRuntime.package | $expr_nvr +host.OCIRuntime.path | $expr_path +store.ConfigFile | $expr_path +store.GraphDriverName | [a-z0-9]\\\+\\\$ +store.GraphRoot | $expr_path +store.ImageStore.number | 1 +" + + parse_table "$tests" | while read field expect; do + actual=$(echo "$output" | jq -r ".$field") + dprint "# actual=<$actual> expect=<$expect>" + is "$actual" "$expect" "jq .$field" + done + +} + +# vim: filetype=sh diff --git a/test/system/010-images.bats b/test/system/010-images.bats new file mode 100644 index 000000000..1c9577e34 --- /dev/null +++ b/test/system/010-images.bats @@ -0,0 +1,46 @@ +#!/usr/bin/env bats + +load helpers + +@test "podman images - basic output" { + run_podman images -a + + is "${lines[0]}" "REPOSITORY *TAG *IMAGE ID *CREATED *SIZE" "header line" + is "${lines[1]}" "$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME *$PODMAN_TEST_IMAGE_TAG *[0-9a-f]\+" "podman images output" +} + +@test "podman images - custom formats" { + tests=" +--format {{.ID}} | [0-9a-f]\\\{12\\\} +--format {{.ID}} --no-trunc | sha256:[0-9a-f]\\\{64\\\} +--format {{.Repository}}:{{.Tag}} | $PODMAN_TEST_IMAGE_FQN +" + + parse_table "$tests" | while read fmt expect; do + run_podman images $fmt + is "$output" "$expect\$" "podman images $fmt" + done + +} + + +@test "podman images - json" { + tests=" +names[0] | $PODMAN_TEST_IMAGE_FQN +id | [0-9a-f]\\\{64\\\} +digest | sha256:[0-9a-f]\\\{64\\\} +created | [0-9-]\\\+T[0-9:]\\\+\\\.[0-9]\\\+Z +size | [0-9]\\\+ +" + + run_podman images -a --format json + + parse_table "$tests" | while read field expect; do + actual=$(echo "$output" | jq -r ".[0].$field") + dprint "# actual=<$actual> expect=<$expect}>" + is "$actual" "$expect" "jq .$field" + done + +} + +# vim: filetype=sh diff --git a/test/system/015-help.bats b/test/system/015-help.bats new file mode 100644 index 000000000..8e07b8822 --- /dev/null +++ b/test/system/015-help.bats @@ -0,0 +1,95 @@ +#!/usr/bin/env bats +# +# Tests based on 'podman help' +# +# Find all commands listed by 'podman --help'. Run each one, make sure it +# provides its own --help output. If the usage message ends in '[command]', +# treat it as a subcommand, and recurse into its own list of sub-subcommands. +# +# Any usage message that ends in '[flags]' is interpreted as a command +# that takes no further arguments; we confirm by running with 'invalid-arg' +# and confirming that it exits with error status and message. +# +load helpers + +# run 'podman help', parse the output looking for 'Available Commands'; +# return that list. +function podman_commands() { + dprint "$@" + run_podman help "$@" |\ + awk '/^Available Commands:/{ok=1;next}/^Flags:/{ok=0}ok { print $1 }' |\ + grep . + "$output" +} + + +function check_help() { + local count=0 + local subcommands_found=0 + + for cmd in $(podman_commands "$@"); do + dprint "podman $@ $cmd --help" + run_podman "$@" $cmd --help + + # The line immediately after 'Usage:' gives us a 1-line synopsis + usage=$(echo "$output" | grep -A1 '^Usage:' | tail -1) + [ -n "$usage" ] || die "podman $cmd: no Usage message found" + + # If usage ends in '[command]', recurse into subcommands + if expr "$usage" : '.*\[command\]$' >/dev/null; then + subcommands_found=$(expr $subcommands_found + 1) + check_help "$@" $cmd + continue + fi + + # If usage ends in '[flag]', command takes no more arguments. + # Confirm that by running with 'invalid-arg' and expecting failure. + if expr "$usage" : '.*\[flags\]$' >/dev/null; then + if [ "$cmd" != "help" ]; then + dprint "podman $@ $cmd invalid-arg" + run_podman 125 "$@" $cmd invalid-arg + is "$output" "Error: .* takes no arguments" \ + "'podman $@ $cmd' with extra (invalid) arguments" + fi + fi + + # If usage has required arguments, try running without them + if expr "$usage" : '.*\[flags\] [A-Z]' >/dev/null; then + dprint "podman $@ $cmd (without required args)" + run_podman 125 "$@" $cmd + is "$output" "Error:" + fi + + count=$(expr $count + 1) + done + + # Any command that takes subcommands, must throw error if called + # without one. + dprint "podman $@" + run_podman 125 "$@" + is "$output" "Error: missing command .*$@ COMMAND" + + # Assume that 'NoSuchCommand' is not a command + dprint "podman $@ NoSuchCommand" + run_podman 125 "$@" NoSuchCommand + is "$output" "Error: unrecognized command .*$@ NoSuchCommand" + + # 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" + + # At least the top level must have some subcommands + if [ -z "$*" -a $subcommands_found -eq 0 ]; then + die "Internal error: did not find any podman subcommands" + fi +} + + +@test "podman help - basic tests" { + # Called with no args -- start with 'podman --help'. check_help() will + # recurse for any subcommands. + check_help +} + +# vim: filetype=sh diff --git a/test/system/030-run.bats b/test/system/030-run.bats new file mode 100644 index 000000000..8ae68f33d --- /dev/null +++ b/test/system/030-run.bats @@ -0,0 +1,34 @@ +#!/usr/bin/env bats + +load helpers + +@test "podman run - basic tests" { + rand=$(random_string 30) + tests=" +true | 0 | +false | 1 | +sh -c 'exit 32' | 32 | +echo $rand | 0 | $rand +/no/such/command | 127 | Error: container create failed:.*exec:.* no such file or dir +/etc | 126 | Error: container create failed:.*exec:.* permission denied +" + + while read cmd expected_rc expected_output; do + if [ "$expected_output" = "''" ]; then expected_output=""; fi + + # THIS IS TRICKY: this is what lets us handle a quoted command. + # Without this incantation (and the "$@" below), the cmd string + # gets passed on as individual tokens: eg "sh" "-c" "'exit" "32'" + # (note unmatched opening and closing single-quotes in the last 2). + # That results in a bizarre and hard-to-understand failure + # in the BATS 'run' invocation. + # This should really be done inside parse_table; I can't find + # a way to do so. + eval set "$cmd" + + run_podman $expected_rc run $IMAGE "$@" + is "$output" "$expected_output" "podman run $cmd - output" + done < <(parse_table "$tests") +} + +# vim: filetype=sh diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats new file mode 100644 index 000000000..055865c8d --- /dev/null +++ b/test/system/035-logs.bats @@ -0,0 +1,51 @@ +#!/usr/bin/env bats -*- bats -*- +# +# Basic tests for podman logs +# + +load helpers + +@test "podman logs - basic test" { + rand_string=$(random_string 40) + + run_podman create $IMAGE echo $rand_string + cid="$output" + + run_podman logs $cid + is "$output" "" "logs on created container: empty" + + run_podman start --attach --interactive $cid + is "$output" "$rand_string" "output from podman-start on created ctr" + is "$output" "$rand_string" "logs of started container" + + run_podman logs $cid + is "$output" "$rand_string" "output from podman-logs after container is run" + + run_podman rm $cid +} + +@test "podman logs - multi" { + # Simple helper to make the container starts, below, easier to read + local -a cid + doit() { + run_podman run --rm -d --name "$1" $IMAGE sh -c "$2"; + cid+=($(echo "${output:0:12}")) + } + + # Not really a guarantee that we'll get a-b-c-d in order, but it's + # the best we can do. The trailing 'sleep' in each container + # minimizes the chance of a race condition in which the container + # is removed before 'podman logs' has a chance to wake up and read + # the final output. + doit c1 "echo a;sleep 10;echo d;sleep 3" + doit c2 "sleep 1;echo b;sleep 2;echo c;sleep 3" + + run_podman logs -f c1 c2 + is "$output" \ + "${cid[0]} a +${cid[1]} b +${cid[1]} c +${cid[0]} d" "Sequential output from logs" +} + +# vim: filetype=sh diff --git a/test/system/040-ps.bats b/test/system/040-ps.bats new file mode 100644 index 000000000..dec2df4d5 --- /dev/null +++ b/test/system/040-ps.bats @@ -0,0 +1,38 @@ +#!/usr/bin/env bats + +load helpers + +@test "podman ps - basic tests" { + rand_name=$(random_string 30) + + run_podman run -d --name $rand_name $IMAGE sleep 5 + cid=$output + is "$cid" "[0-9a-f]\{64\}$" + + # Special case: formatted ps + run_podman ps --no-trunc \ + --format '{{.ID}} {{.Image}} {{.Command}} {{.Names}}' + is "$output" "$cid $IMAGE sleep 5 $rand_name" "podman ps" + + + # Plain old regular ps + run_podman ps + is "${lines[1]}" \ + "${cid:0:12} \+$IMAGE \+sleep [0-9]\+ .*second.* $cname"\ + "output from podman ps" + + # OK. Wait for sleep to finish... + run_podman wait $cid + + # ...then make sure container shows up as stopped + run_podman ps -a + is "${lines[1]}" \ + "${cid:0:12} \+$IMAGE *sleep .* Exited .* $rand_name" \ + "podman ps -a" + + + + run_podman rm $cid +} + +# vim: filetype=sh diff --git a/test/system/050-stop.bats b/test/system/050-stop.bats new file mode 100644 index 000000000..093606ece --- /dev/null +++ b/test/system/050-stop.bats @@ -0,0 +1,67 @@ +#!/usr/bin/env bats + +load helpers + +# Very simple test +@test "podman stop - basic test" { + run_podman run -d $IMAGE sleep 60 + cid="$output" + + # Run 'stop'. Time how long it takes. + t0=$SECONDS + run_podman stop $cid + t1=$SECONDS + + # Confirm that container is stopped + run_podman inspect --format '{{.State.Status}} {{.State.ExitCode}}' $cid + is "$output" "exited \+137" "Status and exit code of stopped container" + + # 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)" + + run_podman rm $cid +} + + +# Test fallback + + +# Regression test for #2472 +@test "podman stop - can trap signal" { + # Because the --time and --timeout options can be wonky, try three + # different variations of this test. + for t_opt in '' '--time=5' '--timeout=5'; do + # Run a simple container that logs output on SIGTERM + run_podman run -d $IMAGE sh -c \ + "trap 'echo Received SIGTERM, finishing; exit' SIGTERM; echo READY; while :; do sleep 1; done" + cid="$output" + wait_for_ready $cid + + # Run 'stop' against it... + t0=$SECONDS + run_podman stop $t_opt $cid + t1=$SECONDS + + # ...the container should trap the signal, log it, and exit. + run_podman logs $cid + is "$output" ".*READY.*Received SIGTERM, finishing" "podman stop $t_opt" + + # Exit code should be 0, because container did its own exit + run_podman inspect --format '{{.State.ExitCode}}' $cid + is "$output" "0" "Exit code of stopped container" + + # 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)" + + run_podman rm $cid + done +} + +# vim: filetype=sh diff --git a/test/system/060-mount.bats b/test/system/060-mount.bats new file mode 100644 index 000000000..e249b2883 --- /dev/null +++ b/test/system/060-mount.bats @@ -0,0 +1,37 @@ +#!/usr/bin/env bats + +load helpers + + +@test "podman mount - basic test" { + # Only works with root (FIXME: does it work with rootless + vfs?) + skip_if_rootless "mount does not work rootless" + + f_path=/tmp/tmpfile_$(random_string 8) + f_content=$(random_string 30) + + c_name=mount_test_$(random_string 5) + run_podman run --name $c_name $IMAGE \ + sh -c "echo $f_content > $f_path" + + run_podman mount $c_name + mount_path=$output + + test -d $mount_path + test -e "$mount_path/$f_path" + is $(< "$mount_path/$f_path") "$f_content" "contents of file, as read via fs" + + # Make sure that 'podman mount' (no args) returns the expected path + run_podman mount --notruncate + # FIXME: is it worth the effort to validate the CID ($1) ? + reported_mountpoint=$(echo "$output" | awk '{print $2}') + is $reported_mountpoint $mount_path "mountpoint reported by 'podman mount'" + + # umount, and make sure files are gone + run_podman umount $c_name + if [ -e "$mount_path/$f_path" ]; then + die "Mounted file exists even after umount: $mount_path/$f_path" + fi +} + +# vim: filetype=sh diff --git a/test/system/070-build.bats b/test/system/070-build.bats new file mode 100644 index 000000000..25eb36c58 --- /dev/null +++ b/test/system/070-build.bats @@ -0,0 +1,28 @@ +#!/usr/bin/env bats -*- bats -*- +# +# Tests for podman build +# + +load helpers + +@test "podman build - basic test" { + rand_filename=$(random_string 20) + rand_content=$(random_string 50) + + tmpdir=$PODMAN_TMPDIR/build-test + run mkdir -p $tmpdir || die "Could not mkdir $tmpdir" + dockerfile=$tmpdir/Dockerfile + cat >$dockerfile <<EOF +FROM $IMAGE +RUN echo $rand_content > /$rand_filename +EOF + + run_podman build -t build_test --format=docker $tmpdir + + run_podman run --rm build_test cat /$rand_filename + is "$output" "$rand_content" "reading generated file in image" + + run_podman rmi build_test +} + +# vim: filetype=sh diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats new file mode 100644 index 000000000..a12d28b32 --- /dev/null +++ b/test/system/075-exec.bats @@ -0,0 +1,30 @@ +#!/usr/bin/env bats -*- bats -*- +# +# Tests for podman exec +# + +load helpers + +@test "podman exec - basic test" { + rand_filename=$(random_string 20) + rand_content=$(random_string 50) + + # Start a container. Write random content to random file, then stay + # alive as long as file exists. (This test will remove that file soon.) + run_podman run -d $IMAGE sh -c \ + "echo $rand_content >/$rand_filename;echo READY;while [ -f /$rand_filename ]; do sleep 1; done" + cid="$output" + wait_for_ready $cid + + run_podman exec $cid sh -c "cat /$rand_filename" + is "$output" "$rand_content" "Can exec and see file in running container" + + run_podman exec $cid rm -f /$rand_filename + + run_podman wait $cid + is "$output" "0" "output from podman wait (container exit code)" + + run_podman rm $cid +} + +# vim: filetype=sh diff --git a/test/system/110-history.bats b/test/system/110-history.bats new file mode 100644 index 000000000..84a1e42b4 --- /dev/null +++ b/test/system/110-history.bats @@ -0,0 +1,49 @@ +#!/usr/bin/env bats + +load helpers + +@test "podman history - basic tests" { + tests=" + | .*[0-9a-f]\\\{12\\\} .* CMD .* LABEL +--format '{{.ID}} {{.Created}}' | .*[0-9a-f]\\\{12\\\} .* ago +--human=false | .*[0-9a-f]\\\{12\\\} *[0-9-]\\\+T[0-9:]\\\+Z +-qH | .*[0-9a-f]\\\{12\\\} +--no-trunc | .*[0-9a-f]\\\{64\\\} +" + + parse_table "$tests" | while read options expect; do + if [ "$options" = "''" ]; then options=; fi + + eval set -- "$options" + + run_podman history "$@" $IMAGE + is "$output" "$expect" "podman history $options" + done +} + +@test "podman history - json" { + tests=" +id | [0-9a-f]\\\{64\\\} +created | [0-9-]\\\+T[0-9:]\\\+\\\.[0-9]\\\+Z +size | -\\\?[0-9]\\\+ +" + + run_podman history --format json $IMAGE + + parse_table "$tests" | while read field expect; do + # HACK: we can't include '|' in the table + if [ "$field" = "id" ]; then expect="$expect\|<missing>";fi + + # output is an array of dicts; check each one + count=$(echo "$output" | jq '. | length') + i=0 + while [ $i -lt $count ]; do + actual=$(echo "$output" | jq -r ".[$i].$field") + is "$actual" "$expect\$" "jq .[$i].$field" + i=$(expr $i + 1) + done + done + +} + +# vim: filetype=sh diff --git a/test/system/120-load.bats b/test/system/120-load.bats new file mode 100644 index 000000000..dedfe6172 --- /dev/null +++ b/test/system/120-load.bats @@ -0,0 +1,96 @@ +#!/usr/bin/env bats -*- bats -*- +# +# tests for podman load +# + +load helpers + +# Custom helpers for this test only. These just save us having to duplicate +# the same thing four times (two tests, each with -i and stdin). +# +# initialize, read image ID and name +get_iid_and_name() { + run_podman images --format '{{.ID}} {{.Repository}}:{{.Tag}}' + read iid img_name < <(echo "$output") + + archive=$PODMAN_TMPDIR/myimage-$(random_string 8).tar +} + +# Simple verification of image ID and name +verify_iid_and_name() { + run_podman images --format '{{.ID}} {{.Repository}}:{{.Tag}}' + read new_iid new_img_name < <(echo "$output") + + # Verify + is "$new_iid" "$iid" "Image ID of loaded image == original" + is "$new_img_name" "$1" "Name & tag of restored image" +} + + +@test "podman load - by image ID" { + # FIXME: how to build a simple archive instead? + get_iid_and_name + + # Save image by ID, and remove it. + run_podman save $iid -o $archive + run_podman rmi $iid + + # Load using -i; IID should be preserved, but name is not. + run_podman load -i $archive + verify_iid_and_name "<none>:<none>" + + # Same as above, using stdin + run_podman rmi $iid + run_podman load < $archive + verify_iid_and_name "<none>:<none>" + + # Cleanup: since load-by-iid doesn't preserve name, re-tag it; + # otherwise our global teardown will rmi and re-pull our standard image. + run_podman tag $iid $img_name +} + +@test "podman load - by image name" { + get_iid_and_name + run_podman save $img_name -o $archive + run_podman rmi $iid + + # Load using -i; this time the image should be tagged. + run_podman load -i $archive + verify_iid_and_name $img_name + + # Same as above, using stdin + run_podman rmi $iid + run_podman load < $archive + verify_iid_and_name $img_name +} + +@test "podman load - NAME and NAME:TAG arguments work (requires: #2674)" { + get_iid_and_name + run_podman save $iid -o $archive + run_podman rmi $iid + + # Load with just a name (note: names must be lower-case) + random_name=$(random_string 20 | tr A-Z a-z) + run_podman load -i $archive $random_name + verify_iid_and_name "localhost/$random_name:latest" + + # Load with NAME:TAG arg + run_podman rmi $iid + random_tag=$(random_string 10 | tr A-Z a-z) + run_podman load -i $archive $random_name:$random_tag + verify_iid_and_name "localhost/$random_name:$random_tag" + + # Cleanup: restore desired image name + run_podman tag $iid $img_name + run_podman rmi "$random_name:$random_tag" +} + + +@test "podman load - will not read from tty" { + run_podman 125 load + is "$output" \ + "Error: cannot read from terminal. Use command-line redirection" \ + "Diagnostic from 'podman load' without redirection or -i" +} + +# vim: filetype=sh diff --git a/test/system/200-pod-top.bats b/test/system/200-pod-top.bats new file mode 100644 index 000000000..0200df00d --- /dev/null +++ b/test/system/200-pod-top.bats @@ -0,0 +1,41 @@ +#!/usr/bin/env bats + +load helpers + +@test "podman pod top - containers in different PID namespaces" { + # With infra=false, we don't get a /pause container (we also + # don't pull k8s.gcr.io/pause ) + no_infra='--infra=false' + run_podman pod create $no_infra + podid="$output" + + # Start two containers... + run_podman run -d --pod $podid $IMAGE top -d 2 + cid1="$output" + run_podman run -d --pod $podid $IMAGE top -d 2 + cid2="$output" + + # ...and wait for them to actually start. + wait_for_output "PID \+PPID \+USER " $cid1 + wait_for_output "PID \+PPID \+USER " $cid2 + + # Both containers have emitted at least one top-like line. + # Now run 'pod top', and expect two 'top -d 2' processes running. + run_podman pod top $podid + is "$output" ".*root.*top -d 2.*root.*top -d 2" "two 'top' containers" + + # By default (podman pod create w/ default --infra) there should be + # a /pause container. + # FIXME: sometimes there is, sometimes there isn't. If anyone ever + # actually figures this out, please either reenable this line or + # remove it entirely. + if [ -z "$no_infra" ]; then + is "$output" ".*0 \+1 \+0 \+[0-9. ?s]\+/pause" "there is a /pause container" + fi + + # Clean up + run_podman pod rm -f $podid +} + + +# vim: filetype=sh diff --git a/test/system/300-cli-parsing.bats b/test/system/300-cli-parsing.bats new file mode 100644 index 000000000..92c073102 --- /dev/null +++ b/test/system/300-cli-parsing.bats @@ -0,0 +1,15 @@ +#!/usr/bin/env bats -*- bats -*- +# +# Various command-line parsing regression tests that don't fit in elsewhere +# + +load helpers + +@test "podman cli parsing - quoted args - #2574" { + # 1.1.2 fails with: + # Error: invalid argument "true=\"false\"" for "-l, --label" \ + # flag: parse error on line 1, column 5: bare " in non-quoted-field + run_podman run --rm --label 'true="false"' $IMAGE true +} + +# vim: filetype=sh diff --git a/test/system/README.md b/test/system/README.md new file mode 100644 index 000000000..6ac408f4e --- /dev/null +++ b/test/system/README.md @@ -0,0 +1,82 @@ +Quick overview of podman system tests. The idea is to use BATS, +but with a framework for making it easy to add new tests and to +debug failures. + +Quick Start +=========== + +Look at [030-run.bats](030-run.bats) for a simple but packed example. +This introduces the basic set of helper functions: + +* `setup` (implicit) - resets container storage so there's +one and only one (standard) image, and no running containers. + +* `parse_table` - you can define tables of inputs and expected results, +then read those in a `while` loop. This makes it easy to add new tests. +Because bash is not a programming language, the caller of `parse_table` +sometimes needs to massage the returned values; `015-run.bats` offers +examples of how to deal with the more typical such issues. + +* `run_podman` - runs command defined in `$PODMAN` (default: 'podman' +but could also be './bin/podman' or 'podman-remote'), with a timeout. +Checks its exit status. + +* `is` - compare actual vs expected output. Emits a useful diagnostic +on failure. + +* `die` - output a properly-formatted message to stderr, and fail test + +* `skip_if_rootless` - if rootless, skip this test with a helpful message. + +* `random_string` - returns a pseudorandom alphanumeric string + +Test files are of the form `NNN-name.bats` where NNN is a three-digit +number. Please preserve this convention, it simplifies viewing the +directory and understanding test order. In particular, `00x` tests +should be reserved for a first-pass fail-fast subset of tests: + + bats test/system/00*.bats || exit 1 + bats test/system + +...the goal being to provide quick feedback on catastrophic failures +without having to wait for the entire test suite. + + +Analyzing test failures +======================= + +The top priority for this scheme is to make it easy to diagnose +what went wrong. To that end, `podman_run` always logs all invoked +commands, their output and exit codes. In a normal run you will never +see this, but BATS will display it on failure. The goal here is to +give you everything you need to diagnose without having to rerun tests. + +The `is` comparison function is designed to emit useful diagnostics, +in particular, the actual and expected strings. Please do not use +the horrible BATS standard of `[ x = y ]`; that's nearly useless +for tracking down failures. + +If the above are not enough to help you track down a failure: + + +Debugging tests +--------------- + +Some functions have `dprint` statements. To see the output of these, +set `PODMAN_TEST_DEBUG="funcname"` where `funcname` is the name of +the function or perhaps just a substring. + + +Requirements +============ + +The `jq` tool is needed for parsing JSON output. + + +Further Details +=============== + +TBD. For now, look in [helpers.bash](helpers.bash); each helper function +has (what are intended to be) helpful header comments. For even more +examples, see and/or run `helpers.t`; that's a regression test +and provides a thorough set of examples of how the helpers work. diff --git a/test/system/TODO.md b/test/system/TODO.md new file mode 100644 index 000000000..f6110d2e9 --- /dev/null +++ b/test/system/TODO.md @@ -0,0 +1,105 @@ +![PODMAN logo](../../logo/podman-logo-source.svg) + +# Overview + +System tests exercise Podman in the context of a complete, composed environment from +distribution packages. It should match as closely as possible to how an end-user +would experience a fresh-install. Dependencies on external configuration and resources +must be kept minimal, and the tests must be generic and vendor-neutral. + +The system-tests must execute cleanly on all tested platforms. They may optionally +be executed during continuous-integration testing of code-changes, after all other +testing completes successfully. For a list of tested platforms, please see [the +CI configuration file.](../../.cirrus.yml) + + +# Execution + +When working from a clone of [the libpod repository](https://github.com/containers/libpod), +the main entry-point for humans and automation is `make localsystem`. When operating +from a packaged version of the system-tests, the entry-point may vary as appropriate. +Running the packaged system-tests assumes the version of Podman matches the test +version, and all standard dependencies are installed. + + +# Test Design and overview + +System-tests should be high-level and user work-flow oriented. For example, consider +how multiple Podman invocations would be used together by an end-user. The set of +related commands should be considered a single test. If one or more intermediate +commands fail, the test could still pass if the end-result is still achieved. + + +# *TODO*: List of needed System-tests + +***Note***: Common operations (like `rm` and `rmi` for cleanup/reset) +have been omitted as they are verified by repeated implied use. + +- [ ] pull, build, run, attach, commit, diff, inspect + + - Pull existing image from registry + - Build new image FROM explicitly pulled image + - Run built container in detached mode + - Attach to running container, execute command to modify storage. + - Commit running container to new image w/ changed ENV VAR + - Verify attach + commit using diff + - verify changed ENV VAR with inspect + +- [ ] Implied pull, create, start, exec, log, stop, wait, rm + + - Create non-existing local image + - start stopped container + - exec simple command in running container + - verify exec result with log + - wait on running container + - stop running container with 2 second timeout + - verify wait in 4 seconds or less + - verify stopped by rm **without** --force + +- [ ] Implied pull, build, export, modify, import, tag, run, kill + + - Build from Dockerfile FROM non-existing local image + - Export built container as tarball + - Modify tarball contents + - Import tarball + - Tag imported image + - Run imported image to confirm tarball modification, block on non-special signal + - Kill can send non-TERM/KILL signal to container to exit + - Confirm exit within timeout + +- [ ] Container runlabel, exists, checkpoint, exists, restore, stop, prune + + - Using pre-existing remote image, start it with 'podman container runlabel --pull' + - Run a named container that exits immediatly + - Confirm 'container exists' zero exit (both containers) + - Checkpoint the running container + - Confirm 'container exists' non-zero exit (runlabel container) + - Confirm 'container exists' zero exit (named container) + - Run 'container restore' + - Confirm 'container exists' zero exit (both containers) + - Stop container + - Run 'container prune' + - Confirm `podman ps -a` lists no containers + + +# TODO: List of commands to be combined into additional workflows above. + +- podman-remote (workflow TBD) +- history +- image +- load +- mount +- pause +- pod +- port +- login, push, & logout (difficult, save for last) +- restart +- save +- search +- stats +- top +- umount, unmount +- unpause +- volume +- `--namespace` +- `--storage-driver` diff --git a/test/system/helpers.bash b/test/system/helpers.bash new file mode 100644 index 000000000..431228498 --- /dev/null +++ b/test/system/helpers.bash @@ -0,0 +1,349 @@ +# -*- bash -*- + +# Podman command to run; may be podman-remote +PODMAN=${PODMAN:-podman} + +# Standard image to use for most tests +PODMAN_TEST_IMAGE_REGISTRY=${PODMAN_TEST_IMAGE_REGISTRY:-"quay.io"} +PODMAN_TEST_IMAGE_USER=${PODMAN_TEST_IMAGE_USER:-"libpod"} +PODMAN_TEST_IMAGE_NAME=${PODMAN_TEST_IMAGE_NAME:-"alpine_labels"} +PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"latest"} +PODMAN_TEST_IMAGE_FQN="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG" + +# Because who wants to spell that out each time? +IMAGE=$PODMAN_TEST_IMAGE_FQN + +# Default timeout for a podman command. +PODMAN_TIMEOUT=${PODMAN_TIMEOUT:-60} + +############################################################################### +# BEGIN setup/teardown tools + +# Provide common setup and teardown functions, but do not name them such! +# That way individual tests can override with their own setup/teardown, +# while retaining the ability to include these if they so desire. + +# Setup helper: establish a test environment with exactly the images needed +function basic_setup() { + # Clean up all containers + run_podman rm --all --force + + # Clean up all images except those desired + found_needed_image= + run_podman images --all --format '{{.Repository}}:{{.Tag}} {{.ID}}' + for line in "${lines[@]}"; do + set $line + if [ "$1" == "$PODMAN_TEST_IMAGE_FQN" ]; then + found_needed_image=1 + else + echo "# setup(): removing stray images" >&3 + run_podman rmi --force "$1" >/dev/null 2>&1 || true + run_podman rmi --force "$2" >/dev/null 2>&1 || true + fi + done + + # Make sure desired images are present + if [ -z "$found_needed_image" ]; then + run_podman pull "$PODMAN_TEST_IMAGE_FQN" + fi + + # Argh. Although BATS provides $BATS_TMPDIR, it's just /tmp! + # That's bloody worthless. Let's make our own, in which subtests + # can write whatever they like and trust that it'll be deleted + # on cleanup. + # TODO: do this outside of setup, so it carries across tests? + PODMAN_TMPDIR=$(mktemp -d --tmpdir=${BATS_TMPDIR:-/tmp} podman_bats.XXXXXX) +} + +# Basic teardown: remove all pods and containers +function basic_teardown() { + echo "# [teardown]" >&2 + run_podman '?' pod rm --all --force + run_podman '?' rm --all --force + + /bin/rm -rf $PODMAN_TMPDIR +} + + +# Provide the above as default methods. +function setup() { + basic_setup +} + +function teardown() { + basic_teardown +} + + +# Helpers useful for tests running rmi +function archive_image() { + local image=$1 + + # FIXME: refactor? + archive_basename=$(echo $1 | tr -c a-zA-Z0-9._- _) + archive=$BATS_TMPDIR/$archive_basename.tar + + run_podman save -o $archive $image +} + +function restore_image() { + local image=$1 + + archive_basename=$(echo $1 | tr -c a-zA-Z0-9._- _) + archive=$BATS_TMPDIR/$archive_basename.tar + + run_podman restore $archive +} + +# END setup/teardown tools +############################################################################### +# BEGIN podman helpers + +################ +# run_podman # Invoke $PODMAN, with timeout, using BATS 'run' +################ +# +# This is the preferred mechanism for invoking podman: first, it +# invokes $PODMAN, which may be 'podman-remote' or '/some/path/podman'. +# +# Second, we use 'timeout' to abort (with a diagnostic) if something +# takes too long; this is preferable to a CI hang. +# +# Third, we log the command run and its output. This doesn't normally +# appear in BATS output, but it will if there's an error. +# +# Next, we check exit status. Since the normal desired code is 0, +# that's the default; but the first argument can override: +# +# run_podman 125 nonexistent-subcommand +# run_podman '?' some-other-command # let our caller check status +# +# Since we use the BATS 'run' mechanism, $output and $status will be +# defined for our caller. +# +function run_podman() { + # Number as first argument = expected exit code; default 0 + expected_rc=0 + case "$1" in + [0-9]) expected_rc=$1; shift;; + [1-9][0-9]) expected_rc=$1; shift;; + [12][0-9][0-9]) expected_rc=$1; shift;; + '?') expected_rc= ; shift;; # ignore exit code + esac + + # stdout is only emitted upon error; this echo is to help a debugger + echo "\$ $PODMAN $*" + run timeout --foreground -v --kill=10 $PODMAN_TIMEOUT $PODMAN "$@" + # without "quotes", multiple lines are glommed together into one + if [ -n "$output" ]; then + echo "$output" + fi + if [ "$status" -ne 0 ]; then + echo -n "[ rc=$status "; + if [ -n "$expected_rc" ]; then + if [ "$status" -eq "$expected_rc" ]; then + echo -n "(expected) "; + else + echo -n "(** EXPECTED $expected_rc **) "; + fi + fi + echo "]" + fi + + if [ "$status" -eq 124 ]; then + if expr "$output" : ".*timeout: sending" >/dev/null; then + echo "*** TIMED OUT ***" + false + fi + fi + + if [ -n "$expected_rc" ]; then + if [ "$status" -ne "$expected_rc" ]; then + die "exit code is $status; expected $expected_rc" + fi + fi +} + + +# Wait for certain output from a container, indicating that it's ready. +function wait_for_output { + local sleep_delay=5 + local how_long=$PODMAN_TIMEOUT + local expect= + local cid= + + # Arg processing. A single-digit number is how long to sleep between + # iterations; a 2- or 3-digit number is the total time to wait; all + # else are, in order, the string to expect and the container name/ID. + local i + for i in "$@"; do + if expr "$i" : '[0-9]\+$' >/dev/null; then + if [ $i -le 9 ]; then + sleep_delay=$i + else + how_long=$i + fi + elif [ -z "$expect" ]; then + expect=$i + else + cid=$i + fi + done + + [ -n "$cid" ] || die "FATAL: wait_for_ready: no container name/ID in '$*'" + + t1=$(expr $SECONDS + $how_long) + while [ $SECONDS -lt $t1 ]; do + run_podman logs $cid + if expr "$output" : ".*$expect" >/dev/null; then + return + fi + + sleep $sleep_delay + done + + die "timed out waiting for '$expect' from $cid" +} + +# Shortcut for the lazy +function wait_for_ready { + wait_for_output 'READY' "$@" +} + +# END podman helpers +############################################################################### +# BEGIN miscellaneous tools + +###################### +# skip_if_rootless # ...with an optional message +###################### +function skip_if_rootless() { + if [ "$(id -u)" -eq 0 ]; then + return + fi + + skip "${1:-not applicable under rootless podman}" +} + + +######### +# die # Abort with helpful message +######### +function die() { + echo "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" >&2 + echo "#| FAIL: $*" >&2 + echo "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" >&2 + false +} + + +######## +# is # Compare actual vs expected string; fail w/diagnostic if mismatch +######## +# +# Compares given string against expectations, using 'expr' to allow patterns. +# +# 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" +# +function is() { + local actual="$1" + local expect="$2" + local testname="${3:-FIXME}" + + if [ -z "$expect" ]; then + if [ -z "$actual" ]; then + return + fi + expect='[no output]' + elif expr "$actual" : "$expect" >/dev/null; then + return + fi + + # This is a multi-line message, which may in turn contain multi-line + # output, so let's format it ourself, readably + local -a actual_split + readarray -t actual_split <<<"$actual" + printf "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" >&2 + printf "#| FAIL: $testname\n" >&2 + printf "#| expected: '%s'\n" "$expect" >&2 + printf "#| actual: '%s'\n" "${actual_split[0]}" >&2 + local line + for line in "${actual_split[@]:1}"; do + printf "#| > '%s'\n" "$line" >&2 + done + printf "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" >&2 + false +} + + +############ +# dprint # conditional debug message +############ +# +# Set PODMAN_TEST_DEBUG to the name of one or more functions you want to debug +# +# Examples: +# +# $ PODMAN_TEST_DEBUG=parse_table bats . +# $ PODMAN_TEST_DEBUG="test_podman_images test_podman_run" bats . +# +function dprint() { + test -z "$PODMAN_TEST_DEBUG" && return + + caller="${FUNCNAME[1]}" + + # PODMAN_TEST_DEBUG is a space-separated list of desired functions + # e.g. "parse_table test_podman_images" (or even just "table") + for want in $PODMAN_TEST_DEBUG; do + # Check if our calling function matches any of the desired strings + if expr "$caller" : ".*$want" >/dev/null; then + echo "# ${FUNCNAME[1]}() : $*" >&3 + return + fi + done +} + + +################# +# parse_table # Split a table on '|' delimiters; return space-separated +################# +# +# See sample .bats scripts for examples. The idea is to list a set of +# tests in a table, then use simple logic to iterate over each test. +# Columns are separated using '|' (pipe character) because sometimes +# we need spaces in our fields. +# +function parse_table() { + while read line; do + test -z "$line" && continue + + declare -a row=() + while read col; do + dprint "col=<<$col>>" + row+=("$col") + done < <(echo "$line" | tr '|' '\012' | sed -e 's/^ *//' -e 's/\\/\\\\/g') + + printf "%q " "${row[@]}" + printf "\n" + done <<<"$1" +} + + +################### +# random_string # Returns a pseudorandom human-readable string +################### +# +# Numeric argument, if present, is desired length of string +# +function random_string() { + local length=${1:-10} + + head /dev/urandom | tr -dc a-zA-Z0-9 | head -c$length +} + +# END miscellaneous tools +############################################################################### diff --git a/test/system/helpers.t b/test/system/helpers.t new file mode 100755 index 000000000..7b4e48a84 --- /dev/null +++ b/test/system/helpers.t @@ -0,0 +1,145 @@ +#!/bin/bash +# +# regression tests for helpers.bash +# +# Some of those helper functions are fragile, and we don't want to break +# anything if we have to mess with them. +# + +source $(dirname $0)/helpers.bash + +die() { + echo "$(basename $0): $*" >&2 + exit 1 +} + +# Iterator and return code; updated in check_result() +testnum=0 +rc=0 + +############################################################################### +# BEGIN test the parse_table helper + +function check_result { + testnum=$(expr $testnum + 1) + if [ "$1" = "$2" ]; then + echo "ok $testnum $3 = $1" + else + echo "not ok $testnum $3" + echo "# expected: $2" + echo "# actual: $1" + rc=1 + fi +} + +# IMPORTANT NOTE: you have to do +# this: while ... done < <(parse_table) +# and not: parse_table | while read ... +# +# ...because piping to 'while' makes it a subshell, hence testnum and rc +# will not be updated. +# +while read x y z; do + check_result "$x" "a" "parse_table simple: column 1" + check_result "$y" "b" "parse_table simple: column 2" + check_result "$z" "c" "parse_table simple: column 3" +done < <(parse_table "a | b | c") + +# More complicated example, with spaces +while read x y z; do + check_result "$x" "a b" "parse_table with spaces: column 1" + check_result "$y" "c d" "parse_table with spaces: column 2" + check_result "$z" "e f g" "parse_table with spaces: column 3" +done < <(parse_table "a b | c d | e f g") + +# Multi-row, with spaces and with blank lines +table=" +a | b | c d e +d e f | g h | i j +" +declare -A expect=( + [0,0]="a" + [0,1]="b" + [0,2]="c d e" + [1,0]="d e f" + [1,1]="g h" + [1,2]="i j" +) +row=0 +while read x y z;do + check_result "$x" "${expect[$row,0]}" "parse_table multi_row[$row,0]" + check_result "$y" "${expect[$row,1]}" "parse_table multi_row[$row,1]" + check_result "$z" "${expect[$row,2]}" "parse_table multi_row[$row,2]" + row=$(expr $row + 1) +done < <(parse_table "$table") + +# Backslash handling. The first element should have none, the second some +while read x y;do + check_result "$x" '[0-9]{2}' "backslash test - no backslashes" + check_result "$y" '[0-9]\{3\}' "backslash test - one backslash each" +done < <(parse_table "[0-9]{2} | [0-9]\\\{3\\\}") + +# Empty strings. I wish we could convert those to real empty strings. +while read x y z; do + check_result "$x" "''" "empty string - left-hand" + check_result "$y" "''" "empty string - middle" + check_result "$z" "''" "empty string - right" +done < <(parse_table " | |") + +# Quotes +while read x y z;do + check_result "$x" "a 'b c'" "single quotes" + check_result "$y" "d \"e f\" g" "double quotes" + check_result "$z" "h" "no quotes" + + # FIXME FIXME FIXME: this is the only way I can find to get bash-like + # splitting of tokens. It really should be done inside parse_table + # but I can't find any way of doing so. If you can find a way, please + # update this test and any BATS tests that rely on quoting. + eval set "$x" + check_result "$1" "a" "single quotes - token split - 1" + check_result "$2" "b c" "single quotes - token split - 2" + check_result "$3" "" "single quotes - token split - 3" + + eval set "$y" + check_result "$1" "d" "double quotes - token split - 1" + check_result "$2" "e f" "double quotes - token split - 2" + check_result "$3" "g" "double quotes - token split - 3" +done < <(parse_table "a 'b c' | d \"e f\" g | h") + +# END test the parse_table helper +############################################################################### +# BEGIN dprint + +function dprint_test_1() { + dprint "$*" +} + +# parse_table works, might as well use it +# +# <value of PODMAN_TEST_DEBUG> | <blank for no msg, - for msg> | <desc> +# +table=" + | | debug unset +dprint_test | - | substring match +dprint_test_1 | - | exact match +dprint_test_10 | | caller name mismatch +xxx yyy zzz | | multiple callers, no match +dprint_test_1 xxx yyy zzz | - | multiple callers, match at start +xxx dprint_test_1 yyy zzz | - | multiple callers, match in middle +xxx yyy zzz dprint_test_1 | - | multiple callers, match at end +" +while read var expect name; do + random_string=$(random_string 20) + PODMAN_TEST_DEBUG="$var" result=$(dprint_test_1 "$random_string" 3>&1) + expect_full="" + if [ -n "$expect" -a "$expect" != "''" ]; then + expect_full="# dprint_test_1() : $random_string" + fi + check_result "$result" "$expect_full" "DEBUG='$var' - $name" +done < <(parse_table "$table") + +# END dprint +############################################################################### + +exit $rc diff --git a/test/system/libpod_suite_test.go b/test/system/libpod_suite_test.go deleted file mode 100644 index 5de50e4e7..000000000 --- a/test/system/libpod_suite_test.go +++ /dev/null @@ -1,217 +0,0 @@ -package system - -import ( - "fmt" - "os" - "strings" - "testing" - - . "github.com/containers/libpod/test/utils" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var ( - PODMAN_BINARY string - GLOBALOPTIONS = []string{"--cgroup-manager", - "--cni-config-dir", - "--config", "-c", - "--conmon", - "--cpu-profile", - "--log-level", - "--root", - "--tmpdir", - "--runroot", - "--runtime", - "--storage-driver", - "--storage-opt", - "--syslog", - } - PODMAN_SUBCMD = []string{"attach", - "commit", - "container", - "build", - "create", - "diff", - "exec", - "export", - "history", - "image", - "images", - "import", - "info", - "inspect", - "kill", - "load", - "login", - "logout", - "logs", - "mount", - "pause", - "ps", - "pod", - "port", - "pull", - "push", - "restart", - "rm", - "rmi", - "run", - "save", - "search", - "start", - "stats", - "stop", - "tag", - "top", - "umount", - "unpause", - "version", - "wait", - "h", - } - INTEGRATION_ROOT string - ARTIFACT_DIR = "/tmp/.artifacts" - ALPINE = "docker.io/library/alpine:latest" - BB = "docker.io/library/busybox:latest" - BB_GLIBC = "docker.io/library/busybox:glibc" - fedoraMinimal = "registry.fedoraproject.org/fedora-minimal:latest" - nginx = "quay.io/baude/alpine_nginx:latest" - redis = "docker.io/library/redis:alpine" - registry = "docker.io/library/registry:2" - infra = "k8s.gcr.io/pause:3.1" - defaultWaitTimeout = 90 -) - -// PodmanTestSystem struct for command line options -type PodmanTestSystem struct { - PodmanTest - GlobalOptions map[string]string - PodmanCmdOptions map[string][]string -} - -// TestLibpod ginkgo master function -func TestLibpod(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Libpod Suite") -} - -var _ = BeforeSuite(func() { -}) - -// PodmanTestCreate creates a PodmanTestSystem instance for the tests -func PodmanTestCreate(tempDir string) *PodmanTestSystem { - var envKey string - globalOptions := make(map[string]string) - podmanCmdOptions := make(map[string][]string) - - for _, n := range GLOBALOPTIONS { - envKey = strings.Replace(strings.ToUpper(strings.Trim(n, "-")), "-", "_", -1) - if isEnvSet(envKey) { - globalOptions[n] = os.Getenv(envKey) - } - } - - for _, n := range PODMAN_SUBCMD { - envKey = strings.Replace("PODMAN_SUBCMD_OPTIONS", "SUBCMD", strings.ToUpper(n), -1) - if isEnvSet(envKey) { - podmanCmdOptions[n] = strings.Split(os.Getenv(envKey), " ") - } - } - - podmanBinary := "podman" - if os.Getenv("PODMAN_BINARY") != "" { - podmanBinary = os.Getenv("PODMAN_BINARY") - } - - p := &PodmanTestSystem{ - PodmanTest: PodmanTest{ - PodmanBinary: podmanBinary, - ArtifactPath: ARTIFACT_DIR, - TempDir: tempDir, - }, - GlobalOptions: globalOptions, - PodmanCmdOptions: podmanCmdOptions, - } - - p.PodmanMakeOptions = p.makeOptions - - return p -} - -func (p *PodmanTestSystem) Podman(args []string) *PodmanSession { - return p.PodmanBase(args) -} - -//MakeOptions assembles all the podman options -func (p *PodmanTestSystem) makeOptions(args []string) []string { - var addOptions, subArgs []string - for _, n := range GLOBALOPTIONS { - if p.GlobalOptions[n] != "" { - addOptions = append(addOptions, n, p.GlobalOptions[n]) - } - } - - if len(args) == 0 { - return addOptions - } - - subCmd := args[0] - addOptions = append(addOptions, subCmd) - if subCmd == "unmount" { - subCmd = "umount" - } - if subCmd == "help" { - subCmd = "h" - } - - if _, ok := p.PodmanCmdOptions[subCmd]; ok { - m := make(map[string]bool) - subArgs = p.PodmanCmdOptions[subCmd] - for i := 0; i < len(subArgs); i++ { - m[subArgs[i]] = true - } - for i := 1; i < len(args); i++ { - if _, ok := m[args[i]]; !ok { - subArgs = append(subArgs, args[i]) - } - } - } else { - subArgs = args[1:] - } - - addOptions = append(addOptions, subArgs...) - - return addOptions -} - -// Cleanup cleans up the temporary store -func (p *PodmanTestSystem) Cleanup() { - // Remove all containers - stopall := p.Podman([]string{"stop", "-a", "--timeout", "0"}) - stopall.WaitWithDefaultTimeout() - - session := p.Podman([]string{"rm", "-fa"}) - session.Wait(90) - // Nuke tempdir - if err := os.RemoveAll(p.TempDir); err != nil { - fmt.Printf("%q\n", err) - } -} - -// CleanupPod cleans up the temporary store -func (p *PodmanTestSystem) CleanupPod() { - // Remove all containers - session := p.Podman([]string{"pod", "rm", "-fa"}) - session.Wait(90) - // Nuke tempdir - if err := os.RemoveAll(p.TempDir); err != nil { - fmt.Printf("%q\n", err) - } -} - -// Check if the key is set in Env -func isEnvSet(key string) bool { - _, set := os.LookupEnv(key) - return set -} diff --git a/test/system/version_test.go b/test/system/version_test.go deleted file mode 100644 index ada0093b7..000000000 --- a/test/system/version_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package system - -import ( - "fmt" - "os" - "regexp" - - . "github.com/containers/libpod/test/utils" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Podman version test", func() { - var ( - tempdir string - err error - podmanTest *PodmanTestSystem - ) - - BeforeEach(func() { - tempdir, err = CreateTempDirInTempDir() - if err != nil { - os.Exit(1) - } - podmanTest = PodmanTestCreate(tempdir) - }) - - AfterEach(func() { - podmanTest.Cleanup() - f := CurrentGinkgoTestDescription() - timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) - GinkgoWriter.Write([]byte(timedResult)) - }) - - It("Smoking test: podman version with extra args", func() { - logc := podmanTest.Podman([]string{"version", "anything", "-", "--"}) - logc.WaitWithDefaultTimeout() - Expect(logc.ExitCode()).To(Equal(0)) - ver := logc.OutputToString() - Expect(regexp.MatchString("Version:.*?Go Version:.*?OS/Arch", ver)).To(BeTrue()) - }) - - It("Negative test: podman version with extra flag", func() { - logc := podmanTest.Podman([]string{"version", "--foo"}) - logc.WaitWithDefaultTimeout() - Expect(logc.ExitCode()).NotTo(Equal(0)) - err, _ := logc.GrepString("Incorrect Usage: flag provided but not defined: -foo") - Expect(err).To(BeTrue()) - }) - -}) diff --git a/test/test_podman_baseline.sh b/test/test_podman_baseline.sh index 664fd2b03..5c24229bb 100755 --- a/test/test_podman_baseline.sh +++ b/test/test_podman_baseline.sh @@ -19,6 +19,7 @@ ####### # See if we want to stop on errors and/or install and then remove Docker. ####### +HOST_PORT="${HOST_PORT:-8080}" showerror=0 installdocker=0 usedocker=1 @@ -78,7 +79,99 @@ echo $image ######## # Run container and display contents in /etc ######## -podman run $image ls -alF /etc +podman run --rm $image ls -alF /etc + +######## +# Test networking, bind mounting a file, stdin/stdout redirect +######## +echo "Testing networking: ..." +port_test_failed=0 +txt1="Hello, Podman" +echo "$txt1" > /tmp/hello.txt +podman run -d --name myweb -p "$HOST_PORT:80" -w /var/www -v /tmp/hello.txt:/var/www/index.txt busybox httpd -f -p 80 +echo "$txt1" | podman exec -i myweb sh -c "cat > /var/www/index2.txt" +txt2=$( podman exec myweb cat /var/www/index2.txt ) +[ "x$txt1" == "x$txt2" ] && echo "PASS1" || { echo "FAIL1"; port_test_failed=1; } +txt2=$( podman run --rm --net host busybox wget -qO - http://localhost:$HOST_PORT/index.txt ) +[ "x$txt1" == "x$txt2" ] && echo "PASS2" || { echo "FAIL2"; port_test_failed=1; } +txt2=$( podman run --rm --net host busybox wget -qO - http://localhost:$HOST_PORT/index2.txt ) +[ "x$txt1" == "x$txt2" ] && echo "PASS3" || { echo "FAIL3"; port_test_failed=1; } +# podman run --rm --net container:myweb --add-host myweb:127.0.0.1 busybox wget -qO - http://myweb/index.txt +rm /tmp/hello.txt +podman stop myweb +podman rm myweb +[ "0$port_test_failed" -eq 1 ] && [ "0$showerror" -eq 1 ] && { + echo "networking test failed"; + exit -1; +} + + +######## +# pull and run many containers in parallel, test locks ..etc. +######## +prun_test_failed=0 +podman rmi docker.io/library/busybox:latest > /dev/null || : +for i in `seq 10` +do ( podman run -d --name b$i docker.io/library/busybox:latest busybox httpd -f -p 80 )& +done +echo -e "\nwaiting for creation...\n" +wait +echo -e "\ndone\n" +# assert we have 10 running containers +count=$( podman ps -q | wc -l ) +[ "x$count" == "x10" ] && echo "PASS" || { echo "FAIL, expecting 10 found $count"; prun_test_failed=1; } +[ "0$prun_test_failed" -eq 1 ] && [ "0$showerror" -eq 1 ] && { + echo "was expecting 10 running containers"; + exit -1; +} + +prun_test_failed=0 +for i in `seq 10`; do ( podman stop -t=1 b$i; podman rm b$i )& done +echo -e "\nwaiting for deletion...\n" +wait +echo -e "\ndone\n" +# assert we have 0 running containers +count=$( podman ps -q | wc -l ) +[ "x$count" == "x0" ] && echo "PASS" || { echo "FAIL, expecting 0 found $count"; prun_test_failed=1; } +[ "0$prun_test_failed" -eq 1 ] && [ "0$showerror" -eq 1 ] && { + echo "was expecting 0 running containers"; + exit -1; +} + + + +######## +# run many containers in parallel for an existing image, test locks ..etc. +######## +prun_test_failed=0 +podman pull docker.io/library/busybox:latest > /dev/null || : +for i in `seq 10` +do ( podman run -d --name c$i docker.io/library/busybox:latest busybox httpd -f -p 80 )& +done +echo -e "\nwaiting for creation...\n" +wait +echo -e "\ndone\n" +# assert we have 10 running containers +count=$( podman ps -q | wc -l ) +[ "x$count" == "x10" ] && echo "PASS" || { echo "FAIL, expecting 10 found $count"; prun_test_failed=1; } +[ "0$prun_test_failed" -eq 1 ] && [ "0$showerror" -eq 1 ] && { + echo "was expecting 10 running containers"; + exit -1; +} + + +for i in `seq 10`; do ( podman stop -t=1 c$i; podman rm c$i )& done +echo -e "\nwaiting for deletion...\n" +wait +echo -e "\ndone\n" +# assert we have 0 running containers +count=$( podman ps -q | wc -l ) +[ "x$count" == "x0" ] && echo "PASS" || { echo "FAIL, expecting 0 found $count"; prun_test_failed=1; } +[ "0$prun_test_failed" -eq 1 ] && [ "0$showerror" -eq 1 ] && { + echo "was expecting 0 running containers"; + exit -1; +} + ######## # Run Java in the container - should ERROR but never stop diff --git a/test/test_podman_build.sh b/test/test_podman_build.sh index 9faefc78a..39f1e784d 100644 --- a/test/test_podman_build.sh +++ b/test/test_podman_build.sh @@ -34,6 +34,13 @@ echo ######################################################## echo ######################################################## +echo test "build directory before other options create a tag" +echo ######################################################## +TARGET=tagged-image +podman build $HOME/test/build/from-scratch --quiet=True -t $TARGET +podman images | grep tagged-image + +echo ######################################################## echo test "build-preserve-subvolumes" echo ######################################################## TARGET=volume-image |