knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/tracker/interface_test.go (about) 1 /* 2 Copyright 2019 The Knative 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 tracker 18 19 import ( 20 "context" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/runtime/schema" 26 "knative.dev/pkg/apis" 27 ) 28 29 func TestGroupVersionKind(t *testing.T) { 30 ref := Reference{ 31 APIVersion: "apps/v1", 32 Kind: "Deployment", 33 Namespace: "default", 34 Name: "nginx", 35 } 36 37 want := schema.GroupVersionKind{ 38 Group: "apps", 39 Version: "v1", 40 Kind: "Deployment", 41 } 42 got := ref.GroupVersionKind() 43 if want != got { 44 t.Errorf("GroupVersionKind() = %v, wanted = %v", got, want) 45 } 46 } 47 48 func TestValidateObjectReference(t *testing.T) { 49 tests := []struct { 50 name string 51 ref Reference 52 want *apis.FieldError 53 }{{ 54 name: "empty reference", 55 want: apis.ErrMissingField("apiVersion", "kind", "name", "namespace"), 56 }, { 57 name: "good reference", 58 ref: Reference{ 59 APIVersion: "apps/v1", 60 Kind: "Deployment", 61 Namespace: "default", 62 Name: "nginx", 63 }, 64 }, { 65 name: "another good reference", 66 ref: Reference{ 67 APIVersion: "v1", 68 Kind: "Service", 69 Namespace: "default", 70 Name: "nginx", 71 }, 72 }, { 73 name: "bad apiVersion", 74 ref: Reference{ 75 APIVersion: "a b c d", // Bad! 76 Kind: "Service", 77 Namespace: "default", 78 Name: "nginx", 79 }, 80 want: apis.ErrInvalidValue("name part must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]')", "apiVersion"), 81 }, { 82 name: "bad kind", 83 ref: Reference{ 84 APIVersion: "apps/v1", 85 Kind: "a b c d", // Bad! 86 Namespace: "default", 87 Name: "nginx", 88 }, 89 want: apis.ErrInvalidValue("a valid C identifier must start with alphabetic character or '_', followed by a string of alphanumeric characters or '_' (e.g. 'my_name', or 'MY_NAME', or 'MyName', regex used for validation is '[A-Za-z_][A-Za-z0-9_]*')", "kind"), 90 }, { 91 name: "bad namespace and name", 92 ref: Reference{ 93 APIVersion: "apps/v1", 94 Kind: "Deployment", 95 Namespace: "a.b", 96 Name: "c.d", 97 }, 98 want: &apis.FieldError{ 99 Message: "invalid value: must not contain dots", 100 Paths: []string{"namespace", "name"}, 101 }, 102 }, { 103 name: "with selector too", 104 ref: Reference{ 105 APIVersion: "apps/v1", 106 Kind: "Deployment", 107 Namespace: "default", 108 Name: "nginx", 109 Selector: &metav1.LabelSelector{}, 110 }, 111 want: apis.ErrDisallowedFields("selector"), 112 }} 113 114 for _, test := range tests { 115 t.Run(test.name, func(t *testing.T) { 116 got := test.ref.ValidateObjectReference(context.Background()) 117 if (test.want != nil) != (got != nil) { 118 t.Errorf("ValidateObjectReference() = %v, wanted %v", got, test.want) 119 } else if test.want != nil { 120 want, got := test.want.Error(), got.Error() 121 if diff := cmp.Diff(want, got); diff != "" { 122 t.Errorf("ValidateObjectReference() diff: %s", diff) 123 } 124 } 125 }) 126 } 127 } 128 129 func TestValidate(t *testing.T) { 130 tests := []struct { 131 name string 132 ref Reference 133 want *apis.FieldError 134 }{{ 135 name: "empty reference", 136 want: apis.ErrMissingField("apiVersion", "kind", "namespace").Also( 137 apis.ErrMissingOneOf("name", "selector")), 138 }, { 139 name: "good reference", 140 ref: Reference{ 141 APIVersion: "apps/v1", 142 Kind: "Deployment", 143 Namespace: "default", 144 Name: "nginx", 145 }, 146 }, { 147 name: "another good reference", 148 ref: Reference{ 149 APIVersion: "v1", 150 Kind: "Service", 151 Namespace: "default", 152 Name: "nginx", 153 }, 154 }, { 155 name: "bad apiVersion", 156 ref: Reference{ 157 APIVersion: "a b c d", // Bad! 158 Kind: "Service", 159 Namespace: "default", 160 Name: "nginx", 161 }, 162 want: apis.ErrInvalidValue("name part must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]')", "apiVersion"), 163 }, { 164 name: "bad kind", 165 ref: Reference{ 166 APIVersion: "apps/v1", 167 Kind: "a b c d", // Bad! 168 Namespace: "default", 169 Name: "nginx", 170 }, 171 want: apis.ErrInvalidValue("a valid C identifier must start with alphabetic character or '_', followed by a string of alphanumeric characters or '_' (e.g. 'my_name', or 'MY_NAME', or 'MyName', regex used for validation is '[A-Za-z_][A-Za-z0-9_]*')", "kind"), 172 }, { 173 name: "bad namespace and name", 174 ref: Reference{ 175 APIVersion: "apps/v1", 176 Kind: "Deployment", 177 Namespace: "a.b", 178 Name: "c.d", 179 }, 180 want: &apis.FieldError{ 181 Message: "invalid value: must not contain dots", 182 Paths: []string{"namespace", "name"}, 183 }, 184 }, { 185 name: "with selector too", 186 ref: Reference{ 187 APIVersion: "apps/v1", 188 Kind: "Deployment", 189 Namespace: "default", 190 Name: "nginx", 191 Selector: &metav1.LabelSelector{}, 192 }, 193 want: apis.ErrMultipleOneOf("name", "selector"), 194 }, { 195 name: "with just selector", 196 ref: Reference{ 197 APIVersion: "apps/v1", 198 Kind: "Deployment", 199 Namespace: "default", 200 Selector: &metav1.LabelSelector{ 201 MatchLabels: map[string]string{ 202 "foo": "bar", 203 }, 204 }, 205 }, 206 }, { 207 name: "with invalid selector", 208 ref: Reference{ 209 APIVersion: "apps/v1", 210 Kind: "Deployment", 211 Namespace: "default", 212 Selector: &metav1.LabelSelector{ 213 MatchLabels: map[string]string{ 214 "a b c": "bar", 215 }, 216 }, 217 }, 218 want: apis.ErrInvalidValue(`key: Invalid value: "a b c": name part must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]')`, "selector"), 219 }} 220 221 for _, test := range tests { 222 t.Run(test.name, func(t *testing.T) { 223 got := test.ref.Validate(context.Background()) 224 if (test.want != nil) != (got != nil) { 225 t.Errorf("ValidateObjectReference() = %v, wanted %v", got, test.want) 226 } else if test.want != nil { 227 want, got := test.want.Error(), got.Error() 228 if diff := cmp.Diff(want, got); diff != "" { 229 t.Errorf("ValidateObjectReference() diff %s", diff) 230 } 231 } 232 }) 233 } 234 }