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  }