Switch testutil to go-cmp

Remove a dependency by using go-cmp for `testutil.CollectAndCompare()`.
Note that the string output of `cmp.Diff()` is non-stable, so users
depending on stable `error` strings will nolonger work.

Signed-off-by: SuperQ <[email protected]>
diff --git a/NOTICE b/NOTICE
index ba89c57..b9cc55a 100644
--- a/NOTICE
+++ b/NOTICE
@@ -16,8 +16,3 @@
 http://github.com/golang/protobuf/
 Copyright 2010 The Go Authors
 See source code for license details.
-
-diff - a pretty-printed complete of a Go data structure
-https://github.com/kylelemons/godebug
-Copyright 2013 Google Inc.  All rights reserved.
-See source code for license details.
diff --git a/prometheus/testutil/diff/diff.go b/prometheus/testutil/diff/diff.go
deleted file mode 100644
index b886256..0000000
--- a/prometheus/testutil/diff/diff.go
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2013 Google Inc.  All rights reserved.
-//
-// 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.
-//
-// The code in this package is copy/paste to avoid a dependency. Hence this file
-// carries the copyright of the original repo.
-// https://github.com/kylelemons/godebug/tree/v1.1.0/diff
-//
-// Package diff implements a linewise diff algorithm.
-package diff
-
-import (
-	"fmt"
-	"strings"
-)
-
-// Chunk represents a piece of the diff.  A chunk will not have both added and
-// deleted lines.  Equal lines are always after any added or deleted lines.
-// A Chunk may or may not have any lines in it, especially for the first or last
-// chunk in a computation.
-type Chunk struct {
-	Added   []string
-	Deleted []string
-	Equal   []string
-}
-
-func (c *Chunk) empty() bool {
-	return len(c.Added) == 0 && len(c.Deleted) == 0 && len(c.Equal) == 0
-}
-
-// Diff returns a string containing a line-by-line unified diff of the linewise
-// changes required to make A into B.  Each line is prefixed with '+', '-', or
-// ' ' to indicate if it should be added, removed, or is correct respectively.
-func Diff(A, B string) string {
-	aLines := strings.Split(A, "\n")
-	bLines := strings.Split(B, "\n")
-	return Render(DiffChunks(aLines, bLines))
-}
-
-// Render renders the slice of chunks into a representation that prefixes
-// the lines with '+', '-', or ' ' depending on whether the line was added,
-// removed, or equal (respectively).
-func Render(chunks []Chunk) string {
-	buf := new(strings.Builder)
-	for _, c := range chunks {
-		for _, line := range c.Added {
-			fmt.Fprintf(buf, "+%s\n", line)
-		}
-		for _, line := range c.Deleted {
-			fmt.Fprintf(buf, "-%s\n", line)
-		}
-		for _, line := range c.Equal {
-			fmt.Fprintf(buf, " %s\n", line)
-		}
-	}
-	return strings.TrimRight(buf.String(), "\n")
-}
-
-// DiffChunks uses an O(D(N+M)) shortest-edit-script algorithm
-// to compute the edits required from A to B and returns the
-// edit chunks.
-func DiffChunks(a, b []string) []Chunk {
-	// algorithm: http://www.xmailserver.org/diff2.pdf
-
-	// We'll need these quantities a lot.
-	alen, blen := len(a), len(b) // M, N
-
-	// At most, it will require len(a) deletions and len(b) additions
-	// to transform a into b.
-	maxPath := alen + blen // MAX
-	if maxPath == 0 {
-		// degenerate case: two empty lists are the same
-		return nil
-	}
-
-	// Store the endpoint of the path for diagonals.
-	// We store only the a index, because the b index on any diagonal
-	// (which we know during the loop below) is aidx-diag.
-	// endpoint[maxPath] represents the 0 diagonal.
-	//
-	// Stated differently:
-	// endpoint[d] contains the aidx of a furthest reaching path in diagonal d
-	endpoint := make([]int, 2*maxPath+1) // V
-
-	saved := make([][]int, 0, 8) // Vs
-	save := func() {
-		dup := make([]int, len(endpoint))
-		copy(dup, endpoint)
-		saved = append(saved, dup)
-	}
-
-	var editDistance int // D
-dLoop:
-	for editDistance = 0; editDistance <= maxPath; editDistance++ {
-		// The 0 diag(onal) represents equality of a and b.  Each diagonal to
-		// the left is numbered one lower, to the right is one higher, from
-		// -alen to +blen.  Negative diagonals favor differences from a,
-		// positive diagonals favor differences from b.  The edit distance to a
-		// diagonal d cannot be shorter than d itself.
-		//
-		// The iterations of this loop cover either odds or evens, but not both,
-		// If odd indices are inputs, even indices are outputs and vice versa.
-		for diag := -editDistance; diag <= editDistance; diag += 2 { // k
-			var aidx int // x
-			switch {
-			case diag == -editDistance:
-				// This is a new diagonal; copy from previous iter
-				aidx = endpoint[maxPath-editDistance+1] + 0
-			case diag == editDistance:
-				// This is a new diagonal; copy from previous iter
-				aidx = endpoint[maxPath+editDistance-1] + 1
-			case endpoint[maxPath+diag+1] > endpoint[maxPath+diag-1]:
-				// diagonal d+1 was farther along, so use that
-				aidx = endpoint[maxPath+diag+1] + 0
-			default:
-				// diagonal d-1 was farther (or the same), so use that
-				aidx = endpoint[maxPath+diag-1] + 1
-			}
-			// On diagonal d, we can compute bidx from aidx.
-			bidx := aidx - diag // y
-			// See how far we can go on this diagonal before we find a difference.
-			for aidx < alen && bidx < blen && a[aidx] == b[bidx] {
-				aidx++
-				bidx++
-			}
-			// Store the end of the current edit chain.
-			endpoint[maxPath+diag] = aidx
-			// If we've found the end of both inputs, we're done!
-			if aidx >= alen && bidx >= blen {
-				save() // save the final path
-				break dLoop
-			}
-		}
-		save() // save the current path
-	}
-	if editDistance == 0 {
-		return nil
-	}
-	chunks := make([]Chunk, editDistance+1)
-
-	x, y := alen, blen
-	for d := editDistance; d > 0; d-- {
-		endpoint := saved[d]
-		diag := x - y
-		insert := diag == -d || (diag != d && endpoint[maxPath+diag-1] < endpoint[maxPath+diag+1])
-
-		x1 := endpoint[maxPath+diag]
-		var x0, xM, kk int
-		if insert {
-			kk = diag + 1
-			x0 = endpoint[maxPath+kk]
-			xM = x0
-		} else {
-			kk = diag - 1
-			x0 = endpoint[maxPath+kk]
-			xM = x0 + 1
-		}
-		y0 := x0 - kk
-
-		var c Chunk
-		if insert {
-			c.Added = b[y0:][:1]
-		} else {
-			c.Deleted = a[x0:][:1]
-		}
-		if xM < x1 {
-			c.Equal = a[xM:][:x1-xM]
-		}
-
-		x, y = x0, y0
-		chunks[d] = c
-	}
-	if x > 0 {
-		chunks[0].Equal = a[:x]
-	}
-	if chunks[0].empty() {
-		chunks = chunks[1:]
-	}
-	if len(chunks) == 0 {
-		return nil
-	}
-	return chunks
-}
diff --git a/prometheus/testutil/diff/diff_test.go b/prometheus/testutil/diff/diff_test.go
deleted file mode 100644
index 6dfba99..0000000
--- a/prometheus/testutil/diff/diff_test.go
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2013 Google Inc.  All rights reserved.
-//
-// 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.
-//
-// The code in this package is copy/paste to avoid a dependency. Hence this file
-// carries the copyright of the original repo.
-// https://github.com/kylelemons/godebug/tree/v1.1.0/diff
-package diff
-
-import (
-	"fmt"
-	"reflect"
-	"strings"
-	"testing"
-)
-
-func TestDiff(t *testing.T) {
-	tests := []struct {
-		desc   string
-		A, B   []string
-		chunks []Chunk
-	}{
-		{
-			desc: "nil",
-		},
-		{
-			desc: "empty",
-			A:    []string{},
-			B:    []string{},
-		},
-		{
-			desc: "same",
-			A:    []string{"foo"},
-			B:    []string{"foo"},
-		},
-		{
-			desc: "a empty",
-			A:    []string{},
-		},
-		{
-			desc: "b empty",
-			B:    []string{},
-		},
-		{
-			desc: "b nil",
-			A:    []string{"foo"},
-			chunks: []Chunk{
-				0: {Deleted: []string{"foo"}},
-			},
-		},
-		{
-			desc: "a nil",
-			B:    []string{"foo"},
-			chunks: []Chunk{
-				0: {Added: []string{"foo"}},
-			},
-		},
-		{
-			desc: "start with change",
-			A:    []string{"a", "b", "c"},
-			B:    []string{"A", "b", "c"},
-			chunks: []Chunk{
-				0: {Deleted: []string{"a"}},
-				1: {Added: []string{"A"}, Equal: []string{"b", "c"}},
-			},
-		},
-		{
-			desc: "constitution",
-			A: []string{
-				"We the People of the United States, in Order to form a more perfect Union,",
-				"establish Justice, insure domestic Tranquility, provide for the common defence,",
-				"and secure the Blessings of Liberty to ourselves",
-				"and our Posterity, do ordain and establish this Constitution for the United",
-				"States of America.",
-			},
-			B: []string{
-				"We the People of the United States, in Order to form a more perfect Union,",
-				"establish Justice, insure domestic Tranquility, provide for the common defence,",
-				"promote the general Welfare, and secure the Blessings of Liberty to ourselves",
-				"and our Posterity, do ordain and establish this Constitution for the United",
-				"States of America.",
-			},
-			chunks: []Chunk{
-				0: {
-					Equal: []string{
-						"We the People of the United States, in Order to form a more perfect Union,",
-						"establish Justice, insure domestic Tranquility, provide for the common defence,",
-					},
-				},
-				1: {
-					Deleted: []string{
-						"and secure the Blessings of Liberty to ourselves",
-					},
-				},
-				2: {
-					Added: []string{
-						"promote the general Welfare, and secure the Blessings of Liberty to ourselves",
-					},
-					Equal: []string{
-						"and our Posterity, do ordain and establish this Constitution for the United",
-						"States of America.",
-					},
-				},
-			},
-		},
-	}
-
-	for _, test := range tests {
-		t.Run(test.desc, func(t *testing.T) {
-			got := DiffChunks(test.A, test.B)
-			if got, want := len(got), len(test.chunks); got != want {
-				t.Errorf("edit distance = %v, want %v", got-1, want-1)
-				return
-			}
-			for i := range got {
-				got, want := got[i], test.chunks[i]
-				if got, want := got.Added, want.Added; !reflect.DeepEqual(got, want) {
-					t.Errorf("chunks[%d]: Added = %v, want %v", i, got, want)
-				}
-				if got, want := got.Deleted, want.Deleted; !reflect.DeepEqual(got, want) {
-					t.Errorf("chunks[%d]: Deleted = %v, want %v", i, got, want)
-				}
-				if got, want := got.Equal, want.Equal; !reflect.DeepEqual(got, want) {
-					t.Errorf("chunks[%d]: Equal = %v, want %v", i, got, want)
-				}
-			}
-		})
-	}
-}
-
-func TestRender(t *testing.T) {
-	tests := []struct {
-		desc   string
-		chunks []Chunk
-		out    string
-	}{
-		{
-			desc: "ordering",
-			chunks: []Chunk{
-				{
-					Added:   []string{"1"},
-					Deleted: []string{"2"},
-					Equal:   []string{"3"},
-				},
-				{
-					Added:   []string{"4"},
-					Deleted: []string{"5"},
-				},
-			},
-			out: strings.TrimSpace(`
-+1
--2
- 3
-+4
--5
-			`),
-		},
-		{
-			desc: "only_added",
-			chunks: []Chunk{
-				{
-					Added: []string{"1"},
-				},
-			},
-			out: strings.TrimSpace(`
-+1
-			`),
-		},
-		{
-			desc: "only_deleted",
-			chunks: []Chunk{
-				{
-					Deleted: []string{"1"},
-				},
-			},
-			out: strings.TrimSpace(`
--1
-			`),
-		},
-	}
-
-	for _, test := range tests {
-		t.Run(test.desc, func(t *testing.T) {
-			if got, want := Render(test.chunks), test.out; got != want {
-				t.Errorf("Render(%q):", test.chunks)
-				t.Errorf("GOT\n%s", got)
-				t.Errorf("WANT\n%s", want)
-			}
-		})
-	}
-}
-
-func ExampleDiff() {
-	constitution := strings.TrimSpace(`
-We the People of the United States, in Order to form a more perfect Union,
-establish Justice, insure domestic Tranquility, provide for the common defence,
-promote the general Welfare, and secure the Blessings of Liberty to ourselves
-and our Posterity, do ordain and establish this Constitution for the United
-States of America.
-`)
-
-	got := strings.TrimSpace(`
-:wq
-We the People of the United States, in Order to form a more perfect Union,
-establish Justice, insure domestic Tranquility, provide for the common defence,
-and secure the Blessings of Liberty to ourselves
-and our Posterity, do ordain and establish this Constitution for the United
-States of America.
-`)
-
-	fmt.Println(Diff(got, constitution))
-
-	// Output:
-	// -:wq
-	//  We the People of the United States, in Order to form a more perfect Union,
-	//  establish Justice, insure domestic Tranquility, provide for the common defence,
-	// -and secure the Blessings of Liberty to ourselves
-	// +promote the general Welfare, and secure the Blessings of Liberty to ourselves
-	//  and our Posterity, do ordain and establish this Constitution for the United
-	//  States of America.
-}
diff --git a/prometheus/testutil/testutil.go b/prometheus/testutil/testutil.go
index de7eaf1..92d0479 100644
--- a/prometheus/testutil/testutil.go
+++ b/prometheus/testutil/testutil.go
@@ -43,13 +43,13 @@
 	"io"
 	"net/http"
 
