Source File
compare.go
Belonging Package
github.com/google/go-cmp/cmp
package cmp
import (
)
if len(.reporters) == 0 {
.compareAny(rootStep(, ))
if .result.Equal() {
return ""
}
.result = diff.Result{} // Reset results
}
:= new(defaultReporter)
.reporters = append(.reporters, reporter{})
.compareAny(rootStep(, ))
:= .String()
if ( == "") != .result.Equal() {
panic("inconsistent difference and equality results")
}
return
}
:= &state{opts: Options{validator{}}}
.curPtrs.Init()
.processOption(Options())
return
}
func ( *state) ( Option) {
switch opt := .(type) {
case nil:
case Options:
for , := range {
.()
}
case coreOption:
type interface {
() bool
}
if , := .(); && !.() {
panic(fmt.Sprintf("cannot use an unfiltered option: %v", ))
}
.opts = append(.opts, )
case exporter:
.exporters = append(.exporters, )
case reporter:
.reporters = append(.reporters, )
default:
panic(fmt.Sprintf("unknown option %T", ))
}
}
if .tryOptions(, , ) {
return
}
if .tryMethod(, , ) {
return
}
switch .Kind() {
case reflect.Bool:
.report(.Bool() == .Bool(), 0)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
.report(.Int() == .Int(), 0)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
.report(.Uint() == .Uint(), 0)
case reflect.Float32, reflect.Float64:
.report(.Float() == .Float(), 0)
case reflect.Complex64, reflect.Complex128:
.report(.Complex() == .Complex(), 0)
case reflect.String:
.report(.String() == .String(), 0)
case reflect.Chan, reflect.UnsafePointer:
.report(.Pointer() == .Pointer(), 0)
case reflect.Func:
.report(.IsNil() && .IsNil(), 0)
case reflect.Struct:
.compareStruct(, , )
case reflect.Slice, reflect.Array:
.compareSlice(, , )
case reflect.Map:
.compareMap(, , )
case reflect.Ptr:
.comparePtr(, , )
case reflect.Interface:
.compareInterface(, , )
default:
panic(fmt.Sprintf("%v kind not handled", .Kind()))
}
}
, := .MethodByName("Equal")
if ! || !function.IsType(.Type, function.EqualAssignable) {
return false
}
:= .callTTBFunc(.Func, , )
.report(, reportByMethod)
return true
}
func ( *state) (, reflect.Value, Transform) reflect.Value {
= sanitizeValue(, .Type().In(0))
if !.dynChecker.Next() {
return .Call([]reflect.Value{})[0]
}
if .vx, .vy = , ; !.statelessCompare().Equal() {
return
}
panic(fmt.Sprintf("non-deterministic function detected: %s", function.NameOf()))
}
return
}
func ( *state) (, , reflect.Value) bool {
= sanitizeValue(, .Type().In(0))
= sanitizeValue(, .Type().In(1))
if !.dynChecker.Next() {
return .Call([]reflect.Value{, })[0].Bool()
}
:= make(chan reflect.Value)
go detectRaces(, , , )
:= <-
:= .Call([]reflect.Value{, })[0].Bool()
if !.IsValid() || .Bool() != {
panic(fmt.Sprintf("non-deterministic or non-symmetric function detected: %s", function.NameOf()))
}
return
}
func ( chan<- reflect.Value, reflect.Value, ...reflect.Value) {
var reflect.Value
defer func() {
recover() // Ignore panics, let the other call to f panic instead
<-
}()
= .Call()[0]
}
if !flags.AtLeastGo110 {
if .Kind() == reflect.Interface && .IsNil() && .Type() != {
return reflect.New().Elem()
}
}
return
}
func ( *state) ( reflect.Type, , reflect.Value) {
var bool
var , reflect.Value // Addressable versions of vx and vy
var , bool
:= StructField{&structField{}}
for := 0; < .NumField(); ++ {
.typ = .Field().Type
.vx = .Field()
.vy = .Field()
.name = .Field().Name
.idx =
.unexported = !isExported(.name)
if .unexported {
if .name == "_" {
continue
= .CanAddr() || .CanAddr()
= makeAddressable()
= makeAddressable()
}
if ! {
for , := range .exporters {
= || ()
}
= true
}
.mayForce =
.paddr =
.pvx =
.pvy =
.field = .Field()
}
.compareAny()
}
}
func ( *state) ( reflect.Type, , reflect.Value) {
:= .Kind() == reflect.Slice
if && (.IsNil() || .IsNil()) {
.report(.IsNil() && .IsNil(), 0)
return
}
:= diff.Difference(len(), len(), func(, int) diff.Result {
return .statelessCompare(([], []))
})
var , int
for < .Len() || < .Len() {
var diff.EditType
switch {
case < len() && []:
= diff.UniqueX
case < len() && []:
= diff.UniqueY
default:
, = [0], [1:]
}
switch {
case diff.UniqueX:
.compareAny((, -1))
++
case diff.UniqueY:
.compareAny((-1, ))
++
default:
.compareAny((, ))
++
++
}
}
}
func ( *state) ( reflect.Type, , reflect.Value) {
if .IsNil() || .IsNil() {
.report(.IsNil() && .IsNil(), 0)
return
}
if , := .curPtrs.Push(, ); {
.report(, reportByCycle)
return
}
defer .curPtrs.Pop(, )
, = .Elem(), .Elem()
.compareAny(Indirect{&indirect{pathStep{.Elem(), , }}})
}
func ( *state) ( reflect.Type, , reflect.Value) {
if .IsNil() || .IsNil() {
.report(.IsNil() && .IsNil(), 0)
return
}
, = .Elem(), .Elem()
if .Type() != .Type() {
.report(false, 0)
return
}
.compareAny(TypeAssertion{&typeAssertion{pathStep{.Type(), , }}})
}
func ( *state) ( bool, resultFlags) {
if &reportByIgnore == 0 {
if {
.result.NumSame++
|= reportEqual
} else {
.result.NumDiff++
|= reportUnequal
}
}
for , := range .reporters {
.Report(Result{flags: })
}
}
type recChecker struct{ next int }
var []string
:= map[Option]int{}
for , := range {
if , := .(Transform); {
:= .Option()
if [] == 1 { // Transformer was used exactly once before
:= .(*transformer).fnc.Type()
= append(, fmt.Sprintf("%v: %v => %v", , .In(0), .Out(0)))
}
[]++
}
}
if len() > 0 {
const = "recursive set of Transformers detected"
const = "consider using cmpopts.AcyclicTransformer"
:= strings.Join(, "\n\t")
panic(fmt.Sprintf("%s:\n\t%s\n%s", , , ))
}
}
type dynChecker struct{ curr, next int }
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |