mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-01 14:47:38 +00:00
790eab3026
### Describe Your Changes This PR continues the implementation of integration tests (#7199). It adds the support for vm-single: - A vmsingle app wrapper has been added - Sample vmsingle tests that test the VM documentation related to querying data (#7435) - The tests use the go-cmp/{cmp,/cmpopts} packages, therefore they have been added to ./vendor - Minor refactoring: data objects have been moved to model.go Advice on porting things to cluster branch: - The build rule must include tests that start with TestVmsingle (similarly to how TestCluster tests are skipped in master branch) - The build rule must depend on `vmstorage vminsert vmselect` instead of `victoria-metrics` - The query_test.go can actually be implemented for cluster as well. To do this the tests need to be renamed to start with TestCluster and the tests must instantiace vm{storage,insert,select} instead of vmsingle. ### Checklist The following checks are **mandatory**: - [x] My change adheres [VictoriaMetrics contributing guidelines](https://docs.victoriametrics.com/contributing/). --------- Signed-off-by: Artem Fetishev <rtm@victoriametrics.com> Signed-off-by: hagen1778 <roman@victoriametrics.com> Co-authored-by: hagen1778 <roman@victoriametrics.com> Signed-off-by: hagen1778 <roman@victoriametrics.com>
121 lines
3.6 KiB
Go
121 lines
3.6 KiB
Go
package apptest
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// PrometheusQuerier contains methods available to Prometheus-like HTTP API for Querying
|
|
type PrometheusQuerier interface {
|
|
PrometheusAPIV1Query(t *testing.T, query, time, step string, opts QueryOpts) *PrometheusAPIV1QueryResponse
|
|
PrometheusAPIV1QueryRange(t *testing.T, query, start, end, step string, opts QueryOpts) *PrometheusAPIV1QueryResponse
|
|
PrometheusAPIV1Series(t *testing.T, matchQuery string, opts QueryOpts) *PrometheusAPIV1SeriesResponse
|
|
}
|
|
|
|
// PrometheusWriter contains methods available to Prometheus-like HTTP API for Writing new data
|
|
type PrometheusWriter interface {
|
|
PrometheusAPIV1ImportPrometheus(t *testing.T, records []string, opts QueryOpts)
|
|
}
|
|
|
|
// QueryOpts contains various params used for querying or ingesting data
|
|
type QueryOpts struct {
|
|
Tenant string
|
|
Timeout string
|
|
}
|
|
|
|
// PrometheusAPIV1QueryResponse is an inmemory representation of the
|
|
// /prometheus/api/v1/query or /prometheus/api/v1/query_range response.
|
|
type PrometheusAPIV1QueryResponse struct {
|
|
Status string
|
|
Data *QueryData
|
|
}
|
|
|
|
// NewPrometheusAPIV1QueryResponse is a test helper function that creates a new
|
|
// instance of PrometheusAPIV1QueryResponse by unmarshalling a json string.
|
|
func NewPrometheusAPIV1QueryResponse(t *testing.T, s string) *PrometheusAPIV1QueryResponse {
|
|
t.Helper()
|
|
|
|
res := &PrometheusAPIV1QueryResponse{}
|
|
if err := json.Unmarshal([]byte(s), res); err != nil {
|
|
t.Fatalf("could not unmarshal query response: %v", err)
|
|
}
|
|
return res
|
|
}
|
|
|
|
// QueryData holds the query result along with its type.
|
|
type QueryData struct {
|
|
ResultType string
|
|
Result []*QueryResult
|
|
}
|
|
|
|
// QueryResult holds the metric name (in the form of label name-value
|
|
// collection) and its samples.
|
|
//
|
|
// Sample or Samples field is set for /prometheus/api/v1/query or
|
|
// /prometheus/api/v1/query_range response respectively.
|
|
type QueryResult struct {
|
|
Metric map[string]string
|
|
Sample *Sample `json:"value"`
|
|
Samples []*Sample `json:"values"`
|
|
}
|
|
|
|
// Sample is a timeseries value at a given timestamp.
|
|
type Sample struct {
|
|
Timestamp int64
|
|
Value float64
|
|
}
|
|
|
|
// NewSample is a test helper function that creates a new sample out of time in
|
|
// RFC3339 format and a value.
|
|
func NewSample(t *testing.T, timeStr string, value float64) *Sample {
|
|
parsedTime, err := time.Parse(time.RFC3339, timeStr)
|
|
if err != nil {
|
|
t.Fatalf("could not parse RFC3339 time %q: %v", timeStr, err)
|
|
}
|
|
return &Sample{parsedTime.Unix(), value}
|
|
}
|
|
|
|
// UnmarshalJSON populates the sample fields from a JSON string.
|
|
func (s *Sample) UnmarshalJSON(b []byte) error {
|
|
var (
|
|
ts int64
|
|
v string
|
|
)
|
|
raw := []any{&ts, &v}
|
|
if err := json.Unmarshal(b, &raw); err != nil {
|
|
return err
|
|
}
|
|
if got, want := len(raw), 2; got != want {
|
|
return fmt.Errorf("unexpected number of fields: got %d, want %d (raw sample: %s)", got, want, string(b))
|
|
}
|
|
s.Timestamp = ts
|
|
var err error
|
|
s.Value, err = strconv.ParseFloat(v, 64)
|
|
if err != nil {
|
|
return fmt.Errorf("could not parse sample value %q: %w", v, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PrometheusAPIV1SeriesResponse is an inmemory representation of the
|
|
// /prometheus/api/v1/series response.
|
|
type PrometheusAPIV1SeriesResponse struct {
|
|
Status string
|
|
IsPartial bool
|
|
Data []map[string]string
|
|
}
|
|
|
|
// NewPrometheusAPIV1SeriesResponse is a test helper function that creates a new
|
|
// instance of PrometheusAPIV1SeriesResponse by unmarshalling a json string.
|
|
func NewPrometheusAPIV1SeriesResponse(t *testing.T, s string) *PrometheusAPIV1SeriesResponse {
|
|
t.Helper()
|
|
|
|
res := &PrometheusAPIV1SeriesResponse{}
|
|
if err := json.Unmarshal([]byte(s), res); err != nil {
|
|
t.Fatalf("could not unmarshal series response: %v", err)
|
|
}
|
|
return res
|
|
}
|