github.com/thanos-io/thanos@v0.32.5/pkg/store/acceptance_test.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package store
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"net/url"
    10  	"os"
    11  	"path/filepath"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/go-kit/log"
    16  	"github.com/pkg/errors"
    17  	"github.com/prometheus/prometheus/model/labels"
    18  	"github.com/prometheus/prometheus/model/timestamp"
    19  	"github.com/prometheus/prometheus/storage"
    20  	"github.com/prometheus/prometheus/tsdb"
    21  	"golang.org/x/exp/slices"
    22  
    23  	"github.com/efficientgo/core/testutil"
    24  	"github.com/thanos-io/objstore"
    25  	"github.com/thanos-io/objstore/providers/filesystem"
    26  	"github.com/thanos-io/thanos/pkg/block"
    27  	"github.com/thanos-io/thanos/pkg/block/metadata"
    28  	"github.com/thanos-io/thanos/pkg/component"
    29  	"github.com/thanos-io/thanos/pkg/promclient"
    30  	"github.com/thanos-io/thanos/pkg/store/storepb"
    31  	"github.com/thanos-io/thanos/pkg/testutil/custom"
    32  	"github.com/thanos-io/thanos/pkg/testutil/e2eutil"
    33  )
    34  
    35  type labelNameCallCase struct {
    36  	matchers []storepb.LabelMatcher
    37  	start    int64
    38  	end      int64
    39  
    40  	expectedNames []string
    41  	expectErr     error
    42  }
    43  
    44  type labelValuesCallCase struct {
    45  	label string
    46  
    47  	matchers []storepb.LabelMatcher
    48  	start    int64
    49  	end      int64
    50  
    51  	expectedValues []string
    52  	expectErr      error
    53  }
    54  
    55  type seriesCallCase struct {
    56  	matchers []storepb.LabelMatcher
    57  	start    int64
    58  	end      int64
    59  
    60  	expectedLabels []labels.Labels
    61  	expectErr      error
    62  }
    63  
    64  // testStoreAPIsAcceptance tests StoreAPI from closed box perspective.
    65  func testStoreAPIsAcceptance(t *testing.T, startStore func(t *testing.T, extLset labels.Labels, append func(app storage.Appender)) storepb.StoreServer) {
    66  	t.Helper()
    67  
    68  	now := time.Now()
    69  	extLset := labels.FromStrings("region", "eu-west")
    70  	for _, tc := range []struct {
    71  		desc             string
    72  		appendFn         func(app storage.Appender)
    73  		labelNameCalls   []labelNameCallCase
    74  		labelValuesCalls []labelValuesCallCase
    75  		seriesCalls      []seriesCallCase
    76  	}{
    77  		{
    78  			desc: "no label in tsdb, empty results",
    79  			labelNameCalls: []labelNameCallCase{
    80  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime)},
    81  			},
    82  			labelValuesCalls: []labelValuesCallCase{
    83  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), expectErr: errors.New("rpc error: code = InvalidArgument desc = label name parameter cannot be empty")},
    84  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "foo"},
    85  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "region", expectedValues: []string{"eu-west"}}, // External labels should be visible.
    86  			},
    87  		},
    88  		{
    89  			desc: "{foo=foovalue1} 1",
    90  			appendFn: func(app storage.Appender) {
    91  				_, err := app.Append(0, labels.FromStrings("foo", "foovalue1"), timestamp.FromTime(now), 1)
    92  				testutil.Ok(t, err)
    93  				testutil.Ok(t, app.Commit())
    94  			},
    95  			labelNameCalls: []labelNameCallCase{
    96  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), expectedNames: []string{"foo", "region"}},
    97  			},
    98  			labelValuesCalls: []labelValuesCallCase{
    99  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "foo", expectedValues: []string{"foovalue1"}},
   100  			},
   101  		},
   102  		{
   103  			desc: "{foo=foovalue2} 1 and {foo=foovalue2} 1",
   104  			appendFn: func(app storage.Appender) {
   105  				_, err := app.Append(0, labels.FromStrings("foo", "foovalue1"), timestamp.FromTime(now), 1)
   106  				testutil.Ok(t, err)
   107  				_, err = app.Append(0, labels.FromStrings("foo", "foovalue2"), timestamp.FromTime(now), 1)
   108  				testutil.Ok(t, err)
   109  				testutil.Ok(t, app.Commit())
   110  			},
   111  			labelNameCalls: []labelNameCallCase{
   112  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), expectedNames: []string{"foo", "region"}},
   113  			},
   114  			labelValuesCalls: []labelValuesCallCase{
   115  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "foo", expectedValues: []string{"foovalue1", "foovalue2"}},
   116  			},
   117  		},
   118  		{
   119  			desc: "{foo=foovalue1, bar=barvalue1} 1 and {foo=foovalue2} 1 and {foo=foovalue2} 1",
   120  			appendFn: func(app storage.Appender) {
   121  				_, err := app.Append(0, labels.FromStrings("foo", "foovalue1"), timestamp.FromTime(now), 1)
   122  				testutil.Ok(t, err)
   123  				_, err = app.Append(0, labels.FromStrings("foo", "foovalue2"), timestamp.FromTime(now), 1)
   124  				testutil.Ok(t, err)
   125  				_, err = app.Append(0, labels.FromStrings("foo", "foovalue1", "bar", "barvalue1"), timestamp.FromTime(now), 1)
   126  				testutil.Ok(t, err)
   127  				testutil.Ok(t, app.Commit())
   128  			},
   129  			labelNameCalls: []labelNameCallCase{
   130  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), expectedNames: []string{"bar", "foo", "region"}},
   131  				// Query range outside added samples timestamp.
   132  				// NOTE: Ideally we could do 'end: timestamp.FromTime(now.Add(-1 * time.Second))'. In practice however we index labels within block range, so we approximate label and label values to chunk of block time.
   133  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(now.Add(-4 * time.Hour))},
   134  				// Matchers on normal series.
   135  				{
   136  					start:         timestamp.FromTime(minTime),
   137  					end:           timestamp.FromTime(maxTime),
   138  					expectedNames: []string{"bar", "foo", "region"},
   139  					matchers:      []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "bar", Value: "barvalue1"}},
   140  				},
   141  				{
   142  					start:         timestamp.FromTime(minTime),
   143  					end:           timestamp.FromTime(maxTime),
   144  					expectedNames: []string{"foo", "region"},
   145  					matchers:      []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "foo", Value: "foovalue2"}},
   146  				},
   147  				{
   148  					start:    timestamp.FromTime(minTime),
   149  					end:      timestamp.FromTime(maxTime),
   150  					matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "bar", Value: "different"}},
   151  				},
   152  				// Matchers on external labels.
   153  				{
   154  					start:         timestamp.FromTime(minTime),
   155  					end:           timestamp.FromTime(maxTime),
   156  					expectedNames: []string{"bar", "foo", "region"},
   157  					matchers:      []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "eu-west"}},
   158  				},
   159  				{
   160  					start:    timestamp.FromTime(minTime),
   161  					end:      timestamp.FromTime(maxTime),
   162  					matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "different"}},
   163  				},
   164  			},
   165  			labelValuesCalls: []labelValuesCallCase{
   166  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "foo", expectedValues: []string{"foovalue1", "foovalue2"}},
   167  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(maxTime), label: "bar", expectedValues: []string{"barvalue1"}},
   168  				// Query range outside added samples timestamp.
   169  				// NOTE: Ideally we could do 'end: timestamp.FromTime(now.Add(-1 * time.Second))'. In practice however we index labels within block range, so we approximate label and label values to chunk of block time.
   170  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(now.Add(-4 * time.Hour)), label: "foo"},
   171  				{start: timestamp.FromTime(minTime), end: timestamp.FromTime(now.Add(-4 * time.Hour)), label: "bar"},
   172  				// Matchers on normal series.
   173  				{
   174  					start:          timestamp.FromTime(minTime),
   175  					end:            timestamp.FromTime(maxTime),
   176  					label:          "foo",
   177  					expectedValues: []string{"foovalue1"},
   178  					matchers:       []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "bar", Value: "barvalue1"}},
   179  				},
   180  				{
   181  					start:    timestamp.FromTime(minTime),
   182  					end:      timestamp.FromTime(maxTime),
   183  					label:    "foo",
   184  					matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "bar", Value: "different"}},
   185  				},
   186  				// Matchers on external labels.
   187  				{
   188  					start:          timestamp.FromTime(minTime),
   189  					end:            timestamp.FromTime(maxTime),
   190  					label:          "region",
   191  					expectedValues: []string(nil),
   192  					matchers:       []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "eu-east"}},
   193  				},
   194  				{
   195  					start:          timestamp.FromTime(minTime),
   196  					end:            timestamp.FromTime(maxTime),
   197  					label:          "foo",
   198  					expectedValues: []string{"foovalue1", "foovalue2"},
   199  					matchers:       []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "eu-west"}},
   200  				},
   201  				{
   202  					start:          timestamp.FromTime(minTime),
   203  					end:            timestamp.FromTime(maxTime),
   204  					label:          "bar",
   205  					expectedValues: []string{"barvalue1"},
   206  					matchers:       []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "eu-west"}},
   207  				},
   208  				{
   209  					start:    timestamp.FromTime(minTime),
   210  					end:      timestamp.FromTime(maxTime),
   211  					label:    "foo",
   212  					matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "different"}},
   213  				},
   214  				{
   215  					start:    timestamp.FromTime(minTime),
   216  					end:      timestamp.FromTime(maxTime),
   217  					label:    "bar",
   218  					matchers: []storepb.LabelMatcher{{Type: storepb.LabelMatcher_EQ, Name: "region", Value: "different"}},
   219  				},
   220  			},
   221  		},
   222  		{
   223  			// Testcases taken from https://github.com/prometheus/prometheus/blob/95e705612c1d557f1681bd081a841b78f93ee158/tsdb/querier_test.go#L1898
   224  			desc: "matching behavior",
   225  			appendFn: func(app storage.Appender) {
   226  				_, err := app.Append(0, labels.FromStrings("n", "1"), 0, 0)
   227  				testutil.Ok(t, err)
   228  				_, err = app.Append(0, labels.FromStrings("n", "1", "i", "a"), 0, 0)
   229  				testutil.Ok(t, err)
   230  				_, err = app.Append(0, labels.FromStrings("n", "1", "i", "b"), 0, 0)
   231  				testutil.Ok(t, err)
   232  				_, err = app.Append(0, labels.FromStrings("n", "2"), 0, 0)
   233  				testutil.Ok(t, err)
   234  				_, err = app.Append(0, labels.FromStrings("n", "2.5"), 0, 0)
   235  				testutil.Ok(t, err)
   236  
   237  				testutil.Ok(t, app.Commit())
   238  			},
   239  			seriesCalls: []seriesCallCase{
   240  				{
   241  					start: timestamp.FromTime(minTime),
   242  					end:   timestamp.FromTime(maxTime),
   243  					matchers: []storepb.LabelMatcher{
   244  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   245  					},
   246  					expectedLabels: []labels.Labels{
   247  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   248  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   249  						labels.FromStrings("n", "1", "region", "eu-west"),
   250  					},
   251  				},
   252  				{
   253  					start: timestamp.FromTime(minTime),
   254  					end:   timestamp.FromTime(maxTime),
   255  					matchers: []storepb.LabelMatcher{
   256  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   257  						{Type: storepb.LabelMatcher_EQ, Name: "i", Value: "a"},
   258  					},
   259  					expectedLabels: []labels.Labels{
   260  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   261  					},
   262  				},
   263  				{
   264  					start: timestamp.FromTime(minTime),
   265  					end:   timestamp.FromTime(maxTime),
   266  					matchers: []storepb.LabelMatcher{
   267  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   268  						{Type: storepb.LabelMatcher_EQ, Name: "i", Value: "missing"},
   269  					},
   270  					expectedLabels: []labels.Labels{},
   271  				},
   272  				{
   273  					start: timestamp.FromTime(minTime),
   274  					end:   timestamp.FromTime(maxTime),
   275  					matchers: []storepb.LabelMatcher{
   276  						{Type: storepb.LabelMatcher_EQ, Name: "missing", Value: ""},
   277  					},
   278  					expectedLabels: []labels.Labels{
   279  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   280  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   281  						labels.FromStrings("n", "1", "region", "eu-west"),
   282  						labels.FromStrings("n", "2", "region", "eu-west"),
   283  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   284  					},
   285  				},
   286  				{
   287  					start: timestamp.FromTime(minTime),
   288  					end:   timestamp.FromTime(maxTime),
   289  					matchers: []storepb.LabelMatcher{
   290  						{Type: storepb.LabelMatcher_NEQ, Name: "n", Value: "1"},
   291  					},
   292  					expectedLabels: []labels.Labels{
   293  						labels.FromStrings("n", "2", "region", "eu-west"),
   294  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   295  					},
   296  				},
   297  				{
   298  					start: timestamp.FromTime(minTime),
   299  					end:   timestamp.FromTime(maxTime),
   300  					matchers: []storepb.LabelMatcher{
   301  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: ".+"},
   302  					},
   303  					expectedLabels: []labels.Labels{
   304  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   305  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   306  					},
   307  				},
   308  				{
   309  					start: timestamp.FromTime(minTime),
   310  					end:   timestamp.FromTime(maxTime),
   311  					matchers: []storepb.LabelMatcher{
   312  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: ".*"},
   313  					},
   314  					expectedLabels: []labels.Labels{
   315  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   316  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   317  						labels.FromStrings("n", "1", "region", "eu-west"),
   318  						labels.FromStrings("n", "2", "region", "eu-west"),
   319  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   320  					},
   321  				},
   322  				{
   323  					start: timestamp.FromTime(minTime),
   324  					end:   timestamp.FromTime(maxTime),
   325  					matchers: []storepb.LabelMatcher{
   326  						{Type: storepb.LabelMatcher_EQ, Name: "i", Value: ""},
   327  					},
   328  					expectedLabels: []labels.Labels{
   329  						labels.FromStrings("n", "1", "region", "eu-west"),
   330  						labels.FromStrings("n", "2", "region", "eu-west"),
   331  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   332  					},
   333  				},
   334  				{
   335  					start: timestamp.FromTime(minTime),
   336  					end:   timestamp.FromTime(maxTime),
   337  					matchers: []storepb.LabelMatcher{
   338  						{Type: storepb.LabelMatcher_NEQ, Name: "i", Value: ""},
   339  					},
   340  					expectedLabels: []labels.Labels{
   341  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   342  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   343  					},
   344  				},
   345  				{
   346  					start: timestamp.FromTime(minTime),
   347  					end:   timestamp.FromTime(maxTime),
   348  					matchers: []storepb.LabelMatcher{
   349  						{Type: storepb.LabelMatcher_NEQ, Name: "missing", Value: ""},
   350  					},
   351  					expectedLabels: []labels.Labels{},
   352  				},
   353  				{
   354  					start: timestamp.FromTime(minTime),
   355  					end:   timestamp.FromTime(maxTime),
   356  					matchers: []storepb.LabelMatcher{
   357  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   358  						{Type: storepb.LabelMatcher_NEQ, Name: "i", Value: "a"},
   359  					},
   360  					expectedLabels: []labels.Labels{
   361  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   362  						labels.FromStrings("n", "1", "region", "eu-west"),
   363  					},
   364  				},
   365  				{
   366  					start: timestamp.FromTime(minTime),
   367  					end:   timestamp.FromTime(maxTime),
   368  					matchers: []storepb.LabelMatcher{
   369  						{Type: storepb.LabelMatcher_RE, Name: "n", Value: "^1$"},
   370  					},
   371  					expectedLabels: []labels.Labels{
   372  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   373  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   374  						labels.FromStrings("n", "1", "region", "eu-west"),
   375  					},
   376  				},
   377  				{
   378  					start: timestamp.FromTime(minTime),
   379  					end:   timestamp.FromTime(maxTime),
   380  					matchers: []storepb.LabelMatcher{
   381  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   382  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^a$"},
   383  					},
   384  					expectedLabels: []labels.Labels{
   385  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   386  					},
   387  				},
   388  				{
   389  					start: timestamp.FromTime(minTime),
   390  					end:   timestamp.FromTime(maxTime),
   391  					matchers: []storepb.LabelMatcher{
   392  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   393  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^a?$"},
   394  					},
   395  					expectedLabels: []labels.Labels{
   396  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   397  						labels.FromStrings("n", "1", "region", "eu-west"),
   398  					},
   399  				},
   400  				{
   401  					start: timestamp.FromTime(minTime),
   402  					end:   timestamp.FromTime(maxTime),
   403  					matchers: []storepb.LabelMatcher{
   404  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^$"},
   405  					},
   406  					expectedLabels: []labels.Labels{
   407  						labels.FromStrings("n", "1", "region", "eu-west"),
   408  						labels.FromStrings("n", "2", "region", "eu-west"),
   409  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   410  					},
   411  				},
   412  				{
   413  					start: timestamp.FromTime(minTime),
   414  					end:   timestamp.FromTime(maxTime),
   415  					matchers: []storepb.LabelMatcher{
   416  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   417  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^$"},
   418  					},
   419  					expectedLabels: []labels.Labels{
   420  						labels.FromStrings("n", "1", "region", "eu-west"),
   421  					},
   422  				},
   423  				{
   424  					start: timestamp.FromTime(minTime),
   425  					end:   timestamp.FromTime(maxTime),
   426  					matchers: []storepb.LabelMatcher{
   427  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   428  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^.*$"},
   429  					},
   430  					expectedLabels: []labels.Labels{
   431  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   432  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   433  						labels.FromStrings("n", "1", "region", "eu-west"),
   434  					},
   435  				},
   436  				{
   437  					start: timestamp.FromTime(minTime),
   438  					end:   timestamp.FromTime(maxTime),
   439  					matchers: []storepb.LabelMatcher{
   440  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   441  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^.+$"},
   442  					},
   443  					expectedLabels: []labels.Labels{
   444  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   445  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   446  					},
   447  				},
   448  				{
   449  					start: timestamp.FromTime(minTime),
   450  					end:   timestamp.FromTime(maxTime),
   451  					matchers: []storepb.LabelMatcher{
   452  						{Type: storepb.LabelMatcher_NRE, Name: "n", Value: "^1$"},
   453  					},
   454  					expectedLabels: []labels.Labels{
   455  						labels.FromStrings("n", "2", "region", "eu-west"),
   456  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   457  					},
   458  				},
   459  				{
   460  					start: timestamp.FromTime(minTime),
   461  					end:   timestamp.FromTime(maxTime),
   462  					matchers: []storepb.LabelMatcher{
   463  						{Type: storepb.LabelMatcher_NRE, Name: "n", Value: "1"},
   464  					},
   465  					expectedLabels: []labels.Labels{
   466  						labels.FromStrings("n", "2", "region", "eu-west"),
   467  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   468  					},
   469  				},
   470  				{
   471  					start: timestamp.FromTime(minTime),
   472  					end:   timestamp.FromTime(maxTime),
   473  					matchers: []storepb.LabelMatcher{
   474  						{Type: storepb.LabelMatcher_NRE, Name: "n", Value: "1|2.5"},
   475  					},
   476  					expectedLabels: []labels.Labels{
   477  						labels.FromStrings("n", "2", "region", "eu-west"),
   478  					},
   479  				},
   480  				{
   481  					start: timestamp.FromTime(minTime),
   482  					end:   timestamp.FromTime(maxTime),
   483  					matchers: []storepb.LabelMatcher{
   484  						{Type: storepb.LabelMatcher_NRE, Name: "n", Value: "(1|2.5)"},
   485  					},
   486  					expectedLabels: []labels.Labels{
   487  						labels.FromStrings("n", "2", "region", "eu-west"),
   488  					},
   489  				},
   490  				{
   491  					start: timestamp.FromTime(minTime),
   492  					end:   timestamp.FromTime(maxTime),
   493  					matchers: []storepb.LabelMatcher{
   494  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   495  						{Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^a$"},
   496  					},
   497  					expectedLabels: []labels.Labels{
   498  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   499  						labels.FromStrings("n", "1", "region", "eu-west"),
   500  					},
   501  				},
   502  				{
   503  					start: timestamp.FromTime(minTime),
   504  					end:   timestamp.FromTime(maxTime),
   505  					matchers: []storepb.LabelMatcher{
   506  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   507  						{Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^a?$"},
   508  					},
   509  					expectedLabels: []labels.Labels{
   510  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   511  					},
   512  				},
   513  				{
   514  					start: timestamp.FromTime(minTime),
   515  					end:   timestamp.FromTime(maxTime),
   516  					matchers: []storepb.LabelMatcher{
   517  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   518  						{Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^$"},
   519  					},
   520  					expectedLabels: []labels.Labels{
   521  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   522  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   523  					},
   524  				},
   525  				{
   526  					start: timestamp.FromTime(minTime),
   527  					end:   timestamp.FromTime(maxTime),
   528  					matchers: []storepb.LabelMatcher{
   529  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   530  						{Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^.*$"},
   531  					},
   532  					expectedLabels: []labels.Labels{},
   533  				},
   534  				{
   535  					start: timestamp.FromTime(minTime),
   536  					end:   timestamp.FromTime(maxTime),
   537  					matchers: []storepb.LabelMatcher{
   538  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   539  						{Type: storepb.LabelMatcher_NRE, Name: "i", Value: "^.+$"},
   540  					},
   541  					expectedLabels: []labels.Labels{
   542  						labels.FromStrings("n", "1", "region", "eu-west"),
   543  					},
   544  				},
   545  				{
   546  					start: timestamp.FromTime(minTime),
   547  					end:   timestamp.FromTime(maxTime),
   548  					matchers: []storepb.LabelMatcher{
   549  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   550  						{Type: storepb.LabelMatcher_NEQ, Name: "i", Value: ""},
   551  						{Type: storepb.LabelMatcher_EQ, Name: "i", Value: "a"},
   552  					},
   553  					expectedLabels: []labels.Labels{
   554  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   555  					},
   556  				},
   557  				{
   558  					start: timestamp.FromTime(minTime),
   559  					end:   timestamp.FromTime(maxTime),
   560  					matchers: []storepb.LabelMatcher{
   561  						{Type: storepb.LabelMatcher_EQ, Name: "n", Value: "1"},
   562  						{Type: storepb.LabelMatcher_NEQ, Name: "i", Value: "b"},
   563  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "^(b|a).*$"},
   564  					},
   565  					expectedLabels: []labels.Labels{
   566  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   567  					},
   568  				},
   569  				{
   570  					start: timestamp.FromTime(minTime),
   571  					end:   timestamp.FromTime(maxTime),
   572  					matchers: []storepb.LabelMatcher{
   573  						{Type: storepb.LabelMatcher_RE, Name: "n", Value: "(1|2)"},
   574  					},
   575  					expectedLabels: []labels.Labels{
   576  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   577  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   578  						labels.FromStrings("n", "1", "region", "eu-west"),
   579  						labels.FromStrings("n", "2", "region", "eu-west"),
   580  					},
   581  				},
   582  				{
   583  					start: timestamp.FromTime(minTime),
   584  					end:   timestamp.FromTime(maxTime),
   585  					matchers: []storepb.LabelMatcher{
   586  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "a|b"},
   587  					},
   588  					expectedLabels: []labels.Labels{
   589  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   590  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   591  					},
   592  				},
   593  				{
   594  					start: timestamp.FromTime(minTime),
   595  					end:   timestamp.FromTime(maxTime),
   596  					matchers: []storepb.LabelMatcher{
   597  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "(a|b)"},
   598  					},
   599  					expectedLabels: []labels.Labels{
   600  						labels.FromStrings("i", "a", "n", "1", "region", "eu-west"),
   601  						labels.FromStrings("i", "b", "n", "1", "region", "eu-west"),
   602  					},
   603  				},
   604  				{
   605  					start: timestamp.FromTime(minTime),
   606  					end:   timestamp.FromTime(maxTime),
   607  					matchers: []storepb.LabelMatcher{
   608  						{Type: storepb.LabelMatcher_RE, Name: "n", Value: "x1|2"},
   609  					},
   610  					expectedLabels: []labels.Labels{
   611  						labels.FromStrings("n", "2", "region", "eu-west"),
   612  					},
   613  				},
   614  				{
   615  					start: timestamp.FromTime(minTime),
   616  					end:   timestamp.FromTime(maxTime),
   617  					matchers: []storepb.LabelMatcher{
   618  						{Type: storepb.LabelMatcher_RE, Name: "n", Value: "2|2\\.5"},
   619  					},
   620  					expectedLabels: []labels.Labels{
   621  						labels.FromStrings("n", "2", "region", "eu-west"),
   622  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   623  					},
   624  				},
   625  				{
   626  					start: timestamp.FromTime(minTime),
   627  					end:   timestamp.FromTime(maxTime),
   628  					matchers: []storepb.LabelMatcher{
   629  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "c||d"},
   630  					},
   631  					expectedLabels: []labels.Labels{
   632  						labels.FromStrings("n", "1", "region", "eu-west"),
   633  						labels.FromStrings("n", "2", "region", "eu-west"),
   634  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   635  					},
   636  				},
   637  				{
   638  					start: timestamp.FromTime(minTime),
   639  					end:   timestamp.FromTime(maxTime),
   640  					matchers: []storepb.LabelMatcher{
   641  						{Type: storepb.LabelMatcher_RE, Name: "i", Value: "(c||d)"},
   642  					},
   643  					expectedLabels: []labels.Labels{
   644  						labels.FromStrings("n", "1", "region", "eu-west"),
   645  						labels.FromStrings("n", "2", "region", "eu-west"),
   646  						labels.FromStrings("n", "2.5", "region", "eu-west"),
   647  					},
   648  				},
   649  			},
   650  		},
   651  	} {
   652  		t.Run(tc.desc, func(t *testing.T) {
   653  			appendFn := tc.appendFn
   654  			if appendFn == nil {
   655  				appendFn = func(storage.Appender) {}
   656  			}
   657  			store := startStore(t, extLset, appendFn)
   658  
   659  			for _, c := range tc.labelNameCalls {
   660  				t.Run("label_names", func(t *testing.T) {
   661  					resp, err := store.LabelNames(context.Background(), &storepb.LabelNamesRequest{
   662  						Start:    c.start,
   663  						End:      c.end,
   664  						Matchers: c.matchers,
   665  					})
   666  					if c.expectErr != nil {
   667  						testutil.NotOk(t, err)
   668  						testutil.Equals(t, c.expectErr.Error(), err.Error())
   669  						return
   670  					}
   671  					testutil.Ok(t, err)
   672  					testutil.Equals(t, 0, len(resp.Warnings))
   673  					if len(resp.Names) == 0 {
   674  						resp.Names = nil
   675  					}
   676  					testutil.Equals(t, c.expectedNames, resp.Names)
   677  				})
   678  			}
   679  			for _, c := range tc.labelValuesCalls {
   680  				t.Run("label_name_values", func(t *testing.T) {
   681  					resp, err := store.LabelValues(context.Background(), &storepb.LabelValuesRequest{
   682  						Start:    c.start,
   683  						End:      c.end,
   684  						Label:    c.label,
   685  						Matchers: c.matchers,
   686  					})
   687  					if c.expectErr != nil {
   688  						testutil.NotOk(t, err)
   689  						testutil.Equals(t, c.expectErr.Error(), err.Error())
   690  						return
   691  					}
   692  					testutil.Ok(t, err)
   693  					testutil.Equals(t, 0, len(resp.Warnings))
   694  					if len(resp.Values) == 0 {
   695  						resp.Values = nil
   696  					}
   697  					testutil.Equals(t, c.expectedValues, resp.Values)
   698  				})
   699  			}
   700  			for _, c := range tc.seriesCalls {
   701  				t.Run("series", func(t *testing.T) {
   702  					srv := newStoreSeriesServer(context.Background())
   703  					err := store.Series(&storepb.SeriesRequest{
   704  						MinTime:  c.start,
   705  						MaxTime:  c.end,
   706  						Matchers: c.matchers,
   707  					}, srv)
   708  					if c.expectErr != nil {
   709  						testutil.NotOk(t, err)
   710  						testutil.Equals(t, c.expectErr.Error(), err.Error())
   711  						return
   712  					}
   713  					testutil.Ok(t, err)
   714  
   715  					testutil.Equals(t, true, slices.IsSortedFunc(srv.SeriesSet, func(x, y storepb.Series) bool {
   716  						return labels.Compare(x.PromLabels(), y.PromLabels()) < 0
   717  					}))
   718  
   719  					receivedLabels := make([]labels.Labels, 0)
   720  					for _, s := range srv.SeriesSet {
   721  						receivedLabels = append(receivedLabels, s.PromLabels())
   722  					}
   723  
   724  					testutil.Equals(t, c.expectedLabels, receivedLabels)
   725  				})
   726  			}
   727  		})
   728  	}
   729  }
   730  
   731  func TestBucketStore_Acceptance(t *testing.T) {
   732  	t.Cleanup(func() { custom.TolerantVerifyLeak(t) })
   733  
   734  	testStoreAPIsAcceptance(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer {
   735  		tmpDir := tt.TempDir()
   736  		bktDir := filepath.Join(tmpDir, "bkt")
   737  		auxDir := filepath.Join(tmpDir, "aux")
   738  		metaDir := filepath.Join(tmpDir, "meta")
   739  
   740  		testutil.Ok(tt, os.MkdirAll(metaDir, os.ModePerm))
   741  		testutil.Ok(tt, os.MkdirAll(auxDir, os.ModePerm))
   742  
   743  		bkt, err := filesystem.NewBucket(bktDir)
   744  		testutil.Ok(tt, err)
   745  		tt.Cleanup(func() { testutil.Ok(tt, bkt.Close()) })
   746  
   747  		headOpts := tsdb.DefaultHeadOptions()
   748  		headOpts.ChunkDirRoot = tmpDir
   749  		headOpts.ChunkRange = 1000
   750  		h, err := tsdb.NewHead(nil, nil, nil, nil, headOpts, nil)
   751  		testutil.Ok(tt, err)
   752  		tt.Cleanup(func() { testutil.Ok(tt, h.Close()) })
   753  		logger := log.NewNopLogger()
   754  
   755  		appendFn(h.Appender(context.Background()))
   756  
   757  		if h.NumSeries() == 0 {
   758  			tt.Skip("Bucket Store cannot handle empty HEAD")
   759  		}
   760  
   761  		id := createBlockFromHead(tt, auxDir, h)
   762  
   763  		auxBlockDir := filepath.Join(auxDir, id.String())
   764  		_, err = metadata.InjectThanos(log.NewNopLogger(), auxBlockDir, metadata.Thanos{
   765  			Labels:     extLset.Map(),
   766  			Downsample: metadata.ThanosDownsample{Resolution: 0},
   767  			Source:     metadata.TestSource,
   768  		}, nil)
   769  		testutil.Ok(tt, err)
   770  
   771  		testutil.Ok(tt, block.Upload(context.Background(), logger, bkt, auxBlockDir, metadata.NoneFunc))
   772  		testutil.Ok(tt, block.Upload(context.Background(), logger, bkt, auxBlockDir, metadata.NoneFunc))
   773  
   774  		chunkPool, err := NewDefaultChunkBytesPool(2e5)
   775  		testutil.Ok(tt, err)
   776  
   777  		metaFetcher, err := block.NewMetaFetcher(logger, 20, objstore.WithNoopInstr(bkt), metaDir, nil, []block.MetadataFilter{
   778  			block.NewTimePartitionMetaFilter(allowAllFilterConf.MinTime, allowAllFilterConf.MaxTime),
   779  		})
   780  		testutil.Ok(tt, err)
   781  
   782  		bucketStore, err := NewBucketStore(
   783  			objstore.WithNoopInstr(bkt),
   784  			metaFetcher,
   785  			"",
   786  			NewChunksLimiterFactory(10e6),
   787  			NewSeriesLimiterFactory(10e6),
   788  			NewBytesLimiterFactory(10e6),
   789  			NewGapBasedPartitioner(PartitionerMaxGapSize),
   790  			20,
   791  			true,
   792  			DefaultPostingOffsetInMemorySampling,
   793  			false,
   794  			false,
   795  			1*time.Minute,
   796  			WithChunkPool(chunkPool),
   797  			WithFilterConfig(allowAllFilterConf),
   798  		)
   799  		testutil.Ok(tt, err)
   800  		tt.Cleanup(func() { testutil.Ok(tt, bucketStore.Close()) })
   801  
   802  		testutil.Ok(tt, bucketStore.SyncBlocks(context.Background()))
   803  
   804  		return bucketStore
   805  	})
   806  }
   807  
   808  func TestPrometheusStore_Acceptance(t *testing.T) {
   809  	t.Cleanup(func() { custom.TolerantVerifyLeak(t) })
   810  
   811  	testStoreAPIsAcceptance(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer {
   812  		p, err := e2eutil.NewPrometheus()
   813  		testutil.Ok(tt, err)
   814  		tt.Cleanup(func() { testutil.Ok(tt, p.Stop()) })
   815  
   816  		appendFn(p.Appender())
   817  
   818  		testutil.Ok(tt, p.Start())
   819  		u, err := url.Parse(fmt.Sprintf("http://%s", p.Addr()))
   820  		testutil.Ok(tt, err)
   821  
   822  		version, err := promclient.NewDefaultClient().BuildVersion(context.Background(), u)
   823  		testutil.Ok(tt, err)
   824  
   825  		promStore, err := NewPrometheusStore(nil, nil, promclient.NewDefaultClient(), u, component.Sidecar,
   826  			func() labels.Labels { return extLset },
   827  			func() (int64, int64) { return timestamp.FromTime(minTime), timestamp.FromTime(maxTime) },
   828  			func() string { return version })
   829  		testutil.Ok(tt, err)
   830  
   831  		return promStore
   832  	})
   833  }
   834  
   835  func TestTSDBStore_Acceptance(t *testing.T) {
   836  	t.Cleanup(func() { custom.TolerantVerifyLeak(t) })
   837  
   838  	testStoreAPIsAcceptance(t, func(tt *testing.T, extLset labels.Labels, appendFn func(app storage.Appender)) storepb.StoreServer {
   839  		db, err := e2eutil.NewTSDB()
   840  		testutil.Ok(tt, err)
   841  		tt.Cleanup(func() { testutil.Ok(tt, db.Close()) })
   842  
   843  		tsdbStore := NewTSDBStore(nil, db, component.Rule, extLset)
   844  
   845  		appendFn(db.Appender(context.Background()))
   846  		return tsdbStore
   847  	})
   848  }