k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/controller/job/success_policy_test.go (about) 1 /* 2 Copyright 2024 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 job 18 19 import ( 20 "testing" 21 22 "github.com/google/go-cmp/cmp" 23 batch "k8s.io/api/batch/v1" 24 "k8s.io/klog/v2/ktesting" 25 "k8s.io/utils/ptr" 26 ) 27 28 func TestMatchSuccessPolicy(t *testing.T) { 29 testCases := map[string]struct { 30 successPolicy *batch.SuccessPolicy 31 completions int32 32 succeededIndexes orderedIntervals 33 wantMessage string 34 wantMetSuccessPolicy bool 35 }{ 36 "successPolicy is null": { 37 completions: 10, 38 succeededIndexes: orderedIntervals{{0, 0}}, 39 }, 40 "any rules are nothing": { 41 completions: 10, 42 succeededIndexes: orderedIntervals{{0, 0}}, 43 successPolicy: &batch.SuccessPolicy{Rules: []batch.SuccessPolicyRule{}}, 44 }, 45 "rules.succeededIndexes is invalid format": { 46 completions: 10, 47 succeededIndexes: orderedIntervals{{0, 0}}, 48 successPolicy: &batch.SuccessPolicy{ 49 Rules: []batch.SuccessPolicyRule{{ 50 SucceededIndexes: ptr.To("invalid-form"), 51 }}, 52 }, 53 }, 54 "rules.succeededIndexes is specified; succeededIndexes matched rules": { 55 completions: 10, 56 succeededIndexes: orderedIntervals{{0, 2}, {4, 7}}, 57 successPolicy: &batch.SuccessPolicy{ 58 Rules: []batch.SuccessPolicyRule{{ 59 SucceededIndexes: ptr.To("0-2"), 60 }}, 61 }, 62 wantMessage: "Matched rules at index 0", 63 wantMetSuccessPolicy: true, 64 }, 65 "rules.succeededIndexes is specified; succeededIndexes didn't match rules": { 66 completions: 10, 67 succeededIndexes: orderedIntervals{{0, 2}}, 68 successPolicy: &batch.SuccessPolicy{ 69 Rules: []batch.SuccessPolicyRule{{ 70 SucceededIndexes: ptr.To("3"), 71 }}, 72 }, 73 }, 74 "rules.succeededCount is specified; succeededIndexes matched rules": { 75 completions: 10, 76 succeededIndexes: orderedIntervals{{0, 2}}, 77 successPolicy: &batch.SuccessPolicy{ 78 Rules: []batch.SuccessPolicyRule{{ 79 SucceededCount: ptr.To[int32](2), 80 }}, 81 }, 82 wantMessage: "Matched rules at index 0", 83 wantMetSuccessPolicy: true, 84 }, 85 "rules.succeededCount is specified; succeededIndexes didn't match rules": { 86 completions: 10, 87 succeededIndexes: orderedIntervals{{0, 2}}, 88 successPolicy: &batch.SuccessPolicy{ 89 Rules: []batch.SuccessPolicyRule{{ 90 SucceededCount: ptr.To[int32](4), 91 }}, 92 }, 93 }, 94 "multiple rules; rules.succeededIndexes is specified; succeededIndexes met one of rules": { 95 completions: 10, 96 succeededIndexes: orderedIntervals{{0, 2}, {4, 7}}, 97 successPolicy: &batch.SuccessPolicy{ 98 Rules: []batch.SuccessPolicyRule{ 99 { 100 SucceededIndexes: ptr.To("9"), 101 }, 102 { 103 SucceededIndexes: ptr.To("4,6"), 104 }, 105 }, 106 }, 107 wantMessage: "Matched rules at index 1", 108 wantMetSuccessPolicy: true, 109 }, 110 "multiple rules; rules.succeededIndexes is specified; succeededIndexes met all rules": { 111 completions: 10, 112 succeededIndexes: orderedIntervals{{0, 2}, {4, 7}}, 113 successPolicy: &batch.SuccessPolicy{ 114 Rules: []batch.SuccessPolicyRule{ 115 { 116 SucceededIndexes: ptr.To("0,1"), 117 }, 118 { 119 SucceededIndexes: ptr.To("5"), 120 }, 121 }, 122 }, 123 wantMessage: "Matched rules at index 0", 124 wantMetSuccessPolicy: true, 125 }, 126 "rules.succeededIndexes and rules.succeededCount are specified; succeededIndexes met all rules": { 127 completions: 10, 128 succeededIndexes: orderedIntervals{{0, 2}, {4, 7}}, 129 successPolicy: &batch.SuccessPolicy{ 130 Rules: []batch.SuccessPolicyRule{{ 131 SucceededIndexes: ptr.To("3-6"), 132 SucceededCount: ptr.To[int32](2), 133 }}, 134 }, 135 wantMetSuccessPolicy: true, 136 wantMessage: "Matched rules at index 0", 137 }, 138 "rules.succeededIndexes and rules.succeededCount are specified; succeededIndexes didn't match rules": { 139 completions: 10, 140 succeededIndexes: orderedIntervals{{0, 2}, {6, 7}}, 141 successPolicy: &batch.SuccessPolicy{ 142 Rules: []batch.SuccessPolicyRule{{ 143 SucceededIndexes: ptr.To("3-6"), 144 SucceededCount: ptr.To[int32](2), 145 }}, 146 }, 147 }, 148 "rules.succeededIndexes is specified; succeededIndexes are nothing": { 149 completions: 10, 150 succeededIndexes: orderedIntervals{}, 151 successPolicy: &batch.SuccessPolicy{ 152 Rules: []batch.SuccessPolicyRule{{ 153 SucceededCount: ptr.To[int32](4), 154 }}, 155 }, 156 }, 157 158 "rules.succeededIndexes is specified; succeededIndexes matched rules; rules is proper subset of succeededIndexes": { 159 completions: 10, 160 succeededIndexes: orderedIntervals{{1, 5}, {6, 9}}, 161 successPolicy: &batch.SuccessPolicy{ 162 Rules: []batch.SuccessPolicyRule{{ 163 SucceededIndexes: ptr.To("2-4,6-8"), 164 }}, 165 }, 166 wantMetSuccessPolicy: true, 167 wantMessage: "Matched rules at index 0", 168 }, 169 "rules.succeededIndexes is specified; succeededIndexes matched rules; rules equals succeededIndexes": { 170 completions: 10, 171 succeededIndexes: orderedIntervals{{2, 4}, {6, 9}}, 172 successPolicy: &batch.SuccessPolicy{ 173 Rules: []batch.SuccessPolicyRule{{ 174 SucceededIndexes: ptr.To("2-4,6-9"), 175 }}, 176 }, 177 wantMetSuccessPolicy: true, 178 wantMessage: "Matched rules at index 0", 179 }, 180 "rules.succeededIndexes is specified; succeededIndexes matched rules; rules is subset of succeededIndexes": { 181 completions: 10, 182 succeededIndexes: orderedIntervals{{2, 5}, {7, 15}}, 183 successPolicy: &batch.SuccessPolicy{ 184 Rules: []batch.SuccessPolicyRule{{ 185 SucceededIndexes: ptr.To("2-4,8-12"), 186 }}, 187 }, 188 wantMetSuccessPolicy: true, 189 wantMessage: "Matched rules at index 0", 190 }, 191 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; rules is an empty set": { 192 completions: 10, 193 succeededIndexes: orderedIntervals{{1, 3}}, 194 successPolicy: &batch.SuccessPolicy{ 195 Rules: []batch.SuccessPolicyRule{{ 196 SucceededIndexes: ptr.To(""), 197 }}, 198 }, 199 }, 200 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; succeededIndexes is an empty set": { 201 completions: 10, 202 succeededIndexes: orderedIntervals{}, 203 successPolicy: &batch.SuccessPolicy{ 204 Rules: []batch.SuccessPolicyRule{{ 205 SucceededIndexes: ptr.To(""), 206 }}, 207 }, 208 }, 209 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; rules and succeededIndexes are empty set": { 210 completions: 10, 211 succeededIndexes: orderedIntervals{}, 212 successPolicy: &batch.SuccessPolicy{ 213 Rules: []batch.SuccessPolicyRule{{ 214 SucceededIndexes: ptr.To(""), 215 }}, 216 }, 217 }, 218 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; all elements of rules.succeededIndexes aren't included in succeededIndexes": { 219 completions: 10, 220 succeededIndexes: orderedIntervals{{1, 3}, {5, 7}}, 221 successPolicy: &batch.SuccessPolicy{ 222 Rules: []batch.SuccessPolicyRule{{ 223 SucceededIndexes: ptr.To("10-12,14-16"), 224 }}, 225 }, 226 }, 227 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; rules overlaps succeededIndexes at first": { 228 completions: 10, 229 succeededIndexes: orderedIntervals{{2, 4}, {6, 8}}, 230 successPolicy: &batch.SuccessPolicy{ 231 Rules: []batch.SuccessPolicyRule{{ 232 SucceededIndexes: ptr.To("1-3,5-7"), 233 }}, 234 }, 235 }, 236 "rules.succeededIndexes and rules.succeededCount are specified; succeededIndexes matched rules; rules overlaps succeededIndexes at first": { 237 completions: 10, 238 succeededIndexes: orderedIntervals{{2, 4}, {6, 8}}, 239 successPolicy: &batch.SuccessPolicy{ 240 Rules: []batch.SuccessPolicyRule{{ 241 SucceededIndexes: ptr.To("1-3,5-7"), 242 SucceededCount: ptr.To[int32](4), 243 }}, 244 }, 245 wantMetSuccessPolicy: true, 246 wantMessage: "Matched rules at index 0", 247 }, 248 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; rules overlaps succeededIndexes at last": { 249 completions: 10, 250 succeededIndexes: orderedIntervals{{1, 3}, {5, 7}}, 251 successPolicy: &batch.SuccessPolicy{ 252 Rules: []batch.SuccessPolicyRule{{ 253 SucceededIndexes: ptr.To("2-4,6-9"), 254 }}, 255 }, 256 }, 257 "rules.succeededIndexes and rules.succeededCount are specified; succeededIndexes matched rules; rules overlaps succeededIndexes at last": { 258 completions: 10, 259 succeededIndexes: orderedIntervals{{1, 3}, {5, 7}}, 260 successPolicy: &batch.SuccessPolicy{ 261 Rules: []batch.SuccessPolicyRule{{ 262 SucceededIndexes: ptr.To("2-4,6-9"), 263 SucceededCount: ptr.To[int32](4), 264 }}, 265 }, 266 wantMetSuccessPolicy: true, 267 wantMessage: "Matched rules at index 0", 268 }, 269 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; rules completely overlaps succeededIndexes": { 270 completions: 10, 271 succeededIndexes: orderedIntervals{{1, 3}, {7, 8}}, 272 successPolicy: &batch.SuccessPolicy{ 273 Rules: []batch.SuccessPolicyRule{{ 274 SucceededIndexes: ptr.To("0-4,6-9"), 275 }}, 276 }, 277 }, 278 "rules.succeededIndexes and rules.succeededCount are specified; succeededIndexes matched rules; rules completely overlaps succeededIndexes": { 279 completions: 10, 280 succeededIndexes: orderedIntervals{{1, 3}, {7, 8}}, 281 successPolicy: &batch.SuccessPolicy{ 282 Rules: []batch.SuccessPolicyRule{{ 283 SucceededIndexes: ptr.To("0-4,6-9"), 284 SucceededCount: ptr.To[int32](5), 285 }}, 286 }, 287 wantMetSuccessPolicy: true, 288 wantMessage: "Matched rules at index 0", 289 }, 290 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; rules overlaps multiple succeededIndexes at last": { 291 completions: 10, 292 succeededIndexes: orderedIntervals{{1, 3}, {5, 9}}, 293 successPolicy: &batch.SuccessPolicy{ 294 Rules: []batch.SuccessPolicyRule{{ 295 SucceededIndexes: ptr.To("0-6,8-9"), 296 }}, 297 }, 298 }, 299 "rules.succeededIndexes and rules.succeededCount are specified; succeededIndexes matched rules; rules overlaps multiple succeededIndexes at last": { 300 completions: 10, 301 succeededIndexes: orderedIntervals{{1, 3}, {5, 9}}, 302 successPolicy: &batch.SuccessPolicy{ 303 Rules: []batch.SuccessPolicyRule{{ 304 SucceededIndexes: ptr.To("0-6,8-9"), 305 SucceededCount: ptr.To[int32](7), 306 }}, 307 }, 308 wantMetSuccessPolicy: true, 309 wantMessage: "Matched rules at index 0", 310 }, 311 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; rules overlaps succeededIndexes at first, and rules equals succeededIndexes at last": { 312 completions: 10, 313 succeededIndexes: orderedIntervals{{1, 5}, {7, 10}}, 314 successPolicy: &batch.SuccessPolicy{ 315 Rules: []batch.SuccessPolicyRule{{ 316 SucceededIndexes: ptr.To("0-5,7-9"), 317 }}, 318 }, 319 }, 320 "rules.succeededIndexes and rules.succeededCount are specified; succeededIndexes matched rules; rules overlaps succeededIndexes at first, and rules equals succeededIndexes at last": { 321 completions: 10, 322 succeededIndexes: orderedIntervals{{1, 5}, {7, 10}}, 323 successPolicy: &batch.SuccessPolicy{ 324 Rules: []batch.SuccessPolicyRule{{ 325 SucceededIndexes: ptr.To("0-5,7-9"), 326 SucceededCount: ptr.To[int32](8), 327 }}, 328 }, 329 wantMetSuccessPolicy: true, 330 wantMessage: "Matched rules at index 0", 331 }, 332 "rules.succeededIndexes is specified; succeededIndexes didn't match rules; the first rules overlaps succeededIndexes at first": { 333 completions: 10, 334 succeededIndexes: orderedIntervals{{1, 10}}, 335 successPolicy: &batch.SuccessPolicy{ 336 Rules: []batch.SuccessPolicyRule{{ 337 SucceededIndexes: ptr.To("0-3,6-9"), 338 }}, 339 }, 340 }, 341 "rules.succeededIndexes and rules.succeededCount are specified; succeededIndexes matched rules; the first rules overlaps succeededIndexes at first": { 342 completions: 10, 343 succeededIndexes: orderedIntervals{{1, 10}}, 344 successPolicy: &batch.SuccessPolicy{ 345 Rules: []batch.SuccessPolicyRule{{ 346 SucceededIndexes: ptr.To("0-3,6-9"), 347 SucceededCount: ptr.To[int32](7), 348 }}, 349 }, 350 wantMetSuccessPolicy: true, 351 wantMessage: "Matched rules at index 0", 352 }, 353 } 354 for name, tc := range testCases { 355 t.Run(name, func(t *testing.T) { 356 logger := ktesting.NewLogger(t, 357 ktesting.NewConfig( 358 ktesting.BufferLogs(true), 359 ), 360 ) 361 gotMessage, gotMetSuccessPolicy := matchSuccessPolicy(logger, tc.successPolicy, tc.completions, tc.succeededIndexes) 362 if tc.wantMetSuccessPolicy != gotMetSuccessPolicy { 363 t.Errorf("Unexpected bool from matchSuccessPolicy\nwant:%v\ngot:%v\n", tc.wantMetSuccessPolicy, gotMetSuccessPolicy) 364 } 365 if diff := cmp.Diff(tc.wantMessage, gotMessage); diff != "" { 366 t.Errorf("Unexpected message from matchSuccessPolicy (-want,+got):\n%s", diff) 367 } 368 }) 369 } 370 }