|
|
|
@ -22,6 +22,7 @@ import (
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"sort"
|
|
|
|
|
"strconv"
|
|
|
|
|
"sync"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
@ -2194,6 +2195,71 @@ func TestPostingsForMatchers(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestQuerierIndexQueriesRace tests the index queries with racing appends.
|
|
|
|
|
func TestQuerierIndexQueriesRace(t *testing.T) {
|
|
|
|
|
const testRepeats = 1000
|
|
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
matchers []*labels.Matcher
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
matchers: []*labels.Matcher{
|
|
|
|
|
// This matcher should involve the AllPostings posting list in calculating the posting lists.
|
|
|
|
|
labels.MustNewMatcher(labels.MatchNotEqual, labels.MetricName, "metric"),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
matchers: []*labels.Matcher{
|
|
|
|
|
// The first matcher should be effectively the same as AllPostings, because all series have always_0=0
|
|
|
|
|
// If it is evaluated first, then __name__=metric will contain more series than always_0=0.
|
|
|
|
|
labels.MustNewMatcher(labels.MatchNotEqual, "always_0", "0"),
|
|
|
|
|
labels.MustNewMatcher(labels.MatchEqual, labels.MetricName, "metric"),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, c := range testCases {
|
|
|
|
|
c := c
|
|
|
|
|
t.Run(fmt.Sprintf("%v", c.matchers), func(t *testing.T) {
|
|
|
|
|
db := openTestDB(t, DefaultOptions(), nil)
|
|
|
|
|
h := db.Head()
|
|
|
|
|
t.Cleanup(func() {
|
|
|
|
|
require.NoError(t, db.Close())
|
|
|
|
|
})
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
wg := &sync.WaitGroup{}
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
go appendSeries(t, ctx, wg, h)
|
|
|
|
|
t.Cleanup(wg.Wait)
|
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
|
|
for i := 0; i < testRepeats; i++ {
|
|
|
|
|
q, err := db.Querier(ctx, math.MinInt64, math.MaxInt64)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
values, _, err := q.LabelValues("seq", c.matchers...)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Emptyf(t, values, `label values for label "seq" should be empty`)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func appendSeries(t *testing.T, ctx context.Context, wg *sync.WaitGroup, h *Head) {
|
|
|
|
|
defer wg.Done()
|
|
|
|
|
|
|
|
|
|
for i := 0; ctx.Err() != nil; i++ {
|
|
|
|
|
app := h.Appender(context.Background())
|
|
|
|
|
_, err := app.Append(0, labels.FromStrings(labels.MetricName, "metric", "seq", strconv.Itoa(i), "always_0", "0"), 0, 0)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
err = app.Commit()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
// Throttle down the appends to keep the test somewhat nimble.
|
|
|
|
|
time.Sleep(time.Millisecond)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestClose ensures that calling Close more than once doesn't block and doesn't panic.
|
|
|
|
|
func TestClose(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
|
|
|
|