aboutsummaryrefslogtreecommitdiff
path: root/cmp
diff options
context:
space:
mode:
Diffstat (limited to 'cmp')
-rw-r--r--cmp/cmpopts/equate.go1
-rw-r--r--cmp/cmpopts/sort.go14
-rw-r--r--cmp/cmpopts/struct_filter.go2
-rw-r--r--cmp/cmpopts/xform.go1
-rw-r--r--cmp/compare.go62
-rw-r--r--cmp/compare_test.go2
-rw-r--r--cmp/internal/diff/diff.go44
-rw-r--r--cmp/options.go8
-rw-r--r--cmp/path.go16
-rw-r--r--cmp/report_slices.go12
-rw-r--r--cmp/report_text.go1
11 files changed, 88 insertions, 75 deletions
diff --git a/cmp/cmpopts/equate.go b/cmp/cmpopts/equate.go
index c49a756..e54a76c 100644
--- a/cmp/cmpopts/equate.go
+++ b/cmp/cmpopts/equate.go
@@ -42,6 +42,7 @@ func isEmpty(x, y interface{}) bool {
// The fraction and margin must be non-negative.
//
// The mathematical expression used is equivalent to:
+//
// |x-y| ≤ max(fraction*min(|x|, |y|), margin)
//
// EquateApprox can be used in conjunction with EquateNaNs.
diff --git a/cmp/cmpopts/sort.go b/cmp/cmpopts/sort.go
index a646d74..0eb2a75 100644
--- a/cmp/cmpopts/sort.go
+++ b/cmp/cmpopts/sort.go
@@ -18,9 +18,9 @@ import (
// sort any slice with element type V that is assignable to T.
//
// The less function must be:
-// • Deterministic: less(x, y) == less(x, y)
-// • Irreflexive: !less(x, x)
-// • Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
+// - Deterministic: less(x, y) == less(x, y)
+// - Irreflexive: !less(x, x)
+// - Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
//
// The less function does not have to be "total". That is, if !less(x, y) and
// !less(y, x) for two elements x and y, their relative order is maintained.
@@ -91,10 +91,10 @@ func (ss sliceSorter) less(v reflect.Value, i, j int) bool {
// use Comparers on K or the K.Equal method if it exists.
//
// The less function must be:
-// • Deterministic: less(x, y) == less(x, y)
-// • Irreflexive: !less(x, x)
-// • Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
-// • Total: if x != y, then either less(x, y) or less(y, x)
+// - Deterministic: less(x, y) == less(x, y)
+// - Irreflexive: !less(x, x)
+// - Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
+// - Total: if x != y, then either less(x, y) or less(y, x)
//
// SortMaps can be used in conjunction with EquateEmpty.
func SortMaps(lessFunc interface{}) cmp.Option {
diff --git a/cmp/cmpopts/struct_filter.go b/cmp/cmpopts/struct_filter.go
index a09829c..ca11a40 100644
--- a/cmp/cmpopts/struct_filter.go
+++ b/cmp/cmpopts/struct_filter.go
@@ -67,12 +67,14 @@ func (sf structFilter) filter(p cmp.Path) bool {
// fieldTree represents a set of dot-separated identifiers.
//
// For example, inserting the following selectors:
+//
// Foo
// Foo.Bar.Baz
// Foo.Buzz
// Nuka.Cola.Quantum
//
// Results in a tree of the form:
+//
// {sub: {
// "Foo": {ok: true, sub: {
// "Bar": {sub: {
diff --git a/cmp/cmpopts/xform.go b/cmp/cmpopts/xform.go
index 4eb49d6..8812443 100644
--- a/cmp/cmpopts/xform.go
+++ b/cmp/cmpopts/xform.go
@@ -23,6 +23,7 @@ func (xf xformFilter) filter(p cmp.Path) bool {
// that the transformer cannot be recursively applied upon its own output.
//
// An example use case is a transformer that splits a string by lines:
+//
// AcyclicTransformer("SplitLines", func(s string) []string{
// return strings.Split(s, "\n")
// })
diff --git a/cmp/compare.go b/cmp/compare.go
index fd2b3a4..caf75ad 100644
--- a/cmp/compare.go
+++ b/cmp/compare.go
@@ -13,21 +13,21 @@
//
// The primary features of cmp are:
//
-// • When the default behavior of equality does not suit the needs of the test,
-// custom equality functions can override the equality operation.
-// For example, an equality function may report floats as equal so long as they
-// are within some tolerance of each other.
+// - When the default behavior of equality does not suit the test's needs,
+// custom equality functions can override the equality operation.
+// For example, an equality function may report floats as equal so long as
+// they are within some tolerance of each other.
//
-// • Types that have an Equal method may use that method to determine equality.
-// This allows package authors to determine the equality operation for the types
-// that they define.
+// - Types with an Equal method may use that method to determine equality.
+// This allows package authors to determine the equality operation
+// for the types that they define.
//
-// • If no custom equality functions are used and no Equal method is defined,
-// equality is determined by recursively comparing the primitive kinds on both
-// values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported
-// fields are not compared by default; they result in panics unless suppressed
-// by using an Ignore option (see cmpopts.IgnoreUnexported) or explicitly
-// compared using the Exporter option.
+// - If no custom equality functions are used and no Equal method is defined,
+// equality is determined by recursively comparing the primitive kinds on
+// both values, much like reflect.DeepEqual. Unlike reflect.DeepEqual,
+// unexported fields are not compared by default; they result in panics
+// unless suppressed by using an Ignore option (see cmpopts.IgnoreUnexported)
+// or explicitly compared using the Exporter option.
package cmp
import (
@@ -45,25 +45,25 @@ import (
// Equal reports whether x and y are equal by recursively applying the
// following rules in the given order to x and y and all of their sub-values:
//
-// • Let S be the set of all Ignore, Transformer, and Comparer options that
-// remain after applying all path filters, value filters, and type filters.
-// If at least one Ignore exists in S, then the comparison is ignored.
-// If the number of Transformer and Comparer options in S is greater than one,
-// then Equal panics because it is ambiguous which option to use.
-// If S contains a single Transformer, then use that to transform the current
-// values and recursively call Equal on the output values.
-// If S contains a single Comparer, then use that to compare the current values.
-// Otherwise, evaluation proceeds to the next rule.
+// - Let S be the set of all Ignore, Transformer, and Comparer options that
+// remain after applying all path filters, value filters, and type filters.
+// If at least one Ignore exists in S, then the comparison is ignored.
+// If the number of Transformer and Comparer options in S is non-zero,
+// then Equal panics because it is ambiguous which option to use.
+// If S contains a single Transformer, then use that to transform
+// the current values and recursively call Equal on the output values.
+// If S contains a single Comparer, then use that to compare the current values.
+// Otherwise, evaluation proceeds to the next rule.
//
-// • If the values have an Equal method of the form "(T) Equal(T) bool" or
-// "(T) Equal(I) bool" where T is assignable to I, then use the result of
-// x.Equal(y) even if x or y is nil. Otherwise, no such method exists and
-// evaluation proceeds to the next rule.
+// - If the values have an Equal method of the form "(T) Equal(T) bool" or
+// "(T) Equal(I) bool" where T is assignable to I, then use the result of
+// x.Equal(y) even if x or y is nil. Otherwise, no such method exists and
+// evaluation proceeds to the next rule.
//
-// • Lastly, try to compare x and y based on their basic kinds.
-// Simple kinds like booleans, integers, floats, complex numbers, strings, and
-// channels are compared using the equivalent of the == operator in Go.
-// Functions are only equal if they are both nil, otherwise they are unequal.
+// - Lastly, try to compare x and y based on their basic kinds.
+// Simple kinds like booleans, integers, floats, complex numbers, strings,
+// and channels are compared using the equivalent of the == operator in Go.
+// Functions are only equal if they are both nil, otherwise they are unequal.
//
// Structs are equal if recursively calling Equal on all fields report equal.
// If a struct contains unexported fields, Equal panics unless an Ignore option
@@ -639,7 +639,9 @@ type dynChecker struct{ curr, next int }
// Next increments the state and reports whether a check should be performed.
//
// Checks occur every Nth function call, where N is a triangular number:
+//
// 0 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 ...
+//
// See https://en.wikipedia.org/wiki/Triangular_number
//
// This sequence ensures that the cost of checks drops significantly as
diff --git a/cmp/compare_test.go b/cmp/compare_test.go
index aafe441..dc86f01 100644
--- a/cmp/compare_test.go
+++ b/cmp/compare_test.go
@@ -43,7 +43,7 @@ var update = flag.Bool("update", false, "update golden test files")
const goldenHeaderPrefix = "<<< "
const goldenFooterPrefix = ">>> "
-/// mustParseGolden parses a file as a set of key-value pairs.
+// mustParseGolden parses a file as a set of key-value pairs.
//
// The syntax is simple and looks something like:
//
diff --git a/cmp/internal/diff/diff.go b/cmp/internal/diff/diff.go
index bc196b1..a248e54 100644
--- a/cmp/internal/diff/diff.go
+++ b/cmp/internal/diff/diff.go
@@ -127,9 +127,9 @@ var randBool = rand.New(rand.NewSource(time.Now().Unix())).Intn(2) == 0
// This function returns an edit-script, which is a sequence of operations
// needed to convert one list into the other. The following invariants for
// the edit-script are maintained:
-// • eq == (es.Dist()==0)
-// • nx == es.LenX()
-// • ny == es.LenY()
+// - eq == (es.Dist()==0)
+// - nx == es.LenX()
+// - ny == es.LenY()
//
// This algorithm is not guaranteed to be an optimal solution (i.e., one that
// produces an edit-script with a minimal Levenshtein distance). This algorithm
@@ -169,12 +169,13 @@ func Difference(nx, ny int, f EqualFunc) (es EditScript) {
// A diagonal edge is equivalent to a matching symbol between both X and Y.
// Invariants:
- // • 0 ≤ fwdPath.X ≤ (fwdFrontier.X, revFrontier.X) ≤ revPath.X ≤ nx
- // • 0 ≤ fwdPath.Y ≤ (fwdFrontier.Y, revFrontier.Y) ≤ revPath.Y ≤ ny
+ // - 0 ≤ fwdPath.X ≤ (fwdFrontier.X, revFrontier.X) ≤ revPath.X ≤ nx
+ // - 0 ≤ fwdPath.Y ≤ (fwdFrontier.Y, revFrontier.Y) ≤ revPath.Y ≤ ny
//
// In general:
- // • fwdFrontier.X < revFrontier.X
- // • fwdFrontier.Y < revFrontier.Y
+ // - fwdFrontier.X < revFrontier.X
+ // - fwdFrontier.Y < revFrontier.Y
+ //
// Unless, it is time for the algorithm to terminate.
fwdPath := path{+1, point{0, 0}, make(EditScript, 0, (nx+ny)/2)}
revPath := path{-1, point{nx, ny}, make(EditScript, 0)}
@@ -195,19 +196,21 @@ func Difference(nx, ny int, f EqualFunc) (es EditScript) {
// computing sub-optimal edit-scripts between two lists.
//
// The algorithm is approximately as follows:
- // • Searching for differences switches back-and-forth between
- // a search that starts at the beginning (the top-left corner), and
- // a search that starts at the end (the bottom-right corner). The goal of
- // the search is connect with the search from the opposite corner.
- // • As we search, we build a path in a greedy manner, where the first
- // match seen is added to the path (this is sub-optimal, but provides a
- // decent result in practice). When matches are found, we try the next pair
- // of symbols in the lists and follow all matches as far as possible.
- // • When searching for matches, we search along a diagonal going through
- // through the "frontier" point. If no matches are found, we advance the
- // frontier towards the opposite corner.
- // • This algorithm terminates when either the X coordinates or the
- // Y coordinates of the forward and reverse frontier points ever intersect.
+ // - Searching for differences switches back-and-forth between
+ // a search that starts at the beginning (the top-left corner), and
+ // a search that starts at the end (the bottom-right corner).
+ // The goal of the search is connect with the search
+ // from the opposite corner.
+ // - As we search, we build a path in a greedy manner,
+ // where the first match seen is added to the path (this is sub-optimal,
+ // but provides a decent result in practice). When matches are found,
+ // we try the next pair of symbols in the lists and follow all matches
+ // as far as possible.
+ // - When searching for matches, we search along a diagonal going through
+ // through the "frontier" point. If no matches are found,
+ // we advance the frontier towards the opposite corner.
+ // - This algorithm terminates when either the X coordinates or the
+ // Y coordinates of the forward and reverse frontier points ever intersect.
// This algorithm is correct even if searching only in the forward direction
// or in the reverse direction. We do both because it is commonly observed
@@ -389,6 +392,7 @@ type point struct{ X, Y int }
func (p *point) add(dx, dy int) { p.X += dx; p.Y += dy }
// zigzag maps a consecutive sequence of integers to a zig-zag sequence.
+//
// [0 1 2 3 4 5 ...] => [0 -1 +1 -2 +2 ...]
func zigzag(x int) int {
if x&1 != 0 {
diff --git a/cmp/options.go b/cmp/options.go
index e57b9eb..e254ffd 100644
--- a/cmp/options.go
+++ b/cmp/options.go
@@ -33,6 +33,7 @@ type Option interface {
}
// applicableOption represents the following types:
+//
// Fundamental: ignore | validator | *comparer | *transformer
// Grouping: Options
type applicableOption interface {
@@ -43,6 +44,7 @@ type applicableOption interface {
}
// coreOption represents the following types:
+//
// Fundamental: ignore | validator | *comparer | *transformer
// Filters: *pathFilter | *valuesFilter
type coreOption interface {
@@ -336,9 +338,9 @@ func (tr transformer) String() string {
// both implement T.
//
// The equality function must be:
-// • Symmetric: equal(x, y) == equal(y, x)
-// • Deterministic: equal(x, y) == equal(x, y)
-// • Pure: equal(x, y) does not modify x or y
+// - Symmetric: equal(x, y) == equal(y, x)
+// - Deterministic: equal(x, y) == equal(x, y)
+// - Pure: equal(x, y) does not modify x or y
func Comparer(f interface{}) Option {
v := reflect.ValueOf(f)
if !function.IsType(v.Type(), function.Equal) || v.IsNil() {
diff --git a/cmp/path.go b/cmp/path.go
index c710034..557c7f2 100644
--- a/cmp/path.go
+++ b/cmp/path.go
@@ -41,13 +41,13 @@ type PathStep interface {
// The type of each valid value is guaranteed to be identical to Type.
//
// In some cases, one or both may be invalid or have restrictions:
- // • For StructField, both are not interface-able if the current field
- // is unexported and the struct type is not explicitly permitted by
- // an Exporter to traverse unexported fields.
- // • For SliceIndex, one may be invalid if an element is missing from
- // either the x or y slice.
- // • For MapIndex, one may be invalid if an entry is missing from
- // either the x or y map.
+ // - For StructField, both are not interface-able if the current field
+ // is unexported and the struct type is not explicitly permitted by
+ // an Exporter to traverse unexported fields.
+ // - For SliceIndex, one may be invalid if an element is missing from
+ // either the x or y slice.
+ // - For MapIndex, one may be invalid if an entry is missing from
+ // either the x or y map.
//
// The provided values must not be mutated.
Values() (vx, vy reflect.Value)
@@ -94,6 +94,7 @@ func (pa Path) Index(i int) PathStep {
// The simplified path only contains struct field accesses.
//
// For example:
+//
// MyMap.MySlices.MyField
func (pa Path) String() string {
var ss []string
@@ -108,6 +109,7 @@ func (pa Path) String() string {
// GoString returns the path to a specific node using Go syntax.
//
// For example:
+//
// (*root.MyMap["key"].(*mypkg.MyStruct).MySlices)[2][3].MyField
func (pa Path) GoString() string {
var ssPre, ssPost []string
diff --git a/cmp/report_slices.go b/cmp/report_slices.go
index 68b5c1a..21aecd9 100644
--- a/cmp/report_slices.go
+++ b/cmp/report_slices.go
@@ -171,12 +171,13 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode {
// differences in a string literal. This format is more readable,
// but has edge-cases where differences are visually indistinguishable.
// This format is avoided under the following conditions:
- // • A line starts with `"""`
- // • A line starts with "..."
- // • A line contains non-printable characters
- // • Adjacent different lines differ only by whitespace
+ // - A line starts with `"""`
+ // - A line starts with "..."
+ // - A line contains non-printable characters
+ // - Adjacent different lines differ only by whitespace
//
// For example:
+ //
// """
// ... // 3 identical lines
// foo
@@ -446,7 +447,6 @@ func (opts formatOptions) formatDiffSlice(
// {NumIdentical: 3},
// {NumInserted: 1},
// ]
-//
func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats) {
var prevMode byte
lastStats := func(mode byte) *diffStats {
@@ -503,7 +503,6 @@ func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats)
// {NumIdentical: 8, NumRemoved: 12, NumInserted: 3},
// {NumIdentical: 63},
// ]
-//
func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStats {
groups, groupsOrig := groups[:0], groups
for i, ds := range groupsOrig {
@@ -548,7 +547,6 @@ func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStat
// {NumRemoved: 9},
// {NumIdentical: 64}, // incremented by 10
// ]
-//
func cleanupSurroundingIdentical(groups []diffStats, eq func(i, j int) bool) []diffStats {
var ix, iy int // indexes into sequence x and y
for i, ds := range groups {
diff --git a/cmp/report_text.go b/cmp/report_text.go
index 0fd46d7..388fcf5 100644
--- a/cmp/report_text.go
+++ b/cmp/report_text.go
@@ -393,6 +393,7 @@ func (s diffStats) Append(ds diffStats) diffStats {
// String prints a humanly-readable summary of coalesced records.
//
// Example:
+//
// diffStats{Name: "Field", NumIgnored: 5}.String() => "5 ignored fields"
func (s diffStats) String() string {
var ss []string