Hackaton 12: Add some unit tests, take 1 (#101457)
* tsdb/graphite: add happy path test for QueryData * infra/httpclient/httpclientprovider: add tests for RedirectLimitMiddleware
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user