Re-use defined endpoints for tests

This commit is contained in:
Edd Steel 2018-03-03 11:19:18 -08:00
parent 35c2083422
commit 413cb3d3b5
No known key found for this signature in database
GPG Key ID: 33620159D40385A0
1 changed files with 63 additions and 92 deletions

View File

@ -10,77 +10,19 @@ import (
"github.com/hashicorp/consul/logger" "github.com/hashicorp/consul/logger"
) )
var expectedEndpoints = []struct { // extra endpoints that should be tested, and their allowed methods
methods, uri string var extraTestEndpoints = map[string][]string{
}{ "/v1/query": []string{"GET", "POST"},
{"OPTIONS,PUT", "/v1/acl/bootstrap"}, "/v1/query/": []string{"GET", "PUT", "DELETE"},
{"OPTIONS,PUT", "/v1/acl/create"}, "/v1/query/xxx/execute": []string{"GET"},
{"OPTIONS,PUT", "/v1/acl/update"}, "/v1/query/xxx/explain": []string{"GET"},
{"OPTIONS,PUT", "/v1/acl/destroy/"}, }
{"OPTIONS,GET", "/v1/acl/info/"},
{"OPTIONS,PUT", "/v1/acl/clone/"}, // certain endpoints can't be unit tested.
{"OPTIONS,GET", "/v1/acl/list"}, func includePathInTest(path string) bool {
{"OPTIONS,GET", "/v1/acl/replication"}, var hanging = path == "/v1/status/peers" || path == "/v1/agent/monitor" || path == "/v1/agent/reload" // these hang
{"OPTIONS,PUT", "/v1/agent/token/"}, var custom = path == "/v1/query" || path == "/v1/query/" // these have custom logic
{"OPTIONS,GET", "/v1/agent/self"}, return !(hanging || custom)
{"OPTIONS,GET", "/v1/agent/members"},
{"OPTIONS,PUT", "/v1/agent/check/deregister/"},
{"OPTIONS,PUT", "/v1/agent/check/fail/"},
{"OPTIONS,PUT", "/v1/agent/check/pass/"},
{"OPTIONS,PUT", "/v1/agent/check/register"},
{"OPTIONS,PUT", "/v1/agent/check/update/"},
{"OPTIONS,PUT", "/v1/agent/check/warn/"},
{"OPTIONS,GET", "/v1/agent/checks"},
{"OPTIONS,PUT", "/v1/agent/force-leave/"},
{"OPTIONS,PUT", "/v1/agent/join/"},
{"OPTIONS,PUT", "/v1/agent/leave"},
{"OPTIONS,PUT", "/v1/agent/maintenance"},
{"OPTIONS,GET", "/v1/agent/metrics"},
// {"GET", "/v1/agent/monitor"}, // requires LogWriter. Hangs if LogWriter is provided
{"OPTIONS,PUT", "/v1/agent/reload"},
{"OPTIONS,PUT", "/v1/agent/service/deregister/"},
{"OPTIONS,PUT", "/v1/agent/service/maintenance/"},
{"OPTIONS,PUT", "/v1/agent/service/register"},
{"OPTIONS,GET", "/v1/agent/services"},
{"OPTIONS,GET", "/v1/catalog/datacenters"},
{"OPTIONS,PUT", "/v1/catalog/deregister"},
{"OPTIONS,GET", "/v1/catalog/node/"},
{"OPTIONS,GET", "/v1/catalog/nodes"},
{"OPTIONS,PUT", "/v1/catalog/register"},
{"OPTIONS,GET", "/v1/catalog/service/"},
{"OPTIONS,GET", "/v1/catalog/services"},
{"OPTIONS,GET", "/v1/coordinate/datacenters"},
{"OPTIONS,GET", "/v1/coordinate/nodes"},
{"OPTIONS,GET", "/v1/coordinate/node/"},
{"OPTIONS,PUT", "/v1/event/fire/"},
{"OPTIONS,GET", "/v1/event/list"},
{"OPTIONS,GET", "/v1/health/checks/"},
{"OPTIONS,GET", "/v1/health/node/"},
{"OPTIONS,GET", "/v1/health/service/"},
{"OPTIONS,GET", "/v1/health/state/"},
{"OPTIONS,GET", "/v1/internal/ui/node/"},
{"OPTIONS,GET", "/v1/internal/ui/nodes"},
{"OPTIONS,GET", "/v1/internal/ui/services"},
{"OPTIONS,GET,PUT,DELETE", "/v1/kv/"},
{"OPTIONS,GET,PUT", "/v1/operator/autopilot/configuration"},
{"OPTIONS,GET", "/v1/operator/autopilot/health"},
{"OPTIONS,GET,POST,PUT,DELETE", "/v1/operator/keyring"},
{"OPTIONS,GET", "/v1/operator/raft/configuration"},
{"OPTIONS,DELETE", "/v1/operator/raft/peer"},
{"OPTIONS,GET,POST", "/v1/query"},
{"OPTIONS,GET,PUT,DELETE", "/v1/query/"},
{"OPTIONS,GET", "/v1/query/xxx/execute"},
{"OPTIONS,GET", "/v1/query/xxx/explain"},
{"OPTIONS,PUT", "/v1/session/create"},
{"OPTIONS,PUT", "/v1/session/destroy/"},
{"OPTIONS,GET", "/v1/session/info/"},
{"OPTIONS,GET", "/v1/session/list"},
{"OPTIONS,GET", "/v1/session/node/"},
{"OPTIONS,PUT", "/v1/session/renew/"},
{"OPTIONS,GET,PUT", "/v1/snapshot"},
{"OPTIONS,GET", "/v1/status/leader"},
// {"GET", "/v1/status/peers"},// hangs
{"OPTIONS,PUT", "/v1/txn"},
} }
func TestHTTPAPI_MethodNotAllowed_OSS(t *testing.T) { func TestHTTPAPI_MethodNotAllowed_OSS(t *testing.T) {
@ -92,24 +34,43 @@ func TestHTTPAPI_MethodNotAllowed_OSS(t *testing.T) {
all := []string{"GET", "PUT", "POST", "DELETE", "HEAD", "OPTIONS"} all := []string{"GET", "PUT", "POST", "DELETE", "HEAD", "OPTIONS"}
client := http.Client{} client := http.Client{}
for _, tt := range expectedEndpoints { testMethodNotAllowed := func(method string, path string, allowedMethods []string) {
for _, m := range all { t.Run(method+" "+path, func(t *testing.T) {
t.Run(m+" "+tt.uri, func(t *testing.T) { uri := fmt.Sprintf("http://%s%s", a.HTTPAddr(), path)
uri := fmt.Sprintf("http://%s%s", a.HTTPAddr(), tt.uri) req, _ := http.NewRequest(method, uri, nil)
req, _ := http.NewRequest(m, uri, nil) resp, err := client.Do(req)
resp, err := client.Do(req) if err != nil {
if err != nil { t.Fatal("client.Do failed: ", err)
t.Fatal("client.Do failed: ", err) }
}
allowed := strings.Contains(tt.methods, m) allowed := method == "OPTIONS"
if allowed && resp.StatusCode == http.StatusMethodNotAllowed { for _, allowedMethod := range allowedMethods {
t.Fatalf("method allowed: got status code %d want any other code", resp.StatusCode) if allowedMethod == method {
allowed = true
break
} }
if !allowed && resp.StatusCode != http.StatusMethodNotAllowed { }
t.Fatalf("method not allowed: got status code %d want %d", resp.StatusCode, http.StatusMethodNotAllowed)
} if allowed && resp.StatusCode == http.StatusMethodNotAllowed {
}) t.Fatalf("method allowed: got status code %d want any other code", resp.StatusCode)
}
if !allowed && resp.StatusCode != http.StatusMethodNotAllowed {
t.Fatalf("method not allowed: got status code %d want %d", resp.StatusCode, http.StatusMethodNotAllowed)
}
})
}
for path, methods := range extraTestEndpoints {
for _, method := range all {
testMethodNotAllowed(method, path, methods)
}
}
for path, methods := range allowedMethods {
if includePathInTest(path) {
for _, method := range all {
testMethodNotAllowed(method, path, methods)
}
} }
} }
} }
@ -119,12 +80,13 @@ func TestHTTPAPI_OptionMethod_OSS(t *testing.T) {
a.Agent.LogWriter = logger.NewLogWriter(512) a.Agent.LogWriter = logger.NewLogWriter(512)
defer a.Shutdown() defer a.Shutdown()
for _, tt := range expectedEndpoints { testOptionMethod := func(path string, methods []string) {
t.Run("OPTIONS "+tt.uri, func(t *testing.T) { t.Run("OPTIONS "+path, func(t *testing.T) {
uri := fmt.Sprintf("http://%s%s", a.HTTPAddr(), tt.uri) uri := fmt.Sprintf("http://%s%s", a.HTTPAddr(), path)
req, _ := http.NewRequest("OPTIONS", uri, nil) req, _ := http.NewRequest("OPTIONS", uri, nil)
resp := httptest.NewRecorder() resp := httptest.NewRecorder()
a.srv.Handler.ServeHTTP(resp, req) a.srv.Handler.ServeHTTP(resp, req)
allMethods := append([]string{"OPTIONS"}, methods...)
if resp.Code != http.StatusOK { if resp.Code != http.StatusOK {
t.Fatalf("options request: got status code %d want %d", resp.Code, http.StatusOK) t.Fatalf("options request: got status code %d want %d", resp.Code, http.StatusOK)
@ -133,9 +95,18 @@ func TestHTTPAPI_OptionMethod_OSS(t *testing.T) {
optionsStr := resp.Header().Get("Allow") optionsStr := resp.Header().Get("Allow")
if optionsStr == "" { if optionsStr == "" {
t.Fatalf("options request: got empty 'Allow' header") t.Fatalf("options request: got empty 'Allow' header")
} else if optionsStr != tt.methods { } else if optionsStr != strings.Join(allMethods, ",") {
t.Fatalf("options request: got 'Allow' header value of %s want %s", optionsStr, tt.methods) t.Fatalf("options request: got 'Allow' header value of %s want %s", optionsStr, allMethods)
} }
}) })
} }
for path, methods := range extraTestEndpoints {
testOptionMethod(path, methods)
}
for path, methods := range allowedMethods {
if includePathInTest(path) {
testOptionMethod(path, methods)
}
}
} }