mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 03:20:11 +00:00
test: Add tests for convertDockerSwarmInfo, namespacePathsForDatastore, preserveFailedStorageBackups
- convertDockerSwarmInfo: 66.7%→100% (4 cases for nil, empty, populated structs) - namespacePathsForDatastore: 92.3%→100% (removed unreachable dead code) - preserveFailedStorageBackups: 91.3%→100% (6 cases for filtering, deduplication)
This commit is contained in:
parent
79272eda40
commit
dfc0059bd9
3 changed files with 254 additions and 3 deletions
|
|
@ -8134,9 +8134,6 @@ func namespacePathsForDatastore(ds models.PBSDatastore) []string {
|
|||
seen[path] = struct{}{}
|
||||
paths = append(paths, path)
|
||||
}
|
||||
if len(paths) == 0 {
|
||||
paths = append(paths, "")
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/models"
|
||||
agentsdocker "github.com/rcourtman/pulse-go-rewrite/pkg/agents/docker"
|
||||
)
|
||||
|
||||
func TestParseDurationEnv(t *testing.T) {
|
||||
|
|
@ -1677,3 +1678,110 @@ func TestSchedulerHealth(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestConvertDockerSwarmInfo(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input *agentsdocker.SwarmInfo
|
||||
expected *models.DockerSwarmInfo
|
||||
}{
|
||||
{
|
||||
name: "nil input returns nil",
|
||||
input: nil,
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "empty struct returns empty struct",
|
||||
input: &agentsdocker.SwarmInfo{},
|
||||
expected: &models.DockerSwarmInfo{},
|
||||
},
|
||||
{
|
||||
name: "all fields populated",
|
||||
input: &agentsdocker.SwarmInfo{
|
||||
NodeID: "node-abc123",
|
||||
NodeRole: "manager",
|
||||
LocalState: "active",
|
||||
ControlAvailable: true,
|
||||
ClusterID: "cluster-xyz789",
|
||||
ClusterName: "my-swarm",
|
||||
Scope: "swarm",
|
||||
Error: "",
|
||||
},
|
||||
expected: &models.DockerSwarmInfo{
|
||||
NodeID: "node-abc123",
|
||||
NodeRole: "manager",
|
||||
LocalState: "active",
|
||||
ControlAvailable: true,
|
||||
ClusterID: "cluster-xyz789",
|
||||
ClusterName: "my-swarm",
|
||||
Scope: "swarm",
|
||||
Error: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "worker node with error",
|
||||
input: &agentsdocker.SwarmInfo{
|
||||
NodeID: "node-worker1",
|
||||
NodeRole: "worker",
|
||||
LocalState: "pending",
|
||||
ControlAvailable: false,
|
||||
ClusterID: "",
|
||||
ClusterName: "",
|
||||
Scope: "local",
|
||||
Error: "connection refused",
|
||||
},
|
||||
expected: &models.DockerSwarmInfo{
|
||||
NodeID: "node-worker1",
|
||||
NodeRole: "worker",
|
||||
LocalState: "pending",
|
||||
ControlAvailable: false,
|
||||
ClusterID: "",
|
||||
ClusterName: "",
|
||||
Scope: "local",
|
||||
Error: "connection refused",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := convertDockerSwarmInfo(tt.input)
|
||||
|
||||
if tt.expected == nil {
|
||||
if result != nil {
|
||||
t.Errorf("expected nil, got %+v", result)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
t.Fatal("expected non-nil result")
|
||||
}
|
||||
|
||||
if result.NodeID != tt.expected.NodeID {
|
||||
t.Errorf("NodeID: expected %q, got %q", tt.expected.NodeID, result.NodeID)
|
||||
}
|
||||
if result.NodeRole != tt.expected.NodeRole {
|
||||
t.Errorf("NodeRole: expected %q, got %q", tt.expected.NodeRole, result.NodeRole)
|
||||
}
|
||||
if result.LocalState != tt.expected.LocalState {
|
||||
t.Errorf("LocalState: expected %q, got %q", tt.expected.LocalState, result.LocalState)
|
||||
}
|
||||
if result.ControlAvailable != tt.expected.ControlAvailable {
|
||||
t.Errorf("ControlAvailable: expected %v, got %v", tt.expected.ControlAvailable, result.ControlAvailable)
|
||||
}
|
||||
if result.ClusterID != tt.expected.ClusterID {
|
||||
t.Errorf("ClusterID: expected %q, got %q", tt.expected.ClusterID, result.ClusterID)
|
||||
}
|
||||
if result.ClusterName != tt.expected.ClusterName {
|
||||
t.Errorf("ClusterName: expected %q, got %q", tt.expected.ClusterName, result.ClusterName)
|
||||
}
|
||||
if result.Scope != tt.expected.Scope {
|
||||
t.Errorf("Scope: expected %q, got %q", tt.expected.Scope, result.Scope)
|
||||
}
|
||||
if result.Error != tt.expected.Error {
|
||||
t.Errorf("Error: expected %q, got %q", tt.expected.Error, result.Error)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,152 @@ func TestPreserveFailedStorageBackupsSkipsDuplicates(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPreserveFailedStorageBackupsEmptyPreserveMap(t *testing.T) {
|
||||
instance := "pve01"
|
||||
current := []models.StorageBackup{
|
||||
{ID: "backup1", Instance: instance, Storage: "local"},
|
||||
}
|
||||
snapshot := models.StateSnapshot{
|
||||
PVEBackups: models.PVEBackups{
|
||||
StorageBackups: []models.StorageBackup{
|
||||
{ID: "backup2", Instance: instance, Storage: "nas-share"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
merged, storages := preserveFailedStorageBackups(instance, snapshot, nil, current)
|
||||
|
||||
if len(merged) != 1 {
|
||||
t.Fatalf("expected current unchanged with 1 backup, got %d", len(merged))
|
||||
}
|
||||
if storages != nil {
|
||||
t.Fatalf("expected nil storages list, got %v", storages)
|
||||
}
|
||||
|
||||
// Also test empty map (not nil)
|
||||
merged2, storages2 := preserveFailedStorageBackups(instance, snapshot, map[string]struct{}{}, current)
|
||||
if len(merged2) != 1 {
|
||||
t.Fatalf("expected current unchanged with 1 backup, got %d", len(merged2))
|
||||
}
|
||||
if storages2 != nil {
|
||||
t.Fatalf("expected nil storages list for empty map, got %v", storages2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreserveFailedStorageBackupsNoMatchingBackups(t *testing.T) {
|
||||
instance := "pve01"
|
||||
current := []models.StorageBackup{
|
||||
{ID: "backup1", Instance: instance, Storage: "local"},
|
||||
}
|
||||
snapshot := models.StateSnapshot{
|
||||
PVEBackups: models.PVEBackups{
|
||||
StorageBackups: []models.StorageBackup{
|
||||
{ID: "backup2", Instance: instance, Storage: "other-storage"},
|
||||
},
|
||||
},
|
||||
}
|
||||
toPreserve := map[string]struct{}{
|
||||
"nas-share": {}, // Storage not in snapshot
|
||||
}
|
||||
|
||||
merged, storages := preserveFailedStorageBackups(instance, snapshot, toPreserve, current)
|
||||
|
||||
if len(merged) != 1 {
|
||||
t.Fatalf("expected current unchanged with 1 backup, got %d", len(merged))
|
||||
}
|
||||
if storages != nil {
|
||||
t.Fatalf("expected nil storages list when no matches, got %v", storages)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreserveFailedStorageBackupsWrongInstance(t *testing.T) {
|
||||
instance := "pve01"
|
||||
current := []models.StorageBackup{
|
||||
{ID: "backup1", Instance: instance, Storage: "local"},
|
||||
}
|
||||
snapshot := models.StateSnapshot{
|
||||
PVEBackups: models.PVEBackups{
|
||||
StorageBackups: []models.StorageBackup{
|
||||
{ID: "backup2", Instance: "pve02", Storage: "nas-share"}, // Wrong instance
|
||||
},
|
||||
},
|
||||
}
|
||||
toPreserve := map[string]struct{}{
|
||||
"nas-share": {},
|
||||
}
|
||||
|
||||
merged, storages := preserveFailedStorageBackups(instance, snapshot, toPreserve, current)
|
||||
|
||||
if len(merged) != 1 {
|
||||
t.Fatalf("expected current unchanged (wrong instance skipped), got %d backups", len(merged))
|
||||
}
|
||||
if storages != nil {
|
||||
t.Fatalf("expected nil storages list, got %v", storages)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreserveFailedStorageBackupsStorageNotInPreserveMap(t *testing.T) {
|
||||
instance := "pve01"
|
||||
current := []models.StorageBackup{
|
||||
{ID: "backup1", Instance: instance, Storage: "local"},
|
||||
}
|
||||
snapshot := models.StateSnapshot{
|
||||
PVEBackups: models.PVEBackups{
|
||||
StorageBackups: []models.StorageBackup{
|
||||
{ID: "backup2", Instance: instance, Storage: "nas-share"},
|
||||
{ID: "backup3", Instance: instance, Storage: "other-storage"},
|
||||
},
|
||||
},
|
||||
}
|
||||
toPreserve := map[string]struct{}{
|
||||
"nas-share": {}, // Only nas-share should be preserved
|
||||
}
|
||||
|
||||
merged, storages := preserveFailedStorageBackups(instance, snapshot, toPreserve, current)
|
||||
|
||||
if len(merged) != 2 {
|
||||
t.Fatalf("expected 2 backups (original + nas-share), got %d", len(merged))
|
||||
}
|
||||
if len(storages) != 1 || storages[0] != "nas-share" {
|
||||
t.Fatalf("expected [nas-share], got %v", storages)
|
||||
}
|
||||
// Verify other-storage was not added
|
||||
for _, b := range merged {
|
||||
if b.Storage == "other-storage" {
|
||||
t.Fatal("other-storage should not have been preserved")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreserveFailedStorageBackupsSortedStorageNames(t *testing.T) {
|
||||
instance := "pve01"
|
||||
current := []models.StorageBackup{}
|
||||
snapshot := models.StateSnapshot{
|
||||
PVEBackups: models.PVEBackups{
|
||||
StorageBackups: []models.StorageBackup{
|
||||
{ID: "backup1", Instance: instance, Storage: "zebra-storage"},
|
||||
{ID: "backup2", Instance: instance, Storage: "alpha-storage"},
|
||||
{ID: "backup3", Instance: instance, Storage: "middle-storage"},
|
||||
},
|
||||
},
|
||||
}
|
||||
toPreserve := map[string]struct{}{
|
||||
"zebra-storage": {},
|
||||
"alpha-storage": {},
|
||||
"middle-storage": {},
|
||||
}
|
||||
|
||||
merged, storages := preserveFailedStorageBackups(instance, snapshot, toPreserve, current)
|
||||
|
||||
if len(merged) != 3 {
|
||||
t.Fatalf("expected 3 backups, got %d", len(merged))
|
||||
}
|
||||
expected := []string{"alpha-storage", "middle-storage", "zebra-storage"}
|
||||
if !slices.Equal(storages, expected) {
|
||||
t.Fatalf("expected sorted storages %v, got %v", expected, storages)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStorageNamesForNode(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue