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 }