Migrate matrix tests, remove old test files.

This commit is contained in:
Fabian Reinartz 2015-05-12 13:41:57 +02:00
parent 71ef7ab405
commit 0d3012a605
6 changed files with 50 additions and 734 deletions

View file

@ -120,7 +120,7 @@ func (p *parser) parseExpr() (expr Expr, err error) {
return
}
// sequenceValue is a omittable value in a sequence of time series values.
// sequenceValue is an omittable value in a sequence of time series values.
type sequenceValue struct {
value clientmodel.SampleValue
omitted bool

View file

@ -1,4 +1,4 @@
// Copyright 2013 The Prometheus Authors
// Copyright 2015 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@ -14,341 +14,24 @@
package promql
import (
"fmt"
"math"
"regexp"
"strconv"
"strings"
"path/filepath"
"testing"
"time"
clientmodel "github.com/prometheus/client_golang/model"
"github.com/prometheus/prometheus/storage/local"
"github.com/prometheus/prometheus/storage/metric"
"github.com/prometheus/prometheus/utility/test"
)
var (
testEvalTime = testStartTime.Add(testSampleInterval * 10)
fixturesPath = "fixtures"
reSample = regexp.MustCompile(`^(.*)(?: \=\>|:) (\-?\d+\.?\d*(?:e-?\d+)?|[+-]Inf|NaN) \@\[(\d+)\]$`)
// minNormal = math.Float64frombits(0x0010000000000000) // The smallest positive normal value of type float64.
)
// const (
// epsilon = 0.000001 // Relative error allowed for sample values.
// )
func annotateWithTime(lines []string, timestamp clientmodel.Timestamp) []string {
annotatedLines := []string{}
for _, line := range lines {
annotatedLines = append(annotatedLines, fmt.Sprintf(line, timestamp))
}
return annotatedLines
}
func vectorComparisonString(expected []string, actual []string) string {
separator := "\n--------------\n"
return fmt.Sprintf("Expected:%v%v%v\nActual:%v%v%v ",
separator,
strings.Join(expected, "\n"),
separator,
separator,
strings.Join(actual, "\n"),
separator)
}
// samplesAlmostEqual returns true if the two sample lines only differ by a
// small relative error in their sample value.
func samplesAlmostEqual(a, b string) bool {
if a == b {
// Fast path if strings are equal.
return true
}
aMatches := reSample.FindStringSubmatch(a)
if aMatches == nil {
panic(fmt.Errorf("sample %q did not match regular expression", a))
}
bMatches := reSample.FindStringSubmatch(b)
if bMatches == nil {
panic(fmt.Errorf("sample %q did not match regular expression", b))
}
if aMatches[1] != bMatches[1] {
return false // Labels don't match.
}
if aMatches[3] != bMatches[3] {
return false // Timestamps don't match.
}
// If we are here, we have the diff in the floats.
// We have to check if they are almost equal.
aVal, err := strconv.ParseFloat(aMatches[2], 64)
func TestEvaluations(t *testing.T) {
files, err := filepath.Glob("testdata/*.test")
if err != nil {
panic(err)
t.Fatal(err)
}
bVal, err := strconv.ParseFloat(bMatches[2], 64)
if err != nil {
panic(err)
}
// Cf. http://floating-point-gui.de/errors/comparison/
if aVal == bVal {
return true
}
diff := math.Abs(aVal - bVal)
if aVal == 0 || bVal == 0 || diff < minNormal {
return diff < epsilon*minNormal
}
return diff/(math.Abs(aVal)+math.Abs(bVal)) < epsilon
}
func newTestStorage(t testing.TB) (storage local.Storage, closer test.Closer) {
storage, closer = local.NewTestStorage(t, 1)
storeMatrix(storage, testMatrix)
return storage, closer
}
func TestRangedEvaluationRegressions(t *testing.T) {
scenarios := []struct {
in Matrix
out Matrix
expr string
}{
{
// Testing COWMetric behavior in drop_common_labels.
in: Matrix{
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"testlabel": "1",
},
},
Values: metric.Values{
{
Timestamp: testStartTime,
Value: 1,
},
{
Timestamp: testStartTime.Add(time.Hour),
Value: 1,
},
},
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"testlabel": "2",
},
},
Values: metric.Values{
{
Timestamp: testStartTime.Add(time.Hour),
Value: 2,
},
},
},
},
out: Matrix{
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
},
},
Values: metric.Values{
{
Timestamp: testStartTime,
Value: 1,
},
},
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"testlabel": "1",
},
},
Values: metric.Values{
{
Timestamp: testStartTime.Add(time.Hour),
Value: 1,
},
},
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"testlabel": "2",
},
},
Values: metric.Values{
{
Timestamp: testStartTime.Add(time.Hour),
Value: 2,
},
},
},
},
expr: "drop_common_labels(testmetric)",
},
{
// Testing COWMetric behavior in vector aggregation.
in: Matrix{
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"testlabel": "1",
},
},
Values: metric.Values{
{
Timestamp: testStartTime,
Value: 1,
},
{
Timestamp: testStartTime.Add(time.Hour),
Value: 1,
},
},
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"testlabel": "2",
},
},
Values: metric.Values{
{
Timestamp: testStartTime,
Value: 2,
},
},
},
},
out: Matrix{
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{},
},
Values: metric.Values{
{
Timestamp: testStartTime,
Value: 3,
},
},
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
"testlabel": "1",
},
},
Values: metric.Values{
{
Timestamp: testStartTime.Add(time.Hour),
Value: 1,
},
},
},
},
expr: "sum(testmetric) keeping_extra",
},
{
// Testing metric fingerprint grouping behavior.
in: Matrix{
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"aa": "bb",
},
},
Values: metric.Values{
{
Timestamp: testStartTime,
Value: 1,
},
},
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"a": "abb",
},
},
Values: metric.Values{
{
Timestamp: testStartTime,
Value: 2,
},
},
},
},
out: Matrix{
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"aa": "bb",
},
},
Values: metric.Values{
{
Timestamp: testStartTime,
Value: 1,
},
},
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testmetric",
"a": "abb",
},
},
Values: metric.Values{
{
Timestamp: testStartTime,
Value: 2,
},
},
},
},
expr: "testmetric",
},
}
for i, s := range scenarios {
storage, closer := local.NewTestStorage(t, 1)
storeMatrix(storage, s.in)
engine := NewEngine(storage)
query, err := engine.NewRangeQuery(s.expr, testStartTime, testStartTime.Add(time.Hour), time.Hour)
for _, fn := range files {
test, err := NewTestFromFile(t, fn)
if err != nil {
t.Errorf("%d. Error in expression %q", i, s.expr)
t.Fatalf("%d. Error parsing expression: %v", i, err)
t.Errorf("error creating test for %s: %s", fn, err)
}
res := query.Exec()
if res.Err != nil {
t.Errorf("%d. Error in expression %q", i, s.expr)
t.Fatalf("%d. Error evaluating expression: %v", i, err)
err = test.Run()
if err != nil {
t.Errorf("error running test %s: %s", fn, err)
}
if res.String() != s.out.String() {
t.Errorf("%d. Error in expression %q", i, s.expr)
t.Fatalf("%d. Expression: %s\n\ngot:\n=====\n%v\n====\n\nwant:\n=====\n%v\n=====\n", i, s.expr, res.String(), s.out.String())
}
closer.Close()
test.Close()
}
}

View file

@ -1,402 +0,0 @@
// Copyright 2013 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package promql
import (
"time"
clientmodel "github.com/prometheus/client_golang/model"
"github.com/prometheus/prometheus/storage/local"
"github.com/prometheus/prometheus/storage/metric"
)
var testSampleInterval = time.Duration(5) * time.Minute
// var testStartTime = clientmodel.Timestamp(0)
func getTestValueStream(startVal, endVal, stepVal clientmodel.SampleValue, startTime clientmodel.Timestamp) (resultValues metric.Values) {
currentTime := startTime
for currentVal := startVal; currentVal <= endVal; currentVal += stepVal {
sample := metric.SamplePair{
Value: currentVal,
Timestamp: currentTime,
}
resultValues = append(resultValues, sample)
currentTime = currentTime.Add(testSampleInterval)
}
return resultValues
}
func getTestVectorFromTestMatrix(matrix Matrix) Vector {
vector := Vector{}
for _, sampleStream := range matrix {
lastSample := sampleStream.Values[len(sampleStream.Values)-1]
vector = append(vector, &Sample{
Metric: sampleStream.Metric,
Value: lastSample.Value,
Timestamp: lastSample.Timestamp,
})
}
return vector
}
func storeMatrix(storage local.Storage, matrix Matrix) {
pendingSamples := clientmodel.Samples{}
for _, sampleStream := range matrix {
for _, sample := range sampleStream.Values {
pendingSamples = append(pendingSamples, &clientmodel.Sample{
Metric: sampleStream.Metric.Metric,
Value: sample.Value,
Timestamp: sample.Timestamp,
})
}
}
for _, s := range pendingSamples {
storage.Append(s)
}
storage.WaitForIndexing()
}
var testVector = getTestVectorFromTestMatrix(testMatrix)
var testMatrix = Matrix{
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "http_requests",
clientmodel.JobLabel: "api-server",
"instance": "0",
"group": "production",
},
},
Values: getTestValueStream(0, 100, 10, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "http_requests",
clientmodel.JobLabel: "api-server",
"instance": "1",
"group": "production",
},
},
Values: getTestValueStream(0, 200, 20, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "http_requests",
clientmodel.JobLabel: "api-server",
"instance": "0",
"group": "canary",
},
},
Values: getTestValueStream(0, 300, 30, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "http_requests",
clientmodel.JobLabel: "api-server",
"instance": "1",
"group": "canary",
},
},
Values: getTestValueStream(0, 400, 40, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "http_requests",
clientmodel.JobLabel: "app-server",
"instance": "0",
"group": "production",
},
},
Values: getTestValueStream(0, 500, 50, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "http_requests",
clientmodel.JobLabel: "app-server",
"instance": "1",
"group": "production",
},
},
Values: getTestValueStream(0, 600, 60, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "http_requests",
clientmodel.JobLabel: "app-server",
"instance": "0",
"group": "canary",
},
},
Values: getTestValueStream(0, 700, 70, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "http_requests",
clientmodel.JobLabel: "app-server",
"instance": "1",
"group": "canary",
},
},
Values: getTestValueStream(0, 800, 80, testStartTime),
},
// Single-letter metric and label names.
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "x",
"y": "testvalue",
},
},
Values: getTestValueStream(0, 100, 10, testStartTime),
},
// Counter reset in the middle of range.
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testcounter_reset_middle",
},
},
Values: append(getTestValueStream(0, 40, 10, testStartTime), getTestValueStream(0, 50, 10, testStartTime.Add(testSampleInterval*5))...),
},
// Counter reset at the end of range.
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "testcounter_reset_end",
},
},
Values: append(getTestValueStream(0, 90, 10, testStartTime), getTestValueStream(0, 0, 10, testStartTime.Add(testSampleInterval*10))...),
},
// For label-key grouping regression test.
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "label_grouping_test",
"a": "aa",
"b": "bb",
},
},
Values: getTestValueStream(0, 100, 10, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "label_grouping_test",
"a": "a",
"b": "abb",
},
},
Values: getTestValueStream(0, 200, 20, testStartTime),
},
// Now a more realistic histogram per job and instance to test aggregation.
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job1",
"instance": "ins1",
"le": "0.1",
},
},
Values: getTestValueStream(0, 10, 1, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job1",
"instance": "ins1",
"le": "0.2",
},
},
Values: getTestValueStream(0, 30, 3, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job1",
"instance": "ins1",
"le": "+Inf",
},
},
Values: getTestValueStream(0, 40, 4, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job1",
"instance": "ins2",
"le": "0.1",
},
},
Values: getTestValueStream(0, 20, 2, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job1",
"instance": "ins2",
"le": "0.2",
},
},
Values: getTestValueStream(0, 50, 5, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job1",
"instance": "ins2",
"le": "+Inf",
},
},
Values: getTestValueStream(0, 60, 6, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job2",
"instance": "ins1",
"le": "0.1",
},
},
Values: getTestValueStream(0, 30, 3, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job2",
"instance": "ins1",
"le": "0.2",
},
},
Values: getTestValueStream(0, 40, 4, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job2",
"instance": "ins1",
"le": "+Inf",
},
},
Values: getTestValueStream(0, 60, 6, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job2",
"instance": "ins2",
"le": "0.1",
},
},
Values: getTestValueStream(0, 40, 4, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job2",
"instance": "ins2",
"le": "0.2",
},
},
Values: getTestValueStream(0, 70, 7, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "request_duration_seconds_bucket",
clientmodel.JobLabel: "job2",
"instance": "ins2",
"le": "+Inf",
},
},
Values: getTestValueStream(0, 90, 9, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "vector_matching_a",
"l": "x",
},
},
Values: getTestValueStream(0, 100, 1, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "vector_matching_a",
"l": "y",
},
},
Values: getTestValueStream(0, 100, 2, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "vector_matching_b",
"l": "x",
},
},
Values: getTestValueStream(0, 100, 4, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "cpu_count",
"instance": "0",
"type": "numa",
},
},
Values: getTestValueStream(0, 500, 30, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "cpu_count",
"instance": "0",
"type": "smp",
},
},
Values: getTestValueStream(0, 200, 10, testStartTime),
},
{
Metric: clientmodel.COWMetric{
Metric: clientmodel.Metric{
clientmodel.MetricNameLabel: "cpu_count",
"instance": "1",
"type": "smp",
},
},
Values: getTestValueStream(0, 200, 20, testStartTime),
},
}

