mirror of
https://github.com/prometheus/prometheus
synced 2024-12-30 19:03:03 +00:00
dbd7021cc2
* promql: refactor BenchmarkRangeQuery so we can re-use test cases Signed-off-by: Bryan Boreham <bjboreham@gmail.com> * promql: add test for race conditions in query engine Note we skip large count_values queries - `count_values` allocates a slice per unique value in the output, and this test has unique values on every step of every series so it adds up to a lot of slices. Add Go runtime overhead for checking `-race`, and it chews up many gigabytes. Signed-off-by: Bryan Boreham <bjboreham@gmail.com> * TestConcurrentRangeQueries: wait before starting goroutine Instead of starting 100 goroutines which just wait for the semaphore. Signed-off-by: Bryan Boreham <bjboreham@gmail.com> Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
100 lines
2.4 KiB
Go
100 lines
2.4 KiB
Go
// Copyright 2015 The Prometheus Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package promql
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/sync/errgroup"
|
|
|
|
"github.com/prometheus/prometheus/util/teststorage"
|
|
)
|
|
|
|
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()
|
|
})
|
|
}
|
|
}
|
|
|
|
// Run a lot of queries at the same time, to check for race conditions.
|
|
func TestConcurrentRangeQueries(t *testing.T) {
|
|
stor := teststorage.New(t)
|
|
defer stor.Close()
|
|
opts := EngineOpts{
|
|
Logger: nil,
|
|
Reg: nil,
|
|
MaxSamples: 50000000,
|
|
Timeout: 100 * time.Second,
|
|
}
|
|
engine := NewEngine(opts)
|
|
|
|
const interval = 10000 // 10s interval.
|
|
// A day of data plus 10k steps.
|
|
numIntervals := 8640 + 10000
|
|
err := setupRangeQueryTestData(stor, engine, interval, numIntervals)
|
|
require.NoError(t, err)
|
|
|
|
cases := rangeQueryCases()
|
|
|
|
// Limit the number of queries running at the same time.
|
|
const numConcurrent = 4
|
|
sem := make(chan struct{}, numConcurrent)
|
|
for i := 0; i < numConcurrent; i++ {
|
|
sem <- struct{}{}
|
|
}
|
|
var g errgroup.Group
|
|
for _, c := range cases {
|
|
c := c
|
|
if strings.Contains(c.expr, "count_values") && c.steps > 10 {
|
|
continue // This test is too big to run with -race.
|
|
}
|
|
<-sem
|
|
g.Go(func() error {
|
|
defer func() {
|
|
sem <- struct{}{}
|
|
}()
|
|
qry, err := engine.NewRangeQuery(
|
|
stor, nil, c.expr,
|
|
time.Unix(int64((numIntervals-c.steps)*10), 0),
|
|
time.Unix(int64(numIntervals*10), 0), time.Second*10)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
res := qry.Exec(context.Background())
|
|
if res.Err != nil {
|
|
return res.Err
|
|
}
|
|
qry.Close()
|
|
return nil
|
|
})
|
|
}
|
|
|
|
err = g.Wait()
|
|
require.NoError(t, err)
|
|
}
|