From 680d8edf61fd030a219576a2a3f2198197d2b8f0 Mon Sep 17 00:00:00 2001 From: SuperQ Date: Wed, 19 Jun 2024 08:22:50 +0200 Subject: [PATCH] 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 --- NOTICE | 5 - prometheus/testutil/diff/diff.go | 193 --------------------- prometheus/testutil/diff/diff_test.go | 231 -------------------------- prometheus/testutil/testutil.go | 4 +- prometheus/testutil/testutil_test.go | 12 -- 5 files changed, 2 insertions(+), 443 deletions(-) delete mode 100644 prometheus/testutil/diff/diff.go delete mode 100644 prometheus/testutil/diff/diff_test.go diff --git a/NOTICE b/NOTICE index ba89c57..b9cc55a 100644 --- a/NOTICE +++ b/NOTICE @@ -16,8 +16,3 @@ Go support for Protocol Buffers - Google's data interchange format 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 @@ import ( "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 @@ func compare(got, want []*dto.MetricFamily) error { 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 @@ func TestMetricNotFound(t *testing.T) { 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) {