Skip to content

Commit e78254e

Browse files
authored
Add tests for pkg/util/test.AssertGatherAndCompare (#9543)
Signed-off-by: Arve Knudsen <[email protected]>
1 parent cd1294b commit e78254e

File tree

2 files changed

+158
-5
lines changed

2 files changed

+158
-5
lines changed

pkg/util/test/metrics.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111

1212
"github.com/prometheus/client_golang/prometheus"
1313
"github.com/prometheus/client_golang/prometheus/testutil"
14-
"github.com/stretchr/testify/require"
14+
"github.com/stretchr/testify/assert"
1515
)
1616

1717
type ExpectedMetricsContext struct {
@@ -67,7 +67,20 @@ func (m *ExpectedMetrics) GetNames() []string {
6767
return m.Names
6868
}
6969

70+
// AssertGatherAndCompare asserts that metrics in expectedText are found among g's metrics.
71+
// If, however, any metrics are provided, the following rules apply:
72+
// * Provided metrics that also exist in expectedText are required to be found among g's metrics.
73+
// * Provided metrics that don't exist in expectedText are required to be absent from g's metrics.
7074
func AssertGatherAndCompare(t *testing.T, g prometheus.Gatherer, expectedText string, metrics ...string) {
75+
t.Helper()
76+
assert.NoError(t, gatherAndCompare(g, expectedText, metrics...))
77+
}
78+
79+
func gatherAndCompare(g prometheus.Gatherer, expectedText string, metrics ...string) error {
80+
if len(metrics) == 0 {
81+
return testutil.GatherAndCompare(g, strings.NewReader(expectedText))
82+
}
83+
7184
sc := bufio.NewScanner(strings.NewReader(expectedText))
7285
absent := make([]string, len(metrics))
7386
copy(absent, metrics)
@@ -85,17 +98,31 @@ func AssertGatherAndCompare(t *testing.T, g prometheus.Gatherer, expectedText st
8598
}
8699
}
87100
}
88-
require.Equal(t, len(metrics), len(required)+len(absent)) // Sanity check.
101+
// Sanity check.
102+
if len(required)+len(absent) != len(metrics) {
103+
panic(fmt.Errorf("length of required+absent doesn't match up with metrics"))
104+
}
105+
89106
if len(required) > 0 {
90-
require.NoError(t, testutil.GatherAndCompare(g, strings.NewReader(expectedText), required...), "should be present: metrics=%s", strings.Join(required, ", "))
107+
if err := testutil.GatherAndCompare(g, strings.NewReader(expectedText), required...); err != nil {
108+
return err
109+
}
91110
}
111+
92112
notAbsent := []string{}
93113
for _, metric := range absent {
94114
count, err := testutil.GatherAndCount(g, metric)
95-
require.NoError(t, err)
115+
if err != nil {
116+
return fmt.Errorf("GatherAndCount(g, %s): %w", metric, err)
117+
}
118+
96119
if count > 0 {
97120
notAbsent = append(notAbsent, metric)
98121
}
99122
}
100-
require.Empty(t, notAbsent, "should be absent: metrics=%s", strings.Join(notAbsent, ", "))
123+
if len(notAbsent) > 0 {
124+
return fmt.Errorf("should be absent: metrics=%s", strings.Join(notAbsent, ", "))
125+
}
126+
127+
return nil
101128
}

