github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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  }