func TestValidateMetrics(t *testing.T) {
	testcases := map[string]struct {
		setup func(ctx context.Context, t *testing.T) (prober.Prober, sm.Check, func())
	}{
		"ping": {
			setup: func(ctx context.Context, t *testing.T) (prober.Prober, sm.Check, func()) {
				check := sm.Check{
					Target:  "127.0.0.1",
					Timeout: 2000,
					Settings: sm.CheckSettings{
						Ping: &sm.PingSettings{
							IpVersion: sm.IpVersion_V4,
						},
					},
				}
				prober, err := icmp.NewProber(check)
				if err != nil {
					t.Fatalf("cannot create ICMP prober: %s", err)
				}
				return prober, check, func() {}
			},
		},
		"http": {
			setup: func(ctx context.Context, t *testing.T) (prober.Prober, sm.Check, func()) {
				httpSrv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
					w.WriteHeader(http.StatusOK)
				}))
				httpSrv.Start()
				check := sm.Check{
					Target:  httpSrv.URL,
					Timeout: 2000,
					Settings: sm.CheckSettings{
						Http: &sm.HttpSettings{
							IpVersion: sm.IpVersion_V4,
						},
					},
				}
				prober, err := httpProber.NewProber(
					ctx,
					check,
					zerolog.New(io.Discard),
				)
				if err != nil {
					t.Fatalf("cannot create HTTP prober: %s", err)
				}
				return prober, check, httpSrv.Close
			},
		},
		"http_ssl": {
			setup: func(ctx context.Context, t *testing.T) (prober.Prober, sm.Check, func()) {
				httpSrv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
					w.WriteHeader(http.StatusOK)
				}))
				httpSrv.StartTLS()
				check := sm.Check{
					Target:  httpSrv.URL,
					Timeout: 2000,
					Settings: sm.CheckSettings{
						Http: &sm.HttpSettings{
							IpVersion: sm.IpVersion_V4,
							TlsConfig: &sm.TLSConfig{
								InsecureSkipVerify: true,
							},
						},
					},
				}
				prober, err := httpProber.NewProber(
					ctx,
					check,
					zerolog.New(io.Discard),
				)
				if err != nil {
					t.Fatalf("cannot create HTTP prober: %s", err)
				}
				return prober, check, httpSrv.Close
			},
		},
		"dns": {
			setup: func(ctx context.Context, t *testing.T) (prober.Prober, sm.Check, func()) {
				srv, clean := setupDNSServer(t)
				check := sm.Check{
					Target:  "example.org",
					Timeout: 2000,
					Settings: sm.CheckSettings{
						Dns: &sm.DnsSettings{
							Server:    srv,
							IpVersion: sm.IpVersion_V4,
							Protocol:  sm.DnsProtocol_UDP,
						},
					},
				}
				prober, err := dnsProber.NewProber(check)
				if err != nil {
					clean()
					t.Fatalf("cannot create DNS prober: %s", err)
				}
				return prober, check, clean
			},
		},
		"tcp": {
			setup: func(ctx context.Context, t *testing.T) (prober.Prober, sm.Check, func()) {
				srv, clean := setupTCPServer(t)
				check := sm.Check{
					Target:  srv,
					Timeout: 2000,
					Settings: sm.CheckSettings{
						Tcp: &sm.TcpSettings{
							IpVersion: sm.IpVersion_V4,
						},
					},
				}
				prober, err := tcp.NewProber(
					ctx,
					check,
					zerolog.New(io.Discard))
				if err != nil {
					clean()
					t.Fatalf("cannot create TCP prober: %s", err)
				}
				return prober, check, clean
			},
		},
		"tcp_ssl": {
			setup: func(ctx context.Context, t *testing.T) (prober.Prober, sm.Check, func()) {
				srv, clean := setupTCPServerWithSSL(t)
				check := sm.Check{
					Target:  srv,
					Timeout: 2000,
					Settings: sm.CheckSettings{
						Tcp: &sm.TcpSettings{
							IpVersion: sm.IpVersion_V4,
							Tls:       true,
							TlsConfig: &sm.TLSConfig{
								InsecureSkipVerify: true,
							},
						},
					},
				}
				prober, err := tcp.NewProber(
					ctx,
					check,
					zerolog.New(io.Discard))
				if err != nil {
					clean()
					t.Fatalf("cannot create TCP prober: %s", err)
				}
				return prober, check, clean
			},
		},
		"traceroute": {
			setup: func(ctx context.Context, t *testing.T) (prober.Prober, sm.Check, func()) {
				httpSrv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
					w.WriteHeader(http.StatusOK)
				}))
				httpSrv.Start()
				check := sm.Check{
					Target: httpSrv.URL,
					Settings: sm.CheckSettings{
						Traceroute: &sm.TracerouteSettings{},
					},
				}
				p, err := traceroute.NewProber(check, zerolog.New(io.Discard))
				if err != nil {
					t.Fatalf("cannot create traceroute prober %s", err)
				}
				return p, check, func() {}
			},
		},
	}
	for name, testcase := range testcases {
		t.Run(name, func(t *testing.T) {
			verifyProberMetrics(t, name, testcase.setup, false)
		})
		t.Run(name+"_basic", func(t *testing.T) {
			verifyProberMetrics(t, name+"_basic", testcase.setup, true)
		})
	}
}
TestValidateMetrics verify that the exposed metrics have not changed.

It does this by setting up local targets (HTTP server, DNS server,
TCP server) that the BBE probers can run against. The resulting
metrics are then compared (only names and labels, not values) against
known outputs. If metrics are added or removed, this test will fail.

The golden files can be updated by running:

go test -v -race -run TestValidateMetrics ./internal/scraper/
package scraper
import (
	"bytes"
	"context"
	"crypto/tls"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"testing"
	"time"
	"github.com/grafana/synthetic-monitoring-agent/internal/prober"
	dnsProber "github.com/grafana/synthetic-monitoring-agent/internal/prober/dns"
	httpProber "github.com/grafana/synthetic-monitoring-agent/internal/prober/http"
	"github.com/grafana/synthetic-monitoring-agent/internal/prober/icmp"
	"github.com/grafana/synthetic-monitoring-agent/internal/prober/tcp"
	"github.com/grafana/synthetic-monitoring-agent/internal/prober/traceroute"
	sm "github.com/grafana/synthetic-monitoring-agent/pkg/pb/synthetic_monitoring"
	"github.com/miekg/dns"
	"github.com/prometheus/client_golang/prometheus"
	dto "github.com/prometheus/client_model/go"
	"github.com/prometheus/common/expfmt"
	"github.com/prometheus/prometheus/prompb"
	"github.com/rs/zerolog"
	"github.com/stretchr/testify/require"
)
var updateGolden = flag.Bool("update-golden", false, "update golden files")