Files
karma/proxy_test.go
Łukasz Mierzwa 129ffb7e17 fix(test): use httptest.newRequest instead of (incorrect) http.newRequest
httptest.newRequest is suppose to be used for testing request handing, http.newRequest is for preparing outgoing requests, this allows to fix cache key selection and increase test coverage
2018-08-21 09:35:49 +01:00

227 lines
6.9 KiB
Go

package main
import (
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/prymitive/unsee/internal/alertmanager"
httpmock "gopkg.in/jarcoal/httpmock.v1"
)
// httptest.NewRecorder() doesn't implement http.CloseNotifier
type closeNotifyingRecorder struct {
*httptest.ResponseRecorder
closed chan bool
}
func newCloseNotifyingRecorder() *closeNotifyingRecorder {
return &closeNotifyingRecorder{
httptest.NewRecorder(),
make(chan bool, 1),
}
}
func (c *closeNotifyingRecorder) CloseNotify() <-chan bool {
return c.closed
}
type proxyTest struct {
method string
localPath string
upstreamURI string
code int
response string
}
var proxyTests = []proxyTest{
// valid alertmanager and methods
{
method: "POST",
localPath: "/proxy/alertmanager/dummy/api/v1/silences",
upstreamURI: "http://localhost:9093/api/v1/silences",
code: 200,
response: "{\"status\":\"success\",\"data\":{\"silenceId\":\"d8a61ca8-ee2e-4076-999f-276f1e986bf3\"}}",
},
{
method: "DELETE",
localPath: "/proxy/alertmanager/dummy/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
upstreamURI: "http://localhost:9093/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
code: 200,
response: "{\"status\":\"success\"}",
},
// invalid alertmanager name
{
method: "POST",
localPath: "/proxy/alertmanager/INVALID/api/v1/silences",
upstreamURI: "",
code: 404,
response: "404 page not found",
},
{
method: "DELETE",
localPath: "/proxy/alertmanager/INVALID/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
upstreamURI: "http://localhost:9093/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
code: 404,
response: "404 page not found",
},
// valid alertmanager name, but invalid method
{
method: "GET",
localPath: "/proxy/alertmanager/dummy/api/v1/silences",
upstreamURI: "",
code: 404,
response: "404 page not found",
},
{
method: "GET",
localPath: "/proxy/alertmanager/dummy/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
upstreamURI: "http://localhost:9093/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
code: 404,
response: "404 page not found",
},
}
func TestProxy(t *testing.T) {
r := ginTestEngine()
am, err := alertmanager.NewAlertmanager(
"dummy",
"http://localhost:9093",
alertmanager.WithRequestTimeout(time.Second*5),
alertmanager.WithProxy(true),
)
if err != nil {
t.Error(err)
}
err = setupRouterProxyHandlers(r, am)
if err != nil {
t.Errorf("Failed to setup proxy for Alertmanager %s: %s", am.Name, err)
}
httpmock.Activate()
defer httpmock.DeactivateAndReset()
for _, testCase := range proxyTests {
httpmock.Reset()
if testCase.upstreamURI != "" {
httpmock.RegisterResponder(testCase.method, testCase.upstreamURI, httpmock.NewStringResponder(testCase.code, testCase.response))
}
req := httptest.NewRequest(testCase.method, testCase.localPath, nil)
resp := newCloseNotifyingRecorder()
r.ServeHTTP(resp, req)
if resp.Code != testCase.code {
t.Errorf("%s %s proxied to %s returned status %d while %d was expected",
testCase.method, testCase.localPath, testCase.upstreamURI, resp.Code, testCase.code)
}
body := resp.Body.String()
if body != testCase.response {
t.Errorf("%s %s proxied to %s returned content '%s' while '%s' was expected",
testCase.method, testCase.localPath, testCase.upstreamURI, body, testCase.response)
}
}
}
type proxyHeaderTest struct {
method string
localPath string
upstreamURI string
code int
alertmanagerURI string
alertmanagerHost string
authUser string
authPass string
}
var proxyHeaderTests = []proxyHeaderTest{
{
method: "POST",
localPath: "/proxy/alertmanager/dummy/api/v1/silences",
upstreamURI: "http://localhost:9093/api/v1/silences",
code: 200,
alertmanagerURI: "http://localhost:9093",
alertmanagerHost: "localhost:9093",
},
{
method: "POST",
localPath: "/proxy/alertmanager/dummy/api/v1/silences",
upstreamURI: "http://alertmanager.example.com/api/v1/silences",
code: 200,
alertmanagerURI: "http://alertmanager.example.com",
alertmanagerHost: "alertmanager.example.com",
},
{
method: "POST",
localPath: "/proxy/alertmanager/dummy/api/v1/silences",
upstreamURI: "http://alertmanager.example.com/api/v1/silences",
code: 200,
alertmanagerURI: "http://foo:bar@alertmanager.example.com",
alertmanagerHost: "alertmanager.example.com",
authUser: "foo",
authPass: "bar",
},
{
method: "POST",
localPath: "/proxy/alertmanager/dummy/api/v1/silences",
upstreamURI: "http://alertmanager.example.com/api/v1/silences",
code: 200,
alertmanagerURI: "http://foo@alertmanager.example.com",
alertmanagerHost: "alertmanager.example.com",
authUser: "foo",
authPass: "",
},
}
func TestProxyHeaders(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
for _, testCase := range proxyHeaderTests {
r := ginTestEngine()
am, err := alertmanager.NewAlertmanager(
"dummy",
testCase.alertmanagerURI,
alertmanager.WithRequestTimeout(time.Second*5),
alertmanager.WithProxy(true),
)
if err != nil {
t.Error(err)
}
err = setupRouterProxyHandlers(r, am)
if err != nil {
t.Errorf("Failed to setup proxy for Alertmanager %s: %s", am.Name, err)
}
httpmock.Reset()
httpmock.RegisterResponder(testCase.method, testCase.upstreamURI, func(req *http.Request) (*http.Response, error) {
if req.Host != testCase.alertmanagerHost {
t.Errorf("req.Host is '%s' while '%s' was expected", req.Host, testCase.alertmanagerHost)
}
if req.Header.Get("Host") != "" {
t.Errorf("req.Header.Host is '%s' while '%s' was expected", req.Header.Get("Host"), testCase.alertmanagerHost)
}
if testCase.authUser != "" || testCase.authPass != "" {
user, password, _ := req.BasicAuth()
if testCase.authUser != "" && testCase.authUser != user {
t.Errorf("%s %s proxied to %s was expected to have Basic Auth user '%s', got '%s'",
testCase.method, testCase.localPath, testCase.upstreamURI, testCase.authUser, user)
}
if testCase.authPass != "" && testCase.authPass != password {
t.Errorf("%s %s proxied to %s was expected to have Basic Auth password '%s', got '%s'",
testCase.method, testCase.localPath, testCase.upstreamURI, testCase.authPass, password)
}
}
return httpmock.NewStringResponse(testCase.code, "ok"), nil
})
req := httptest.NewRequest(testCase.method, testCase.localPath, nil)
resp := newCloseNotifyingRecorder()
r.ServeHTTP(resp, req)
if resp.Code != testCase.code {
t.Errorf("%s %s proxied to %s returned status %d while %d was expected",
testCase.method, testCase.localPath, testCase.upstreamURI, resp.Code, testCase.code)
}
}
}