mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 04:22:39 +08:00
190 lines
4.8 KiB
Go
190 lines
4.8 KiB
Go
package resource_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/promlib/models"
|
|
"github.com/grafana/grafana/pkg/promlib/resource"
|
|
)
|
|
|
|
type mockRoundTripper struct {
|
|
Response *http.Response
|
|
Err error
|
|
customRoundTrip func(req *http.Request) (*http.Response, error)
|
|
}
|
|
|
|
func (m *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
if m.customRoundTrip != nil {
|
|
return m.customRoundTrip(req)
|
|
}
|
|
return m.Response, m.Err
|
|
}
|
|
|
|
func setup() (*http.Client, backend.DataSourceInstanceSettings, log.Logger) {
|
|
// Mock HTTP Response
|
|
mockResponse := &http.Response{
|
|
StatusCode: 200,
|
|
Body: io.NopCloser(bytes.NewReader([]byte(`{"message": "success"}`))),
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
// Create a mock RoundTripper
|
|
mockTransport := &mockRoundTripper{
|
|
Response: mockResponse,
|
|
}
|
|
|
|
// Create a mock HTTP client using the mock RoundTripper
|
|
mockClient := &http.Client{
|
|
Transport: mockTransport,
|
|
}
|
|
|
|
settings := backend.DataSourceInstanceSettings{
|
|
ID: 1,
|
|
URL: "http://mock-server",
|
|
JSONData: []byte(`{}`),
|
|
}
|
|
|
|
logger := log.DefaultLogger
|
|
|
|
return mockClient, settings, logger
|
|
}
|
|
|
|
func TestNewResource(t *testing.T) {
|
|
mockClient, settings, logger := setup()
|
|
res, err := resource.New(mockClient, settings, logger)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, res)
|
|
}
|
|
|
|
func TestResource_Execute(t *testing.T) {
|
|
mockClient, settings, logger := setup()
|
|
res, err := resource.New(mockClient, settings, logger)
|
|
require.NoError(t, err)
|
|
|
|
req := &backend.CallResourceRequest{
|
|
URL: "/test",
|
|
}
|
|
ctx := context.Background()
|
|
|
|
resp, err := res.Execute(ctx, req)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, resp)
|
|
}
|
|
|
|
func TestResource_GetSuggestions(t *testing.T) {
|
|
mockClient, _, logger := setup()
|
|
settings := backend.DataSourceInstanceSettings{
|
|
ID: 1,
|
|
URL: "http://localhost:9090",
|
|
JSONData: []byte(`{"httpMethod": "GET"}`),
|
|
}
|
|
|
|
res, err := resource.New(mockClient, settings, logger)
|
|
require.NoError(t, err)
|
|
|
|
suggestionReq := resource.SuggestionRequest{
|
|
LabelName: "instance",
|
|
Queries: []string{"up"},
|
|
Start: "1609459200",
|
|
End: "1609462800",
|
|
Limit: 10,
|
|
}
|
|
|
|
body, err := json.Marshal(suggestionReq)
|
|
require.NoError(t, err)
|
|
|
|
req := &backend.CallResourceRequest{
|
|
Body: body,
|
|
}
|
|
ctx := context.Background()
|
|
|
|
resp, err := res.GetSuggestions(ctx, req)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, resp)
|
|
}
|
|
|
|
func TestResource_GetSuggestionsWithEmptyQueriesButFilters(t *testing.T) {
|
|
var capturedURL string
|
|
|
|
// Create a mock transport that captures the request URL
|
|
mockTransport := &mockRoundTripper{
|
|
Response: &http.Response{
|
|
StatusCode: 200,
|
|
Body: io.NopCloser(bytes.NewReader([]byte(`{"status":"success","data":[]}`))),
|
|
Header: make(http.Header),
|
|
},
|
|
customRoundTrip: func(req *http.Request) (*http.Response, error) {
|
|
capturedURL = req.URL.String()
|
|
return &http.Response{
|
|
StatusCode: 200,
|
|
Body: io.NopCloser(bytes.NewReader([]byte(`{"status":"success","data":[]}`))),
|
|
Header: make(http.Header),
|
|
}, nil
|
|
},
|
|
}
|
|
|
|
// Create a client with the mock transport
|
|
mockClient := &http.Client{
|
|
Transport: mockTransport,
|
|
}
|
|
|
|
settings := backend.DataSourceInstanceSettings{
|
|
ID: 1,
|
|
URL: "http://localhost:9090",
|
|
JSONData: []byte(`{"httpMethod": "GET"}`),
|
|
}
|
|
|
|
res, err := resource.New(mockClient, settings, log.DefaultLogger)
|
|
require.NoError(t, err)
|
|
|
|
// Create a request with empty queries but with filters
|
|
suggestionReq := resource.SuggestionRequest{
|
|
Queries: []string{}, // Empty queries
|
|
Scopes: []models.ScopeFilter{
|
|
{Key: "job", Operator: models.FilterOperatorEquals, Value: "testjob"},
|
|
},
|
|
AdhocFilters: []models.ScopeFilter{
|
|
{Key: "instance", Operator: models.FilterOperatorEquals, Value: "localhost:9090"},
|
|
},
|
|
}
|
|
|
|
body, err := json.Marshal(suggestionReq)
|
|
require.NoError(t, err)
|
|
|
|
req := &backend.CallResourceRequest{
|
|
Body: body,
|
|
}
|
|
ctx := context.Background()
|
|
|
|
resp, err := res.GetSuggestions(ctx, req)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, resp)
|
|
|
|
// Parse the captured URL to get the query parameters
|
|
parsedURL, err := url.Parse(capturedURL)
|
|
require.NoError(t, err)
|
|
|
|
// Get the match[] parameter
|
|
matchValues := parsedURL.Query()["match[]"]
|
|
require.Len(t, matchValues, 1, "Expected exactly one match[] parameter")
|
|
|
|
// The actual filter expression should match our expectation, regardless of URL encoding
|
|
decodedMatch, err := url.QueryUnescape(matchValues[0])
|
|
require.NoError(t, err)
|
|
|
|
// Check that both label matchers are present with their correct values
|
|
assert.Contains(t, decodedMatch, `job="testjob"`)
|
|
assert.Contains(t, decodedMatch, `instance="localhost:9090"`)
|
|
}
|