pkg/util/test/metrics_test.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// SPDX-License-Identifier: AGPL-3.0-only
2+
3+
package test
4+
5+
import (
6+
"testing"
7+
8+
dto "github.com/prometheus/client_model/go"
9+
"github.com/stretchr/testify/require"
10+
"google.golang.org/protobuf/proto"
11+
)
12+
13+
func TestAssertGatherAndCompare(t *testing.T) {
14+
g := fakeGatherer{
15+
metrics: []*dto.MetricFamily{
16+
{
17+
Name: proto.String("cortex_distributor_deduped_samples_total"),
18+
Help: proto.String("The total number of deduplicated samples."),
19+
Metric: []*dto.Metric{
20+
{
21+
Label: []*dto.LabelPair{
22+
{
23+
Name: proto.String("environment"),
24+
Value: proto.String("test"),
25+
},
26+
},
27+
TimestampMs: proto.Int64(1000),
28+
Counter: &dto.Counter{
29+
Value: proto.Float64(1),
30+
},
31+
},
32+
},
33+
},
34+
},
35+
}
36+
37+
t.Run("don't specify any metrics", func(t *testing.T) {
38+
// When not specifying any metrics, an error should be returned due to missing metric
39+
// cortex_distributor_latest_seen_sample_timestamp_seconds.
40+
err := gatherAndCompare(g, `
41+
# HELP cortex_distributor_deduped_samples_total The total number of deduplicated samples.
42+
# TYPE cortex_distributor_deduped_samples_total counter
43+
cortex_distributor_deduped_samples_total{environment="test"} 1 1000
44+
45+
# HELP cortex_distributor_latest_seen_sample_timestamp_seconds Unix timestamp of latest received sample per user.
46+
# TYPE cortex_distributor_latest_seen_sample_timestamp_seconds gauge
47+
cortex_distributor_latest_seen_sample_timestamp_seconds{user="userA"} 1111
48+
`)
49+
require.EqualError(t, err, ` # HELP cortex_distributor_deduped_samples_total The total number of deduplicated samples.
50+
# TYPE cortex_distributor_deduped_samples_total counter
51+
cortex_distributor_deduped_samples_total{environment="test"} 1 1000
52+
+# HELP cortex_distributor_latest_seen_sample_timestamp_seconds Unix timestamp of latest received sample per user.
53+
+# TYPE cortex_distributor_latest_seen_sample_timestamp_seconds gauge
54+
+cortex_distributor_latest_seen_sample_timestamp_seconds{user="userA"} 1111
55+
`)
56+
})
57+
58+
t.Run("specify required metric", func(t *testing.T) {
59+
// When specifying that cortex_distributor_deduped_samples_total as the one required metric,
60+
// cortex_distributor_latest_seen_sample_timestamp_seconds should be ignored even if it's missing.
61+
AssertGatherAndCompare(t, g, `
62+
# HELP cortex_distributor_deduped_samples_total The total number of deduplicated samples.
63+
# TYPE cortex_distributor_deduped_samples_total counter
64+
cortex_distributor_deduped_samples_total{environment="test"} 1 1000
65+
66+
# HELP cortex_distributor_latest_seen_sample_timestamp_seconds Unix timestamp of latest received sample per user.
67+
# TYPE cortex_distributor_latest_seen_sample_timestamp_seconds gauge
68+
cortex_distributor_latest_seen_sample_timestamp_seconds{user="userA"} 1111
69+
`, "cortex_distributor_deduped_samples_total")
70+
})
71+
72+
t.Run("specify required metric which isn't there", func(t *testing.T) {
73+
// When specifying that cortex_distributor_deduped_samples_total as the one required metric,
74+
// cortex_distributor_latest_seen_sample_timestamp_seconds should be ignored even if it's missing.
75+
err := gatherAndCompare(g, `
76+
# HELP cortex_distributor_deduped_samples_total The total number of deduplicated samples.
77+
# TYPE cortex_distributor_deduped_samples_total counter
78+
cortex_distributor_deduped_samples_total{environment="test"} 1 1000
79+
80+
# HELP cortex_distributor_latest_seen_sample_timestamp_seconds Unix timestamp of latest received sample per user.
81+
# TYPE cortex_distributor_latest_seen_sample_timestamp_seconds gauge
82+
cortex_distributor_latest_seen_sample_timestamp_seconds{user="userA"} 1111
83+
`, "cortex_distributor_latest_seen_sample_timestamp_seconds")
84+
require.EqualError(t, err, "expected metric name(s) not found: [cortex_distributor_latest_seen_sample_timestamp_seconds]")
85+
})
86+
87+
t.Run("specify required metric and absent metric", func(t *testing.T) {
88+
// Verify that cortex_distributor_deduped_samples_total is found among metrics returned by g,
89+
// and that conversely, cortex_distributor_non_ha_samples_received_total is not found among
90+
// metrics returned by g.
91+
// cortex_distributor_latest_seen_sample_timestamp_seconds is ignored, since it's not among
92+
// the specified metrics.
93+
AssertGatherAndCompare(t, g, `
94+
# HELP cortex_distributor_deduped_samples_total The total number of deduplicated samples.
95+
# TYPE cortex_distributor_deduped_samples_total counter
96+
cortex_distributor_deduped_samples_total{environment="test"} 1 1000
97+
98+
# HELP cortex_distributor_latest_seen_sample_timestamp_seconds Unix timestamp of latest received sample per user.
99+
# TYPE cortex_distributor_latest_seen_sample_timestamp_seconds gauge
100+
cortex_distributor_latest_seen_sample_timestamp_seconds{user="userA"} 1111
101+
`, "cortex_distributor_deduped_samples_total", "cortex_distributor_non_ha_samples_received_total")
102+
})
103+
104+
t.Run("specify absent metric which is actually there", func(t *testing.T) {
105+
// Verify that cortex_distributor_deduped_samples_total is found among metrics returned by g,
106+
// and that conversely, cortex_distributor_non_ha_samples_received_total is not found among
107+
// metrics returned by g.
108+
// cortex_distributor_latest_seen_sample_timestamp_seconds is ignored, since it's not among
109+
// the specified metrics.
110+
err := gatherAndCompare(g, `
111+
# HELP cortex_distributor_latest_seen_sample_timestamp_seconds Unix timestamp of latest received sample per user.
112+
# TYPE cortex_distributor_latest_seen_sample_timestamp_seconds gauge
113+
cortex_distributor_latest_seen_sample_timestamp_seconds{user="userA"} 1111
114+
`, "cortex_distributor_deduped_samples_total", "cortex_distributor_non_ha_samples_received_total")
115+
require.EqualError(t, err, "should be absent: metrics=cortex_distributor_deduped_samples_total")
116+
})
117+
}
118+
119+
type fakeGatherer struct {
120+
metrics []*dto.MetricFamily
121+
err error
122+
}
123+
124+
func (g fakeGatherer) Gather() ([]*dto.MetricFamily, error) {
125+
return g.metrics, g.err
126+
}

0 commit comments

Comments
 (0)