github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/querier/querier_mock_test.go (about)

     1  package querier
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"time"
     8  
     9  	"github.com/grafana/dskit/grpcclient"
    10  	"github.com/grafana/dskit/ring"
    11  	ring_client "github.com/grafana/dskit/ring/client"
    12  	"github.com/prometheus/client_golang/prometheus"
    13  	"github.com/prometheus/common/model"
    14  	"github.com/prometheus/prometheus/model/labels"
    15  	"google.golang.org/grpc"
    16  	"google.golang.org/grpc/health/grpc_health_v1"
    17  	grpc_metadata "google.golang.org/grpc/metadata"
    18  
    19  	"github.com/grafana/loki/pkg/distributor/clientpool"
    20  	"github.com/grafana/loki/pkg/ingester/client"
    21  	"github.com/grafana/loki/pkg/iter"
    22  	"github.com/grafana/loki/pkg/loghttp"
    23  	"github.com/grafana/loki/pkg/logproto"
    24  	"github.com/grafana/loki/pkg/logql"
    25  	"github.com/grafana/loki/pkg/storage/chunk"
    26  	"github.com/grafana/loki/pkg/storage/chunk/fetcher"
    27  	"github.com/grafana/loki/pkg/storage/config"
    28  	"github.com/grafana/loki/pkg/storage/stores/index/stats"
    29  	"github.com/grafana/loki/pkg/util"
    30  )
    31  
    32  // querierClientMock is a mockable version of QuerierClient, used in querier
    33  // unit tests to control the behaviour of a remote ingester
    34  type querierClientMock struct {
    35  	util.ExtendedMock
    36  	grpc_health_v1.HealthClient
    37  	logproto.QuerierClient
    38  }
    39  
    40  func newQuerierClientMock() *querierClientMock {
    41  	return &querierClientMock{}
    42  }
    43  
    44  func (c *querierClientMock) Query(ctx context.Context, in *logproto.QueryRequest, opts ...grpc.CallOption) (logproto.Querier_QueryClient, error) {
    45  	args := c.Called(ctx, in, opts)
    46  	return args.Get(0).(logproto.Querier_QueryClient), args.Error(1)
    47  }
    48  
    49  func (c *querierClientMock) QuerySample(ctx context.Context, in *logproto.SampleQueryRequest, opts ...grpc.CallOption) (logproto.Querier_QuerySampleClient, error) {
    50  	args := c.Called(ctx, in, opts)
    51  	return args.Get(0).(logproto.Querier_QuerySampleClient), args.Error(1)
    52  }
    53  
    54  func (c *querierClientMock) Label(ctx context.Context, in *logproto.LabelRequest, opts ...grpc.CallOption) (*logproto.LabelResponse, error) {
    55  	args := c.Called(ctx, in, opts)
    56  	return args.Get(0).(*logproto.LabelResponse), args.Error(1)
    57  }
    58  
    59  func (c *querierClientMock) Tail(ctx context.Context, in *logproto.TailRequest, opts ...grpc.CallOption) (logproto.Querier_TailClient, error) {
    60  	args := c.Called(ctx, in, opts)
    61  	return args.Get(0).(logproto.Querier_TailClient), args.Error(1)
    62  }
    63  
    64  func (c *querierClientMock) Series(ctx context.Context, in *logproto.SeriesRequest, opts ...grpc.CallOption) (*logproto.SeriesResponse, error) {
    65  	args := c.Called(ctx, in)
    66  	res := args.Get(0)
    67  	if res == nil {
    68  		return (*logproto.SeriesResponse)(nil), args.Error(1)
    69  	}
    70  	return res.(*logproto.SeriesResponse), args.Error(1)
    71  }
    72  
    73  func (c *querierClientMock) TailersCount(ctx context.Context, in *logproto.TailersCountRequest, opts ...grpc.CallOption) (*logproto.TailersCountResponse, error) {
    74  	args := c.Called(ctx, in, opts)
    75  	return args.Get(0).(*logproto.TailersCountResponse), args.Error(1)
    76  }
    77  
    78  func (c *querierClientMock) Context() context.Context {
    79  	return context.Background()
    80  }
    81  
    82  func (c *querierClientMock) Close() error {
    83  	return nil
    84  }
    85  
    86  // newIngesterClientMockFactory creates a factory function always returning
    87  // the input querierClientMock
    88  func newIngesterClientMockFactory(c *querierClientMock) ring_client.PoolFactory {
    89  	return func(addr string) (ring_client.PoolClient, error) {
    90  		return c, nil
    91  	}
    92  }
    93  
    94  // mockIngesterClientConfig returns an ingester client config suitable for testing
    95  func mockIngesterClientConfig() client.Config {
    96  	return client.Config{
    97  		PoolConfig: clientpool.PoolConfig{
    98  			ClientCleanupPeriod:  1 * time.Minute,
    99  			HealthCheckIngesters: false,
   100  			RemoteTimeout:        1 * time.Second,
   101  		},
   102  		GRPCClientConfig: grpcclient.Config{
   103  			MaxRecvMsgSize: 1024,
   104  		},
   105  		RemoteTimeout: 1 * time.Second,
   106  	}
   107  }
   108  
   109  // queryClientMock is a mockable version of Querier_QueryClient
   110  type queryClientMock struct {
   111  	util.ExtendedMock
   112  	logproto.Querier_QueryClient
   113  }
   114  
   115  func newQueryClientMock() *queryClientMock {
   116  	return &queryClientMock{}
   117  }
   118  
   119  func (c *queryClientMock) Recv() (*logproto.QueryResponse, error) {
   120  	args := c.Called()
   121  	res := args.Get(0)
   122  	if res == nil {
   123  		return (*logproto.QueryResponse)(nil), args.Error(1)
   124  	}
   125  	return res.(*logproto.QueryResponse), args.Error(1)
   126  }
   127  
   128  func (c *queryClientMock) Header() (grpc_metadata.MD, error) {
   129  	return nil, nil
   130  }
   131  
   132  func (c *queryClientMock) Trailer() grpc_metadata.MD {
   133  	return nil
   134  }
   135  
   136  func (c *queryClientMock) CloseSend() error {
   137  	return nil
   138  }
   139  
   140  func (c *queryClientMock) SendMsg(m interface{}) error {
   141  	return nil
   142  }
   143  
   144  func (c *queryClientMock) RecvMsg(m interface{}) error {
   145  	return nil
   146  }
   147  
   148  func (c *queryClientMock) Context() context.Context {
   149  	return context.Background()
   150  }
   151  
   152  // queryClientMock is a mockable version of Querier_QueryClient
   153  type querySampleClientMock struct {
   154  	util.ExtendedMock
   155  	logproto.Querier_QueryClient
   156  }
   157  
   158  func newQuerySampleClientMock() *querySampleClientMock {
   159  	return &querySampleClientMock{}
   160  }
   161  
   162  func (c *querySampleClientMock) Recv() (*logproto.SampleQueryResponse, error) {
   163  	args := c.Called()
   164  	res := args.Get(0)
   165  	if res == nil {
   166  		return (*logproto.SampleQueryResponse)(nil), args.Error(1)
   167  	}
   168  	return res.(*logproto.SampleQueryResponse), args.Error(1)
   169  }
   170  
   171  func (c *querySampleClientMock) Header() (grpc_metadata.MD, error) {
   172  	return nil, nil
   173  }
   174  
   175  func (c *querySampleClientMock) Trailer() grpc_metadata.MD {
   176  	return nil
   177  }
   178  
   179  func (c *querySampleClientMock) CloseSend() error {
   180  	return nil
   181  }
   182  
   183  func (c *querySampleClientMock) SendMsg(m interface{}) error {
   184  	return nil
   185  }
   186  
   187  func (c *querySampleClientMock) RecvMsg(m interface{}) error {
   188  	return nil
   189  }
   190  
   191  func (c *querySampleClientMock) Context() context.Context {
   192  	return context.Background()
   193  }
   194  
   195  // tailClientMock is mockable version of Querier_TailClient
   196  type tailClientMock struct {
   197  	util.ExtendedMock
   198  	logproto.Querier_TailClient
   199  	recvTrigger chan time.Time
   200  }
   201  
   202  func newTailClientMock() *tailClientMock {
   203  	return &tailClientMock{
   204  		recvTrigger: make(chan time.Time, 10),
   205  	}
   206  }
   207  
   208  func (c *tailClientMock) Recv() (*logproto.TailResponse, error) {
   209  	args := c.Called()
   210  	return args.Get(0).(*logproto.TailResponse), args.Error(1)
   211  }
   212  
   213  func (c *tailClientMock) Header() (grpc_metadata.MD, error) {
   214  	return nil, nil
   215  }
   216  
   217  func (c *tailClientMock) Trailer() grpc_metadata.MD {
   218  	return nil
   219  }
   220  
   221  func (c *tailClientMock) CloseSend() error {
   222  	return nil
   223  }
   224  
   225  func (c *tailClientMock) Context() context.Context {
   226  	return context.Background()
   227  }
   228  
   229  func (c *tailClientMock) SendMsg(m interface{}) error {
   230  	return nil
   231  }
   232  
   233  func (c *tailClientMock) RecvMsg(m interface{}) error {
   234  	return nil
   235  }
   236  
   237  func (c *tailClientMock) mockRecvWithTrigger(response *logproto.TailResponse) *tailClientMock {
   238  	c.On("Recv").WaitUntil(c.recvTrigger).Return(response, nil)
   239  
   240  	return c
   241  }
   242  
   243  // triggerRecv triggers the Recv() mock to return from the next invocation
   244  // or from the current invocation if was already called and waiting for the
   245  // trigger. This method works if and only if the Recv() has been mocked with
   246  // mockRecvWithTrigger().
   247  func (c *tailClientMock) triggerRecv() {
   248  	c.recvTrigger <- time.Now()
   249  }
   250  
   251  // storeMock is a mockable version of Loki's storage, used in querier unit tests
   252  // to control the behaviour of the store without really hitting any storage backend
   253  type storeMock struct {
   254  	util.ExtendedMock
   255  }
   256  
   257  func newStoreMock() *storeMock {
   258  	return &storeMock{}
   259  }
   260  
   261  func (s *storeMock) SetChunkFilterer(chunk.RequestChunkFilterer) {}
   262  
   263  func (s *storeMock) SelectLogs(ctx context.Context, req logql.SelectLogParams) (iter.EntryIterator, error) {
   264  	args := s.Called(ctx, req)
   265  	res := args.Get(0)
   266  	if res == nil {
   267  		return iter.EntryIterator(nil), args.Error(1)
   268  	}
   269  	return res.(iter.EntryIterator), args.Error(1)
   270  }
   271  
   272  func (s *storeMock) SelectSamples(ctx context.Context, req logql.SelectSampleParams) (iter.SampleIterator, error) {
   273  	args := s.Called(ctx, req)
   274  	res := args.Get(0)
   275  	if res == nil {
   276  		return iter.SampleIterator(nil), args.Error(1)
   277  	}
   278  	return res.(iter.SampleIterator), args.Error(1)
   279  }
   280  
   281  func (s *storeMock) GetChunkRefs(ctx context.Context, userID string, from, through model.Time, matchers ...*labels.Matcher) ([][]chunk.Chunk, []*fetcher.Fetcher, error) {
   282  	args := s.Called(ctx, userID, from, through, matchers)
   283  	return args.Get(0).([][]chunk.Chunk), args.Get(0).([]*fetcher.Fetcher), args.Error(2)
   284  }
   285  
   286  func (s *storeMock) Put(ctx context.Context, chunks []chunk.Chunk) error {
   287  	return errors.New("storeMock.Put() has not been mocked")
   288  }
   289  
   290  func (s *storeMock) PutOne(ctx context.Context, from, through model.Time, chunk chunk.Chunk) error {
   291  	return errors.New("storeMock.PutOne() has not been mocked")
   292  }
   293  
   294  func (s *storeMock) LabelValuesForMetricName(ctx context.Context, userID string, from, through model.Time, metricName string, labelName string, matchers ...*labels.Matcher) ([]string, error) {
   295  	args := s.Called(ctx, userID, from, through, metricName, labelName)
   296  	return args.Get(0).([]string), args.Error(1)
   297  }
   298  
   299  func (s *storeMock) LabelNamesForMetricName(ctx context.Context, userID string, from, through model.Time, metricName string) ([]string, error) {
   300  	args := s.Called(ctx, userID, from, through, metricName)
   301  	return args.Get(0).([]string), args.Error(1)
   302  }
   303  
   304  func (s *storeMock) GetChunkFetcher(_ model.Time) *fetcher.Fetcher {
   305  	panic("don't call me please")
   306  }
   307  
   308  func (s *storeMock) GetSchemaConfigs() []config.PeriodConfig {
   309  	panic("don't call me please")
   310  }
   311  
   312  func (s *storeMock) Series(ctx context.Context, req logql.SelectLogParams) ([]logproto.SeriesIdentifier, error) {
   313  	args := s.Called(ctx, req)
   314  	res := args.Get(0)
   315  	if res == nil {
   316  		return []logproto.SeriesIdentifier(nil), args.Error(1)
   317  	}
   318  	return res.([]logproto.SeriesIdentifier), args.Error(1)
   319  }
   320  
   321  func (s *storeMock) GetSeries(ctx context.Context, userID string, from, through model.Time, matchers ...*labels.Matcher) ([]labels.Labels, error) {
   322  	panic("don't call me please")
   323  }
   324  
   325  func (s *storeMock) Stats(ctx context.Context, userID string, from, through model.Time, matchers ...*labels.Matcher) (*stats.Stats, error) {
   326  	return nil, nil
   327  }
   328  
   329  func (s *storeMock) Stop() {
   330  }
   331  
   332  // readRingMock is a mocked version of a ReadRing, used in querier unit tests
   333  // to control the pool of ingesters available
   334  type readRingMock struct {
   335  	replicationSet ring.ReplicationSet
   336  }
   337  
   338  func newReadRingMock(ingesters []ring.InstanceDesc) *readRingMock {
   339  	return &readRingMock{
   340  		replicationSet: ring.ReplicationSet{
   341  			Instances: ingesters,
   342  			MaxErrors: 0,
   343  		},
   344  	}
   345  }
   346  
   347  func (r *readRingMock) Describe(ch chan<- *prometheus.Desc) {
   348  }
   349  
   350  func (r *readRingMock) Collect(ch chan<- prometheus.Metric) {
   351  }
   352  
   353  func (r *readRingMock) Get(key uint32, op ring.Operation, buf []ring.InstanceDesc, _ []string, _ []string) (ring.ReplicationSet, error) {
   354  	return r.replicationSet, nil
   355  }
   356  
   357  func (r *readRingMock) ShuffleShard(identifier string, size int) ring.ReadRing {
   358  	// pass by value to copy
   359  	return func(r readRingMock) *readRingMock {
   360  		r.replicationSet.Instances = r.replicationSet.Instances[:size]
   361  		return &r
   362  	}(*r)
   363  }
   364  
   365  func (r *readRingMock) BatchGet(keys []uint32, op ring.Operation) ([]ring.ReplicationSet, error) {
   366  	return []ring.ReplicationSet{r.replicationSet}, nil
   367  }
   368  
   369  func (r *readRingMock) GetAllHealthy(op ring.Operation) (ring.ReplicationSet, error) {
   370  	return r.replicationSet, nil
   371  }
   372  
   373  func (r *readRingMock) GetReplicationSetForOperation(op ring.Operation) (ring.ReplicationSet, error) {
   374  	return r.replicationSet, nil
   375  }
   376  
   377  func (r *readRingMock) ReplicationFactor() int {
   378  	return 1
   379  }
   380  
   381  func (r *readRingMock) InstancesCount() int {
   382  	return len(r.replicationSet.Instances)
   383  }
   384  
   385  func (r *readRingMock) Subring(key uint32, n int) ring.ReadRing {
   386  	return r
   387  }
   388  
   389  func (r *readRingMock) HasInstance(instanceID string) bool {
   390  	for _, ing := range r.replicationSet.Instances {
   391  		if ing.Addr != instanceID {
   392  			return true
   393  		}
   394  	}
   395  	return false
   396  }
   397  
   398  func (r *readRingMock) ShuffleShardWithLookback(identifier string, size int, lookbackPeriod time.Duration, now time.Time) ring.ReadRing {
   399  	return r
   400  }
   401  
   402  func (r *readRingMock) CleanupShuffleShardCache(identifier string) {}
   403  
   404  func (r *readRingMock) GetInstanceState(instanceID string) (ring.InstanceState, error) {
   405  	return 0, nil
   406  }
   407  
   408  func mockReadRingWithOneActiveIngester() *readRingMock {
   409  	return newReadRingMock([]ring.InstanceDesc{
   410  		{Addr: "test", Timestamp: time.Now().UnixNano(), State: ring.ACTIVE, Tokens: []uint32{1, 2, 3}},
   411  	})
   412  }
   413  
   414  func mockInstanceDesc(addr string, state ring.InstanceState) ring.InstanceDesc {
   415  	return ring.InstanceDesc{
   416  		Addr:      addr,
   417  		Timestamp: time.Now().UnixNano(),
   418  		State:     state,
   419  		Tokens:    []uint32{1, 2, 3},
   420  	}
   421  }
   422  
   423  // mockStreamIterator returns an iterator with 1 stream and quantity entries,
   424  // where entries timestamp and line string are constructed as sequential numbers
   425  // starting at from
   426  func mockStreamIterator(from int, quantity int) iter.EntryIterator {
   427  	return iter.NewStreamIterator(mockStream(from, quantity))
   428  }
   429  
   430  // mockSampleIterator returns an iterator with 1 stream and quantity entries,
   431  // where entries timestamp and line string are constructed as sequential numbers
   432  // starting at from
   433  func mockSampleIterator(client iter.QuerySampleClient) iter.SampleIterator {
   434  	return iter.NewSampleQueryClientIterator(client)
   435  }
   436  
   437  // mockStream return a stream with quantity entries, where entries timestamp and
   438  // line string are constructed as sequential numbers starting at from
   439  func mockStream(from int, quantity int) logproto.Stream {
   440  	return mockStreamWithLabels(from, quantity, `{type="test"}`)
   441  }
   442  
   443  func mockStreamWithLabels(from int, quantity int, labels string) logproto.Stream {
   444  	entries := make([]logproto.Entry, 0, quantity)
   445  
   446  	for i := from; i < from+quantity; i++ {
   447  		entries = append(entries, logproto.Entry{
   448  			Timestamp: time.Unix(int64(i), 0),
   449  			Line:      fmt.Sprintf("line %d", i),
   450  		})
   451  	}
   452  
   453  	return logproto.Stream{
   454  		Entries: entries,
   455  		Labels:  labels,
   456  	}
   457  }
   458  
   459  type querierMock struct {
   460  	util.ExtendedMock
   461  }
   462  
   463  func newQuerierMock() *querierMock {
   464  	return &querierMock{}
   465  }
   466  
   467  func (q *querierMock) SelectLogs(ctx context.Context, params logql.SelectLogParams) (iter.EntryIterator, error) {
   468  	args := q.Called(ctx, params)
   469  	return args.Get(0).(func() iter.EntryIterator)(), args.Error(1)
   470  }
   471  
   472  func (q *querierMock) SelectSamples(ctx context.Context, params logql.SelectSampleParams) (iter.SampleIterator, error) {
   473  	args := q.Called(ctx, params)
   474  	return args.Get(0).(func() iter.SampleIterator)(), args.Error(1)
   475  }
   476  
   477  func (q *querierMock) Label(ctx context.Context, req *logproto.LabelRequest) (*logproto.LabelResponse, error) {
   478  	args := q.Called(ctx, req)
   479  	return args.Get(0).(*logproto.LabelResponse), args.Error(1)
   480  }
   481  
   482  func (q *querierMock) Series(ctx context.Context, req *logproto.SeriesRequest) (*logproto.SeriesResponse, error) {
   483  	args := q.Called(ctx, req)
   484  	return args.Get(0).(func() *logproto.SeriesResponse)(), args.Error(1)
   485  }
   486  
   487  func (q *querierMock) Tail(ctx context.Context, req *logproto.TailRequest) (*Tailer, error) {
   488  	return nil, errors.New("querierMock.Tail() has not been mocked")
   489  }
   490  
   491  func (q *querierMock) IndexStats(ctx context.Context, req *loghttp.RangeQuery) (*stats.Stats, error) {
   492  	return nil, nil
   493  }