github.com/thanos-io/thanos@v0.32.5/pkg/query/internal/test-storeset-pre-v0.8.0/storeset_test.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package testoldstoreset
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"math"
    10  	"net"
    11  	"os"
    12  	"sort"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/go-kit/log"
    17  	"github.com/go-kit/log/level"
    18  	"github.com/prometheus/prometheus/model/labels"
    19  	"google.golang.org/grpc"
    20  	"google.golang.org/grpc/codes"
    21  	"google.golang.org/grpc/credentials/insecure"
    22  	"google.golang.org/grpc/status"
    23  
    24  	"github.com/efficientgo/core/testutil"
    25  	"github.com/thanos-io/thanos/pkg/component"
    26  	"github.com/thanos-io/thanos/pkg/store"
    27  	"github.com/thanos-io/thanos/pkg/store/labelpb"
    28  	"github.com/thanos-io/thanos/pkg/store/storepb"
    29  	"github.com/thanos-io/thanos/pkg/testutil/custom"
    30  )
    31  
    32  var testGRPCOpts = []grpc.DialOption{
    33  	grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32)),
    34  	grpc.WithTransportCredentials(insecure.NewCredentials()),
    35  }
    36  
    37  type testStore struct {
    38  	info storepb.InfoResponse
    39  }
    40  
    41  func (s *testStore) Info(ctx context.Context, r *storepb.InfoRequest) (*storepb.InfoResponse, error) {
    42  	return &s.info, nil
    43  }
    44  
    45  func (s *testStore) Series(r *storepb.SeriesRequest, srv storepb.Store_SeriesServer) error {
    46  	return status.Error(codes.Unimplemented, "not implemented")
    47  }
    48  
    49  func (s *testStore) LabelNames(ctx context.Context, r *storepb.LabelNamesRequest) (
    50  	*storepb.LabelNamesResponse, error,
    51  ) {
    52  	return nil, status.Error(codes.Unimplemented, "not implemented")
    53  }
    54  
    55  func (s *testStore) LabelValues(ctx context.Context, r *storepb.LabelValuesRequest) (
    56  	*storepb.LabelValuesResponse, error,
    57  ) {
    58  	return nil, status.Error(codes.Unimplemented, "not implemented")
    59  }
    60  
    61  type testStoreMeta struct {
    62  	extlsetFn func(addr string) []labelpb.ZLabelSet
    63  	storeType component.StoreAPI
    64  }
    65  
    66  type testStores struct {
    67  	srvs map[string]*grpc.Server
    68  }
    69  
    70  func startTestStores(stores []testStoreMeta) (*testStores, error) {
    71  	st := &testStores{
    72  		srvs: map[string]*grpc.Server{},
    73  	}
    74  
    75  	for _, store := range stores {
    76  		listener, err := net.Listen("tcp", "127.0.0.1:0")
    77  		if err != nil {
    78  			// Close so far started servers.
    79  			st.Close()
    80  			return nil, err
    81  		}
    82  
    83  		srv := grpc.NewServer()
    84  		storepb.RegisterStoreServer(srv, &testStore{info: storepb.InfoResponse{LabelSets: store.extlsetFn(listener.Addr().String()), StoreType: store.storeType.ToProto()}})
    85  		go func() {
    86  			_ = srv.Serve(listener)
    87  		}()
    88  
    89  		st.srvs[listener.Addr().String()] = srv
    90  	}
    91  
    92  	return st, nil
    93  }
    94  
    95  func (s *testStores) StoreAddresses() []string {
    96  	var stores []string
    97  	for addr := range s.srvs {
    98  		stores = append(stores, addr)
    99  	}
   100  	return stores
   101  }
   102  
   103  func (s *testStores) Close() {
   104  	for _, srv := range s.srvs {
   105  		srv.Stop()
   106  	}
   107  	s.srvs = nil
   108  }
   109  
   110  func (s *testStores) CloseOne(addr string) {
   111  	srv, ok := s.srvs[addr]
   112  	if !ok {
   113  		return
   114  	}
   115  
   116  	srv.Stop()
   117  	delete(s.srvs, addr)
   118  }
   119  
   120  func specsFromAddrFunc(addrs []string) func() []StoreSpec {
   121  	return func() (specs []StoreSpec) {
   122  		for _, addr := range addrs {
   123  			specs = append(specs, NewGRPCStoreSpec(addr))
   124  		}
   125  		return specs
   126  	}
   127  }
   128  
   129  func TestMain(m *testing.M) {
   130  	custom.TolerantVerifyLeakMain(m)
   131  }
   132  
   133  func TestPre0_8_0_StoreSet_AgainstNewStoreGW(t *testing.T) {
   134  	st, err := startTestStores([]testStoreMeta{
   135  		{
   136  			storeType: component.Sidecar,
   137  			extlsetFn: func(addr string) []labelpb.ZLabelSet {
   138  				return []labelpb.ZLabelSet{
   139  					{
   140  						Labels: []labelpb.ZLabel{
   141  							{Name: "l1", Value: "v2"},
   142  							{Name: "l2", Value: "v3"},
   143  						},
   144  					},
   145  				}
   146  			},
   147  		},
   148  		{
   149  			storeType: component.Store,
   150  			extlsetFn: func(addr string) []labelpb.ZLabelSet {
   151  				return []labelpb.ZLabelSet{
   152  					{
   153  						Labels: []labelpb.ZLabel{
   154  							// This is the labelset exposed by store when having only one sidecar's data.
   155  							{Name: "l1", Value: "v2"},
   156  							{Name: "l2", Value: "v3"},
   157  						},
   158  					},
   159  					{
   160  						Labels: []labelpb.ZLabel{{Name: store.CompatibilityTypeLabelName, Value: "store"}},
   161  					},
   162  				}
   163  			},
   164  		},
   165  		// We expect this to be duplicated.
   166  		{
   167  			storeType: component.Store,
   168  			extlsetFn: func(addr string) []labelpb.ZLabelSet {
   169  				return []labelpb.ZLabelSet{
   170  					{
   171  						Labels: []labelpb.ZLabel{
   172  							{Name: "l1", Value: "v2"},
   173  							{Name: "l2", Value: "v3"},
   174  						},
   175  					},
   176  					{
   177  						Labels: []labelpb.ZLabel{{Name: store.CompatibilityTypeLabelName, Value: "store"}},
   178  					},
   179  				}
   180  			},
   181  		},
   182  	})
   183  	testutil.Ok(t, err)
   184  	defer st.Close()
   185  
   186  	logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
   187  	logger = level.NewFilter(logger, level.AllowDebug())
   188  	logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
   189  	storeSet := NewStoreSet(logger, nil, specsFromAddrFunc(st.StoreAddresses()), testGRPCOpts, time.Minute)
   190  	storeSet.gRPCInfoCallTimeout = 2 * time.Second
   191  	defer storeSet.Close()
   192  
   193  	// Should not matter how many of these we run.
   194  	storeSet.Update(context.Background())
   195  	storeSet.Update(context.Background())
   196  	storeSet.Update(context.Background())
   197  	storeSet.Update(context.Background())
   198  
   199  	testutil.Assert(t, len(storeSet.stores) == 2, fmt.Sprintf("all services should respond just fine, but we expect duplicates being blocked. Expected %d stores, got %d", 5, len(storeSet.stores)))
   200  
   201  	// Sort result to be able to compare.
   202  	var existingStoreLabels [][]labels.Labels
   203  	for _, store := range storeSet.stores {
   204  		lset := append([]labels.Labels{}, store.LabelSets()...)
   205  		existingStoreLabels = append(existingStoreLabels, lset)
   206  	}
   207  	sort.Slice(existingStoreLabels, func(i, j int) bool {
   208  		return len(existingStoreLabels[i]) > len(existingStoreLabels[j])
   209  	})
   210  
   211  	testutil.Equals(t, [][]labels.Labels{
   212  		{
   213  			{
   214  				{Name: "l1", Value: "v2"},
   215  				{Name: "l2", Value: "v3"},
   216  			},
   217  			{
   218  				{Name: store.CompatibilityTypeLabelName, Value: "store"},
   219  			},
   220  		},
   221  		{
   222  			{
   223  				{Name: "l1", Value: "v2"},
   224  				{Name: "l2", Value: "v3"},
   225  			},
   226  		},
   227  	}, existingStoreLabels)
   228  }