...

Source file src/k8s.io/kubernetes/pkg/controller/job/success_policy_test.go

Documentation: k8s.io/kubernetes/pkg/controller/job

     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  }
   371  

View as plain text