View file

@ -138,4 +138,4 @@ eval instant at 50m histogram_quantile(0.5, rate(request_duration_seconds_bucket
{instance="ins1", job="job1"} 0.15
{instance="ins2", job="job1"} 0.13333333333333333
{instance="ins1", job="job2"} 0.1
{instance="ins2", job="job2"} 0.11666666666666667
{instance="ins2", job="job2"} 0.11666666666666667

View file

@ -636,3 +636,38 @@ eval instant at 50m stdvar(http_requests)
eval instant at 50m stdvar by (instance)(http_requests)
{instance="0"} 50000
{instance="1"} 50000
# Matrix tests.
clear
load 1h
testmetric{testlabel="1"} 1 1
testmetric{testlabel="2"} _ 2
eval instant at 0h drop_common_labels(testmetric)
testmetric 1
eval instant at 1h drop_common_labels(testmetric)
testmetric{testlabel="1"} 1
testmetric{testlabel="2"} 2
clear
load 1h
testmetric{testlabel="1"} 1 1
testmetric{testlabel="2"} 2 _
eval instant at 0h sum(testmetric) keeping_extra
{} 3
eval instant at 1h sum(testmetric) keeping_extra
{testlabel="1"} 1
clear
load 1h
testmetric{aa="bb"} 1
testmetric{a="abb"} 2
eval instant at 0h testmetric
testmetric{aa="bb"} 1
testmetric{a="abb"} 2

View file

@ -53,4 +53,4 @@ eval instant at 50m 0 / 0
NaN
eval instant at 50m 1 % 0
NaN
NaN