Hackaton 12: Add some unit tests, take 1 (#101457)

* tsdb/graphite: add happy path test for QueryData

* infra/httpclient/httpclientprovider: add tests for RedirectLimitMiddleware
pull/101469/head
Matheus Macabu 4 months ago committed by GitHub
parent fc6f841942
commit 9eaaf95701
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 117
      pkg/infra/httpclient/httpclientprovider/host_redirect_validation_middleware_test.go
  2. 73
      pkg/tsdb/graphite/graphite_test.go

@ -0,0 +1,117 @@
package httpclientprovider
import (
"errors"
"net/http"
"net/http/httptest"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/stretchr/testify/require"
)
func TestRedirectLimitMiddleware(t *testing.T) {
t.Parallel()
t.Run("when the server responds with a status code 3xx", func(t *testing.T) {
t.Parallel()
t.Run("but there is no Location header in the response, then the response is not validated", func(t *testing.T) {
t.Parallel()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusTemporaryRedirect)
}))
t.Cleanup(server.Close)
mw := RedirectLimitMiddleware(&fakeValidator{err: errors.New("this wont be called")})
rt := mw.CreateMiddleware(httpclient.Options{}, http.DefaultTransport)
require.NotNil(t, rt)
middlewareName, ok := mw.(httpclient.MiddlewareName)
require.True(t, ok)
require.Equal(t, HostRedirectValidationMiddlewareName, middlewareName.MiddlewareName())
req, err := http.NewRequest(http.MethodGet, server.URL, nil)
require.NoError(t, err)
res, err := rt.RoundTrip(req)
require.NoError(t, err)
require.NotNil(t, res)
if res.Body != nil {
require.NoError(t, res.Body.Close())
}
})
t.Run("and there is a Location header in the response", func(t *testing.T) {
t.Parallel()
t.Run("but the validation function fails, it returns the validation error", func(t *testing.T) {
t.Parallel()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "http://www.example.com")
w.WriteHeader(http.StatusTemporaryRedirect)
}))
t.Cleanup(server.Close)
fakeErr := errors.New("fake error")
mw := RedirectLimitMiddleware(&fakeValidator{err: fakeErr})
rt := mw.CreateMiddleware(httpclient.Options{}, http.DefaultTransport)
require.NotNil(t, rt)
middlewareName, ok := mw.(httpclient.MiddlewareName)
require.True(t, ok)
require.Equal(t, HostRedirectValidationMiddlewareName, middlewareName.MiddlewareName())
req, err := http.NewRequest(http.MethodGet, server.URL, nil)
require.NoError(t, err)
res, err := rt.RoundTrip(req)
require.ErrorIs(t, err, fakeErr)
require.Nil(t, res)
if res != nil && res.Body != nil {
require.NoError(t, res.Body.Close())
}
})
t.Run("and the validation function succeeds, it returns the response", func(t *testing.T) {
t.Parallel()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "http://www.example.com")
w.WriteHeader(http.StatusTemporaryRedirect)
}))
t.Cleanup(server.Close)
mw := RedirectLimitMiddleware(&fakeValidator{})
rt := mw.CreateMiddleware(httpclient.Options{}, http.DefaultTransport)
require.NotNil(t, rt)
middlewareName, ok := mw.(httpclient.MiddlewareName)
require.True(t, ok)
require.Equal(t, HostRedirectValidationMiddlewareName, middlewareName.MiddlewareName())
req, err := http.NewRequest(http.MethodGet, server.URL, nil)
require.NoError(t, err)
res, err := rt.RoundTrip(req)
require.NoError(t, err)
require.NotNil(t, res)
if res.Body != nil {
require.NoError(t, res.Body.Close())
}
})
})
})
}
type fakeValidator struct {
err error
}
func (v *fakeValidator) Validate(_ string) error { return v.err }

@ -6,18 +6,20 @@ import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/tracing"
)
func TestFixIntervalFormat(t *testing.T) {
@ -141,14 +143,71 @@ func TestProcessQueries(t *testing.T) {
},
}
service.im = fakeInstanceManager{}
service := ProvideService(httpclient.NewProvider(), tracing.NewNoopTracerService())
rsp, err := service.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
ID: 0,
URL: "http://localhost",
},
},
Queries: queries,
})
assert.NoError(t, err)
expectedResponse := backend.ErrDataResponseWithSource(400, backend.ErrorSourceDownstream, "no query target found for the alert rule")
assert.Equal(t, expectedResponse, rsp.Responses["A"])
})
t.Run("QueryData with no queries returns an error", func(t *testing.T) {
service := &Service{}
rsp, err := service.QueryData(context.Background(), &backend.QueryDataRequest{})
assert.Nil(t, rsp)
assert.Error(t, err)
})
t.Run("QueryData happy path with service provider and plugin context", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`[
{
"target": "target A",
"tags": { "fooTag": "fooValue", "barTag": "barValue", "int": 100, "float": 3.14 },
"datapoints": [[50, 1], [null, 2], [100, 3]]
}
]`))
}))
t.Cleanup(server.Close)
service := ProvideService(httpclient.NewProvider(), tracing.NewNoopTracerService())
queries := []backend.DataQuery{
{
RefID: "A",
JSON: []byte(`{
"target": "app.grafana.*.dashboards.views.1M.count"
}`),
},
{
RefID: "B",
JSON: []byte(`{
"query": "app.grafana.*.dashboards.views.1M.count"
}`),
},
}
rsp, err := service.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
ID: 0,
URL: server.URL,
},
},
Queries: queries,
})
assert.NoError(t, err)
assert.NotNil(t, rsp)
})
}
func TestConvertResponses(t *testing.T) {
@ -289,13 +348,3 @@ func TestConvertResponses(t *testing.T) {
require.Error(t, err)
})
}
type fakeInstanceManager struct{}
func (f fakeInstanceManager) Get(_ context.Context, _ backend.PluginContext) (instancemgmt.Instance, error) {
return datasourceInfo{}, nil
}
func (f fakeInstanceManager) Do(_ context.Context, _ backend.PluginContext, _ instancemgmt.InstanceCallbackFunc) error {
return nil
}

Loading…
Cancel
Save