~ubuntu-branches/ubuntu/trusty/juju-core/trusty

« back to all changes in this revision

Viewing changes to src/launchpad.net/juju-core/testing/checkers/deepequal.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-03-24 16:05:44 UTC
  • mfrom: (1.1.20)
  • Revision ID: package-import@ubuntu.com-20140324160544-g8lsfufby18d5fj4
Tags: 1.17.6-0ubuntu1
* New upstream point release, including fixes for:
  - br0 not bought up by cloud-init with MAAS provider (LP: #1271144).
  - ppc64el enablement for juju/lxc (LP: #1273769).
  - juju userdata should not restart networking (LP: #1248283).
  - error detecting hardware characteristics (LP: #1276909).
  - juju instances not including the default security group (LP: #1129720).
  - juju bootstrap does not honor https_proxy (LP: #1240260).
* d/control,rules: Drop BD on bash-completion, install bash-completion
  direct from upstream source code.
* d/rules: Set HOME prior to generating man pages.
* d/control: Drop alternative dependency on mongodb-server; juju now only
  works on trusty with juju-mongodb.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copied with small adaptations from the reflect package in the
2
 
// Go source tree.
3
 
 
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.
7
 
 
8
 
package checkers
9
 
 
10
 
import (
11
 
        "fmt"
12
 
        "reflect"
13
 
        "unsafe"
14
 
)
15
 
 
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.
20
 
type visit struct {
21
 
        a1  uintptr
22
 
        a2  uintptr
23
 
        typ reflect.Type
24
 
}
25
 
 
26
 
type mismatchError struct {
27
 
        v1, v2 reflect.Value
28
 
        path   string
29
 
        how    string
30
 
}
31
 
 
32
 
func (err *mismatchError) Error() string {
33
 
        path := err.path
34
 
        if path == "" {
35
 
                path = "top level"
36
 
        }
37
 
        return fmt.Sprintf("mismatch at %s: %s; obtained %#v; expected %#v", path, err.how, interfaceOf(err.v1), interfaceOf(err.v2))
38
 
}
39
 
 
40
 
// Tests for deep equality using reflected types. The map argument tracks
41
 
// comparisons that have already been seen, which allows short circuiting on
42
 
// recursive types.
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{
46
 
                        v1:   v1,
47
 
                        v2:   v2,
48
 
                        path: path,
49
 
                        how:  fmt.Sprintf(f, a...),
50
 
                }
51
 
        }
52
 
        if !v1.IsValid() || !v2.IsValid() {
53
 
                if v1.IsValid() == v2.IsValid() {
54
 
                        return true, nil
55
 
                }
56
 
                return false, errorf("validity mismatch")
57
 
        }
58
 
        if v1.Type() != v2.Type() {
59
 
                return false, errorf("type mismatch %s vs %s", v1.Type(), v2.Type())
60
 
        }
61
 
 
62
 
        // if depth > 10 { panic("deepValueEqual") }    // for debugging
63
 
        hard := func(k reflect.Kind) bool {
64
 
                switch k {
65
 
                case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct:
66
 
                        return true
67
 
                }
68
 
                return false
69
 
        }
70
 
 
71
 
        if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
72
 
                addr1 := v1.UnsafeAddr()
73
 
                addr2 := v2.UnsafeAddr()
74
 
                if addr1 > addr2 {
75
 
                        // Canonicalize order to reduce number of entries in visited.
76
 
                        addr1, addr2 = addr2, addr1
77
 
                }
78
 
 
79
 
                // Short circuit if references are identical ...
80
 
                if addr1 == addr2 {
81
 
                        return true, nil
82
 
                }
83
 
 
84
 
                // ... or already seen
85
 
                typ := v1.Type()
86
 
                v := visit{addr1, addr2, typ}
87
 
                if visited[v] {
88
 
                        return true, nil
89
 
                }
90
 
 
91
 
                // Remember for later.
92
 
                visited[v] = true
93
 
        }
94
 
 
95
 
        switch v1.Kind() {
96
 
        case reflect.Array:
97
 
                if v1.Len() != v2.Len() {
98
 
                        // can't happen!
99
 
                        return false, errorf("length mismatch, %d vs %d", v1.Len(), v2.Len())
100
 
                }
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 {
105
 
                                return false, err
106
 
                        }
107
 
                }
108
 
                return true, nil
109
 
        case reflect.Slice:
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())
113
 
                }
114
 
                if v1.Pointer() == v2.Pointer() {
115
 
                        return true, nil
116
 
                }
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 {
121
 
                                return false, err
122
 
                        }
123
 
                }
124
 
                return true, nil
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")
129
 
                        }
130
 
                        return true, nil