+	"github.com/google/go-cmp/cmp"
 	dto "github.com/prometheus/client_model/go"
 	"github.com/prometheus/common/expfmt"
 	"google.golang.org/protobuf/proto"
 
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/internal"
-	"github.com/prometheus/client_golang/prometheus/testutil/diff"
 )
 
 // ToFloat64 collects all Metrics from the provided Collector. It expects that
@@ -309,7 +309,7 @@
 			return fmt.Errorf("encoding expected metrics failed: %w", err)
 		}
 	}
-	if diffErr := diff.Diff(gotBuf.String(), wantBuf.String()); diffErr != "" {
+	if diffErr := cmp.Diff(gotBuf.String(), wantBuf.String()); diffErr != "" {
 		return fmt.Errorf(diffErr)
 	}
 	return nil
diff --git a/prometheus/testutil/testutil_test.go b/prometheus/testutil/testutil_test.go
index ec835a6..136bdf9 100644
--- a/prometheus/testutil/testutil_test.go
+++ b/prometheus/testutil/testutil_test.go
@@ -309,22 +309,10 @@
 		some_other_metric{label1="value1"} 1
 	`
 
-	expectedError := `-# HELP some_total A value that represents a counter.
--# TYPE some_total counter
--some_total{label1="value1"} 1
-+# HELP some_other_metric A value that represents a counter.
-+# TYPE some_other_metric counter
-+some_other_metric{label1="value1"} 1
- `
-
 	err := CollectAndCompare(c, strings.NewReader(metadata+expected))
 	if err == nil {
 		t.Error("Expected error, got no error.")
 	}
-
-	if err.Error() != expectedError {
-		t.Errorf("Expected\n%#+v\nGot:\n%#+v", expectedError, err.Error())
-	}
 }
 
 func TestScrapeAndCompare(t *testing.T) {