mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-11 22:07:27 -08:00
promql: allow tests to be imported (#12050)
Signed-off-by: Michael Hoffmann <mhoffm@posteo.de>
This commit is contained in:
parent
214d6434c9
commit
4d8e380269
|
@ -25,8 +25,6 @@ import (
|
|||
|
||||
"github.com/go-kit/log"
|
||||
|
||||
"github.com/prometheus/prometheus/tsdb/tsdbutil"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
|
||||
|
@ -35,7 +33,9 @@ import (
|
|||
"github.com/prometheus/prometheus/model/timestamp"
|
||||
"github.com/prometheus/prometheus/promql/parser"
|
||||
"github.com/prometheus/prometheus/storage"
|
||||
"github.com/prometheus/prometheus/tsdb/tsdbutil"
|
||||
"github.com/prometheus/prometheus/util/stats"
|
||||
"github.com/prometheus/prometheus/util/teststorage"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -566,6 +566,7 @@ func TestSelectHintsSetCorrectly(t *testing.T) {
|
|||
err error
|
||||
)
|
||||
ctx := context.Background()
|
||||
|
||||
if tc.end == 0 {
|
||||
query, err = engine.NewInstantQuery(ctx, hintsRecorder, nil, tc.query, timestamp.Time(tc.start))
|
||||
} else {
|
||||
|
@ -573,7 +574,7 @@ func TestSelectHintsSetCorrectly(t *testing.T) {
|
|||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
res := query.Exec(ctx)
|
||||
res := query.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
|
||||
require.Equal(t, tc.expected, hintsRecorder.hints)
|
||||
|
@ -636,15 +637,11 @@ func TestEngineShutdown(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestEngineEvalStmtTimestamps(t *testing.T) {
|
||||
test, err := NewTest(t, `
|
||||
storage := LoadedStorage(t, `
|
||||
load 10s
|
||||
metric 1 2
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
|
||||
err = test.Run()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
cases := []struct {
|
||||
Query string
|
||||
|
@ -728,14 +725,15 @@ load 10s
|
|||
t.Run(fmt.Sprintf("%d query=%s", i, c.Query), func(t *testing.T) {
|
||||
var err error
|
||||
var qry Query
|
||||
engine := newTestEngine()
|
||||
if c.Interval == 0 {
|
||||
qry, err = test.QueryEngine().NewInstantQuery(test.context, test.Queryable(), nil, c.Query, c.Start)
|
||||
qry, err = engine.NewInstantQuery(context.Background(), storage, nil, c.Query, c.Start)
|
||||
} else {
|
||||
qry, err = test.QueryEngine().NewRangeQuery(test.context, test.Queryable(), nil, c.Query, c.Start, c.End, c.Interval)
|
||||
qry, err = engine.NewRangeQuery(context.Background(), storage, nil, c.Query, c.Start, c.End, c.Interval)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
if c.ShouldError {
|
||||
require.Error(t, res.Err, "expected error for the query %q", c.Query)
|
||||
return
|
||||
|
@ -748,18 +746,14 @@ load 10s
|
|||
}
|
||||
|
||||
func TestQueryStatistics(t *testing.T) {
|
||||
test, err := NewTest(t, `
|
||||
storage := LoadedStorage(t, `
|
||||
load 10s
|
||||
metricWith1SampleEvery10Seconds 1+1x100
|
||||
metricWith3SampleEvery10Seconds{a="1",b="1"} 1+1x100
|
||||
metricWith3SampleEvery10Seconds{a="2",b="2"} 1+1x100
|
||||
metricWith3SampleEvery10Seconds{a="3",b="2"} 1+1x100
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
|
||||
err = test.Run()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
cases := []struct {
|
||||
Query string
|
||||
|
@ -1194,7 +1188,7 @@ load 10s
|
|||
},
|
||||
}
|
||||
|
||||
engine := test.QueryEngine()
|
||||
engine := newTestEngine()
|
||||
engine.enablePerStepStats = true
|
||||
origMaxSamples := engine.maxSamplesPerQuery
|
||||
for _, c := range cases {
|
||||
|
@ -1206,13 +1200,13 @@ load 10s
|
|||
var err error
|
||||
var qry Query
|
||||
if c.Interval == 0 {
|
||||
qry, err = engine.NewInstantQuery(test.context, test.Queryable(), opts, c.Query, c.Start)
|
||||
qry, err = engine.NewInstantQuery(context.Background(), storage, opts, c.Query, c.Start)
|
||||
} else {
|
||||
qry, err = engine.NewRangeQuery(test.context, test.Queryable(), opts, c.Query, c.Start, c.End, c.Interval)
|
||||
qry, err = engine.NewRangeQuery(context.Background(), storage, opts, c.Query, c.Start, c.End, c.Interval)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.Equal(t, expErr, res.Err)
|
||||
|
||||
return qry.Stats()
|
||||
|
@ -1234,17 +1228,13 @@ load 10s
|
|||
}
|
||||
|
||||
func TestMaxQuerySamples(t *testing.T) {
|
||||
test, err := NewTest(t, `
|
||||
storage := LoadedStorage(t, `
|
||||
load 10s
|
||||
metric 1+1x100
|
||||
bigmetric{a="1"} 1+1x100
|
||||
bigmetric{a="2"} 1+1x100
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
|
||||
err = test.Run()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
// These test cases should be touching the limit exactly (hence no exceeding).
|
||||
// Exceeding the limit will be tested by doing -1 to the MaxSamples.
|
||||
|
@ -1382,20 +1372,20 @@ load 10s
|
|||
},
|
||||
}
|
||||
|
||||
engine := test.QueryEngine()
|
||||
for _, c := range cases {
|
||||
t.Run(c.Query, func(t *testing.T) {
|
||||
engine := newTestEngine()
|
||||
testFunc := func(expError error) {
|
||||
var err error
|
||||
var qry Query
|
||||
if c.Interval == 0 {
|
||||
qry, err = engine.NewInstantQuery(test.context, test.Queryable(), nil, c.Query, c.Start)
|
||||
qry, err = engine.NewInstantQuery(context.Background(), storage, nil, c.Query, c.Start)
|
||||
} else {
|
||||
qry, err = engine.NewRangeQuery(test.context, test.Queryable(), nil, c.Query, c.Start, c.End, c.Interval)
|
||||
qry, err = engine.NewRangeQuery(context.Background(), storage, nil, c.Query, c.Start, c.End, c.Interval)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
stats := qry.Stats()
|
||||
require.Equal(t, expError, res.Err)
|
||||
require.NotNil(t, stats)
|
||||
|
@ -1416,7 +1406,8 @@ load 10s
|
|||
}
|
||||
|
||||
func TestAtModifier(t *testing.T) {
|
||||
test, err := NewTest(t, `
|
||||
engine := newTestEngine()
|
||||
storage := LoadedStorage(t, `
|
||||
load 10s
|
||||
metric{job="1"} 0+1x1000
|
||||
metric{job="2"} 0+2x1000
|
||||
|
@ -1427,11 +1418,7 @@ load 10s
|
|||
load 1ms
|
||||
metric_ms 0+1x10000
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
|
||||
err = test.Run()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
lbls1 := labels.FromStrings("__name__", "metric", "job", "1")
|
||||
lbls2 := labels.FromStrings("__name__", "metric", "job", "2")
|
||||
|
@ -1441,7 +1428,7 @@ load 1ms
|
|||
lblsneg := labels.FromStrings("__name__", "metric_neg")
|
||||
|
||||
// Add some samples with negative timestamp.
|
||||
db := test.TSDB()
|
||||
db := storage.DB
|
||||
app := db.Appender(context.Background())
|
||||
ref, err := app.Append(0, lblsneg, -1000000, 1000)
|
||||
require.NoError(t, err)
|
||||
|
@ -1630,13 +1617,13 @@ load 1ms
|
|||
var err error
|
||||
var qry Query
|
||||
if c.end == 0 {
|
||||
qry, err = test.QueryEngine().NewInstantQuery(test.context, test.Queryable(), nil, c.query, start)
|
||||
qry, err = engine.NewInstantQuery(context.Background(), storage, nil, c.query, start)
|
||||
} else {
|
||||
qry, err = test.QueryEngine().NewRangeQuery(test.context, test.Queryable(), nil, c.query, start, end, interval)
|
||||
qry, err = engine.NewRangeQuery(context.Background(), storage, nil, c.query, start, end, interval)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
if expMat, ok := c.result.(Matrix); ok {
|
||||
sort.Sort(expMat)
|
||||
|
@ -1955,18 +1942,16 @@ func TestSubquerySelector(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run("", func(t *testing.T) {
|
||||
test, err := NewTest(t, tst.loadString)
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
engine := newTestEngine()
|
||||
storage := LoadedStorage(t, tst.loadString)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
require.NoError(t, test.Run())
|
||||
engine := test.QueryEngine()
|
||||
for _, c := range tst.cases {
|
||||
t.Run(c.Query, func(t *testing.T) {
|
||||
qry, err := engine.NewInstantQuery(test.context, test.Queryable(), nil, c.Query, c.Start)
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, c.Query, c.Start)
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.Equal(t, c.Result.Err, res.Err)
|
||||
mat := res.Value.(Matrix)
|
||||
sort.Sort(mat)
|
||||
|
@ -1978,15 +1963,12 @@ func TestSubquerySelector(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTimestampFunction_StepsMoreOftenThanSamples(t *testing.T) {
|
||||
test, err := NewTest(t, `
|
||||
engine := newTestEngine()
|
||||
storage := LoadedStorage(t, `
|
||||
load 1m
|
||||
metric 0+1x1000
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
|
||||
err = test.Run()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
query := "timestamp(metric)"
|
||||
start := time.Unix(0, 0)
|
||||
|
@ -2013,10 +1995,10 @@ load 1m
|
|||
},
|
||||
}
|
||||
|
||||
qry, err := test.QueryEngine().NewRangeQuery(test.context, test.Queryable(), nil, query, start, end, interval)
|
||||
qry, err := engine.NewRangeQuery(context.Background(), storage, nil, query, start, end, interval)
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
require.Equal(t, expectedResult, res.Value)
|
||||
}
|
||||
|
@ -2955,7 +2937,6 @@ func TestPreprocessAndWrapWithStepInvariantExpr(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestEngineOptsValidation(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cases := []struct {
|
||||
opts EngineOpts
|
||||
query string
|
||||
|
@ -3015,8 +2996,8 @@ func TestEngineOptsValidation(t *testing.T) {
|
|||
|
||||
for _, c := range cases {
|
||||
eng := NewEngine(c.opts)
|
||||
_, err1 := eng.NewInstantQuery(ctx, nil, nil, c.query, time.Unix(10, 0))
|
||||
_, err2 := eng.NewRangeQuery(ctx, nil, nil, c.query, time.Unix(0, 0), time.Unix(10, 0), time.Second)
|
||||
_, err1 := eng.NewInstantQuery(context.Background(), nil, nil, c.query, time.Unix(10, 0))
|
||||
_, err2 := eng.NewRangeQuery(context.Background(), nil, nil, c.query, time.Unix(0, 0), time.Unix(10, 0), time.Second)
|
||||
if c.fail {
|
||||
require.Equal(t, c.expError, err1)
|
||||
require.Equal(t, c.expError, err2)
|
||||
|
@ -3156,17 +3137,14 @@ func TestRangeQuery(t *testing.T) {
|
|||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.Name, func(t *testing.T) {
|
||||
test, err := NewTest(t, c.Load)
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
engine := newTestEngine()
|
||||
storage := LoadedStorage(t, c.Load)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
err = test.Run()
|
||||
qry, err := engine.NewRangeQuery(context.Background(), storage, nil, c.Query, c.Start, c.End, c.Interval)
|
||||
require.NoError(t, err)
|
||||
|
||||
qry, err := test.QueryEngine().NewRangeQuery(test.context, test.Queryable(), nil, c.Query, c.Start, c.End, c.Interval)
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
require.Equal(t, c.Result, res.Value)
|
||||
})
|
||||
|
@ -3176,27 +3154,24 @@ func TestRangeQuery(t *testing.T) {
|
|||
func TestNativeHistogramRate(t *testing.T) {
|
||||
// TODO(beorn7): Integrate histograms into the PromQL testing framework
|
||||
// and write more tests there.
|
||||
test, err := NewTest(t, "")
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
engine := newTestEngine()
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
seriesName := "sparse_histogram_series"
|
||||
lbls := labels.FromStrings("__name__", seriesName)
|
||||
|
||||
app := test.Storage().Appender(context.TODO())
|
||||
app := storage.Appender(context.Background())
|
||||
for i, h := range tsdbutil.GenerateTestHistograms(100) {
|
||||
_, err := app.AppendHistogram(0, lbls, int64(i)*int64(15*time.Second/time.Millisecond), h, nil)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.NoError(t, app.Commit())
|
||||
|
||||
require.NoError(t, test.Run())
|
||||
engine := test.QueryEngine()
|
||||
|
||||
queryString := fmt.Sprintf("rate(%s[1m])", seriesName)
|
||||
qry, err := engine.NewInstantQuery(test.context, test.Queryable(), nil, queryString, timestamp.Time(int64(5*time.Minute/time.Millisecond)))
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(int64(5*time.Minute/time.Millisecond)))
|
||||
require.NoError(t, err)
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
vector, err := res.Vector()
|
||||
require.NoError(t, err)
|
||||
|
@ -3220,27 +3195,24 @@ func TestNativeHistogramRate(t *testing.T) {
|
|||
func TestNativeFloatHistogramRate(t *testing.T) {
|
||||
// TODO(beorn7): Integrate histograms into the PromQL testing framework
|
||||
// and write more tests there.
|
||||
test, err := NewTest(t, "")
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
engine := newTestEngine()
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
seriesName := "sparse_histogram_series"
|
||||
lbls := labels.FromStrings("__name__", seriesName)
|
||||
|
||||
app := test.Storage().Appender(context.TODO())
|
||||
app := storage.Appender(context.Background())
|
||||
for i, fh := range tsdbutil.GenerateTestFloatHistograms(100) {
|
||||
_, err := app.AppendHistogram(0, lbls, int64(i)*int64(15*time.Second/time.Millisecond), nil, fh)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.NoError(t, app.Commit())
|
||||
|
||||
require.NoError(t, test.Run())
|
||||
engine := test.QueryEngine()
|
||||
|
||||
queryString := fmt.Sprintf("rate(%s[1m])", seriesName)
|
||||
qry, err := engine.NewInstantQuery(test.context, test.Queryable(), nil, queryString, timestamp.Time(int64(5*time.Minute/time.Millisecond)))
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(int64(5*time.Minute/time.Millisecond)))
|
||||
require.NoError(t, err)
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
vector, err := res.Vector()
|
||||
require.NoError(t, err)
|
||||
|
@ -3283,16 +3255,16 @@ func TestNativeHistogram_HistogramCountAndSum(t *testing.T) {
|
|||
}
|
||||
for _, floatHisto := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("floatHistogram=%t", floatHisto), func(t *testing.T) {
|
||||
test, err := NewTest(t, "")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(test.Close)
|
||||
engine := newTestEngine()
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
seriesName := "sparse_histogram_series"
|
||||
lbls := labels.FromStrings("__name__", seriesName)
|
||||
engine := test.QueryEngine()
|
||||
|
||||
ts := int64(10 * time.Minute / time.Millisecond)
|
||||
app := test.Storage().Appender(context.TODO())
|
||||
app := storage.Appender(context.Background())
|
||||
var err error
|
||||
if floatHisto {
|
||||
_, err = app.AppendHistogram(0, lbls, ts, nil, h.ToFloat())
|
||||
} else {
|
||||
|
@ -3302,10 +3274,10 @@ func TestNativeHistogram_HistogramCountAndSum(t *testing.T) {
|
|||
require.NoError(t, app.Commit())
|
||||
|
||||
queryString := fmt.Sprintf("histogram_count(%s)", seriesName)
|
||||
qry, err := engine.NewInstantQuery(test.context, test.Queryable(), nil, queryString, timestamp.Time(ts))
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(ts))
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
|
||||
vector, err := res.Vector()
|
||||
|
@ -3320,10 +3292,10 @@ func TestNativeHistogram_HistogramCountAndSum(t *testing.T) {
|
|||
}
|
||||
|
||||
queryString = fmt.Sprintf("histogram_sum(%s)", seriesName)
|
||||
qry, err = engine.NewInstantQuery(test.context, test.Queryable(), nil, queryString, timestamp.Time(ts))
|
||||
qry, err = engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(ts))
|
||||
require.NoError(t, err)
|
||||
|
||||
res = qry.Exec(test.Context())
|
||||
res = qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
|
||||
vector, err = res.Vector()
|
||||
|
@ -3533,18 +3505,18 @@ func TestNativeHistogram_HistogramQuantile(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
test, err := NewTest(t, "")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(test.Close)
|
||||
engine := newTestEngine()
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
idx := int64(0)
|
||||
for _, floatHisto := range []bool{true, false} {
|
||||
for _, c := range cases {
|
||||
t.Run(fmt.Sprintf("%s floatHistogram=%t", c.text, floatHisto), func(t *testing.T) {
|
||||
seriesName := "sparse_histogram_series"
|
||||
lbls := labels.FromStrings("__name__", seriesName)
|
||||
engine := test.QueryEngine()
|
||||
ts := idx * int64(10*time.Minute/time.Millisecond)
|
||||
app := test.Storage().Appender(context.TODO())
|
||||
app := storage.Appender(context.Background())
|
||||
var err error
|
||||
if floatHisto {
|
||||
_, err = app.AppendHistogram(0, lbls, ts, nil, c.h.ToFloat())
|
||||
} else {
|
||||
|
@ -3556,10 +3528,10 @@ func TestNativeHistogram_HistogramQuantile(t *testing.T) {
|
|||
for j, sc := range c.subCases {
|
||||
t.Run(fmt.Sprintf("%d %s", j, sc.quantile), func(t *testing.T) {
|
||||
queryString := fmt.Sprintf("histogram_quantile(%s, %s)", sc.quantile, seriesName)
|
||||
qry, err := engine.NewInstantQuery(test.context, test.Queryable(), nil, queryString, timestamp.Time(ts))
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(ts))
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
|
||||
vector, err := res.Vector()
|
||||
|
@ -3966,16 +3938,16 @@ func TestNativeHistogram_HistogramFraction(t *testing.T) {
|
|||
for _, floatHisto := range []bool{true, false} {
|
||||
for _, c := range cases {
|
||||
t.Run(fmt.Sprintf("%s floatHistogram=%t", c.text, floatHisto), func(t *testing.T) {
|
||||
test, err := NewTest(t, "")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(test.Close)
|
||||
engine := newTestEngine()
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
seriesName := "sparse_histogram_series"
|
||||
lbls := labels.FromStrings("__name__", seriesName)
|
||||
engine := test.QueryEngine()
|
||||
|
||||
ts := idx * int64(10*time.Minute/time.Millisecond)
|
||||
app := test.Storage().Appender(context.TODO())
|
||||
app := storage.Appender(context.Background())
|
||||
var err error
|
||||
if floatHisto {
|
||||
_, err = app.AppendHistogram(0, lbls, ts, nil, c.h.ToFloat())
|
||||
} else {
|
||||
|
@ -3987,10 +3959,10 @@ func TestNativeHistogram_HistogramFraction(t *testing.T) {
|
|||
for j, sc := range c.subCases {
|
||||
t.Run(fmt.Sprintf("%d %s %s", j, sc.lower, sc.upper), func(t *testing.T) {
|
||||
queryString := fmt.Sprintf("histogram_fraction(%s, %s, %s)", sc.lower, sc.upper, seriesName)
|
||||
qry, err := engine.NewInstantQuery(test.context, test.Queryable(), nil, queryString, timestamp.Time(ts))
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(ts))
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
|
||||
vector, err := res.Vector()
|
||||
|
@ -4125,20 +4097,20 @@ func TestNativeHistogram_Sum_Count_Add_AvgOperator(t *testing.T) {
|
|||
for _, c := range cases {
|
||||
for _, floatHisto := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("floatHistogram=%t %d", floatHisto, idx0), func(t *testing.T) {
|
||||
test, err := NewTest(t, "")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(test.Close)
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
seriesName := "sparse_histogram_series"
|
||||
seriesNameOverTime := "sparse_histogram_series_over_time"
|
||||
|
||||
engine := test.QueryEngine()
|
||||
engine := newTestEngine()
|
||||
|
||||
ts := idx0 * int64(10*time.Minute/time.Millisecond)
|
||||
app := test.Storage().Appender(context.TODO())
|
||||
app := storage.Appender(context.Background())
|
||||
for idx1, h := range c.histograms {
|
||||
lbls := labels.FromStrings("__name__", seriesName, "idx", fmt.Sprintf("%d", idx1))
|
||||
// Since we mutate h later, we need to create a copy here.
|
||||
var err error
|
||||
if floatHisto {
|
||||
_, err = app.AppendHistogram(0, lbls, ts, nil, h.Copy().ToFloat())
|
||||
} else {
|
||||
|
@ -4159,10 +4131,10 @@ func TestNativeHistogram_Sum_Count_Add_AvgOperator(t *testing.T) {
|
|||
require.NoError(t, app.Commit())
|
||||
|
||||
queryAndCheck := func(queryString string, ts int64, exp Vector) {
|
||||
qry, err := engine.NewInstantQuery(test.context, test.Queryable(), nil, queryString, timestamp.Time(ts))
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(ts))
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
|
||||
vector, err := res.Vector()
|
||||
|
@ -4385,19 +4357,18 @@ func TestNativeHistogram_SubOperator(t *testing.T) {
|
|||
for _, c := range cases {
|
||||
for _, floatHisto := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("floatHistogram=%t %d", floatHisto, idx0), func(t *testing.T) {
|
||||
test, err := NewTest(t, "")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(test.Close)
|
||||
engine := newTestEngine()
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
seriesName := "sparse_histogram_series"
|
||||
|
||||
engine := test.QueryEngine()
|
||||
|
||||
ts := idx0 * int64(10*time.Minute/time.Millisecond)
|
||||
app := test.Storage().Appender(context.TODO())
|
||||
app := storage.Appender(context.Background())
|
||||
for idx1, h := range c.histograms {
|
||||
lbls := labels.FromStrings("__name__", seriesName, "idx", fmt.Sprintf("%d", idx1))
|
||||
// Since we mutate h later, we need to create a copy here.
|
||||
var err error
|
||||
if floatHisto {
|
||||
_, err = app.AppendHistogram(0, lbls, ts, nil, h.Copy().ToFloat())
|
||||
} else {
|
||||
|
@ -4408,10 +4379,10 @@ func TestNativeHistogram_SubOperator(t *testing.T) {
|
|||
require.NoError(t, app.Commit())
|
||||
|
||||
queryAndCheck := func(queryString string, exp Vector) {
|
||||
qry, err := engine.NewInstantQuery(test.context, test.Queryable(), nil, queryString, timestamp.Time(ts))
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(ts))
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
|
||||
vector, err := res.Vector()
|
||||
|
@ -4531,20 +4502,20 @@ func TestNativeHistogram_MulDivOperator(t *testing.T) {
|
|||
for _, c := range cases {
|
||||
for _, floatHisto := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("floatHistogram=%t %d", floatHisto, idx0), func(t *testing.T) {
|
||||
test, err := NewTest(t, "")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(test.Close)
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
seriesName := "sparse_histogram_series"
|
||||
floatSeriesName := "float_series"
|
||||
|
||||
engine := test.QueryEngine()
|
||||
engine := newTestEngine()
|
||||
|
||||
ts := idx0 * int64(10*time.Minute/time.Millisecond)
|
||||
app := test.Storage().Appender(context.TODO())
|
||||
app := storage.Appender(context.Background())
|
||||
h := c.histogram
|
||||
lbls := labels.FromStrings("__name__", seriesName)
|
||||
// Since we mutate h later, we need to create a copy here.
|
||||
var err error
|
||||
if floatHisto {
|
||||
_, err = app.AppendHistogram(0, lbls, ts, nil, h.Copy().ToFloat())
|
||||
} else {
|
||||
|
@ -4556,10 +4527,10 @@ func TestNativeHistogram_MulDivOperator(t *testing.T) {
|
|||
require.NoError(t, app.Commit())
|
||||
|
||||
queryAndCheck := func(queryString string, exp Vector) {
|
||||
qry, err := engine.NewInstantQuery(test.context, test.Queryable(), nil, queryString, timestamp.Time(ts))
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(ts))
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
|
||||
vector, err := res.Vector()
|
||||
|
@ -4660,22 +4631,18 @@ metric 0 1 2
|
|||
for _, c := range cases {
|
||||
c := c
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
test, err := NewTest(t, load)
|
||||
require.NoError(t, err)
|
||||
defer test.Close()
|
||||
engine := newTestEngine()
|
||||
storage := LoadedStorage(t, load)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
err = test.Run()
|
||||
require.NoError(t, err)
|
||||
|
||||
eng := test.QueryEngine()
|
||||
if c.engineLookback != 0 {
|
||||
eng.lookbackDelta = c.engineLookback
|
||||
engine.lookbackDelta = c.engineLookback
|
||||
}
|
||||
opts := NewPrometheusQueryOpts(false, c.queryLookback)
|
||||
qry, err := eng.NewInstantQuery(test.context, test.Queryable(), opts, query, c.ts)
|
||||
qry, err := engine.NewInstantQuery(context.Background(), storage, opts, query, c.ts)
|
||||
require.NoError(t, err)
|
||||
|
||||
res := qry.Exec(test.Context())
|
||||
res := qry.Exec(context.Background())
|
||||
require.NoError(t, res.Err)
|
||||
vec, ok := res.Value.(Vector)
|
||||
require.True(t, ok)
|
||||
|
|
|
@ -15,7 +15,6 @@ package promql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -26,19 +25,21 @@ import (
|
|||
"github.com/prometheus/prometheus/util/teststorage"
|
||||
)
|
||||
|
||||
func newTestEngine() *Engine {
|
||||
return NewEngine(EngineOpts{
|
||||
Logger: nil,
|
||||
Reg: nil,
|
||||
MaxSamples: 10000,
|
||||
Timeout: 100 * time.Second,
|
||||
NoStepSubqueryIntervalFn: func(int64) int64 { return durationMilliseconds(1 * time.Minute) },
|
||||
EnableAtModifier: true,
|
||||
EnableNegativeOffset: true,
|
||||
EnablePerStepStats: true,
|
||||
})
|
||||
}
|
||||
|
||||
func TestEvaluations(t *testing.T) {
|
||||
files, err := filepath.Glob("testdata/*.test")
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, fn := range files {
|
||||
t.Run(fn, func(t *testing.T) {
|
||||
test, err := newTestFromFile(t, fn)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, test.Run())
|
||||
|
||||
test.Close()
|
||||
})
|
||||
}
|
||||
RunBuiltinTests(t, newTestEngine())
|
||||
}
|
||||
|
||||
// Run a lot of queries at the same time, to check for race conditions.
|
||||
|
|
162
promql/test.go
162
promql/test.go
|
@ -15,12 +15,14 @@ package promql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/regexp"
|
||||
|
@ -32,7 +34,6 @@ import (
|
|||
"github.com/prometheus/prometheus/model/timestamp"
|
||||
"github.com/prometheus/prometheus/promql/parser"
|
||||
"github.com/prometheus/prometheus/storage"
|
||||
"github.com/prometheus/prometheus/tsdb"
|
||||
"github.com/prometheus/prometheus/util/teststorage"
|
||||
"github.com/prometheus/prometheus/util/testutil"
|
||||
)
|
||||
|
@ -51,23 +52,74 @@ const (
|
|||
|
||||
var testStartTime = time.Unix(0, 0).UTC()
|
||||
|
||||
// Test is a sequence of read and write commands that are run
|
||||
// LoadedStorage returns storage with generated data using the provided load statements.
|
||||
// Non-load statements will cause test errors.
|
||||
func LoadedStorage(t testutil.T, input string) *teststorage.TestStorage {
|
||||
test, err := newTest(t, input)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, cmd := range test.cmds {
|
||||
switch cmd.(type) {
|
||||
case *loadCmd:
|
||||
require.NoError(t, test.exec(cmd, nil))
|
||||
default:
|
||||
t.Errorf("only 'load' commands accepted, got '%s'", cmd)
|
||||
}
|
||||
}
|
||||
return test.storage
|
||||
}
|
||||
|
||||
// RunBuiltinTests runs an acceptance test suite against the provided engine.
|
||||
func RunBuiltinTests(t *testing.T, engine engineQuerier) {
|
||||
files, err := fs.Glob(testsFs, "*/*.test")
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, fn := range files {
|
||||
t.Run(fn, func(t *testing.T) {
|
||||
content, err := fs.ReadFile(testsFs, fn)
|
||||
require.NoError(t, err)
|
||||
RunTest(t, string(content), engine)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// RunTest parses and runs the test against the provided engine.
|
||||
func RunTest(t testutil.T, input string, engine engineQuerier) {
|
||||
test, err := newTest(t, input)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer func() {
|
||||
if test.storage != nil {
|
||||
test.storage.Close()
|
||||
}
|
||||
if test.cancelCtx != nil {
|
||||
test.cancelCtx()
|
||||
}
|
||||
}()
|
||||
|
||||
for _, cmd := range test.cmds {
|
||||
// TODO(fabxc): aggregate command errors, yield diffs for result
|
||||
// comparison errors.
|
||||
require.NoError(t, test.exec(cmd, engine))
|
||||
}
|
||||
}
|
||||
|
||||
// test is a sequence of read and write commands that are run
|
||||
// against a test storage.
|
||||
type Test struct {
|
||||
type test struct {
|
||||
testutil.T
|
||||
|
||||
cmds []testCommand
|
||||
|
||||
storage *teststorage.TestStorage
|
||||
|
||||
queryEngine *Engine
|
||||
context context.Context
|
||||
cancelCtx context.CancelFunc
|
||||
context context.Context
|
||||
cancelCtx context.CancelFunc
|
||||
}
|
||||
|
||||
// NewTest returns an initialized empty Test.
|
||||
func NewTest(t testutil.T, input string) (*Test, error) {
|
||||
test := &Test{
|
||||
// newTest returns an initialized empty Test.
|
||||
func newTest(t testutil.T, input string) (*test, error) {
|
||||
test := &test{
|
||||
T: t,
|
||||
cmds: []testCommand{},
|
||||
}
|
||||
|
@ -77,46 +129,12 @@ func NewTest(t testutil.T, input string) (*Test, error) {
|
|||
return test, err
|
||||
}
|
||||
|
||||
func newTestFromFile(t testutil.T, filename string) (*Test, error) {
|
||||
content, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewTest(t, string(content))
|
||||
}
|
||||
//go:embed testdata
|
||||
var testsFs embed.FS
|
||||
|
||||
// QueryEngine returns the test's query engine.
|
||||
func (t *Test) QueryEngine() *Engine {
|
||||
return t.queryEngine
|
||||
}
|
||||
|
||||
// Queryable allows querying the test data.
|
||||
func (t *Test) Queryable() storage.Queryable {
|
||||
return t.storage
|
||||
}
|
||||
|
||||
// Context returns the test's context.
|
||||
func (t *Test) Context() context.Context {
|
||||
return t.context
|
||||
}
|
||||
|
||||
// Storage returns the test's storage.
|
||||
func (t *Test) Storage() storage.Storage {
|
||||
return t.storage
|
||||
}
|
||||
|
||||
// TSDB returns test's TSDB.
|
||||
func (t *Test) TSDB() *tsdb.DB {
|
||||
return t.storage.DB
|
||||
}
|
||||
|
||||
// ExemplarStorage returns the test's exemplar storage.
|
||||
func (t *Test) ExemplarStorage() storage.ExemplarStorage {
|
||||
return t.storage
|
||||
}
|
||||
|
||||
func (t *Test) ExemplarQueryable() storage.ExemplarQueryable {
|
||||
return t.storage.ExemplarQueryable()
|
||||
type engineQuerier interface {
|
||||
NewRangeQuery(ctx context.Context, q storage.Queryable, opts QueryOpts, qs string, start, end time.Time, interval time.Duration) (Query, error)
|
||||
NewInstantQuery(ctx context.Context, q storage.Queryable, opts QueryOpts, qs string, ts time.Time) (Query, error)
|
||||
}
|
||||
|
||||
func raise(line int, format string, v ...interface{}) error {
|
||||
|
@ -157,7 +175,7 @@ func parseLoad(lines []string, i int) (int, *loadCmd, error) {
|
|||
return i, cmd, nil
|
||||
}
|
||||
|
||||
func (t *Test) parseEval(lines []string, i int) (int, *evalCmd, error) {
|
||||
func (t *test) parseEval(lines []string, i int) (int, *evalCmd, error) {
|
||||
if !patEvalInstant.MatchString(lines[i]) {
|
||||
return i, nil, raise(i, "invalid evaluation command. (eval[_fail|_ordered] instant [at <offset:duration>] <query>")
|
||||
}
|
||||
|
@ -237,7 +255,7 @@ func getLines(input string) []string {
|
|||
}
|
||||
|
||||
// parse the given command sequence and appends it to the test.
|
||||
func (t *Test) parse(input string) error {
|
||||
func (t *test) parse(input string) error {
|
||||
lines := getLines(input)
|
||||
var err error
|
||||
// Scan for steps line by line.
|
||||
|
@ -433,19 +451,6 @@ func (cmd clearCmd) String() string {
|
|||
return "clear"
|
||||
}
|
||||
|
||||
// Run executes the command sequence of the test. Until the maximum error number
|
||||
// is reached, evaluation errors do not terminate execution.
|
||||
func (t *Test) Run() error {
|
||||
for _, cmd := range t.cmds {
|
||||
// TODO(fabxc): aggregate command errors, yield diffs for result
|
||||
// comparison errors.
|
||||
if err := t.exec(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type atModifierTestCase struct {
|
||||
expr string
|
||||
evalTime time.Time
|
||||
|
@ -515,7 +520,7 @@ func atModifierTestCases(exprStr string, evalTime time.Time) ([]atModifierTestCa
|
|||
}
|
||||
|
||||
// exec processes a single step of the test.
|
||||
func (t *Test) exec(tc testCommand) error {
|
||||
func (t *test) exec(tc testCommand, engine engineQuerier) error {
|
||||
switch cmd := tc.(type) {
|
||||
case *clearCmd:
|
||||
t.clear()
|
||||
|
@ -538,7 +543,7 @@ func (t *Test) exec(tc testCommand) error {
|
|||
}
|
||||
queries = append([]atModifierTestCase{{expr: cmd.expr, evalTime: cmd.start}}, queries...)
|
||||
for _, iq := range queries {
|
||||
q, err := t.QueryEngine().NewInstantQuery(t.context, t.storage, nil, iq.expr, iq.evalTime)
|
||||
q, err := engine.NewInstantQuery(t.context, t.storage, nil, iq.expr, iq.evalTime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -560,7 +565,7 @@ func (t *Test) exec(tc testCommand) error {
|
|||
|
||||
// Check query returns same result in range mode,
|
||||
// by checking against the middle step.
|
||||
q, err = t.queryEngine.NewRangeQuery(t.context, t.storage, nil, iq.expr, iq.evalTime.Add(-time.Minute), iq.evalTime.Add(time.Minute), time.Minute)
|
||||
q, err = engine.NewRangeQuery(t.context, t.storage, nil, iq.expr, iq.evalTime.Add(-time.Minute), iq.evalTime.Add(time.Minute), time.Minute)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -601,7 +606,7 @@ func (t *Test) exec(tc testCommand) error {
|
|||
}
|
||||
|
||||
// clear the current test storage of all inserted samples.
|
||||
func (t *Test) clear() {
|
||||
func (t *test) clear() {
|
||||
if t.storage != nil {
|
||||
err := t.storage.Close()
|
||||
require.NoError(t.T, err, "Unexpected error while closing test storage.")
|
||||
|
@ -610,30 +615,9 @@ func (t *Test) clear() {
|
|||
t.cancelCtx()
|
||||
}
|
||||
t.storage = teststorage.New(t)
|
||||
|
||||
opts := EngineOpts{
|
||||
Logger: nil,
|
||||
Reg: nil,
|
||||
MaxSamples: 10000,
|
||||
Timeout: 100 * time.Second,
|
||||
NoStepSubqueryIntervalFn: func(int64) int64 { return durationMilliseconds(1 * time.Minute) },
|
||||
EnableAtModifier: true,
|
||||
EnableNegativeOffset: true,
|
||||
EnablePerStepStats: true,
|
||||
}
|
||||
|
||||
t.queryEngine = NewEngine(opts)
|
||||
t.context, t.cancelCtx = context.WithCancel(context.Background())
|
||||
}
|
||||
|
||||
// Close closes resources associated with the Test.
|
||||
func (t *Test) Close() {
|
||||
t.cancelCtx()
|
||||
|
||||
err := t.storage.Close()
|
||||
require.NoError(t.T, err, "Unexpected error while closing test storage.")
|
||||
}
|
||||
|
||||
// samplesAlmostEqual returns true if the two sample lines only differ by a
|
||||
// small relative error in their sample value.
|
||||
func almostEqual(a, b float64) bool {
|
||||
|
|
|
@ -33,6 +33,17 @@ import (
|
|||
"github.com/prometheus/prometheus/util/teststorage"
|
||||
)
|
||||
|
||||
var testEngine = promql.NewEngine(promql.EngineOpts{
|
||||
Logger: nil,
|
||||
Reg: nil,
|
||||
MaxSamples: 10000,
|
||||
Timeout: 100 * time.Second,
|
||||
NoStepSubqueryIntervalFn: func(int64) int64 { return 60 * 1000 },
|
||||
EnableAtModifier: true,
|
||||
EnableNegativeOffset: true,
|
||||
EnablePerStepStats: true,
|
||||
})
|
||||
|
||||
func TestAlertingRuleState(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -74,14 +85,11 @@ func TestAlertingRuleState(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAlertingRuleLabelsUpdate(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
http_requests{job="app-server", instance="0"} 75 85 70 70 stale
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests < 100`)
|
||||
require.NoError(t, err)
|
||||
|
@ -158,7 +166,7 @@ func TestAlertingRuleLabelsUpdate(t *testing.T) {
|
|||
t.Logf("case %d", i)
|
||||
evalTime := baseTime.Add(time.Duration(i) * time.Minute)
|
||||
result[0].T = timestamp.FromTime(evalTime)
|
||||
res, err := rule.Eval(suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
res, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
var filteredRes promql.Vector // After removing 'ALERTS_FOR_STATE' samples.
|
||||
|
@ -175,20 +183,17 @@ func TestAlertingRuleLabelsUpdate(t *testing.T) {
|
|||
require.Equal(t, result, filteredRes)
|
||||
}
|
||||
evalTime := baseTime.Add(time.Duration(len(results)) * time.Minute)
|
||||
res, err := rule.Eval(suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
res, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(res))
|
||||
}
|
||||
|
||||
func TestAlertingRuleExternalLabelsInTemplate(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
http_requests{job="app-server", instance="0"} 75 85 70 70
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests < 100`)
|
||||
require.NoError(t, err)
|
||||
|
@ -246,7 +251,7 @@ func TestAlertingRuleExternalLabelsInTemplate(t *testing.T) {
|
|||
|
||||
var filteredRes promql.Vector // After removing 'ALERTS_FOR_STATE' samples.
|
||||
res, err := ruleWithoutExternalLabels.Eval(
|
||||
suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0,
|
||||
context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
for _, smpl := range res {
|
||||
|
@ -260,7 +265,7 @@ func TestAlertingRuleExternalLabelsInTemplate(t *testing.T) {
|
|||
}
|
||||
|
||||
res, err = ruleWithExternalLabels.Eval(
|
||||
suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0,
|
||||
context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
for _, smpl := range res {
|
||||
|
@ -277,14 +282,11 @@ func TestAlertingRuleExternalLabelsInTemplate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAlertingRuleExternalURLInTemplate(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
http_requests{job="app-server", instance="0"} 75 85 70 70
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests < 100`)
|
||||
require.NoError(t, err)
|
||||
|
@ -342,7 +344,7 @@ func TestAlertingRuleExternalURLInTemplate(t *testing.T) {
|
|||
|
||||
var filteredRes promql.Vector // After removing 'ALERTS_FOR_STATE' samples.
|
||||
res, err := ruleWithoutExternalURL.Eval(
|
||||
suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0,
|
||||
context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
for _, smpl := range res {
|
||||
|
@ -356,7 +358,7 @@ func TestAlertingRuleExternalURLInTemplate(t *testing.T) {
|
|||
}
|
||||
|
||||
res, err = ruleWithExternalURL.Eval(
|
||||
suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0,
|
||||
context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
for _, smpl := range res {
|
||||
|
@ -373,14 +375,11 @@ func TestAlertingRuleExternalURLInTemplate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAlertingRuleEmptyLabelFromTemplate(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
http_requests{job="app-server", instance="0"} 75 85 70 70
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests < 100`)
|
||||
require.NoError(t, err)
|
||||
|
@ -414,7 +413,7 @@ func TestAlertingRuleEmptyLabelFromTemplate(t *testing.T) {
|
|||
|
||||
var filteredRes promql.Vector // After removing 'ALERTS_FOR_STATE' samples.
|
||||
res, err := rule.Eval(
|
||||
suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0,
|
||||
context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
for _, smpl := range res {
|
||||
|
@ -430,14 +429,11 @@ func TestAlertingRuleEmptyLabelFromTemplate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAlertingRuleQueryInTemplate(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
http_requests{job="app-server", instance="0"} 70 85 70 70
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`sum(http_requests) < 100`)
|
||||
require.NoError(t, err)
|
||||
|
@ -473,7 +469,7 @@ instance: {{ $v.Labels.instance }}, value: {{ printf "%.0f" $v.Value }};
|
|||
require.Fail(t, "unexpected blocking when template expanding.")
|
||||
}
|
||||
}
|
||||
return EngineQueryFunc(suite.QueryEngine(), suite.Storage())(ctx, q, ts)
|
||||
return EngineQueryFunc(testEngine, storage)(ctx, q, ts)
|
||||
}
|
||||
go func() {
|
||||
<-startQueryCh
|
||||
|
@ -484,7 +480,7 @@ instance: {{ $v.Labels.instance }}, value: {{ printf "%.0f" $v.Value }};
|
|||
close(getDoneCh)
|
||||
}()
|
||||
_, err = ruleWithQueryInTemplate.Eval(
|
||||
suite.Context(), evalTime, slowQueryFunc, nil, 0,
|
||||
context.TODO(), evalTime, slowQueryFunc, nil, 0,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
@ -542,15 +538,12 @@ func TestAlertingRuleDuplicate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAlertingRuleLimit(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
metric{label="1"} 1
|
||||
metric{label="2"} 1
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
tests := []struct {
|
||||
limit int
|
||||
|
@ -587,7 +580,7 @@ func TestAlertingRuleLimit(t *testing.T) {
|
|||
evalTime := time.Unix(0, 0)
|
||||
|
||||
for _, test := range tests {
|
||||
switch _, err := rule.Eval(suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, test.limit); {
|
||||
switch _, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, test.limit); {
|
||||
case err != nil:
|
||||
require.EqualError(t, err, test.err)
|
||||
case test.err != "":
|
||||
|
@ -729,14 +722,11 @@ func TestSendAlertsDontAffectActiveAlerts(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKeepFiringFor(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
http_requests{job="app-server", instance="0"} 75 85 70 70 10x5
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests > 50`)
|
||||
require.NoError(t, err)
|
||||
|
@ -819,7 +809,7 @@ func TestKeepFiringFor(t *testing.T) {
|
|||
t.Logf("case %d", i)
|
||||
evalTime := baseTime.Add(time.Duration(i) * time.Minute)
|
||||
result[0].T = timestamp.FromTime(evalTime)
|
||||
res, err := rule.Eval(suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
res, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
var filteredRes promql.Vector // After removing 'ALERTS_FOR_STATE' samples.
|
||||
|
@ -836,20 +826,17 @@ func TestKeepFiringFor(t *testing.T) {
|
|||
require.Equal(t, result, filteredRes)
|
||||
}
|
||||
evalTime := baseTime.Add(time.Duration(len(results)) * time.Minute)
|
||||
res, err := rule.Eval(suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
res, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(res))
|
||||
}
|
||||
|
||||
func TestPendingAndKeepFiringFor(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
http_requests{job="app-server", instance="0"} 75 10x10
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests > 50`)
|
||||
require.NoError(t, err)
|
||||
|
@ -876,7 +863,7 @@ func TestPendingAndKeepFiringFor(t *testing.T) {
|
|||
|
||||
baseTime := time.Unix(0, 0)
|
||||
result.T = timestamp.FromTime(baseTime)
|
||||
res, err := rule.Eval(suite.Context(), baseTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
res, err := rule.Eval(context.TODO(), baseTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, res, 2)
|
||||
|
@ -891,7 +878,7 @@ func TestPendingAndKeepFiringFor(t *testing.T) {
|
|||
}
|
||||
|
||||
evalTime := baseTime.Add(time.Minute)
|
||||
res, err = rule.Eval(suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
res, err = rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(res))
|
||||
}
|
||||
|
|
|
@ -47,16 +47,12 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
|
||||
func TestAlertingRule(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 5m
|
||||
http_requests{job="app-server", instance="0", group="canary", severity="overwrite-me"} 75 85 95 105 105 95 85
|
||||
http_requests{job="app-server", instance="1", group="canary", severity="overwrite-me"} 80 90 100 110 120 130 140
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
err = suite.Run()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests{group="canary", job="app-server"} < 100`)
|
||||
require.NoError(t, err)
|
||||
|
@ -161,7 +157,7 @@ func TestAlertingRule(t *testing.T) {
|
|||
|
||||
evalTime := baseTime.Add(test.time)
|
||||
|
||||
res, err := rule.Eval(suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
res, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
var filteredRes promql.Vector // After removing 'ALERTS_FOR_STATE' samples.
|
||||
|
@ -191,16 +187,12 @@ func TestAlertingRule(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestForStateAddSamples(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 5m
|
||||
http_requests{job="app-server", instance="0", group="canary", severity="overwrite-me"} 75 85 95 105 105 95 85
|
||||
http_requests{job="app-server", instance="1", group="canary", severity="overwrite-me"} 80 90 100 110 120 130 140
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
err = suite.Run()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests{group="canary", job="app-server"} < 100`)
|
||||
require.NoError(t, err)
|
||||
|
@ -311,7 +303,7 @@ func TestForStateAddSamples(t *testing.T) {
|
|||
forState = float64(value.StaleNaN)
|
||||
}
|
||||
|
||||
res, err := rule.Eval(suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
res, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
var filteredRes promql.Vector // After removing 'ALERTS' samples.
|
||||
|
@ -353,24 +345,20 @@ func sortAlerts(items []*Alert) {
|
|||
}
|
||||
|
||||
func TestForStateRestore(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 5m
|
||||
http_requests{job="app-server", instance="0", group="canary", severity="overwrite-me"} 75 85 50 0 0 25 0 0 40 0 120
|
||||
http_requests{job="app-server", instance="1", group="canary", severity="overwrite-me"} 125 90 60 0 0 25 0 0 40 0 130
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
err = suite.Run()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests{group="canary", job="app-server"} < 100`)
|
||||
require.NoError(t, err)
|
||||
|
||||
opts := &ManagerOptions{
|
||||
QueryFunc: EngineQueryFunc(suite.QueryEngine(), suite.Storage()),
|
||||
Appendable: suite.Storage(),
|
||||
Queryable: suite.Storage(),
|
||||
QueryFunc: EngineQueryFunc(testEngine, storage),
|
||||
Appendable: storage,
|
||||
Queryable: storage,
|
||||
Context: context.Background(),
|
||||
Logger: log.NewNopLogger(),
|
||||
NotifyFunc: func(ctx context.Context, expr string, alerts ...*Alert) {},
|
||||
|
@ -404,7 +392,7 @@ func TestForStateRestore(t *testing.T) {
|
|||
baseTime := time.Unix(0, 0)
|
||||
for _, duration := range initialRuns {
|
||||
evalTime := baseTime.Add(duration)
|
||||
group.Eval(suite.Context(), evalTime)
|
||||
group.Eval(context.TODO(), evalTime)
|
||||
}
|
||||
|
||||
exp := rule.ActiveAlerts()
|
||||
|
@ -468,7 +456,7 @@ func TestForStateRestore(t *testing.T) {
|
|||
|
||||
restoreTime := baseTime.Add(tst.restoreDuration)
|
||||
// First eval before restoration.
|
||||
newGroup.Eval(suite.Context(), restoreTime)
|
||||
newGroup.Eval(context.TODO(), restoreTime)
|
||||
// Restore happens here.
|
||||
newGroup.RestoreForState(restoreTime)
|
||||
|
||||
|
@ -515,7 +503,7 @@ func TestForStateRestore(t *testing.T) {
|
|||
// Testing the grace period.
|
||||
for _, duration := range []time.Duration{10 * time.Minute, 15 * time.Minute, 20 * time.Minute} {
|
||||
evalTime := baseTime.Add(duration)
|
||||
group.Eval(suite.Context(), evalTime)
|
||||
group.Eval(context.TODO(), evalTime)
|
||||
}
|
||||
testFunc(testInput{
|
||||
restoreDuration: 25 * time.Minute,
|
||||
|
@ -1239,16 +1227,11 @@ func TestRuleHealthUpdates(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRuleGroupEvalIterationFunc(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 5m
|
||||
http_requests{instance="0"} 75 85 50 0 0 25 0 0 40 0 120
|
||||
`)
|
||||
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
err = suite.Run()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
expr, err := parser.ParseExpr(`http_requests{group="canary", job="app-server"} < 100`)
|
||||
require.NoError(t, err)
|
||||
|
@ -1294,9 +1277,9 @@ func TestRuleGroupEvalIterationFunc(t *testing.T) {
|
|||
|
||||
testFunc := func(tst testInput) {
|
||||
opts := &ManagerOptions{
|
||||
QueryFunc: EngineQueryFunc(suite.QueryEngine(), suite.Storage()),
|
||||
Appendable: suite.Storage(),
|
||||
Queryable: suite.Storage(),
|
||||
QueryFunc: EngineQueryFunc(testEngine, storage),
|
||||
Appendable: storage,
|
||||
Queryable: storage,
|
||||
Context: context.Background(),
|
||||
Logger: log.NewNopLogger(),
|
||||
NotifyFunc: func(ctx context.Context, expr string, alerts ...*Alert) {},
|
||||
|
@ -1361,15 +1344,11 @@ func TestRuleGroupEvalIterationFunc(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNativeHistogramsInRecordingRules(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, "")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(suite.Close)
|
||||
|
||||
err = suite.Run()
|
||||
require.NoError(t, err)
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
// Add some histograms.
|
||||
db := suite.TSDB()
|
||||
db := storage.DB
|
||||
hists := tsdbutil.GenerateTestHistograms(5)
|
||||
ts := time.Now()
|
||||
app := db.Appender(context.Background())
|
||||
|
@ -1381,9 +1360,9 @@ func TestNativeHistogramsInRecordingRules(t *testing.T) {
|
|||
require.NoError(t, app.Commit())
|
||||
|
||||
opts := &ManagerOptions{
|
||||
QueryFunc: EngineQueryFunc(suite.QueryEngine(), suite.Storage()),
|
||||
Appendable: suite.Storage(),
|
||||
Queryable: suite.Storage(),
|
||||
QueryFunc: EngineQueryFunc(testEngine, storage),
|
||||
Appendable: storage,
|
||||
Queryable: storage,
|
||||
Context: context.Background(),
|
||||
Logger: log.NewNopLogger(),
|
||||
}
|
||||
|
|
|
@ -109,27 +109,22 @@ var ruleEvalTestScenarios = []struct {
|
|||
},
|
||||
}
|
||||
|
||||
func setUpRuleEvalTest(t require.TestingT) *promql.Test {
|
||||
suite, err := promql.NewTest(t, `
|
||||
func setUpRuleEvalTest(t require.TestingT) *teststorage.TestStorage {
|
||||
return promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
metric{label_a="1",label_b="3"} 1
|
||||
metric{label_a="2",label_b="4"} 10
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
|
||||
return suite
|
||||
}
|
||||
|
||||
func TestRuleEval(t *testing.T) {
|
||||
suite := setUpRuleEvalTest(t)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
storage := setUpRuleEvalTest(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
for _, scenario := range ruleEvalTestScenarios {
|
||||
t.Run(scenario.name, func(t *testing.T) {
|
||||
rule := NewRecordingRule("test_rule", scenario.expr, scenario.ruleLabels)
|
||||
result, err := rule.Eval(suite.Context(), ruleEvaluationTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
result, err := rule.Eval(context.TODO(), ruleEvaluationTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, scenario.expected, result)
|
||||
})
|
||||
|
@ -137,10 +132,8 @@ func TestRuleEval(t *testing.T) {
|
|||
}
|
||||
|
||||
func BenchmarkRuleEval(b *testing.B) {
|
||||
suite := setUpRuleEvalTest(b)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(b, suite.Run())
|
||||
storage := setUpRuleEvalTest(b)
|
||||
b.Cleanup(func() { storage.Close() })
|
||||
|
||||
for _, scenario := range ruleEvalTestScenarios {
|
||||
b.Run(scenario.name, func(b *testing.B) {
|
||||
|
@ -149,7 +142,7 @@ func BenchmarkRuleEval(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := rule.Eval(suite.Context(), ruleEvaluationTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, 0)
|
||||
_, err := rule.Eval(context.TODO(), ruleEvaluationTime, EngineQueryFunc(testEngine, storage), nil, 0)
|
||||
if err != nil {
|
||||
require.NoError(b, err)
|
||||
}
|
||||
|
@ -184,15 +177,12 @@ func TestRuleEvalDuplicate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRecordingRuleLimit(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
metric{label="1"} 1
|
||||
metric{label="2"} 1
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
tests := []struct {
|
||||
limit int
|
||||
|
@ -223,7 +213,7 @@ func TestRecordingRuleLimit(t *testing.T) {
|
|||
evalTime := time.Unix(0, 0)
|
||||
|
||||
for _, test := range tests {
|
||||
switch _, err := rule.Eval(suite.Context(), evalTime, EngineQueryFunc(suite.QueryEngine(), suite.Storage()), nil, test.limit); {
|
||||
switch _, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, test.limit); {
|
||||
case err != nil:
|
||||
require.EqualError(t, err, test.err)
|
||||
case test.err != "":
|
||||
|
|
|
@ -33,22 +33,19 @@ import (
|
|||
"github.com/prometheus/prometheus/promql"
|
||||
"github.com/prometheus/prometheus/storage"
|
||||
"github.com/prometheus/prometheus/tsdb/tsdbutil"
|
||||
"github.com/prometheus/prometheus/util/teststorage"
|
||||
)
|
||||
|
||||
func TestSampledReadEndpoint(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
store := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
test_metric1{foo="bar",baz="qux"} 1
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
defer store.Close()
|
||||
|
||||
addNativeHistogramsToTestSuite(t, suite, 1)
|
||||
addNativeHistogramsToTestSuite(t, store, 1)
|
||||
|
||||
err = suite.Run()
|
||||
require.NoError(t, err)
|
||||
|
||||
h := NewReadHandler(nil, nil, suite.Storage(), func() config.Config {
|
||||
h := NewReadHandler(nil, nil, store, func() config.Config {
|
||||
return config.Config{
|
||||
GlobalConfig: config.GlobalConfig{
|
||||
// We expect external labels to be added, with the source labels honored.
|
||||
|
@ -135,19 +132,16 @@ func TestSampledReadEndpoint(t *testing.T) {
|
|||
}
|
||||
|
||||
func BenchmarkStreamReadEndpoint(b *testing.B) {
|
||||
suite, err := promql.NewTest(b, `
|
||||
store := promql.LoadedStorage(b, `
|
||||
load 1m
|
||||
test_metric1{foo="bar1",baz="qux"} 0+100x119
|
||||
test_metric1{foo="bar2",baz="qux"} 0+100x120
|
||||
test_metric1{foo="bar3",baz="qux"} 0+100x240
|
||||
`)
|
||||
require.NoError(b, err)
|
||||
|
||||
defer suite.Close()
|
||||
b.Cleanup(func() { store.Close() })
|
||||
|
||||
require.NoError(b, suite.Run())
|
||||
|
||||
api := NewReadHandler(nil, nil, suite.Storage(), func() config.Config {
|
||||
api := NewReadHandler(nil, nil, store, func() config.Config {
|
||||
return config.Config{}
|
||||
},
|
||||
0, 1, 0,
|
||||
|
@ -206,20 +200,17 @@ func TestStreamReadEndpoint(t *testing.T) {
|
|||
// Second with 121 samples, We expect 1 frame with 2 chunks.
|
||||
// Third with 241 samples. We expect 1 frame with 2 chunks, and 1 frame with 1 chunk for the same series due to bytes limit.
|
||||
// Fourth with 120 histogram samples. We expect 1 frame with 1 chunk.
|
||||
suite, err := promql.NewTest(t, `
|
||||
store := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
test_metric1{foo="bar1",baz="qux"} 0+100x119
|
||||
test_metric1{foo="bar2",baz="qux"} 0+100x120
|
||||
test_metric1{foo="bar3",baz="qux"} 0+100x240
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
defer store.Close()
|
||||
|
||||
addNativeHistogramsToTestSuite(t, suite, 120)
|
||||
addNativeHistogramsToTestSuite(t, store, 120)
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
|
||||
api := NewReadHandler(nil, nil, suite.Storage(), func() config.Config {
|
||||
api := NewReadHandler(nil, nil, store, func() config.Config {
|
||||
return config.Config{
|
||||
GlobalConfig: config.GlobalConfig{
|
||||
// We expect external labels to be added, with the source labels honored.
|
||||
|
@ -440,10 +431,10 @@ func TestStreamReadEndpoint(t *testing.T) {
|
|||
}, results)
|
||||
}
|
||||
|
||||
func addNativeHistogramsToTestSuite(t *testing.T, pqlTest *promql.Test, n int) {
|
||||
func addNativeHistogramsToTestSuite(t *testing.T, storage *teststorage.TestStorage, n int) {
|
||||
lbls := labels.FromStrings("__name__", "test_histogram_metric1", "baz", "qux")
|
||||
|
||||
app := pqlTest.Storage().Appender(context.TODO())
|
||||
app := storage.Appender(context.TODO())
|
||||
for i, fh := range tsdbutil.GenerateTestFloatHistograms(n) {
|
||||
_, err := app.AppendHistogram(0, lbls, int64(i)*int64(60*time.Second/time.Millisecond), nil, fh)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -56,6 +56,17 @@ import (
|
|||
"github.com/prometheus/prometheus/util/teststorage"
|
||||
)
|
||||
|
||||
var testEngine = promql.NewEngine(promql.EngineOpts{
|
||||
Logger: nil,
|
||||
Reg: nil,
|
||||
MaxSamples: 10000,
|
||||
Timeout: 100 * time.Second,
|
||||
NoStepSubqueryIntervalFn: func(int64) int64 { return 60 * 1000 },
|
||||
EnableAtModifier: true,
|
||||
EnableNegativeOffset: true,
|
||||
EnablePerStepStats: true,
|
||||
})
|
||||
|
||||
// testMetaStore satisfies the scrape.MetricMetadataStore interface.
|
||||
// It is used to inject specific metadata as part of a test case.
|
||||
type testMetaStore struct {
|
||||
|
@ -305,7 +316,7 @@ var sampleFlagMap = map[string]string{
|
|||
}
|
||||
|
||||
func TestEndpoints(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
test_metric1{foo="bar"} 0+100x100
|
||||
test_metric1{foo="boo"} 1+0x100
|
||||
|
@ -316,6 +327,7 @@ func TestEndpoints(t *testing.T) {
|
|||
test_metric4{foo="boo", dup="1"} 1+0x100
|
||||
test_metric4{foo="boo"} 1+0x100
|
||||
`)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
start := time.Unix(0, 0)
|
||||
exemplars := []exemplar.QueryResult{
|
||||
|
@ -361,15 +373,10 @@ func TestEndpoints(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, ed := range exemplars {
|
||||
suite.ExemplarStorage().AppendExemplar(0, ed.SeriesLabels, ed.Exemplars[0])
|
||||
_, err := storage.AppendExemplar(0, ed.SeriesLabels, ed.Exemplars[0])
|
||||
require.NoError(t, err, "failed to add exemplar: %+v", ed.Exemplars[0])
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
|
||||
require.NoError(t, suite.Run())
|
||||
|
||||
now := time.Now()
|
||||
|
||||
t.Run("local", func(t *testing.T) {
|
||||
|
@ -383,9 +390,9 @@ func TestEndpoints(t *testing.T) {
|
|||
testTargetRetriever := setupTestTargetRetriever(t)
|
||||
|
||||
api := &API{
|
||||
Queryable: suite.Storage(),
|
||||
QueryEngine: suite.QueryEngine(),
|
||||
ExemplarQueryable: suite.ExemplarQueryable(),
|
||||
Queryable: storage,
|
||||
QueryEngine: testEngine,
|
||||
ExemplarQueryable: storage.ExemplarQueryable(),
|
||||
targetRetriever: testTargetRetriever.toFactory(),
|
||||
alertmanagerRetriever: testAlertmanagerRetriever{}.toFactory(),
|
||||
flagsMap: sampleFlagMap,
|
||||
|
@ -394,14 +401,14 @@ func TestEndpoints(t *testing.T) {
|
|||
ready: func(f http.HandlerFunc) http.HandlerFunc { return f },
|
||||
rulesRetriever: algr.toFactory(),
|
||||
}
|
||||
testEndpoints(t, api, testTargetRetriever, suite.ExemplarStorage(), true)
|
||||
testEndpoints(t, api, testTargetRetriever, storage, true)
|
||||
})
|
||||
|
||||
// Run all the API tests against a API that is wired to forward queries via
|
||||
// the remote read client to a test server, which in turn sends them to the
|
||||
// data from the test suite.
|
||||
// data from the test storage.
|
||||
t.Run("remote", func(t *testing.T) {
|
||||
server := setupRemote(suite.Storage())
|
||||
server := setupRemote(storage)
|
||||
defer server.Close()
|
||||
|
||||
u, err := url.Parse(server.URL)
|
||||
|
@ -446,8 +453,8 @@ func TestEndpoints(t *testing.T) {
|
|||
|
||||
api := &API{
|
||||
Queryable: remote,
|
||||
QueryEngine: suite.QueryEngine(),
|
||||
ExemplarQueryable: suite.ExemplarQueryable(),
|
||||
QueryEngine: testEngine,
|
||||
ExemplarQueryable: storage.ExemplarQueryable(),
|
||||
targetRetriever: testTargetRetriever.toFactory(),
|
||||
alertmanagerRetriever: testAlertmanagerRetriever{}.toFactory(),
|
||||
flagsMap: sampleFlagMap,
|
||||
|
@ -456,8 +463,7 @@ func TestEndpoints(t *testing.T) {
|
|||
ready: func(f http.HandlerFunc) http.HandlerFunc { return f },
|
||||
rulesRetriever: algr.toFactory(),
|
||||
}
|
||||
|
||||
testEndpoints(t, api, testTargetRetriever, suite.ExemplarStorage(), false)
|
||||
testEndpoints(t, api, testTargetRetriever, storage, false)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -470,7 +476,7 @@ func (b byLabels) Less(i, j int) bool { return labels.Compare(b[i], b[j]) < 0 }
|
|||
func TestGetSeries(t *testing.T) {
|
||||
// TestEndpoints doesn't have enough label names to test api.labelNames
|
||||
// endpoint properly. Hence we test it separately.
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
test_metric1{foo1="bar", baz="abc"} 0+100x100
|
||||
test_metric1{foo2="boo"} 1+0x100
|
||||
|
@ -478,11 +484,9 @@ func TestGetSeries(t *testing.T) {
|
|||
test_metric2{foo="boo", xyz="qwerty"} 1+0x100
|
||||
test_metric2{foo="baz", abc="qwerty"} 1+0x100
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
api := &API{
|
||||
Queryable: suite.Storage(),
|
||||
Queryable: storage,
|
||||
}
|
||||
request := func(method string, matchers ...string) (*http.Request, error) {
|
||||
u, err := url.Parse("http://example.com")
|
||||
|
@ -576,7 +580,7 @@ func TestGetSeries(t *testing.T) {
|
|||
|
||||
func TestQueryExemplars(t *testing.T) {
|
||||
start := time.Unix(0, 0)
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
test_metric1{foo="bar"} 0+100x100
|
||||
test_metric1{foo="boo"} 1+0x100
|
||||
|
@ -587,15 +591,12 @@ func TestQueryExemplars(t *testing.T) {
|
|||
test_metric4{foo="boo", dup="1"} 1+0x100
|
||||
test_metric4{foo="boo"} 1+0x100
|
||||
`)
|
||||
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
api := &API{
|
||||
Queryable: suite.Storage(),
|
||||
QueryEngine: suite.QueryEngine(),
|
||||
ExemplarQueryable: suite.ExemplarQueryable(),
|
||||
Queryable: storage,
|
||||
QueryEngine: testEngine,
|
||||
ExemplarQueryable: storage.ExemplarQueryable(),
|
||||
}
|
||||
|
||||
request := func(method string, qs url.Values) (*http.Request, error) {
|
||||
|
@ -673,7 +674,7 @@ func TestQueryExemplars(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
es := suite.ExemplarStorage()
|
||||
es := storage
|
||||
ctx := context.Background()
|
||||
|
||||
for _, te := range tc.exemplars {
|
||||
|
@ -700,7 +701,7 @@ func TestQueryExemplars(t *testing.T) {
|
|||
func TestLabelNames(t *testing.T) {
|
||||
// TestEndpoints doesn't have enough label names to test api.labelNames
|
||||
// endpoint properly. Hence we test it separately.
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
test_metric1{foo1="bar", baz="abc"} 0+100x100
|
||||
test_metric1{foo2="boo"} 1+0x100
|
||||
|
@ -708,11 +709,9 @@ func TestLabelNames(t *testing.T) {
|
|||
test_metric2{foo="boo", xyz="qwerty"} 1+0x100
|
||||
test_metric2{foo="baz", abc="qwerty"} 1+0x100
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
require.NoError(t, suite.Run())
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
api := &API{
|
||||
Queryable: suite.Storage(),
|
||||
Queryable: storage,
|
||||
}
|
||||
request := func(method string, matchers ...string) (*http.Request, error) {
|
||||
u, err := url.Parse("http://example.com")
|
||||
|
@ -801,14 +800,12 @@ func (testStats) Builtin() (_ stats.BuiltinStats) {
|
|||
}
|
||||
|
||||
func TestStats(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, ``)
|
||||
require.NoError(t, err)
|
||||
defer suite.Close()
|
||||
require.NoError(t, suite.Run())
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
api := &API{
|
||||
Queryable: suite.Storage(),
|
||||
QueryEngine: suite.QueryEngine(),
|
||||
Queryable: storage,
|
||||
QueryEngine: testEngine,
|
||||
now: func() time.Time {
|
||||
return time.Unix(123, 0)
|
||||
},
|
||||
|
|
|
@ -36,6 +36,7 @@ import (
|
|||
"github.com/prometheus/prometheus/promql"
|
||||
"github.com/prometheus/prometheus/storage"
|
||||
"github.com/prometheus/prometheus/tsdb"
|
||||
"github.com/prometheus/prometheus/util/teststorage"
|
||||
)
|
||||
|
||||
var scenarios = map[string]struct {
|
||||
|
@ -199,7 +200,7 @@ test_metric_without_labels{instance="baz"} 1001 6000000
|
|||
}
|
||||
|
||||
func TestFederation(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, `
|
||||
storage := promql.LoadedStorage(t, `
|
||||
load 1m
|
||||
test_metric1{foo="bar",instance="i"} 0+100x100
|
||||
test_metric1{foo="boo",instance="i"} 1+0x100
|
||||
|
@ -208,17 +209,10 @@ func TestFederation(t *testing.T) {
|
|||
test_metric_stale 1+10x99 stale
|
||||
test_metric_old 1+10x98
|
||||
`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer suite.Close()
|
||||
|
||||
if err := suite.Run(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
h := &Handler{
|
||||
localStorage: &dbAdapter{suite.TSDB()},
|
||||
localStorage: &dbAdapter{storage.DB},
|
||||
lookbackDelta: 5 * time.Minute,
|
||||
now: func() model.Time { return 101 * 60 * 1000 }, // 101min after epoch.
|
||||
config: &config.Config{
|
||||
|
@ -305,19 +299,12 @@ func normalizeBody(body *bytes.Buffer) string {
|
|||
}
|
||||
|
||||
func TestFederationWithNativeHistograms(t *testing.T) {
|
||||
suite, err := promql.NewTest(t, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer suite.Close()
|
||||
|
||||
if err := suite.Run(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
storage := teststorage.New(t)
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
|
||||
var expVec promql.Vector
|
||||
|
||||
db := suite.TSDB()
|
||||
db := storage.DB
|
||||
hist := &histogram.Histogram{
|
||||
Count: 10,
|
||||
ZeroCount: 2,
|
||||
|
@ -354,6 +341,7 @@ func TestFederationWithNativeHistograms(t *testing.T) {
|
|||
for i := 0; i < 6; i++ {
|
||||
l := labels.FromStrings("__name__", "test_metric", "foo", fmt.Sprintf("%d", i))
|
||||
expL := labels.FromStrings("__name__", "test_metric", "instance", "", "foo", fmt.Sprintf("%d", i))
|
||||
var err error
|
||||
switch i {
|
||||
case 0, 3:
|
||||
_, err = app.Append(0, l, 100*60*1000, float64(i*100))
|
||||
|
@ -383,7 +371,7 @@ func TestFederationWithNativeHistograms(t *testing.T) {
|
|||
require.NoError(t, app.Commit())
|
||||
|
||||
h := &Handler{
|
||||
localStorage: &dbAdapter{suite.TSDB()},
|
||||
localStorage: &dbAdapter{db},
|
||||
lookbackDelta: 5 * time.Minute,
|
||||
now: func() model.Time { return 101 * 60 * 1000 }, // 101min after epoch.
|
||||
config: &config.Config{
|
||||
|
|
Loading…
Reference in a new issue