github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/utils/slices_test.go (about) 1 /* 2 Copyright 2022 Gravitational, Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package utils 18 19 import ( 20 "bytes" 21 "strconv" 22 "testing" 23 24 "github.com/stretchr/testify/require" 25 ) 26 27 func TestDeduplicate(t *testing.T) { 28 tests := []struct { 29 name string 30 in, expected []string 31 }{ 32 {name: "empty slice", in: []string{}, expected: []string{}}, 33 {name: "slice with unique elements", in: []string{"a", "b"}, expected: []string{"a", "b"}}, 34 {name: "slice with duplicate elements", in: []string{"a", "b", "b", "a", "c"}, expected: []string{"a", "b", "c"}}, 35 } 36 for _, tc := range tests { 37 t.Run(tc.name, func(t *testing.T) { 38 require.Equal(t, tc.expected, Deduplicate(tc.in)) 39 }) 40 } 41 } 42 43 func TestDeduplicateAny(t *testing.T) { 44 tests := []struct { 45 name string 46 in, expected [][]byte 47 }{ 48 {name: "empty slice", in: [][]byte{}, expected: [][]byte{}}, 49 {name: "slice with unique elements", in: [][]byte{{0}, {1}}, expected: [][]byte{{0}, {1}}}, 50 {name: "slice with duplicate elements", in: [][]byte{{0}, {1}, {1}, {0}, {2}}, expected: [][]byte{{0}, {1}, {2}}}, 51 } 52 for _, tc := range tests { 53 t.Run(tc.name, func(t *testing.T) { 54 require.Equal(t, tc.expected, DeduplicateAny(tc.in, bytes.Equal)) 55 }) 56 } 57 } 58 59 func TestContainSameUniqueElements(t *testing.T) { 60 tests := []struct { 61 name string 62 s1 []string 63 s2 []string 64 check require.BoolAssertionFunc 65 }{ 66 { 67 name: "empty", 68 s1: nil, 69 s2: []string{}, 70 check: require.True, 71 }, 72 { 73 name: "same", 74 s1: []string{"a", "b", "c"}, 75 s2: []string{"a", "b", "c"}, 76 check: require.True, 77 }, 78 { 79 name: "same with different order", 80 s1: []string{"b", "c", "a"}, 81 s2: []string{"a", "b", "c"}, 82 check: require.True, 83 }, 84 { 85 name: "same with duplicates", 86 s1: []string{"a", "a", "b", "c"}, 87 s2: []string{"c", "c", "a", "b", "c", "c"}, 88 check: require.True, 89 }, 90 { 91 name: "different", 92 s1: []string{"a", "b"}, 93 s2: []string{"a", "b", "c"}, 94 check: require.False, 95 }, 96 { 97 name: "different (same length)", 98 s1: []string{"d", "a", "b"}, 99 s2: []string{"a", "b", "c"}, 100 check: require.False, 101 }, 102 } 103 104 for _, test := range tests { 105 t.Run(test.name, func(t *testing.T) { 106 test.check(t, ContainSameUniqueElements(test.s1, test.s2)) 107 }) 108 } 109 } 110 111 func TestAny(t *testing.T) { 112 tests := []struct { 113 name string 114 inputSlice []int 115 predicate func(e int) bool 116 expected bool 117 }{ 118 { 119 name: "empty slice", 120 inputSlice: []int{}, 121 predicate: func(e int) bool { return e > 0 }, 122 expected: false, 123 }, 124 { 125 name: "non-empty slice with matching element", 126 inputSlice: []int{1, 2, 3}, 127 predicate: func(e int) bool { return e > 0 }, 128 expected: true, 129 }, 130 { 131 name: "non-empty slice with no matching element", 132 inputSlice: []int{-1, -2, -3}, 133 predicate: func(e int) bool { return e > 0 }, 134 expected: false, 135 }, 136 } 137 138 for _, tt := range tests { 139 t.Run(tt.name, func(t *testing.T) { 140 require.Equal(t, tt.expected, Any(tt.inputSlice, tt.predicate)) 141 }) 142 } 143 } 144 145 func TestAll(t *testing.T) { 146 tests := []struct { 147 name string 148 inputSlice []int 149 predicate func(e int) bool 150 expected bool 151 }{ 152 { 153 name: "empty slice", 154 inputSlice: []int{}, 155 predicate: func(e int) bool { return e > 0 }, 156 expected: true, 157 }, 158 { 159 name: "non-empty slice with all matching elements", 160 inputSlice: []int{1, 2, 3}, 161 predicate: func(e int) bool { return e > 0 }, 162 expected: true, 163 }, 164 { 165 name: "non-empty slice with at least one non-matching element", 166 inputSlice: []int{1, 2, -3}, 167 predicate: func(e int) bool { return e > 0 }, 168 expected: false, 169 }, 170 } 171 172 for _, tt := range tests { 173 t.Run(tt.name, func(t *testing.T) { 174 require.Equal(t, tt.expected, All(tt.inputSlice, tt.predicate)) 175 }) 176 } 177 } 178 179 func TestCountBy(t *testing.T) { 180 type testCase struct { 181 name string 182 elements []int 183 mapper func(int) string 184 want map[string]int 185 } 186 tests := []testCase{ 187 { 188 name: "empty slice", 189 elements: nil, 190 mapper: nil, 191 want: make(map[string]int), 192 }, 193 { 194 name: "identity", 195 elements: []int{1, 2, 3, 4}, 196 mapper: strconv.Itoa, 197 want: map[string]int{ 198 "1": 1, 199 "2": 1, 200 "3": 1, 201 "4": 1, 202 }, 203 }, 204 { 205 name: "even-odd", 206 elements: []int{1, 2, 3, 4}, 207 mapper: func(i int) string { 208 if i%2 == 0 { 209 return "even" 210 } 211 return "odd" 212 }, 213 want: map[string]int{ 214 "odd": 2, 215 "even": 2, 216 }, 217 }, 218 } 219 for _, tt := range tests { 220 t.Run(tt.name, func(t *testing.T) { 221 got := CountBy(tt.elements, tt.mapper) 222 require.Equal(t, tt.want, got) 223 }) 224 } 225 }