1
// Copied with small adaptations from the reflect package in the
4
// Copyright 2009 The Go Authors. All rights reserved.
5
// Use of this source code is governed by a BSD-style
6
// license that can be found in the LICENSE file.
16
// During deepValueEqual, must keep track of checks that are
17
// in progress. The comparison algorithm assumes that all
18
// checks in progress are true when it reencounters them.
19
// Visited comparisons are stored in a map indexed by visit.
26
type mismatchError struct {
32
func (err *mismatchError) Error() string {
37
return fmt.Sprintf("mismatch at %s: %s; obtained %#v; expected %#v", path, err.how, interfaceOf(err.v1), interfaceOf(err.v2))
40
// Tests for deep equality using reflected types. The map argument tracks
41
// comparisons that have already been seen, which allows short circuiting on
43
func deepValueEqual(path string, v1, v2 reflect.Value, visited map[visit]bool, depth int) (ok bool, err error) {
44
errorf := func(f string, a ...interface{}) error {
45
return &mismatchError{
49
how: fmt.Sprintf(f, a...),
52
if !v1.IsValid() || !v2.IsValid() {
53
if v1.IsValid() == v2.IsValid() {
56
return false, errorf("validity mismatch")
58
if v1.Type() != v2.Type() {
59
return false, errorf("type mismatch %s vs %s", v1.Type(), v2.Type())
62
// if depth > 10 { panic("deepValueEqual") } // for debugging
63
hard := func(k reflect.Kind) bool {
65
case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct:
71
if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
72
addr1 := v1.UnsafeAddr()
73
addr2 := v2.UnsafeAddr()
75
// Canonicalize order to reduce number of entries in visited.
76
addr1, addr2 = addr2, addr1
79
// Short circuit if references are identical ...
84
// ... or already seen
86
v := visit{addr1, addr2, typ}
91
// Remember for later.
97
if v1.Len() != v2.Len() {
99
return false, errorf("length mismatch, %d vs %d", v1.Len(), v2.Len())
101
for i := 0; i < v1.Len(); i++ {
102
if ok, err := deepValueEqual(
103
fmt.Sprintf("%s[%d]", path, i),
104
v1.Index(i), v2.Index(i), visited, depth+1); !ok {
110
// We treat a nil slice the same as an empty slice.
111
if v1.Len() != v2.Len() {
112
return false, errorf("length mismatch, %d vs %d", v1.Len(), v2.Len())
114
if v1.Pointer() == v2.Pointer() {
117
for i := 0; i < v1.Len(); i++ {
118
if ok, err := deepValueEqual(
119
fmt.Sprintf("%s[%d]", path, i),
120
v1.Index(i), v2.Index(i), visited, depth+1); !ok {
125
case reflect.Interface:
126
if v1.IsNil() || v2.IsNil() {
127
if v1.IsNil() != v2.IsNil() {
128
return false, fmt.Errorf("nil vs non-nil interface mismatch")
132
return deepValueEqual(path, v1.Elem(), v2.Elem(), visited, depth+1)
134
return deepValueEqual("(*"+path+")", v1.Elem(), v2.Elem(), visited, depth+1)
136
for i, n := 0, v1.NumField(); i < n; i++ {
137
path := path + "." + v1.Type().Field(i).Name
138
if ok, err := deepValueEqual(path, v1.Field(i), v2.Field(i), visited, depth+1); !ok {
144
if v1.IsNil() != v2.IsNil() {
145
return false, errorf("nil vs non-nil mismatch")
147
if v1.Len() != v2.Len() {
148
return false, errorf("length mismatch, %d vs %d", v1.Len(), v2.Len())
150
if v1.Pointer() == v2.Pointer() {
153
for _, k := range v1.MapKeys() {
155
if k.CanInterface() {
156
p = path + "[" + fmt.Sprintf("%#v", k.Interface()) + "]"
158
p = path + "[someKey]"
160
if ok, err := deepValueEqual(p, v1.MapIndex(k), v2.MapIndex(k), visited, depth+1); !ok {
166
if v1.IsNil() && v2.IsNil() {
169
// Can't do better than this:
170
return false, errorf("non-nil functions")
171
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
172
if v1.Int() != v2.Int() {
173
return false, errorf("unequal")
176
case reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
177
if v1.Uint() != v2.Uint() {
178
return false, errorf("unequal")
181
case reflect.Float32, reflect.Float64:
182
if v1.Float() != v2.Float() {
183
return false, errorf("unequal")
186
case reflect.Complex64, reflect.Complex128:
187
if v1.Complex() != v2.Complex() {
188
return false, errorf("unequal")
192
if v1.Bool() != v2.Bool() {
193
return false, errorf("unequal")
197
if v1.String() != v2.String() {
198
return false, errorf("unequal")
201
case reflect.Chan, reflect.UnsafePointer:
202
if v1.Pointer() != v2.Pointer() {
203
return false, errorf("unequal")
207
panic("unexpected type " + v1.Type().String())
211
// DeepEqual tests for deep equality. It uses normal == equality where
212
// possible but will scan elements of arrays, slices, maps, and fields
213
// of structs. In maps, keys are compared with == but elements use deep
214
// equality. DeepEqual correctly handles recursive types. Functions are
215
// equal only if they are both nil.
217
// DeepEqual differs from reflect.DeepEqual in that an empty slice is
218
// equal to a nil slice. If the two values compare unequal, the
219
// resulting error holds the first difference encountered.
220
func DeepEqual(a1, a2 interface{}) (bool, error) {
221
errorf := func(f string, a ...interface{}) error {
222
return &mismatchError{
223
v1: reflect.ValueOf(a1),
224
v2: reflect.ValueOf(a2),
226
how: fmt.Sprintf(f, a...),
229
if a1 == nil || a2 == nil {
233
return false, errorf("nil vs non-nil mismatch")
235
v1 := reflect.ValueOf(a1)
236
v2 := reflect.ValueOf(a2)
237
if v1.Type() != v2.Type() {
238
return false, errorf("type mismatch %s vs %s", v1.Type(), v2.Type())
240
return deepValueEqual("", v1, v2, make(map[visit]bool), 0)
243
// interfaceOf returns v.Interface() even if v.CanInterface() == false.
244
// This enables us to call fmt.Printf on a value even if it's derived
245
// from inside an unexported field.
246
func interfaceOf(v reflect.Value) interface{} {
250
return bypassCanInterface(v).Interface()
255
// copied from reflect/value.go
257
flagRO flag = 1 << iota
260
var flagValOffset = func() uintptr {
261
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
263
panic("reflect.Value has no flag field")
268
func flagField(v *reflect.Value) *flag {
269
return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
272
// bypassCanInterface returns a version of v that
273
// bypasses the CanInterface check.
274
func bypassCanInterface(v reflect.Value) reflect.Value {
275
if !v.IsValid() || v.CanInterface() {
278
*flagField(&v) &^= flagRO
282
// Sanity checks against future reflect package changes
283
// to the type or semantics of the Value.flag field.
285
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
287
panic("reflect.Value has no flag field")
289
if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
290
panic("reflect.Value flag field has changed kind")
296
vA := reflect.ValueOf(t).FieldByName("A")
297
va := reflect.ValueOf(t).FieldByName("a")
298
flagA := *flagField(&vA)
299
flaga := *flagField(&va)
300
if flagA&flagRO != 0 || flaga&flagRO == 0 {
301
panic("reflect.Value read-only flag has changed value")