volcano.sh/volcano@v1.9.0/pkg/controllers/cache/cache_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 cache
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  
    26  	"volcano.sh/apis/pkg/apis/batch/v1alpha1"
    27  	"volcano.sh/volcano/pkg/controllers/apis"
    28  )
    29  
    30  func TestJobCache_Add(t *testing.T) {
    31  	namespace := "test"
    32  
    33  	testcases := []struct {
    34  		Name        string
    35  		Job         *v1alpha1.Job
    36  		JobsInCache map[string]*v1alpha1.Job
    37  		ExpectedVal error
    38  	}{
    39  		{
    40  			Name: "Success case",
    41  			Job: &v1alpha1.Job{
    42  				ObjectMeta: metav1.ObjectMeta{
    43  					Name:      "job1",
    44  					Namespace: namespace,
    45  				},
    46  			},
    47  			JobsInCache: nil,
    48  			ExpectedVal: nil,
    49  		},
    50  		{
    51  			Name: "Error case",
    52  			Job: &v1alpha1.Job{
    53  				ObjectMeta: metav1.ObjectMeta{
    54  					Name:      "job1",
    55  					Namespace: namespace,
    56  				},
    57  			},
    58  			JobsInCache: map[string]*v1alpha1.Job{
    59  				"job1": {
    60  					ObjectMeta: metav1.ObjectMeta{
    61  						Name:      "job1",
    62  						Namespace: namespace,
    63  					},
    64  				},
    65  			},
    66  			ExpectedVal: fmt.Errorf("duplicated jobInfo <%s/%s>", "test", "job1"),
    67  		},
    68  	}
    69  
    70  	for i, testcase := range testcases {
    71  		jobCache := New()
    72  
    73  		for _, job := range testcase.JobsInCache {
    74  			err := jobCache.Add(job)
    75  			if err != nil {
    76  				t.Errorf("Expected not to occur while adding job, but got error: %s in case %d", err, i)
    77  			}
    78  		}
    79  
    80  		err := jobCache.Add(testcase.Job)
    81  		if err != nil && testcase.ExpectedVal != nil && err.Error() != testcase.ExpectedVal.Error() {
    82  			t.Errorf("Expected Return Value to be: %s, but got: %s in case %d", testcase.ExpectedVal, err, i)
    83  		}
    84  	}
    85  }
    86  
    87  func TestJobCache_GetStatus(t *testing.T) {
    88  	namespace := "test"
    89  
    90  	testcases := []struct {
    91  		Name        string
    92  		Job         *v1alpha1.Job
    93  		JobsInCache map[string]*v1alpha1.Job
    94  		ExpectedVal v1alpha1.JobState
    95  		ExpectedErr error
    96  	}{
    97  		{
    98  			Name: "Success Case",
    99  			Job: &v1alpha1.Job{
   100  				ObjectMeta: metav1.ObjectMeta{
   101  					Name:      "job1",
   102  					Namespace: namespace,
   103  				},
   104  			},
   105  			JobsInCache: map[string]*v1alpha1.Job{
   106  				"job1": {
   107  					ObjectMeta: metav1.ObjectMeta{
   108  						Name:      "job1",
   109  						Namespace: namespace,
   110  					},
   111  					Status: v1alpha1.JobStatus{
   112  						State: v1alpha1.JobState{
   113  							Phase: v1alpha1.Completed,
   114  						},
   115  					},
   116  				},
   117  			},
   118  			ExpectedVal: v1alpha1.JobState{
   119  				Phase: v1alpha1.Completed,
   120  			},
   121  			ExpectedErr: nil,
   122  		},
   123  		{
   124  			Name: "Error Case",
   125  			Job: &v1alpha1.Job{
   126  				ObjectMeta: metav1.ObjectMeta{
   127  					Name:      "job1",
   128  					Namespace: namespace,
   129  				},
   130  			},
   131  			JobsInCache: nil,
   132  			ExpectedVal: v1alpha1.JobState{
   133  				Phase: v1alpha1.Completed,
   134  			},
   135  			ExpectedErr: fmt.Errorf("failed to find job <%s/%s>", namespace, "job1"),
   136  		},
   137  	}
   138  
   139  	for i, testcase := range testcases {
   140  		jobCache := New()
   141  
   142  		for _, job := range testcase.JobsInCache {
   143  			err := jobCache.Add(job)
   144  			if err != nil {
   145  				t.Errorf("Expected not to occur while adding job, but got error: %s in case %d", err, i)
   146  			}
   147  		}
   148  
   149  		status, err := jobCache.GetStatus(fmt.Sprintf("%s/%s", testcase.Job.Namespace, testcase.Job.Name))
   150  		if err != nil && testcase.ExpectedErr != nil && err.Error() != testcase.ExpectedErr.Error() {
   151  			t.Errorf("Expected to get: %s, but got: %s in case %d", testcase.ExpectedErr, err, i)
   152  		}
   153  		if status != nil && status.State.Phase != testcase.ExpectedVal.Phase {
   154  			t.Errorf("Expected Return Value to be: %s, but got: %s in case %d", testcase.ExpectedVal, status.State.Phase, i)
   155  		}
   156  	}
   157  }
   158  
   159  func TestJobCache_Get(t *testing.T) {
   160  	namespace := "test"
   161  
   162  	testcases := []struct {
   163  		Name        string
   164  		Key         string
   165  		JobsInCache map[string]*v1alpha1.Job
   166  		ExpectedVal *apis.JobInfo
   167  		ExpectedErr error
   168  	}{
   169  		{
   170  			Name: "Success Case",
   171  			Key:  fmt.Sprintf("%s/%s", namespace, "job1"),
   172  			JobsInCache: map[string]*v1alpha1.Job{
   173  				"job1": {
   174  					ObjectMeta: metav1.ObjectMeta{
   175  						Name:      "job1",
   176  						Namespace: namespace,
   177  					},
   178  					Status: v1alpha1.JobStatus{
   179  						State: v1alpha1.JobState{
   180  							Phase: v1alpha1.Completed,
   181  						},
   182  					},
   183  				},
   184  			},
   185  			ExpectedVal: &apis.JobInfo{
   186  				Name:      "job1",
   187  				Namespace: namespace,
   188  				Job: &v1alpha1.Job{
   189  					ObjectMeta: metav1.ObjectMeta{
   190  						Name:      "job1",
   191  						Namespace: namespace,
   192  					},
   193  					Status: v1alpha1.JobStatus{
   194  						State: v1alpha1.JobState{
   195  							Phase: v1alpha1.Completed,
   196  						},
   197  					},
   198  				},
   199  			},
   200  			ExpectedErr: nil,
   201  		},
   202  		{
   203  			Name:        "Error Case",
   204  			Key:         fmt.Sprintf("%s/%s", namespace, "job1"),
   205  			JobsInCache: nil,
   206  			ExpectedVal: &apis.JobInfo{},
   207  			ExpectedErr: fmt.Errorf("failed to find job <%s/%s>", namespace, "job1"),
   208  		},
   209  	}
   210  
   211  	for i, testcase := range testcases {
   212  		jobCache := New()
   213  
   214  		for _, job := range testcase.JobsInCache {
   215  			err := jobCache.Add(job)
   216  			if err != nil {
   217  				t.Errorf("Expected not to occur while adding job, but got error: %s in case %d", err, i)
   218  			}
   219  		}
   220  
   221  		job, err := jobCache.Get(testcase.Key)
   222  		if err != nil && testcase.ExpectedErr != nil && err.Error() != testcase.ExpectedErr.Error() {
   223  			t.Errorf("Expected to get: %s, but got: %s in case %d", testcase.ExpectedErr, err, i)
   224  		}
   225  		if job != nil && (job.Name != testcase.ExpectedVal.Name || job.Job.Name != testcase.ExpectedVal.Job.Name) {
   226  			fmt.Println(job.Job)
   227  			t.Errorf("Expected Return Value to be same but got different values in case %d", i)
   228  		}
   229  	}
   230  }
   231  
   232  func TestJobCache_Update(t *testing.T) {
   233  	namespace := "test"
   234  
   235  	testcases := []struct {
   236  		Name        string
   237  		JobsInCache map[string]*v1alpha1.Job
   238  		UpdatedJob  *v1alpha1.Job
   239  		ExpectedErr error
   240  	}{
   241  		{
   242  			Name: "Success Case",
   243  			JobsInCache: map[string]*v1alpha1.Job{
   244  				"job1": {
   245  					ObjectMeta: metav1.ObjectMeta{
   246  						Name:            "job1",
   247  						Namespace:       namespace,
   248  						ResourceVersion: "100",
   249  					},
   250  					Status: v1alpha1.JobStatus{
   251  						State: v1alpha1.JobState{
   252  							Phase: v1alpha1.Running,
   253  						},
   254  					},
   255  				},
   256  			},
   257  			UpdatedJob: &v1alpha1.Job{
   258  				ObjectMeta: metav1.ObjectMeta{
   259  					Name:            "job1",
   260  					Namespace:       namespace,
   261  					ResourceVersion: "100",
   262  				},
   263  				Status: v1alpha1.JobStatus{
   264  					State: v1alpha1.JobState{
   265  						Phase: v1alpha1.Completed,
   266  					},
   267  				},
   268  			},
   269  			ExpectedErr: nil,
   270  		},
   271  		{
   272  			Name:        "Error Case",
   273  			JobsInCache: nil,
   274  			UpdatedJob: &v1alpha1.Job{
   275  				ObjectMeta: metav1.ObjectMeta{
   276  					Name:            "job1",
   277  					Namespace:       namespace,
   278  					ResourceVersion: "100",
   279  				},
   280  				Status: v1alpha1.JobStatus{
   281  					State: v1alpha1.JobState{
   282  						Phase: v1alpha1.Completed,
   283  					},
   284  				},
   285  			},
   286  			ExpectedErr: fmt.Errorf("failed to find job <%s/%s>", namespace, "job1"),
   287  		},
   288  	}
   289  
   290  	for i, testcase := range testcases {
   291  		jobCache := New()
   292  
   293  		for _, job := range testcase.JobsInCache {
   294  			err := jobCache.Add(job)
   295  			if err != nil {
   296  				t.Errorf("Expected not to occur while adding job, but got error: %s in case %d", err, i)
   297  			}
   298  		}
   299  
   300  		err := jobCache.Update(testcase.UpdatedJob)
   301  		if err != nil && testcase.ExpectedErr != nil && err.Error() != testcase.ExpectedErr.Error() {
   302  			t.Errorf("Expected to get: %s, but got: %s in case %d", testcase.ExpectedErr, err, i)
   303  		}
   304  		if testcase.ExpectedErr == nil {
   305  			job, err := jobCache.Get(fmt.Sprintf("%s/%s", testcase.UpdatedJob.Namespace, testcase.UpdatedJob.Name))
   306  			if err != nil {
   307  				t.Errorf("Expected Error not to have occurred in case %d", i)
   308  			}
   309  			if job.Job.Status.State.Phase != testcase.UpdatedJob.Status.State.Phase {
   310  				t.Errorf("Error in updating Job, Expected: %s, but got: %s in case %d", testcase.UpdatedJob.Status.State.Phase, job.Job.Status.State.Phase, i)
   311  			}
   312  		}
   313  	}
   314  }
   315  
   316  func TestJobCache_Delete(t *testing.T) {
   317  	namespace := "test"
   318  
   319  	testcases := []struct {
   320  		Name        string
   321  		JobsInCache map[string]*v1alpha1.Job
   322  		DeleteJob   *v1alpha1.Job
   323  		ExpectedErr error
   324  	}{
   325  		{
   326  			Name: "Success Case",
   327  			JobsInCache: map[string]*v1alpha1.Job{
   328  				"job1": {
   329  					ObjectMeta: metav1.ObjectMeta{
   330  						Name:      "job1",
   331  						Namespace: namespace,
   332  					},
   333  					Status: v1alpha1.JobStatus{
   334  						State: v1alpha1.JobState{
   335  							Phase: v1alpha1.Running,
   336  						},
   337  					},
   338  				},
   339  			},
   340  			DeleteJob: &v1alpha1.Job{
   341  				ObjectMeta: metav1.ObjectMeta{
   342  					Name:      "job1",
   343  					Namespace: namespace,
   344  				},
   345  				Status: v1alpha1.JobStatus{
   346  					State: v1alpha1.JobState{
   347  						Phase: v1alpha1.Completed,
   348  					},
   349  				},
   350  			},
   351  			ExpectedErr: nil,
   352  		},
   353  		{
   354  			Name:        "Error Case",
   355  			JobsInCache: nil,
   356  			DeleteJob: &v1alpha1.Job{
   357  				ObjectMeta: metav1.ObjectMeta{
   358  					Name:      "job1",
   359  					Namespace: namespace,
   360  				},
   361  				Status: v1alpha1.JobStatus{
   362  					State: v1alpha1.JobState{
   363  						Phase: v1alpha1.Completed,
   364  					},
   365  				},
   366  			},
   367  			ExpectedErr: fmt.Errorf("failed to find job <%s/%s>", namespace, "job1"),
   368  		},
   369  	}
   370  
   371  	for i, testcase := range testcases {
   372  		jobCache := New()
   373  
   374  		for _, job := range testcase.JobsInCache {
   375  			err := jobCache.Add(job)
   376  			if err != nil {
   377  				t.Errorf("Expected not to occur while adding job, but got error: %s in case %d", err, i)
   378  			}
   379  		}
   380  
   381  		err := jobCache.Delete(testcase.DeleteJob)
   382  		if err != nil && testcase.ExpectedErr != nil && err.Error() != testcase.ExpectedErr.Error() {
   383  			t.Errorf("Expected to get: %s, but got: %s in case %d", testcase.ExpectedErr, err, i)
   384  		}
   385  		if testcase.ExpectedErr == nil {
   386  			job, err := jobCache.Get(fmt.Sprintf("%s/%s", testcase.DeleteJob.Namespace, testcase.DeleteJob.Name))
   387  			if err == nil {
   388  				t.Errorf("Expected Error to have occurred in case %d", i)
   389  			}
   390  			if job != nil {
   391  				t.Errorf("Expected Job to be nil but got value in case %d", i)
   392  			}
   393  		}
   394  	}
   395  }
   396  
   397  func TestJobCache_AddPod(t *testing.T) {
   398  	namespace := "test"
   399  
   400  	testcases := []struct {
   401  		Name        string
   402  		JobsInCache map[string]*v1alpha1.Job
   403  		AddPod      *v1.Pod
   404  		ExpectedErr error
   405  	}{
   406  		{
   407  			Name: "Success Case",
   408  			JobsInCache: map[string]*v1alpha1.Job{
   409  				"job1": {
   410  					ObjectMeta: metav1.ObjectMeta{
   411  						Name:      "job1",
   412  						Namespace: namespace,
   413  					},
   414  					Status: v1alpha1.JobStatus{
   415  						State: v1alpha1.JobState{
   416  							Phase: v1alpha1.Running,
   417  						},
   418  					},
   419  				},
   420  			},
   421  			AddPod: &v1.Pod{
   422  				ObjectMeta: metav1.ObjectMeta{
   423  					Name:      "pod1",
   424  					Namespace: namespace,
   425  					Annotations: map[string]string{
   426  						v1alpha1.JobNameKey:  "job1",
   427  						v1alpha1.TaskSpecKey: "task1",
   428  						v1alpha1.JobVersion:  "1",
   429  					},
   430  				},
   431  				Status: v1.PodStatus{
   432  					Phase: v1.PodRunning,
   433  				},
   434  			},
   435  			ExpectedErr: nil,
   436  		},
   437  		{
   438  			Name:        "Error Case",
   439  			JobsInCache: nil,
   440  			AddPod: &v1.Pod{
   441  				ObjectMeta: metav1.ObjectMeta{
   442  					Name:      "pod1",
   443  					Namespace: namespace,
   444  					Annotations: map[string]string{
   445  						v1alpha1.TaskSpecKey: "task1",
   446  						v1alpha1.JobVersion:  "1",
   447  					},
   448  				},
   449  				Status: v1.PodStatus{
   450  					Phase: v1.PodRunning,
   451  				},
   452  			},
   453  			ExpectedErr: fmt.Errorf("failed to find job name of pod <%s/%s>", namespace, "pod1"),
   454  		},
   455  	}
   456  
   457  	for i, testcase := range testcases {
   458  		jobCache := New()
   459  
   460  		for _, job := range testcase.JobsInCache {
   461  			err := jobCache.Add(job)
   462  			if err != nil {
   463  				t.Errorf("Expected not to occur while adding job, but got error: %s in case %d", err, i)
   464  			}
   465  		}
   466  
   467  		err := jobCache.AddPod(testcase.AddPod)
   468  		if err != nil && testcase.ExpectedErr != nil && err.Error() != testcase.ExpectedErr.Error() {
   469  			t.Errorf("Expected Error to be: %s, but got: %s in case %d", testcase.ExpectedErr.Error(), err.Error(), i)
   470  		}
   471  
   472  		if err == nil {
   473  			job, err := jobCache.Get(fmt.Sprintf("%s/%s", testcase.JobsInCache["job1"].Namespace, testcase.JobsInCache["job1"].Name))
   474  			if err != nil {
   475  				t.Errorf("Expected Error not to occur while retrieving job from cache in case %d", i)
   476  			}
   477  			if err == nil {
   478  				if len(job.Pods) != 1 {
   479  					t.Errorf("Expected Len to 1 but got %d in case %d", len(job.Pods), i)
   480  				}
   481  			}
   482  		}
   483  	}
   484  }
   485  
   486  func TestJobCache_DeletePod(t *testing.T) {
   487  	namespace := "test"
   488  
   489  	testcases := []struct {
   490  		Name        string
   491  		JobsInCache map[string]*v1alpha1.Job
   492  		AddPod      map[string]*v1.Pod
   493  		DeletePod   *v1.Pod
   494  		ExpectedErr error
   495  	}{
   496  		{
   497  			Name: "Success Case",
   498  			JobsInCache: map[string]*v1alpha1.Job{
   499  				"job1": {
   500  					ObjectMeta: metav1.ObjectMeta{
   501  						Name:      "job1",
   502  						Namespace: namespace,
   503  					},
   504  					Status: v1alpha1.JobStatus{
   505  						State: v1alpha1.JobState{
   506  							Phase: v1alpha1.Running,
   507  						},
   508  					},
   509  				},
   510  			},
   511  			AddPod: map[string]*v1.Pod{
   512  				"pod1": {
   513  					ObjectMeta: metav1.ObjectMeta{
   514  						Name:      "pod1",
   515  						Namespace: namespace,
   516  						Annotations: map[string]string{
   517  							v1alpha1.JobNameKey:  "job1",
   518  							v1alpha1.TaskSpecKey: "task1",
   519  							v1alpha1.JobVersion:  "1",
   520  						},
   521  					},
   522  					Status: v1.PodStatus{
   523  						Phase: v1.PodRunning,
   524  					},
   525  				},
   526  				"pod2": {
   527  					ObjectMeta: metav1.ObjectMeta{
   528  						Name:      "pod2",
   529  						Namespace: namespace,
   530  						Annotations: map[string]string{
   531  							v1alpha1.JobNameKey:  "job1",
   532  							v1alpha1.TaskSpecKey: "task1",
   533  							v1alpha1.JobVersion:  "1",
   534  						},
   535  					},
   536  					Status: v1.PodStatus{
   537  						Phase: v1.PodRunning,
   538  					},
   539  				},
   540  			},
   541  			DeletePod: &v1.Pod{
   542  				ObjectMeta: metav1.ObjectMeta{
   543  					Name:      "pod1",
   544  					Namespace: namespace,
   545  					Annotations: map[string]string{
   546  						v1alpha1.JobNameKey:  "job1",
   547  						v1alpha1.TaskSpecKey: "task1",
   548  						v1alpha1.JobVersion:  "1",
   549  					},
   550  				},
   551  				Status: v1.PodStatus{
   552  					Phase: v1.PodRunning,
   553  				},
   554  			},
   555  			ExpectedErr: nil,
   556  		},
   557  	}
   558  
   559  	for i, testcase := range testcases {
   560  		jobCache := New()
   561  
   562  		for _, job := range testcase.JobsInCache {
   563  			err := jobCache.Add(job)
   564  			if err != nil {
   565  				t.Errorf("Expected not to occur while adding job, but got error: %s in case %d", err, i)
   566  			}
   567  		}
   568  
   569  		for _, pod := range testcase.AddPod {
   570  			err := jobCache.AddPod(pod)
   571  			if err != nil {
   572  				t.Errorf("Expected Error not occur when adding Adding Pod in case %d", i)
   573  			}
   574  		}
   575  
   576  		err := jobCache.DeletePod(testcase.DeletePod)
   577  		if err != nil && testcase.ExpectedErr != nil && err.Error() != testcase.ExpectedErr.Error() {
   578  			t.Errorf("Expected Error to be: %s, but got: %s in case %d", testcase.ExpectedErr.Error(), err.Error(), i)
   579  		}
   580  
   581  		if err == nil {
   582  			job, err := jobCache.Get(fmt.Sprintf("%s/%s", namespace, "job1"))
   583  			if err != nil {
   584  				t.Errorf("Expected Error not to have occurred but got error: %s in case %d", err, i)
   585  			}
   586  			if len(job.Pods["task1"]) != 1 {
   587  				t.Errorf("Expected total pods to be 1, but got: %d in case %d", len(job.Pods["task1"]), i)
   588  			}
   589  		}
   590  	}
   591  }
   592  
   593  func TestJobCache_UpdatePod(t *testing.T) {
   594  	namespace := "test"
   595  
   596  	testcases := []struct {
   597  		Name        string
   598  		JobsInCache map[string]*v1alpha1.Job
   599  		AddPod      map[string]*v1.Pod
   600  		UpdatePod   *v1.Pod
   601  		ExpectedErr error
   602  	}{
   603  		{
   604  			Name: "Success Case",
   605  			JobsInCache: map[string]*v1alpha1.Job{
   606  				"job1": {
   607  					ObjectMeta: metav1.ObjectMeta{
   608  						Name:      "job1",
   609  						Namespace: namespace,
   610  					},
   611  					Status: v1alpha1.JobStatus{
   612  						State: v1alpha1.JobState{
   613  							Phase: v1alpha1.Running,
   614  						},
   615  					},
   616  				},
   617  			},
   618  			AddPod: map[string]*v1.Pod{
   619  				"pod1": {
   620  					ObjectMeta: metav1.ObjectMeta{
   621  						Name:      "pod1",
   622  						Namespace: namespace,
   623  						Annotations: map[string]string{
   624  							v1alpha1.JobNameKey:  "job1",
   625  							v1alpha1.TaskSpecKey: "task1",
   626  							v1alpha1.JobVersion:  "1",
   627  						},
   628  					},
   629  					Status: v1.PodStatus{
   630  						Phase: v1.PodRunning,
   631  					},
   632  				},
   633  				"pod2": {
   634  					ObjectMeta: metav1.ObjectMeta{
   635  						Name:      "pod2",
   636  						Namespace: namespace,
   637  						Annotations: map[string]string{
   638  							v1alpha1.JobNameKey:  "job1",
   639  							v1alpha1.TaskSpecKey: "task1",
   640  							v1alpha1.JobVersion:  "1",
   641  						},
   642  					},
   643  					Status: v1.PodStatus{
   644  						Phase: v1.PodRunning,
   645  					},
   646  				},
   647  			},
   648  			UpdatePod: &v1.Pod{
   649  				ObjectMeta: metav1.ObjectMeta{
   650  					Name:      "pod1",
   651  					Namespace: namespace,
   652  					Annotations: map[string]string{
   653  						v1alpha1.JobNameKey:  "job1",
   654  						v1alpha1.TaskSpecKey: "task1",
   655  						v1alpha1.JobVersion:  "1",
   656  					},
   657  				},
   658  				Status: v1.PodStatus{
   659  					Phase: v1.PodSucceeded,
   660  				},
   661  			},
   662  			ExpectedErr: nil,
   663  		},
   664  	}
   665  
   666  	for i, testcase := range testcases {
   667  		jobCache := New()
   668  
   669  		for _, job := range testcase.JobsInCache {
   670  			err := jobCache.Add(job)
   671  			if err != nil {
   672  				t.Errorf("Expected not to occur while adding job, but got error: %s in case %d", err, i)
   673  			}
   674  		}
   675  
   676  		for _, pod := range testcase.AddPod {
   677  			err := jobCache.AddPod(pod)
   678  			if err != nil {
   679  				t.Errorf("Expected Error not occur when adding Adding Pod in case %d", i)
   680  			}
   681  		}
   682  
   683  		err := jobCache.UpdatePod(testcase.UpdatePod)
   684  		if err != nil && testcase.ExpectedErr != nil && err.Error() != testcase.ExpectedErr.Error() {
   685  			t.Errorf("Expected Error to be: %s, but got: %s in case %d", testcase.ExpectedErr.Error(), err.Error(), i)
   686  		}
   687  
   688  		if err == nil {
   689  			job, err := jobCache.Get(fmt.Sprintf("%s/%s", namespace, "job1"))
   690  			if err != nil {
   691  				t.Errorf("Expected Error not to have occurred but got error: %s in case %d", err, i)
   692  			}
   693  			for _, task := range job.Pods {
   694  				for _, pod := range task {
   695  					if pod.Name == testcase.UpdatePod.Name {
   696  						if pod.Status.Phase != testcase.UpdatePod.Status.Phase {
   697  							t.Errorf("Expected Pod status to be updated to %s, but got %s in case %d", testcase.UpdatePod.Status.Phase, pod.Status.Phase, i)
   698  						}
   699  					}
   700  				}
   701  			}
   702  		}
   703  	}
   704  }
   705  
   706  func TestJobCache_TaskCompleted(t *testing.T) {
   707  	namespace := "test"
   708  
   709  	testcases := []struct {
   710  		Name        string
   711  		JobsInCache map[string]*v1alpha1.Job
   712  		AddPod      map[string]*v1.Pod
   713  		ExpectedVal bool
   714  	}{
   715  		{
   716  			Name: "Success Case",
   717  			JobsInCache: map[string]*v1alpha1.Job{
   718  				"job1": {
   719  					ObjectMeta: metav1.ObjectMeta{
   720  						Name:      "job1",
   721  						Namespace: namespace,
   722  					},
   723  					Spec: v1alpha1.JobSpec{
   724  						Tasks: []v1alpha1.TaskSpec{
   725  							{
   726  								Name:     "task1",
   727  								Replicas: 2,
   728  							},
   729  						},
   730  					},
   731  					Status: v1alpha1.JobStatus{
   732  						State: v1alpha1.JobState{
   733  							Phase: v1alpha1.Running,
   734  						},
   735  					},
   736  				},
   737  			},
   738  			AddPod: map[string]*v1.Pod{
   739  				"pod1": {
   740  					ObjectMeta: metav1.ObjectMeta{
   741  						Name:      "pod1",
   742  						Namespace: namespace,
   743  						Annotations: map[string]string{
   744  							v1alpha1.JobNameKey:  "job1",
   745  							v1alpha1.TaskSpecKey: "task1",
   746  							v1alpha1.JobVersion:  "1",
   747  						},
   748  					},
   749  					Status: v1.PodStatus{
   750  						Phase: v1.PodSucceeded,
   751  					},
   752  				},
   753  				"pod2": {
   754  					ObjectMeta: metav1.ObjectMeta{
   755  						Name:      "pod2",
   756  						Namespace: namespace,
   757  						Annotations: map[string]string{
   758  							v1alpha1.JobNameKey:  "job1",
   759  							v1alpha1.TaskSpecKey: "task1",
   760  							v1alpha1.JobVersion:  "1",
   761  						},
   762  					},
   763  					Status: v1.PodStatus{
   764  						Phase: v1.PodSucceeded,
   765  					},
   766  				},
   767  			},
   768  			ExpectedVal: true,
   769  		},
   770  		{
   771  			Name: "False Case",
   772  			JobsInCache: map[string]*v1alpha1.Job{
   773  				"job1": {
   774  					ObjectMeta: metav1.ObjectMeta{
   775  						Name:      "job1",
   776  						Namespace: namespace,
   777  					},
   778  					Spec: v1alpha1.JobSpec{
   779  						Tasks: []v1alpha1.TaskSpec{
   780  							{
   781  								Name:     "task1",
   782  								Replicas: 2,
   783  							},
   784  						},
   785  					},
   786  					Status: v1alpha1.JobStatus{
   787  						State: v1alpha1.JobState{
   788  							Phase: v1alpha1.Running,
   789  						},
   790  					},
   791  				},
   792  			},
   793  			AddPod: map[string]*v1.Pod{
   794  				"pod1": {
   795  					ObjectMeta: metav1.ObjectMeta{
   796  						Name:      "pod1",
   797  						Namespace: namespace,
   798  						Annotations: map[string]string{
   799  							v1alpha1.JobNameKey:  "job1",
   800  							v1alpha1.TaskSpecKey: "task1",
   801  							v1alpha1.JobVersion:  "1",
   802  						},
   803  					},
   804  					Status: v1.PodStatus{
   805  						Phase: v1.PodSucceeded,
   806  					},
   807  				},
   808  				"pod2": {
   809  					ObjectMeta: metav1.ObjectMeta{
   810  						Name:      "pod2",
   811  						Namespace: namespace,
   812  						Annotations: map[string]string{
   813  							v1alpha1.JobNameKey:  "job1",
   814  							v1alpha1.TaskSpecKey: "task1",
   815  							v1alpha1.JobVersion:  "1",
   816  						},
   817  					},
   818  					Status: v1.PodStatus{
   819  						Phase: v1.PodRunning,
   820  					},
   821  				},
   822  			},
   823  			ExpectedVal: false,
   824  		},
   825  	}
   826  
   827  	for i, testcase := range testcases {
   828  		jobCache := New()
   829  
   830  		for _, job := range testcase.JobsInCache {
   831  			err := jobCache.Add(job)
   832  			if err != nil {
   833  				t.Errorf("Expected not to occur while adding job, but got error: %s in case %d", err, i)
   834  			}
   835  		}
   836  
   837  		for _, pod := range testcase.AddPod {
   838  			err := jobCache.AddPod(pod)
   839  			if err != nil {
   840  				t.Errorf("Expected Error not occur when adding Adding Pod in case %d", i)
   841  			}
   842  		}
   843  
   844  		completed := jobCache.TaskCompleted(fmt.Sprintf("%s/%s", namespace, "job1"), "task1")
   845  		if completed != testcase.ExpectedVal {
   846  			t.Errorf("Expected Return Value to be: %t, but got: %t in case %d", testcase.ExpectedVal, completed, i)
   847  		}
   848  	}
   849  }