diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 4b08f34e23d..09cb467e1ae 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -17,6 +17,7 @@ package client import ( "encoding/json" + "net/http" "net/http/httptest" "net/url" "reflect" @@ -26,13 +27,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) -// TODO: This doesn't reduce typing enough to make it worth the less readable errors. Remove. -func expectNoError(t *testing.T, err error) { - if err != nil { - t.Errorf("Unexpected error: %#v", err) - } -} - // TODO: Move this to a common place, it's needed in multiple tests. var apiPath = "/api/v1beta1" @@ -41,63 +35,68 @@ func makeUrl(suffix string) string { } func TestListEmptyPods(t *testing.T) { - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: `{ "items": []}`, + c := &TestClient{ + Request: Request{Method: "GET", Path: "/pods"}, + Response: Response{StatusCode: 200, Body: api.PodList{}}, } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - podList, err := client.ListPods(nil) - fakeHandler.ValidateRequest(t, makeUrl("/pods"), "GET", nil) - if err != nil { - t.Errorf("Unexpected error in listing pods: %#v", err) - } - if len(podList.Items) != 0 { - t.Errorf("Unexpected items in pod list: %#v", podList) - } - testServer.Close() + podList, err := c.Setup().ListPods(nil) + c.Validate(t, podList, err) } func TestListPods(t *testing.T) { - expectedPodList := api.PodList{ - Items: []api.Pod{ - { - CurrentState: api.PodState{ - Status: "Foobar", - }, - Labels: map[string]string{ - "foo": "bar", - "name": "baz", + c := &TestClient{ + Request: Request{Method: "GET", Path: "/pods"}, + Response: Response{StatusCode: 200, + Body: api.PodList{ + Items: []api.Pod{ + { + CurrentState: api.PodState{ + Status: "Foobar", + }, + Labels: map[string]string{ + "foo": "bar", + "name": "baz", + }, + }, }, }, }, } - body, _ := json.Marshal(expectedPodList) - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: string(body), - } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - receivedPodList, err := client.ListPods(nil) - fakeHandler.ValidateRequest(t, makeUrl("/pods"), "GET", nil) - if err != nil { - t.Errorf("Unexpected error in listing pods: %#v", err) - } - if !reflect.DeepEqual(expectedPodList, receivedPodList) { - t.Errorf("Unexpected pod list: %#v\nvs.\n%#v", receivedPodList, expectedPodList) - } - testServer.Close() + receivedPodList, err := c.Setup().ListPods(nil) + c.Validate(t, receivedPodList, err) } func TestListPodsLabels(t *testing.T) { - expectedPodList := api.PodList{ - Items: []api.Pod{ - { + c := &TestClient{ + Request: Request{Method: "GET", Path: "/pods", Query: url.Values{"labels": []string{"foo=bar,name=baz"}}}, + Response: Response{ + StatusCode: 200, + Body: api.PodList{ + Items: []api.Pod{ + { + CurrentState: api.PodState{ + Status: "Foobar", + }, + Labels: map[string]string{ + "foo": "bar", + "name": "baz", + }, + }, + }, + }, + }, + } + selector := map[string]string{"foo": "bar", "name": "baz"} + receivedPodList, err := c.Setup().ListPods(selector) + c.Validate(t, receivedPodList, err) +} + +func TestGetPod(t *testing.T) { + c := &TestClient{ + Request: Request{Method: "GET", Path: "/pods/foo"}, + Response: Response{ + StatusCode: 200, + Body: api.Pod{ CurrentState: api.PodState{ Status: "Foobar", }, @@ -108,76 +107,17 @@ func TestListPodsLabels(t *testing.T) { }, }, } - body, _ := json.Marshal(expectedPodList) - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: string(body), - } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - selector := map[string]string{"foo": "bar", "name": "baz"} - receivedPodList, err := client.ListPods(selector) - fakeHandler.ValidateRequest(t, makeUrl("/pods"), "GET", nil) - selectorString := fakeHandler.RequestReceived.URL.Query().Get("labels") - selectorString, _ = url.QueryUnescape(selectorString) - parsedSelectorString := DecodeSelector(selectorString) - expectEqual(t, selector, parsedSelectorString) - if err != nil { - t.Errorf("Unexpected error in listing pods: %#v", err) - } - if !reflect.DeepEqual(expectedPodList, receivedPodList) { - t.Errorf("Unexpected pod list: %#v\nvs.\n%#v", receivedPodList, expectedPodList) - } - testServer.Close() -} - -func TestGetPod(t *testing.T) { - expectedPod := api.Pod{ - CurrentState: api.PodState{ - Status: "Foobar", - }, - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - } - body, _ := json.Marshal(expectedPod) - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: string(body), - } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - receivedPod, err := client.GetPod("foo") - fakeHandler.ValidateRequest(t, makeUrl("/pods/foo"), "GET", nil) - if err != nil { - t.Errorf("Unexpected error: %#v", err) - } - if !reflect.DeepEqual(expectedPod, receivedPod) { - t.Errorf("Received pod: %#v\n doesn't match expected pod: %#v", receivedPod, expectedPod) - } - testServer.Close() + receivedPod, err := c.Setup().GetPod("foo") + c.Validate(t, receivedPod, err) } func TestDeletePod(t *testing.T) { - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: `{"success": true}`, + c := &TestClient{ + Request: Request{Method: "DELETE", Path: "/pods/foo"}, + Response: Response{StatusCode: 200}, } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - err := client.DeletePod("foo") - fakeHandler.ValidateRequest(t, makeUrl("/pods/foo"), "DELETE", nil) - if err != nil { - t.Errorf("Unexpected error: %#v", err) - } - testServer.Close() + err := c.Setup().DeletePod("foo") + c.Validate(t, nil, err) } func TestCreatePod(t *testing.T) { @@ -190,24 +130,15 @@ func TestCreatePod(t *testing.T) { "name": "baz", }, } - body, _ := json.Marshal(requestPod) - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: string(body), + c := &TestClient{ + Request: Request{Method: "POST", Path: "/pods", Body: requestPod}, + Response: Response{ + StatusCode: 200, + Body: requestPod, + }, } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - receivedPod, err := client.CreatePod(requestPod) - fakeHandler.ValidateRequest(t, makeUrl("/pods"), "POST", nil) - if err != nil { - t.Errorf("Unexpected error: %#v", err) - } - if !reflect.DeepEqual(requestPod, receivedPod) { - t.Errorf("Received pod: %#v\n doesn't match expected pod: %#v", receivedPod, requestPod) - } - testServer.Close() + receivedPod, err := c.Setup().CreatePod(requestPod) + c.Validate(t, receivedPod, err) } func TestUpdatePod(t *testing.T) { @@ -221,144 +152,232 @@ func TestUpdatePod(t *testing.T) { "name": "baz", }, } - body, _ := json.Marshal(requestPod) - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: string(body), - } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - receivedPod, err := client.UpdatePod(requestPod) - fakeHandler.ValidateRequest(t, makeUrl("/pods/foo"), "PUT", nil) - if err != nil { - t.Errorf("Unexpected error: %#v", err) - } - expectEqual(t, requestPod, receivedPod) - testServer.Close() -} - -func expectEqual(t *testing.T, expected, observed interface{}) { - if !reflect.DeepEqual(expected, observed) { - t.Errorf("Unexpected inequality. Expected: %#v Observed: %#v", expected, observed) + c := &TestClient{ + Request: Request{Method: "PUT", Path: "/pods/foo"}, + Response: Response{StatusCode: 200, Body: requestPod}, } + receivedPod, err := c.Setup().UpdatePod(requestPod) + c.Validate(t, receivedPod, err) } func TestGetController(t *testing.T) { - expectedController := api.ReplicationController{ - JSONBase: api.JSONBase{ - ID: "foo", - }, - DesiredState: api.ReplicationControllerState{ - Replicas: 2, - }, - Labels: map[string]string{ - "foo": "bar", - "name": "baz", + c := &TestClient{ + Request: Request{Method: "GET", Path: "/replicationControllers/foo"}, + Response: Response{ + StatusCode: 200, + Body: api.ReplicationController{ + JSONBase: api.JSONBase{ + ID: "foo", + }, + DesiredState: api.ReplicationControllerState{ + Replicas: 2, + }, + Labels: map[string]string{ + "foo": "bar", + "name": "baz", + }, + }, }, } - body, _ := json.Marshal(expectedController) - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: string(body), - } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - receivedController, err := client.GetReplicationController("foo") - expectNoError(t, err) - if !reflect.DeepEqual(expectedController, receivedController) { - t.Errorf("Unexpected controller, expected: %#v, received %#v", expectedController, receivedController) - } - fakeHandler.ValidateRequest(t, makeUrl("/replicationControllers/foo"), "GET", nil) - testServer.Close() + receivedController, err := c.Setup().GetReplicationController("foo") + c.Validate(t, receivedController, err) } func TestUpdateController(t *testing.T) { - expectedController := api.ReplicationController{ + requestController := api.ReplicationController{ JSONBase: api.JSONBase{ ID: "foo", }, - DesiredState: api.ReplicationControllerState{ - Replicas: 2, - }, - Labels: map[string]string{ - "foo": "bar", - "name": "baz", + } + c := &TestClient{ + Request: Request{Method: "PUT", Path: "/replicationControllers/foo"}, + Response: Response{ + StatusCode: 200, + Body: api.ReplicationController{ + JSONBase: api.JSONBase{ + ID: "foo", + }, + DesiredState: api.ReplicationControllerState{ + Replicas: 2, + }, + Labels: map[string]string{ + "foo": "bar", + "name": "baz", + }, + }, }, } - body, _ := json.Marshal(expectedController) - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: string(body), - } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - receivedController, err := client.UpdateReplicationController(api.ReplicationController{ - JSONBase: api.JSONBase{ - ID: "foo", - }, - }) - expectNoError(t, err) - if !reflect.DeepEqual(expectedController, receivedController) { - t.Errorf("Unexpected controller, expected: %#v, received %#v", expectedController, receivedController) - } - fakeHandler.ValidateRequest(t, makeUrl("/replicationControllers/foo"), "PUT", nil) - testServer.Close() + receivedController, err := c.Setup().UpdateReplicationController(requestController) + c.Validate(t, receivedController, err) } func TestDeleteController(t *testing.T) { - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: `{"success": true}`, + c := &TestClient{ + Request: Request{Method: "DELETE", Path: "/replicationControllers/foo"}, + Response: Response{StatusCode: 200}, } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - err := client.DeleteReplicationController("foo") - fakeHandler.ValidateRequest(t, makeUrl("/replicationControllers/foo"), "DELETE", nil) - if err != nil { - t.Errorf("Unexpected error: %#v", err) - } - testServer.Close() + err := c.Setup().DeleteReplicationController("foo") + c.Validate(t, nil, err) } func TestCreateController(t *testing.T) { - expectedController := api.ReplicationController{ + requestController := api.ReplicationController{ JSONBase: api.JSONBase{ ID: "foo", }, - DesiredState: api.ReplicationControllerState{ - Replicas: 2, - }, - Labels: map[string]string{ - "foo": "bar", - "name": "baz", + } + c := &TestClient{ + Request: Request{Method: "POST", Path: "/replicationControllers", Body: requestController}, + Response: Response{ + StatusCode: 200, + Body: api.ReplicationController{ + JSONBase: api.JSONBase{ + ID: "foo", + }, + DesiredState: api.ReplicationControllerState{ + Replicas: 2, + }, + Labels: map[string]string{ + "foo": "bar", + "name": "baz", + }, + }, }, } - body, _ := json.Marshal(expectedController) - fakeHandler := util.FakeHandler{ - StatusCode: 200, - ResponseBody: string(body), - } - testServer := httptest.NewTLSServer(&fakeHandler) - client := Client{ - Host: testServer.URL, - } - receivedController, err := client.CreateReplicationController(api.ReplicationController{ - JSONBase: api.JSONBase{ - ID: "foo", - }, - }) - expectNoError(t, err) - if !reflect.DeepEqual(expectedController, receivedController) { - t.Errorf("Unexpected controller, expected: %#v, received %#v", expectedController, receivedController) - } - fakeHandler.ValidateRequest(t, makeUrl("/replicationControllers"), "POST", nil) - testServer.Close() + receivedController, err := c.Setup().CreateReplicationController(requestController) + c.Validate(t, receivedController, err) +} + +func body(obj interface{}, raw *string) *string { + if obj != nil { + bs, _ := json.Marshal(obj) + body := string(bs) + return &body + } + return raw +} + +type Request struct { + Method string + Path string + Header string + Query url.Values + Body interface{} + RawBody *string +} + +type Response struct { + StatusCode int + Body interface{} + RawBody *string +} + +type TestClient struct { + *Client + Request Request + Response Response + Error bool + server *httptest.Server + handler *util.FakeHandler + Target interface{} +} + +func (c *TestClient) Setup() *TestClient { + c.handler = &util.FakeHandler{ + StatusCode: c.Response.StatusCode, + } + if responseBody := body(c.Response.Body, c.Response.RawBody); responseBody != nil { + c.handler.ResponseBody = *responseBody + } + c.server = httptest.NewTLSServer(c.handler) + if c.Client == nil { + c.Client = &Client{} + } + c.Client.Host = c.server.URL + return c +} + +func (c *TestClient) Validate(t *testing.T, received interface{}, err error) { + defer c.server.Close() + + if c.Error { + if err == nil { + t.Errorf("error expeced for %#v, got none", c.Request) + } + return + } + if err != nil { + t.Errorf("no error expected for %#v, got: %v", c.Request, err) + } + + requestBody := body(c.Request.Body, c.Request.RawBody) + c.handler.ValidateRequest(t, makeUrl(c.Request.Path), c.Request.Method, requestBody) + if expected, received := c.Request.Query.Encode(), c.handler.RequestReceived.URL.Query().Encode(); expected != received { + t.Errorf("bad query for request %#v: expected %s, got %s", c.Request, expected, received) + } + if c.Request.Header != "" { + if c.handler.RequestReceived.Header.Get(c.Request.Header) == "" { + t.Errorf("header %q not found in request %#v", c.Request.Header, c.handler.RequestReceived) + } + } + + if expected, received := requestBody, c.handler.RequestBody; expected != nil && *expected != received { + t.Errorf("bad body for request %#v: expected %s, got %s", c.Request, expected, received) + } + + if c.Response.Body != nil && !reflect.DeepEqual(c.Response.Body, received) { + t.Errorf("bad response for request %#v: expeced %s, got %s", c.Request, c.Response.Body, received) + } +} + +func TestGetService(t *testing.T) { + c := &TestClient{ + Request: Request{Method: "GET", Path: "/services/1"}, + Response: Response{StatusCode: 200, Body: &api.Service{JSONBase: api.JSONBase{ID: "service-1"}}}, + } + response, err := c.Setup().GetService("1") + c.Validate(t, &response, err) +} + +func TestCreateService(t *testing.T) { + c := (&TestClient{ + Request: Request{Method: "POST", Path: "/services", Body: &api.Service{JSONBase: api.JSONBase{ID: "service-1"}}}, + Response: Response{StatusCode: 200, Body: &api.Service{JSONBase: api.JSONBase{ID: "service-1"}}}, + }).Setup() + response, err := c.Setup().CreateService(api.Service{JSONBase: api.JSONBase{ID: "service-1"}}) + c.Validate(t, &response, err) +} + +func TestUpdateService(t *testing.T) { + c := &TestClient{ + Request: Request{Method: "PUT", Path: "/services/service-1", Body: &api.Service{JSONBase: api.JSONBase{ID: "service-1"}}}, + Response: Response{StatusCode: 200, Body: &api.Service{JSONBase: api.JSONBase{ID: "service-1"}}}, + } + response, err := c.Setup().UpdateService(api.Service{JSONBase: api.JSONBase{ID: "service-1"}}) + c.Validate(t, &response, err) +} + +func TestDeleteService(t *testing.T) { + c := &TestClient{ + Request: Request{Method: "DELETE", Path: "/services/1"}, + Response: Response{StatusCode: 200}, + } + err := c.Setup().DeleteService("1") + c.Validate(t, nil, err) +} + +func TestMakeRequest(t *testing.T) { + testClients := []TestClient{ + {Request: Request{Method: "GET", Path: "/good"}, Response: Response{StatusCode: 200}}, + {Request: Request{Method: "GET", Path: "/bad%ZZ"}, Error: true}, + {Client: &Client{Auth: &AuthInfo{"foo", "bar"}}, Request: Request{Method: "GET", Path: "/auth", Header: "Authorization"}, Response: Response{StatusCode: 200}}, + {Client: &Client{httpClient: http.DefaultClient}, Request: Request{Method: "GET", Path: "/nocertificate"}, Error: true}, + {Request: Request{Method: "GET", Path: "/error"}, Response: Response{StatusCode: 500}, Error: true}, + {Request: Request{Method: "POST", Path: "/faildecode"}, Response: Response{StatusCode: 200, Body: "aaaaa"}, Target: &struct{}{}, Error: true}, + {Request: Request{Method: "GET", Path: "/failread"}, Response: Response{StatusCode: 200, Body: "aaaaa"}, Target: &struct{}{}, Error: true}, + } + for _, c := range testClients { + response, err := c.Setup().rawRequest(c.Request.Method, c.Request.Path[1:], nil, c.Target) + c.Validate(t, response, err) + } } diff --git a/pkg/client/container_info_test.go b/pkg/client/container_info_test.go index 3dfc0f7bedd..e6bc28ba2e9 100644 --- a/pkg/client/container_info_test.go +++ b/pkg/client/container_info_test.go @@ -27,6 +27,13 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) +// TODO: This doesn't reduce typing enough to make it worth the less readable errors. Remove. +func expectNoError(t *testing.T, err error) { + if err != nil { + t.Errorf("Unexpected error: %#v", err) + } +} + func TestHTTPContainerInfo(t *testing.T) { body := `{"items":[]}` fakeHandler := util.FakeHandler{ diff --git a/pkg/util/fake_handler.go b/pkg/util/fake_handler.go index 94936a69993..6ca4a3fabf5 100644 --- a/pkg/util/fake_handler.go +++ b/pkg/util/fake_handler.go @@ -54,10 +54,10 @@ func (f *FakeHandler) ServeHTTP(response http.ResponseWriter, request *http.Requ func (f FakeHandler) ValidateRequest(t TestInterface, expectedPath, expectedMethod string, body *string) { if f.RequestReceived.URL.Path != expectedPath { - t.Errorf("Unexpected request path: %s", f.RequestReceived.URL.Path) + t.Errorf("Unexpected request path for request %#v, received: %q, expected: %q", f.RequestReceived, f.RequestReceived.URL.Path, expectedPath) } if f.RequestReceived.Method != expectedMethod { - t.Errorf("Unexpected method: %s", f.RequestReceived.Method) + t.Errorf("Unexpected method: %q, expected: %q", f.RequestReceived.Method, expectedMethod) } if body != nil { if *body != f.RequestBody {