diff --git a/scripts/comparator/run.sh b/scripts/comparator/run.sh index d1bb833188..ea5c05d781 100755 --- a/scripts/comparator/run.sh +++ b/scripts/comparator/run.sh @@ -75,4 +75,4 @@ $comparator -input=$QUERY_FILE \ -regressionDir=$REGRESSION_DIR # Run PromQL testdata tests -go test -v -timeout 300s -tags=compatibility -count=1 github.com/m3db/m3/src/query/test/ +go test -v -timeout 300s -tags=compatibility -count=1 github.com/m3db/m3/src/query/test/compatibility/ diff --git a/src/cmd/services/m3comparator/main/querier.go b/src/cmd/services/m3comparator/main/querier.go index 41229b983d..91cab6eb50 100644 --- a/src/cmd/services/m3comparator/main/querier.go +++ b/src/cmd/services/m3comparator/main/querier.go @@ -36,6 +36,7 @@ import ( "github.com/m3db/m3/src/dbnode/encoding" "github.com/m3db/m3/src/dbnode/ts" "github.com/m3db/m3/src/query/block" + "github.com/m3db/m3/src/query/models" "github.com/m3db/m3/src/query/storage" "github.com/m3db/m3/src/query/storage/m3" "github.com/m3db/m3/src/query/storage/m3/consolidators" @@ -149,27 +150,38 @@ func (q *querier) FetchCompressed( options *storage.FetchOptions, ) (consolidators.SeriesFetchResult, m3.Cleanup, error) { var ( - iters encoding.SeriesIterators - randomSeries []series - ignoreFilter bool - err error - nameTagFound bool + iters encoding.SeriesIterators + randomSeries []series + ignoreFilter bool + err error + strictMetricsFilter bool ) name := q.iteratorOpts.tagOptions.MetricName() for _, matcher := range query.TagMatchers { if bytes.Equal(name, matcher.Name) { - nameTagFound = true - iters, err = q.handler.getSeriesIterators(string(matcher.Value)) - if err != nil { - return consolidators.SeriesFetchResult{}, noop, err + + metricsName := string(matcher.Value) + + // NB: the default behaviour of this querier is to return predefined metrics with random data if no match by + // metrics name is found. To force it return an empty result, query the "nonexistent*" metrics. + if match, _ := regexp.MatchString("^nonexist[ae]nt", metricsName); match { + return consolidators.SeriesFetchResult{}, noop, nil } - break + if matcher.Type == models.MatchEqual { + strictMetricsFilter = true + iters, err = q.handler.getSeriesIterators(metricsName) + if err != nil { + return consolidators.SeriesFetchResult{}, noop, err + } + + break + } } } - if iters == nil && !nameTagFound && len(query.TagMatchers) > 0 { + if iters == nil && !strictMetricsFilter && len(query.TagMatchers) > 0 { iters, err = q.handler.getSeriesIterators("") if err != nil { return consolidators.SeriesFetchResult{}, noop, err diff --git a/src/cmd/services/m3comparator/main/querier_test.go b/src/cmd/services/m3comparator/main/querier_test.go index 574f9354e5..69d73e4438 100644 --- a/src/cmd/services/m3comparator/main/querier_test.go +++ b/src/cmd/services/m3comparator/main/querier_test.go @@ -111,6 +111,16 @@ func TestGenerateRandomSeries(t *testing.T) { givenQuery *storage.FetchQuery wantSeries []tagMap }{ + { + name: "querying nonexistent_metric returns empty", + givenQuery: matcherQuery(t, metricNameTag, "nonexistent_metric"), + wantSeries: []tagMap{}, + }, + { + name: "querying nonexistant returns empty", + givenQuery: matcherQuery(t, metricNameTag, "nonexistant"), + wantSeries: []tagMap{}, + }, { name: "random data for known metrics", givenQuery: matcherQuery(t, metricNameTag, "quail"), diff --git a/src/cmd/services/m3comparator/main/series_load_handler.go b/src/cmd/services/m3comparator/main/series_load_handler.go index 8c60f8c495..cdfdbe0e04 100644 --- a/src/cmd/services/m3comparator/main/series_load_handler.go +++ b/src/cmd/services/m3comparator/main/series_load_handler.go @@ -88,64 +88,75 @@ func (l *httpSeriesLoadHandler) getSeriesIterators( l.RLock() defer l.RUnlock() + var seriesMaps []idSeriesMap logger := l.iterOpts.iOpts.Logger() - seriesMap, found := l.nameIDSeriesMap[name] - if !found || len(seriesMap.series) == 0 { - return nil, nil + if name == "" { + // return all preloaded data + for _, series := range l.nameIDSeriesMap { + seriesMaps = append(seriesMaps, series) + } + } else { + seriesMap, found := l.nameIDSeriesMap[name] + if !found || len(seriesMap.series) == 0 { + return nil, nil + } + seriesMaps = append(seriesMaps, seriesMap) } - iters := make([]encoding.SeriesIterator, 0, len(seriesMap.series)) - for _, series := range seriesMap.series { - encoder := l.iterOpts.encoderPool.Get() - dps := series.Datapoints - startTime := time.Time{} - if len(dps) > 0 { - startTime = dps[0].Timestamp.Truncate(time.Hour) - } + iters := make([]encoding.SeriesIterator, 0, len(seriesMaps)) + for _, seriesMap := range seriesMaps { + for _, series := range seriesMap.series { + encoder := l.iterOpts.encoderPool.Get() + dps := series.Datapoints + startTime := time.Time{} + if len(dps) > 0 { + startTime = dps[0].Timestamp.Truncate(time.Hour) + } - encoder.Reset(startTime, len(dps), nil) - for _, dp := range dps { - err := encoder.Encode(ts.Datapoint{ - Timestamp: dp.Timestamp, - Value: float64(dp.Value), - TimestampNanos: xtime.ToUnixNano(dp.Timestamp), - }, xtime.Nanosecond, nil) - - if err != nil { - encoder.Close() - logger.Error("error encoding datapoints", zap.Error(err)) - return nil, err + encoder.Reset(startTime, len(dps), nil) + for _, dp := range dps { + err := encoder.Encode(ts.Datapoint{ + Timestamp: dp.Timestamp, + Value: float64(dp.Value), + TimestampNanos: xtime.ToUnixNano(dp.Timestamp), + }, xtime.Nanosecond, nil) + + if err != nil { + encoder.Close() + logger.Error("error encoding datapoints", zap.Error(err)) + return nil, err + } } - } - readers := [][]xio.BlockReader{{{ - SegmentReader: xio.NewSegmentReader(encoder.Discard()), - Start: series.Start, - BlockSize: series.End.Sub(series.Start), - }}} - - multiReader := encoding.NewMultiReaderIterator( - iterAlloc, - l.iterOpts.iteratorPools.MultiReaderIterator(), - ) - - sliceOfSlicesIter := xio.NewReaderSliceOfSlicesFromBlockReadersIterator(readers) - multiReader.ResetSliceOfSlices(sliceOfSlicesIter, nil) - - tagIter, id := buildTagIteratorAndID(series.Tags, l.iterOpts.tagOptions) - iter := encoding.NewSeriesIterator( - encoding.SeriesIteratorOptions{ - ID: id, - Namespace: ident.StringID("ns"), - Tags: tagIter, - StartInclusive: xtime.ToUnixNano(series.Start), - EndExclusive: xtime.ToUnixNano(series.End), - Replicas: []encoding.MultiReaderIterator{ - multiReader, - }, - }, nil) - - iters = append(iters, iter) + readers := [][]xio.BlockReader{{{ + SegmentReader: xio.NewSegmentReader(encoder.Discard()), + Start: series.Start, + BlockSize: series.End.Sub(series.Start), + }}} + + multiReader := encoding.NewMultiReaderIterator( + iterAlloc, + l.iterOpts.iteratorPools.MultiReaderIterator(), + ) + + sliceOfSlicesIter := xio.NewReaderSliceOfSlicesFromBlockReadersIterator(readers) + multiReader.ResetSliceOfSlices(sliceOfSlicesIter, nil) + + tagIter, id := buildTagIteratorAndID(series.Tags, l.iterOpts.tagOptions) + iter := encoding.NewSeriesIterator( + encoding.SeriesIteratorOptions{ + ID: id, + Namespace: ident.StringID("ns"), + Tags: tagIter, + StartInclusive: xtime.ToUnixNano(series.Start), + EndExclusive: xtime.ToUnixNano(series.End), + Replicas: []encoding.MultiReaderIterator{ + multiReader, + }, + }, nil) + + iters = append(iters, iter) + } } return encoding.NewSeriesIterators( diff --git a/src/cmd/services/m3comparator/main/series_load_handler_test.go b/src/cmd/services/m3comparator/main/series_load_handler_test.go index ec01a83bcd..87df74ec5c 100644 --- a/src/cmd/services/m3comparator/main/series_load_handler_test.go +++ b/src/cmd/services/m3comparator/main/series_load_handler_test.go @@ -146,23 +146,33 @@ const seriesStr = ` } ]` -func TestIngestSeries(t *testing.T) { - opts := iteratorOptions{ - encoderPool: encoderPool, - iteratorPools: iterPools, - tagOptions: tagOptions, - iOpts: iOpts, +const otherSeriesStr = ` +[ + { + "start": "2020-03-30T12:00:00Z", + "end": "2020-03-30T12:01:00Z", + "tags": [ + ["__name__", "foo"], + ["bar", "baz"] + ], + "datapoints": [ + { "val": "555", "ts": "2020-03-30T12:00:00Z" } + ] } +]` - req, err := http.NewRequest(http.MethodPost, "", strings.NewReader(seriesStr)) - require.NoError(t, err) - - recorder := httptest.NewRecorder() +var opts = iteratorOptions{ + encoderPool: encoderPool, + iteratorPools: iterPools, + tagOptions: tagOptions, + iOpts: iOpts, +} +func TestIngestSeries(t *testing.T) { handler := newHTTPSeriesLoadHandler(opts) - handler.ServeHTTP(recorder, req) - assert.Equal(t, http.StatusOK, recorder.Code) + loadSeries(t, handler, seriesStr) + loadSeries(t, handler, otherSeriesStr) iters, err := handler.getSeriesIterators("series_name") require.NoError(t, err) @@ -173,7 +183,7 @@ func TestIngestSeries(t *testing.T) { require.Equal(t, 1, len(expectedList)) expected := expectedList[0] - require.Equal(t, 1, len(iters.Iters())) + require.Equal(t, 1, iters.Len()) it := iters.Iters()[0] j := 0 for it.Next() { @@ -190,38 +200,38 @@ func TestIngestSeries(t *testing.T) { assert.Equal(t, j, len(expected.Datapoints)) } -func TestClearData(t *testing.T) { - opts := iteratorOptions{ - encoderPool: encoderPool, - iteratorPools: iterPools, - tagOptions: tagOptions, - iOpts: iOpts, - } +func TestGetAllSeries(t *testing.T) { + handler := newHTTPSeriesLoadHandler(opts) - req, err := http.NewRequest(http.MethodPost, "", strings.NewReader(seriesStr)) - require.NoError(t, err) + loadSeries(t, handler, seriesStr) + loadSeries(t, handler, otherSeriesStr) - recorder := httptest.NewRecorder() + iters, err := handler.getSeriesIterators("") + require.NoError(t, err) + require.Equal(t, 2, iters.Len()) +} +func TestClearData(t *testing.T) { handler := newHTTPSeriesLoadHandler(opts) - handler.ServeHTTP(recorder, req) - assert.Equal(t, http.StatusOK, recorder.Code) + loadSeries(t, handler, seriesStr) + loadSeries(t, handler, otherSeriesStr) - iters, err := handler.getSeriesIterators("series_name") + iters, err := handler.getSeriesIterators("") require.NoError(t, err) - require.Equal(t, 1, len(iters.Iters())) + require.Equal(t, 2, iters.Len()) // Call clear data - req, err = http.NewRequest(http.MethodDelete, "", nil) + req, err := http.NewRequest(http.MethodDelete, "", nil) require.NoError(t, err) + recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, req) assert.Equal(t, http.StatusOK, recorder.Code) - iters, err = handler.getSeriesIterators("series_name") + iters, err = handler.getSeriesIterators("") require.NoError(t, err) - require.Nil(t, iters) + require.Equal(t, 0, iters.Len()) } func readTags(it encoding.SeriesIterator) parser.Tags { @@ -235,3 +245,14 @@ func readTags(it encoding.SeriesIterator) parser.Tags { return tags } + +func loadSeries(t *testing.T, handler *httpSeriesLoadHandler, data string) { + req, err := http.NewRequest(http.MethodPost, "", strings.NewReader(data)) + require.NoError(t, err) + + recorder := httptest.NewRecorder() + + handler.ServeHTTP(recorder, req) + + assert.Equal(t, http.StatusOK, recorder.Code) +} diff --git a/src/query/api/v1/handler/prometheus/response.go b/src/query/api/v1/handler/prometheus/response.go index d4cbb9bed2..a28384e162 100644 --- a/src/query/api/v1/handler/prometheus/response.go +++ b/src/query/api/v1/handler/prometheus/response.go @@ -48,23 +48,23 @@ type result interface { matches(other result) (MatchInformation, error) } -type matrixResult struct { - // Result is the list of matrixRow for the response. +// MatrixResult contains a list matrixRow. +type MatrixResult struct { Result []matrixRow `json:"result"` } -type vectorResult struct { - // Result is the list of vectorItem for the response. +// VectorResult contains a list of vectorItem. +type VectorResult struct { Result []vectorItem `json:"result"` } -type scalarResult struct { - // Result is the scalar Value for the response. +// ScalarResult is the scalar Value for the response. +type ScalarResult struct { Result Value `json:"result"` } -type stringResult struct { - // Result is the string Value for the response. +// StringResult is the string Value for the response. +type StringResult struct { Result Value `json:"result"` } @@ -81,16 +81,16 @@ func (d *data) UnmarshalJSON(bytes []byte) error { switch discriminator.ResultType { case "matrix": - d.Result = &matrixResult{} + d.Result = &MatrixResult{} case "vector": - d.Result = &vectorResult{} + d.Result = &VectorResult{} case "scalar": - d.Result = &scalarResult{} + d.Result = &ScalarResult{} case "string": - d.Result = &stringResult{} + d.Result = &StringResult{} default: return fmt.Errorf("unknown resultType: %s", discriminator.ResultType) @@ -100,19 +100,19 @@ func (d *data) UnmarshalJSON(bytes []byte) error { } // Len is the number of elements in the collection. -func (r matrixResult) Len() int { return len(r.Result) } +func (r MatrixResult) Len() int { return len(r.Result) } // Less reports whether the element with // index i should sort before the element with index j. -func (r matrixResult) Less(i, j int) bool { +func (r MatrixResult) Less(i, j int) bool { return r.Result[i].id < r.Result[j].id } // Swap swaps the elements with indexes i and j. -func (r matrixResult) Swap(i, j int) { r.Result[i], r.Result[j] = r.Result[j], r.Result[i] } +func (r MatrixResult) Swap(i, j int) { r.Result[i], r.Result[j] = r.Result[j], r.Result[i] } -// Sort sorts the matrixResult. -func (r matrixResult) Sort() { +// Sort sorts the MatrixResult. +func (r MatrixResult) Sort() { for i, result := range r.Result { r.Result[i].id = result.Metric.genID() } @@ -121,19 +121,19 @@ func (r matrixResult) Sort() { } // Len is the number of elements in the vector. -func (r vectorResult) Len() int { return len(r.Result) } +func (r VectorResult) Len() int { return len(r.Result) } // Less reports whether the element with // index i should sort before the element with index j. -func (r vectorResult) Less(i, j int) bool { +func (r VectorResult) Less(i, j int) bool { return r.Result[i].id < r.Result[j].id } // Swap swaps the elements with indexes i and j. -func (r vectorResult) Swap(i, j int) { r.Result[i], r.Result[j] = r.Result[j], r.Result[i] } +func (r VectorResult) Swap(i, j int) { r.Result[i], r.Result[j] = r.Result[j], r.Result[i] } -// Sort sorts the vectorResult. -func (r vectorResult) Sort() { +// Sort sorts the VectorResult. +func (r VectorResult) Sort() { for i, result := range r.Result { r.Result[i].id = result.Metric.genID() } @@ -224,10 +224,10 @@ func (d data) matches(other data) (MatchInformation, error) { return d.Result.matches(other.Result) } -func (r matrixResult) matches(other result) (MatchInformation, error) { - otherMatrix, ok := other.(*matrixResult) +func (r MatrixResult) matches(other result) (MatchInformation, error) { + otherMatrix, ok := other.(*MatrixResult) if !ok { - err := fmt.Errorf("incorrect type for matching, expected matrixResult, %v", other) + err := fmt.Errorf("incorrect type for matching, expected MatrixResult, %v", other) return MatchInformation{ NoMatch: true, }, err @@ -254,10 +254,10 @@ func (r matrixResult) matches(other result) (MatchInformation, error) { return MatchInformation{FullMatch: true}, nil } -func (r vectorResult) matches(other result) (MatchInformation, error) { - otherVector, ok := other.(*vectorResult) +func (r VectorResult) matches(other result) (MatchInformation, error) { + otherVector, ok := other.(*VectorResult) if !ok { - err := fmt.Errorf("incorrect type for matching, expected vectorResult") + err := fmt.Errorf("incorrect type for matching, expected VectorResult") return MatchInformation{ NoMatch: true, }, err @@ -284,10 +284,10 @@ func (r vectorResult) matches(other result) (MatchInformation, error) { return MatchInformation{FullMatch: true}, nil } -func (r scalarResult) matches(other result) (MatchInformation, error) { - otherScalar, ok := other.(*scalarResult) +func (r ScalarResult) matches(other result) (MatchInformation, error) { + otherScalar, ok := other.(*ScalarResult) if !ok { - err := fmt.Errorf("incorrect type for matching, expected scalarResult") + err := fmt.Errorf("incorrect type for matching, expected ScalarResult") return MatchInformation{ NoMatch: true, }, err @@ -302,10 +302,10 @@ func (r scalarResult) matches(other result) (MatchInformation, error) { return MatchInformation{FullMatch: true}, nil } -func (r stringResult) matches(other result) (MatchInformation, error) { - otherString, ok := other.(*stringResult) +func (r StringResult) matches(other result) (MatchInformation, error) { + otherString, ok := other.(*StringResult) if !ok { - err := fmt.Errorf("incorrect type for matching, expected stringResult") + err := fmt.Errorf("incorrect type for matching, expected StringResult") return MatchInformation{ NoMatch: true, }, err diff --git a/src/query/api/v1/handler/prometheus/response_test.go b/src/query/api/v1/handler/prometheus/response_test.go index a067822ffd..c076410458 100644 --- a/src/query/api/v1/handler/prometheus/response_test.go +++ b/src/query/api/v1/handler/prometheus/response_test.go @@ -64,7 +64,7 @@ func TestUnmarshalPrometheusResponse(t *testing.T) { "success", data{ "scalar", - &scalarResult{Value{1590605774.0, "84"}}, + &ScalarResult{Value{1590605774.0, "84"}}, }, }, }, @@ -81,7 +81,7 @@ func TestUnmarshalPrometheusResponse(t *testing.T) { "success", data{ "string", - &stringResult{Value{1590605775.0, "FOO"}}, + &StringResult{Value{1590605775.0, "FOO"}}, }, }, }, @@ -113,7 +113,7 @@ func TestUnmarshalPrometheusResponse(t *testing.T) { "success", data{ "vector", - &vectorResult{[]vectorItem{ + &VectorResult{[]vectorItem{ { Metric: Tags{"__name__": "foo", "bar": "1"}, Value: Value{1590605775.0, "0.5"}, @@ -154,7 +154,7 @@ func TestUnmarshalPrometheusResponse(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "foo", "bar": "1"}, Values: Values{{1590605775.0, "1"}, {1590605785.0, "11"}}, @@ -197,7 +197,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "scalar", - &scalarResult{Value{1590605774.0, "1"}}, + &ScalarResult{Value{1590605774.0, "1"}}, }, }, }, @@ -207,7 +207,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "scalar", - &scalarResult{Value{1590605775.0, "1"}}, + &ScalarResult{Value{1590605775.0, "1"}}, }, }, }, @@ -217,7 +217,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "scalar", - &scalarResult{Value{1590605774.0, "2"}}, + &ScalarResult{Value{1590605774.0, "2"}}, }, }, }, @@ -228,7 +228,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "vector", - &vectorResult{[]vectorItem{ + &VectorResult{[]vectorItem{ { Metric: Tags{"__name__": "foo"}, Value: Value{1590605775.0, "0.5"}, @@ -243,7 +243,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "vector", - &vectorResult{[]vectorItem{ + &VectorResult{[]vectorItem{ { Metric: Tags{"__name__": "foo", "bar": "1"}, Value: Value{1590605775.0, "0.5"}, @@ -258,7 +258,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "vector", - &vectorResult{[]vectorItem{ + &VectorResult{[]vectorItem{ { Metric: Tags{"__name__": "foo", "bar": "1"}, Value: Value{1590605775.0, "0.5"}, @@ -277,7 +277,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "vector", - &vectorResult{[]vectorItem{ + &VectorResult{[]vectorItem{ { Metric: Tags{"__name__": "bar"}, Value: Value{1590605775.0, "0.5"}, @@ -292,7 +292,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "vector", - &vectorResult{[]vectorItem{ + &VectorResult{[]vectorItem{ { Metric: Tags{"__name__": "foo"}, Value: Value{1590605775.0, "1"}, @@ -307,7 +307,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "vector", - &vectorResult{[]vectorItem{ + &VectorResult{[]vectorItem{ { Metric: Tags{"__name__": "foo"}, Value: Value{1590605774.0, "0.5"}, @@ -323,7 +323,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "foo"}, Values: Values{{1590605775.0, "1"}}, @@ -338,7 +338,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "bar"}, Values: Values{{1590605775.0, "1"}}, @@ -353,7 +353,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "foo"}, Values: Values{{1590605775.0, "2"}}, @@ -368,7 +368,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "foo"}, Values: Values{{1590605776.0, "1"}}, @@ -383,7 +383,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "foo", "bar": "1"}, Values: Values{{1590605775.0, "1"}}, @@ -398,7 +398,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "foo"}, Values: Values{{1590605775.0, "1"}, {1590605776.0, "2"}}, @@ -413,7 +413,7 @@ func TestResponseMatching(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "foo"}, Values: Values{{1590605775.0, "1"}}, @@ -456,7 +456,7 @@ func TestResponseMatchingOrderInsensitive(t *testing.T) { "success", data{ "vector", - &vectorResult{[]vectorItem{ + &VectorResult{[]vectorItem{ { Metric: Tags{"__name__": "first"}, Value: Value{1590605775.0, "1"}, @@ -472,7 +472,7 @@ func TestResponseMatchingOrderInsensitive(t *testing.T) { "success", data{ "vector", - &vectorResult{[]vectorItem{ + &VectorResult{[]vectorItem{ { Metric: Tags{"__name__": "second"}, Value: Value{1590605775.0, "2"}, @@ -491,7 +491,7 @@ func TestResponseMatchingOrderInsensitive(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "first"}, Values: Values{{1590605775.0, "1"}}, @@ -507,7 +507,7 @@ func TestResponseMatchingOrderInsensitive(t *testing.T) { "success", data{ "matrix", - &matrixResult{[]matrixRow{ + &MatrixResult{[]matrixRow{ { Metric: Tags{"__name__": "second"}, Values: Values{{1590605775.0, "2"}}, diff --git a/src/query/test/m3comparator_client.go b/src/query/test/compatibility/m3comparator_client.go similarity index 99% rename from src/query/test/m3comparator_client.go rename to src/query/test/compatibility/m3comparator_client.go index a3582909fb..58819d853b 100644 --- a/src/query/test/m3comparator_client.go +++ b/src/query/test/compatibility/m3comparator_client.go @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package test +package compatibility import ( "bytes" diff --git a/src/query/test/m3query_client.go b/src/query/test/compatibility/m3query_client.go similarity index 98% rename from src/query/test/m3query_client.go rename to src/query/test/compatibility/m3query_client.go index 8b0c57bad1..067f8faa57 100644 --- a/src/query/test/m3query_client.go +++ b/src/query/test/compatibility/m3query_client.go @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package test +package compatibility import ( "fmt" diff --git a/src/query/test/promql_test.go b/src/query/test/compatibility/promql_test.go similarity index 99% rename from src/query/test/promql_test.go rename to src/query/test/compatibility/promql_test.go index 7dab41d803..d5f756800f 100644 --- a/src/query/test/promql_test.go +++ b/src/query/test/compatibility/promql_test.go @@ -35,7 +35,7 @@ // This code was taken from prometheus repo: https://github.com/prometheus/prometheus/blob/master/promql/promql_test.go -package test +package compatibility import ( "path/filepath" diff --git a/src/query/test/test.go b/src/query/test/compatibility/test.go similarity index 91% rename from src/query/test/test.go rename to src/query/test/compatibility/test.go index 97dd3b52a3..f67600c8f3 100644 --- a/src/query/test/test.go +++ b/src/query/test/compatibility/test.go @@ -33,7 +33,7 @@ // Parts of code were taken from prometheus repo: https://github.com/prometheus/prometheus/blob/master/promql/test.go -package test +package compatibility import ( "context" @@ -48,10 +48,10 @@ import ( "time" cparser "github.com/m3db/m3/src/cmd/services/m3comparator/main/parser" + "github.com/m3db/m3/src/query/api/v1/handler/prometheus" "github.com/pkg/errors" "github.com/prometheus/common/model" - "github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/promql/parser" @@ -391,15 +391,13 @@ func (ev *evalCmd) expect(pos int, m labels.Labels, vals ...parser.SequenceValue ev.expected[h] = entry{pos: pos, vals: vals} } -const sep = '\xff' - // Hash returns a hash value for the label set. -func hash(ls model.Metric) uint64 { +func hash(ls prometheus.Tags) uint64 { lbs := make(labels.Labels, 0, len(ls)) for k, v := range ls { lbs = append(lbs, labels.Label{ - Name: string(k), - Value: string(v), + Name: k, + Value: v, }) } @@ -410,34 +408,27 @@ func hash(ls model.Metric) uint64 { return lbs.Hash() } -// QueryResponse defines a structure for expected response. -type QueryResponse struct { - Status string - Data struct { - ResultType string - Result model.Samples - } -} - // compareResult compares the result value with the defined expectation. func (ev *evalCmd) compareResult(j []byte) error { - var result QueryResponse - err := json.Unmarshal(j, &result) + var response prometheus.Response + err := json.Unmarshal(j, &response) if err != nil { return err } - if result.Status != "success" { - return fmt.Errorf("unsuccess status received: %s", result.Status) + if response.Status != "success" { + return fmt.Errorf("unsuccess status received: %s", response.Status) } - switch result.Data.ResultType { - case "matrix": + result := response.Data.Result + + switch result := result.(type) { + case *prometheus.MatrixResult: return errors.New("received range result on instant evaluation") - case "vector": + case *prometheus.VectorResult: seen := map[uint64]bool{} - for pos, v := range result.Data.Result { + for pos, v := range result.Result { fp := hash(v.Metric) if _, ok := ev.metrics[fp]; !ok { return errors.Errorf("unexpected metric %s in result", v.Metric) @@ -447,31 +438,43 @@ func (ev *evalCmd) compareResult(j []byte) error { if ev.ordered && exp.pos != pos+1 { return errors.Errorf("expected metric %s with %v at position %d but was at %d", v.Metric, exp.vals, exp.pos, pos+1) } - if !almostEqual(exp.vals[0].Value, float64(v.Value)) { - return errors.Errorf("expected %v for %s but got %v", exp.vals[0].Value, v.Metric, v.Value) + val, err := parseNumber(fmt.Sprint(v.Value[1])) + if err != nil { + return err + } + if !almostEqual(exp.vals[0].Value, val) { + return errors.Errorf("expected %v for %s but got %v", exp.vals[0].Value, v.Metric, val) } seen[fp] = true } for fp, expVals := range ev.expected { if !seen[fp] { - fmt.Println("vector result", len(result.Data.Result), ev.expr) - for _, ss := range result.Data.Result { + fmt.Println("vector result", len(result.Result), ev.expr) + for _, ss := range result.Result { fmt.Println(" ", ss.Metric, ss.Value) } return errors.Errorf("expected metric %s with %v not found", ev.metrics[fp], expVals) } } - // TODO: Untested code. Uncomment when m3query will support scalars and fix it if needed. - //case "scalar": - // if !almostEqual(ev.expected[0].vals[0].Value, val.V) { - // return errors.Errorf("expected Scalar %v but got %v", val.V, ev.expected[0].vals[0].Value) - // } + case *prometheus.ScalarResult: + v, err := parseNumber(fmt.Sprint(result.Result[1])) + if err != nil { + return err + } + if len(ev.expected) == 0 || len(ev.expected[0].vals) == 0 { + return errors.Errorf("expected no Scalar value but got %v", v) + } + expected := ev.expected[0].vals[0].Value + if !almostEqual(expected, v) { + return errors.Errorf("expected Scalar %v but got %v", expected, v) + } default: panic(errors.Errorf("promql.Test.compareResult: unexpected result type %T", result)) } + return nil } @@ -535,8 +538,7 @@ func (t *Test) exec(tc testCommand) error { // clear the current test storage of all inserted samples. func (t *Test) clear() error { - t.m3comparator.clear() - return nil + return t.m3comparator.clear() } // Close closes resources associated with the Test. @@ -560,7 +562,7 @@ func almostEqual(a, b float64) bool { diff := math.Abs(a - b) if a == 0 || b == 0 || diff < minNormal { - return diff < epsilon*minNormal + return diff < epsilon } return diff/(math.Abs(a)+math.Abs(b)) < epsilon } diff --git a/src/query/test/testdata/LICENSE.txt b/src/query/test/compatibility/testdata/LICENSE.txt similarity index 100% rename from src/query/test/testdata/LICENSE.txt rename to src/query/test/compatibility/testdata/LICENSE.txt diff --git a/src/query/test/testdata/aggregators.test b/src/query/test/compatibility/testdata/aggregators.test similarity index 90% rename from src/query/test/testdata/aggregators.test rename to src/query/test/compatibility/testdata/aggregators.test index 8505cf18f1..716395e8b7 100644 --- a/src/query/test/testdata/aggregators.test +++ b/src/query/test/compatibility/testdata/aggregators.test @@ -36,10 +36,10 @@ eval instant at 50m count by (group) (http_requests{job="api-server"}) {group="canary"} 2 {group="production"} 2 -# FAILING issue #9. Simple without. -#eval instant at 50m sum without (instance) (http_requests{job="api-server"}) -# {group="canary",job="api-server"} 700 -# {group="production",job="api-server"} 300 +# Simple without. +eval instant at 50m sum without (instance) (http_requests{job="api-server"}) + {group="canary",job="api-server"} 700 + {group="production",job="api-server"} 300 # Empty by. eval instant at 50m sum by () (http_requests{job="api-server"}) @@ -49,17 +49,17 @@ eval instant at 50m sum by () (http_requests{job="api-server"}) eval instant at 50m sum(http_requests{job="api-server"}) {} 1000 -# FAILING issue #9. Empty without. -#eval instant at 50m sum without () (http_requests{job="api-server",group="production"}) -# {group="production",job="api-server",instance="0"} 100 -# {group="production",job="api-server",instance="1"} 200 +# Empty without. +eval instant at 50m sum without () (http_requests{job="api-server",group="production"}) + {group="production",job="api-server",instance="0"} 100 + {group="production",job="api-server",instance="1"} 200 -# FAILING issue #9. Without with mismatched and missing labels. Do not do this. -#eval instant at 50m sum without (instance) (http_requests{job="api-server"} or foo) -# {group="canary",job="api-server"} 700 -# {group="production",job="api-server"} 300 -# {region="europe",job="api-server"} 900 -# {job="api-server"} 1000 +# Without with mismatched and missing labels. Do not do this. +eval instant at 50m sum without (instance) (http_requests{job="api-server"} or foo) + {group="canary",job="api-server"} 700 + {group="production",job="api-server"} 300 + {region="europe",job="api-server"} 900 + {job="api-server"} 1000 # Lower-cased aggregation operators should work too. eval instant at 50m sum(http_requests) by (job) + min(http_requests) by (job) + max(http_requests) by (job) + avg(http_requests) by (job) @@ -101,9 +101,11 @@ load 5m http_requests{job="api-server", instance="1", group="production"} 0+1.33x10 http_requests{job="api-server", instance="0", group="canary"} 0+1.33x10 +# FAILING issue #10. (it is almost zero) #eval instant at 50m stddev(http_requests) # {} 0.0 +# FAILING issue #11. (it is almost zero) #eval instant at 50m stdvar(http_requests) # {} 0.0 @@ -115,10 +117,9 @@ load 5m label_grouping_test{a="aa", b="bb"} 0+10x10 label_grouping_test{a="a", b="abb"} 0+20x10 -# FAILING -#eval instant at 50m sum(label_grouping_test) by (a, b) -# {a="a", b="abb"} 200 -# {a="aa", b="bb"} 100 +eval instant at 50m sum(label_grouping_test) by (a, b) + {a="a", b="abb"} 200 + {a="aa", b="bb"} 100 @@ -184,9 +185,9 @@ load 5m # http_requests{group="canary", instance="0", job="app-server"} 700 # http_requests{group="canary", instance="1", job="app-server"} 800 -#eval instant at 50m topk by (group) (1, http_requests) -# http_requests{group="production", instance="1", job="app-server"} 600 -# http_requests{group="canary", instance="1", job="app-server"} 800 +eval instant at 50m topk by (group) (1, http_requests) + http_requests{group="production", instance="1", job="app-server"} 600 + http_requests{group="canary", instance="1", job="app-server"} 800 #eval instant at 50m bottomk by (group) (2, http_requests) # http_requests{group="canary", instance="0", job="api-server"} 300 @@ -239,7 +240,7 @@ load 5m version{job="app-server", instance="0", group="canary"} 7 version{job="app-server", instance="1", group="canary"} 7 -# FAILING issue #14 +# FAILING issue #14 (count_values) #eval instant at 5m count_values("version", version) # {version="6"} 5 # {version="7"} 2 @@ -285,7 +286,7 @@ load 10s data{test="uneven samples",point="c"} 4 foo .8 -# FAILING issue #8 +# FAILING issue #8 (quantile) #eval instant at 1m quantile without(point)(0.8, data) # {test="two samples"} 0.8 # {test="three samples"} 1.6 diff --git a/src/query/test/testdata/functions.test b/src/query/test/compatibility/testdata/functions.test similarity index 86% rename from src/query/test/testdata/functions.test rename to src/query/test/compatibility/testdata/functions.test index 9f7f769cb1..bef714ed38 100644 --- a/src/query/test/testdata/functions.test +++ b/src/query/test/compatibility/testdata/functions.test @@ -26,7 +26,7 @@ eval instant at 50m resets(http_requests[50m]) {path="/bar"} 1 {path="/biz"} 0 -# FAILING. eval instant at 50m resets(nonexistent_metric[50m]) +eval instant at 50m resets(nonexistent_metric[50m]) # Tests for changes(). # FAILING issue #17 @@ -55,7 +55,7 @@ eval instant at 50m changes(http_requests[30m]) # {path="/bar"} 9 # {path="/biz"} 1 -# FAILING. eval instant at 50m changes(nonexistent_metric[50m]) +eval instant at 50m changes(nonexistent_metric[50m]) clear @@ -141,12 +141,10 @@ load 5m testcounter_reset_middle 0+10x4 0+10x5 http_requests{job="app-server", instance="1", group="canary"} 0+80x10 -# FAILING TODO: should not fail, need to check # deriv should return the same as rate in simple cases. eval instant at 50m rate(http_requests{group="canary", instance="1", job="app-server"}[50m]) {group="canary", instance="1", job="app-server"} 0.26666666666666666 -# FAILING TODO: should not fail, need to check eval instant at 50m deriv(http_requests{group="canary", instance="1", job="app-server"}[50m]) {group="canary", instance="1", job="app-server"} 0.26666666666666666 @@ -241,16 +239,16 @@ clear load 10s metric 1 1 -# FAILING. eval instant at 0s timestamp(metric) +# FAILING issue #23. eval instant at 0s timestamp(metric) # {} 0 -# FAILING. eval instant at 5s timestamp(metric) +# FAILING issue #23. eval instant at 5s timestamp(metric) # {} 0 -# FAILING. eval instant at 10s timestamp(metric) +# FAILING issue #23. eval instant at 10s timestamp(metric) # {} 10 -# FAILING. eval instant at 10s timestamp(((metric))) +# FAILING issue #23. eval instant at 10s timestamp(((metric))) # {} 10 # Tests for label_join. @@ -344,7 +342,8 @@ load 5m http_requests{job="app-server", instance="0", group="canary"} 0+70x10 http_requests{job="app-server", instance="1", group="canary"} 0+80x10 -# FAILING. eval_ordered instant at 50m sort(http_requests) +# FAILING issue #28: +#eval_ordered instant at 50m sort(http_requests) # http_requests{group="production", instance="0", job="api-server"} 100 # http_requests{group="production", instance="1", job="api-server"} 200 # http_requests{group="canary", instance="0", job="api-server"} 300 @@ -415,7 +414,7 @@ eval instant at 1m stdvar_over_time(metric[1m]) eval instant at 1m stddev_over_time(metric[1m]) {} 3.249615 -# FAILING. eval instant at 1m stddev_over_time((metric[1m])) +# FAILING issue #19. eval instant at 1m stddev_over_time((metric[1m])) # {} 3.249615 # Tests for stddev_over_time and stdvar_over_time #4927. @@ -472,14 +471,14 @@ eval instant at 1m quantile_over_time(2, data[1m]) {test="three samples"} +Inf {test="uneven samples"} +Inf -# FAILING. eval instant at 1m (quantile_over_time(2, (data[1m]))) +# FAILING issue #19. eval instant at 1m (quantile_over_time(2, (data[1m]))) # {test="two samples"} +Inf # {test="three samples"} +Inf # {test="uneven samples"} +Inf clear -# FAILING. Test time-related functions. +# FAILING issue #30. Test time-related functions. #eval instant at 0m year() # {} 1970 @@ -579,23 +578,23 @@ load 10s clear -# FAILING. Testdata for absent_over_time() +# FAILING issue #6. Testdata for absent_over_time() #eval instant at 1m absent_over_time(http_requests[5m]) # {} 1 -# FAILING. eval instant at 1m absent_over_time(http_requests{handler="/foo"}[5m]) +# FAILING issue #6. eval instant at 1m absent_over_time(http_requests{handler="/foo"}[5m]) # {handler="/foo"} 1 -# FAILING. eval instant at 1m absent_over_time(http_requests{handler!="/foo"}[5m]) +# FAILING issue #6. eval instant at 1m absent_over_time(http_requests{handler!="/foo"}[5m]) # {} 1 -# FAILING. eval instant at 1m absent_over_time(http_requests{handler="/foo", handler="/bar", handler="/foobar"}[5m]) +# FAILING issue #6. eval instant at 1m absent_over_time(http_requests{handler="/foo", handler="/bar", handler="/foobar"}[5m]) # {} 1 -# FAILING. eval instant at 1m absent_over_time(rate(nonexistant[5m])[5m:]) +# FAILING issue #6. eval instant at 1m absent_over_time(rate(nonexistant[5m])[5m:]) # {} 1 -# FAILING. eval instant at 1m absent_over_time(http_requests{handler="/foo", handler="/bar", instance="127.0.0.1"}[5m]) +# FAILING issue #6. eval instant at 1m absent_over_time(http_requests{handler="/foo", handler="/bar", instance="127.0.0.1"}[5m]) # {instance="127.0.0.1"} 1 load 1m @@ -605,40 +604,40 @@ load 1m httpd_log_lines_total{instance="127.0.0.1",job="node"} 1 ssl_certificate_expiry_seconds{job="ingress"} NaN NaN NaN NaN NaN -# FAILING. eval instant at 5m absent_over_time(http_requests[5m]) +# FAILING issue #6. eval instant at 5m absent_over_time(http_requests[5m]) -# FAILING. eval instant at 5m absent_over_time(rate(http_requests[5m])[5m:1m]) +# FAILING issue #6. eval instant at 5m absent_over_time(rate(http_requests[5m])[5m:1m]) -# FAILING. eval instant at 0m absent_over_time(httpd_log_lines_total[30s]) +# FAILING issue #6. eval instant at 0m absent_over_time(httpd_log_lines_total[30s]) -# FAILING. eval instant at 1m absent_over_time(httpd_log_lines_total[30s]) +# FAILING issue #6. eval instant at 1m absent_over_time(httpd_log_lines_total[30s]) # {} 1 -# FAILING. eval instant at 15m absent_over_time(http_requests[5m]) +# FAILING issue #6. eval instant at 15m absent_over_time(http_requests[5m]) -# FAILING. eval instant at 16m absent_over_time(http_requests[5m]) +# FAILING issue #6. eval instant at 16m absent_over_time(http_requests[5m]) # {} 1 -# FAILING. eval instant at 16m absent_over_time(http_requests[6m]) +# FAILING issue #6. eval instant at 16m absent_over_time(http_requests[6m]) -# FAILING. eval instant at 16m absent_over_time(httpd_handshake_failures_total[1m]) +# FAILING issue #6. eval instant at 16m absent_over_time(httpd_handshake_failures_total[1m]) -# FAILING. eval instant at 16m absent_over_time({instance="127.0.0.1"}[5m]) +# FAILING issue #6. eval instant at 16m absent_over_time({instance="127.0.0.1"}[5m]) -# FAILING. eval instant at 16m absent_over_time({instance="127.0.0.1"}[5m]) +# FAILING issue #6. eval instant at 16m absent_over_time({instance="127.0.0.1"}[5m]) -# FAILING. eval instant at 21m absent_over_time({instance="127.0.0.1"}[5m]) -# FAILING. {instance="127.0.0.1"} 1 +# FAILING issue #6. eval instant at 21m absent_over_time({instance="127.0.0.1"}[5m]) +# FAILING issue #6. {instance="127.0.0.1"} 1 -# FAILING. eval instant at 21m absent_over_time({instance="127.0.0.1"}[20m]) +# FAILING issue #6. eval instant at 21m absent_over_time({instance="127.0.0.1"}[20m]) -# FAILING. eval instant at 21m absent_over_time({job="grok"}[20m]) -# FAILING. {job="grok"} 1 +# FAILING issue #6. eval instant at 21m absent_over_time({job="grok"}[20m]) +# FAILING issue #6. {job="grok"} 1 -# FAILING. eval instant at 30m absent_over_time({instance="127.0.0.1"}[5m:5s]) -# FAILING. {} 1 +# FAILING issue #6. eval instant at 30m absent_over_time({instance="127.0.0.1"}[5m:5s]) +# FAILING issue #6. {} 1 -# FAILING. eval instant at 5m absent_over_time({job="ingress"}[4m]) +# FAILING issue #6. eval instant at 5m absent_over_time({job="ingress"}[4m]) -# FAILING. eval instant at 10m absent_over_time({job="ingress"}[4m]) -# FAILING. {job="ingress"} 1 +# FAILING issue #6. eval instant at 10m absent_over_time({job="ingress"}[4m]) +# FAILING issue #6. {job="ingress"} 1 diff --git a/src/query/test/testdata/histograms.test b/src/query/test/compatibility/testdata/histograms.test similarity index 97% rename from src/query/test/testdata/histograms.test rename to src/query/test/compatibility/testdata/histograms.test index 88fe483e64..664fd6c4ed 100644 --- a/src/query/test/testdata/histograms.test +++ b/src/query/test/compatibility/testdata/histograms.test @@ -164,7 +164,8 @@ load 5m nonmonotonic_bucket{le="+Inf"} 0+9x10 # Nonmonotonic buckets -# FAILING issue #48. eval instant at 50m histogram_quantile(0.99, nonmonotonic_bucket) +# TODO - enable after https://github.com/prometheus/prometheus/commit/7eaffa71802821087c8ee42dbda652453ec1f867 is released: +# eval instant at 50m histogram_quantile(0.99, nonmonotonic_bucket) # {} 0.989875 # FAILING issue #48. Buckets with different representations of the same upper bound. diff --git a/src/query/test/testdata/legacy.test b/src/query/test/compatibility/testdata/legacy.test similarity index 78% rename from src/query/test/testdata/legacy.test rename to src/query/test/compatibility/testdata/legacy.test index b60a352ed1..10a7143ae5 100644 --- a/src/query/test/testdata/legacy.test +++ b/src/query/test/compatibility/testdata/legacy.test @@ -229,69 +229,69 @@ eval instant at 50m sum_over_time(http_requests{group="production",job="api-serv # FAILING. eval instant at 50m time() # 3000 -# FAILING. eval instant at 50m {__name__=~".+"} -# http_requests{group="canary", instance="0", job="api-server"} 300 -# http_requests{group="canary", instance="0", job="app-server"} 700 -# http_requests{group="canary", instance="1", job="api-server"} 400 -# http_requests{group="canary", instance="1", job="app-server"} 800 -# http_requests{group="production", instance="0", job="api-server"} 100 -# http_requests{group="production", instance="0", job="app-server"} 500 -# http_requests{group="production", instance="1", job="api-server"} 200 -# http_requests{group="production", instance="1", job="app-server"} 600 -# testcounter_reset_end 0 -# testcounter_reset_middle 50 -# x{y="testvalue"} 100 -# label_grouping_test{a="a", b="abb"} 200 -# label_grouping_test{a="aa", b="bb"} 100 -# vector_matching_a{l="x"} 10 -# vector_matching_a{l="y"} 20 -# vector_matching_b{l="x"} 40 -# cpu_count{instance="1", type="smp"} 200 -# cpu_count{instance="0", type="smp"} 100 -# cpu_count{instance="0", type="numa"} 300 - - -# FAILING. eval instant at 50m {job=~".+-server", job!~"api-.+"} -# http_requests{group="canary", instance="0", job="app-server"} 700 -# http_requests{group="canary", instance="1", job="app-server"} 800 -# http_requests{group="production", instance="0", job="app-server"} 500 -# http_requests{group="production", instance="1", job="app-server"} 600 - -# FAILING. eval instant at 50m absent(nonexistent) +eval instant at 50m {__name__=~".+"} + http_requests{group="canary", instance="0", job="api-server"} 300 + http_requests{group="canary", instance="0", job="app-server"} 700 + http_requests{group="canary", instance="1", job="api-server"} 400 + http_requests{group="canary", instance="1", job="app-server"} 800 + http_requests{group="production", instance="0", job="api-server"} 100 + http_requests{group="production", instance="0", job="app-server"} 500 + http_requests{group="production", instance="1", job="api-server"} 200 + http_requests{group="production", instance="1", job="app-server"} 600 + testcounter_reset_end 0 + testcounter_reset_middle 50 + x{y="testvalue"} 100 + label_grouping_test{a="a", b="abb"} 200 + label_grouping_test{a="aa", b="bb"} 100 + vector_matching_a{l="x"} 10 + vector_matching_a{l="y"} 20 + vector_matching_b{l="x"} 40 + cpu_count{instance="1", type="smp"} 200 + cpu_count{instance="0", type="smp"} 100 + cpu_count{instance="0", type="numa"} 300 + + +eval instant at 50m {job=~".+-server", job!~"api-.+"} + http_requests{group="canary", instance="0", job="app-server"} 700 + http_requests{group="canary", instance="1", job="app-server"} 800 + http_requests{group="production", instance="0", job="app-server"} 500 + http_requests{group="production", instance="1", job="app-server"} 600 + +# eval instant at 50m absent(nonexistent) # {} 1 -# FAILING. eval instant at 50m absent(nonexistent{job="testjob", instance="testinstance", method=~".x"}) +# FAILING issue #52. eval instant at 50m absent(nonexistent{job="testjob", instance="testinstance", method=~".x"}) # {instance="testinstance", job="testjob"} 1 -# FAILING. eval instant at 50m absent(nonexistent{job="testjob",job="testjob2",foo="bar"}) +# FAILING issue #52. eval instant at 50m absent(nonexistent{job="testjob",job="testjob2",foo="bar"}) # {foo="bar"} 1 -# FAILING. eval instant at 50m absent(nonexistent{job="testjob",job="testjob2",job="three",foo="bar"}) +# FAILING issue #52. eval instant at 50m absent(nonexistent{job="testjob",job="testjob2",job="three",foo="bar"}) # {foo="bar"} 1 -# FAILING. eval instant at 50m absent(nonexistent{job="testjob",job=~"testjob2",foo="bar"}) +# FAILING issue #52. eval instant at 50m absent(nonexistent{job="testjob",job=~"testjob2",foo="bar"}) # {foo="bar"} 1 eval instant at 50m absent(http_requests) eval instant at 50m absent(sum(http_requests)) -# FAILING. eval instant at 50m absent(sum(nonexistent{job="testjob", instance="testinstance"})) +# FAILING issue #52. eval instant at 50m absent(sum(nonexistent{job="testjob", instance="testinstance"})) # {} 1 -# FAILING. eval instant at 50m absent(max(nonexistant)) +# FAILING issue #52. eval instant at 50m absent(max(nonexistant)) # {} 1 -# FAILING. eval instant at 50m absent(nonexistant > 1) +# FAILING issue #52. eval instant at 50m absent(nonexistant > 1) # {} 1 -# FAILING. eval instant at 50m absent(a + b) +# FAILING issue #52. eval instant at 50m absent(a + b) # {} 1 -# FAILING. eval instant at 50m absent(a and b) +# FAILING issue #52. eval instant at 50m absent(a and b) # {} 1 -# FAILING. eval instant at 50m absent(rate(nonexistant[5m])) +# FAILING issue #52. eval instant at 50m absent(rate(nonexistant[5m])) # {} 1 eval instant at 50m http_requests{group="production",job="api-server"} offset 5m @@ -314,7 +314,7 @@ eval instant at 50m -1 * http_requests{group="canary", instance="0", job="api-se # Failing with keepNaN feature. eval instant at 50m 0 * http_requests{group="canary", instance="0", job="api-server"} % 0 # {group="canary", instance="0", job="api-server"} NaN -# FAILING. eval instant at 50m exp(vector_matching_a) +# FAILING issue #53. eval instant at 50m exp(vector_matching_a) # {l="x"} 22026.465794806718 # {l="y"} 485165195.4097903 @@ -326,53 +326,54 @@ eval instant at 50m exp(vector_matching_a - 20) {l="x"} 4.5399929762484854e-05 {l="y"} 1 -# FAILING. eval instant at 50m ln(vector_matching_a) +# FAILING issue #53. eval instant at 50m ln(vector_matching_a) # {l="x"} 2.302585092994046 # {l="y"} 2.995732273553991 -# FAILING. eval instant at 50m ln(vector_matching_a - 10) -# {l="y"} 2.302585092994046 -# {l="x"} -Inf +eval instant at 50m ln(vector_matching_a - 10) + {l="y"} 2.302585092994046 + {l="x"} -Inf -# FAILING. eval instant at 50m ln(vector_matching_a - 20) +# FAILING with keepNaN feature. eval instant at 50m ln(vector_matching_a - 20) # {l="y"} -Inf # {l="x"} NaN -# FAILING. eval instant at 50m exp(ln(vector_matching_a)) +# FAILING issue #53. eval instant at 50m exp(ln(vector_matching_a)) # {l="y"} 20 # {l="x"} 10 -# FAILING. eval instant at 50m sqrt(vector_matching_a) +# FAILING issue #53. eval instant at 50m sqrt(vector_matching_a) # {l="x"} 3.1622776601683795 # {l="y"} 4.47213595499958 -# FAILING. eval instant at 50m log2(vector_matching_a) +# FAILING issue #53. eval instant at 50m log2(vector_matching_a) # {l="x"} 3.3219280948873626 # {l="y"} 4.321928094887363 -# FAILING. eval instant at 50m log2(vector_matching_a - 10) -# {l="y"} 3.3219280948873626 -# {l="x"} -Inf +eval instant at 50m log2(vector_matching_a - 10) + {l="y"} 3.3219280948873626 + {l="x"} -Inf -# FAILING. eval instant at 50m log2(vector_matching_a - 20) +# FAILING with keepNaN feature. eval instant at 50m log2(vector_matching_a - 20) # {l="x"} NaN # {l="y"} -Inf -# FAILING. eval instant at 50m log10(vector_matching_a) +# FAILING issue #53. eval instant at 50m log10(vector_matching_a) # {l="x"} 1 # {l="y"} 1.301029995663981 -# FAILING. eval instant at 50m log10(vector_matching_a - 10) -# {l="y"} 1 -# {l="x"} -Inf +eval instant at 50m log10(vector_matching_a - 10) + {l="y"} 1 + {l="x"} -Inf -# FAILING. eval instant at 50m log10(vector_matching_a - 20) +# FAILING with keepNaN feature. eval instant at 50m log10(vector_matching_a - 20) # {l="x"} NaN # {l="y"} -Inf # Matrix tests. clear + load 1h testmetric{aa="bb"} 1 testmetric{a="abb"} 2 diff --git a/src/query/test/compatibility/testdata/literals.test b/src/query/test/compatibility/testdata/literals.test new file mode 100644 index 0000000000..346d792610 --- /dev/null +++ b/src/query/test/compatibility/testdata/literals.test @@ -0,0 +1,59 @@ +eval instant at 50m 12.34e6 + 12340000 + +eval instant at 50m 12.34e+6 + 12340000 + +eval instant at 50m 12.34e-6 + 0.00001234 + +eval instant at 50m 1+1 + 2 + +eval instant at 50m 1-1 + 0 + +eval instant at 50m 1 - -1 + 2 + +eval instant at 50m .2 + 0.2 + +eval instant at 50m +0.2 + 0.2 + +eval instant at 50m -0.2e-6 + -0.0000002 + +eval instant at 50m +Inf + +Inf + +eval instant at 50m inF + +Inf + +eval instant at 50m -inf + -Inf + +eval instant at 50m NaN + NaN + +eval instant at 50m nan + NaN + +eval instant at 50m 2. + 2 + +eval instant at 50m 1 / 0 + +Inf + +eval instant at 50m ((1) / (0)) + +Inf + +eval instant at 50m -1 / 0 + -Inf + +eval instant at 50m 0 / 0 + NaN + +eval instant at 50m 1 % 0 + NaN diff --git a/src/query/test/testdata/operators.test b/src/query/test/compatibility/testdata/operators.test similarity index 94% rename from src/query/test/testdata/operators.test rename to src/query/test/compatibility/testdata/operators.test index a0ecb8779e..a7c541af62 100644 --- a/src/query/test/testdata/operators.test +++ b/src/query/test/compatibility/testdata/operators.test @@ -22,7 +22,7 @@ eval instant at 50m 2 - SUM(http_requests) BY (job) {job="api-server"} -998 {job="app-server"} -2598 -# FAILING. eval instant at 50m -http_requests{job="api-server",instance="0",group="production"} +# FAILING issue #53. eval instant at 50m -http_requests{job="api-server",instance="0",group="production"} # {job="api-server",instance="0",group="production"} -100 eval instant at 50m +http_requests{job="api-server",instance="0",group="production"} @@ -32,14 +32,14 @@ eval instant at 50m - - - SUM(http_requests) BY (job) {job="api-server"} -1000 {job="app-server"} -2600 -# FAILING. eval instant at 50m - - - 1 -# -1 +eval instant at 50m - - - 1 + -1 # FAILING. eval instant at 50m -2^---1*3 # -1.5 # FAILING. eval instant at 50m 2/-2^---1*3+2 -# -10 +# -10 # FAILING. eval instant at 50m -10^3 * - SUM(http_requests) BY (job) ^ -1 # {job="api-server"} 1 @@ -115,7 +115,7 @@ eval instant at 50m rate(http_requests[25m]) * 25 * 60 {group="production", instance="1", job="api-server"} 100 {group="production", instance="1", job="app-server"} 300 -# FAILING issue #30. eval instant at 50m (rate((http_requests[25m])) * 25) * 60 +# FAILING issue #19. eval instant at 50m (rate((http_requests[25m])) * 25) * 60 # {group="canary", instance="0", job="api-server"} 150 # {group="canary", instance="0", job="app-server"} 350 # {group="canary", instance="1", job="api-server"} 200 @@ -126,7 +126,7 @@ eval instant at 50m rate(http_requests[25m]) * 25 * 60 # {group="production", instance="1", job="app-server"} 300 -# FAILING issue #23. eval instant at 50m http_requests{group="canary"} and http_requests{instance="0"} +# FAILING order of rows differs. eval instant at 50m http_requests{group="canary"} and http_requests{instance="0"} # http_requests{group="canary", instance="0", job="api-server"} 300 # http_requests{group="canary", instance="0", job="app-server"} 700 @@ -150,7 +150,7 @@ eval instant at 50m (http_requests{group="canary"} + 1) and ignoring(group, job) {group="canary", instance="0", job="api-server"} 301 {group="canary", instance="0", job="app-server"} 701 -# FAILING issue #23. eval instant at 50m http_requests{group="canary"} or http_requests{group="production"} +# FAILING order of rows differs. eval instant at 50m http_requests{group="canary"} or http_requests{group="production"} # http_requests{group="canary", instance="0", job="api-server"} 300 # http_requests{group="canary", instance="0", job="app-server"} 700 # http_requests{group="canary", instance="1", job="api-server"} 400 @@ -239,20 +239,20 @@ eval instant at 50m (http_requests{group="canary"} + 1) and ignoring(group, job) # Comparisons. -# FAILING issue #37. eval instant at 50m SUM(http_requests) BY (job) > 1000 -# {job="app-server"} 2600 +eval instant at 50m SUM(http_requests) BY (job) > 1000 + {job="app-server"} 2600 -# FAILING issue #37. eval instant at 50m 1000 < SUM(http_requests) BY (job) +# FAILING (returns lhs instead of rhs). eval instant at 50m 1000 < SUM(http_requests) BY (job) # {job="app-server"} 2600 -# FAILING issue #37. eval instant at 50m SUM(http_requests) BY (job) <= 1000 -# {job="api-server"} 1000 +eval instant at 50m SUM(http_requests) BY (job) <= 1000 + {job="api-server"} 1000 -# FAILING issue #37. eval instant at 50m SUM(http_requests) BY (job) != 1000 -# {job="app-server"} 2600 +eval instant at 50m SUM(http_requests) BY (job) != 1000 + {job="app-server"} 2600 -# FAILING issue #37. eval instant at 50m SUM(http_requests) BY (job) == 1000 -# {job="api-server"} 1000 +eval instant at 50m SUM(http_requests) BY (job) == 1000 + {job="api-server"} 1000 eval instant at 50m SUM(http_requests) BY (job) == bool 1000 {job="api-server"} 1 @@ -266,11 +266,11 @@ eval instant at 50m SUM(http_requests) BY (job) != bool SUM(http_requests) BY (j {job="api-server"} 0 {job="app-server"} 0 -# FAILING issue #31. eval instant at 50m 0 == bool 1 -# 0 +eval instant at 50m 0 == bool 1 + 0 -# FAILING issue #31. eval instant at 50m 1 == bool 1 -# 1 +eval instant at 50m 1 == bool 1 + 1 eval instant at 50m http_requests{job="api-server", instance="0", group="production"} == bool 100 {job="api-server", instance="0", group="production"} 1 @@ -420,7 +420,7 @@ load 5m metricB{baz="meh"} 4 # On with no labels, for metrics with no common labels. -# FAILING. eval instant at 5m random + on() metricA +# FAILING issue #36. eval instant at 5m random + on() metricA # {} 5 # Ignoring with no labels is the same as no ignoring. diff --git a/src/query/test/testdata/selectors.test b/src/query/test/compatibility/testdata/selectors.test similarity index 100% rename from src/query/test/testdata/selectors.test rename to src/query/test/compatibility/testdata/selectors.test diff --git a/src/query/test/testdata/staleness.test b/src/query/test/compatibility/testdata/staleness.test similarity index 100% rename from src/query/test/testdata/staleness.test rename to src/query/test/compatibility/testdata/staleness.test diff --git a/src/query/test/testdata/subquery.test b/src/query/test/compatibility/testdata/subquery.test similarity index 100% rename from src/query/test/testdata/subquery.test rename to src/query/test/compatibility/testdata/subquery.test diff --git a/src/query/test/testdata/literals.test b/src/query/test/testdata/literals.test deleted file mode 100644 index 344e2a808a..0000000000 --- a/src/query/test/testdata/literals.test +++ /dev/null @@ -1,61 +0,0 @@ -# FAILING issue #46 (we return vector resultType in place of scalar). - -# FAILING. eval instant at 50m 12.34e6 -# 12340000 - -# FAILING. eval instant at 50m 12.34e+6 -# 12340000 - -# FAILING. eval instant at 50m 12.34e-6 -# 0.00001234 - -# FAILING. eval instant at 50m 1+1 -# 2 - -# FAILING. eval instant at 50m 1-1 -# 0 - -# FAILING. eval instant at 50m 1 - -1 -# 2 - -# FAILING. eval instant at 50m .2 -# 0.2 - -# FAILING. eval instant at 50m +0.2 -# 0.2 - -# FAILING. eval instant at 50m -0.2e-6 -# -0.0000002 - -# FAILING. eval instant at 50m +Inf -# +Inf - -# FAILING. eval instant at 50m inF -# +Inf - -# FAILING. eval instant at 50m -inf -# -Inf - -# FAILING. eval instant at 50m NaN -# NaN - -# FAILING. eval instant at 50m nan -# NaN - -# FAILING. eval instant at 50m 2. -# 2 - -# FAILING. eval instant at 50m 1 / 0 -# +Inf - -# FAILING. eval instant at 50m ((1) / (0)) -# +Inf - -# FAILING. eval instant at 50m -1 / 0 -# -Inf - -# FAILING. eval instant at 50m 0 / 0 -# NaN - -# FAILING. eval instant at 50m 1 % 0 -# NaN