Files
grafana-zabbix/pkg/zabbix_api_test.go
2020-01-14 17:42:12 +03:00

446 lines
16 KiB
Go

package main
import (
"bytes"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"testing"
"time"
simplejson "github.com/bitly/go-simplejson"
"github.com/grafana/grafana_plugin_model/go/datasource"
hclog "github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
type RoundTripFunc func(req *http.Request) *http.Response
func (f RoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
return f(req), nil
}
//NewTestClient returns *http.Client with Transport replaced to avoid making real calls
func NewTestClient(fn RoundTripFunc) *http.Client {
return &http.Client{
Transport: RoundTripFunc(fn),
}
}
var basicDatasourceInfo = &datasource.DatasourceInfo{
Id: 1,
Name: "TestDatasource",
Url: "http://zabbix.org/zabbix",
JsonData: `{"username":"username", "password":"password"}}`,
}
func mockDataSourceRequest(modelJSON string) *datasource.DatasourceRequest {
return &datasource.DatasourceRequest{
Datasource: basicDatasourceInfo,
Queries: []*datasource.Query{
&datasource.Query{
ModelJson: modelJSON,
},
},
}
}
func mockZabbixDataSource(body string, statusCode int) ZabbixDatasource {
apiUrl, _ := url.Parse(basicDatasourceInfo.Url)
return ZabbixDatasource{
url: apiUrl,
dsInfo: basicDatasourceInfo,
queryCache: NewCache(10*time.Minute, 10*time.Minute),
httpClient: NewTestClient(func(req *http.Request) *http.Response {
return &http.Response{
StatusCode: statusCode,
Body: ioutil.NopCloser(bytes.NewBufferString(body)),
Header: make(http.Header),
}
}),
authToken: "sampleAuthToken",
logger: hclog.Default(),
}
}
func TestZabbixAPIQuery(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
resp, err := zabbixDatasource.ZabbixAPIQuery(context.Background(), mockDataSourceRequest(`{"target":{"method":"Method","params":{"param1" : "Param1"}}}`))
assert.Equal(t, "\"sampleResult\"", resp.GetResults()[0].GetMetaJson())
assert.Equal(t, "zabbixAPI", resp.GetResults()[0].GetRefId())
assert.Nil(t, err)
}
func TestZabbixAPIQueryEmptyQuery(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
resp, err := zabbixDatasource.ZabbixAPIQuery(context.Background(), mockDataSourceRequest(``))
assert.Nil(t, resp)
assert.NotNil(t, err)
}
func TestZabbixAPIQueryNoQueries(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
basicDatasourceRequest := &datasource.DatasourceRequest{
Datasource: &datasource.DatasourceInfo{
Id: 1,
Name: "TestDatasource",
},
}
resp, err := zabbixDatasource.ZabbixAPIQuery(context.Background(), basicDatasourceRequest)
assert.Nil(t, resp)
assert.Equal(t, "At least one query should be provided", err.Error())
}
func TestZabbixAPIQueryError(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 500)
resp, err := zabbixDatasource.ZabbixAPIQuery(context.Background(), mockDataSourceRequest(`{"target":{"method":"Method","params":{"param1" : "Param1"}}}`))
assert.Nil(t, resp)
assert.Equal(t, "ZabbixAPIQuery is not implemented yet", err.Error())
}
func TestLogin(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
resp, err := zabbixDatasource.login(context.Background(), "username", "password")
assert.Equal(t, "sampleResult", resp)
assert.Nil(t, err)
}
func TestLoginError(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 500)
resp, err := zabbixDatasource.login(context.Background(), "username", "password")
assert.Equal(t, "", resp)
assert.NotNil(t, err)
}
func TestLoginWithDs(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
err := zabbixDatasource.loginWithDs(context.Background())
assert.Equal(t, "sampleResult", zabbixDatasource.authToken)
assert.Nil(t, err)
}
func TestLoginWithDsError(t *testing.T) {
errResponse := `{"error":{"code":-32500,"message":"Application error.","data":"Login name or password is incorrect."}}`
zabbixDatasource := mockZabbixDataSource(errResponse, 200)
err := zabbixDatasource.loginWithDs(context.Background())
assert.Equal(t, "", zabbixDatasource.authToken)
assert.NotNil(t, err)
}
func TestZabbixRequest(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
resp, err := zabbixDatasource.ZabbixRequest(context.Background(), "method", ZabbixAPIParams{})
assert.Equal(t, "sampleResult", resp.MustString())
assert.Nil(t, err)
}
func TestZabbixRequestWithNoAuthToken(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"auth"}`, 200)
resp, err := zabbixDatasource.ZabbixRequest(context.Background(), "method", ZabbixAPIParams{})
assert.Equal(t, "auth", resp.MustString())
assert.Nil(t, err)
}
func TestZabbixRequestError(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 500)
resp, err := zabbixDatasource.ZabbixRequest(context.Background(), "method", ZabbixAPIParams{})
assert.Nil(t, resp)
assert.NotNil(t, err)
}
func TestZabbixAPIRequest(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
resp, err := zabbixDatasource.ZabbixAPIRequest(context.Background(), "item.get", ZabbixAPIParams{}, "auth")
assert.Equal(t, "sampleResult", resp.MustString())
assert.Nil(t, err)
}
func TestZabbixAPIRequestError(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 500)
resp, err := zabbixDatasource.ZabbixAPIRequest(context.Background(), "item.get", ZabbixAPIParams{}, "auth")
assert.Nil(t, resp)
assert.NotNil(t, err)
}
func TestTestConnection(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
resp, err := zabbixDatasource.TestConnection(context.Background(), mockDataSourceRequest(``))
assert.Equal(t, "{\"zabbixVersion\":\"sampleResult\",\"dbConnectorStatus\":null}", resp.Results[0].GetMetaJson())
assert.Nil(t, err)
}
func TestTestConnectionError(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 500)
resp, err := zabbixDatasource.TestConnection(context.Background(), mockDataSourceRequest(``))
assert.Equal(t, "", resp.Results[0].GetMetaJson())
assert.NotNil(t, resp.Results[0].GetError())
assert.Nil(t, err)
}
func TestIsNotAuthorized(t *testing.T) {
testPositive := isNotAuthorized("Not authorised.")
assert.True(t, testPositive)
testNegative := isNotAuthorized("testNegative")
assert.False(t, testNegative)
}
func TestHandleAPIResult(t *testing.T) {
expectedResponse, err := handleAPIResult([]byte(`{"result":"sampleResult"}`))
assert.Equal(t, "sampleResult", expectedResponse.MustString())
assert.Nil(t, err)
}
func TestHandleAPIResultFormatError(t *testing.T) {
expectedResponse, err := handleAPIResult([]byte(`{"result"::"sampleResult"}`))
assert.NotNil(t, err)
assert.Nil(t, expectedResponse)
}
func TestHandleAPIResultError(t *testing.T) {
expectedResponse, err := handleAPIResult([]byte(`{"result":"sampleResult", "error":{"message":"Message", "data":"Data"}}`))
assert.Equal(t, "Message Data", err.Error())
assert.Nil(t, expectedResponse)
}
func TestGetAllGroups(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"groupid": "46489126", "name": "name1"},{"groupid": "46489127", "name":"name2"}]}`, 200)
resp, err := zabbixDatasource.getAllGroups(context.Background(), basicDatasourceInfo)
assert.Equal(t, "46489126", resp.MustArray()[0].(map[string]interface{})["groupid"])
assert.Equal(t, "46489127", resp.MustArray()[1].(map[string]interface{})["groupid"])
assert.Nil(t, err)
}
func TestGetAllHosts(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"hostid": "46489126", "name": "hostname1"},{"hostid": "46489127", "name":"hostname2"}]}`, 200)
resp, err := zabbixDatasource.getAllHosts(context.Background(), basicDatasourceInfo, []string{"46489127", "46489127"})
assert.Equal(t, "46489126", resp.MustArray()[0].(map[string]interface{})["hostid"])
assert.Equal(t, "46489127", resp.MustArray()[1].(map[string]interface{})["hostid"])
assert.Nil(t, err)
}
func TestGetAllApps(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"applicationid": "46489126", "name": "hostname1"},{"applicationid": "46489127", "name":"hostname2"}]}`, 200)
resp, err := zabbixDatasource.getAllApps(context.Background(), basicDatasourceInfo, []string{"46489127", "46489127"})
assert.Equal(t, "46489126", resp.MustArray()[0].(map[string]interface{})["applicationid"])
assert.Equal(t, "46489127", resp.MustArray()[1].(map[string]interface{})["applicationid"])
assert.Nil(t, err)
}
func TestGetAllItems(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"itemid": "46489126", "name": "hostname1"},{"itemid": "46489127", "name":"hostname2"}]}`, 200)
resp, err := zabbixDatasource.getAllItems(context.Background(), basicDatasourceInfo, []string{"46489127", "46489127"}, []string{"7947934", "9182763"}, "num")
assert.Equal(t, "46489126", resp.MustArray()[0].(map[string]interface{})["itemid"])
assert.Equal(t, "46489127", resp.MustArray()[1].(map[string]interface{})["itemid"])
assert.Nil(t, err)
}
func TestGetGroups(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"groupid": "46489126", "name": "name1"},{"groupid": "46489127", "name":"name2"}]}`, 200)
resp, err := zabbixDatasource.getGroups(context.Background(), basicDatasourceInfo, "name1")
assert.Equal(t, "46489126", resp[0]["groupid"])
assert.Equal(t, "name1", resp[0]["name"])
assert.Nil(t, err)
}
func TestGetGroupsError(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"groupid": "46489126", "name": "name1"},{"groupid": "46489127", "name":"name2"}]}`, 500)
resp, err := zabbixDatasource.getGroups(context.Background(), basicDatasourceInfo, "name1")
assert.Nil(t, resp)
assert.NotNil(t, err)
}
func TestGetHosts(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"groupid": "46489126", "hostid": "7468763", "name": "hostname1"},{"groupid": "46489127","hostid": "846586", "name":"hostname2"}]}`, 200)
resp, err := zabbixDatasource.getHosts(context.Background(), basicDatasourceInfo, "nam", "hostname1")
assert.Equal(t, "7468763", resp[0]["hostid"])
assert.Equal(t, "hostname1", resp[0]["name"])
assert.Nil(t, err)
}
func TestGetHostsError(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"groupid": "46489126", "hostid": "7468763", "name": "hostname1"},{"groupid": "46489127","hostid": "846586", "name":"hostname2"}]}`, 500)
resp, err := zabbixDatasource.getHosts(context.Background(), basicDatasourceInfo, "nam", "hostna")
assert.Nil(t, resp)
assert.NotNil(t, err)
}
func TestGetApps(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"groupid": "46489126", "hostid": "7468763", "applicationid": "7947934", "name": "appname1"},
{"groupid": "46489127","hostid": "846586", "applicationid": "9182763", "name": "appname2"}]}`, 200)
resp, err := zabbixDatasource.getApps(context.Background(), basicDatasourceInfo, "nam", "hostnam", "appname1")
assert.Equal(t, "7947934", resp[0]["applicationid"])
assert.Equal(t, "appname1", resp[0]["name"])
assert.Nil(t, err)
}
func TestGetAppsError(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"groupid": "46489126", "hostid": "7468763", "applicationid": "7947934", "name": "appname1"},
{"groupid": "46489127","hostid": "846586", "applicationid": "9182763", "name": "appname2"}]}`, 500)
resp, err := zabbixDatasource.getApps(context.Background(), basicDatasourceInfo, "nam", "hostnam", "appname1")
assert.Nil(t, resp)
assert.NotNil(t, err)
}
func TestGetItems(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"groupid": "46489126", "hostid": "7468763", "applicationid": "7947934", "itemid": "837465", "name": "itemname1", "status": "0"},
{"groupid": "46489127","hostid": "846586", "applicationid": "9182763", "itemid" : "0288374", "name": "itemname2", "status": "0"}]}`, 200)
resp, err := zabbixDatasource.getItems(context.Background(), basicDatasourceInfo, "itemname1", "itemname1", "itemname1", "itemname1", "num")
assert.Equal(t, "837465", resp[0].ID)
assert.Equal(t, "itemname1", resp[0].Name)
assert.Nil(t, err)
}
func TestGetItemsError(t *testing.T) {
zabbixDatasource := mockZabbixDataSource(`{"result":[{"groupid": "46489126", "hostid": "7468763", "applicationid": "7947934", "itemid": "837465", "name": "itemname1", "status": "0"},
{"groupid": "46489127","hostid": "846586", "applicationid": "9182763", "itemid" : "0288374", "name": "itemname2", "status": "0"}]}`, 500)
resp, err := zabbixDatasource.getItems(context.Background(), basicDatasourceInfo, "name", "name", "name", "name", "num")
assert.Nil(t, resp)
assert.NotNil(t, err)
}
func TestGetTrendValueType(t *testing.T) {
json1, _ := simplejson.NewJson([]byte(`{"functions":[{"def":{"name":"name1"}},{"def":{"name":"name2"}}]}`))
json2, _ := simplejson.NewJson([]byte(`{"functions":[{"def":{"name":"name1"}},{"def":{"name":"name2"}}]}`))
jsonQueries := []*simplejson.Json{json1, json2}
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
resp := zabbixDatasource.getTrendValueType(jsonQueries)
assert.Equal(t, "avg", resp)
}
func TestGetConsolidateBy(t *testing.T) {
json1, _ := simplejson.NewJson([]byte(`{"functions":[{"def":{"name":"consolidateBy", "params":["sum"]}},{"def":{"name":"name2"}}]}`))
json2, _ := simplejson.NewJson([]byte(`{"functions":[{"def":{"name":"name1"}},{"def":{"name":"name2"}}]}`))
jsonQueries := []*simplejson.Json{json1, json2}
zabbixDatasource := mockZabbixDataSource(`{"result":"sampleResult"}`, 200)
resp := zabbixDatasource.getConsolidateBy(jsonQueries)
assert.Equal(t, "sum", resp)
}
func Test_isUseTrend(t *testing.T) {
tests := []struct {
name string
timeRange *datasource.TimeRange
want bool
}{
{
name: "History time",
timeRange: &datasource.TimeRange{
FromEpochMs: time.Now().Add(-time.Hour*48).Unix() * 1000,
ToEpochMs: time.Now().Add(-time.Hour*12).Unix() * 1000,
},
want: false,
},
{
name: "Trend time (past 7 days)",
timeRange: &datasource.TimeRange{
FromEpochMs: time.Now().Add(-time.Hour*24*14).Unix() * 1000,
ToEpochMs: time.Now().Add(-time.Hour*24*13).Unix() * 1000,
},
want: true,
},
{
name: "Trend time (longer than 4 days)",
timeRange: &datasource.TimeRange{
FromEpochMs: time.Now().Add(-time.Hour*24*8).Unix() * 1000,
ToEpochMs: time.Now().Add(-time.Hour*24*1).Unix() * 1000,
},
want: true,
},
}
for _, tt := range tests {
got := isUseTrend(tt.timeRange)
assert.Equal(t, tt.want, got, tt.name, tt.timeRange)
}
}
func Test_parseFilter(t *testing.T) {
tests := []struct {
name string
filter string
want *regexp.Regexp
wantErr string
}{
{
name: "Non-regex filter",
filter: "foobar",
want: nil,
},
{
name: "Non-regex filter (would-be invalid regex)",
filter: "fooba(r",
want: nil,
},
{
name: "Regex filter",
filter: "/^foo.+/",
want: regexp.MustCompile("^foo.+"),
},
{
name: "Regex filter with flags",
filter: "/^foo.+/s",
want: regexp.MustCompile("(?s)^foo.+"),
},
{
name: "Invalid regex",
filter: "/fooba(r/",
wantErr: "error parsing regexp: missing closing ): `fooba(r`",
},
{
name: "Unsupported flag",
filter: "/foo.+/z",
wantErr: "error parsing regexp: unsupported flags `z` (expected [imsU])",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseFilter(tt.filter)
if tt.wantErr != "" {
assert.Error(t, err)
assert.EqualError(t, err, tt.wantErr)
assert.Nil(t, got)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}