mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-04-04 17:58:13 +00:00
214 lines
5.6 KiB
Go
214 lines
5.6 KiB
Go
// Copyright 2020-2025 Project Capsule Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package meta_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"github.com/projectcapsule/capsule/pkg/api/meta"
|
|
)
|
|
|
|
// helper
|
|
func makeCond(tpe, status, reason, msg string, gen int64) meta.Condition {
|
|
return meta.Condition{
|
|
Type: tpe,
|
|
Status: metav1.ConditionStatus(status),
|
|
Reason: reason,
|
|
Message: msg,
|
|
ObservedGeneration: gen,
|
|
LastTransitionTime: metav1.NewTime(time.Unix(0, 0)),
|
|
}
|
|
}
|
|
|
|
func TestConditionList_GetConditionByType(t *testing.T) {
|
|
t.Run("returns matching condition", func(t *testing.T) {
|
|
list := meta.ConditionList{
|
|
makeCond("Ready", "False", "Init", "starting", 1),
|
|
makeCond("Synced", "True", "Ok", "done", 2),
|
|
}
|
|
|
|
got := list.GetConditionByType("Synced")
|
|
assert.NotNil(t, got)
|
|
assert.Equal(t, "Synced", got.Type)
|
|
assert.Equal(t, metav1.ConditionTrue, got.Status)
|
|
assert.Equal(t, "Ok", got.Reason)
|
|
assert.Equal(t, "done", got.Message)
|
|
})
|
|
|
|
t.Run("returns nil when not found", func(t *testing.T) {
|
|
list := meta.ConditionList{
|
|
makeCond("Ready", "False", "Init", "starting", 1),
|
|
}
|
|
assert.Nil(t, list.GetConditionByType("Missing"))
|
|
})
|
|
|
|
t.Run("returned pointer refers to slice element (not copy)", func(t *testing.T) {
|
|
list := meta.ConditionList{
|
|
makeCond("Ready", "False", "Init", "starting", 1),
|
|
makeCond("Synced", "True", "Ok", "done", 2),
|
|
}
|
|
ptr := list.GetConditionByType("Ready")
|
|
assert.NotNil(t, ptr)
|
|
|
|
ptr.Message = "mutated"
|
|
// This asserts GetConditionByType returns &list[i] (via index),
|
|
// not &cond where cond is the range variable copy.
|
|
assert.Equal(t, "mutated", list[0].Message)
|
|
})
|
|
}
|
|
|
|
func TestConditionList_UpdateConditionByType(t *testing.T) {
|
|
now := metav1.Now()
|
|
|
|
t.Run("updates existing condition in place", func(t *testing.T) {
|
|
list := meta.ConditionList{
|
|
makeCond("Ready", "False", "Init", "starting", 1),
|
|
makeCond("Synced", "True", "Ok", "done", 2),
|
|
}
|
|
beforeLen := len(list)
|
|
|
|
list.UpdateConditionByType(meta.Condition{
|
|
Type: "Ready",
|
|
Status: metav1.ConditionTrue,
|
|
Reason: "Reconciled",
|
|
Message: "ready now",
|
|
ObservedGeneration: 3,
|
|
LastTransitionTime: now,
|
|
})
|
|
|
|
assert.Equal(t, beforeLen, len(list))
|
|
got := list.GetConditionByType("Ready")
|
|
assert.NotNil(t, got)
|
|
assert.Equal(t, metav1.ConditionTrue, got.Status)
|
|
assert.Equal(t, "Reconciled", got.Reason)
|
|
assert.Equal(t, "ready now", got.Message)
|
|
assert.Equal(t, int64(3), got.ObservedGeneration)
|
|
})
|
|
|
|
t.Run("appends when condition type not present", func(t *testing.T) {
|
|
list := meta.ConditionList{
|
|
makeCond("Ready", "True", "Ok", "ready", 1),
|
|
}
|
|
beforeLen := len(list)
|
|
|
|
list.UpdateConditionByType(meta.Condition{
|
|
Type: "Synced",
|
|
Status: metav1.ConditionTrue,
|
|
Reason: "Done",
|
|
Message: "synced",
|
|
ObservedGeneration: 2,
|
|
LastTransitionTime: now,
|
|
})
|
|
|
|
assert.Equal(t, beforeLen+1, len(list))
|
|
got := list.GetConditionByType("Synced")
|
|
assert.NotNil(t, got)
|
|
assert.Equal(t, metav1.ConditionTrue, got.Status)
|
|
assert.Equal(t, "Done", got.Reason)
|
|
assert.Equal(t, "synced", got.Message)
|
|
assert.Equal(t, int64(2), got.ObservedGeneration)
|
|
})
|
|
}
|
|
|
|
func TestConditionList_RemoveConditionByType(t *testing.T) {
|
|
t.Run("removes all conditions with matching type", func(t *testing.T) {
|
|
list := meta.ConditionList{
|
|
makeCond("A", "True", "x", "m1", 1),
|
|
makeCond("B", "True", "y", "m2", 1),
|
|
makeCond("A", "False", "z", "m3", 2),
|
|
}
|
|
list.RemoveConditionByType("A")
|
|
|
|
assert.Len(t, list, 1)
|
|
assert.Equal(t, "B", list[0].Type)
|
|
})
|
|
|
|
t.Run("no-op when type not present", func(t *testing.T) {
|
|
orig := meta.ConditionList{
|
|
makeCond("A", "True", "x", "m1", 1),
|
|
}
|
|
list := append(meta.ConditionList{}, orig...) // copy
|
|
|
|
list.RemoveConditionByType("Missing")
|
|
|
|
assert.Equal(t, orig, list)
|
|
})
|
|
|
|
t.Run("nil receiver is safe", func(t *testing.T) {
|
|
var list *meta.ConditionList // nil receiver
|
|
assert.NotPanics(t, func() {
|
|
list.RemoveConditionByType("X")
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestUpdateCondition(t *testing.T) {
|
|
now := metav1.Now()
|
|
|
|
t.Run("no update when all relevant fields match", func(t *testing.T) {
|
|
c := &meta.Condition{
|
|
Type: "Ready",
|
|
Status: "True",
|
|
Reason: "Success",
|
|
Message: "All good",
|
|
}
|
|
|
|
updated := c.UpdateCondition(meta.Condition{
|
|
Type: "Ready",
|
|
Status: "True",
|
|
Reason: "Success",
|
|
Message: "All good",
|
|
LastTransitionTime: now,
|
|
})
|
|
|
|
assert.False(t, updated)
|
|
})
|
|
|
|
t.Run("update occurs on message change", func(t *testing.T) {
|
|
c := &meta.Condition{
|
|
Type: "Ready",
|
|
Status: "True",
|
|
Reason: "Success",
|
|
Message: "Old message",
|
|
}
|
|
|
|
updated := c.UpdateCondition(meta.Condition{
|
|
Type: "Ready",
|
|
Status: "True",
|
|
Reason: "Success",
|
|
Message: "New message",
|
|
LastTransitionTime: now,
|
|
})
|
|
|
|
assert.True(t, updated)
|
|
assert.Equal(t, "New message", c.Message)
|
|
})
|
|
|
|
t.Run("update occurs on status change", func(t *testing.T) {
|
|
c := &meta.Condition{
|
|
Type: "Ready",
|
|
Status: "False",
|
|
Reason: "Pending",
|
|
Message: "Not ready yet",
|
|
}
|
|
|
|
updated := c.UpdateCondition(meta.Condition{
|
|
Type: "Ready",
|
|
Status: "True",
|
|
Reason: "Success",
|
|
Message: "Ready",
|
|
LastTransitionTime: now,
|
|
})
|
|
|
|
assert.True(t, updated)
|
|
assert.Equal(t, "True", string(c.Status))
|
|
assert.Equal(t, "Success", c.Reason)
|
|
assert.Equal(t, "Ready", c.Message)
|
|
})
|
|
}
|