Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions tests/e2e/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,6 @@ type containerTestArgs struct {
ExpectOut string
}

const (
testCtr = "TestCtr"
testCrictl = "TestCrictl"
testDocker = "TestDocker"
testNerdctl = "TestNerdctl"
)

var errToolDoesNotSupport = errors.New("Operation not support")

func commonNewContainerCmd(a containerTestArgs) string {
Expand Down
10 changes: 4 additions & 6 deletions tests/e2e/crictl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,8 @@ var _ = Describe("Crictl", Ordered, ContinueOnFailure, func() {
var tool *crictlInfo

BeforeAll(func() {
cases := crictlTestCases()
images := getTestImages(cases)
err := pullAllImages(testCrictl, images)
Expect(err).NotTo(HaveOccurred(), "Failed to pull crictl images")

DeferCleanup(func() {
removeAllImages(testCrictl, images)
cleanupImages(crictlName)
})
})

Expand All @@ -48,6 +43,9 @@ var _ = Describe("Crictl", Ordered, ContinueOnFailure, func() {
skipMissingVolumes(tc)
tool = newCrictlTool(tc)

By("Ensuring images are available")
Expect(ensureTestImages(tool, tc)).To(Succeed())

By("Creating pod")
pID, err := tool.createPod()
Expect(err).NotTo(HaveOccurred(), "Failed to create pod: %s", pID)
Expand Down
8 changes: 1 addition & 7 deletions tests/e2e/ctr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,14 @@ package urunce2etesting

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("Ctr", Ordered, ContinueOnFailure, func() {
var tool *ctrInfo

BeforeAll(func() {
cases := ctrTestCases()
images := getTestImages(cases)
err := pullAllImages(testCtr, images)
Expect(err).NotTo(HaveOccurred(), "Failed to pull ctr images")

DeferCleanup(func() {
removeAllImages(testCtr, images)
cleanupImages(ctrName)
})
})

Expand Down
8 changes: 1 addition & 7 deletions tests/e2e/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,14 @@ package urunce2etesting

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("Docker", Ordered, ContinueOnFailure, func() {
var tool *dockerInfo

BeforeAll(func() {
cases := dockerTestCases()
images := getTestImages(cases)
err := pullAllImages(testDocker, images)
Expect(err).NotTo(HaveOccurred(), "Failed to pull docker images")

DeferCleanup(func() {
removeAllImages(testDocker, images)
cleanupImages(dockerName)
})
})

Expand Down
8 changes: 1 addition & 7 deletions tests/e2e/nerdctl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,14 @@ package urunce2etesting

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("Nerdctl", Ordered, ContinueOnFailure, func() {
var tool *nerdctlInfo

BeforeAll(func() {
cases := nerdctlTestCases()
images := getTestImages(cases)
err := pullAllImages(testNerdctl, images)
Expect(err).NotTo(HaveOccurred(), "Failed to pull nerdctl images")

DeferCleanup(func() {
removeAllImages(testNerdctl, images)
cleanupImages(nerdctlName)
})
})

Expand Down
6 changes: 6 additions & 0 deletions tests/e2e/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ func captureContainerLogs(tool testTool) {
// runDetachedTest runs a container in detached mode: create, start, and
// verify via TestFunc.
func runDetachedTest(tool testTool, tc containerTestArgs) {
By("Ensuring images are available")
Expect(ensureTestImages(tool, tc)).To(Succeed())

By("Creating container")
cID, err := tool.createContainer()
Expect(err).NotTo(HaveOccurred(), "Failed to create container: %s", cID)
Expand Down Expand Up @@ -135,6 +138,9 @@ func runDetachedTest(tool testTool, tc containerTestArgs) {
// runForegroundTest runs a container in the foreground and verifies the
// output contains the expected string.
func runForegroundTest(tool testTool, tc containerTestArgs) {
By("Ensuring images are available")
Expect(ensureTestImages(tool, tc)).To(Succeed())

tool.setContainerID(tc.Name)

DeferCleanup(func() {
Expand Down
92 changes: 56 additions & 36 deletions tests/e2e/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
"time"

probing "github.com/prometheus-community/pro-bing"
Expand All @@ -32,42 +33,69 @@ const (
pullRetryDelay = 2 * time.Second
)

func getTestImages(cases []containerTestArgs) []string {
unique := make(map[string]struct{})
for _, tc := range cases {
unique[tc.Image] = struct{}{}
var (
pulledImagesLock sync.Mutex
// pulledImages maps tool -> image -> bool.
pulledImages = make(map[string]map[string]bool)
)

func ensureImage(tool string, image string) error {
pulledImagesLock.Lock()
if pulledImages[tool] == nil {
pulledImages[tool] = make(map[string]bool)
}
if pulledImages[tool][image] {
pulledImagesLock.Unlock()
return nil
}
pulledImagesLock.Unlock()

images := make([]string, 0, len(unique))
for img := range unique {
images = append(images, img)
log.Printf("Pulling image for %s: %s", tool, image)
if err := pullImageWithRetry(tool, image); err != nil {
return fmt.Errorf("failed to pull %s: %w", image, err)
}
return images

pulledImagesLock.Lock()
pulledImages[tool][image] = true
pulledImagesLock.Unlock()

return nil
}

func pullAllImages(testFunc string, images []string) error {
for _, image := range images {
log.Printf("Pulling image: %s", image)
if err := pullImageWithRetry(testFunc, image); err != nil {
return fmt.Errorf("failed to pull %s: %w", image, err)
func ensureTestImages(tool testTool, tc containerTestArgs) error {
if tc.Image != "" {
if err := ensureImage(tool.Name(), tc.Image); err != nil {
return err
}
}
for _, side := range tc.SideContainers {
if side != "" {
if err := ensureImage(tool.Name(), side); err != nil {
return err
}
}
}
return nil
}

func removeAllImages(testFunc string, images []string) {
for _, image := range images {
log.Printf("Removing image: %s", image)
if err := removeImageForTest(testFunc, image); err != nil {
log.Printf("Warning: failed to remove %s: %v", image, err)
func cleanupImages(tool string) {
pulledImagesLock.Lock()
toolImages := pulledImages[tool]
delete(pulledImages, tool)
pulledImagesLock.Unlock()

for img := range toolImages {
log.Printf("Removing image for %s: %s", tool, img)
if err := removeImageForTest(tool, img); err != nil {
log.Printf("Warning: failed to remove %s: %v", img, err)
}
}
}

func pullImageWithRetry(testFunc string, image string) error {
func pullImageWithRetry(tool string, image string) error {
var err error
for i := 0; i < maxPullRetries; i++ {
err = pullImageForTest(testFunc, image)
err = pullImageForTest(tool, image)
if err == nil {
return nil
}
Expand All @@ -78,39 +106,31 @@ func pullImageWithRetry(testFunc string, image string) error {
return fmt.Errorf("failed to pull %s after %d attempts: %w", image, maxPullRetries, err)
}

func pullImageForTest(testFunc string, image string) error {
switch testFunc {
case testCrictl:
func pullImageForTest(tool string, image string) error {
switch tool {
case crictlName:
cmd := crictlName + " pull " + image
output, err := commonCmdExec(cmd)
if err != nil {
return fmt.Errorf("%s -- %v", output, err)
}
return nil
case testNerdctl:
return commonPull(nerdctlName, image)
case testDocker:
return commonPull(dockerName, image)
default:
return commonPull(ctrName, image)
return commonPull(tool, image)
}
}

func removeImageForTest(testFunc string, image string) error {
switch testFunc {
case testCrictl:
func removeImageForTest(tool string, image string) error {
switch tool {
case crictlName:
cmd := crictlName + " rmi " + image
output, err := commonCmdExec(cmd)
if err != nil {
return fmt.Errorf("%s -- %v", output, err)
}
return nil
case testNerdctl:
return commonRmImage(nerdctlName, image)
case testDocker:
return commonRmImage(dockerName, image)
default:
return commonRmImage(ctrName, image)
return commonRmImage(tool, image)
}
}

Expand Down