github.com/m3db/m3@v1.5.0/src/query/storage/prometheus/prometheus_storage_test.go (about)

     1  // Copyright (c) 2020 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package prometheus
    22  
    23  import (
    24  	"context"
    25  	"sync"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/golang/mock/gomock"
    30  	"github.com/m3db/m3/src/query/block"
    31  	"github.com/m3db/m3/src/query/generated/proto/prompb"
    32  	"github.com/m3db/m3/src/query/models"
    33  	"github.com/m3db/m3/src/query/storage"
    34  	"github.com/m3db/m3/src/x/instrument"
    35  	xtest "github.com/m3db/m3/src/x/test"
    36  
    37  	"github.com/prometheus/prometheus/pkg/labels"
    38  	promstorage "github.com/prometheus/prometheus/storage"
    39  	"github.com/stretchr/testify/assert"
    40  	"github.com/stretchr/testify/require"
    41  )
    42  
    43  func TestSelectWithMetaInContext(t *testing.T) {
    44  	ctrl := xtest.NewController(t)
    45  	defer ctrl.Finish()
    46  
    47  	var resMutex sync.Mutex
    48  	res := block.NewResultMetadata()
    49  	resultMetadataReceiveFn := func(m block.ResultMetadata) {
    50  		resMutex.Lock()
    51  		defer resMutex.Unlock()
    52  		res = res.CombineMetadata(m)
    53  	}
    54  	ctx := context.Background()
    55  	ctx = context.WithValue(ctx, FetchOptionsContextKey, storage.NewFetchOptions())
    56  	ctx = context.WithValue(ctx, BlockResultMetadataFnKey, resultMetadataReceiveFn)
    57  
    58  	store := storage.NewMockStorage(ctrl)
    59  	opts := PrometheusOptions{
    60  		Storage:           store,
    61  		InstrumentOptions: instrument.NewOptions(),
    62  	}
    63  
    64  	queryable := NewPrometheusQueryable(opts)
    65  	q, err := queryable.Querier(ctx, 0, 0)
    66  	require.NoError(t, err)
    67  
    68  	start := time.Now().Truncate(time.Hour)
    69  	end := start.Add(time.Hour)
    70  	step := int64(time.Second)
    71  
    72  	hints := &promstorage.SelectHints{
    73  		Start: start.Unix() * 1000,
    74  		End:   end.Unix() * 1000,
    75  
    76  		Step: step / int64(time.Millisecond),
    77  	}
    78  
    79  	matchers := []*labels.Matcher{
    80  		labels.MustNewMatcher(labels.MatchEqual, "foo", "bar"),
    81  		labels.MustNewMatcher(labels.MatchRegexp, "qux", "q.z"),
    82  	}
    83  
    84  	m, err := models.NewMatcher(models.MatchEqual, []byte("foo"), []byte("bar"))
    85  	require.NoError(t, err)
    86  	m2, err := models.NewMatcher(models.MatchRegexp, []byte("qux"), []byte("q.z"))
    87  	require.NoError(t, err)
    88  
    89  	exQuery := &storage.FetchQuery{
    90  		TagMatchers: models.Matchers{m, m2},
    91  		Start:       start,
    92  		End:         end,
    93  		Interval:    time.Duration(step),
    94  	}
    95  
    96  	meta := block.NewResultMetadata()
    97  	meta.AddWarning("warn", "warning")
    98  	store.EXPECT().FetchProm(ctx, exQuery, gomock.Any()).DoAndReturn(
    99  		func(_ context.Context, arg1 *storage.FetchQuery, _ *storage.FetchOptions) (storage.PromResult, error) {
   100  			return storage.PromResult{
   101  				Metadata: meta,
   102  				PromResult: &prompb.QueryResult{
   103  					Timeseries: []*prompb.TimeSeries{
   104  						{
   105  							Labels: []prompb.Label{
   106  								{Name: []byte("foo"), Value: []byte("bar")},
   107  								{Name: []byte("qux"), Value: []byte("qzz")},
   108  							},
   109  							Samples: []prompb.Sample{
   110  								prompb.Sample{Value: 1, Timestamp: 100},
   111  							},
   112  						},
   113  						{
   114  							Labels: []prompb.Label{
   115  								{Name: []byte("foo"), Value: []byte("bar")},
   116  								{Name: []byte("qux"), Value: []byte("qaz")},
   117  							},
   118  							Samples: []prompb.Sample{
   119  								prompb.Sample{Value: 100, Timestamp: 200},
   120  							},
   121  						},
   122  					},
   123  				},
   124  			}, nil
   125  		})
   126  
   127  	series := q.Select(true, hints, matchers...)
   128  	warnings := series.Warnings()
   129  	assert.NoError(t, series.Err())
   130  
   131  	type dp struct {
   132  		v float64
   133  		t int64
   134  	}
   135  
   136  	acDp := make([][]dp, 0, 2)
   137  	acTags := make([]string, 0, 2)
   138  	for series.Next() {
   139  		curr := series.At()
   140  		acTags = append(acTags, curr.Labels().String())
   141  		it := curr.Iterator()
   142  		ac := make([]dp, 0, 1)
   143  		for it.Next() {
   144  			t, v := it.At()
   145  			ac = append(ac, dp{t: t, v: v})
   146  		}
   147  
   148  		assert.NoError(t, it.Err())
   149  		acDp = append(acDp, ac)
   150  	}
   151  
   152  	assert.NoError(t, series.Err())
   153  
   154  	exDp := [][]dp{{{v: 100, t: 200}}, {{v: 1, t: 100}}}
   155  	exTags := []string{`{foo="bar", qux="qaz"}`, `{foo="bar", qux="qzz"}`}
   156  	assert.Equal(t, exTags, acTags)
   157  	assert.Equal(t, exDp, acDp)
   158  	require.Equal(t, 1, len(warnings))
   159  	require.EqualError(t, warnings[0], "warn_warning")
   160  	require.NoError(t, q.Close())
   161  
   162  	// NB: assert warnings on context were propagated.
   163  	assert.Equal(t, []string{"warn_warning"}, res.WarningStrings())
   164  }