github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/internal/fmtsort/sort_test.go (about) 1 // Copyright 2018 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 fmtsort_test 6 7 import ( 8 "fmt" 9 "internal/fmtsort" 10 "math" 11 "reflect" 12 "strings" 13 "testing" 14 ) 15 16 var compareTests = [][]reflect.Value{ 17 ct(reflect.TypeOf(int(0)), -1, 0, 1), 18 ct(reflect.TypeOf(int8(0)), -1, 0, 1), 19 ct(reflect.TypeOf(int16(0)), -1, 0, 1), 20 ct(reflect.TypeOf(int32(0)), -1, 0, 1), 21 ct(reflect.TypeOf(int64(0)), -1, 0, 1), 22 ct(reflect.TypeOf(uint(0)), 0, 1, 5), 23 ct(reflect.TypeOf(uint8(0)), 0, 1, 5), 24 ct(reflect.TypeOf(uint16(0)), 0, 1, 5), 25 ct(reflect.TypeOf(uint32(0)), 0, 1, 5), 26 ct(reflect.TypeOf(uint64(0)), 0, 1, 5), 27 ct(reflect.TypeOf(uintptr(0)), 0, 1, 5), 28 ct(reflect.TypeOf(string("")), "", "a", "ab"), 29 ct(reflect.TypeOf(float32(0)), math.NaN(), math.Inf(-1), -1e10, 0, 1e10, math.Inf(1)), 30 ct(reflect.TypeOf(float64(0)), math.NaN(), math.Inf(-1), -1e10, 0, 1e10, math.Inf(1)), 31 ct(reflect.TypeOf(complex64(0+1i)), -1-1i, -1+0i, -1+1i, 0-1i, 0+0i, 0+1i, 1-1i, 1+0i, 1+1i), 32 ct(reflect.TypeOf(complex128(0+1i)), -1-1i, -1+0i, -1+1i, 0-1i, 0+0i, 0+1i, 1-1i, 1+0i, 1+1i), 33 ct(reflect.TypeOf(false), false, true), 34 ct(reflect.TypeOf(&ints[0]), &ints[0], &ints[1], &ints[2]), 35 ct(reflect.TypeOf(chans[0]), chans[0], chans[1], chans[2]), 36 ct(reflect.TypeOf(toy{}), toy{0, 1}, toy{0, 2}, toy{1, -1}, toy{1, 1}), 37 ct(reflect.TypeOf([2]int{}), [2]int{1, 1}, [2]int{1, 2}, [2]int{2, 0}), 38 ct(reflect.TypeOf(interface{}(interface{}(0))), iFace, 1, 2, 3), 39 } 40 41 var iFace interface{} 42 43 func ct(typ reflect.Type, args ...interface{}) []reflect.Value { 44 value := make([]reflect.Value, len(args)) 45 for i, v := range args { 46 x := reflect.ValueOf(v) 47 if !x.IsValid() { // Make it a typed nil. 48 x = reflect.Zero(typ) 49 } else { 50 x = x.Convert(typ) 51 } 52 value[i] = x 53 } 54 return value 55 } 56 57 func TestCompare(t *testing.T) { 58 for _, test := range compareTests { 59 for i, v0 := range test { 60 for j, v1 := range test { 61 c := fmtsort.Compare(v0, v1) 62 var expect int 63 switch { 64 case i == j: 65 expect = 0 66 // NaNs are tricky. 67 if typ := v0.Type(); (typ.Kind() == reflect.Float32 || typ.Kind() == reflect.Float64) && math.IsNaN(v0.Float()) { 68 expect = -1 69 } 70 case i < j: 71 expect = -1 72 case i > j: 73 expect = 1 74 } 75 if c != expect { 76 t.Errorf("%s: compare(%v,%v)=%d; expect %d", v0.Type(), v0, v1, c, expect) 77 } 78 } 79 } 80 } 81 } 82 83 type sortTest struct { 84 data interface{} // Always a map. 85 print string // Printed result using our custom printer. 86 } 87 88 var sortTests = []sortTest{ 89 { 90 map[int]string{7: "bar", -3: "foo"}, 91 "-3:foo 7:bar", 92 }, 93 { 94 map[uint8]string{7: "bar", 3: "foo"}, 95 "3:foo 7:bar", 96 }, 97 { 98 map[string]string{"7": "bar", "3": "foo"}, 99 "3:foo 7:bar", 100 }, 101 { 102 map[float64]string{7: "bar", -3: "foo", math.NaN(): "nan", math.Inf(0): "inf"}, 103 "NaN:nan -3:foo 7:bar +Inf:inf", 104 }, 105 { 106 map[complex128]string{7 + 2i: "bar2", 7 + 1i: "bar", -3: "foo", complex(math.NaN(), 0i): "nan", complex(math.Inf(0), 0i): "inf"}, 107 "(NaN+0i):nan (-3+0i):foo (7+1i):bar (7+2i):bar2 (+Inf+0i):inf", 108 }, 109 { 110 map[bool]string{true: "true", false: "false"}, 111 "false:false true:true", 112 }, 113 { 114 chanMap(), 115 "CHAN0:0 CHAN1:1 CHAN2:2", 116 }, 117 { 118 pointerMap(), 119 "PTR0:0 PTR1:1 PTR2:2", 120 }, 121 { 122 map[toy]string{toy{7, 2}: "72", toy{7, 1}: "71", toy{3, 4}: "34"}, 123 "{3 4}:34 {7 1}:71 {7 2}:72", 124 }, 125 { 126 map[[2]int]string{{7, 2}: "72", {7, 1}: "71", {3, 4}: "34"}, 127 "[3 4]:34 [7 1]:71 [7 2]:72", 128 }, 129 { 130 map[interface{}]string{7: "7", 4: "4", 3: "3", nil: "nil"}, 131 "<nil>:nil 3:3 4:4 7:7", 132 }, 133 } 134 135 func sprint(data interface{}) string { 136 om := fmtsort.Sort(reflect.ValueOf(data)) 137 if om == nil { 138 return "nil" 139 } 140 b := new(strings.Builder) 141 for i, key := range om.Key { 142 if i > 0 { 143 b.WriteRune(' ') 144 } 145 b.WriteString(sprintKey(key)) 146 b.WriteRune(':') 147 b.WriteString(fmt.Sprint(om.Value[i])) 148 } 149 return b.String() 150 } 151 152 // sprintKey formats a reflect.Value but gives reproducible values for some 153 // problematic types such as pointers. Note that it only does special handling 154 // for the troublesome types used in the test cases; it is not a general 155 // printer. 156 func sprintKey(key reflect.Value) string { 157 switch str := key.Type().String(); str { 158 case "*int": 159 ptr := key.Interface().(*int) 160 for i := range ints { 161 if ptr == &ints[i] { 162 return fmt.Sprintf("PTR%d", i) 163 } 164 } 165 return "PTR???" 166 case "chan int": 167 c := key.Interface().(chan int) 168 for i := range chans { 169 if c == chans[i] { 170 return fmt.Sprintf("CHAN%d", i) 171 } 172 } 173 return "CHAN???" 174 default: 175 return fmt.Sprint(key) 176 } 177 } 178 179 var ( 180 ints [3]int 181 chans = [3]chan int{make(chan int), make(chan int), make(chan int)} 182 ) 183 184 func pointerMap() map[*int]string { 185 m := make(map[*int]string) 186 for i := 2; i >= 0; i-- { 187 m[&ints[i]] = fmt.Sprint(i) 188 } 189 return m 190 } 191 192 func chanMap() map[chan int]string { 193 m := make(map[chan int]string) 194 for i := 2; i >= 0; i-- { 195 m[chans[i]] = fmt.Sprint(i) 196 } 197 return m 198 } 199 200 type toy struct { 201 A int // Exported. 202 b int // Unexported. 203 } 204 205 func TestOrder(t *testing.T) { 206 for _, test := range sortTests { 207 got := sprint(test.data) 208 if got != test.print { 209 t.Errorf("%s: got %q, want %q", reflect.TypeOf(test.data), got, test.print) 210 } 211 } 212 }