k8s.io/kubernetes@v1.29.3/pkg/scheduler/framework/interface_test.go (about) 1 /* 2 Copyright 2019 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 framework 18 19 import ( 20 "errors" 21 "fmt" 22 "testing" 23 24 "github.com/google/go-cmp/cmp" 25 "k8s.io/apimachinery/pkg/util/sets" 26 ) 27 28 var errorStatus = NewStatus(Error, "internal error") 29 var statusWithErr = AsStatus(errors.New("internal error")) 30 31 func TestStatus(t *testing.T) { 32 tests := []struct { 33 name string 34 status *Status 35 expectedCode Code 36 expectedMessage string 37 expectedIsSuccess bool 38 expectedIsWait bool 39 expectedIsSkip bool 40 expectedAsError error 41 }{ 42 { 43 name: "success status", 44 status: NewStatus(Success, ""), 45 expectedCode: Success, 46 expectedMessage: "", 47 expectedIsSuccess: true, 48 expectedIsWait: false, 49 expectedIsSkip: false, 50 expectedAsError: nil, 51 }, 52 { 53 name: "wait status", 54 status: NewStatus(Wait, ""), 55 expectedCode: Wait, 56 expectedMessage: "", 57 expectedIsSuccess: false, 58 expectedIsWait: true, 59 expectedIsSkip: false, 60 expectedAsError: nil, 61 }, 62 { 63 name: "error status", 64 status: NewStatus(Error, "unknown error"), 65 expectedCode: Error, 66 expectedMessage: "unknown error", 67 expectedIsSuccess: false, 68 expectedIsWait: false, 69 expectedIsSkip: false, 70 expectedAsError: errors.New("unknown error"), 71 }, 72 { 73 name: "skip status", 74 status: NewStatus(Skip, ""), 75 expectedCode: Skip, 76 expectedMessage: "", 77 expectedIsSuccess: false, 78 expectedIsWait: false, 79 expectedIsSkip: true, 80 expectedAsError: nil, 81 }, 82 { 83 name: "nil status", 84 status: nil, 85 expectedCode: Success, 86 expectedMessage: "", 87 expectedIsSuccess: true, 88 expectedIsSkip: false, 89 expectedAsError: nil, 90 }, 91 } 92 93 for _, test := range tests { 94 t.Run(test.name, func(t *testing.T) { 95 if test.status.Code() != test.expectedCode { 96 t.Errorf("expect status.Code() returns %v, but %v", test.expectedCode, test.status.Code()) 97 } 98 99 if test.status.Message() != test.expectedMessage { 100 t.Errorf("expect status.Message() returns %v, but %v", test.expectedMessage, test.status.Message()) 101 } 102 103 if test.status.IsSuccess() != test.expectedIsSuccess { 104 t.Errorf("expect status.IsSuccess() returns %v, but %v", test.expectedIsSuccess, test.status.IsSuccess()) 105 } 106 107 if test.status.IsWait() != test.expectedIsWait { 108 t.Errorf("status.IsWait() returns %v, but want %v", test.status.IsWait(), test.expectedIsWait) 109 } 110 111 if test.status.IsSkip() != test.expectedIsSkip { 112 t.Errorf("status.IsSkip() returns %v, but want %v", test.status.IsSkip(), test.expectedIsSkip) 113 } 114 115 if test.status.AsError() == test.expectedAsError { 116 return 117 } 118 119 if test.status.AsError().Error() != test.expectedAsError.Error() { 120 t.Errorf("expect status.AsError() returns %v, but %v", test.expectedAsError, test.status.AsError()) 121 } 122 }) 123 } 124 } 125 126 func TestPreFilterResultMerge(t *testing.T) { 127 tests := map[string]struct { 128 receiver *PreFilterResult 129 in *PreFilterResult 130 want *PreFilterResult 131 }{ 132 "all nil": {}, 133 "nil receiver empty input": { 134 in: &PreFilterResult{NodeNames: sets.New[string]()}, 135 want: &PreFilterResult{NodeNames: sets.New[string]()}, 136 }, 137 "empty receiver nil input": { 138 receiver: &PreFilterResult{NodeNames: sets.New[string]()}, 139 want: &PreFilterResult{NodeNames: sets.New[string]()}, 140 }, 141 "empty receiver empty input": { 142 receiver: &PreFilterResult{NodeNames: sets.New[string]()}, 143 in: &PreFilterResult{NodeNames: sets.New[string]()}, 144 want: &PreFilterResult{NodeNames: sets.New[string]()}, 145 }, 146 "nil receiver populated input": { 147 in: &PreFilterResult{NodeNames: sets.New("node1")}, 148 want: &PreFilterResult{NodeNames: sets.New("node1")}, 149 }, 150 "empty receiver populated input": { 151 receiver: &PreFilterResult{NodeNames: sets.New[string]()}, 152 in: &PreFilterResult{NodeNames: sets.New("node1")}, 153 want: &PreFilterResult{NodeNames: sets.New[string]()}, 154 }, 155 156 "populated receiver nil input": { 157 receiver: &PreFilterResult{NodeNames: sets.New("node1")}, 158 want: &PreFilterResult{NodeNames: sets.New("node1")}, 159 }, 160 "populated receiver empty input": { 161 receiver: &PreFilterResult{NodeNames: sets.New("node1")}, 162 in: &PreFilterResult{NodeNames: sets.New[string]()}, 163 want: &PreFilterResult{NodeNames: sets.New[string]()}, 164 }, 165 "populated receiver and input": { 166 receiver: &PreFilterResult{NodeNames: sets.New("node1", "node2")}, 167 in: &PreFilterResult{NodeNames: sets.New("node2", "node3")}, 168 want: &PreFilterResult{NodeNames: sets.New("node2")}, 169 }, 170 } 171 for name, test := range tests { 172 t.Run(name, func(t *testing.T) { 173 got := test.receiver.Merge(test.in) 174 if diff := cmp.Diff(test.want, got); diff != "" { 175 t.Errorf("unexpected diff (-want, +got):\n%s", diff) 176 } 177 }) 178 } 179 } 180 181 func TestIsStatusEqual(t *testing.T) { 182 tests := []struct { 183 name string 184 x, y *Status 185 want bool 186 }{ 187 { 188 name: "two nil should be equal", 189 x: nil, 190 y: nil, 191 want: true, 192 }, 193 { 194 name: "nil should be equal to success status", 195 x: nil, 196 y: NewStatus(Success), 197 want: true, 198 }, 199 { 200 name: "nil should not be equal with status except success", 201 x: nil, 202 y: NewStatus(Error, "internal error"), 203 want: false, 204 }, 205 { 206 name: "one status should be equal to itself", 207 x: errorStatus, 208 y: errorStatus, 209 want: true, 210 }, 211 { 212 name: "same type statuses without reasons should be equal", 213 x: NewStatus(Success), 214 y: NewStatus(Success), 215 want: true, 216 }, 217 { 218 name: "statuses with same message should be equal", 219 x: NewStatus(Unschedulable, "unschedulable"), 220 y: NewStatus(Unschedulable, "unschedulable"), 221 want: true, 222 }, 223 { 224 name: "error statuses with same message should be equal", 225 x: NewStatus(Error, "error"), 226 y: NewStatus(Error, "error"), 227 want: true, 228 }, 229 { 230 name: "statuses with different reasons should not be equal", 231 x: NewStatus(Unschedulable, "unschedulable"), 232 y: NewStatus(Unschedulable, "unschedulable", "injected filter status"), 233 want: false, 234 }, 235 { 236 name: "statuses with different codes should not be equal", 237 x: NewStatus(Error, "internal error"), 238 y: NewStatus(Unschedulable, "internal error"), 239 want: false, 240 }, 241 { 242 name: "wrap error status should be equal with original one", 243 x: statusWithErr, 244 y: AsStatus(fmt.Errorf("error: %w", statusWithErr.AsError())), 245 want: true, 246 }, 247 { 248 name: "statues with different errors that have the same message shouldn't be equal", 249 x: AsStatus(errors.New("error")), 250 y: AsStatus(errors.New("error")), 251 want: false, 252 }, 253 } 254 for _, tt := range tests { 255 t.Run(tt.name, func(t *testing.T) { 256 if got := tt.x.Equal(tt.y); got != tt.want { 257 t.Errorf("cmp.Equal() = %v, want %v", got, tt.want) 258 } 259 }) 260 } 261 }