1 // Copyright 2017, The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
16 "github.com/google/go-cmp/cmp"
19 // TODO: Re-write these examples in terms of how you actually use the
20 // fundamental options and filters and not in terms of what cool things you can
21 // do with them since that overlaps with cmp/cmpopts.
23 // Use Diff to print out a human-readable report of differences for tests
24 // comparing nested or structured data.
25 func ExampleDiff_testing() {
26 // Let got be the hypothetical value obtained from some logic under test
27 // and want be the expected golden data.
28 got, want := MakeGatewayInfo()
30 if diff := cmp.Diff(want, got); diff != "" {
31 t.Errorf("MakeGatewayInfo() mismatch (-want +got):\n%s", diff)
35 // MakeGatewayInfo() mismatch (-want +got):
37 // SSID: "CoffeeShopWiFi",
38 // - IPAddress: s"192.168.0.2",
39 // + IPAddress: s"192.168.0.1",
40 // NetMask: {0xff, 0xff, 0x00, 0x00},
41 // Clients: []cmp_test.Client{
42 // ... // 2 identical elements
43 // {Hostname: "macchiato", IPAddress: s"192.168.0.153", LastSeen: s"2009-11-10 23:39:43 +0000 UTC"},
44 // {Hostname: "espresso", IPAddress: s"192.168.0.121"},
47 // - IPAddress: s"192.168.0.221",
48 // + IPAddress: s"192.168.0.219",
49 // LastSeen: s"2009-11-10 23:00:23 +0000 UTC",
52 // + Hostname: "americano",
53 // + IPAddress: s"192.168.0.188",
54 // + LastSeen: s"2009-11-10 23:03:05 +0000 UTC",
60 // Approximate equality for floats can be handled by defining a custom
61 // comparer on floats that determines two values to be equal if they are within
62 // some range of each other.
64 // This example is for demonstrative purposes; use cmpopts.EquateApprox instead.
65 func ExampleOption_approximateFloats() {
66 // This Comparer only operates on float64.
67 // To handle float32s, either define a similar function for that type
68 // or use a Transformer to convert float32s into float64s.
69 opt := cmp.Comparer(func(x, y float64) bool {
70 delta := math.Abs(x - y)
71 mean := math.Abs(x+y) / 2.0
72 return delta/mean < 0.00001
75 x := []float64{1.0, 1.1, 1.2, math.Pi}
76 y := []float64{1.0, 1.1, 1.2, 3.14159265359} // Accurate enough to Pi
77 z := []float64{1.0, 1.1, 1.2, 3.1415} // Diverges too far from Pi
79 fmt.Println(cmp.Equal(x, y, opt))
80 fmt.Println(cmp.Equal(y, z, opt))
81 fmt.Println(cmp.Equal(z, x, opt))
89 // Normal floating-point arithmetic defines == to be false when comparing
90 // NaN with itself. In certain cases, this is not the desired property.
92 // This example is for demonstrative purposes; use cmpopts.EquateNaNs instead.
93 func ExampleOption_equalNaNs() {
94 // This Comparer only operates on float64.
95 // To handle float32s, either define a similar function for that type
96 // or use a Transformer to convert float32s into float64s.
97 opt := cmp.Comparer(func(x, y float64) bool {
98 return (math.IsNaN(x) && math.IsNaN(y)) || x == y
101 x := []float64{1.0, math.NaN(), math.E, -0.0, +0.0}
102 y := []float64{1.0, math.NaN(), math.E, -0.0, +0.0}
103 z := []float64{1.0, math.NaN(), math.Pi, -0.0, +0.0} // Pi constant instead of E
105 fmt.Println(cmp.Equal(x, y, opt))
106 fmt.Println(cmp.Equal(y, z, opt))
107 fmt.Println(cmp.Equal(z, x, opt))
115 // To have floating-point comparisons combine both properties of NaN being
116 // equal to itself and also approximate equality of values, filters are needed
117 // to restrict the scope of the comparison so that they are composable.
119 // This example is for demonstrative purposes;
120 // use cmpopts.EquateNaNs and cmpopts.EquateApprox instead.
121 func ExampleOption_equalNaNsAndApproximateFloats() {
122 alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
125 // This option declares that a float64 comparison is equal only if
126 // both inputs are NaN.
127 cmp.FilterValues(func(x, y float64) bool {
128 return math.IsNaN(x) && math.IsNaN(y)
131 // This option declares approximate equality on float64s only if
132 // both inputs are not NaN.
133 cmp.FilterValues(func(x, y float64) bool {
134 return !math.IsNaN(x) && !math.IsNaN(y)
135 }, cmp.Comparer(func(x, y float64) bool {
136 delta := math.Abs(x - y)
137 mean := math.Abs(x+y) / 2.0
138 return delta/mean < 0.00001
142 x := []float64{math.NaN(), 1.0, 1.1, 1.2, math.Pi}
143 y := []float64{math.NaN(), 1.0, 1.1, 1.2, 3.14159265359} // Accurate enough to Pi
144 z := []float64{math.NaN(), 1.0, 1.1, 1.2, 3.1415} // Diverges too far from Pi
146 fmt.Println(cmp.Equal(x, y, opts))
147 fmt.Println(cmp.Equal(y, z, opts))
148 fmt.Println(cmp.Equal(z, x, opts))
156 // Sometimes, an empty map or slice is considered equal to an allocated one
159 // This example is for demonstrative purposes; use cmpopts.EquateEmpty instead.
160 func ExampleOption_equalEmpty() {
161 alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
163 // This option handles slices and maps of any type.
164 opt := cmp.FilterValues(func(x, y interface{}) bool {
165 vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
166 return (vx.IsValid() && vy.IsValid() && vx.Type() == vy.Type()) &&
167 (vx.Kind() == reflect.Slice || vx.Kind() == reflect.Map) &&
168 (vx.Len() == 0 && vy.Len() == 0)
175 x := S{nil, make(map[string]bool, 100)}
176 y := S{make([]int, 0, 200), nil}
177 z := S{[]int{0}, nil} // []int has a single element (i.e., not empty)
179 fmt.Println(cmp.Equal(x, y, opt))
180 fmt.Println(cmp.Equal(y, z, opt))
181 fmt.Println(cmp.Equal(z, x, opt))
189 // Two slices may be considered equal if they have the same elements,
190 // regardless of the order that they appear in. Transformations can be used
191 // to sort the slice.
193 // This example is for demonstrative purposes; use cmpopts.SortSlices instead.
194 func ExampleOption_sortedSlice() {
195 // This Transformer sorts a []int.
196 trans := cmp.Transformer("Sort", func(in []int) []int {
197 out := append([]int(nil), in...) // Copy input to avoid mutating it
202 x := struct{ Ints []int }{[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}
203 y := struct{ Ints []int }{[]int{2, 8, 0, 9, 6, 1, 4, 7, 3, 5}}
204 z := struct{ Ints []int }{[]int{0, 0, 1, 2, 3, 4, 5, 6, 7, 8}}
206 fmt.Println(cmp.Equal(x, y, trans))
207 fmt.Println(cmp.Equal(y, z, trans))
208 fmt.Println(cmp.Equal(z, x, trans))
216 type otherString string
218 func (x otherString) Equal(y otherString) bool {
219 return strings.ToLower(string(x)) == strings.ToLower(string(y))
222 // If the Equal method defined on a type is not suitable, the type can be
223 // dynamically transformed to be stripped of the Equal method (or any method
225 func ExampleOption_avoidEqualMethod() {
226 // Suppose otherString.Equal performs a case-insensitive equality,
227 // which is too loose for our needs.
228 // We can avoid the methods of otherString by declaring a new type.
229 type myString otherString
231 // This transformer converts otherString to myString, allowing Equal to use
232 // other Options to determine equality.
233 trans := cmp.Transformer("", func(in otherString) myString {
237 x := []otherString{"foo", "bar", "baz"}
238 y := []otherString{"fOO", "bAr", "Baz"} // Same as before, but with different case
240 fmt.Println(cmp.Equal(x, y)) // Equal because of case-insensitivity
241 fmt.Println(cmp.Equal(x, y, trans)) // Not equal because of more exact equality
248 func roundF64(z float64) float64 {
250 return math.Ceil(z - 0.5)
252 return math.Floor(z + 0.5)
255 // The complex numbers complex64 and complex128 can really just be decomposed
256 // into a pair of float32 or float64 values. It would be convenient to be able
257 // define only a single comparator on float64 and have float32, complex64, and
258 // complex128 all be able to use that comparator. Transformations can be used
260 func ExampleOption_transformComplex() {
261 opts := []cmp.Option{
262 // This transformer decomposes complex128 into a pair of float64s.
263 cmp.Transformer("T1", func(in complex128) (out struct{ Real, Imag float64 }) {
264 out.Real, out.Imag = real(in), imag(in)
267 // This transformer converts complex64 to complex128 to allow the
268 // above transform to take effect.
269 cmp.Transformer("T2", func(in complex64) complex128 {
270 return complex128(in)
272 // This transformer converts float32 to float64.
273 cmp.Transformer("T3", func(in float32) float64 {
276 // This equality function compares float64s as rounded integers.
277 cmp.Comparer(func(x, y float64) bool {
278 return roundF64(x) == roundF64(y)
283 complex128(3.0), complex64(5.1 + 2.9i), float32(-1.2), float64(12.3),
286 complex128(3.1), complex64(4.9 + 3.1i), float32(-1.3), float64(11.7),
289 complex128(3.8), complex64(4.9 + 3.1i), float32(-1.3), float64(11.7),
292 fmt.Println(cmp.Equal(x, y, opts...))
293 fmt.Println(cmp.Equal(y, z, opts...))
294 fmt.Println(cmp.Equal(z, x, opts...))
316 func MakeGatewayInfo() (x, y Gateway) {
318 SSID: "CoffeeShopWiFi",
319 IPAddress: net.IPv4(192, 168, 0, 1),
320 NetMask: net.IPv4Mask(255, 255, 0, 0),
322 Hostname: "ristretto",
323 IPAddress: net.IPv4(192, 168, 0, 116),
326 IPAddress: net.IPv4(192, 168, 0, 104),
327 LastSeen: time.Date(2009, time.November, 10, 23, 6, 32, 0, time.UTC),
329 Hostname: "macchiato",
330 IPAddress: net.IPv4(192, 168, 0, 153),
331 LastSeen: time.Date(2009, time.November, 10, 23, 39, 43, 0, time.UTC),
333 Hostname: "espresso",
334 IPAddress: net.IPv4(192, 168, 0, 121),
337 IPAddress: net.IPv4(192, 168, 0, 219),
338 LastSeen: time.Date(2009, time.November, 10, 23, 0, 23, 0, time.UTC),
340 Hostname: "americano",
341 IPAddress: net.IPv4(192, 168, 0, 188),
342 LastSeen: time.Date(2009, time.November, 10, 23, 3, 5, 0, time.UTC),
346 SSID: "CoffeeShopWiFi",
347 IPAddress: net.IPv4(192, 168, 0, 2),
348 NetMask: net.IPv4Mask(255, 255, 0, 0),
350 Hostname: "ristretto",
351 IPAddress: net.IPv4(192, 168, 0, 116),
354 IPAddress: net.IPv4(192, 168, 0, 104),
355 LastSeen: time.Date(2009, time.November, 10, 23, 6, 32, 0, time.UTC),
357 Hostname: "macchiato",
358 IPAddress: net.IPv4(192, 168, 0, 153),
359 LastSeen: time.Date(2009, time.November, 10, 23, 39, 43, 0, time.UTC),
361 Hostname: "espresso",
362 IPAddress: net.IPv4(192, 168, 0, 121),
365 IPAddress: net.IPv4(192, 168, 0, 221),
366 LastSeen: time.Date(2009, time.November, 10, 23, 0, 23, 0, time.UTC),
376 func (t fakeT) Errorf(format string, args ...interface{}) { fmt.Printf(format+"\n", args...) }