From 82485986012510ab8a9afb83abb7dafa061fb038 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 5 Jun 2016 22:51:28 +0900 Subject: [PATCH] Add integration tests for nghttpx API endpoint --- integration-tests/nghttpx_http2_test.go | 112 ++++++++++++++++++++++++ integration-tests/server_tester.go | 26 ++++-- 2 files changed, 130 insertions(+), 8 deletions(-) diff --git a/integration-tests/nghttpx_http2_test.go b/integration-tests/nghttpx_http2_test.go index bb9d8b0e..e24375fe 100644 --- a/integration-tests/nghttpx_http2_test.go +++ b/integration-tests/nghttpx_http2_test.go @@ -2,6 +2,7 @@ package nghttp2 import ( "crypto/tls" + "encoding/json" "fmt" "golang.org/x/net/http2" "golang.org/x/net/http2/hpack" @@ -1843,3 +1844,114 @@ func TestH2H2RespPhaseReturn(t *testing.T) { t.Errorf("body = %v; want %v", got, want) } } + +// TestH2APIBackendReplace exercise backend/replace API endpoint +// routine for successful case. +func TestH2APIBackendReplace(t *testing.T) { + st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }, 3010) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2APIBackendReplace", + path: "/api/v1beta1/backend/replace", + method: "PUT", + body: []byte(`# comment +backend=127.0.0.1,3011 + +`), + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + if got, want := res.status, 200; got != want { + t.Errorf("res.status: %v; want %v", got, want) + } + + var apiResp APIResponse + err = json.Unmarshal(res.body, &apiResp) + if err != nil { + t.Fatalf("Error unmarshaling API response: %v", err) + } + if got, want := apiResp.Status, "Success"; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } + if got, want := apiResp.Code, 200; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } +} + +// TestH2APIBackendReplaceBadMethod exercise backend/replace API +// endpoint routine with bad method. +func TestH2APIBackendReplaceBadMethod(t *testing.T) { + st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }, 3010) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2APIBackendReplaceBadMethod", + path: "/api/v1beta1/backend/replace", + method: "GET", + body: []byte(`# comment +backend=127.0.0.1,3011 + +`), + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + if got, want := res.status, 405; got != want { + t.Errorf("res.status: %v; want %v", got, want) + } + + var apiResp APIResponse + err = json.Unmarshal(res.body, &apiResp) + if err != nil { + t.Fatalf("Error unmarshaling API response: %v", err) + } + if got, want := apiResp.Status, "Failure"; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } + if got, want := apiResp.Code, 405; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } +} + +// TestH2APINotFound exercise backend/replace API endpoint routine +// when API endpoint is not found. +func TestH2APINotFound(t *testing.T) { + st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }, 3010) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2APINotFound", + path: "/api/notfound", + method: "GET", + body: []byte(`# comment +backend=127.0.0.1,3011 + +`), + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + if got, want := res.status, 404; got != want { + t.Errorf("res.status: %v; want %v", got, want) + } + + var apiResp APIResponse + err = json.Unmarshal(res.body, &apiResp) + if err != nil { + t.Fatalf("Error unmarshaling API response: %v", err) + } + if got, want := apiResp.Status, "Failure"; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } + if got, want := apiResp.Code, 404; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } +} diff --git a/integration-tests/server_tester.go b/integration-tests/server_tester.go index 3cebc7e2..7111a094 100644 --- a/integration-tests/server_tester.go +++ b/integration-tests/server_tester.go @@ -66,27 +66,32 @@ type serverTester struct { // newServerTester creates test context for plain TCP frontend // connection. func newServerTester(args []string, t *testing.T, handler http.HandlerFunc) *serverTester { - return newServerTesterInternal(args, t, handler, false, nil) + return newServerTesterInternal(args, t, handler, false, serverPort, nil) +} + +func newServerTesterConnectPort(args []string, t *testing.T, handler http.HandlerFunc, port int) *serverTester { + return newServerTesterInternal(args, t, handler, false, port, nil) } func newServerTesterHandler(args []string, t *testing.T, handler http.Handler) *serverTester { - return newServerTesterInternal(args, t, handler, false, nil) + return newServerTesterInternal(args, t, handler, false, serverPort, nil) } // newServerTester creates test context for TLS frontend connection. func newServerTesterTLS(args []string, t *testing.T, handler http.HandlerFunc) *serverTester { - return newServerTesterInternal(args, t, handler, true, nil) + return newServerTesterInternal(args, t, handler, true, serverPort, nil) } // newServerTester creates test context for TLS frontend connection // with given clientConfig func newServerTesterTLSConfig(args []string, t *testing.T, handler http.HandlerFunc, clientConfig *tls.Config) *serverTester { - return newServerTesterInternal(args, t, handler, true, clientConfig) + return newServerTesterInternal(args, t, handler, true, serverPort, clientConfig) } // newServerTesterInternal creates test context. If frontendTLS is -// true, set up TLS frontend connection. -func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handler, frontendTLS bool, clientConfig *tls.Config) *serverTester { +// true, set up TLS frontend connection. connectPort is the server +// side port where client connection is made. +func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handler, frontendTLS bool, connectPort int, clientConfig *tls.Config) *serverTester { ts := httptest.NewUnstartedServer(handler) args := []string{} @@ -138,7 +143,7 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl args = append(args, fmt.Sprintf("-f127.0.0.1,%v;%v", serverPort, noTLS), b, "--errorlog-file="+logDir+"/log.txt", "-LINFO") - authority := fmt.Sprintf("127.0.0.1:%v", serverPort) + authority := fmt.Sprintf("127.0.0.1:%v", connectPort) st := &serverTester{ cmd: exec.Command(serverBin, args...), @@ -170,7 +175,7 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl tlsConfig = clientConfig } tlsConfig.InsecureSkipVerify = true - tlsConfig.NextProtos = []string{"h2-14", "spdy/3.1"} + tlsConfig.NextProtos = []string{"h2", "spdy/3.1"} conn, err = tls.Dial("tcp", authority, tlsConfig) } else { conn, err = net.Dial("tcp", authority) @@ -746,3 +751,8 @@ func cloneHeader(h http.Header) http.Header { } func noopHandler(w http.ResponseWriter, r *http.Request) {} + +type APIResponse struct { + Status string `json:"status,omitempty"` + Code int `json:"code,omitempty"` +}