github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/sortx/intersort_test.go (about)

     1  package sortx
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"math/rand"
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  )
    11  
    12  func TestSingleType(t *testing.T) {
    13  	ptrArray := [2]int{2, 1}
    14  	chanArray := [2]chan int{make(chan int), make(chan int)}
    15  
    16  	tests := []struct {
    17  		desc   string
    18  		orig   interface{}
    19  		sorted interface{}
    20  	}{
    21  		{
    22  			// "When applicable, nil compares low"
    23  			desc:   "Nil",
    24  			orig:   []*int{&ptrArray[0], (*int)(nil)},
    25  			sorted: []*int{nil, &ptrArray[0]},
    26  		},
    27  		{
    28  			// "ints, floats, and strings order by <"
    29  			desc:   "Ints",
    30  			orig:   []int{3, 2, 1},
    31  			sorted: []int{1, 2, 3},
    32  		},
    33  		{
    34  			// "ints, floats, and strings order by <"
    35  			desc:   "Floats",
    36  			orig:   []float64{3.1, 2.1, 1.1},
    37  			sorted: []float64{1.1, 2.1, 3.1},
    38  		},
    39  		{
    40  			// "ints, floats, and strings order by <"
    41  			desc:   "Strings",
    42  			orig:   []string{"c", "b", "a"},
    43  			sorted: []string{"a", "b", "c"},
    44  		},
    45  		{
    46  			// "NaN compares less than non-NaN floats"
    47  			desc:   "NaN",
    48  			orig:   []float64{3.1, 2.1, math.NaN()},
    49  			sorted: []float64{math.NaN(), 2.1, 3.1},
    50  		},
    51  		{
    52  			// "bool compares false before true"
    53  			desc:   "Bool",
    54  			orig:   []bool{true, false},
    55  			sorted: []bool{false, true},
    56  		},
    57  		{
    58  			// "Complex compares real, then imaginary"
    59  			desc:   "Complex",
    60  			orig:   []complex128{2 + 1i, 1 + 2i},
    61  			sorted: []complex128{1 + 2i, 2 + 1i},
    62  		},
    63  		{
    64  			// "Pointers compare by machine address"
    65  			desc:   "Pointers",
    66  			orig:   []*int{&ptrArray[1], &ptrArray[0]},
    67  			sorted: []*int{&ptrArray[0], &ptrArray[1]},
    68  		},
    69  		{
    70  			// "Channel values compare by machine address"
    71  			desc:   "Channel",
    72  			orig:   []chan int{chanArray[1], chanArray[0]},
    73  			sorted: []chan int{chanArray[0], chanArray[1]},
    74  		},
    75  		{
    76  			// "Structs compare each field in turn"
    77  			desc:   "Structs",
    78  			orig:   []struct{ x, y int }{{1, 0}, {0, 1}},
    79  			sorted: []struct{ x, y int }{{0, 1}, {1, 0}},
    80  		},
    81  		{
    82  			// "Arrays compare each element in turn"
    83  			desc:   "Arrays",
    84  			orig:   [][2]int{{1, 0}, {0, 1}},
    85  			sorted: [][2]int{{0, 1}, {1, 0}},
    86  		},
    87  	}
    88  	for _, test := range tests {
    89  		t.Run(test.desc, func(t *testing.T) {
    90  			Sort(test.orig)
    91  			// can't use reflect.DeepEqual, since NaN != NaN
    92  			if fmt.Sprint(test.orig) != fmt.Sprint(test.sorted) {
    93  				t.Fatalf("expected %#v, got %#v", test.sorted, test.orig)
    94  			}
    95  		})
    96  	}
    97  }
    98  
    99  // "Interface values compare first by reflect.Type describing the
   100  // concrete type and then by concrete value as described in the
   101  // previous rules."
   102  func TestMultiType(t *testing.T) {
   103  	ptrArray := [2]int{2, 1}
   104  	chanArray := [2]chan int{make(chan int), make(chan int)}
   105  
   106  	// Unfortunately, sorting is unpredictable because it compares the machine
   107  	// addresses of the *reflect.rtype pointers. But we can at least assert that
   108  	// the result contains all sorted subgroups.
   109  	groups := [][]interface{}{
   110  		{(*int)(nil), &ptrArray[0], &ptrArray[1]},
   111  		{1, 2, 3},
   112  		{"a", "b", "c"},
   113  		{false, true},
   114  		{1 + 2i, 2 + 1i},
   115  		{chanArray[0], chanArray[1]},
   116  		{struct{ x, y int }{0, 1}, struct{ x, y int }{1, 0}},
   117  		{[2]int{0, 1}, [2]int{1, 0}},
   118  	}
   119  
   120  	var elems Slice
   121  	for _, g := range groups {
   122  		elems = append(elems, g...)
   123  	}
   124  	rand.Shuffle(len(elems), elems.Swap) // nice
   125  
   126  	sort.Sort(elems)
   127  	str := fmt.Sprint(elems)
   128  	for _, g := range groups {
   129  		exp := strings.TrimSpace(fmt.Sprintln(g...))
   130  		if !strings.Contains(str, exp) {
   131  			t.Errorf("sorted map should contain %q", exp)
   132  		}
   133  	}
   134  }