summaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2026-08-18 13:40:30 +0200
committerStefan Majewsky <majewsky@gmx.net>2026-08-18 13:40:30 +0200
commit5cc0f9db288ffaf44d104974707338d52530cece (patch)
treef0ad530dd072c55c6f46dfea23af993fb31333d4 /testing
parentab5012e0083ff6623ffab78f52f9ea1120d80ffb (diff)
parenta3ccdd9f491c20771cfda343ebebd4b5d0ea6602 (diff)
downloadgo-gg-5cc0f9db288ffaf44d104974707338d52530cece.tar.gz
Merge branch 'microprom'
Diffstat (limited to 'testing')
-rw-r--r--testing/go.mod14
-rw-r--r--testing/go.sum40
-rw-r--r--testing/microprom/handler_test.go95
3 files changed, 146 insertions, 3 deletions
diff --git a/testing/go.mod b/testing/go.mod
index 9206521..9c371c2 100644
--- a/testing/go.mod
+++ b/testing/go.mod
@@ -4,5 +4,17 @@ go 1.26
require (
github.com/lib/pq v1.12.3
- go.xyrillian.de/gg v1.13.0
+ go.xyrillian.de/gg v1.13.4-0.20260817144159-a48f97c25d42
+)
+
+require (
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/prometheus/client_golang v1.24.1
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/common v0.70.1 // indirect
+ github.com/prometheus/procfs v0.21.1 // indirect
+ golang.org/x/sys v0.47.0 // indirect
+ google.golang.org/protobuf v1.36.11 // indirect
)
diff --git a/testing/go.sum b/testing/go.sum
index df1974e..6a62175 100644
--- a/testing/go.sum
+++ b/testing/go.sum
@@ -1,4 +1,40 @@
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
+github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ=
github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
-go.xyrillian.de/gg v1.12.1-0.20260731210839-e26a214de395 h1:nA6DhnjgGw1sg+Piv4xZupuoD0dM+x4Fyd91Gi7XgOo=
-go.xyrillian.de/gg v1.12.1-0.20260731210839-e26a214de395/go.mod h1:DoO4fQSWIrBRlNlCjVyrYM0kAEBt/Jg2GkMH+cGRZ0k=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU=
+github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
+github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY=
+github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc=
+github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI=
+github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY=
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.xyrillian.de/gg v1.13.4-0.20260817144159-a48f97c25d42 h1:QACQsLeI3fAWQBbZZ2/VCXBjGeeY9v+vsXnzsl0hJig=
+go.xyrillian.de/gg v1.13.4-0.20260817144159-a48f97c25d42/go.mod h1:DoO4fQSWIrBRlNlCjVyrYM0kAEBt/Jg2GkMH+cGRZ0k=
+go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
+go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
+golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
+golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
+google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
+google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/testing/microprom/handler_test.go b/testing/microprom/handler_test.go
new file mode 100644
index 0000000..93027e3
--- /dev/null
+++ b/testing/microprom/handler_test.go
@@ -0,0 +1,95 @@
+// SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net>
+// SPDX-License-Identifier: Apache-2.0
+
+package microprom_test
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "maps"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ "go.xyrillian.de/gg/assert"
+ "go.xyrillian.de/gg/microprom"
+)
+
+func TestHandlerFunctionallyIdenticalToPromhttp(t *testing.T) {
+ // build a microprom.Handler rendering two metric families
+ h1 := microprom.Handler{
+ Families: map[microprom.MetricFamilyName]microprom.MetricFamilyInfo{
+ "events": {
+ Type: microprom.MetricTypeCounter,
+ Help: "Counts events that happened.",
+ },
+ "memory_usage_bytes": {
+ Type: microprom.MetricTypeGauge,
+ Help: "How much memory is currently used.",
+ },
+ },
+ SortOutput: true,
+ Collect: func(ctx context.Context, ms *microprom.MetricSet) error {
+ labelNames := microprom.NewLabelNames("shard", "type")
+ for idx := range 5 {
+ labels := ms.FormatLabels(labelNames, fmt.Sprintf("node%d", idx), "update")
+ ms.Add("events", labels, float64(10*idx))
+ }
+ ms.Add("memory_usage_bytes", "", 42<<20)
+ return nil
+ },
+ }
+
+ // build a promhttp.Handler rendering the same metric families
+ eventsCounter := prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "events_total",
+ Help: "Counts events that happened.",
+ }, []string{"type", "shard"})
+ for idx := range 5 {
+ eventsCounter.With(prometheus.Labels{
+ "type": "update",
+ "shard": fmt.Sprintf("node%d", idx),
+ }).Add(float64(10 * idx))
+ }
+ memoryUsageBytesGauge := prometheus.NewGauge(prometheus.GaugeOpts{
+ Name: "memory_usage_bytes",
+ Help: "How much memory is currently used.",
+ })
+ memoryUsageBytesGauge.Set(42 << 20)
+ r := prometheus.NewRegistry()
+ r.MustRegister(eventsCounter)
+ r.MustRegister(memoryUsageBytesGauge)
+ h2 := promhttp.HandlerFor(r, promhttp.HandlerOpts{EnableOpenMetrics: true})
+
+ // test identical behavior for Prometheus Text Format
+ body1, headers1 := getMetrics(t, h1, nil)
+ body2, headers2 := getMetrics(t, h2, nil)
+ assert.Equal(t, strings.Split(body1, "\n"), strings.Split(body2, "\n"))
+ assert.Equal(t, headers1, headers2)
+
+ // test identical behavior for OpenMetrics 1.0 text format
+ body1, headers1 = getMetrics(t, h1, http.Header{"Accept": {"application/openmetrics-text; version=1.0.0"}})
+ body2, headers2 = getMetrics(t, h2, http.Header{"Accept": {"application/openmetrics-text; version=1.0.0"}})
+ assert.Equal(t, strings.Split(body1, "\n"), strings.Split(body2, "\n"))
+ assert.Equal(t, headers1, headers2)
+}
+
+func getMetrics(t *testing.T, h http.Handler, requestHeaders http.Header) (responseBody string, responseHeaders http.Header) {
+ t.Helper()
+ r := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/metrics", nil)
+ maps.Copy(r.Header, requestHeaders)
+
+ w := httptest.NewRecorder()
+ h.ServeHTTP(w, r)
+ resp := w.Result()
+
+ buf, err := io.ReadAll(resp.Body)
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+ return string(buf), resp.Header
+}