102 lines
3.8 KiB
Go
102 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestParseMetricQuery(t *testing.T) {
|
|
query, err := parseMetricQuery(`vps_control_cpu_usage_percent{server_id="srv-1",server_name="edge"}`)
|
|
if err != nil || query.Name != "vps_control_cpu_usage_percent" || query.ServerID != "srv-1" || query.ServerName != "edge" {
|
|
t.Fatalf("unexpected metric query: %#v, %v", query, err)
|
|
}
|
|
for _, invalid := range []string{
|
|
`process_cpu_seconds_total`,
|
|
`vps_control_cpu_usage_percent{job=~".*"}`,
|
|
`vps_control_cpu_usage_percent or vector(1)`,
|
|
} {
|
|
if _, err = parseMetricQuery(invalid); err == nil {
|
|
t.Fatalf("accepted unsupported PromQL %q", invalid)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseLogQueryIsAllowListedAndAnchored(t *testing.T) {
|
|
matchers, err := parseLogQuery(`{server_name="edge",unit=~"(nginx|ssh)\.service"}`)
|
|
if err != nil || len(matchers) != 2 {
|
|
t.Fatalf("unexpected log selector: %#v, %v", matchers, err)
|
|
}
|
|
if logMatches(map[string]string{"server_name": "edge", "unit": "prefix-nginx.service"}, matchers) {
|
|
t.Fatal("regex matcher was not anchored")
|
|
}
|
|
if !logMatches(map[string]string{"server_name": "edge", "unit": "nginx.service"}, matchers) {
|
|
t.Fatal("valid labels did not match")
|
|
}
|
|
for _, invalid := range []string{`{}`, `{message="secret"}`, `{unit!="ssh.service"}`, `{unit="x"} |= "error"`} {
|
|
if _, err = parseLogQuery(invalid); err == nil {
|
|
t.Fatalf("accepted unsupported LogQL %q", invalid)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBuildLokiStreamsIsBounded(t *testing.T) {
|
|
now := time.Now()
|
|
entries := []IntegrationLog{
|
|
{ServerID: "1", ServerName: "edge", Unit: "nginx.service", Priority: 6, Timestamp: now, Message: "new"},
|
|
{ServerID: "1", ServerName: "edge", Unit: "nginx.service", Priority: 6, Timestamp: now.Add(-time.Second), Message: "old"},
|
|
}
|
|
streams := buildLokiStreams(entries, []logMatcher{{Label: "server_id", Exact: "1"}}, 1, "backward")
|
|
if len(streams) != 1 || len(streams[0].Values) != 1 || streams[0].Values[0][1] != "new" {
|
|
t.Fatalf("unexpected bounded streams: %#v", streams)
|
|
}
|
|
}
|
|
|
|
func TestReadIntegrationTokenPermissionsAndLength(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "token")
|
|
if err := os.WriteFile(path, []byte("0123456789abcdef0123456789abcdef\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := readIntegrationToken(path); err != nil {
|
|
t.Fatalf("valid token rejected: %v", err)
|
|
}
|
|
if err := os.Chmod(path, 0o622); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := readIntegrationToken(path); err == nil {
|
|
t.Fatal("group-writable token accepted")
|
|
}
|
|
}
|
|
|
|
func TestTimestampBounds(t *testing.T) {
|
|
if _, err := parseTimestamp("NaN", time.Now()); err == nil {
|
|
t.Fatal("NaN timestamp accepted")
|
|
}
|
|
if _, err := parseLokiTimestamp("4102444800000000000", time.Now()); err == nil {
|
|
t.Fatal("2100 timestamp accepted")
|
|
}
|
|
}
|
|
|
|
func TestGrafanaDatasourceHealthExpressions(t *testing.T) {
|
|
app := &App{}
|
|
prometheusRequest := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("query=1%2B1&time=4"))
|
|
prometheusRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
prometheusResponse := httptest.NewRecorder()
|
|
app.prometheusQuery(prometheusResponse, prometheusRequest, false)
|
|
if prometheusResponse.Code != http.StatusOK || !strings.Contains(prometheusResponse.Body.String(), `"resultType":"scalar"`) {
|
|
t.Fatalf("unexpected Prometheus health response: %d %s", prometheusResponse.Code, prometheusResponse.Body.String())
|
|
}
|
|
|
|
lokiRequest := httptest.NewRequest(http.MethodGet,
|
|
"/integrations/loki/loki/api/v1/query?query=vector%281%29%2Bvector%281%29&time=4000000000", nil)
|
|
lokiResponse := httptest.NewRecorder()
|
|
app.lokiAPI(lokiResponse, lokiRequest)
|
|
if lokiResponse.Code != http.StatusOK || !strings.Contains(lokiResponse.Body.String(), `"resultType":"vector"`) {
|
|
t.Fatalf("unexpected Loki health response: %d %s", lokiResponse.Code, lokiResponse.Body.String())
|
|
}
|
|
}
|