| /* |
| Copyright 2017 The Kubernetes Authors. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| package controllerrevision |
| |
| import ( |
| "testing" |
| |
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| "k8s.io/apimachinery/pkg/runtime" |
| genericapirequest "k8s.io/apiserver/pkg/endpoints/request" |
| "k8s.io/kubernetes/pkg/apis/apps" |
| api "k8s.io/kubernetes/pkg/apis/core" |
| ) |
| |
| func TestStrategy_NamespaceScoped(t *testing.T) { |
| if !Strategy.NamespaceScoped() { |
| t.Error("ControllerRevision strategy must be namespace scoped") |
| } |
| } |
| |
| func TestStrategy_AllowCreateOnUpdate(t *testing.T) { |
| if Strategy.AllowCreateOnUpdate() { |
| t.Error("ControllerRevision should not be created on update") |
| } |
| } |
| |
| func TestStrategy_Validate(t *testing.T) { |
| ctx := genericapirequest.NewDefaultContext() |
| var ( |
| valid = newControllerRevision("validname", "validns", newObject(), 0) |
| badRevision = newControllerRevision("validname", "validns", newObject(), -1) |
| emptyName = newControllerRevision("", "validns", newObject(), 0) |
| invalidName = newControllerRevision("NoUppercaseOrSpecialCharsLike=Equals", "validns", newObject(), 0) |
| emptyNs = newControllerRevision("validname", "", newObject(), 100) |
| invalidNs = newControllerRevision("validname", "NoUppercaseOrSpecialCharsLike=Equals", newObject(), 100) |
| nilData = newControllerRevision("validname", "validns", nil, 0) |
| ) |
| |
| tests := map[string]struct { |
| history *apps.ControllerRevision |
| isValid bool |
| }{ |
| "valid": {valid, true}, |
| "negative revision": {badRevision, false}, |
| "empty name": {emptyName, false}, |
| "invalid name": {invalidName, false}, |
| "empty namespace": {emptyNs, false}, |
| "invalid namespace": {invalidNs, false}, |
| "nil data": {nilData, false}, |
| } |
| |
| for name, tc := range tests { |
| errs := Strategy.Validate(ctx, tc.history) |
| if tc.isValid && len(errs) > 0 { |
| t.Errorf("%v: unexpected error: %v", name, errs) |
| } |
| if !tc.isValid && len(errs) == 0 { |
| t.Errorf("%v: unexpected non-error", name) |
| } |
| } |
| } |
| |
| func TestStrategy_ValidateUpdate(t *testing.T) { |
| ctx := genericapirequest.NewDefaultContext() |
| var ( |
| valid = newControllerRevision("validname", "validns", newObject(), 0) |
| changedData = newControllerRevision("validname", "validns", |
| func() runtime.Object { |
| modified := newObject() |
| ss := modified.(*apps.StatefulSet) |
| ss.Name = "cde" |
| return modified |
| }(), 0) |
| changedRevision = newControllerRevision("validname", "validns", newObject(), 1) |
| ) |
| |
| cases := []struct { |
| name string |
| newHistory *apps.ControllerRevision |
| oldHistory *apps.ControllerRevision |
| isValid bool |
| }{ |
| { |
| name: "valid", |
| newHistory: valid, |
| oldHistory: valid, |
| isValid: true, |
| }, |
| { |
| name: "changed data", |
| newHistory: changedData, |
| oldHistory: valid, |
| isValid: false, |
| }, |
| { |
| name: "changed revision", |
| newHistory: changedRevision, |
| oldHistory: valid, |
| isValid: true, |
| }, |
| } |
| |
| for _, tc := range cases { |
| errs := Strategy.ValidateUpdate(ctx, tc.newHistory, tc.oldHistory) |
| if tc.isValid && len(errs) > 0 { |
| t.Errorf("%v: unexpected error: %v", tc.name, errs) |
| } |
| if !tc.isValid && len(errs) == 0 { |
| t.Errorf("%v: unexpected non-error", tc.name) |
| } |
| } |
| } |
| |
| func newControllerRevision(name, namespace string, data runtime.Object, revision int64) *apps.ControllerRevision { |
| return &apps.ControllerRevision{ |
| ObjectMeta: metav1.ObjectMeta{ |
| Name: name, |
| Namespace: namespace, |
| ResourceVersion: "1", |
| Labels: map[string]string{"foo": "bar"}, |
| }, |
| Data: data, |
| Revision: revision, |
| } |
| } |
| |
| func newObject() runtime.Object { |
| return &apps.StatefulSet{ |
| ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault}, |
| Spec: apps.StatefulSetSpec{ |
| Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, |
| Template: api.PodTemplateSpec{ |
| Spec: api.PodSpec{ |
| RestartPolicy: api.RestartPolicyAlways, |
| DNSPolicy: api.DNSClusterFirst, |
| }, |
| ObjectMeta: metav1.ObjectMeta{ |
| Labels: map[string]string{"foo": "bar"}, |
| }, |
| }, |
| }, |
| } |
| } |