volcano.sh/volcano@v1.9.0/pkg/controllers/jobflow/jobflow_controller_action_test.go (about)

     1  /*
     2  Copyright 2022 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 jobflow
    18  
    19  import (
    20  	"context"
    21  	"reflect"
    22  	"testing"
    23  	"time"
    24  
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/client-go/informers"
    27  	kubeclient "k8s.io/client-go/kubernetes/fake"
    28  	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    29  
    30  	"volcano.sh/apis/pkg/apis/batch/v1alpha1"
    31  	jobflowv1alpha1 "volcano.sh/apis/pkg/apis/flow/v1alpha1"
    32  	"volcano.sh/apis/pkg/apis/helpers"
    33  	volcanoclient "volcano.sh/apis/pkg/client/clientset/versioned/fake"
    34  	"volcano.sh/apis/pkg/client/clientset/versioned/scheme"
    35  	"volcano.sh/volcano/pkg/controllers/framework"
    36  )
    37  
    38  func newFakeController() *jobflowcontroller {
    39  	volcanoClientSet := volcanoclient.NewSimpleClientset()
    40  	kubeClientSet := kubeclient.NewSimpleClientset()
    41  
    42  	sharedInformers := informers.NewSharedInformerFactory(kubeClientSet, 0)
    43  
    44  	controller := &jobflowcontroller{}
    45  	opt := &framework.ControllerOption{
    46  		VolcanoClient:         volcanoClientSet,
    47  		KubeClient:            kubeClientSet,
    48  		SharedInformerFactory: sharedInformers,
    49  		WorkerNum:             3,
    50  	}
    51  
    52  	controller.Initialize(opt)
    53  
    54  	return controller
    55  }
    56  
    57  func TestSyncJobFlowFunc(t *testing.T) {
    58  	type args struct {
    59  		jobFlow         *jobflowv1alpha1.JobFlow
    60  		jobTemplateList []*jobflowv1alpha1.JobTemplate
    61  	}
    62  	type wantRes struct {
    63  		jobFlowStatus *jobflowv1alpha1.JobFlowStatus
    64  		err           error
    65  	}
    66  	tests := []struct {
    67  		name string
    68  		args args
    69  		want wantRes
    70  	}{
    71  		{
    72  			name: "SyncJobFlow success case",
    73  			args: args{
    74  				jobFlow: &jobflowv1alpha1.JobFlow{
    75  					ObjectMeta: metav1.ObjectMeta{
    76  						Name:      "jobflow",
    77  						Namespace: "default",
    78  					},
    79  					Spec: jobflowv1alpha1.JobFlowSpec{
    80  						Flows: []jobflowv1alpha1.Flow{
    81  							{
    82  								Name:      "jobtemplate",
    83  								DependsOn: nil,
    84  							},
    85  						},
    86  						JobRetainPolicy: jobflowv1alpha1.Retain,
    87  					},
    88  				},
    89  				jobTemplateList: []*jobflowv1alpha1.JobTemplate{
    90  					{
    91  						ObjectMeta: metav1.ObjectMeta{
    92  							Name:      "jobtemplate",
    93  							Namespace: "default",
    94  						},
    95  						Spec: v1alpha1.JobSpec{},
    96  					},
    97  				},
    98  			},
    99  			want: wantRes{
   100  				jobFlowStatus: &jobflowv1alpha1.JobFlowStatus{
   101  					PendingJobs:    make([]string, 0),
   102  					RunningJobs:    []string{getJobName("jobflow", "jobtemplate")},
   103  					FailedJobs:     make([]string, 0),
   104  					CompletedJobs:  make([]string, 0),
   105  					TerminatedJobs: make([]string, 0),
   106  					UnKnowJobs:     make([]string, 0),
   107  					JobStatusList: []jobflowv1alpha1.JobStatus{
   108  						{
   109  							Name:           getJobName("jobflow", "jobtemplate"),
   110  							State:          v1alpha1.Running,
   111  							StartTimestamp: metav1.Time{},
   112  							EndTimestamp:   metav1.Time{},
   113  							RestartCount:   0,
   114  							RunningHistories: []jobflowv1alpha1.JobRunningHistory{
   115  								{
   116  									StartTimestamp: metav1.Time{},
   117  									EndTimestamp:   metav1.Time{},
   118  									State:          v1alpha1.Running,
   119  								},
   120  							},
   121  						},
   122  					},
   123  					Conditions: map[string]jobflowv1alpha1.Condition{
   124  						getJobName("jobflow", "jobtemplate"): {
   125  							Phase:           v1alpha1.Running,
   126  							CreateTimestamp: metav1.Time{},
   127  							RunningDuration: nil,
   128  							TaskStatusCount: nil,
   129  						},
   130  					},
   131  					State: jobflowv1alpha1.State{
   132  						Phase: jobflowv1alpha1.Running,
   133  					},
   134  				},
   135  				err: nil,
   136  			},
   137  		},
   138  	}
   139  	for _, tt := range tests {
   140  		t.Run(tt.name, func(t *testing.T) {
   141  			fakeController := newFakeController()
   142  			for i := range tt.args.jobTemplateList {
   143  				if err := fakeController.jobTemplateInformer.Informer().GetIndexer().Add(tt.args.jobTemplateList[i]); err != nil {
   144  					t.Errorf("add jobTemplate to informerFake,error : %s", err.Error())
   145  				}
   146  				job := &v1alpha1.Job{
   147  					ObjectMeta: metav1.ObjectMeta{
   148  						Name:      getJobName(tt.args.jobFlow.Name, tt.args.jobTemplateList[i].Name),
   149  						Namespace: tt.args.jobFlow.Namespace,
   150  						Labels:    map[string]string{CreatedByJobTemplate: GetTemplateString(tt.args.jobFlow.Namespace, tt.args.jobTemplateList[i].Name)},
   151  					},
   152  					Spec: tt.args.jobTemplateList[i].Spec,
   153  					Status: v1alpha1.JobStatus{
   154  						State: v1alpha1.JobState{
   155  							Phase: v1alpha1.Running,
   156  						},
   157  					},
   158  				}
   159  				if err := controllerutil.SetControllerReference(tt.args.jobFlow, job, scheme.Scheme); err != nil {
   160  					t.Errorf("SetControllerReference error : %s", err.Error())
   161  				}
   162  				if err := fakeController.jobInformer.Informer().GetIndexer().Add(job); err != nil {
   163  					t.Errorf("add jobTemplate to informerFake,error : %s", err.Error())
   164  				}
   165  			}
   166  			if _, err := fakeController.vcClient.FlowV1alpha1().JobFlows(tt.args.jobFlow.Namespace).Create(context.Background(), tt.args.jobFlow, metav1.CreateOptions{}); err != nil {
   167  				t.Errorf("create jobflow error : %s", err.Error())
   168  			}
   169  
   170  			if got := fakeController.syncJobFlow(tt.args.jobFlow, func(status *jobflowv1alpha1.JobFlowStatus, allJobList int) {
   171  				if len(status.RunningJobs) > 0 || len(status.CompletedJobs) > 0 {
   172  					status.State.Phase = jobflowv1alpha1.Running
   173  				} else if len(status.FailedJobs) > 0 {
   174  					status.State.Phase = jobflowv1alpha1.Failed
   175  				} else {
   176  					status.State.Phase = jobflowv1alpha1.Pending
   177  				}
   178  			}); got != tt.want.err {
   179  				t.Error("Expected deleteAllJobsCreatedByJobFlow() return nil, but not nil")
   180  			}
   181  			for i := range tt.args.jobFlow.Status.JobStatusList {
   182  				for i2 := range tt.args.jobFlow.Status.JobStatusList[i].RunningHistories {
   183  					tt.args.jobFlow.Status.JobStatusList[i].RunningHistories[i2].StartTimestamp = metav1.Time{}
   184  				}
   185  			}
   186  			if !reflect.DeepEqual(&tt.args.jobFlow.Status, tt.want.jobFlowStatus) {
   187  				t.Error("not the expected result")
   188  			}
   189  		})
   190  	}
   191  }
   192  
   193  func TestGetRunningHistoriesFunc(t *testing.T) {
   194  	type args struct {
   195  		jobStatusList []jobflowv1alpha1.JobStatus
   196  		job           *v1alpha1.Job
   197  	}
   198  	startTime := time.Now()
   199  	endTime := startTime.Add(1 * time.Second)
   200  	tests := []struct {
   201  		name string
   202  		args args
   203  		want []jobflowv1alpha1.JobRunningHistory
   204  	}{
   205  		{
   206  			name: "GetRunningHistories success case",
   207  			args: args{
   208  				jobStatusList: []jobflowv1alpha1.JobStatus{
   209  					{
   210  						Name:           "vcJobA",
   211  						State:          v1alpha1.Completed,
   212  						StartTimestamp: metav1.Time{Time: startTime},
   213  						EndTimestamp:   metav1.Time{Time: endTime},
   214  						RestartCount:   0,
   215  						RunningHistories: []jobflowv1alpha1.JobRunningHistory{
   216  							{
   217  								StartTimestamp: metav1.Time{Time: startTime},
   218  								EndTimestamp:   metav1.Time{Time: endTime},
   219  								State:          v1alpha1.Completed,
   220  							},
   221  						},
   222  					},
   223  				},
   224  				job: &v1alpha1.Job{
   225  					TypeMeta:   metav1.TypeMeta{},
   226  					ObjectMeta: metav1.ObjectMeta{Name: "vcJobA"},
   227  					Spec:       v1alpha1.JobSpec{},
   228  					Status: v1alpha1.JobStatus{
   229  						State: v1alpha1.JobState{
   230  							Phase:              v1alpha1.Completed,
   231  							Reason:             "",
   232  							Message:            "",
   233  							LastTransitionTime: metav1.Time{},
   234  						},
   235  					},
   236  				},
   237  			},
   238  			want: []jobflowv1alpha1.JobRunningHistory{
   239  				{
   240  					StartTimestamp: metav1.Time{Time: startTime},
   241  					EndTimestamp:   metav1.Time{Time: endTime},
   242  					State:          v1alpha1.Completed,
   243  				},
   244  			},
   245  		},
   246  	}
   247  	for _, tt := range tests {
   248  		t.Run(tt.name, func(t *testing.T) {
   249  			if got := getRunningHistories(tt.args.jobStatusList, tt.args.job); !reflect.DeepEqual(got, tt.want) {
   250  				t.Errorf("getRunningHistories() = %v, want %v", got, tt.want)
   251  			}
   252  		})
   253  	}
   254  }
   255  
   256  func TestGetAllJobStatusFunc(t *testing.T) {
   257  	// TODO(wangyang0616): First make sure that ut can run, and then fix the failed ut later.
   258  	// See issue for details: https://github.com/volcano-sh/volcano/issues/2851
   259  	t.Skip("Test cases are not as expected, fixed later. see issue: #2851")
   260  	type args struct {
   261  		jobFlow    *jobflowv1alpha1.JobFlow
   262  		allJobList *v1alpha1.JobList
   263  	}
   264  	createJobATime := time.Now()
   265  	jobFlowName := "jobFlowA"
   266  	createJobBTime := createJobATime.Add(time.Second)
   267  	tests := []struct {
   268  		name    string
   269  		args    args
   270  		want    *jobflowv1alpha1.JobFlowStatus
   271  		wantErr bool
   272  	}{
   273  		{
   274  			name: "GetAllJobStatus success case",
   275  			args: args{
   276  				jobFlow: &jobflowv1alpha1.JobFlow{
   277  					TypeMeta: metav1.TypeMeta{},
   278  					ObjectMeta: metav1.ObjectMeta{
   279  						Name: jobFlowName,
   280  					},
   281  					Spec: jobflowv1alpha1.JobFlowSpec{
   282  						Flows: []jobflowv1alpha1.Flow{
   283  							{
   284  								Name:      "A",
   285  								DependsOn: nil,
   286  							},
   287  							{
   288  								Name: "B",
   289  								DependsOn: &jobflowv1alpha1.DependsOn{
   290  									Targets: []string{"A"},
   291  								},
   292  							},
   293  						},
   294  						JobRetainPolicy: "",
   295  					},
   296  					Status: jobflowv1alpha1.JobFlowStatus{},
   297  				},
   298  				allJobList: &v1alpha1.JobList{
   299  					Items: []v1alpha1.Job{
   300  						{
   301  							TypeMeta: metav1.TypeMeta{},
   302  							ObjectMeta: metav1.ObjectMeta{
   303  								Name:              "jobFlowA-A",
   304  								CreationTimestamp: metav1.Time{Time: createJobATime},
   305  								OwnerReferences: []metav1.OwnerReference{{
   306  									APIVersion: "volcano",
   307  									Kind:       JobFlow,
   308  									Name:       jobFlowName,
   309  								}},
   310  							},
   311  							Spec: v1alpha1.JobSpec{},
   312  							Status: v1alpha1.JobStatus{
   313  								State:           v1alpha1.JobState{Phase: v1alpha1.Completed},
   314  								RetryCount:      1,
   315  								RunningDuration: &metav1.Duration{Duration: time.Second},
   316  							},
   317  						},
   318  						{
   319  							TypeMeta: metav1.TypeMeta{},
   320  							ObjectMeta: metav1.ObjectMeta{
   321  								Name:              "jobFlowA-B",
   322  								CreationTimestamp: metav1.Time{Time: createJobBTime},
   323  								OwnerReferences: []metav1.OwnerReference{{
   324  									APIVersion: "volcano",
   325  									Kind:       JobFlow,
   326  									Name:       jobFlowName,
   327  								}},
   328  							},
   329  							Spec: v1alpha1.JobSpec{},
   330  							Status: v1alpha1.JobStatus{
   331  								State: v1alpha1.JobState{Phase: v1alpha1.Running},
   332  							},
   333  						},
   334  					},
   335  				},
   336  			},
   337  			want: &jobflowv1alpha1.JobFlowStatus{
   338  				PendingJobs:    []string{},
   339  				RunningJobs:    []string{"jobFlowA-B"},
   340  				FailedJobs:     []string{},
   341  				CompletedJobs:  []string{"jobFlowA-A"},
   342  				TerminatedJobs: []string{},
   343  				UnKnowJobs:     []string{},
   344  				JobStatusList: []jobflowv1alpha1.JobStatus{
   345  					{
   346  						Name:           "jobFlowA-A",
   347  						State:          v1alpha1.Completed,
   348  						StartTimestamp: metav1.Time{Time: createJobATime},
   349  						EndTimestamp:   metav1.Time{Time: createJobATime.Add(time.Second)},
   350  						RestartCount:   1,
   351  						RunningHistories: []jobflowv1alpha1.JobRunningHistory{
   352  							{
   353  								StartTimestamp: metav1.Time{},
   354  								EndTimestamp:   metav1.Time{},
   355  								State:          v1alpha1.Completed,
   356  							},
   357  						},
   358  					},
   359  					{
   360  						Name:           "jobFlowA-B",
   361  						State:          v1alpha1.Running,
   362  						StartTimestamp: metav1.Time{Time: createJobBTime},
   363  						EndTimestamp:   metav1.Time{},
   364  						RestartCount:   0,
   365  						RunningHistories: []jobflowv1alpha1.JobRunningHistory{
   366  							{
   367  								StartTimestamp: metav1.Time{},
   368  								EndTimestamp:   metav1.Time{},
   369  								State:          v1alpha1.Running,
   370  							},
   371  						},
   372  					},
   373  				},
   374  				Conditions: map[string]jobflowv1alpha1.Condition{
   375  					"jobFlowA-A": {
   376  						Phase:           v1alpha1.Completed,
   377  						CreateTimestamp: metav1.Time{Time: createJobATime},
   378  						RunningDuration: &metav1.Duration{Duration: time.Second},
   379  					},
   380  					"jobFlowA-B": {
   381  						Phase:           v1alpha1.Running,
   382  						CreateTimestamp: metav1.Time{Time: createJobBTime},
   383  					},
   384  				},
   385  				State: jobflowv1alpha1.State{Phase: ""},
   386  			},
   387  			wantErr: false,
   388  		},
   389  	}
   390  	for _, tt := range tests {
   391  		t.Run(tt.name, func(t *testing.T) {
   392  			fakeController := newFakeController()
   393  			for i := range tt.args.allJobList.Items {
   394  				err := fakeController.jobInformer.Informer().GetIndexer().Add(&tt.args.allJobList.Items[i])
   395  				if err != nil {
   396  					t.Error("Error While add vcjob")
   397  				}
   398  			}
   399  
   400  			got, err := fakeController.getAllJobStatus(tt.args.jobFlow)
   401  			if (err != nil) != tt.wantErr {
   402  				t.Errorf("getAllJobStatus() error = %v, wantErr %v", err, tt.wantErr)
   403  				return
   404  			}
   405  			if got != nil {
   406  				got.JobStatusList[0].RunningHistories[0].StartTimestamp = metav1.Time{}
   407  				got.JobStatusList[1].RunningHistories[0].StartTimestamp = metav1.Time{}
   408  			}
   409  			if !reflect.DeepEqual(got, tt.want) {
   410  				t.Errorf("getAllJobStatus() got = %v, want %v", got, tt.want)
   411  			}
   412  		})
   413  	}
   414  }
   415  
   416  func TestLoadJobTemplateAndSetJobFunc(t *testing.T) {
   417  	type args struct {
   418  		jobFlow     *jobflowv1alpha1.JobFlow
   419  		flowName    string
   420  		jobName     string
   421  		job         *v1alpha1.Job
   422  		jobTemplate *jobflowv1alpha1.JobTemplate
   423  	}
   424  	type wantRes struct {
   425  		OwnerReference []metav1.OwnerReference
   426  		Annotations    map[string]string
   427  		Labels         map[string]string
   428  		Err            error
   429  	}
   430  	flag := true
   431  	tests := []struct {
   432  		name string
   433  		args args
   434  		want wantRes
   435  	}{
   436  		{
   437  			name: "LoadJobTemplateAndSetJob success case",
   438  			args: args{
   439  				jobFlow: &jobflowv1alpha1.JobFlow{
   440  					ObjectMeta: metav1.ObjectMeta{
   441  						Name:      "jobflow",
   442  						Namespace: "default",
   443  					},
   444  				},
   445  				flowName: "jobtemplate",
   446  				jobName:  getJobName("jobflow", "jobtemplate"),
   447  				job:      &v1alpha1.Job{},
   448  				jobTemplate: &jobflowv1alpha1.JobTemplate{
   449  					ObjectMeta: metav1.ObjectMeta{
   450  						Name:      "jobtemplate",
   451  						Namespace: "default",
   452  					},
   453  					Spec:   v1alpha1.JobSpec{},
   454  					Status: jobflowv1alpha1.JobTemplateStatus{},
   455  				},
   456  			},
   457  			want: wantRes{
   458  				OwnerReference: []metav1.OwnerReference{
   459  					{
   460  						APIVersion:         helpers.JobFlowKind.Group + "/" + helpers.JobFlowKind.Version,
   461  						Kind:               helpers.JobFlowKind.Kind,
   462  						Name:               "jobflow",
   463  						UID:                "",
   464  						Controller:         &flag,
   465  						BlockOwnerDeletion: &flag,
   466  					},
   467  				},
   468  				Annotations: map[string]string{
   469  					CreatedByJobTemplate: GetTemplateString("default", "jobtemplate"),
   470  				},
   471  				Labels: map[string]string{
   472  					CreatedByJobTemplate: GetTemplateString("default", "jobtemplate"),
   473  				},
   474  				Err: nil,
   475  			},
   476  		},
   477  	}
   478  	for _, tt := range tests {
   479  		t.Run(tt.name, func(t *testing.T) {
   480  			fakeController := newFakeController()
   481  			err := fakeController.jobTemplateInformer.Informer().GetIndexer().Add(tt.args.jobTemplate)
   482  			if err != nil {
   483  				t.Error("Error While add vcjob")
   484  			}
   485  
   486  			if got := fakeController.loadJobTemplateAndSetJob(tt.args.jobFlow, tt.args.flowName, tt.args.jobName, tt.args.job); got != tt.want.Err {
   487  				t.Error("Expected loadJobTemplateAndSetJob() return nil, but not nil")
   488  			}
   489  			if !reflect.DeepEqual(tt.args.job.OwnerReferences, tt.want.OwnerReference) {
   490  				t.Error("not expected job OwnerReferences")
   491  			}
   492  			if !reflect.DeepEqual(tt.args.job.Annotations, tt.want.Annotations) {
   493  				t.Error("not expected job Annotations")
   494  			}
   495  			if !reflect.DeepEqual(tt.args.job.Labels, tt.want.Labels) {
   496  				t.Error("not expected job Annotations")
   497  			}
   498  		})
   499  	}
   500  }
   501  
   502  func TestDeployJobFunc(t *testing.T) {
   503  	type args struct {
   504  		jobFlow         *jobflowv1alpha1.JobFlow
   505  		jobTemplateList []*jobflowv1alpha1.JobTemplate
   506  	}
   507  	tests := []struct {
   508  		name string
   509  		args args
   510  		want error
   511  	}{
   512  		{
   513  			name: "DeployJob success case",
   514  			args: args{
   515  				jobFlow: &jobflowv1alpha1.JobFlow{
   516  					ObjectMeta: metav1.ObjectMeta{
   517  						Name:      "jobflow",
   518  						Namespace: "default",
   519  					},
   520  					Spec: jobflowv1alpha1.JobFlowSpec{
   521  						Flows: []jobflowv1alpha1.Flow{
   522  							{
   523  								Name:      "jobtemplate",
   524  								DependsOn: nil,
   525  							},
   526  						},
   527  						JobRetainPolicy: jobflowv1alpha1.Retain,
   528  					},
   529  				},
   530  				jobTemplateList: []*jobflowv1alpha1.JobTemplate{
   531  					{
   532  						ObjectMeta: metav1.ObjectMeta{
   533  							Name:      "jobtemplate",
   534  							Namespace: "default",
   535  						},
   536  						Spec:   v1alpha1.JobSpec{},
   537  						Status: jobflowv1alpha1.JobTemplateStatus{},
   538  					},
   539  				},
   540  			},
   541  			want: nil,
   542  		},
   543  	}
   544  	for _, tt := range tests {
   545  		t.Run(tt.name, func(t *testing.T) {
   546  			fakeController := newFakeController()
   547  			for i := range tt.args.jobTemplateList {
   548  				err := fakeController.jobTemplateInformer.Informer().GetIndexer().Add(tt.args.jobTemplateList[i])
   549  				if err != nil {
   550  					t.Error("Error While add jobTemplate")
   551  				}
   552  			}
   553  
   554  			if got := fakeController.deployJob(tt.args.jobFlow); got != tt.want {
   555  				t.Error("Expected deployJob() return nil, but not nil")
   556  			}
   557  		})
   558  	}
   559  }
   560  
   561  func TestDeleteAllJobsCreateByJobFlowFunc(t *testing.T) {
   562  	type args struct {
   563  		jobFlow *jobflowv1alpha1.JobFlow
   564  		jobList []*v1alpha1.Job
   565  	}
   566  	tests := []struct {
   567  		name string
   568  		args args
   569  		want error
   570  	}{
   571  		{
   572  			name: "LoadJobTemplateAndSetJob success case",
   573  			args: args{
   574  				jobFlow: &jobflowv1alpha1.JobFlow{
   575  					ObjectMeta: metav1.ObjectMeta{
   576  						Name:      "jobflow",
   577  						Namespace: "default",
   578  					},
   579  					Spec: jobflowv1alpha1.JobFlowSpec{
   580  						Flows: []jobflowv1alpha1.Flow{
   581  							{
   582  								Name:      "jobtemplate",
   583  								DependsOn: nil,
   584  							},
   585  						},
   586  						JobRetainPolicy: jobflowv1alpha1.Retain,
   587  					},
   588  				},
   589  				jobList: []*v1alpha1.Job{
   590  					{
   591  						ObjectMeta: metav1.ObjectMeta{
   592  							Name:      "jobtemplate",
   593  							Namespace: "default",
   594  						},
   595  						Spec: v1alpha1.JobSpec{},
   596  					},
   597  				},
   598  			},
   599  			want: nil,
   600  		},
   601  	}
   602  	for _, tt := range tests {
   603  		t.Run(tt.name, func(t *testing.T) {
   604  			fakeController := newFakeController()
   605  			for i := range tt.args.jobList {
   606  				_, err := fakeController.vcClient.BatchV1alpha1().Jobs(tt.args.jobList[i].Namespace).Create(context.Background(), tt.args.jobList[i], metav1.CreateOptions{})
   607  				if err != nil {
   608  					t.Error("Error While create vcjob")
   609  				}
   610  			}
   611  
   612  			if got := fakeController.deleteAllJobsCreatedByJobFlow(tt.args.jobFlow); got != tt.want {
   613  				t.Error("Expected deleteAllJobsCreatedByJobFlow() return nil, but not nil")
   614  			}
   615  		})
   616  	}
   617  }