1 package conditions
2
3 import (
4 "testing"
5
6 . "github.com/onsi/gomega"
7 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8
9 "edge-infra.dev/pkg/k8s/meta/status"
10 "edge-infra.dev/pkg/k8s/object/fobject"
11 )
12
13 func TestNewConditionsGroup(t *testing.T) {
14 g := NewWithT(t)
15
16 negativeFalseReconciling := FalseCondition(status.ReconcilingCondition, "reason reconciling1", "message reconciling1")
17 negativeTrueStalled := TrueCondition(status.StalledCondition, "reason stalled1", "message stalled1")
18 negativeUnknownReconciling := UnknownCondition(status.ReconcilingCondition, "reason reconciling2", "message reconciling2")
19
20 conditions := []*metav1.Condition{nil1, true1, true1, false1, unknown1, negativeFalseReconciling, negativeTrueStalled, negativeUnknownReconciling}
21
22 got := getConditionGroups(conditionsWithSource(&fobject.Fake{}, conditions...), &mergeOptions{
23 negativePolarityConditionTypes: []string{status.ReconcilingCondition, status.StalledCondition},
24 })
25
26 g.Expect(got).ToNot(BeNil())
27 g.Expect(got).To(HaveLen(6))
28
29
30 g.Expect(got.TopGroup().status).To(Equal(metav1.ConditionTrue))
31 g.Expect(got.TopGroup().negativePolarity).To(BeTrue())
32 g.Expect(got.TopGroup().conditions).To(HaveLen(1))
33
34
35 g.Expect(got.TruePositivePolarityGroup().status).To(Equal(metav1.ConditionTrue))
36 g.Expect(got.TruePositivePolarityGroup().negativePolarity).To(BeFalse())
37 g.Expect(got.TruePositivePolarityGroup().conditions).To(HaveLen(2))
38
39
40 g.Expect(got[0].status).To(Equal(metav1.ConditionTrue))
41 g.Expect(got[0].negativePolarity).To(BeTrue())
42 g.Expect(got[0].conditions).To(HaveLen(1))
43
44
45 g.Expect(got[1].status).To(Equal(metav1.ConditionFalse))
46 g.Expect(got[1].negativePolarity).To(BeFalse())
47 g.Expect(got[1].conditions).To(HaveLen(1))
48
49
50 g.Expect(got[2].status).To(Equal(metav1.ConditionTrue))
51 g.Expect(got[1].negativePolarity).To(BeFalse())
52 g.Expect(got[2].conditions).To(HaveLen(2))
53
54
55 g.Expect(got[3].status).To(Equal(metav1.ConditionFalse))
56 g.Expect(got[3].negativePolarity).To(BeTrue())
57 g.Expect(got[3].conditions).To(HaveLen(1))
58
59
60 g.Expect(got[4].status).To(Equal(metav1.ConditionUnknown))
61 g.Expect(got[4].negativePolarity).To(BeFalse())
62 g.Expect(got[4].conditions).To(HaveLen(1))
63
64
65 g.Expect(got[5].status).To(Equal(metav1.ConditionUnknown))
66 g.Expect(got[5].negativePolarity).To(BeTrue())
67 g.Expect(got[3].conditions).To(HaveLen(1))
68
69
70 }
71
72 func TestMergeRespectPriority(t *testing.T) {
73 tests := []struct {
74 name string
75 negativeConditions []string
76 conditions []*metav1.Condition
77 want *metav1.Condition
78 }{
79 {
80 name: "aggregate nil list return nil",
81 conditions: nil,
82 want: nil,
83 },
84 {
85 name: "aggregate empty list return nil",
86 conditions: []*metav1.Condition{},
87 want: nil,
88 },
89 {
90 name: "When there is True/Negative it returns an inverted False/Positive",
91 negativeConditions: []string{true1.Type},
92 conditions: []*metav1.Condition{false1, false1, false1, unknown1, true1},
93 want: FalseCondition("foo", "reason true1", "message true1"),
94 },
95 {
96 name: "When there is False/Positive and no True/Negative, it returns False/Positive",
97 conditions: []*metav1.Condition{false1, false1, unknown1, true1},
98 want: FalseCondition("foo", "reason false1", "message false1"),
99 },
100 {
101 name: "When there is True/Positive and no True/Negative or False/Positive, it returns True/Positive",
102 negativeConditions: []string{false1.Type},
103 conditions: []*metav1.Condition{false1, unknown1, true1},
104 want: TrueCondition("foo", "reason true1", "message true1"),
105 },
106 {
107 name: "When there is True/Positive and no False/Positive, it returns True/Positive",
108 negativeConditions: []string{false1.Type},
109 conditions: []*metav1.Condition{unknown1, true1, false1},
110 want: TrueCondition("foo", "reason true1", "message true1"),
111 },
112 {
113 name: "When there is False/Negative and no True/* or False/Positive, it returns False/Negative",
114 negativeConditions: []string{false1.Type},
115 conditions: []*metav1.Condition{unknown1, false1},
116 want: TrueCondition("foo", "reason false1", "message false1"),
117 },
118 {
119 name: "When there is Unknown/* but no False/*, it returns Unknown/*",
120 conditions: []*metav1.Condition{unknown1},
121 want: UnknownCondition("foo", "reason unknown1", "message unknown1"),
122 },
123 {
124 name: "When the target condition is inverted, it returns an inverted condition",
125 negativeConditions: []string{"foo"},
126 conditions: []*metav1.Condition{true1},
127 want: FalseCondition("foo", "reason true1", "message true1"),
128 },
129 {
130 name: "When the top and target conditions are inverted, it returns an equal condition",
131 negativeConditions: []string{"foo", true1.Type},
132 conditions: []*metav1.Condition{true1},
133 want: TrueCondition("foo", "reason true1", "message true1"),
134 },
135 {
136 name: "nil conditions are ignored",
137 conditions: []*metav1.Condition{nil1, nil1, nil1},
138 want: nil,
139 },
140 }
141
142 for _, tt := range tests {
143 t.Run(tt.name, func(t *testing.T) {
144 g := NewWithT(t)
145
146 got := merge(conditionsWithSource(&fobject.Fake{}, tt.conditions...), "foo", &mergeOptions{
147 negativePolarityConditionTypes: tt.negativeConditions,
148 })
149
150 if tt.want == nil {
151 g.Expect(got).To(BeNil())
152 return
153 }
154 g.Expect(got).To(HaveSameStateOf(tt.want))
155 })
156 }
157 }
158
159 func TestMergeRespectGeneration(t *testing.T) {
160 tests := []struct {
161 name string
162 negativeConditions []string
163 conditions []*metav1.Condition
164 mergeOpts []MergeOption
165 want *metav1.Condition
166 }{
167 {
168 name: "without generation",
169 negativeConditions: []string{true1.Type},
170 conditions: []*metav1.Condition{
171 conditionWithGeneration(false1, 1),
172 conditionWithGeneration(true1, 2),
173 conditionWithGeneration(unknown1, 3),
174 },
175 want: FalseCondition("foo", "reason true1", "message true1"),
176 },
177 {
178 name: "with generation",
179 negativeConditions: []string{true1.Type},
180 conditions: []*metav1.Condition{
181 conditionWithGeneration(false1, 1),
182 conditionWithGeneration(unknown1, 4),
183 conditionWithGeneration(true1, 4),
184 },
185 mergeOpts: []MergeOption{WithLatestGeneration()},
186 want: FalseCondition("foo", "reason true1", "message true1"),
187 },
188 }
189
190 for _, tt := range tests {
191 t.Run(tt.name, func(t *testing.T) {
192 g := NewWithT(t)
193
194 mo := &mergeOptions{
195 negativePolarityConditionTypes: tt.negativeConditions,
196 }
197 for _, o := range tt.mergeOpts {
198 o(mo)
199 }
200 got := merge(conditionsWithSource(&fobject.Fake{}, tt.conditions...), "foo", mo)
201 g.Expect(got).To(HaveSameStateOf(tt.want))
202 })
203 }
204 }
205
206 func conditionsWithSource(obj Setter, conditions ...*metav1.Condition) []localizedCondition {
207 obj.SetConditions(conditionList(conditions...))
208
209 ret := []localizedCondition{}
210 for i := range conditions {
211 ret = append(ret, localizedCondition{
212 Condition: conditions[i],
213 Getter: obj,
214 })
215 }
216
217 return ret
218 }
219
220 func conditionWithGeneration(condition *metav1.Condition, generation int64) *metav1.Condition {
221 condition.ObservedGeneration = generation
222 return condition
223 }
224
View as plain text