Files
pinniped/internal/controller/conditionsutil/conditions_util_test.go

263 lines
6.7 KiB
Go

// Copyright 2024 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package conditionsutil
import (
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"go.pinniped.dev/internal/plog"
)
func TestMergeIDPConditions(t *testing.T) {
twoHoursAgo := metav1.Time{Time: time.Now().Add(-2 * time.Hour)}
oneHourAgo := metav1.Time{Time: time.Now().Add(-1 * time.Hour)}
testTime := metav1.Now()
tests := []struct {
name string
newConditions []*metav1.Condition
existingConditionsToUpdate *[]metav1.Condition
observedGeneration int64
wantResult bool
wantLogSnippets []string
wantConditions []metav1.Condition
}{
{
name: "Adding a new condition with status=True returns false",
newConditions: []*metav1.Condition{
{
Type: "NewType",
Status: metav1.ConditionTrue,
Reason: "new reason",
Message: "new message",
},
},
observedGeneration: int64(999),
existingConditionsToUpdate: &[]metav1.Condition{},
wantLogSnippets: []string{
`"message":"updated condition","type":"NewType","status":"True"`,
},
wantConditions: []metav1.Condition{
{
Type: "NewType",
Status: metav1.ConditionTrue,
ObservedGeneration: int64(999),
LastTransitionTime: testTime,
Reason: "new reason",
Message: "new message",
},
},
wantResult: false,
},
{
name: "Updating a condition status from False to True returns true",
newConditions: []*metav1.Condition{
{
Type: "UnchangedType",
Status: metav1.ConditionTrue,
Reason: "unchanged reason",
Message: "unchanged message",
},
{
Type: "FalseToTrueType",
Status: metav1.ConditionFalse,
Reason: "new reason",
Message: "new message",
},
{
Type: "NewType",
Status: metav1.ConditionTrue,
Reason: "new reason",
Message: "new message",
},
},
existingConditionsToUpdate: &[]metav1.Condition{
{
Type: "UnchangedType",
Status: metav1.ConditionTrue,
ObservedGeneration: int64(10),
LastTransitionTime: twoHoursAgo,
Reason: "unchanged reason",
Message: "unchanged message",
},
{
Type: "FalseToTrueType",
Status: metav1.ConditionTrue,
ObservedGeneration: int64(5),
LastTransitionTime: oneHourAgo,
Reason: "old reason",
Message: "old message",
},
},
observedGeneration: int64(100),
wantLogSnippets: []string{
`"message":"updated condition","type":"UnchangedType","status":"True"`,
`"message":"updated condition","type":"NewType","status":"True"`,
`"message":"updated condition","type":"FalseToTrueType","status":"False"`,
},
wantConditions: []metav1.Condition{
{
Type: "FalseToTrueType",
Status: metav1.ConditionFalse,
ObservedGeneration: int64(100),
LastTransitionTime: testTime,
Reason: "new reason",
Message: "new message",
},
{
Type: "NewType",
Status: metav1.ConditionTrue,
ObservedGeneration: int64(100),
LastTransitionTime: testTime,
Reason: "new reason",
Message: "new message",
},
{
Type: "UnchangedType",
Status: metav1.ConditionTrue,
ObservedGeneration: int64(100),
LastTransitionTime: twoHoursAgo,
Reason: "unchanged reason",
Message: "unchanged message",
},
},
wantResult: true,
},
{
name: "No logs when ObservedGeneration is unchanged",
newConditions: []*metav1.Condition{
{
Type: "UnchangedType",
Status: metav1.ConditionFalse,
Reason: "unchanged reason",
Message: "unchanged message",
},
},
existingConditionsToUpdate: &[]metav1.Condition{
{
Type: "UnchangedType",
Status: metav1.ConditionFalse,
ObservedGeneration: int64(10),
LastTransitionTime: twoHoursAgo,
Reason: "unchanged reason",
Message: "unchanged message",
},
},
observedGeneration: int64(10),
wantConditions: []metav1.Condition{
{
Type: "UnchangedType",
Status: metav1.ConditionFalse,
ObservedGeneration: int64(10),
LastTransitionTime: twoHoursAgo,
Reason: "unchanged reason",
Message: "unchanged message",
},
},
wantResult: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
logger, log := plog.TestLogger(t)
result := MergeConditions(
test.newConditions,
test.existingConditionsToUpdate,
test.observedGeneration,
testTime,
logger,
)
logString := log.String()
require.Equal(t, len(test.wantLogSnippets), strings.Count(logString, "\n"))
for _, wantLog := range test.wantLogSnippets {
require.Contains(t, logString, wantLog)
}
require.Equal(t, test.wantResult, result)
require.Equal(t, test.wantConditions, *test.existingConditionsToUpdate)
})
}
}
func TestHadErrorCondition(t *testing.T) {
tests := []struct {
name string
conditions []*metav1.Condition
wantResult bool
}{
{
name: "Returns false when all conditions have status true",
conditions: []*metav1.Condition{
{
Status: metav1.ConditionTrue,
},
{
Status: metav1.ConditionTrue,
},
},
wantResult: false,
},
{
name: "Returns false when input is nil",
conditions: nil,
wantResult: false,
},
{
name: "Returns false when input is empty",
conditions: []*metav1.Condition{},
wantResult: false,
},
{
name: "Returns true when any condition has status unknown",
conditions: []*metav1.Condition{
{
Status: metav1.ConditionTrue,
},
{
Status: metav1.ConditionUnknown,
},
},
wantResult: true,
},
{
name: "Returns true when any condition has status false",
conditions: []*metav1.Condition{
{
Status: metav1.ConditionTrue,
},
{
Status: metav1.ConditionFalse,
},
},
wantResult: true,
},
{
name: "Returns true when any condition has invalid status",
conditions: []*metav1.Condition{
{
Status: metav1.ConditionTrue,
},
{
Status: "not a valid status",
},
},
wantResult: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := HadErrorCondition(test.conditions)
require.Equal(t, test.wantResult, actual)
})
}
}