*
* 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 cmd
import (
"fmt"
"testing"
"time"
"github.com/agiledragon/gomonkey/v2"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
configinit "gopkg.openfuyao.cn/cluster-api-provider-bke/common/cluster/initialize"
"gopkg.openfuyao.cn/cluster-api-provider-bke/common/ntp/sntp"
"gopkg.openfuyao.cn/bkeadm/pkg/executor/containerd"
"gopkg.openfuyao.cn/bkeadm/utils"
)
const (
dockerContainerResultCount = 1
containerdContainerResultCount = 1
nfsPortNumber = "2049"
containerdServiceType = "containerd"
dockerServiceType = "docker"
testContainerdName = "test-containerd"
testContainerName = "test-container"
containerType = "container"
containerNotCreatedStatus = "notCreated"
testContainerAddress = "tcp://0.0.0.0:8080"
testContainerId = "test-id"
firstIndex = 0
secondIndex = 1
thirdIndex = 2
fourthIndex = 3
)
func TestStatusCmdInitialization(t *testing.T) {
tests := []struct {
name string
expectedUse string
expectedShort string
}{
{
name: "status command properties",
expectedUse: "status",
expectedShort: "Displays the status of the local service started by bke.",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expectedUse, statusCmd.Use)
assert.Equal(t, tt.expectedShort, statusCmd.Short)
})
}
}
func TestRegisterStatusCommand(t *testing.T) {
registerStatusCommand()
var foundStatusCmd bool
for _, cmd := range rootCmd.Commands() {
if cmd.Use == "status" {
foundStatusCmd = true
break
}
}
assert.True(t, foundStatusCmd, "status command should be registered in root command")
}
func TestGetContainerServers(t *testing.T) {
containerServers := getContainerServers()
assert.NotEmpty(t, containerServers)
expectedContainers := []string{
utils.LocalKubernetesName,
utils.LocalImageRegistryName,
utils.LocalYumRegistryName,
utils.LocalChartRegistryName,
utils.LocalNFSRegistryName,
}
var foundContainers []string
for _, server := range containerServers {
foundContainers = append(foundContainers, server[secondIndex])
}
for _, expected := range expectedContainers {
assert.Contains(t, foundContainers, expected)
}
for _, server := range containerServers {
name := server[secondIndex]
defaultAddr := server[thirdIndex]
switch name {
case utils.LocalKubernetesName:
assert.Contains(t, defaultAddr, utils.DefaultKubernetesPort)
case utils.LocalImageRegistryName:
assert.Contains(t, defaultAddr, configinit.DefaultImageRepoPort)
case utils.LocalYumRegistryName:
assert.Contains(t, defaultAddr, configinit.DefaultYumRepoPort)
case utils.LocalChartRegistryName:
assert.Contains(t, defaultAddr, utils.DefaultChartRegistryPort)
case utils.LocalNFSRegistryName:
assert.Contains(t, defaultAddr, nfsPortNumber)
}
}
}
func TestGetNtpServerStatus(t *testing.T) {
tests := []struct {
name string
mockNtpClient func(string) (time.Time, error)
mockExists func(string) bool
expectedStatus string
expectedServiceType string
}{
{
name: "NTP server running",
mockNtpClient: func(addr string) (time.Time, error) {
return time.Now(), nil
},
mockExists: func(path string) bool {
return true
},
expectedStatus: "running",
expectedServiceType: "systemd",
},
{
name: "NTP server not running",
mockNtpClient: func(addr string) (time.Time, error) {
return time.Now(), fmt.Errorf("connection failed")
},
mockExists: func(path string) bool {
return true
},
expectedStatus: "notCreated",
expectedServiceType: "systemd",
},
{
name: "NTP server running without systemd file",
mockNtpClient: func(addr string) (time.Time, error) {
return time.Now(), nil
},
mockExists: func(path string) bool {
return false
},
expectedStatus: "running",
expectedServiceType: "proc",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(sntp.Client, tt.mockNtpClient)
patches.ApplyFunc(utils.Exists, tt.mockExists)
getNtpServerStatus()
})
}
}
func TestGetContainerdContainerStatus(t *testing.T) {
containerServers := [][]string{
{containerType, testContainerdName, testContainerAddress, containerNotCreatedStatus, ""},
}
tests := []struct {
name string
mockContainerInspect func(name string) (containerd.NerdContainerInfo, error)
expectedStatus string
}{
{
name: "containerd container exists and is running",
mockContainerInspect: func(name string) (containerd.NerdContainerInfo, error) {
return containerd.NerdContainerInfo{}, nil
},
expectedStatus: "running",
},
{
name: "containerd container does not exist",
mockContainerInspect: func(name string) (containerd.NerdContainerInfo, error) {
return containerd.NerdContainerInfo{}, fmt.Errorf("container not found")
},
expectedStatus: "notCreated"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(containerd.ContainerInspect, tt.mockContainerInspect)
result := getContainerdContainerStatus(containerServers)
assert.Len(t, result, containerdContainerResultCount)
assert.Equal(t, containerdServiceType, result[firstIndex][firstIndex])
assert.Equal(t, testContainerdName, result[firstIndex][secondIndex])
})
}
}
func TestStatusCmdRun(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(containerd.ContainerInspect,
func(name string) (containerd.NerdContainerInfo, error) { return containerd.NerdContainerInfo{}, nil })
patches.Reset()
patches.ApplyFunc(containerd.ContainerExists,
func(name string) (containerd.NerdContainerInfo, bool) { return containerd.NerdContainerInfo{}, true })
patches.Reset()
cmd := &cobra.Command{}
args := []string{}
statusCmd.Run(cmd, args)
assert.True(t, true)
}