xref: /aosp_15_r20/external/go-cmp/cmp/example_test.go (revision 88d15eac089d7f20c739ff1001d56b91872b21a1)
1*88d15eacSSasha Smundak// Copyright 2017, The Go Authors. All rights reserved.
2*88d15eacSSasha Smundak// Use of this source code is governed by a BSD-style
3*88d15eacSSasha Smundak// license that can be found in the LICENSE file.
4*88d15eacSSasha Smundak
5*88d15eacSSasha Smundakpackage cmp_test
6*88d15eacSSasha Smundak
7*88d15eacSSasha Smundakimport (
8*88d15eacSSasha Smundak	"fmt"
9*88d15eacSSasha Smundak	"math"
10*88d15eacSSasha Smundak	"net"
11*88d15eacSSasha Smundak	"reflect"
12*88d15eacSSasha Smundak	"sort"
13*88d15eacSSasha Smundak	"strings"
14*88d15eacSSasha Smundak	"time"
15*88d15eacSSasha Smundak
16*88d15eacSSasha Smundak	"github.com/google/go-cmp/cmp"
17*88d15eacSSasha Smundak)
18*88d15eacSSasha Smundak
19*88d15eacSSasha Smundak// TODO: Re-write these examples in terms of how you actually use the
20*88d15eacSSasha Smundak// fundamental options and filters and not in terms of what cool things you can
21*88d15eacSSasha Smundak// do with them since that overlaps with cmp/cmpopts.
22*88d15eacSSasha Smundak
23*88d15eacSSasha Smundak// Use Diff to print out a human-readable report of differences for tests
24*88d15eacSSasha Smundak// comparing nested or structured data.
25*88d15eacSSasha Smundakfunc ExampleDiff_testing() {
26*88d15eacSSasha Smundak	// Let got be the hypothetical value obtained from some logic under test
27*88d15eacSSasha Smundak	// and want be the expected golden data.
28*88d15eacSSasha Smundak	got, want := MakeGatewayInfo()
29*88d15eacSSasha Smundak
30*88d15eacSSasha Smundak	if diff := cmp.Diff(want, got); diff != "" {
31*88d15eacSSasha Smundak		t.Errorf("MakeGatewayInfo() mismatch (-want +got):\n%s", diff)
32*88d15eacSSasha Smundak	}
33*88d15eacSSasha Smundak
34*88d15eacSSasha Smundak	// Output:
35*88d15eacSSasha Smundak	// MakeGatewayInfo() mismatch (-want +got):
36*88d15eacSSasha Smundak	//   cmp_test.Gateway{
37*88d15eacSSasha Smundak	//   	SSID:      "CoffeeShopWiFi",
38*88d15eacSSasha Smundak	// - 	IPAddress: s"192.168.0.2",
39*88d15eacSSasha Smundak	// + 	IPAddress: s"192.168.0.1",
40*88d15eacSSasha Smundak	//   	NetMask:   s"ffff0000",
41*88d15eacSSasha Smundak	//   	Clients: []cmp_test.Client{
42*88d15eacSSasha Smundak	//   		... // 2 identical elements
43*88d15eacSSasha Smundak	//   		{Hostname: "macchiato", IPAddress: s"192.168.0.153", LastSeen: s"2009-11-10 23:39:43 +0000 UTC"},
44*88d15eacSSasha Smundak	//   		{Hostname: "espresso", IPAddress: s"192.168.0.121"},
45*88d15eacSSasha Smundak	//   		{
46*88d15eacSSasha Smundak	//   			Hostname:  "latte",
47*88d15eacSSasha Smundak	// - 			IPAddress: s"192.168.0.221",
48*88d15eacSSasha Smundak	// + 			IPAddress: s"192.168.0.219",
49*88d15eacSSasha Smundak	//   			LastSeen:  s"2009-11-10 23:00:23 +0000 UTC",
50*88d15eacSSasha Smundak	//   		},
51*88d15eacSSasha Smundak	// + 		{
52*88d15eacSSasha Smundak	// + 			Hostname:  "americano",
53*88d15eacSSasha Smundak	// + 			IPAddress: s"192.168.0.188",
54*88d15eacSSasha Smundak	// + 			LastSeen:  s"2009-11-10 23:03:05 +0000 UTC",
55*88d15eacSSasha Smundak	// + 		},
56*88d15eacSSasha Smundak	//   	},
57*88d15eacSSasha Smundak	//   }
58*88d15eacSSasha Smundak}
59*88d15eacSSasha Smundak
60*88d15eacSSasha Smundak// Approximate equality for floats can be handled by defining a custom
61*88d15eacSSasha Smundak// comparer on floats that determines two values to be equal if they are within
62*88d15eacSSasha Smundak// some range of each other.
63*88d15eacSSasha Smundak//
64*88d15eacSSasha Smundak// This example is for demonstrative purposes; use cmpopts.EquateApprox instead.
65*88d15eacSSasha Smundakfunc ExampleOption_approximateFloats() {
66*88d15eacSSasha Smundak	// This Comparer only operates on float64.
67*88d15eacSSasha Smundak	// To handle float32s, either define a similar function for that type
68*88d15eacSSasha Smundak	// or use a Transformer to convert float32s into float64s.
69*88d15eacSSasha Smundak	opt := cmp.Comparer(func(x, y float64) bool {
70*88d15eacSSasha Smundak		delta := math.Abs(x - y)
71*88d15eacSSasha Smundak		mean := math.Abs(x+y) / 2.0
72*88d15eacSSasha Smundak		return delta/mean < 0.00001
73*88d15eacSSasha Smundak	})
74*88d15eacSSasha Smundak
75*88d15eacSSasha Smundak	x := []float64{1.0, 1.1, 1.2, math.Pi}
76*88d15eacSSasha Smundak	y := []float64{1.0, 1.1, 1.2, 3.14159265359} // Accurate enough to Pi
77*88d15eacSSasha Smundak	z := []float64{1.0, 1.1, 1.2, 3.1415}        // Diverges too far from Pi
78*88d15eacSSasha Smundak
79*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(x, y, opt))
80*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(y, z, opt))
81*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(z, x, opt))
82*88d15eacSSasha Smundak
83*88d15eacSSasha Smundak	// Output:
84*88d15eacSSasha Smundak	// true
85*88d15eacSSasha Smundak	// false
86*88d15eacSSasha Smundak	// false
87*88d15eacSSasha Smundak}
88*88d15eacSSasha Smundak
89*88d15eacSSasha Smundak// Normal floating-point arithmetic defines == to be false when comparing
90*88d15eacSSasha Smundak// NaN with itself. In certain cases, this is not the desired property.
91*88d15eacSSasha Smundak//
92*88d15eacSSasha Smundak// This example is for demonstrative purposes; use cmpopts.EquateNaNs instead.
93*88d15eacSSasha Smundakfunc ExampleOption_equalNaNs() {
94*88d15eacSSasha Smundak	// This Comparer only operates on float64.
95*88d15eacSSasha Smundak	// To handle float32s, either define a similar function for that type
96*88d15eacSSasha Smundak	// or use a Transformer to convert float32s into float64s.
97*88d15eacSSasha Smundak	opt := cmp.Comparer(func(x, y float64) bool {
98*88d15eacSSasha Smundak		return (math.IsNaN(x) && math.IsNaN(y)) || x == y
99*88d15eacSSasha Smundak	})
100*88d15eacSSasha Smundak
101*88d15eacSSasha Smundak	x := []float64{1.0, math.NaN(), math.E, 0.0}
102*88d15eacSSasha Smundak	y := []float64{1.0, math.NaN(), math.E, 0.0}
103*88d15eacSSasha Smundak	z := []float64{1.0, math.NaN(), math.Pi, 0.0} // Pi constant instead of E
104*88d15eacSSasha Smundak
105*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(x, y, opt))
106*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(y, z, opt))
107*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(z, x, opt))
108*88d15eacSSasha Smundak
109*88d15eacSSasha Smundak	// Output:
110*88d15eacSSasha Smundak	// true
111*88d15eacSSasha Smundak	// false
112*88d15eacSSasha Smundak	// false
113*88d15eacSSasha Smundak}
114*88d15eacSSasha Smundak
115*88d15eacSSasha Smundak// To have floating-point comparisons combine both properties of NaN being
116*88d15eacSSasha Smundak// equal to itself and also approximate equality of values, filters are needed
117*88d15eacSSasha Smundak// to restrict the scope of the comparison so that they are composable.
118*88d15eacSSasha Smundak//
119*88d15eacSSasha Smundak// This example is for demonstrative purposes;
120*88d15eacSSasha Smundak// use cmpopts.EquateNaNs and cmpopts.EquateApprox instead.
121*88d15eacSSasha Smundakfunc ExampleOption_equalNaNsAndApproximateFloats() {
122*88d15eacSSasha Smundak	alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
123*88d15eacSSasha Smundak
124*88d15eacSSasha Smundak	opts := cmp.Options{
125*88d15eacSSasha Smundak		// This option declares that a float64 comparison is equal only if
126*88d15eacSSasha Smundak		// both inputs are NaN.
127*88d15eacSSasha Smundak		cmp.FilterValues(func(x, y float64) bool {
128*88d15eacSSasha Smundak			return math.IsNaN(x) && math.IsNaN(y)
129*88d15eacSSasha Smundak		}, alwaysEqual),
130*88d15eacSSasha Smundak
131*88d15eacSSasha Smundak		// This option declares approximate equality on float64s only if
132*88d15eacSSasha Smundak		// both inputs are not NaN.
133*88d15eacSSasha Smundak		cmp.FilterValues(func(x, y float64) bool {
134*88d15eacSSasha Smundak			return !math.IsNaN(x) && !math.IsNaN(y)
135*88d15eacSSasha Smundak		}, cmp.Comparer(func(x, y float64) bool {
136*88d15eacSSasha Smundak			delta := math.Abs(x - y)
137*88d15eacSSasha Smundak			mean := math.Abs(x+y) / 2.0
138*88d15eacSSasha Smundak			return delta/mean < 0.00001
139*88d15eacSSasha Smundak		})),
140*88d15eacSSasha Smundak	}
141*88d15eacSSasha Smundak
142*88d15eacSSasha Smundak	x := []float64{math.NaN(), 1.0, 1.1, 1.2, math.Pi}
143*88d15eacSSasha Smundak	y := []float64{math.NaN(), 1.0, 1.1, 1.2, 3.14159265359} // Accurate enough to Pi
144*88d15eacSSasha Smundak	z := []float64{math.NaN(), 1.0, 1.1, 1.2, 3.1415}        // Diverges too far from Pi
145*88d15eacSSasha Smundak
146*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(x, y, opts))
147*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(y, z, opts))
148*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(z, x, opts))
149*88d15eacSSasha Smundak
150*88d15eacSSasha Smundak	// Output:
151*88d15eacSSasha Smundak	// true
152*88d15eacSSasha Smundak	// false
153*88d15eacSSasha Smundak	// false
154*88d15eacSSasha Smundak}
155*88d15eacSSasha Smundak
156*88d15eacSSasha Smundak// Sometimes, an empty map or slice is considered equal to an allocated one
157*88d15eacSSasha Smundak// of zero length.
158*88d15eacSSasha Smundak//
159*88d15eacSSasha Smundak// This example is for demonstrative purposes; use cmpopts.EquateEmpty instead.
160*88d15eacSSasha Smundakfunc ExampleOption_equalEmpty() {
161*88d15eacSSasha Smundak	alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
162*88d15eacSSasha Smundak
163*88d15eacSSasha Smundak	// This option handles slices and maps of any type.
164*88d15eacSSasha Smundak	opt := cmp.FilterValues(func(x, y interface{}) bool {
165*88d15eacSSasha Smundak		vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
166*88d15eacSSasha Smundak		return (vx.IsValid() && vy.IsValid() && vx.Type() == vy.Type()) &&
167*88d15eacSSasha Smundak			(vx.Kind() == reflect.Slice || vx.Kind() == reflect.Map) &&
168*88d15eacSSasha Smundak			(vx.Len() == 0 && vy.Len() == 0)
169*88d15eacSSasha Smundak	}, alwaysEqual)
170*88d15eacSSasha Smundak
171*88d15eacSSasha Smundak	type S struct {
172*88d15eacSSasha Smundak		A []int
173*88d15eacSSasha Smundak		B map[string]bool
174*88d15eacSSasha Smundak	}
175*88d15eacSSasha Smundak	x := S{nil, make(map[string]bool, 100)}
176*88d15eacSSasha Smundak	y := S{make([]int, 0, 200), nil}
177*88d15eacSSasha Smundak	z := S{[]int{0}, nil} // []int has a single element (i.e., not empty)
178*88d15eacSSasha Smundak
179*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(x, y, opt))
180*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(y, z, opt))
181*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(z, x, opt))
182*88d15eacSSasha Smundak
183*88d15eacSSasha Smundak	// Output:
184*88d15eacSSasha Smundak	// true
185*88d15eacSSasha Smundak	// false
186*88d15eacSSasha Smundak	// false
187*88d15eacSSasha Smundak}
188*88d15eacSSasha Smundak
189*88d15eacSSasha Smundak// Two slices may be considered equal if they have the same elements,
190*88d15eacSSasha Smundak// regardless of the order that they appear in. Transformations can be used
191*88d15eacSSasha Smundak// to sort the slice.
192*88d15eacSSasha Smundak//
193*88d15eacSSasha Smundak// This example is for demonstrative purposes; use cmpopts.SortSlices instead.
194*88d15eacSSasha Smundakfunc ExampleOption_sortedSlice() {
195*88d15eacSSasha Smundak	// This Transformer sorts a []int.
196*88d15eacSSasha Smundak	trans := cmp.Transformer("Sort", func(in []int) []int {
197*88d15eacSSasha Smundak		out := append([]int(nil), in...) // Copy input to avoid mutating it
198*88d15eacSSasha Smundak		sort.Ints(out)
199*88d15eacSSasha Smundak		return out
200*88d15eacSSasha Smundak	})
201*88d15eacSSasha Smundak
202*88d15eacSSasha Smundak	x := struct{ Ints []int }{[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}
203*88d15eacSSasha Smundak	y := struct{ Ints []int }{[]int{2, 8, 0, 9, 6, 1, 4, 7, 3, 5}}
204*88d15eacSSasha Smundak	z := struct{ Ints []int }{[]int{0, 0, 1, 2, 3, 4, 5, 6, 7, 8}}
205*88d15eacSSasha Smundak
206*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(x, y, trans))
207*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(y, z, trans))
208*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(z, x, trans))
209*88d15eacSSasha Smundak
210*88d15eacSSasha Smundak	// Output:
211*88d15eacSSasha Smundak	// true
212*88d15eacSSasha Smundak	// false
213*88d15eacSSasha Smundak	// false
214*88d15eacSSasha Smundak}
215*88d15eacSSasha Smundak
216*88d15eacSSasha Smundaktype otherString string
217*88d15eacSSasha Smundak
218*88d15eacSSasha Smundakfunc (x otherString) Equal(y otherString) bool {
219*88d15eacSSasha Smundak	return strings.EqualFold(string(x), string(y))
220*88d15eacSSasha Smundak}
221*88d15eacSSasha Smundak
222*88d15eacSSasha Smundak// If the Equal method defined on a type is not suitable, the type can be
223*88d15eacSSasha Smundak// dynamically transformed to be stripped of the Equal method (or any method
224*88d15eacSSasha Smundak// for that matter).
225*88d15eacSSasha Smundakfunc ExampleOption_avoidEqualMethod() {
226*88d15eacSSasha Smundak	// Suppose otherString.Equal performs a case-insensitive equality,
227*88d15eacSSasha Smundak	// which is too loose for our needs.
228*88d15eacSSasha Smundak	// We can avoid the methods of otherString by declaring a new type.
229*88d15eacSSasha Smundak	type myString otherString
230*88d15eacSSasha Smundak
231*88d15eacSSasha Smundak	// This transformer converts otherString to myString, allowing Equal to use
232*88d15eacSSasha Smundak	// other Options to determine equality.
233*88d15eacSSasha Smundak	trans := cmp.Transformer("", func(in otherString) myString {
234*88d15eacSSasha Smundak		return myString(in)
235*88d15eacSSasha Smundak	})
236*88d15eacSSasha Smundak
237*88d15eacSSasha Smundak	x := []otherString{"foo", "bar", "baz"}
238*88d15eacSSasha Smundak	y := []otherString{"fOO", "bAr", "Baz"} // Same as before, but with different case
239*88d15eacSSasha Smundak
240*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(x, y))        // Equal because of case-insensitivity
241*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(x, y, trans)) // Not equal because of more exact equality
242*88d15eacSSasha Smundak
243*88d15eacSSasha Smundak	// Output:
244*88d15eacSSasha Smundak	// true
245*88d15eacSSasha Smundak	// false
246*88d15eacSSasha Smundak}
247*88d15eacSSasha Smundak
248*88d15eacSSasha Smundakfunc roundF64(z float64) float64 {
249*88d15eacSSasha Smundak	if z < 0 {
250*88d15eacSSasha Smundak		return math.Ceil(z - 0.5)
251*88d15eacSSasha Smundak	}
252*88d15eacSSasha Smundak	return math.Floor(z + 0.5)
253*88d15eacSSasha Smundak}
254*88d15eacSSasha Smundak
255*88d15eacSSasha Smundak// The complex numbers complex64 and complex128 can really just be decomposed
256*88d15eacSSasha Smundak// into a pair of float32 or float64 values. It would be convenient to be able
257*88d15eacSSasha Smundak// define only a single comparator on float64 and have float32, complex64, and
258*88d15eacSSasha Smundak// complex128 all be able to use that comparator. Transformations can be used
259*88d15eacSSasha Smundak// to handle this.
260*88d15eacSSasha Smundakfunc ExampleOption_transformComplex() {
261*88d15eacSSasha Smundak	opts := []cmp.Option{
262*88d15eacSSasha Smundak		// This transformer decomposes complex128 into a pair of float64s.
263*88d15eacSSasha Smundak		cmp.Transformer("T1", func(in complex128) (out struct{ Real, Imag float64 }) {
264*88d15eacSSasha Smundak			out.Real, out.Imag = real(in), imag(in)
265*88d15eacSSasha Smundak			return out
266*88d15eacSSasha Smundak		}),
267*88d15eacSSasha Smundak		// This transformer converts complex64 to complex128 to allow the
268*88d15eacSSasha Smundak		// above transform to take effect.
269*88d15eacSSasha Smundak		cmp.Transformer("T2", func(in complex64) complex128 {
270*88d15eacSSasha Smundak			return complex128(in)
271*88d15eacSSasha Smundak		}),
272*88d15eacSSasha Smundak		// This transformer converts float32 to float64.
273*88d15eacSSasha Smundak		cmp.Transformer("T3", func(in float32) float64 {
274*88d15eacSSasha Smundak			return float64(in)
275*88d15eacSSasha Smundak		}),
276*88d15eacSSasha Smundak		// This equality function compares float64s as rounded integers.
277*88d15eacSSasha Smundak		cmp.Comparer(func(x, y float64) bool {
278*88d15eacSSasha Smundak			return roundF64(x) == roundF64(y)
279*88d15eacSSasha Smundak		}),
280*88d15eacSSasha Smundak	}
281*88d15eacSSasha Smundak
282*88d15eacSSasha Smundak	x := []interface{}{
283*88d15eacSSasha Smundak		complex128(3.0), complex64(5.1 + 2.9i), float32(-1.2), float64(12.3),
284*88d15eacSSasha Smundak	}
285*88d15eacSSasha Smundak	y := []interface{}{
286*88d15eacSSasha Smundak		complex128(3.1), complex64(4.9 + 3.1i), float32(-1.3), float64(11.7),
287*88d15eacSSasha Smundak	}
288*88d15eacSSasha Smundak	z := []interface{}{
289*88d15eacSSasha Smundak		complex128(3.8), complex64(4.9 + 3.1i), float32(-1.3), float64(11.7),
290*88d15eacSSasha Smundak	}
291*88d15eacSSasha Smundak
292*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(x, y, opts...))
293*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(y, z, opts...))
294*88d15eacSSasha Smundak	fmt.Println(cmp.Equal(z, x, opts...))
295*88d15eacSSasha Smundak
296*88d15eacSSasha Smundak	// Output:
297*88d15eacSSasha Smundak	// true
298*88d15eacSSasha Smundak	// false
299*88d15eacSSasha Smundak	// false
300*88d15eacSSasha Smundak}
301*88d15eacSSasha Smundak
302*88d15eacSSasha Smundaktype (
303*88d15eacSSasha Smundak	Gateway struct {
304*88d15eacSSasha Smundak		SSID      string
305*88d15eacSSasha Smundak		IPAddress net.IP
306*88d15eacSSasha Smundak		NetMask   net.IPMask
307*88d15eacSSasha Smundak		Clients   []Client
308*88d15eacSSasha Smundak	}
309*88d15eacSSasha Smundak	Client struct {
310*88d15eacSSasha Smundak		Hostname  string
311*88d15eacSSasha Smundak		IPAddress net.IP
312*88d15eacSSasha Smundak		LastSeen  time.Time
313*88d15eacSSasha Smundak	}
314*88d15eacSSasha Smundak)
315*88d15eacSSasha Smundak
316*88d15eacSSasha Smundakfunc MakeGatewayInfo() (x, y Gateway) {
317*88d15eacSSasha Smundak	x = Gateway{
318*88d15eacSSasha Smundak		SSID:      "CoffeeShopWiFi",
319*88d15eacSSasha Smundak		IPAddress: net.IPv4(192, 168, 0, 1),
320*88d15eacSSasha Smundak		NetMask:   net.IPv4Mask(255, 255, 0, 0),
321*88d15eacSSasha Smundak		Clients: []Client{{
322*88d15eacSSasha Smundak			Hostname:  "ristretto",
323*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 116),
324*88d15eacSSasha Smundak		}, {
325*88d15eacSSasha Smundak			Hostname:  "aribica",
326*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 104),
327*88d15eacSSasha Smundak			LastSeen:  time.Date(2009, time.November, 10, 23, 6, 32, 0, time.UTC),
328*88d15eacSSasha Smundak		}, {
329*88d15eacSSasha Smundak			Hostname:  "macchiato",
330*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 153),
331*88d15eacSSasha Smundak			LastSeen:  time.Date(2009, time.November, 10, 23, 39, 43, 0, time.UTC),
332*88d15eacSSasha Smundak		}, {
333*88d15eacSSasha Smundak			Hostname:  "espresso",
334*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 121),
335*88d15eacSSasha Smundak		}, {
336*88d15eacSSasha Smundak			Hostname:  "latte",
337*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 219),
338*88d15eacSSasha Smundak			LastSeen:  time.Date(2009, time.November, 10, 23, 0, 23, 0, time.UTC),
339*88d15eacSSasha Smundak		}, {
340*88d15eacSSasha Smundak			Hostname:  "americano",
341*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 188),
342*88d15eacSSasha Smundak			LastSeen:  time.Date(2009, time.November, 10, 23, 3, 5, 0, time.UTC),
343*88d15eacSSasha Smundak		}},
344*88d15eacSSasha Smundak	}
345*88d15eacSSasha Smundak	y = Gateway{
346*88d15eacSSasha Smundak		SSID:      "CoffeeShopWiFi",
347*88d15eacSSasha Smundak		IPAddress: net.IPv4(192, 168, 0, 2),
348*88d15eacSSasha Smundak		NetMask:   net.IPv4Mask(255, 255, 0, 0),
349*88d15eacSSasha Smundak		Clients: []Client{{
350*88d15eacSSasha Smundak			Hostname:  "ristretto",
351*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 116),
352*88d15eacSSasha Smundak		}, {
353*88d15eacSSasha Smundak			Hostname:  "aribica",
354*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 104),
355*88d15eacSSasha Smundak			LastSeen:  time.Date(2009, time.November, 10, 23, 6, 32, 0, time.UTC),
356*88d15eacSSasha Smundak		}, {
357*88d15eacSSasha Smundak			Hostname:  "macchiato",
358*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 153),
359*88d15eacSSasha Smundak			LastSeen:  time.Date(2009, time.November, 10, 23, 39, 43, 0, time.UTC),
360*88d15eacSSasha Smundak		}, {
361*88d15eacSSasha Smundak			Hostname:  "espresso",
362*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 121),
363*88d15eacSSasha Smundak		}, {
364*88d15eacSSasha Smundak			Hostname:  "latte",
365*88d15eacSSasha Smundak			IPAddress: net.IPv4(192, 168, 0, 221),
366*88d15eacSSasha Smundak			LastSeen:  time.Date(2009, time.November, 10, 23, 0, 23, 0, time.UTC),
367*88d15eacSSasha Smundak		}},
368*88d15eacSSasha Smundak	}
369*88d15eacSSasha Smundak	return x, y
370*88d15eacSSasha Smundak}
371*88d15eacSSasha Smundak
372*88d15eacSSasha Smundakvar t fakeT
373*88d15eacSSasha Smundak
374*88d15eacSSasha Smundaktype fakeT struct{}
375*88d15eacSSasha Smundak
376*88d15eacSSasha Smundakfunc (t fakeT) Errorf(format string, args ...interface{}) { fmt.Printf(format+"\n", args...) }
377