github.com/kubeflow/training-operator@v1.7.0/pkg/apis/kubeflow.org/v1/tensorflow_validation_test.go (about)

     1  // Copyright 2018 The Kubeflow Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package v1
    16  
    17  import (
    18  	"testing"
    19  
    20  	corev1 "k8s.io/api/core/v1"
    21  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    22  	"k8s.io/utils/pointer"
    23  )
    24  
    25  func TestValidateV1TFJob(t *testing.T) {
    26  	validTFReplicaSpecs := map[ReplicaType]*ReplicaSpec{
    27  		TFJobReplicaTypeWorker: {
    28  			Replicas:      pointer.Int32(2),
    29  			RestartPolicy: RestartPolicyOnFailure,
    30  			Template: corev1.PodTemplateSpec{
    31  				Spec: corev1.PodSpec{
    32  					Containers: []corev1.Container{{
    33  						Name:  "tensorflow",
    34  						Image: "kubeflow/tf-mnist-with-summaries:latest",
    35  						Command: []string{
    36  							"python",
    37  							"/var/tf_mnist/mnist_with_summaries.py",
    38  						},
    39  					}},
    40  				},
    41  			},
    42  		},
    43  	}
    44  
    45  	testCases := map[string]struct {
    46  		tfJob   *TFJob
    47  		wantErr bool
    48  	}{
    49  		"valid tfJob": {
    50  			tfJob: &TFJob{
    51  				ObjectMeta: metav1.ObjectMeta{
    52  					Name: "test",
    53  				},
    54  				Spec: TFJobSpec{
    55  					TFReplicaSpecs: validTFReplicaSpecs,
    56  				},
    57  			},
    58  			wantErr: false,
    59  		},
    60  		"TFJob name does not meet DNS1035": {
    61  			tfJob: &TFJob{
    62  				ObjectMeta: metav1.ObjectMeta{
    63  					Name: "00test",
    64  				},
    65  				Spec: TFJobSpec{
    66  					TFReplicaSpecs: validTFReplicaSpecs,
    67  				},
    68  			},
    69  			wantErr: true,
    70  		},
    71  		"no containers": {
    72  			tfJob: &TFJob{
    73  				ObjectMeta: metav1.ObjectMeta{
    74  					Name: "test",
    75  				},
    76  				Spec: TFJobSpec{
    77  					TFReplicaSpecs: map[ReplicaType]*ReplicaSpec{
    78  						TFJobReplicaTypeWorker: {
    79  							Template: corev1.PodTemplateSpec{
    80  								Spec: corev1.PodSpec{
    81  									Containers: []corev1.Container{},
    82  								},
    83  							},
    84  						},
    85  					},
    86  				},
    87  			},
    88  			wantErr: true,
    89  		},
    90  		"empty image": {
    91  			tfJob: &TFJob{
    92  				ObjectMeta: metav1.ObjectMeta{
    93  					Name: "test",
    94  				},
    95  				Spec: TFJobSpec{
    96  					TFReplicaSpecs: map[ReplicaType]*ReplicaSpec{
    97  						TFJobReplicaTypeWorker: {
    98  							Template: corev1.PodTemplateSpec{
    99  								Spec: corev1.PodSpec{
   100  									Containers: []corev1.Container{{
   101  										Name:  "tensorflow",
   102  										Image: "",
   103  									}},
   104  								},
   105  							},
   106  						},
   107  					},
   108  				},
   109  			},
   110  			wantErr: true,
   111  		},
   112  		"tfJob default container name doesn't present": {
   113  			tfJob: &TFJob{
   114  				ObjectMeta: metav1.ObjectMeta{
   115  					Name: "test",
   116  				},
   117  				Spec: TFJobSpec{
   118  					TFReplicaSpecs: map[ReplicaType]*ReplicaSpec{
   119  						TFJobReplicaTypeWorker: {
   120  							Template: corev1.PodTemplateSpec{
   121  								Spec: corev1.PodSpec{
   122  									Containers: []corev1.Container{{
   123  										Name:  "",
   124  										Image: "kubeflow/tf-dist-mnist-test:1.0",
   125  									}},
   126  								},
   127  							},
   128  						},
   129  					},
   130  				},
   131  			},
   132  			wantErr: true,
   133  		},
   134  		"there are more than 2 masterReplica's or ChiefReplica's": {
   135  			tfJob: &TFJob{
   136  				ObjectMeta: metav1.ObjectMeta{
   137  					Name: "test",
   138  				},
   139  				Spec: TFJobSpec{
   140  					TFReplicaSpecs: map[ReplicaType]*ReplicaSpec{
   141  						TFJobReplicaTypeChief: {
   142  							Template: corev1.PodTemplateSpec{
   143  								Spec: corev1.PodSpec{
   144  									Containers: []corev1.Container{},
   145  								},
   146  							},
   147  						},
   148  						TFJobReplicaTypeMaster: {
   149  							Template: corev1.PodTemplateSpec{
   150  								Spec: corev1.PodSpec{
   151  									Containers: []corev1.Container{},
   152  								},
   153  							},
   154  						},
   155  					},
   156  				},
   157  			},
   158  			wantErr: true,
   159  		},
   160  	}
   161  
   162  	for name, tc := range testCases {
   163  		t.Run(name, func(t *testing.T) {
   164  			got := ValidateV1TFJob(tc.tfJob)
   165  			if (got != nil) != tc.wantErr {
   166  				t.Fatalf("ValidateV1TFJob() error = %v, wantErr %v", got, tc.wantErr)
   167  			}
   168  		})
   169  	}
   170  }
   171  
   172  func TestIsChieforMaster(t *testing.T) {
   173  	tc := []struct {
   174  		Type     ReplicaType
   175  		Expected bool
   176  	}{
   177  		{
   178  			Type:     TFJobReplicaTypeChief,
   179  			Expected: true,
   180  		},
   181  		{
   182  			Type:     TFJobReplicaTypeMaster,
   183  			Expected: true,
   184  		},
   185  		{
   186  			Type:     TFJobReplicaTypeWorker,
   187  			Expected: false,
   188  		},
   189  	}
   190  
   191  	for _, c := range tc {
   192  		actual := IsChieforMaster(c.Type)
   193  		if actual != c.Expected {
   194  			t.Errorf("Expected %v; Got %v", c.Expected, actual)
   195  		}
   196  	}
   197  }