]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmp/cmp_test.go
cmp: add Or
[gostls13.git] / src / cmp / cmp_test.go
1 // Copyright 2023 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 cmp_test
6
7 import (
8         "cmp"
9         "fmt"
10         "math"
11         "sort"
12         "slices"
13         "testing"
14 )
15
16 var negzero = math.Copysign(0, -1)
17
18 var tests = []struct {
19         x, y    any
20         compare int
21 }{
22         {1, 2, -1},
23         {1, 1, 0},
24         {2, 1, +1},
25         {"a", "aa", -1},
26         {"a", "a", 0},
27         {"aa", "a", +1},
28         {1.0, 1.1, -1},
29         {1.1, 1.1, 0},
30         {1.1, 1.0, +1},
31         {math.Inf(1), math.Inf(1), 0},
32         {math.Inf(-1), math.Inf(-1), 0},
33         {math.Inf(-1), 1.0, -1},
34         {1.0, math.Inf(-1), +1},
35         {math.Inf(1), 1.0, +1},
36         {1.0, math.Inf(1), -1},
37         {math.NaN(), math.NaN(), 0},
38         {0.0, math.NaN(), +1},
39         {math.NaN(), 0.0, -1},
40         {math.NaN(), math.Inf(-1), -1},
41         {math.Inf(-1), math.NaN(), +1},
42         {0.0, 0.0, 0},
43         {negzero, negzero, 0},
44         {negzero, 0.0, 0},
45         {0.0, negzero, 0},
46         {negzero, 1.0, -1},
47         {negzero, -1.0, +1},
48 }
49
50 func TestLess(t *testing.T) {
51         for _, test := range tests {
52                 var b bool
53                 switch test.x.(type) {
54                 case int:
55                         b = cmp.Less(test.x.(int), test.y.(int))
56                 case string:
57                         b = cmp.Less(test.x.(string), test.y.(string))
58                 case float64:
59                         b = cmp.Less(test.x.(float64), test.y.(float64))
60                 }
61                 if b != (test.compare < 0) {
62                         t.Errorf("Less(%v, %v) == %t, want %t", test.x, test.y, b, test.compare < 0)
63                 }
64         }
65 }
66
67 func TestCompare(t *testing.T) {
68         for _, test := range tests {
69                 var c int
70                 switch test.x.(type) {
71                 case int:
72                         c = cmp.Compare(test.x.(int), test.y.(int))
73                 case string:
74                         c = cmp.Compare(test.x.(string), test.y.(string))
75                 case float64:
76                         c = cmp.Compare(test.x.(float64), test.y.(float64))
77                 }
78                 if c != test.compare {
79                         t.Errorf("Compare(%v, %v) == %d, want %d", test.x, test.y, c, test.compare)
80                 }
81         }
82 }
83
84 func TestSort(t *testing.T) {
85         // Test that our comparison function is consistent with
86         // sort.Float64s.
87         input := []float64{1.0, 0.0, negzero, math.Inf(1), math.Inf(-1), math.NaN()}
88         sort.Float64s(input)
89         for i := 0; i < len(input)-1; i++ {
90                 if cmp.Less(input[i+1], input[i]) {
91                         t.Errorf("Less sort mismatch at %d in %v", i, input)
92                 }
93                 if cmp.Compare(input[i], input[i+1]) > 0 {
94                         t.Errorf("Compare sort mismatch at %d in %v", i, input)
95                 }
96         }
97 }
98
99 func TestOr(t *testing.T) {
100         cases := []struct {
101                 in   []int
102                 want int
103         }{
104                 {nil, 0},
105                 {[]int{0}, 0},
106                 {[]int{1}, 1},
107                 {[]int{0, 2}, 2},
108                 {[]int{3, 0}, 3},
109                 {[]int{4, 5}, 4},
110                 {[]int{0, 6, 7}, 6},
111         }
112         for _, tc := range cases {
113                 if got := cmp.Or(tc.in...); got != tc.want {
114                         t.Errorf("cmp.Or(%v) = %v; want %v", tc.in, got, tc.want)
115                 }
116         }
117 }
118
119 func ExampleOr() {
120         // Suppose we have some user input
121         // that may or may not be an empty string
122         userInput1 := ""
123         userInput2 := "some text"
124
125         fmt.Println(cmp.Or(userInput1, "default"))
126         fmt.Println(cmp.Or(userInput2, "default"))
127         fmt.Println(cmp.Or(userInput1, userInput2, "default"))
128         // Output:
129         // default
130         // some text
131         // some text
132 }
133
134 func ExampleOr_sort() {
135         type Order struct {
136                 Product string
137                 Customer string
138                 Price float64
139         }
140         orders := []Order{
141                 {"foo", "alice", 1.00},
142                 {"bar", "bob", 3.00},
143                 {"baz", "carol", 4.00},
144                 {"foo", "alice", 2.00},
145                 {"bar", "carol", 1.00},
146                 {"foo", "bob", 4.00},
147         }
148         // Sort by customer first, product second, and last by higher price
149         slices.SortFunc(orders, func(a, b Order) int {
150                 return cmp.Or(
151                         cmp.Compare(a.Customer, b.Customer),
152                         cmp.Compare(a.Product, b.Product),
153                         cmp.Compare(b.Price, a.Price),
154                 )
155         })
156         for _, order := range orders {
157                 fmt.Printf("%s %s %.2f\n", order.Product, order.Customer, order.Price)
158         }
159
160         // Output:
161         // foo alice 2.00
162         // foo alice 1.00
163         // bar bob 3.00
164         // foo bob 4.00
165         // bar carol 1.00
166         // baz carol 4.00
167 }