| // Copyright 2017, The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE.md file. |
| |
| package value_test |
| |
| import ( |
| "math" |
| "reflect" |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/google/go-cmp/cmp/internal/value" |
| ) |
| |
| func TestSortKeys(t *testing.T) { |
| type ( |
| MyString string |
| MyArray [2]int |
| MyStruct struct { |
| A MyString |
| B MyArray |
| C chan float64 |
| } |
| EmptyStruct struct{} |
| ) |
| |
| opts := []cmp.Option{ |
| cmp.Comparer(func(x, y float64) bool { |
| if math.IsNaN(x) && math.IsNaN(y) { |
| return true |
| } |
| return x == y |
| }), |
| cmp.Comparer(func(x, y complex128) bool { |
| rx, ix, ry, iy := real(x), imag(x), real(y), imag(y) |
| if math.IsNaN(rx) && math.IsNaN(ry) { |
| rx, ry = 0, 0 |
| } |
| if math.IsNaN(ix) && math.IsNaN(iy) { |
| ix, iy = 0, 0 |
| } |
| return rx == ry && ix == iy |
| }), |
| cmp.Comparer(func(x, y chan bool) bool { return true }), |
| cmp.Comparer(func(x, y chan int) bool { return true }), |
| cmp.Comparer(func(x, y chan float64) bool { return true }), |
| cmp.Comparer(func(x, y chan interface{}) bool { return true }), |
| cmp.Comparer(func(x, y *int) bool { return true }), |
| } |
| |
| tests := []struct { |
| in map[interface{}]bool // Set of keys to sort |
| want []interface{} |
| }{{ |
| in: map[interface{}]bool{1: true, 2: true, 3: true}, |
| want: []interface{}{1, 2, 3}, |
| }, { |
| in: map[interface{}]bool{ |
| nil: true, |
| true: true, |
| false: true, |
| -5: true, |
| -55: true, |
| -555: true, |
| uint(1): true, |
| uint(11): true, |
| uint(111): true, |
| "abc": true, |
| "abcd": true, |
| "abcde": true, |
| "foo": true, |
| "bar": true, |
| MyString("abc"): true, |
| MyString("abcd"): true, |
| MyString("abcde"): true, |
| new(int): true, |
| new(int): true, |
| make(chan bool): true, |
| make(chan bool): true, |
| make(chan int): true, |
| make(chan interface{}): true, |
| math.Inf(+1): true, |
| math.Inf(-1): true, |
| 1.2345: true, |
| 12.345: true, |
| 123.45: true, |
| 1234.5: true, |
| 0 + 0i: true, |
| 1 + 0i: true, |
| 2 + 0i: true, |
| 0 + 1i: true, |
| 0 + 2i: true, |
| 0 + 3i: true, |
| [2]int{2, 3}: true, |
| [2]int{4, 0}: true, |
| [2]int{2, 4}: true, |
| MyArray([2]int{2, 4}): true, |
| EmptyStruct{}: true, |
| MyStruct{ |
| "bravo", [2]int{2, 3}, make(chan float64), |
| }: true, |
| MyStruct{ |
| "alpha", [2]int{3, 3}, make(chan float64), |
| }: true, |
| }, |
| want: []interface{}{ |
| nil, false, true, |
| -555, -55, -5, uint(1), uint(11), uint(111), |
| math.Inf(-1), 1.2345, 12.345, 123.45, 1234.5, math.Inf(+1), |
| (0 + 0i), (0 + 1i), (0 + 2i), (0 + 3i), (1 + 0i), (2 + 0i), |
| [2]int{2, 3}, [2]int{2, 4}, [2]int{4, 0}, MyArray([2]int{2, 4}), |
| make(chan bool), make(chan bool), make(chan int), make(chan interface{}), |
| new(int), new(int), |
| "abc", "abcd", "abcde", "bar", "foo", |
| MyString("abc"), MyString("abcd"), MyString("abcde"), |
| EmptyStruct{}, |
| MyStruct{"alpha", [2]int{3, 3}, make(chan float64)}, |
| MyStruct{"bravo", [2]int{2, 3}, make(chan float64)}, |
| }, |
| }, { |
| // NaN values cannot be properly deduplicated. |
| // This is okay since map entries with NaN in the keys cannot be |
| // retrieved anyways. |
| in: map[interface{}]bool{ |
| math.NaN(): true, |
| math.NaN(): true, |
| complex(0, math.NaN()): true, |
| complex(0, math.NaN()): true, |
| complex(math.NaN(), 0): true, |
| complex(math.NaN(), 0): true, |
| complex(math.NaN(), math.NaN()): true, |
| }, |
| want: []interface{}{ |
| math.NaN(), math.NaN(), math.NaN(), math.NaN(), |
| complex(math.NaN(), math.NaN()), complex(math.NaN(), math.NaN()), |
| complex(math.NaN(), 0), complex(math.NaN(), 0), complex(math.NaN(), 0), complex(math.NaN(), 0), |
| complex(0, math.NaN()), complex(0, math.NaN()), complex(0, math.NaN()), complex(0, math.NaN()), |
| }, |
| }} |
| |
| for i, tt := range tests { |
| keys := append(reflect.ValueOf(tt.in).MapKeys(), reflect.ValueOf(tt.in).MapKeys()...) |
| var got []interface{} |
| for _, k := range value.SortKeys(keys) { |
| got = append(got, k.Interface()) |
| } |
| if d := cmp.Diff(tt.want, got, opts...); d != "" { |
| t.Errorf("test %d, output mismatch (-want +got):\n%s", i, d) |
| } |
| } |
| } |