.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / github.com / google / go-cmp@v0.5.4 / cmp / example_test.go
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.
4
5 package cmp_test
6
7 import (
8         "fmt"
9         "math"
10         "net"
11         "reflect"
12         "sort"
13         "strings"
14         "time"
15
16         "github.com/google/go-cmp/cmp"
17 )
18
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.
22
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()
29
30         if diff := cmp.Diff(want, got); diff != "" {
31                 t.Errorf("MakeGatewayInfo() mismatch (-want +got):\n%s", diff)
32         }
33
34         // Output:
35         // MakeGatewayInfo() mismatch (-want +got):
36         //   cmp_test.Gateway{
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"},
45         //              {
46         //                      Hostname:  "latte",
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",
50         //              },
51         // +            {
52         // +                    Hostname:  "americano",
53         // +                    IPAddress: s"192.168.0.188",
54         // +                    LastSeen:  s"2009-11-10 23:03:05 +0000 UTC",
55         // +            },
56         //      },
57         //   }
58 }
59
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.
63 //
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
73         })
74
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
78
79         fmt.Println(cmp.Equal(x, y, opt))
80         fmt.Println(cmp.Equal(y, z, opt))
81         fmt.Println(cmp.Equal(z, x, opt))
82
83         // Output:
84         // true
85         // false
86         // false
87 }
88
89 // Normal floating-point arithmetic defines == to be false when comparing
90 // NaN with itself. In certain cases, this is not the desired property.
91 //
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
99         })
100
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
104
105         fmt.Println(cmp.Equal(x, y, opt))
106         fmt.Println(cmp.Equal(y, z, opt))
107         fmt.Println(cmp.Equal(z, x, opt))
108
109         // Output:
110         // true
111         // false
112         // false
113 }
114
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.
118 //
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 })
123
124         opts := cmp.Options{
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)
129                 }, alwaysEqual),
130
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
139                 })),
140         }
141
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
145
146         fmt.Println(cmp.Equal(x, y, opts))
147         fmt.Println(cmp.Equal(y, z, opts))
148         fmt.Println(cmp.Equal(z, x, opts))
149
150         // Output:
151         // true
152         // false
153         // false
154 }
155
156 // Sometimes, an empty map or slice is considered equal to an allocated one
157 // of zero length.
158 //
159 // This example is for demonstrative purposes; use cmpopts.EquateEmpty instead.
160 func ExampleOption_equalEmpty() {
161         alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
162
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)
169         }, alwaysEqual)
170
171         type S struct {
172                 A []int
173                 B map[string]bool
174         }
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)
178
179         fmt.Println(cmp.Equal(x, y, opt))
180         fmt.Println(cmp.Equal(y, z, opt))
181         fmt.Println(cmp.Equal(z, x, opt))
182
183         // Output:
184         // true
185         // false
186         // false
187 }
188
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.
192 //
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
198                 sort.Ints(out)
199                 return out
200         })
201
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}}
205
206         fmt.Println(cmp.Equal(x, y, trans))
207         fmt.Println(cmp.Equal(y, z, trans))
208         fmt.Println(cmp.Equal(z, x, trans))
209
210         // Output:
211         // true
212         // false
213         // false
214 }
215
216 type otherString string
217
218 func (x otherString) Equal(y otherString) bool {
219         return strings.ToLower(string(x)) == strings.ToLower(string(y))
220 }
221
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
224 // for that matter).
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
230
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 {
234                 return myString(in)
235         })
236
237         x := []otherString{"foo", "bar", "baz"}
238         y := []otherString{"fOO", "bAr", "Baz"} // Same as before, but with different case
239
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
242
243         // Output:
244         // true
245         // false
246 }
247
248 func roundF64(z float64) float64 {
249         if z < 0 {
250                 return math.Ceil(z - 0.5)
251         }
252         return math.Floor(z + 0.5)
253 }
254
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
259 // to handle this.
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)
265                         return out
266                 }),
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)
271                 }),
272                 // This transformer converts float32 to float64.
273                 cmp.Transformer("T3", func(in float32) float64 {
274                         return float64(in)
275                 }),
276                 // This equality function compares float64s as rounded integers.
277                 cmp.Comparer(func(x, y float64) bool {
278                         return roundF64(x) == roundF64(y)
279                 }),
280         }
281
282         x := []interface{}{
283                 complex128(3.0), complex64(5.1 + 2.9i), float32(-1.2), float64(12.3),
284         }
285         y := []interface{}{
286                 complex128(3.1), complex64(4.9 + 3.1i), float32(-1.3), float64(11.7),
287         }
288         z := []interface{}{
289                 complex128(3.8), complex64(4.9 + 3.1i), float32(-1.3), float64(11.7),
290         }
291
292         fmt.Println(cmp.Equal(x, y, opts...))
293         fmt.Println(cmp.Equal(y, z, opts...))
294         fmt.Println(cmp.Equal(z, x, opts...))
295
296         // Output:
297         // true
298         // false
299         // false
300 }
301
302 type (
303         Gateway struct {
304                 SSID      string
305                 IPAddress net.IP
306                 NetMask   net.IPMask
307                 Clients   []Client
308         }
309         Client struct {
310                 Hostname  string
311                 IPAddress net.IP
312                 LastSeen  time.Time
313         }
314 )
315
316 func MakeGatewayInfo() (x, y Gateway) {
317         x = Gateway{
318                 SSID:      "CoffeeShopWiFi",
319                 IPAddress: net.IPv4(192, 168, 0, 1),
320                 NetMask:   net.IPv4Mask(255, 255, 0, 0),
321                 Clients: []Client{{
322                         Hostname:  "ristretto",
323                         IPAddress: net.IPv4(192, 168, 0, 116),
324                 }, {
325                         Hostname:  "aribica",
326                         IPAddress: net.IPv4(192, 168, 0, 104),
327                         LastSeen:  time.Date(2009, time.November, 10, 23, 6, 32, 0, time.UTC),
328                 }, {
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),
332                 }, {
333                         Hostname:  "espresso",
334                         IPAddress: net.IPv4(192, 168, 0, 121),
335                 }, {
336                         Hostname:  "latte",
337                         IPAddress: net.IPv4(192, 168, 0, 219),
338                         LastSeen:  time.Date(2009, time.November, 10, 23, 0, 23, 0, time.UTC),
339                 }, {
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),
343                 }},
344         }
345         y = Gateway{
346                 SSID:      "CoffeeShopWiFi",
347                 IPAddress: net.IPv4(192, 168, 0, 2),
348                 NetMask:   net.IPv4Mask(255, 255, 0, 0),
349                 Clients: []Client{{
350                         Hostname:  "ristretto",
351                         IPAddress: net.IPv4(192, 168, 0, 116),
352                 }, {
353                         Hostname:  "aribica",
354                         IPAddress: net.IPv4(192, 168, 0, 104),
355                         LastSeen:  time.Date(2009, time.November, 10, 23, 6, 32, 0, time.UTC),
356                 }, {
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),
360                 }, {
361                         Hostname:  "espresso",
362                         IPAddress: net.IPv4(192, 168, 0, 121),
363                 }, {
364                         Hostname:  "latte",
365                         IPAddress: net.IPv4(192, 168, 0, 221),
366                         LastSeen:  time.Date(2009, time.November, 10, 23, 0, 23, 0, time.UTC),
367                 }},
368         }
369         return x, y
370 }
371
372 var t fakeT
373
374 type fakeT struct{}
375
376 func (t fakeT) Errorf(format string, args ...interface{}) { fmt.Printf(format+"\n", args...) }