sigs.k8s.io/cluster-api@v1.7.1/util/conditions/getter_test.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package conditions 18 19 import ( 20 "testing" 21 22 . "github.com/onsi/gomega" 23 24 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 25 ) 26 27 var ( 28 nil1 *clusterv1.Condition 29 true1 = TrueCondition("true1") 30 unknown1 = UnknownCondition("unknown1", "reason unknown1", "message unknown1") 31 falseInfo1 = FalseCondition("falseInfo1", "reason falseInfo1", clusterv1.ConditionSeverityInfo, "message falseInfo1") 32 falseWarning1 = FalseCondition("falseWarning1", "reason falseWarning1", clusterv1.ConditionSeverityWarning, "message falseWarning1") 33 falseError1 = FalseCondition("falseError1", "reason falseError1", clusterv1.ConditionSeverityError, "message falseError1") 34 ) 35 36 func TestGetAndHas(t *testing.T) { 37 g := NewWithT(t) 38 39 cluster := &clusterv1.Cluster{} 40 41 g.Expect(Has(cluster, "conditionBaz")).To(BeFalse()) 42 g.Expect(Get(cluster, "conditionBaz")).To(BeNil()) 43 44 cluster.SetConditions(conditionList(TrueCondition("conditionBaz"))) 45 46 g.Expect(Has(cluster, "conditionBaz")).To(BeTrue()) 47 g.Expect(Get(cluster, "conditionBaz")).To(HaveSameStateOf(TrueCondition("conditionBaz"))) 48 } 49 50 func TestIsMethods(t *testing.T) { 51 g := NewWithT(t) 52 53 obj := getterWithConditions(nil1, true1, unknown1, falseInfo1, falseWarning1, falseError1) 54 55 // test isTrue 56 g.Expect(IsTrue(obj, "nil1")).To(BeFalse()) 57 g.Expect(IsTrue(obj, "true1")).To(BeTrue()) 58 g.Expect(IsTrue(obj, "falseInfo1")).To(BeFalse()) 59 g.Expect(IsTrue(obj, "unknown1")).To(BeFalse()) 60 61 // test isFalse 62 g.Expect(IsFalse(obj, "nil1")).To(BeFalse()) 63 g.Expect(IsFalse(obj, "true1")).To(BeFalse()) 64 g.Expect(IsFalse(obj, "falseInfo1")).To(BeTrue()) 65 g.Expect(IsFalse(obj, "unknown1")).To(BeFalse()) 66 67 // test isUnknown 68 g.Expect(IsUnknown(obj, "nil1")).To(BeTrue()) 69 g.Expect(IsUnknown(obj, "true1")).To(BeFalse()) 70 g.Expect(IsUnknown(obj, "falseInfo1")).To(BeFalse()) 71 g.Expect(IsUnknown(obj, "unknown1")).To(BeTrue()) 72 73 // test GetReason 74 g.Expect(GetReason(obj, "nil1")).To(Equal("")) 75 g.Expect(GetReason(obj, "falseInfo1")).To(Equal("reason falseInfo1")) 76 77 // test GetMessage 78 g.Expect(GetMessage(obj, "nil1")).To(Equal("")) 79 g.Expect(GetMessage(obj, "falseInfo1")).To(Equal("message falseInfo1")) 80 81 // test GetSeverity 82 g.Expect(GetSeverity(obj, "nil1")).To(BeNil()) 83 severity := GetSeverity(obj, "falseInfo1") 84 expectedSeverity := clusterv1.ConditionSeverityInfo 85 g.Expect(severity).To(Equal(&expectedSeverity)) 86 87 // test GetMessage 88 g.Expect(GetLastTransitionTime(obj, "nil1")).To(BeNil()) 89 g.Expect(GetLastTransitionTime(obj, "falseInfo1")).ToNot(BeNil()) 90 } 91 92 func TestMirror(t *testing.T) { 93 foo := FalseCondition("foo", "reason foo", clusterv1.ConditionSeverityInfo, "message foo") 94 ready := TrueCondition(clusterv1.ReadyCondition) 95 readyBar := ready.DeepCopy() 96 readyBar.Type = "bar" 97 98 tests := []struct { 99 name string 100 from Getter 101 t clusterv1.ConditionType 102 want *clusterv1.Condition 103 }{ 104 { 105 name: "Returns nil when the ready condition does not exists", 106 from: getterWithConditions(foo), 107 want: nil, 108 }, 109 { 110 name: "Returns ready condition from source", 111 from: getterWithConditions(ready, foo), 112 t: "bar", 113 want: readyBar, 114 }, 115 } 116 117 for _, tt := range tests { 118 t.Run(tt.name, func(t *testing.T) { 119 g := NewWithT(t) 120 121 got := mirror(tt.from, tt.t) 122 if tt.want == nil { 123 g.Expect(got).To(BeNil()) 124 return 125 } 126 g.Expect(got).To(HaveSameStateOf(tt.want)) 127 }) 128 } 129 } 130 131 func TestSummary(t *testing.T) { 132 foo := TrueCondition("foo") 133 bar := FalseCondition("bar", "reason falseInfo1", clusterv1.ConditionSeverityInfo, "message falseInfo1") 134 baz := FalseCondition("baz", "reason falseInfo2", clusterv1.ConditionSeverityInfo, "message falseInfo2") 135 existingReady := FalseCondition(clusterv1.ReadyCondition, "reason falseError1", clusterv1.ConditionSeverityError, "message falseError1") // NB. existing ready has higher priority than other conditions 136 137 tests := []struct { 138 name string 139 from Getter 140 options []MergeOption 141 want *clusterv1.Condition 142 }{ 143 { 144 name: "Returns nil when there are no conditions to summarize", 145 from: getterWithConditions(), 146 want: nil, 147 }, 148 { 149 name: "Returns ready condition with the summary of existing conditions (with default options)", 150 from: getterWithConditions(foo, bar), 151 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "message falseInfo1"), 152 }, 153 { 154 name: "Returns ready condition with the summary of existing conditions (using WithStepCounter options)", 155 from: getterWithConditions(foo, bar), 156 options: []MergeOption{WithStepCounter()}, 157 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "1 of 2 completed"), 158 }, 159 { 160 name: "Returns ready condition with the summary of existing conditions (using WithStepCounterIf options)", 161 from: getterWithConditions(foo, bar), 162 options: []MergeOption{WithStepCounterIf(false)}, 163 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "message falseInfo1"), 164 }, 165 { 166 name: "Returns ready condition with the summary of existing conditions (using WithStepCounterIf options)", 167 from: getterWithConditions(foo, bar), 168 options: []MergeOption{WithStepCounterIf(true)}, 169 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "1 of 2 completed"), 170 }, 171 { 172 name: "Returns ready condition with the summary of existing conditions (using WithStepCounterIf and WithStepCounterIfOnly options)", 173 from: getterWithConditions(bar), 174 options: []MergeOption{WithStepCounter(), WithStepCounterIfOnly("bar")}, 175 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "0 of 1 completed"), 176 }, 177 { 178 name: "Returns ready condition with the summary of existing conditions (using WithStepCounterIf and WithStepCounterIfOnly options)", 179 from: getterWithConditions(foo, bar), 180 options: []MergeOption{WithStepCounter(), WithStepCounterIfOnly("foo")}, 181 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "message falseInfo1"), 182 }, 183 { 184 name: "Returns ready condition with the summary of selected conditions (using WithConditions options)", 185 from: getterWithConditions(foo, bar), 186 options: []MergeOption{WithConditions("foo")}, // bar should be ignored 187 want: TrueCondition(clusterv1.ReadyCondition), 188 }, 189 { 190 name: "Returns ready condition with the summary of selected conditions (using WithConditions and WithStepCounter options)", 191 from: getterWithConditions(foo, bar, baz), 192 options: []MergeOption{WithConditions("foo", "bar"), WithStepCounter()}, // baz should be ignored, total steps should be 2 193 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "1 of 2 completed"), 194 }, 195 { 196 name: "Returns ready condition with the summary of selected conditions (using WithConditions and WithStepCounterIfOnly options)", 197 from: getterWithConditions(bar), 198 options: []MergeOption{WithConditions("bar", "baz"), WithStepCounter(), WithStepCounterIfOnly("bar")}, // there is only bar, the step counter should be set and counts only a subset of conditions 199 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "0 of 1 completed"), 200 }, 201 { 202 name: "Returns ready condition with the summary of selected conditions (using WithConditions and WithStepCounterIfOnly options - with inconsistent order between the two)", 203 from: getterWithConditions(bar), 204 options: []MergeOption{WithConditions("baz", "bar"), WithStepCounter(), WithStepCounterIfOnly("bar", "baz")}, // conditions in WithStepCounterIfOnly could be in different order than in WithConditions 205 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "0 of 2 completed"), 206 }, 207 { 208 name: "Returns ready condition with the summary of selected conditions (using WithConditions and WithStepCounterIfOnly options)", 209 from: getterWithConditions(bar, baz), 210 options: []MergeOption{WithConditions("bar", "baz"), WithStepCounter(), WithStepCounterIfOnly("bar")}, // there is also baz, so the step counter should not be set 211 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "message falseInfo1"), 212 }, 213 { 214 name: "Ready condition respects merge order", 215 from: getterWithConditions(bar, baz), 216 options: []MergeOption{WithConditions("baz", "bar")}, // baz should take precedence on bar 217 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo2", clusterv1.ConditionSeverityInfo, "message falseInfo2"), 218 }, 219 { 220 name: "Ignores existing Ready condition when computing the summary", 221 from: getterWithConditions(existingReady, foo, bar), 222 want: FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "message falseInfo1"), 223 }, 224 } 225 226 for _, tt := range tests { 227 t.Run(tt.name, func(t *testing.T) { 228 g := NewWithT(t) 229 230 got := summary(tt.from, tt.options...) 231 if tt.want == nil { 232 g.Expect(got).To(BeNil()) 233 return 234 } 235 g.Expect(got).To(HaveSameStateOf(tt.want)) 236 }) 237 } 238 } 239 240 func TestAggregate(t *testing.T) { 241 ready1 := TrueCondition(clusterv1.ReadyCondition) 242 ready2 := FalseCondition(clusterv1.ReadyCondition, "reason falseInfo1", clusterv1.ConditionSeverityInfo, "message falseInfo1") 243 bar := FalseCondition("bar", "reason falseError1", clusterv1.ConditionSeverityError, "message falseError1") // NB. bar has higher priority than other conditions 244 245 tests := []struct { 246 name string 247 from []Getter 248 t clusterv1.ConditionType 249 want *clusterv1.Condition 250 }{ 251 { 252 name: "Returns nil when there are no conditions to aggregate", 253 from: []Getter{}, 254 want: nil, 255 }, 256 { 257 name: "Returns foo condition with the aggregation of object's ready conditions", 258 from: []Getter{ 259 getterWithConditions(ready1), 260 getterWithConditions(ready1), 261 getterWithConditions(ready2, bar), 262 getterWithConditions(), 263 getterWithConditions(bar), 264 }, 265 t: "foo", 266 want: FalseCondition("foo", "reason falseInfo1", clusterv1.ConditionSeverityInfo, "2 of 5 completed"), 267 }, 268 } 269 270 for _, tt := range tests { 271 t.Run(tt.name, func(t *testing.T) { 272 g := NewWithT(t) 273 274 got := aggregate(tt.from, tt.t) 275 if tt.want == nil { 276 g.Expect(got).To(BeNil()) 277 return 278 } 279 g.Expect(got).To(HaveSameStateOf(tt.want)) 280 }) 281 } 282 } 283 284 func getterWithConditions(conditions ...*clusterv1.Condition) Getter { 285 obj := &clusterv1.Cluster{} 286 obj.SetConditions(conditionList(conditions...)) 287 return obj 288 } 289 290 func nilGetter() Getter { 291 var obj *clusterv1.Cluster 292 return obj 293 } 294 295 func conditionList(conditions ...*clusterv1.Condition) clusterv1.Conditions { 296 cs := clusterv1.Conditions{} 297 for _, x := range conditions { 298 if x != nil { 299 cs = append(cs, *x) 300 } 301 } 302 return cs 303 }