volcano.sh/volcano@v1.9.0/pkg/controllers/garbagecollector/garbagecollector_test.go (about) 1 /* 2 Copyright 2019 The Volcano 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 garbagecollector 18 19 import ( 20 "fmt" 21 "testing" 22 "time" 23 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 26 "volcano.sh/apis/pkg/apis/batch/v1alpha1" 27 volcanoclient "volcano.sh/apis/pkg/client/clientset/versioned/fake" 28 "volcano.sh/volcano/pkg/controllers/framework" 29 ) 30 31 func TestGarbageCollector_ProcessJob(t *testing.T) { 32 33 } 34 35 func TestGarbageCollector_ProcessTTL(t *testing.T) { 36 namespace := "test" 37 var ttlSecond int32 = 3 38 var ttlSecondZero int32 39 testcases := []struct { 40 Name string 41 Job *v1alpha1.Job 42 ExpectedVal bool 43 ExpectedErr error 44 }{ 45 { 46 Name: "False Case", 47 Job: &v1alpha1.Job{ 48 ObjectMeta: metav1.ObjectMeta{ 49 Name: "job1", 50 Namespace: namespace, 51 }, 52 Spec: v1alpha1.JobSpec{ 53 TTLSecondsAfterFinished: &ttlSecond, 54 }, 55 Status: v1alpha1.JobStatus{ 56 State: v1alpha1.JobState{ 57 LastTransitionTime: metav1.NewTime(time.Now()), 58 Phase: v1alpha1.Completed, 59 }, 60 }, 61 }, 62 ExpectedVal: false, 63 ExpectedErr: nil, 64 }, 65 { 66 Name: "True Case", 67 Job: &v1alpha1.Job{ 68 ObjectMeta: metav1.ObjectMeta{ 69 Name: "job1", 70 Namespace: namespace, 71 }, 72 Spec: v1alpha1.JobSpec{ 73 TTLSecondsAfterFinished: &ttlSecondZero, 74 }, 75 Status: v1alpha1.JobStatus{ 76 State: v1alpha1.JobState{ 77 LastTransitionTime: metav1.NewTime(time.Now()), 78 Phase: v1alpha1.Completed, 79 }, 80 }, 81 }, 82 ExpectedVal: true, 83 ExpectedErr: nil, 84 }, 85 } 86 for i, testcase := range testcases { 87 gc := &gccontroller{} 88 gc.Initialize(&framework.ControllerOption{ 89 VolcanoClient: volcanoclient.NewSimpleClientset(), 90 }) 91 92 expired, err := gc.processTTL(testcase.Job) 93 if err != nil { 94 t.Error("Did not expect error") 95 } 96 if expired != testcase.ExpectedVal { 97 t.Errorf("Expected Return Value to be %t, but got %t in case %d", testcase.ExpectedVal, expired, i) 98 } 99 } 100 } 101 102 func TestGarbageCollector_NeedsCleanup(t *testing.T) { 103 namespace := "test" 104 105 var ttlSecond int32 = 3 106 107 testcases := []struct { 108 Name string 109 Job *v1alpha1.Job 110 ExpectedVal bool 111 }{ 112 { 113 Name: "Success Case", 114 Job: &v1alpha1.Job{ 115 ObjectMeta: metav1.ObjectMeta{ 116 Name: "job1", 117 Namespace: namespace, 118 }, 119 Spec: v1alpha1.JobSpec{ 120 TTLSecondsAfterFinished: &ttlSecond, 121 }, 122 Status: v1alpha1.JobStatus{ 123 State: v1alpha1.JobState{ 124 Phase: v1alpha1.Completed, 125 }, 126 }, 127 }, 128 ExpectedVal: true, 129 }, 130 { 131 Name: "Failure Case", 132 Job: &v1alpha1.Job{ 133 ObjectMeta: metav1.ObjectMeta{ 134 Name: "job1", 135 Namespace: namespace, 136 }, 137 Spec: v1alpha1.JobSpec{ 138 TTLSecondsAfterFinished: &ttlSecond, 139 }, 140 Status: v1alpha1.JobStatus{ 141 State: v1alpha1.JobState{ 142 Phase: v1alpha1.Running, 143 }, 144 }, 145 }, 146 ExpectedVal: false, 147 }, 148 } 149 150 for i, testcase := range testcases { 151 finished := needsCleanup(testcase.Job) 152 if finished != testcase.ExpectedVal { 153 t.Errorf("Expected value to be %t, but got: %t in case %d", testcase.ExpectedVal, finished, i) 154 } 155 } 156 } 157 158 func TestGarbageCollector_IsJobFinished(t *testing.T) { 159 namespace := "test" 160 161 testcases := []struct { 162 Name string 163 Job *v1alpha1.Job 164 ExpectedVal bool 165 }{ 166 { 167 Name: "True Case", 168 Job: &v1alpha1.Job{ 169 ObjectMeta: metav1.ObjectMeta{ 170 Name: "job1", 171 Namespace: namespace, 172 }, 173 Status: v1alpha1.JobStatus{ 174 State: v1alpha1.JobState{ 175 Phase: v1alpha1.Completed, 176 }, 177 }, 178 }, 179 ExpectedVal: true, 180 }, 181 { 182 Name: "False Case", 183 Job: &v1alpha1.Job{ 184 ObjectMeta: metav1.ObjectMeta{ 185 Name: "job1", 186 Namespace: namespace, 187 }, 188 Status: v1alpha1.JobStatus{ 189 State: v1alpha1.JobState{ 190 Phase: v1alpha1.Running, 191 }, 192 }, 193 }, 194 ExpectedVal: false, 195 }, 196 } 197 198 for i, testcase := range testcases { 199 finished := isJobFinished(testcase.Job) 200 if finished != testcase.ExpectedVal { 201 t.Errorf("Expected value to be %t, but got: %t in case %d", testcase.ExpectedVal, finished, i) 202 } 203 } 204 } 205 206 func TestGarbageCollector_GetFinishAndExpireTime(t *testing.T) { 207 namespace := "test" 208 209 var ttlSecond int32 = 3 210 var ttlSecondFail int32 = 2 211 212 testTime := time.Date(1, 1, 1, 1, 1, 1, 0, time.UTC) 213 214 testcases := []struct { 215 Name string 216 Job *v1alpha1.Job 217 ExpectedErr error 218 }{ 219 { 220 Name: "Success case", 221 Job: &v1alpha1.Job{ 222 ObjectMeta: metav1.ObjectMeta{ 223 Name: "job1", 224 Namespace: namespace, 225 }, 226 Spec: v1alpha1.JobSpec{ 227 TTLSecondsAfterFinished: &ttlSecond, 228 }, 229 Status: v1alpha1.JobStatus{ 230 State: v1alpha1.JobState{ 231 Phase: v1alpha1.Completed, 232 LastTransitionTime: metav1.NewTime(testTime), 233 }, 234 }, 235 }, 236 ExpectedErr: nil, 237 }, 238 { 239 Name: "Failure case", 240 Job: &v1alpha1.Job{ 241 ObjectMeta: metav1.ObjectMeta{ 242 Name: "job1", 243 Namespace: namespace, 244 }, 245 Spec: v1alpha1.JobSpec{ 246 TTLSecondsAfterFinished: &ttlSecondFail, 247 }, 248 Status: v1alpha1.JobStatus{ 249 State: v1alpha1.JobState{ 250 Phase: v1alpha1.Completed, 251 LastTransitionTime: metav1.NewTime(testTime), 252 }, 253 }, 254 }, 255 ExpectedErr: nil, 256 }, 257 } 258 259 for i, testcase := range testcases { 260 finishTime, expireTime, err := getFinishAndExpireTime(testcase.Job) 261 if err != nil && err.Error() != testcase.ExpectedErr.Error() { 262 t.Errorf("Expected Error to be: %s but got: %s in case %d", testcase.ExpectedErr, err, i) 263 } 264 265 if finishTime != nil && metav1.NewTime(*finishTime) != testcase.Job.Status.State.LastTransitionTime { 266 t.Errorf("Expected value to be: %v, but got: %v in case %d", testcase.Job.Status.State.LastTransitionTime, metav1.NewTime(*finishTime), i) 267 } 268 269 if expireTime != nil && metav1.NewTime(*expireTime) != metav1.NewTime(testcase.Job.Status.State.LastTransitionTime.Add(time.Duration(*testcase.Job.Spec.TTLSecondsAfterFinished)*time.Second)) { 270 t.Errorf("Expected value to be: %v, but got: %v in case %d", testcase.Job.Status.State.LastTransitionTime.Add(time.Duration(*testcase.Job.Spec.TTLSecondsAfterFinished)*time.Second), metav1.NewTime(*expireTime), i) 271 } 272 } 273 } 274 275 func TestGarbageCollector_TimeLeft(t *testing.T) { 276 namespace := "test" 277 278 var ttlSecond int32 = 3 279 280 testTime := time.Date(1, 1, 1, 1, 1, 1, 0, time.UTC) 281 282 testcases := []struct { 283 Name string 284 Job *v1alpha1.Job 285 Time *time.Time 286 ExpectedVal time.Duration 287 ExpectedErr error 288 }{ 289 { 290 Name: "Success Case", 291 Job: &v1alpha1.Job{ 292 ObjectMeta: metav1.ObjectMeta{ 293 Name: "job1", 294 Namespace: namespace, 295 }, 296 Spec: v1alpha1.JobSpec{ 297 TTLSecondsAfterFinished: &ttlSecond, 298 }, 299 Status: v1alpha1.JobStatus{ 300 State: v1alpha1.JobState{ 301 Phase: v1alpha1.Completed, 302 LastTransitionTime: metav1.NewTime(testTime), 303 }, 304 }, 305 }, 306 Time: &testTime, 307 ExpectedVal: time.Duration(3), 308 ExpectedErr: nil, 309 }, 310 { 311 Name: "Failure Case", 312 Job: &v1alpha1.Job{ 313 ObjectMeta: metav1.ObjectMeta{ 314 Name: "job1", 315 Namespace: namespace, 316 }, 317 Spec: v1alpha1.JobSpec{ 318 TTLSecondsAfterFinished: &ttlSecond, 319 }, 320 Status: v1alpha1.JobStatus{ 321 State: v1alpha1.JobState{ 322 LastTransitionTime: metav1.NewTime(testTime), 323 }, 324 }, 325 }, 326 Time: &testTime, 327 ExpectedVal: time.Duration(3), 328 ExpectedErr: fmt.Errorf("job %s/%s should not be cleaned up", "test", "job1"), 329 }, 330 } 331 332 for i, testcase := range testcases { 333 timeDuration, err := timeLeft(testcase.Job, testcase.Time) 334 if err != nil && err.Error() != testcase.ExpectedErr.Error() { 335 t.Errorf("Expected Error to be: %s but got: %s in case %d", testcase.ExpectedErr, err, i) 336 } 337 338 if timeDuration != nil && timeDuration.Seconds() != float64(testcase.ExpectedVal*time.Second)/1e9 { 339 t.Errorf("Expected Value to be: %v but got: %f in case %d", testcase.ExpectedVal, timeDuration.Seconds(), i) 340 } 341 } 342 } 343 344 func TestGarbageCollector_JobFinishTime(t *testing.T) { 345 namespace := "test" 346 347 testcases := []struct { 348 Name string 349 Job *v1alpha1.Job 350 ExpectedVal error 351 }{ 352 { 353 Name: "Success Case", 354 Job: &v1alpha1.Job{ 355 ObjectMeta: metav1.ObjectMeta{ 356 Name: "job1", 357 Namespace: namespace, 358 }, 359 Status: v1alpha1.JobStatus{ 360 State: v1alpha1.JobState{ 361 LastTransitionTime: metav1.NewTime(time.Now()), 362 }, 363 }, 364 }, 365 ExpectedVal: nil, 366 }, 367 { 368 Name: "Failure Case", 369 Job: &v1alpha1.Job{ 370 ObjectMeta: metav1.ObjectMeta{ 371 Name: "job1", 372 Namespace: namespace, 373 }, 374 }, 375 ExpectedVal: fmt.Errorf("unable to find the time when the Job %s/%s finished", "test", "job1"), 376 }, 377 } 378 379 for i, testcase := range testcases { 380 _, err := jobFinishTime(testcase.Job) 381 if err != nil && err.Error() != testcase.ExpectedVal.Error() { 382 t.Errorf("Expected Error to be: %s but got: %s in case %d", testcase.ExpectedVal, err, i) 383 } 384 } 385 }