From 3c0a736908ea9da48ec160f564f610d282d1f896 Mon Sep 17 00:00:00 2001 From: Joe Beda Date: Mon, 25 Aug 2014 15:10:01 -0700 Subject: [PATCH] Fix/expand kubecfg unit tests --- pkg/client/fake.go | 5 ++-- pkg/kubecfg/kubecfg_test.go | 46 ++++++++++++++++++++++++++++++++++--- pkg/runtime/helper.go | 18 +++++++++++++++ 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/pkg/client/fake.go b/pkg/client/fake.go index 136cb20acaf..5405255f34c 100644 --- a/pkg/client/fake.go +++ b/pkg/client/fake.go @@ -19,6 +19,7 @@ package client import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" + "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/version" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" ) @@ -43,7 +44,7 @@ type Fake struct { func (c *Fake) ListPods(selector labels.Selector) (api.PodList, error) { c.Actions = append(c.Actions, FakeAction{Action: "list-pods"}) - return c.Pods, nil + return *runtime.CopyOrDie(c.Pods).(*api.PodList), nil } func (c *Fake) GetPod(name string) (api.Pod, error) { @@ -73,7 +74,7 @@ func (c *Fake) ListReplicationControllers(selector labels.Selector) (api.Replica func (c *Fake) GetReplicationController(name string) (api.ReplicationController, error) { c.Actions = append(c.Actions, FakeAction{Action: "get-controller", Value: name}) - return c.Ctrl, nil + return *runtime.CopyOrDie(c.Ctrl).(*api.ReplicationController), nil } func (c *Fake) CreateReplicationController(controller api.ReplicationController) (api.ReplicationController, error) { diff --git a/pkg/kubecfg/kubecfg_test.go b/pkg/kubecfg/kubecfg_test.go index b08d2663cb8..32cddf70779 100644 --- a/pkg/kubecfg/kubecfg_test.go +++ b/pkg/kubecfg/kubecfg_test.go @@ -26,10 +26,11 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" + "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) func validateAction(expectedAction, actualAction client.FakeAction, t *testing.T) { - if expectedAction != actualAction { + if !reflect.DeepEqual(expectedAction, actualAction) { t.Errorf("Unexpected Action: %#v, expected: %#v", actualAction, expectedAction) } } @@ -43,7 +44,7 @@ func TestUpdateWithPods(t *testing.T) { }, }, } - Update("foo", &fakeClient, 0) + Update("foo", &fakeClient, 0, "") if len(fakeClient.Actions) != 5 { t.Errorf("Unexpected action list %#v", fakeClient.Actions) } @@ -57,7 +58,7 @@ func TestUpdateWithPods(t *testing.T) { func TestUpdateNoPods(t *testing.T) { fakeClient := client.Fake{} - Update("foo", &fakeClient, 0) + Update("foo", &fakeClient, 0, "") if len(fakeClient.Actions) != 2 { t.Errorf("Unexpected action list %#v", fakeClient.Actions) } @@ -65,6 +66,45 @@ func TestUpdateNoPods(t *testing.T) { validateAction(client.FakeAction{Action: "list-pods"}, fakeClient.Actions[1], t) } +func TestUpdateWithNewImage(t *testing.T) { + fakeClient := client.Fake{ + Pods: api.PodList{ + Items: []api.Pod{ + {JSONBase: api.JSONBase{ID: "pod-1"}}, + {JSONBase: api.JSONBase{ID: "pod-2"}}, + }, + }, + Ctrl: api.ReplicationController{ + DesiredState: api.ReplicationControllerState{ + PodTemplate: api.PodTemplate{ + DesiredState: api.PodState{ + Manifest: api.ContainerManifest{ + Containers: []api.Container{ + {Image: "fooImage:1"}, + }, + }, + }, + }, + }, + }, + } + Update("foo", &fakeClient, 0, "fooImage:2") + if len(fakeClient.Actions) != 6 { + t.Errorf("Unexpected action list %#v", fakeClient.Actions) + } + validateAction(client.FakeAction{Action: "get-controller", Value: "foo"}, fakeClient.Actions[0], t) + + newCtrl := *runtime.CopyOrDie(fakeClient.Ctrl).(*api.ReplicationController) + newCtrl.DesiredState.PodTemplate.DesiredState.Manifest.Containers[0].Image = "fooImage:2" + validateAction(client.FakeAction{Action: "update-controller", Value: newCtrl}, fakeClient.Actions[1], t) + + validateAction(client.FakeAction{Action: "list-pods"}, fakeClient.Actions[2], t) + // Update deletes the pods, it relies on the replication controller to replace them. + validateAction(client.FakeAction{Action: "delete-pod", Value: "pod-1"}, fakeClient.Actions[3], t) + validateAction(client.FakeAction{Action: "delete-pod", Value: "pod-2"}, fakeClient.Actions[4], t) + validateAction(client.FakeAction{Action: "list-pods"}, fakeClient.Actions[5], t) +} + func TestRunController(t *testing.T) { fakeClient := client.Fake{} name := "name" diff --git a/pkg/runtime/helper.go b/pkg/runtime/helper.go index c94a5a6ce41..ac195cd8c2c 100644 --- a/pkg/runtime/helper.go +++ b/pkg/runtime/helper.go @@ -194,6 +194,24 @@ func DecodeInto(data []byte, obj interface{}) error { return conversionScheme.DecodeInto(data, obj) } +// Does a deep copy of an API object. Useful mostly for tests. +// TODO(dbsmith): implement directly instead of via Encode/Decode +func Copy(obj interface{}) (interface{}, error) { + data, err := Encode(obj) + if err != nil { + return nil, err + } + return Decode(data) +} + +func CopyOrDie(obj interface{}) interface{} { + newObj, err := Copy(obj) + if err != nil { + panic(err) + } + return newObj +} + // metaInsertion implements conversion.MetaInsertionFactory, which lets the conversion // package figure out how to encode our object's types and versions. These fields are // located in our JSONBase.