131
 
                }
132
 
                return deepValueEqual(path, v1.Elem(), v2.Elem(), visited, depth+1)
133
 
        case reflect.Ptr:
134
 
                return deepValueEqual("(*"+path+")", v1.Elem(), v2.Elem(), visited, depth+1)
135
 
        case reflect.Struct:
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 {
139
 
                                return false, err
140
 
                        }
141
 
                }
142
 
                return true, nil
143
 
        case reflect.Map:
144
 
                if v1.IsNil() != v2.IsNil() {
145
 
                        return false, errorf("nil vs non-nil mismatch")
146
 
                }
147
 
                if v1.Len() != v2.Len() {
148
 
                        return false, errorf("length mismatch, %d vs %d", v1.Len(), v2.Len())
149
 
                }
150
 
                if v1.Pointer() == v2.Pointer() {
151
 
                        return true, nil
152
 
                }
153
 
                for _, k := range v1.MapKeys() {
154
 
                        var p string
155
 
                        if k.CanInterface() {
156
 
                                p = path + "[" + fmt.Sprintf("%#v", k.Interface()) + "]"
157
 
                        } else {
158
 
                                p = path + "[someKey]"
159
 
                        }
160
 
                        if ok, err := deepValueEqual(p, v1.MapIndex(k), v2.MapIndex(k), visited, depth+1); !ok {
161
 
                                return false, err
162
 
                        }
163
 
                }
164
 
                return true, nil
165
 
        case reflect.Func:
166
 
                if v1.IsNil() && v2.IsNil() {
167
 
                        return true, nil
168
 
                }
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")
174
 
                }
175
 
                return true, nil
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")
179
 
                }
180
 
                return true, nil
181
 
        case reflect.Float32, reflect.Float64:
182
 
                if v1.Float() != v2.Float() {
183
 
                        return false, errorf("unequal")
184
 
                }
185
 
                return true, nil
186
 
        case reflect.Complex64, reflect.Complex128:
187
 
                if v1.Complex() != v2.Complex() {
188
 
                        return false, errorf("unequal")
189
 
                }
190
 
                return true, nil
191
 
        case reflect.Bool:
192
 
                if v1.Bool() != v2.Bool() {
193
 
                        return false, errorf("unequal")
194
 
                }
195
 
                return true, nil
196
 
        case reflect.String:
197
 
                if v1.String() != v2.String() {
198
 
                        return false, errorf("unequal")
199
 
                }
200
 
                return true, nil
201
 
        case reflect.Chan, reflect.UnsafePointer:
202
 
                if v1.Pointer() != v2.Pointer() {
203
 
                        return false, errorf("unequal")
204
 
                }
205
 
                return true, nil
206
 
        default:
207
 
                panic("unexpected type " + v1.Type().String())
208
 
        }
209
 
}
210
 
 
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.
216
 
//
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),
225
 
                        path: "",
226
 
                        how:  fmt.Sprintf(f, a...),
227
 
                }
228
 
        }
229
 
        if a1 == nil || a2 == nil {
230
 
                if a1 == a2 {
231
 
                        return true, nil
232
 
                }
233
 
                return false, errorf("nil vs non-nil mismatch")
234
 
        }
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())
239
 
        }
240
 
        return deepValueEqual("", v1, v2, make(map[visit]bool), 0)
241
 
}
242
 
 
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{} {
247
 
        if !v.IsValid() {
248
 
                return nil
249
 
        }
250
 
        return bypassCanInterface(v).Interface()
251
 
}
252
 
 
253
 
type flag uintptr
254
 
 
255
 
// copied from reflect/value.go
256
 
const (
257
 
        flagRO flag = 1 << iota
258
 
)
259
 
 
260
 
var flagValOffset = func() uintptr {
261
 
        field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
262
 
        if !ok {
263
 
                panic("reflect.Value has no flag field")
264
 
        }
265
 
        return field.Offset
266
 
}()
267
 
 
268
 
func flagField(v *reflect.Value) *flag {
269
 
        return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
270
 
}
271
 
 
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() {
276
 
                return v
277
 
        }
278
 
        *flagField(&v) &^= flagRO
279
 
        return v
280
 
}
281
 
 
282
 
// Sanity checks against future reflect package changes
283
 
// to the type or semantics of the Value.flag field.
284
 
func init() {
285
 
        field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
286
 
        if !ok {
287
 
                panic("reflect.Value has no flag field")
288
 
        }
289
 
        if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
290
 
                panic("reflect.Value flag field has changed kind")
291
 
        }
292
 
        var t struct {
293
 
                a int
294
 
                A int
295
 
        }
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")
302
 
        }
303
 
}