-
Notifications
You must be signed in to change notification settings - Fork 467
Add basic integration tests for docker runtime #860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| GO_CMD ?= go | ||
|
|
||
| include $(CURDIR)/versions.mk | ||
|
|
||
| E2E_RUNTIME ?= docker | ||
|
|
||
| .PHONY: test | ||
| test: | ||
| cd $(CURDIR)/test/e2e && $(GO_CMD) test -v . -args \ | ||
| -ginkgo.focus="$(E2E_RUNTIME)" \ | ||
| -test.timeout=1h \ | ||
| -ginkgo.v |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| /* | ||
| * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package e2e | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "context" | ||
| "fmt" | ||
| "os/exec" | ||
| "testing" | ||
|
|
||
| . "github.com/onsi/ginkgo/v2" | ||
| . "github.com/onsi/gomega" | ||
| ) | ||
|
|
||
| // Test context | ||
| var ( | ||
| ctx context.Context | ||
| ) | ||
|
|
||
| func TestMain(t *testing.T) { | ||
| suiteName := "NVIDIA Container Toolkit E2E" | ||
|
|
||
| RegisterFailHandler(Fail) | ||
| RunSpecs(t, | ||
| suiteName, | ||
| ) | ||
| } | ||
|
|
||
| // BeforeSuite runs before the test suite | ||
| var _ = BeforeSuite(func() { | ||
| ctx = context.Background() | ||
| }) | ||
|
|
||
| func runScript(script string) (string, error) { | ||
| // Create a command to run the script using bash | ||
| cmd := exec.Command("bash", "-c", script) | ||
|
|
||
| // Buffer to capture standard output | ||
| var stdout bytes.Buffer | ||
| cmd.Stdout = &stdout | ||
|
|
||
| // Buffer to capture standard error | ||
| var stderr bytes.Buffer | ||
| cmd.Stderr = &stderr | ||
|
|
||
| // Run the command | ||
| err := cmd.Run() | ||
| if err != nil { | ||
| return "", fmt.Errorf("script execution failed: %v\nSTDOUT: %s\nSTDERR: %s", err, stdout.String(), stderr.String()) | ||
| } | ||
|
|
||
| // Return the captured stdout and nil error | ||
| return stdout.String(), nil | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| /* | ||
| * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package e2e | ||
|
|
||
| import ( | ||
| "context" | ||
|
|
||
| . "github.com/onsi/ginkgo/v2" | ||
| . "github.com/onsi/gomega" | ||
| ) | ||
|
|
||
| // Integration tests for Docker runtime | ||
| var _ = Describe("docker", func() { | ||
| // GPUs are accessible in a container: Running nvidia-smi -L inside the | ||
| // container shows the same output inside the container as outside the | ||
| // container. This means that the following commands must all produce | ||
| // the same output | ||
| When("running nvidia-smi -L", Ordered, func() { | ||
| var hostOutput string | ||
|
|
||
| BeforeAll(func(ctx context.Context) { | ||
| _, err := runScript("docker pull ubuntu") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
|
|
||
| hostOutput, err = runScript("nvidia-smi -L") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| }) | ||
|
|
||
| It("should support NVIDIA_VISIBLE_DEVICES", func(ctx context.Context) { | ||
| containerOutput, err := runScript("docker run --rm -i --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all ubuntu nvidia-smi -L") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(containerOutput).To(Equal(hostOutput)) | ||
| }) | ||
|
|
||
| It("should support automatic CDI spec generation", func(ctx context.Context) { | ||
| containerOutput, err := runScript("docker run --rm -i --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=runtime.nvidia.com/gpu=all ubuntu nvidia-smi -L") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(containerOutput).To(Equal(hostOutput)) | ||
| }) | ||
|
|
||
| It("should support the --gpus flag using the nvidia-container-runtime", func(ctx context.Context) { | ||
| containerOutput, err := runScript("docker run --rm -i --runtime=nvidia --gpus all ubuntu nvidia-smi -L") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(containerOutput).To(Equal(hostOutput)) | ||
| }) | ||
|
|
||
| It("should support the --gpus flag using the nvidia-container-runtime-hook", func(ctx context.Context) { | ||
| containerOutput, err := runScript("docker run --rm -i --gpus all ubuntu nvidia-smi -L") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(containerOutput).To(Equal(hostOutput)) | ||
| }) | ||
| }) | ||
|
|
||
| // A vectorAdd sample runs in a container with access to all GPUs. | ||
| // The following should all produce the same result. | ||
| When("Running the cuda-vectorAdd sample", Ordered, func() { | ||
| BeforeAll(func(ctx context.Context) { | ||
| _, err := runScript("docker pull nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| }) | ||
|
|
||
| var referenceOutput string | ||
|
|
||
| It("should support NVIDIA_VISIBLE_DEVICES", func(ctx context.Context) { | ||
| var err error | ||
| referenceOutput, err = runScript("docker run --rm -i --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
|
|
||
| Expect(referenceOutput).To(ContainSubstring("Test PASSED")) | ||
| }) | ||
|
|
||
| It("should support automatic CDI spec generation", func(ctx context.Context) { | ||
| out2, err := runScript("docker run --rm -i --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=runtime.nvidia.com/gpu=all nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(referenceOutput).To(Equal(out2)) | ||
| }) | ||
|
|
||
| It("should support the --gpus flag using the nvidia-container-runtime", func(ctx context.Context) { | ||
| out3, err := runScript("docker run --rm -i --runtime=nvidia --gpus all nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(referenceOutput).To(Equal(out3)) | ||
| }) | ||
|
|
||
| It("should support the --gpus flag using the nvidia-container-runtime-hook", func(ctx context.Context) { | ||
| out4, err := runScript("docker run --rm -i --gpus all nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(referenceOutput).To(Equal(out4)) | ||
| }) | ||
| }) | ||
|
|
||
| // A deviceQuery sample runs in a container with access to all GPUs | ||
| // The following should all produce the same result. | ||
| When("Running the cuda-deviceQuery sample", Ordered, func() { | ||
| BeforeAll(func(ctx context.Context) { | ||
| _, err := runScript("docker pull nvcr.io/nvidia/k8s/cuda-sample:devicequery-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| }) | ||
|
|
||
| var referenceOutput string | ||
|
|
||
| It("should support NVIDIA_VISIBLE_DEVICES", func(ctx context.Context) { | ||
| var err error | ||
| referenceOutput, err = runScript("docker run --rm -i --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all nvcr.io/nvidia/k8s/cuda-sample:devicequery-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
|
|
||
| Expect(referenceOutput).To(ContainSubstring("Result = PASS")) | ||
| }) | ||
|
|
||
| It("should support automatic CDI spec generation", func(ctx context.Context) { | ||
| out2, err := runScript("docker run --rm -i --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=runtime.nvidia.com/gpu=all nvcr.io/nvidia/k8s/cuda-sample:devicequery-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(referenceOutput).To(Equal(out2)) | ||
| }) | ||
|
|
||
| It("should support the --gpus flag using the nvidia-container-runtime", func(ctx context.Context) { | ||
| out3, err := runScript("docker run --rm -i --runtime=nvidia --gpus all nvcr.io/nvidia/k8s/cuda-sample:devicequery-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(referenceOutput).To(Equal(out3)) | ||
| }) | ||
|
|
||
| It("should support the --gpus flag using the nvidia-container-runtime-hook", func(ctx context.Context) { | ||
| out4, err := runScript("docker run --rm -i --gpus all nvcr.io/nvidia/k8s/cuda-sample:devicequery-cuda12.5.0") | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(referenceOutput).To(Equal(out4)) | ||
| }) | ||
| }) | ||
| }) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| module github.com/NVIDIA/nvidia-container-toolkit/test | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not critical to this PR, but we should ensure that we update the dependabot configs.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was it done here? |
||
|
|
||
| go 1.23.2 | ||
|
|
||
| require ( | ||
| github.com/onsi/ginkgo/v2 v2.22.2 | ||
| github.com/onsi/gomega v1.36.2 | ||
| ) | ||
|
|
||
| require ( | ||
| github.com/go-logr/logr v1.4.2 // indirect | ||
| github.com/go-task/slim-sprig/v3 v3.0.0 // indirect | ||
| github.com/google/go-cmp v0.6.0 // indirect | ||
| github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect | ||
| golang.org/x/net v0.33.0 // indirect | ||
| golang.org/x/sys v0.28.0 // indirect | ||
| golang.org/x/text v0.21.0 // indirect | ||
| golang.org/x/tools v0.28.0 // indirect | ||
| gopkg.in/yaml.v3 v3.0.1 // indirect | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
| github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= | ||
| github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= | ||
| github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= | ||
| github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= | ||
| github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | ||
| github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||
| github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= | ||
| github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= | ||
| github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= | ||
| github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= | ||
| github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= | ||
| github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= | ||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
| github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||
| github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||
| golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= | ||
| golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= | ||
| golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= | ||
| golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||
| golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= | ||
| golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= | ||
| golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= | ||
| golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= | ||
| google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= | ||
| google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= | ||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.