Skip to content

Commit

Permalink
Merge pull request kubernetes#13092 from wojtek-t/refactor_etcd_creat…
Browse files Browse the repository at this point in the history
…e_test

Refactoring of create etcd tests.
  • Loading branch information
wojtek-t committed Aug 25, 2015
2 parents 4d10def + 61de4fc commit d146545
Show file tree
Hide file tree
Showing 19 changed files with 369 additions and 470 deletions.
75 changes: 67 additions & 8 deletions pkg/api/rest/resttest/resttest.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ import (

type Tester struct {
*testing.T
storage rest.Storage
storageError injectErrorFunc
clusterScope bool
storage rest.Storage
storageError injectErrorFunc
clusterScope bool
generatesName bool
}

type injectErrorFunc func(err error)
Expand All @@ -62,6 +63,11 @@ func (t *Tester) ClusterScope() *Tester {
return t
}

func (t *Tester) GeneratesName() *Tester {
t.generatesName = true
return t
}

// TestNamespace returns the namespace that will be used when creating contexts.
// Returns NamespaceNone for cluster-scoped objects.
func (t *Tester) TestNamespace() string {
Expand Down Expand Up @@ -96,14 +102,20 @@ func copyOrDie(obj runtime.Object) runtime.Object {
return out
}

type AssignFunc func(objs []runtime.Object) []runtime.Object
type SetRVFunc func(resourceVersion uint64)
type AssignFunc func([]runtime.Object) []runtime.Object
type GetFunc func(api.Context, runtime.Object) (runtime.Object, error)
type SetFunc func(api.Context, runtime.Object) error
type SetRVFunc func(uint64)

// Test creating an object.
func (t *Tester) TestCreate(valid runtime.Object, invalid ...runtime.Object) {
func (t *Tester) TestCreate(valid runtime.Object, setFn SetFunc, getFn GetFunc, invalid ...runtime.Object) {
t.testCreateHasMetadata(copyOrDie(valid))
t.testCreateGeneratesName(copyOrDie(valid))
t.testCreateGeneratesNameReturnsServerTimeout(copyOrDie(valid))
if !t.generatesName {
t.testCreateGeneratesName(copyOrDie(valid))
t.testCreateGeneratesNameReturnsServerTimeout(copyOrDie(valid))
}
t.testCreateEquals(copyOrDie(valid), getFn)
t.testCreateAlreadyExisting(copyOrDie(valid), setFn)
if t.clusterScope {
t.testCreateDiscardsObjectNamespace(copyOrDie(valid))
t.testCreateIgnoresContextNamespace(copyOrDie(valid))
Expand Down Expand Up @@ -161,6 +173,53 @@ func (t *Tester) TestList(obj runtime.Object, assignFn AssignFunc, setRVFn SetRV
// =============================================================================
// Creation tests.

func (t *Tester) testCreateAlreadyExisting(obj runtime.Object, setFn SetFunc) {
ctx := t.TestContext()

foo := copyOrDie(obj)
fooMeta := t.getObjectMetaOrFail(foo)
fooMeta.Name = "foo1"
fooMeta.Namespace = api.NamespaceValue(ctx)
fooMeta.GenerateName = ""
if err := setFn(ctx, foo); err != nil {
t.Errorf("unexpected error: %v", err)
}

_, err := t.storage.(rest.Creater).Create(ctx, foo)
if !errors.IsAlreadyExists(err) {
t.Errorf("expected already exists err, got %v", err)
}
}

func (t *Tester) testCreateEquals(obj runtime.Object, getFn GetFunc) {
ctx := t.TestContext()

foo := copyOrDie(obj)
fooMeta := t.getObjectMetaOrFail(foo)
fooMeta.Name = "foo2"
fooMeta.Namespace = api.NamespaceValue(ctx)
fooMeta.GenerateName = ""

created, err := t.storage.(rest.Creater).Create(ctx, foo)
if err != nil {
t.Errorf("unexpected error: %v", err)
}

got, err := getFn(ctx, foo)
if err != nil {
t.Errorf("unexpected error: %v", err)
}

// Set resource version which might be unset in created object.
createdMeta := t.getObjectMetaOrFail(created)
gotMeta := t.getObjectMetaOrFail(got)
createdMeta.ResourceVersion = gotMeta.ResourceVersion

if e, a := created, got; !api.Semantic.DeepEqual(e, a) {
t.Errorf("unexpected obj: %#v, expected %#v", e, a)
}
}

func (t *Tester) testCreateDiscardsObjectNamespace(valid runtime.Object) {
objectMeta := t.getObjectMetaOrFail(valid)

Expand Down
141 changes: 24 additions & 117 deletions pkg/registry/controller/etcd/etcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package etcd

import (
"strconv"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -87,102 +86,33 @@ var validController = api.ReplicationController{
Spec: validControllerSpec,
}

func TestEtcdCreateController(t *testing.T) {
ctx := api.NewDefaultContext()
storage, fakeClient := newStorage(t)
_, err := storage.Create(ctx, &validController)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
key, _ := storage.KeyFunc(ctx, validController.Name)
key = etcdtest.AddPrefix(key)
resp, err := fakeClient.Get(key, false, false)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
var ctrl api.ReplicationController
err = testapi.Codec().DecodeInto([]byte(resp.Node.Value), &ctrl)
if err != nil {
t.Errorf("unexpected error: %v", err)
}

if ctrl.Name != "foo" {
t.Errorf("Unexpected controller: %#v %s", ctrl, resp.Node.Value)
}
}

func TestEtcdCreateControllerAlreadyExisting(t *testing.T) {
ctx := api.NewDefaultContext()
func TestCreate(t *testing.T) {
storage, fakeClient := newStorage(t)
key, _ := storage.KeyFunc(ctx, validController.Name)
key = etcdtest.AddPrefix(key)
fakeClient.Set(key, runtime.EncodeOrDie(testapi.Codec(), &validController), 0)

_, err := storage.Create(ctx, &validController)
if !errors.IsAlreadyExists(err) {
t.Errorf("expected already exists err, got %#v", err)
}
}

func TestEtcdCreateControllerValidates(t *testing.T) {
ctx := api.NewDefaultContext()
storage, _ := newStorage(t)
emptyName := validController
emptyName.Name = ""
failureCases := []api.ReplicationController{emptyName}
for _, failureCase := range failureCases {
c, err := storage.Create(ctx, &failureCase)
if c != nil {
t.Errorf("Expected nil channel")
}
if !errors.IsInvalid(err) {
t.Errorf("Expected to get an invalid resource error, got %v", err)
}
}
}

func TestCreateControllerWithGeneratedName(t *testing.T) {
storage, _ := newStorage(t)
controller := &api.ReplicationController{
ObjectMeta: api.ObjectMeta{
Namespace: api.NamespaceDefault,
GenerateName: "rc-",
test := resttest.New(t, storage, fakeClient.SetError)
test.TestCreate(
// valid
&api.ReplicationController{
Spec: api.ReplicationControllerSpec{
Replicas: 2,
Selector: map[string]string{"a": "b"},
Template: &validPodTemplate.Template,
},
},
Spec: api.ReplicationControllerSpec{
Replicas: 2,
Selector: map[string]string{"a": "b"},
Template: &validPodTemplate.Template,
func(ctx api.Context, obj runtime.Object) error {
return registrytest.SetObject(fakeClient, storage.KeyFunc, ctx, obj)
},
}

ctx := api.NewDefaultContext()
_, err := storage.Create(ctx, controller)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if controller.Name == "rc-" || !strings.HasPrefix(controller.Name, "rc-") {
t.Errorf("unexpected name: %#v", controller)
}
}

func TestCreateControllerWithConflictingNamespace(t *testing.T) {
storage, _ := newStorage(t)
controller := &api.ReplicationController{
ObjectMeta: api.ObjectMeta{Name: "test", Namespace: "not-default"},
}

ctx := api.NewDefaultContext()
channel, err := storage.Create(ctx, controller)
if channel != nil {
t.Error("Expected a nil channel, but we got a value")
}
errSubString := "namespace"
if err == nil {
t.Errorf("Expected an error, but we didn't get one")
} else if !errors.IsBadRequest(err) ||
strings.Index(err.Error(), errSubString) == -1 {
t.Errorf("Expected a Bad Request error with the sub string '%s', got %v", errSubString, err)
}
func(ctx api.Context, obj runtime.Object) (runtime.Object, error) {
return registrytest.GetObject(fakeClient, storage.KeyFunc, storage.NewFunc, ctx, obj)
},
// invalid
&api.ReplicationController{
Spec: api.ReplicationControllerSpec{
Replicas: 2,
Selector: map[string]string{},
Template: &validPodTemplate.Template,
},
},
)
}

func TestEtcdControllerValidatesUpdate(t *testing.T) {
Expand Down Expand Up @@ -553,29 +483,6 @@ func TestEtcdWatchControllersNotMatch(t *testing.T) {
}
}

func TestCreate(t *testing.T) {
storage, fakeClient := newStorage(t)
test := resttest.New(t, storage, fakeClient.SetError)
test.TestCreate(
// valid
&api.ReplicationController{
Spec: api.ReplicationControllerSpec{
Replicas: 2,
Selector: map[string]string{"a": "b"},
Template: &validPodTemplate.Template,
},
},
// invalid
&api.ReplicationController{
Spec: api.ReplicationControllerSpec{
Replicas: 2,
Selector: map[string]string{},
Template: &validPodTemplate.Template,
},
},
)
}

func TestDelete(t *testing.T) {
ctx := api.NewDefaultContext()
storage, fakeClient := newStorage(t)
Expand Down
Loading

0 comments on commit d146545

Please sign in to comment.