*
* Copyright (c) 2025 Bocloud Technologies Co., Ltd.
* installer is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* <http://license.coscl.org.cn/MulanPSL2>
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*
*/
package common
import (
"fmt"
"testing"
"github.com/agiledragon/gomonkey/v2"
"github.com/stretchr/testify/assert"
econd "gopkg.openfuyao.cn/bkeadm/pkg/executor/containerd"
"gopkg.openfuyao.cn/bkeadm/pkg/executor/docker"
"gopkg.openfuyao.cn/bkeadm/pkg/global"
"gopkg.openfuyao.cn/bkeadm/pkg/infrastructure"
"gopkg.openfuyao.cn/bkeadm/utils"
)
func TestLoadLocalRepositoryFromFile(t *testing.T) {
tests := []struct {
name string
imageFilePath string
mockExists func(string) bool
mockIsDocker func() bool
mockIsContainerd func() bool
mockDockerLoad func(*docker.Client, string) (string, error)
mockContainerdLoad func(string) error
expectError bool
}{
{
name: "file exists, docker runtime, load successful",
imageFilePath: "/path/to/image.tar",
mockExists: func(path string) bool {
return true
},
mockIsDocker: func() bool {
return true
},
mockIsContainerd: func() bool {
return false
},
mockDockerLoad: func(c *docker.Client, path string) (string, error) {
return "loaded successfully", nil
},
mockContainerdLoad: func(path string) error {
return nil
},
expectError: false,
},
{
name: "file exists, containerd runtime, load successful",
imageFilePath: "/path/to/image.tar",
mockExists: func(path string) bool {
return true
},
mockIsDocker: func() bool {
return false
},
mockIsContainerd: func() bool {
return true
},
mockDockerLoad: func(c *docker.Client, path string) (string, error) {
return "", nil
},
mockContainerdLoad: func(path string) error {
return nil
},
expectError: false,
},
{
name: "file exists, both runtimes active, both load successful",
imageFilePath: "/path/to/image.tar",
mockExists: func(path string) bool {
return true
},
mockIsDocker: func() bool {
return true
},
mockIsContainerd: func() bool {
return true
},
mockDockerLoad: func(c *docker.Client, path string) (string, error) {
return "docker loaded", nil
},
mockContainerdLoad: func(path string) error {
return nil
},
expectError: false,
},
{
name: "file exists, docker runtime, docker load fails",
imageFilePath: "/path/to/image.tar",
mockExists: func(path string) bool {
return true
},
mockIsDocker: func() bool {
return true
},
mockIsContainerd: func() bool {
return false
},
mockDockerLoad: func(c *docker.Client, path string) (string, error) {
return "", fmt.Errorf("docker load error")
},
mockContainerdLoad: func(path string) error {
return nil
},
expectError: true,
},
{
name: "file exists, containerd runtime, containerd load fails",
imageFilePath: "/path/to/image.tar",
mockExists: func(path string) bool {
return true
},
mockIsDocker: func() bool {
return false
},
mockIsContainerd: func() bool {
return true
},
mockDockerLoad: func(c *docker.Client, path string) (string, error) {
return "", nil
},
mockContainerdLoad: func(path string) error {
return fmt.Errorf("containerd load error")
},
expectError: true,
},
{
name: "file does not exist",
imageFilePath: "/path/to/nonexistent.tar",
mockExists: func(path string) bool {
return false
},
mockIsDocker: func() bool {
return true
},
mockIsContainerd: func() bool {
return true
},
mockDockerLoad: func(c *docker.Client, path string) (string, error) {
return "", nil
},
mockContainerdLoad: func(path string) error {
return nil
},
expectError: false,
},
{
name: "file exists, neither runtime active",
imageFilePath: "/path/to/image.tar",
mockExists: func(path string) bool {
return true
},
mockIsDocker: func() bool {
return false
},
mockIsContainerd: func() bool {
return false
},
mockDockerLoad: func(c *docker.Client, path string) (string, error) {
return "", nil
},
mockContainerdLoad: func(path string) error {
return nil
},
expectError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.Exists, tt.mockExists)
patches.ApplyFunc(infrastructure.IsDocker, tt.mockIsDocker)
patches.ApplyFunc(infrastructure.IsContainerd, tt.mockIsContainerd)
patches.ApplyFunc((*docker.Client).Load, tt.mockDockerLoad)
patches.ApplyFunc(econd.Load, tt.mockContainerdLoad)
if global.Docker == nil {
global.Docker = &docker.Client{}
}
err := LoadLocalRepositoryFromFile(tt.imageFilePath)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestLoadLocalRepositoryFromFileBothRuntimesFail(t *testing.T) {
imageFilePath := "/path/to/image.tar"
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.Exists, func(path string) bool {
return true
})
patches.ApplyFunc(infrastructure.IsDocker, func() bool {
return true
})
patches.ApplyFunc(infrastructure.IsContainerd, func() bool {
return true
})
patches.ApplyFunc((*docker.Client).Load, func(c *docker.Client, path string) (string, error) {
return "", fmt.Errorf("docker load error")
})
patches.ApplyFunc(econd.Load, func(path string) error {
return fmt.Errorf("containerd load error")
})
err := LoadLocalRepositoryFromFile(imageFilePath)
assert.Error(t, err)
assert.Contains(t, err.Error(), "docker load error")
}
func TestLoadLocalRepositoryFromFileWithEmptyPath(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.Exists, func(path string) bool {
return false
})
patches.ApplyFunc(infrastructure.IsDocker, func() bool {
return true
})
patches.ApplyFunc(infrastructure.IsContainerd, func() bool {
return true
})
patches.ApplyFunc((*docker.Client).Load, func(c *docker.Client, path string) (string, error) {
return "", nil
})
patches.ApplyFunc(econd.Load, func(path string) error {
return nil
})
err := LoadLocalRepositoryFromFile("")
assert.NoError(t, err)
}
func TestLoadLocalRepositoryFromFileDockerOnly(t *testing.T) {
imageFilePath := "/path/to/image.tar"
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.Exists, func(path string) bool {
return true
})
patches.ApplyFunc(infrastructure.IsDocker, func() bool {
return true
})
patches.ApplyFunc(infrastructure.IsContainerd, func() bool {
return false
})
loadCalled := false
patches.ApplyFunc((*docker.Client).Load, func(c *docker.Client, path string) (string, error) {
loadCalled = true
return "docker loaded", nil
})
patches.ApplyFunc(econd.Load, func(path string) error {
t.Error("Containerd load should not be called when only Docker is active")
return nil
})
err := LoadLocalRepositoryFromFile(imageFilePath)
assert.NoError(t, err)
assert.True(t, loadCalled)
}
func TestLoadLocalRepositoryFromFileContainerdOnly(t *testing.T) {
imageFilePath := "/path/to/image.tar"
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.Exists, func(path string) bool {
return true
})
patches.ApplyFunc(infrastructure.IsDocker, func() bool {
return false
})
patches.ApplyFunc(infrastructure.IsContainerd, func() bool {
return true
})
patches.ApplyFunc((*docker.Client).Load, func(c *docker.Client, path string) (string, error) {
t.Error("Docker load should not be called when only Containerd is active")
return "", nil
})
loadCalled := false
patches.ApplyFunc(econd.Load, func(path string) error {
loadCalled = true
return nil
})
err := LoadLocalRepositoryFromFile(imageFilePath)
assert.NoError(t, err)
assert.True(t, loadCalled)
}