Skip to content

Commit

Permalink
Store: add some acceptance tests for label matching
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaHoffmann committed Sep 1, 2023
1 parent 18561b4 commit 883aa43
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 9 deletions.
231 changes: 229 additions & 2 deletions pkg/store/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/timestamp"
"github.com/prometheus/prometheus/storage"
"golang.org/x/exp/slices"

"github.com/efficientgo/core/testutil"
"github.com/thanos-io/thanos/pkg/store/storepb"
Expand All @@ -37,8 +38,17 @@ type labelValuesCallCase struct {
expectErr error
}

// testLabelAPIs tests labels methods from StoreAPI from closed box perspective.
func testLabelAPIs(t *testing.T, startStore func(t *testing.T, extLset labels.Labels, append func(app storage.Appender)) storepb.StoreServer) {
type seriesCallCase struct {
matchers []storepb.LabelMatcher
start int64
end int64

expectedLabels []labels.Labels
expectErr error
}

// testStoreAPIsAcceptance tests StoreAPI from closed box perspective.
func testStoreAPIsAcceptance(t *testing.T, startStore func(t *testing.T, extLset labels.Labels, append func(app storage.Appender)) storepb.StoreServer) {
t.Helper()

now := time.Now()
Expand All @@ -48,6 +58,7 @@ func testLabelAPIs(t *testing.T, startStore func(t *testing.T, extLset labels.La
appendFn func(app storage.Appender)
labelNameCalls []labelNameCallCase
labelValuesCalls []labelValuesCallCase
seriesCalls []seriesCallCase
}{
{
desc: "no label in tsdb, empty results",
Expand Down Expand Up @@ -187,6 +198,198 @@ func testLabelAPIs(t *testing.T, startStore func(t *testing.T, extLset labels.La
},
},
},
{
// Tests mostly taken from https://github.com/prometheus/prometheus/blob/95e705612c1d557f1681bd081a841b78f93ee158/tsdb/querier_test.go#L1898, though some are still missing
desc: "matching behavior",
appendFn: func(app storage.Appender) {
_, err := app.Append(0, labels.FromStrings("n", "1"), 0, 0)
testutil.Ok(t, err)
_, err = app.Append(0, labels.FromStrings("n", "1", "i", "a"), 0, 0)
testutil.Ok(t, err)
_, err = app.Append(0, labels.FromStrings("n", "1", "i", "b"), 0, 0)
testutil.Ok(t, err)
_, err = app.Append(0, labels.FromStrings("n", "2"), 0, 0)
testutil.Ok(t, err)
_, err = app.Append(0, labels.FromStrings("n", "2.5"), 0, 0)
testutil.Ok(t, err)

testutil.Ok(t, app.Commit())
},
seriesCalls: []seriesCallCase{
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "a", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "b", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
{Type: storepb.LabelMatcher_EQ, Name: "i", Value: "a"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "i", "a", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
{Type: storepb.LabelMatcher_EQ, Name: "i", Value: "missing"},
},
expectedLabels: []labels.Labels{},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_EQ, Name: "missing", Value: ""},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "a", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "b", "region", "eu-west"),
labels.FromStrings("n", "2", "region", "eu-west"),
labels.FromStrings("n", "2.5", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_NEQ, Name: "n", Value: "1"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "2", "region", "eu-west"),
labels.FromStrings("n", "2.5", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_RE, Name: "i", Value: ".+"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "i", "a", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "b", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_RE, Name: "i", Value: ".*"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "a", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "b", "region", "eu-west"),
labels.FromStrings("n", "2", "region", "eu-west"),
labels.FromStrings("n", "2.5", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_EQ, Name: "i", Value: ""},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "region", "eu-west"),
labels.FromStrings("n", "2", "region", "eu-west"),
labels.FromStrings("n", "2.5", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_NEQ, Name: "i", Value: ""},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "i", "a", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "b", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_NEQ, Name: "missing", Value: ""},
},
expectedLabels: []labels.Labels{},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
{Type: storepb.LabelMatcher_NEQ, Name: "i", Value: "a"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "b", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_RE, Name: "n", Value: "^1$"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "a", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "b", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^a$"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "i", "a", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^a?$"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "region", "eu-west"),
labels.FromStrings("n", "1", "i", "a", "region", "eu-west"),
},
},
{
start: timestamp.FromTime(minTime),
end: timestamp.FromTime(maxTime),
matchers: []storepb.LabelMatcher{
{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^$"},
},
expectedLabels: []labels.Labels{
labels.FromStrings("n", "1", "region", "eu-west"),
labels.FromStrings("n", "2", "region", "eu-west"),
labels.FromStrings("n", "2.5", "region", "eu-west"),
},
},
},
},
} {
t.Run(tc.desc, func(t *testing.T) {
appendFn := tc.appendFn
Expand Down Expand Up @@ -236,6 +439,30 @@ func testLabelAPIs(t *testing.T, startStore func(t *testing.T, extLset labels.La
testutil.Equals(t, c.expectedValues, resp.Values)
})
}
for _, c := range tc.seriesCalls {
t.Run("series", func(t *testing.T) {
srv := newStoreSeriesServer(context.Background())
err := store.Series(&storepb.SeriesRequest{
MinTime: c.start,
MaxTime: c.end,
Matchers: c.matchers,
}, srv)
if c.expectErr != nil {
testutil.NotOk(t, err)
testutil.Equals(t, c.expectErr.Error(), err.Error())
return
}
testutil.Ok(t, err)

receivedLabels := make([]labels.Labels, 0)
for _, s := range srv.SeriesSet {
receivedLabels = append(receivedLabels, s.PromLabels())
}
slices.SortFunc(c.expectedLabels, func(a, b labels.Labels) bool { return labels.Compare(a, b) < 0 })
slices.SortFunc(receivedLabels, func(a, b labels.Labels) bool { return labels.Compare(a, b) < 0 })
testutil.Equals(t, c.expectedLabels, receivedLabels)
})
}
})
}
}
4 changes: 2 additions & 2 deletions pkg/store/bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3342,10 +3342,10 @@ func TestBucketIndexReader_decodeCachedPostingsErrors(t *testing.T) {
})
}

