package conditions import ( "testing" fuzz "github.com/AdaLogics/go-fuzz-headers" . "github.com/onsi/gomega" //nolint:revive // TODO(aw185176): remove metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestMatchConditions(t *testing.T) { testCases := []struct { name string actual interface{} expected []metav1.Condition expectMatch bool }{ { name: "with an empty conditions", actual: []metav1.Condition{}, expected: []metav1.Condition{}, expectMatch: true, }, { name: "with matching conditions", actual: []metav1.Condition{ { Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, }, expected: []metav1.Condition{ { Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, }, expectMatch: true, }, { name: "with non-matching conditions", actual: []metav1.Condition{ { Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, { Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, }, expected: []metav1.Condition{ { Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, { Type: "different", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "different", Message: "different", }, }, expectMatch: false, }, { name: "with a different number of conditions", actual: []metav1.Condition{ { Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, { Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, }, expected: []metav1.Condition{ { Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, }, expectMatch: false, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { g := NewWithT(t) if tc.expectMatch { g.Expect(tc.actual).To(MatchConditions(tc.expected)) } else { g.Expect(tc.actual).ToNot(MatchConditions(tc.expected)) } }) } } func TestMatchCondition(t *testing.T) { testCases := []struct { name string actual interface{} expected metav1.Condition expectMatch bool }{ { name: "with an empty condition", actual: metav1.Condition{}, expected: metav1.Condition{}, expectMatch: true, }, { name: "with a matching condition", actual: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expected: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expectMatch: true, }, { name: "with a different time", actual: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expected: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Time{}, Reason: "reason", Message: "message", }, expectMatch: true, }, { name: "with a different type", actual: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expected: metav1.Condition{ Type: "different", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expectMatch: false, }, { name: "with a different status", actual: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expected: metav1.Condition{ Type: "type", Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expectMatch: false, }, { name: "with a different reason", actual: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expected: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "different", Message: "message", }, expectMatch: false, }, { name: "with a different message", actual: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expected: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "different", }, expectMatch: false, }, { name: "with a subset message", actual: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "message", }, expected: metav1.Condition{ Type: "type", Status: metav1.ConditionTrue, LastTransitionTime: metav1.Now(), Reason: "reason", Message: "mes", }, expectMatch: true, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { g := NewWithT(t) if tc.expectMatch { g.Expect(tc.actual).To(MatchCondition(tc.expected)) } else { g.Expect(tc.actual).ToNot(MatchCondition(tc.expected)) } }) } } func Fuzz_Match(f *testing.F) { f.Fuzz(func(_ *testing.T, data []byte) { f := fuzz.NewConsumer(data) condition := metav1.Condition{} err := f.GenerateStruct(&condition) if err != nil { return } m := MatchCondition(condition) actual := metav1.Condition{} err = f.GenerateStruct(&actual) if err == nil { _, _ = m.Match(actual) } }) }