aboutsummaryrefslogtreecommitdiff
path: root/cmp/internal
AgeCommit message (Collapse)Author
2022-01-04Add //go:build lines (#285)Tobias Klauser
Starting with Go 1.17, //go:build lines are preferred over // +build lines, see https://golang.org/doc/go1.17#build-lines and https://golang.org/design/draft-gobuild for details. This change was generated by running Go 1.17 go fmt ./... which automatically adds //go:build lines based on the existing // +build lines. Also update the corresponding GitHub action to use Go 1.17 gofmt.
2021-12-07Drop hacks to work around Go reflection bugs in Go1.9 (#282)Joe Tsai
Now that Go 1.11 is the minimally supported version, we can drop some local hacks to work around bugs in reflect that were present in Go1.9.
2021-10-12Use any alias instead of interface{} (#276)Joe Tsai
See golang/go#33232.
2020-11-24Fix non-determinism in diffing algorithm (#247)Joe Tsai
A previous attempt to add non-determinism to the diffing algorithm unfortunately broke the algorithm for half the cases. This change modifies the algorithm to truly switch between starting with a forward search versus a reverse search. The main for-loop of Difference would switch repeatedly between performing a forward search, then a reverse search, and vice-versa. Since we can't jump into the middle of a for-loop to start with the reverse search first, we use a series of labels and goto statements to accomplish the same effect. Fixes #238
2020-11-12Revert "Adjust for reflect.Type.NumMethod change in Go1.16 (#240)" (#242)Joe Tsai
This reverts commit ab46b8bd0abd4c4557cc4709ad7ae12d47570603. The upstream change in Go1.16 has been rolled back. See golang/go#42123
2020-10-20Adjust for reflect.Type.NumMethod change in Go1.16 (#240)Joe Tsai
In Go1.16, the reflect.Type.NumMethod method will no longer report unexported fields, matching the documented behavior on the method. This means that t.NumMethod() == 0 is no longer a reliable means to detect whether an interface type is the empty interface or not. Fix the code to check whether the empty interface itself implements the target type.
2020-09-23Fix license headers (#236)Joe Tsai
There is no LICENSE.md file, but there is a LICENSE file.
2020-06-17Improve reporting of values with cycles (#217)Joe Tsai
Previously, the reporter could handle formatting values with cycles in that it did not crash with a stack overflow. However, the output was not particularly understandable as it did not surface to the user why a particular value was truncated, and if it was truncated due to a cyclic reference, what was the referent. This change annotates the reporter tree with pointer information so that a later pass can inject reference information if it is needed to produce more understandable output. Consider the following example: map[string]*cmp_test.CycleAlpha{ "Foo": &⟪ref#0⟫{ Name: "Foo", Bravos: map[string]*cmp_test.CycleBravo{ "FooBravo": &{ - ID: 101, + ID: 0, Name: "FooBravo", Mods: 100, Alphas: {"Foo": &⟪ref#0⟫(...)}, }, }, }, } This graph contains a cycle. To ensure that a graph can be formatted, the cycle is truncated as indicated with: &⟪ref#0⟫(...). The referent was identified earlier with: &⟪ref#0⟫{...}.
2020-06-12Disambiguate reporter output (#216)Joe Tsai
The reporter tries to aggresively elide data that is not interesting to the user. However, doing so many result in an output that does not visually indicate the difference between semantically different objects. This CL modifies the reporter to try increasingly verbose presets until two different objects are formatted differently. This CL includes a custom implementation of reflect.Type.String that can print the type with fully qualified names to disambiguate types that happen to have the same base package name. Fixes #194
2020-06-10Introduce deliberate instability to difference output (#214)Joe Tsai
The reporter output is documented as unstable. The API for custom reporters also specifies that the diffing of slices is unstable. Introduce deliberate instability to the diffing algorithm so that we have the flexibility to improve it in the future. The current algorithm optimizes for speed, rather than optimality, so there is much room for improvement.
2019-08-05cmp/internal/value: fix handling of negative zero for floats (#152)Joe Tsai
* Fix IsZero to properly report false for IsZero(-0.0) since we define IsZero as whether it is equal to the zero memory value. * Add note to isLess that we don't need to handle -0.0 since we can't possibly have both keys present in the same map. * Use sort.SliceStable in SortedKeys for deterministic output since it is possible to have both -0.0 and +0.0 from two different maps. The zero key from the left left map will be taken over the right map.
2019-03-11Implement specialized diffing for slices (#131)Joe Tsai
Lists of primitives are a common-enough data structure that it is worth providing specialized diffing for. This provides significantly better readability for strings and byte slices. There is also a heuristic for detecting what a string should be diffed as a multiline string.
2019-03-11Add IgnoreSliceElements and IgnoreMapEntries helpers (#126)Joe Tsai
These helper options ignore slice elements or map entries based on a user-provided predicate function. These are especially useful for ignoring missing elements or entries.
2019-03-11Implement a unified difference reporter (#124)Joe Tsai
The previous implementation of the reporter simply listed all differences, each qualified by the full path to the difference. This method of reporting is exact, but difficult for humans to parse. It is one of the more common sources of complaints by users and a significant reason why cmp is not preferred over competing libraries. This change reimplements the reporter to format the output as a structured literal in pseudo-Go syntax. The output resembles literals that the user would likely have in their test code. Differences between the x and y values are denoted by a '-' or '+' prefix at the start of the line. An overview of the new implementation is as follows: * report.go: The defaultReporter type implements the Reporter interface. * report_value: Through the PushStep/PopStep API, the defaultReporter is able to contruct an in-memory valueNode tree representing the comparison of x and y as cmp.Equal walks the sub-values. * report_compare.go: After report_value.go constructs an AST-representation of the compared values, report_compare.go formats the valueNode tree as a textNode tree, which is the textual output in a tree form. Some relevant design decisions include: * The format logic goes through effort to avoid printing ignored nodes. * Some number of surrounding equal (but not ignored) struct fields, slice elements, or map entries are printed for context. * cmp.Equal may declare two sub-reflect.Values to be equal, but are different values when printed. In order to present a unified view on this "equal" node, the logic formats both values and arbitrarily choses the one with the shorter string. * Transformed nodes are formatted with the pseudo-Go syntax of: Inverse(TransformerName, OutputType{...}) where Inverse is some magical pseudo-function that inverts the transformation referred to by TransformerName. The OutputType literal is the output of the transformation. * report_reflect.go: This contains logic to pretty-print reflect.Values and is relied upon by report_compare.go to format the leaves of the tree. Note that the leaves of the tree can be any arbitrary Go type and value (including cyclic data structures). * report_text.go: This contains logic for purely lexicographical formatting and is depended upon by the other report_*.go files. Advantages: * The output is more familiar as it uses pseudo-Go syntax for literals * It provides context about surrounding struct fields, slice elements, or map entries that were equal * Inserted and removed elements in a slice are easier to visualize * Related diffs lie on the same indentation * For diffs in a deeply nested value, the output is easier to visualize than having a list of all the full paths to the diff. Disadvantages: * The implementation is drastically more complex. * In most cases, the output is longer (though more sparse)
2019-02-25Rename {NDiff,NSame} as {NumDiff,NumSame} (#118)Joe Tsai
2019-02-16Move function name logic to function package (#106)Joe Tsai
Adjust the logic of NameOf for more recent versions of Go.
2019-02-14Make debug mode more explicit (#105)Joe Tsai
Switch the build tag for debugging from "debug" to "cmp_debug". The former tag accidentally matches usages of that tag for unrelated projects. Fixes #104
2018-11-01Bump minimum version to Go1.8 (#50)Joe Tsai
Go1.8 went GA on AppEngine. The lack of Go1.8 support was the primary reason for much of these backwards compatibility hacks. Bumping to Go1.8 still ensures that we're supporting at least the latest 2 versions of Go, which are Go1.8 and Go1.9.
2018-03-28Fix cycle detection in internal/value.Format (#87)Joe Tsai
The cycle detection in value.Format uses a map of uintptrs, which is not correct as this assumes that the Go GC never uses a moving collector. Instead, we should be using unsafe.Pointer, which the GC knows how to scan. Also, push pointer checking of slices down to the level of individual elements. We do this because the slice pointer is not sufficient to determine equality. For example, v[:0] and v[:1] both have the same slice pointer, but are clearly different values. Since the purego environment forbids the use of unsafe, create a Pointer type that is an abstraction over an opaque pointer. The Pointer type can only be compared. In the purego, continue to use uintptr, which is the best we can do.
2018-01-03Report with primitive types in diffs (#65)Joe Tsai
When the formatted strings are identical, the reporter tries to fallback on more exact formatting. This fallback should include the types for primitive types since the difference can simply be between an int and an uint. Fixes #64
2017-12-15Adjust Travis CI script (#60)Joe Tsai
Rather than running gofmt for every version, leading to version skew when what gofmt considers "correct" differs between versions, only use one specific version of gofmt. Also, remove the "-s" flag from gofmt because it is not backwards compatible. Suppose Go1.11 allowed for elliding types on struct literals and the "-s" flag strips them, then this would be problematic because it would not compile on Go1.10 and earlier. Also, fix the code so that vet is happy. I am not sure why these checks were not triggered before. There seems to be a bug in the caching of $GOPATH/pkg files. This may be fixed in Go1.10 by the new caching logic. Running "go install" before running go vet fixes the issue. In other words, the only check we perform for differing versions is that the tests pass (and implicitly that it builds).
2017-12-07Fix trivial spelling mistake (#57)Joe Tsai
2017-11-23Fix some typos in comments and readme (#54)ferhat elmas
2017-10-03Adjust heuristics for using raw literals (#48)Joe Tsai
Rather than searching for escape sequences, a better measure of whether to use raw literals or not is whether the raw literal form is shorter than the quoted string encoding. The assumption is that shorter string length is more readable, which is a reasonable (except for non-printable characters).
2017-09-28Use raw literal for string formatting (#46)Joe Tsai
When formatting strings, avoid using strconv.Quote if the string looks like it has already been escaped. Instead, use a raw string literal by wrapping the string with '`' characters if possible. For now, we still use strconv.Quote if the input string contains newlines to maintain the property that Format outputs a single line. Also, prefix strings obtained by the Stringer.String method with a 's'. This allows users to more easily distinguish when an output really is of type string or if the String method was used.
2017-09-28Change diff.Difference to always return an edit-script (#45)Joe Tsai
Rather than performing the heuristic for whether two slices are "too different" in the diff package, just return the full edit-script and move the heuristic logic into the cmp package. The main adjustment to the heuristic is that we only print the full slice if it is composed of a slice of primitive types (e.g., []byte) and the difference between the two slices is sufficiently great enough. Fixes #44
2017-09-27Test unexported field access in format logic (#41)Joe Tsai
The format logic should work even if the reflect.Value is in RO mode.
2017-09-01Fix panic in sort.go (#39)Joe Tsai
Avoid using reflect.Value.Interface to de-duplicate keys since some keys may have source from an unexported field, causing the logic to panic. Instead, just rely on the isLess function, which is already safe to use on unexported values. Fixes #38
2017-08-02Add cmp/internal/function package (#35)Joe Tsai
Unify the common logic for identifying the type of function. This logic is helpful since Go lacks generics, so it is hard to query whether a function is of the signature: func(T, T) bool
2017-08-01Check Value.CanInterface before trying to use fmt.Stringer (#33)Joe Tsai
2017-07-28Fix bug with nil fmt.Stringers (#30)mattdee123
2017-07-25Trivial documentation fixes for cmp/internal/value (#27)Joe Tsai
2017-07-25Trivial style changes to cmp/internal/value tests (#25)Joe Tsai
2017-07-20Move general reflect logic to internal/value (#15)Joe Tsai
This internal package has the API: Format(reflect.Value, useStringer bool) string SortKeys(vs []reflect.Value) []reflect.Value While moving Format and SortKeys, we also tweak the formatting logic to print the type on named primitive types.
2017-07-20Add diffing abilities to reporting (#9)Joe Tsai
This adds an internal package with the following API: func Difference(nx, ny int, f EqualFunc) (eq bool, es EditScript) type EditScript []EditType type EditType int8 const Identity EditType = iota ... type EqualFunc func(ix int, iy int) Result type Result struct{ ... } The cmp.SliceIndex type has a new method SplitKeys to indicate that elements are being compared in x and y are in different indexes. The debug visualizer can be run: go test -tags=debug -v github.com/google/go-cmp/cmp/internal/diff Reviewed-By: kevlar@google.com
2017-07-07Add package cmp for performing equality of Go valuesJoe Tsai
The API of the package is as follows: func Equal(x, y interface{}, opts ...Option) bool func Diff(x, y interface{}, opts ...Option) string type Option interface{ ... } func Ignore() Option func Comparer(f interface{}) Option func Transformer(name string, f interface{}) Option func FilterPath(f func(Path) bool, opt Option) Option func FilterValues(f interface{}, opt Option) Option func AllowUnexported(typs ...interface{}) Option type Options []Option type Path []PathStep type PathStep interface{ ... } type Indirect interface{ ... } type StructField interface{ ... } type MapIndex interface{ ... } type SliceIndex interface{ ... } type TypeAssertion interface{ ... } type Transform interface{ ... } See the package docs in compare.go for a high-level view of this package.