func TestBucketStore_LabelAPIs(t *testing.T) {
func TestBucketStore_Acceptance(t *testing.T) {
t.Cleanup(func() { custom.TolerantVerifyLeak(t) })

testLabelAPIs(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer {
testStoreAPIsAcceptance(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer {
tmpDir := tt.TempDir()
bktDir := filepath.Join(tmpDir, "bkt")
auxDir := filepath.Join(tmpDir, "aux")
Expand Down
6 changes: 3 additions & 3 deletions pkg/store/prometheus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,9 @@ func TestPrometheusStore_SeriesLabels_e2e(t *testing.T) {
}
}

func TestPrometheusStore_LabelAPIs(t *testing.T) {
func TestPrometheusStore_Acceptance(t *testing.T) {
t.Cleanup(func() { custom.TolerantVerifyLeak(t) })
testLabelAPIs(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer {
testStoreAPIsAcceptance(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer {
p, err := e2eutil.NewPrometheus()
testutil.Ok(tt, err)
tt.Cleanup(func() { testutil.Ok(tt, p.Stop()) })
Expand All @@ -406,7 +406,7 @@ func TestPrometheusStore_LabelAPIs(t *testing.T) {

promStore, err := NewPrometheusStore(nil, nil, promclient.NewDefaultClient(), u, component.Sidecar,
func() labels.Labels { return extLset },
nil,
func() (int64, int64) { return timestamp.FromTime(minTime), timestamp.FromTime(maxTime) },
func() stringset.Set { return stringset.AllStrings() },
func() string { return version })
testutil.Ok(tt, err)
Expand Down
4 changes: 2 additions & 2 deletions pkg/store/tsdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,9 @@ func TestTSDBStore_Series(t *testing.T) {
}
}

func TestTSDBStore_LabelAPIs(t *testing.T) {
func TestTSDBStore_Acceptance(t *testing.T) {
t.Cleanup(func() { custom.TolerantVerifyLeak(t) })
testLabelAPIs(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer {
testStoreAPIsAcceptance(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer {
db, err := e2eutil.NewTSDB()
testutil.Ok(tt, err)
tt.Cleanup(func() { testutil.Ok(tt, db.Close()) })
Expand Down

0 comments on commit 883aa43

Please sign in to comment.