Merge pull request #13452 from bboreham/go-cmp

Tests: Use DeepEqual replacement using go-cmp, which is more flexible
This commit is contained in:
Bryan Boreham 2024-02-12 15:40:08 +01:00 committed by GitHub
commit ff6c83269c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 169 additions and 96 deletions

View file

@ -26,6 +26,7 @@ import (
"github.com/prometheus/prometheus/storage"
"github.com/prometheus/prometheus/tsdb"
"github.com/prometheus/prometheus/tsdb/chunkenc"
"github.com/prometheus/prometheus/util/testutil"
)
type backfillSample struct {
@ -76,7 +77,7 @@ func testBlocks(t *testing.T, db *tsdb.DB, expectedMinTime, expectedMaxTime, exp
allSamples := queryAllSeries(t, q, expectedMinTime, expectedMaxTime)
sortSamples(allSamples)
sortSamples(expectedSamples)
require.Equal(t, expectedSamples, allSamples, "did not create correct samples")
testutil.RequireEqual(t, expectedSamples, allSamples, "did not create correct samples")
if len(allSamples) > 0 {
require.Equal(t, expectedMinTime, allSamples[0].Timestamp, "timestamp of first sample is not the expected minimum time")

View file

@ -18,10 +18,10 @@ import (
"encoding/json"
"fmt"
"os"
"reflect"
"time"
"github.com/go-kit/log"
"github.com/google/go-cmp/cmp"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/prometheus/config"
@ -153,7 +153,7 @@ func getSDCheckResult(targetGroups []*targetgroup.Group, scrapeConfig *config.Sc
duplicateRes := false
for _, sdCheckRes := range sdCheckResults {
if reflect.DeepEqual(sdCheckRes, result) {
if cmp.Equal(sdCheckRes, result, cmp.Comparer(labels.Equal)) {
duplicateRes = true
break
}

View file

@ -23,6 +23,7 @@ import (
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/relabel"
"github.com/prometheus/prometheus/util/testutil"
"github.com/stretchr/testify/require"
)
@ -69,5 +70,5 @@ func TestSDCheckResult(t *testing.T) {
},
}
require.Equal(t, expectedSDCheckResult, getSDCheckResult(targetGroups, scrapeConfig, true))
testutil.RequireEqual(t, expectedSDCheckResult, getSDCheckResult(targetGroups, scrapeConfig, true))
}

View file

@ -20,13 +20,13 @@ import (
"fmt"
"os"
"path/filepath"
"reflect"
"sort"
"strconv"
"strings"
"time"
"github.com/go-kit/log"
"github.com/google/go-cmp/cmp"
"github.com/grafana/regexp"
"github.com/nsf/jsondiff"
"github.com/prometheus/common/model"
@ -340,7 +340,7 @@ func (tg *testGroup) test(evalInterval time.Duration, groupOrderMap map[string]i
sort.Sort(gotAlerts)
sort.Sort(expAlerts)
if !reflect.DeepEqual(expAlerts, gotAlerts) {
if !cmp.Equal(expAlerts, gotAlerts, cmp.Comparer(labels.Equal)) {
var testName string
if tg.TestGroupName != "" {
testName = fmt.Sprintf(" name: %s,\n", tg.TestGroupName)
@ -448,7 +448,7 @@ Outer:
sort.Slice(gotSamples, func(i, j int) bool {
return labels.Compare(gotSamples[i].Labels, gotSamples[j].Labels) <= 0
})
if !reflect.DeepEqual(expSamples, gotSamples) {
if !cmp.Equal(expSamples, gotSamples, cmp.Comparer(labels.Equal)) {
errs = append(errs, fmt.Errorf(" expr: %q, time: %s,\n exp: %v\n got: %v", testCase.Expr,
testCase.EvalTime.String(), parsedSamplesString(expSamples), parsedSamplesString(gotSamples)))
}

View file

@ -58,6 +58,7 @@ import (
"github.com/prometheus/prometheus/discovery/zookeeper"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/relabel"
"github.com/prometheus/prometheus/util/testutil"
)
func mustParseURL(u string) *config.URL {
@ -2037,16 +2038,16 @@ func TestExpandExternalLabels(t *testing.T) {
c, err := LoadFile("testdata/external_labels.good.yml", false, false, log.NewNopLogger())
require.NoError(t, err)
require.Equal(t, labels.FromStrings("bar", "foo", "baz", "foo${TEST}bar", "foo", "${TEST}", "qux", "foo$${TEST}", "xyz", "foo$$bar"), c.GlobalConfig.ExternalLabels)
testutil.RequireEqual(t, labels.FromStrings("bar", "foo", "baz", "foo${TEST}bar", "foo", "${TEST}", "qux", "foo$${TEST}", "xyz", "foo$$bar"), c.GlobalConfig.ExternalLabels)
c, err = LoadFile("testdata/external_labels.good.yml", false, true, log.NewNopLogger())
require.NoError(t, err)
require.Equal(t, labels.FromStrings("bar", "foo", "baz", "foobar", "foo", "", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
testutil.RequireEqual(t, labels.FromStrings("bar", "foo", "baz", "foobar", "foo", "", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
os.Setenv("TEST", "TestValue")
c, err = LoadFile("testdata/external_labels.good.yml", false, true, log.NewNopLogger())
require.NoError(t, err)
require.Equal(t, labels.FromStrings("bar", "foo", "baz", "fooTestValuebar", "foo", "TestValue", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
testutil.RequireEqual(t, labels.FromStrings("bar", "foo", "baz", "fooTestValuebar", "foo", "TestValue", "qux", "foo${TEST}", "xyz", "foo$bar"), c.GlobalConfig.ExternalLabels)
}
func TestAgentMode(t *testing.T) {

2
go.mod
View file

@ -28,6 +28,7 @@ require (
github.com/go-zookeeper/zk v1.0.3
github.com/gogo/protobuf v1.3.2
github.com/golang/snappy v0.0.4
github.com/google/go-cmp v0.6.0
github.com/google/pprof v0.0.0-20240117000934-35fc243c5815
github.com/google/uuid v1.5.0
github.com/gophercloud/gophercloud v1.8.0
@ -135,7 +136,6 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/s2a-go v0.1.7 // indirect

View file

@ -22,6 +22,7 @@ import (
"gopkg.in/yaml.v2"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/util/testutil"
)
func TestRelabel(t *testing.T) {
@ -591,7 +592,7 @@ func TestRelabel(t *testing.T) {
res, keep := Process(test.input, test.relabel...)
require.Equal(t, !test.drop, keep)
if keep {
require.Equal(t, test.output, res)
testutil.RequireEqual(t, test.output, res)
}
}
}

View file

@ -23,6 +23,7 @@ import (
"github.com/prometheus/prometheus/model/exemplar"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/util/testutil"
)
func TestOpenMetricsParse(t *testing.T) {
@ -268,12 +269,12 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
require.Equal(t, exp[i].m, string(m))
require.Equal(t, exp[i].t, ts)
require.Equal(t, exp[i].v, v)
require.Equal(t, exp[i].lset, res)
testutil.RequireEqual(t, exp[i].lset, res)
if exp[i].e == nil {
require.False(t, found)
} else {
require.True(t, found)
require.Equal(t, *exp[i].e, e)
testutil.RequireEqual(t, *exp[i].e, e)
}
case EntryType:

View file

@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/util/testutil"
)
func TestPromParse(t *testing.T) {
@ -191,7 +192,7 @@ testmetric{label="\"bar\""} 1`
require.Equal(t, exp[i].m, string(m))
require.Equal(t, exp[i].t, ts)
require.Equal(t, exp[i].v, v)
require.Equal(t, exp[i].lset, res)
testutil.RequireEqual(t, exp[i].lset, res)
case EntryType:
m, typ := p.Type()

View file

@ -27,6 +27,7 @@ import (
"github.com/prometheus/prometheus/model/exemplar"
"github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/util/testutil"
dto "github.com/prometheus/prometheus/prompb/io/prometheus/client"
)
@ -1993,12 +1994,12 @@ func TestProtobufParse(t *testing.T) {
require.Equal(t, int64(0), exp[i].t, "i: %d", i)
}
require.Equal(t, exp[i].v, v, "i: %d", i)
require.Equal(t, exp[i].lset, res, "i: %d", i)
testutil.RequireEqual(t, exp[i].lset, res, "i: %d", i)
if len(exp[i].e) == 0 {
require.False(t, eFound, "i: %d", i)
} else {
require.True(t, eFound, "i: %d", i)
require.Equal(t, exp[i].e[0], e, "i: %d", i)
testutil.RequireEqual(t, exp[i].e[0], e, "i: %d", i)
require.False(t, p.Exemplar(&e), "too many exemplars returned, i: %d", i)
}
if exp[i].ct != 0 {
@ -2017,7 +2018,7 @@ func TestProtobufParse(t *testing.T) {
} else {
require.Equal(t, int64(0), exp[i].t, "i: %d", i)
}
require.Equal(t, exp[i].lset, res, "i: %d", i)
testutil.RequireEqual(t, exp[i].lset, res, "i: %d", i)
require.Equal(t, exp[i].m, string(m), "i: %d", i)
if shs != nil {
require.Equal(t, exp[i].shs, shs, "i: %d", i)
@ -2026,7 +2027,7 @@ func TestProtobufParse(t *testing.T) {
}
j := 0
for e := (exemplar.Exemplar{}); p.Exemplar(&e); j++ {
require.Equal(t, exp[i].e[j], e, "i: %d", i)
testutil.RequireEqual(t, exp[i].e[j], e, "i: %d", i)
e = exemplar.Exemplar{}
}
require.Len(t, exp[i].e, j, "not enough exemplars found, i: %d", i)

View file

@ -38,6 +38,7 @@ import (
"github.com/prometheus/prometheus/util/annotations"
"github.com/prometheus/prometheus/util/stats"
"github.com/prometheus/prometheus/util/teststorage"
"github.com/prometheus/prometheus/util/testutil"
)
func TestMain(m *testing.M) {
@ -1631,7 +1632,7 @@ load 1ms
sort.Sort(expMat)
sort.Sort(res.Value.(Matrix))
}
require.Equal(t, c.result, res.Value, "query %q failed", c.query)
testutil.RequireEqual(t, c.result, res.Value, "query %q failed", c.query)
})
}
}
@ -1956,7 +1957,7 @@ func TestSubquerySelector(t *testing.T) {
require.Equal(t, c.Result.Err, res.Err)
mat := res.Value.(Matrix)
sort.Sort(mat)
require.Equal(t, c.Result.Value, mat)
testutil.RequireEqual(t, c.Result.Value, mat)
})
}
})
@ -2001,7 +2002,7 @@ load 1m
res := qry.Exec(context.Background())
require.NoError(t, res.Err)
require.Equal(t, expectedResult, res.Value)
testutil.RequireEqual(t, expectedResult, res.Value)
}
type FakeQueryLogger struct {
@ -3147,7 +3148,7 @@ func TestRangeQuery(t *testing.T) {
res := qry.Exec(context.Background())
require.NoError(t, res.Err)
require.Equal(t, c.Result, res.Value)
testutil.RequireEqual(t, c.Result, res.Value)
})
}
}
@ -4347,7 +4348,7 @@ func TestNativeHistogram_Sum_Count_Add_AvgOperator(t *testing.T) {
vector, err := res.Vector()
require.NoError(t, err)
require.Equal(t, exp, vector)
testutil.RequireEqual(t, exp, vector)
}
// sum().
@ -4605,7 +4606,7 @@ func TestNativeHistogram_SubOperator(t *testing.T) {
}
}
require.Equal(t, exp, vector)
testutil.RequireEqual(t, exp, vector)
}
// - operator.
@ -4753,7 +4754,7 @@ func TestNativeHistogram_MulDivOperator(t *testing.T) {
vector, err := res.Vector()
require.NoError(t, err)
require.Equal(t, exp, vector)
testutil.RequireEqual(t, exp, vector)
}
// histogram * scalar.

View file

@ -26,6 +26,7 @@ import (
"github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/util/testutil"
"github.com/prometheus/prometheus/promql/parser/posrange"
)
@ -4018,7 +4019,7 @@ func TestParseSeries(t *testing.T) {
if !test.fail {
require.NoError(t, err)
require.Equal(t, test.expectedMetric, metric, "error on input '%s'", test.input)
testutil.RequireEqual(t, test.expectedMetric, metric, "error on input '%s'", test.input)
require.Equal(t, test.expectedValues, vals, "error in input '%s'", test.input)
} else {
require.Error(t, err)

View file

@ -31,6 +31,7 @@ import (
"github.com/prometheus/prometheus/promql/parser"
"github.com/prometheus/prometheus/storage"
"github.com/prometheus/prometheus/util/teststorage"
"github.com/prometheus/prometheus/util/testutil"
)
var testEngine = promql.NewEngine(promql.EngineOpts{
@ -180,7 +181,7 @@ func TestAlertingRuleLabelsUpdate(t *testing.T) {
}
}
require.Equal(t, result, filteredRes)
testutil.RequireEqual(t, result, filteredRes)
}
evalTime := baseTime.Add(time.Duration(len(results)) * time.Minute)
res, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0)
@ -278,7 +279,7 @@ func TestAlertingRuleExternalLabelsInTemplate(t *testing.T) {
}
}
require.Equal(t, result, filteredRes)
testutil.RequireEqual(t, result, filteredRes)
}
func TestAlertingRuleExternalURLInTemplate(t *testing.T) {
@ -371,7 +372,7 @@ func TestAlertingRuleExternalURLInTemplate(t *testing.T) {
}
}
require.Equal(t, result, filteredRes)
testutil.RequireEqual(t, result, filteredRes)
}
func TestAlertingRuleEmptyLabelFromTemplate(t *testing.T) {
@ -425,7 +426,7 @@ func TestAlertingRuleEmptyLabelFromTemplate(t *testing.T) {
require.Equal(t, "ALERTS_FOR_STATE", smplName)
}
}
require.Equal(t, result, filteredRes)
testutil.RequireEqual(t, result, filteredRes)
}
func TestAlertingRuleQueryInTemplate(t *testing.T) {
@ -718,7 +719,7 @@ func TestSendAlertsDontAffectActiveAlerts(t *testing.T) {
// The relabel rule changes a1=1 to a1=bug.
// But the labels with the AlertingRule should not be changed.
require.Equal(t, labels.FromStrings("a1", "1"), rule.active[h].Labels)
testutil.RequireEqual(t, labels.FromStrings("a1", "1"), rule.active[h].Labels)
}
func TestKeepFiringFor(t *testing.T) {
@ -823,7 +824,7 @@ func TestKeepFiringFor(t *testing.T) {
}
}
require.Equal(t, result, filteredRes)
testutil.RequireEqual(t, result, filteredRes)
}
evalTime := baseTime.Add(time.Duration(len(results)) * time.Minute)
res, err := rule.Eval(context.TODO(), evalTime, EngineQueryFunc(testEngine, storage), nil, 0)
@ -870,7 +871,7 @@ func TestPendingAndKeepFiringFor(t *testing.T) {
for _, smpl := range res {
smplName := smpl.Metric.Get("__name__")
if smplName == "ALERTS" {
require.Equal(t, result, smpl)
testutil.RequireEqual(t, result, smpl)
} else {
// If not 'ALERTS', it has to be 'ALERTS_FOR_STATE'.
require.Equal(t, "ALERTS_FOR_STATE", smplName)

View file

@ -42,6 +42,7 @@ import (
"github.com/prometheus/prometheus/tsdb/chunkenc"
"github.com/prometheus/prometheus/tsdb/tsdbutil"
"github.com/prometheus/prometheus/util/teststorage"
prom_testutil "github.com/prometheus/prometheus/util/testutil"
)
func TestMain(m *testing.M) {
@ -180,7 +181,7 @@ func TestAlertingRule(t *testing.T) {
sort.Slice(filteredRes, func(i, j int) bool {
return labels.Compare(filteredRes[i].Metric, filteredRes[j].Metric) < 0
})
require.Equal(t, test.result, filteredRes)
prom_testutil.RequireEqual(t, test.result, filteredRes)
for _, aa := range rule.ActiveAlerts() {
require.Zero(t, aa.Labels.Get(model.MetricNameLabel), "%s label set on active alert: %s", model.MetricNameLabel, aa.Labels)
@ -330,7 +331,7 @@ func TestForStateAddSamples(t *testing.T) {
sort.Slice(filteredRes, func(i, j int) bool {
return labels.Compare(filteredRes[i].Metric, filteredRes[j].Metric) < 0
})
require.Equal(t, test.result, filteredRes)
prom_testutil.RequireEqual(t, test.result, filteredRes)
for _, aa := range rule.ActiveAlerts() {
require.Zero(t, aa.Labels.Get(model.MetricNameLabel), "%s label set on active alert: %s", model.MetricNameLabel, aa.Labels)

View file

@ -25,6 +25,7 @@ import (
"github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/promql/parser"
"github.com/prometheus/prometheus/util/teststorage"
"github.com/prometheus/prometheus/util/testutil"
)
var (
@ -126,7 +127,7 @@ func TestRuleEval(t *testing.T) {
rule := NewRecordingRule("test_rule", scenario.expr, scenario.ruleLabels)
result, err := rule.Eval(context.TODO(), ruleEvaluationTime, EngineQueryFunc(testEngine, storage), nil, 0)
require.NoError(t, err)
require.Equal(t, scenario.expected, result)
testutil.RequireEqual(t, scenario.expected, result)
})
}
}

View file

@ -18,6 +18,7 @@ import (
"context"
"encoding/binary"
"fmt"
"math"
"math/rand"
"strings"
"sync"
@ -71,6 +72,11 @@ type floatSample struct {
f float64
}
func equalFloatSamples(a, b floatSample) bool {
// Compare Float64bits so NaN values which are exactly the same will compare equal.
return labels.Equal(a.metric, b.metric) && a.t == b.t && math.Float64bits(a.f) == math.Float64bits(b.f)
}
type histogramSample struct {
t int64
h *histogram.Histogram

View file

@ -40,6 +40,7 @@ import (
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/relabel"
"github.com/prometheus/prometheus/util/runutil"
"github.com/prometheus/prometheus/util/testutil"
)
func TestPopulateLabels(t *testing.T) {
@ -449,8 +450,8 @@ func TestPopulateLabels(t *testing.T) {
require.NoError(t, err)
}
require.Equal(t, c.in, in)
require.Equal(t, c.res, res)
require.Equal(t, c.resOrig, orig)
testutil.RequireEqual(t, c.res, res)
testutil.RequireEqual(t, c.resOrig, orig)
}
}

View file

@ -32,6 +32,7 @@ import (
"github.com/go-kit/log"
"github.com/gogo/protobuf/proto"
"github.com/google/go-cmp/cmp"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
config_util "github.com/prometheus/common/config"
@ -1341,7 +1342,7 @@ func TestScrapeLoopAppend(t *testing.T) {
scrapeLabels: `metric NaN`,
discoveryLabels: nil,
expLset: labels.FromStrings("__name__", "metric"),
expValue: float64(value.NormalNaN),
expValue: math.Float64frombits(value.NormalNaN),
},
}
@ -1375,18 +1376,17 @@ func TestScrapeLoopAppend(t *testing.T) {
},
}
// When the expected value is NaN
// DeepEqual will report NaNs as being different,
// so replace it with the expected one.
if test.expValue == float64(value.NormalNaN) {
app.resultFloats[0].f = expected[0].f
}
t.Logf("Test:%s", test.title)
require.Equal(t, expected, app.resultFloats)
requireEqual(t, expected, app.resultFloats)
}
}
func requireEqual(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) {
testutil.RequireEqualWithOptions(t, expected, actual,
[]cmp.Option{cmp.Comparer(equalFloatSamples), cmp.AllowUnexported(histogramSample{})},
msgAndArgs...)
}
func TestScrapeLoopAppendForConflictingPrefixedLabels(t *testing.T) {
testcases := map[string]struct {
targetLabels []string
@ -1450,7 +1450,7 @@ func TestScrapeLoopAppendForConflictingPrefixedLabels(t *testing.T) {
require.NoError(t, slApp.Commit())
require.Equal(t, []floatSample{
requireEqual(t, []floatSample{
{
metric: labels.FromStrings(tc.expected...),
t: timestamp.FromTime(time.Date(2000, 1, 1, 1, 0, 0, 0, time.UTC)),
@ -1544,7 +1544,7 @@ func TestScrapeLoopAppendSampleLimit(t *testing.T) {
f: 1,
},
}
require.Equal(t, want, resApp.rolledbackFloats, "Appended samples not as expected:\n%s", appender)
requireEqual(t, want, resApp.rolledbackFloats, "Appended samples not as expected:\n%s", appender)
now = time.Now()
slApp = sl.appender(context.Background())
@ -1684,7 +1684,6 @@ func TestScrapeLoop_ChangingMetricString(t *testing.T) {
require.NoError(t, err)
require.NoError(t, slApp.Commit())
// DeepEqual will report NaNs as being different, so replace with a different value.
want := []floatSample{
{
metric: labels.FromStrings("__name__", "metric_a", "a", "1", "b", "1"),
@ -1716,11 +1715,6 @@ func TestScrapeLoopAppendStaleness(t *testing.T) {
require.NoError(t, err)
require.NoError(t, slApp.Commit())
ingestedNaN := math.Float64bits(app.resultFloats[1].f)
require.Equal(t, value.StaleNaN, ingestedNaN, "Appended stale sample wasn't as expected")
// DeepEqual will report NaNs as being different, so replace with a different value.
app.resultFloats[1].f = 42
want := []floatSample{
{
metric: labels.FromStrings(model.MetricNameLabel, "metric_a"),
@ -1730,10 +1724,10 @@ func TestScrapeLoopAppendStaleness(t *testing.T) {
{
metric: labels.FromStrings(model.MetricNameLabel, "metric_a"),
t: timestamp.FromTime(now.Add(time.Second)),
f: 42,
f: math.Float64frombits(value.StaleNaN),
},
}
require.Equal(t, want, app.resultFloats, "Appended samples not as expected:\n%s", appender)
requireEqual(t, want, app.resultFloats, "Appended samples not as expected:\n%s", appender)
}
func TestScrapeLoopAppendNoStalenessIfTimestamp(t *testing.T) {
@ -1776,8 +1770,6 @@ func TestScrapeLoopAppendStalenessIfTrackTimestampStaleness(t *testing.T) {
require.NoError(t, err)
require.NoError(t, slApp.Commit())
// DeepEqual will report NaNs as being different, so replace with a different value.
app.resultFloats[1].f = 42
want := []floatSample{
{
metric: labels.FromStrings(model.MetricNameLabel, "metric_a"),
@ -1787,10 +1779,10 @@ func TestScrapeLoopAppendStalenessIfTrackTimestampStaleness(t *testing.T) {
{
metric: labels.FromStrings(model.MetricNameLabel, "metric_a"),
t: timestamp.FromTime(now.Add(time.Second)),
f: 42,
f: math.Float64frombits(value.StaleNaN),
},
}
require.Equal(t, want, app.resultFloats, "Appended samples not as expected:\n%s", appender)
requireEqual(t, want, app.resultFloats, "Appended samples not as expected:\n%s", appender)
}
func TestScrapeLoopAppendExemplar(t *testing.T) {
@ -2158,9 +2150,9 @@ metric: <
_, _, _, err := sl.append(app, buf.Bytes(), test.contentType, now)
require.NoError(t, err)
require.NoError(t, app.Commit())
require.Equal(t, test.floats, app.resultFloats)
require.Equal(t, test.histograms, app.resultHistograms)
require.Equal(t, test.exemplars, app.resultExemplars)
requireEqual(t, test.floats, app.resultFloats)
requireEqual(t, test.histograms, app.resultHistograms)
requireEqual(t, test.exemplars, app.resultExemplars)
})
}
}
@ -2215,8 +2207,8 @@ func TestScrapeLoopAppendExemplarSeries(t *testing.T) {
require.NoError(t, app.Commit())
}
require.Equal(t, samples, app.resultFloats)
require.Equal(t, exemplars, app.resultExemplars)
requireEqual(t, samples, app.resultFloats)
requireEqual(t, exemplars, app.resultExemplars)
}
func TestScrapeLoopRunReportsTargetDownOnScrapeError(t *testing.T) {
@ -2292,7 +2284,7 @@ func TestScrapeLoopAppendGracefullyIfAmendOrOutOfOrderOrOutOfBounds(t *testing.T
f: 1,
},
}
require.Equal(t, want, app.resultFloats, "Appended samples not as expected:\n%s", appender)
requireEqual(t, want, app.resultFloats, "Appended samples not as expected:\n%s", appender)
require.Equal(t, 4, total)
require.Equal(t, 4, added)
require.Equal(t, 1, seriesAdded)

View file

@ -44,6 +44,7 @@ import (
"github.com/prometheus/prometheus/scrape"
"github.com/prometheus/prometheus/tsdb/chunks"
"github.com/prometheus/prometheus/tsdb/record"
"github.com/prometheus/prometheus/util/testutil"
)
const defaultFlushDeadline = 1 * time.Minute
@ -1077,7 +1078,7 @@ func TestProcessExternalLabels(t *testing.T) {
} {
b.Reset(tc.labels)
processExternalLabels(b, tc.externalLabels)
require.Equal(t, tc.expected, b.Labels(), "test %d", i)
testutil.RequireEqual(t, tc.expected, b.Labels(), "test %d", i)
}
}

View file

@ -28,6 +28,7 @@ import (
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/prompb"
"github.com/prometheus/prometheus/util/annotations"
"github.com/prometheus/prometheus/util/testutil"
)
func TestNoDuplicateReadConfigs(t *testing.T) {
@ -484,7 +485,7 @@ func TestSampleAndChunkQueryableClient(t *testing.T) {
got = append(got, ss.At().Labels())
}
require.NoError(t, ss.Err())
require.Equal(t, tc.expectedSeries, got)
testutil.RequireEqual(t, tc.expectedSeries, got)
})
}
}

View file

@ -26,6 +26,7 @@ import (
"time"
"github.com/go-kit/log"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/exemplar"
@ -35,6 +36,7 @@ import (
"github.com/prometheus/prometheus/prompb"
"github.com/prometheus/prometheus/storage"
"github.com/prometheus/prometheus/tsdb"
"github.com/prometheus/prometheus/util/testutil"
)
func TestRemoteWriteHandler(t *testing.T) {
@ -59,23 +61,23 @@ func TestRemoteWriteHandler(t *testing.T) {
for _, ts := range writeRequestFixture.Timeseries {
labels := labelProtosToLabels(ts.Labels)
for _, s := range ts.Samples {
require.Equal(t, mockSample{labels, s.Timestamp, s.Value}, appendable.samples[i])
requireEqual(t, mockSample{labels, s.Timestamp, s.Value}, appendable.samples[i])
i++
}
for _, e := range ts.Exemplars {
exemplarLabels := labelProtosToLabels(e.Labels)
require.Equal(t, mockExemplar{labels, exemplarLabels, e.Timestamp, e.Value}, appendable.exemplars[j])
requireEqual(t, mockExemplar{labels, exemplarLabels, e.Timestamp, e.Value}, appendable.exemplars[j])
j++
}
for _, hp := range ts.Histograms {
if hp.IsFloatHistogram() {
fh := FloatHistogramProtoToFloatHistogram(hp)
require.Equal(t, mockHistogram{labels, hp.Timestamp, nil, fh}, appendable.histograms[k])
requireEqual(t, mockHistogram{labels, hp.Timestamp, nil, fh}, appendable.histograms[k])
} else {
h := HistogramProtoToHistogram(hp)
require.Equal(t, mockHistogram{labels, hp.Timestamp, h, nil}, appendable.histograms[k])
requireEqual(t, mockHistogram{labels, hp.Timestamp, h, nil}, appendable.histograms[k])
}
k++
@ -293,6 +295,13 @@ type mockHistogram struct {
fh *histogram.FloatHistogram
}
// Wrapper to instruct go-cmp package to compare a list of structs with unexported fields.
func requireEqual(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) {
testutil.RequireEqualWithOptions(t, expected, actual,
[]cmp.Option{cmp.AllowUnexported(mockSample{}), cmp.AllowUnexported(mockExemplar{}), cmp.AllowUnexported(mockHistogram{})},
msgAndArgs...)
}
func (m *mockAppendable) Appender(_ context.Context) storage.Appender {
return m
}

View file

@ -4058,11 +4058,11 @@ func TestOOOWALWrite(t *testing.T) {
// The normal WAL.
actRecs := getRecords(path.Join(dir, "wal"))
require.Equal(t, inOrderRecords, actRecs)
testutil.RequireEqual(t, inOrderRecords, actRecs)
// The WBL.
actRecs = getRecords(path.Join(dir, wlog.WblDirName))
require.Equal(t, oooRecords, actRecs)
testutil.RequireEqual(t, oooRecords, actRecs)
}
// Tests https://github.com/prometheus/prometheus/issues/10291#issuecomment-1044373110.

View file

@ -30,6 +30,7 @@ import (
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/prometheus/client_golang/prometheus"
prom_testutil "github.com/prometheus/client_golang/prometheus/testutil"
"github.com/prometheus/common/model"
@ -50,6 +51,7 @@ import (
"github.com/prometheus/prometheus/tsdb/tombstones"
"github.com/prometheus/prometheus/tsdb/tsdbutil"
"github.com/prometheus/prometheus/tsdb/wlog"
"github.com/prometheus/prometheus/util/testutil"
)
// newTestHeadDefaultOptions returns the HeadOptions that should be used by default in unit tests.
@ -677,10 +679,10 @@ func TestHead_ReadWAL(t *testing.T) {
s50 := head.series.getByID(50)
s100 := head.series.getByID(100)
require.Equal(t, labels.FromStrings("a", "1"), s10.lset)
require.Equal(t, (*memSeries)(nil), s11) // Series without samples should be garbage collected at head.Init().
require.Equal(t, labels.FromStrings("a", "4"), s50.lset)
require.Equal(t, labels.FromStrings("a", "3"), s100.lset)
testutil.RequireEqual(t, labels.FromStrings("a", "1"), s10.lset)
require.Nil(t, s11) // Series without samples should be garbage collected at head.Init().
testutil.RequireEqual(t, labels.FromStrings("a", "4"), s50.lset)
testutil.RequireEqual(t, labels.FromStrings("a", "3"), s100.lset)
expandChunk := func(c chunkenc.Iterator) (x []sample) {
for c.Next() == chunkenc.ValFloat {
@ -707,7 +709,7 @@ func TestHead_ReadWAL(t *testing.T) {
require.NoError(t, err)
e, err := q.Select(0, 1000, []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "a", "1")})
require.NoError(t, err)
require.Equal(t, exemplar.Exemplar{Ts: 100, Value: 1, Labels: labels.FromStrings("traceID", "asdf")}, e[0].Exemplars[0])
require.True(t, exemplar.Exemplar{Ts: 100, Value: 1, Labels: labels.FromStrings("traceID", "asdf")}.Equals(e[0].Exemplars[0]))
})
}
}
@ -3743,7 +3745,7 @@ func TestChunkSnapshot(t *testing.T) {
})
require.NoError(t, err)
// Verifies both existence of right exemplars and order of exemplars in the buffer.
require.Equal(t, expExemplars, actExemplars)
testutil.RequireEqualWithOptions(t, expExemplars, actExemplars, []cmp.Option{cmp.AllowUnexported(ex{})})
}
var (

View file

@ -205,7 +205,7 @@ func TestIndexRW_Postings(t *testing.T) {
require.NoError(t, err)
require.Empty(t, c)
require.Equal(t, series[i], builder.Labels())
testutil.RequireEqual(t, series[i], builder.Labels())
}
require.NoError(t, p.Err())
@ -488,7 +488,7 @@ func TestPersistence_index_e2e(t *testing.T) {
err = mi.Series(expp.At(), &eBuilder, &expchks)
require.NoError(t, err)
require.Equal(t, eBuilder.Labels(), builder.Labels())
testutil.RequireEqual(t, eBuilder.Labels(), builder.Labels())
require.Equal(t, expchks, chks)
}
require.False(t, expp.Next(), "Expected no more postings for %q=%q", p.Name, p.Value)

View file

@ -24,6 +24,7 @@ import (
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/tsdb/encoding"
"github.com/prometheus/prometheus/tsdb/tombstones"
"github.com/prometheus/prometheus/util/testutil"
)
func TestRecord_EncodeDecode(t *testing.T) {
@ -44,7 +45,7 @@ func TestRecord_EncodeDecode(t *testing.T) {
}
decSeries, err := dec.Series(enc.Series(series, nil), nil)
require.NoError(t, err)
require.Equal(t, series, decSeries)
testutil.RequireEqual(t, series, decSeries)
metadata := []RefMetadata{
{
@ -107,7 +108,7 @@ func TestRecord_EncodeDecode(t *testing.T) {
}
decExemplars, err := dec.Exemplars(enc.Exemplars(exemplars, nil), nil)
require.NoError(t, err)
require.Equal(t, exemplars, decExemplars)
testutil.RequireEqual(t, exemplars, decExemplars)
histograms := []RefHistogramSample{
{

View file

@ -25,6 +25,7 @@ import (
"github.com/prometheus/prometheus/tsdb/chunks"
"github.com/prometheus/prometheus/tsdb/fileutil"
"github.com/prometheus/prometheus/tsdb/index"
"github.com/prometheus/prometheus/util/testutil"
)
func TestRepairBadIndexVersion(t *testing.T) {
@ -112,7 +113,7 @@ func TestRepairBadIndexVersion(t *testing.T) {
}
require.NoError(t, p.Err())
require.Equal(t, []labels.Labels{
testutil.RequireEqual(t, []labels.Labels{
labels.FromStrings("a", "1", "b", "1"),
labels.FromStrings("a", "2", "b", "1"),
}, res)

View file

@ -34,6 +34,7 @@ import (
"github.com/prometheus/prometheus/tsdb/record"
"github.com/prometheus/prometheus/tsdb/tombstones"
"github.com/prometheus/prometheus/tsdb/wlog"
"github.com/prometheus/prometheus/util/testutil"
)
func TestSegmentWAL_cut(t *testing.T) {
@ -147,7 +148,7 @@ func TestSegmentWAL_Truncate(t *testing.T) {
readSeries = append(readSeries, s...)
}, nil, nil))
require.Equal(t, expected, readSeries)
testutil.RequireEqual(t, expected, readSeries)
}
// Symmetrical test of reading and writing to the WAL via its main interface.
@ -213,9 +214,9 @@ func TestSegmentWAL_Log_Restore(t *testing.T) {
require.NoError(t, r.Read(serf, smplf, delf))
require.Equal(t, recordedSamples, resultSamples)
require.Equal(t, recordedSeries, resultSeries)
require.Equal(t, recordedDeletes, resultDeletes)
testutil.RequireEqual(t, recordedSamples, resultSamples)
testutil.RequireEqual(t, recordedSeries, resultSeries)
testutil.RequireEqual(t, recordedDeletes, resultDeletes)
series := series[k : k+(numMetrics/iterations)]
@ -533,7 +534,7 @@ func TestMigrateWAL_Fuzz(t *testing.T) {
}
require.NoError(t, r.Err())
require.Equal(t, []interface{}{
testutil.RequireEqual(t, []interface{}{
[]record.RefSeries{
{Ref: 100, Labels: labels.FromStrings("abc", "def", "123", "456")},
{Ref: 1, Labels: labels.FromStrings("abc", "def2", "1234", "4567")},

View file

@ -29,6 +29,7 @@ import (
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/tsdb/chunks"
"github.com/prometheus/prometheus/tsdb/record"
"github.com/prometheus/prometheus/util/testutil"
)
func TestLastCheckpoint(t *testing.T) {
@ -286,7 +287,7 @@ func TestCheckpoint(t *testing.T) {
{Ref: 2, Labels: labels.FromStrings("a", "b", "c", "2")},
{Ref: 4, Labels: labels.FromStrings("a", "b", "c", "4")},
}
require.Equal(t, expectedRefSeries, series)
testutil.RequireEqual(t, expectedRefSeries, series)
expectedRefMetadata := []record.RefMetadata{
{Ref: 0, Unit: fmt.Sprintf("%d", last-100), Help: fmt.Sprintf("%d", last-100)},

43
util/testutil/cmp.go Normal file
View file

@ -0,0 +1,43 @@
// Copyright 2023 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 testutil
import (
"fmt"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/labels"
)
// Replacement for require.Equal using go-cmp adapted for Prometheus data structures, instead of DeepEqual.
func RequireEqual(t testing.TB, expected, actual interface{}, msgAndArgs ...interface{}) {
t.Helper()
RequireEqualWithOptions(t, expected, actual, nil, msgAndArgs...)
}
// As RequireEqual but allows extra cmp.Options.
func RequireEqualWithOptions(t testing.TB, expected, actual interface{}, extra []cmp.Option, msgAndArgs ...interface{}) {
t.Helper()
options := append([]cmp.Option{cmp.Comparer(labels.Equal)}, extra...)
if cmp.Equal(expected, actual, options...) {
return
}
diff := cmp.Diff(expected, actual, options...)
require.Fail(t, fmt.Sprintf("Not equal: \n"+
"expected: %s\n"+
"actual : %s%s", expected, actual, diff), msgAndArgs...)
}

View file

@ -32,6 +32,7 @@ import (
"github.com/prometheus/prometheus/prompb"
"github.com/prometheus/prometheus/util/stats"
"github.com/prometheus/prometheus/util/testutil"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
@ -597,7 +598,7 @@ func TestGetSeries(t *testing.T) {
r := res.data.([]labels.Labels)
sort.Sort(byLabels(tc.expected))
sort.Sort(byLabels(r))
require.Equal(t, tc.expected, r)
testutil.RequireEqual(t, tc.expected, r)
}
})
}
@ -2878,7 +2879,7 @@ func assertAPIError(t *testing.T, got *apiError, exp errorType) {
func assertAPIResponse(t *testing.T, got, exp interface{}) {
t.Helper()
require.Equal(t, exp, got)
testutil.RequireEqual(t, exp, got)
}
func assertAPIResponseLength(t *testing.T, got interface{}, expLen int) {

View file

@ -37,6 +37,7 @@ import (
"github.com/prometheus/prometheus/storage"
"github.com/prometheus/prometheus/tsdb"
"github.com/prometheus/prometheus/util/teststorage"
"github.com/prometheus/prometheus/util/testutil"
)
var scenarios = map[string]struct {
@ -427,5 +428,5 @@ func TestFederationWithNativeHistograms(t *testing.T) {
// TODO(codesome): Once PromQL is able to set the CounterResetHint on histograms,
// test it with switching histogram types for metric families.
require.Equal(t, 4, metricFamilies)
require.Equal(t, expVec, actVec)
testutil.RequireEqual(t, expVec, actVec)
}