Skip to content

Commit

Permalink
[test] Optimizations, improvements, and unit tests for common/common.…
Browse files Browse the repository at this point in the history
…go (part 2 of 3) (#182)

* test: Add unit-tests for Contains (#167)

* refactor: Add comment to Contains (#167)

* test: Add unit-tests for Map (#167)

* refactor: Add comment to Map (#167)

* refactor: Add names to Map test cases (#167)

* test: Add unit-tests for SliceCopy (#167)

* refactor: Add comment to SliceCopy (#167)

* test: Add unit-tests for ReverseSlice (#167)

* refactor: Add comment to ReverseSlice (#167)

* test: Add unit-tests for MergeMapStringString (#167)

* refactor: Add missing import 'reflect'
  • Loading branch information
art-tapin committed May 10, 2023
1 parent 0c5d79b commit dcad23a
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 0 deletions.
5 changes: 5 additions & 0 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ func NamespacedNameToObjectKey(namespacedName, defaultNamespace string) client.O
return client.ObjectKey{Namespace: defaultNamespace, Name: namespacedName}
}

// Contains checks if the given target string is present in the slice of strings 'slice'.
// It returns true if the target string is found in the slice, false otherwise.
func Contains(slice []string, target string) bool {
for idx := range slice {
if slice[idx] == target {
Expand All @@ -103,6 +105,7 @@ func Find[T any](slice []T, match func(T) bool) (*T, bool) {
return nil, false
}

// Map applies the given mapper function to each element in the input slice and returns a new slice with the results.
func Map[T, U any](slice []T, f func(T) U) []U {
arr := make([]U, len(slice))
for i, e := range slice {
Expand All @@ -111,12 +114,14 @@ func Map[T, U any](slice []T, f func(T) U) []U {
return arr
}

// SliceCopy copies the elements from the input slice into the output slice, and returns the output slice.
func SliceCopy[T any](s1 []T) []T {
s2 := make([]T, len(s1))
copy(s2, s1)
return s2
}

// ReverseSlice creates a reversed copy of the input slice.
func ReverseSlice[T any](input []T) []T {
inputLen := len(input)
output := make([]T, inputLen)
Expand Down
206 changes: 206 additions & 0 deletions pkg/common/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,209 @@ func TestNamespacedNameToObjectKey(t *testing.T) {
}
})
}

func TestContains(t *testing.T) {
testCases := []struct {
name string
slice []string
target string
expected bool
}{
{
name: "when slice has one target item then return true",
slice: []string{"test-gw"},
target: "test-gw",
expected: true,
},
{
name: "when slice is empty then return false",
slice: []string{},
target: "test-gw",
expected: false,
},
{
name: "when target is in a slice then return true",
slice: []string{"test-gw1", "test-gw2", "test-gw3"},
target: "test-gw2",
expected: true,
},
{
name: "when no target in a slice then return false",
slice: []string{"test-gw1", "test-gw2", "test-gw3"},
target: "test-gw4",
expected: false,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if Contains(tc.slice, tc.target) != tc.expected {
t.Errorf("when slice=%v and target=%s, expected=%v, but got=%v", tc.slice, tc.target, tc.expected, !tc.expected)
}
})
}
}

func TestMap(t *testing.T) {
slice1 := []int{1, 2, 3, 4}
f1 := func(x int) int { return x + 1 }
expected1 := []int{2, 3, 4, 5}
result1 := Map(slice1, f1)
t.Run("when mapping an int slice with an increment function then return new slice with the incremented values", func(t *testing.T) {
if !reflect.DeepEqual(result1, expected1) {
t.Errorf("result1 = %v; expected %v", result1, expected1)
}
})

slice2 := []string{"hello", "world", "buz", "a"}
f2 := func(s string) int { return len(s) }
expected2 := []int{5, 5, 3, 1}
result2 := Map(slice2, f2)
t.Run("when mapping a string slice with string->int mapping then return new slice with the mapped values", func(t *testing.T) {
if !reflect.DeepEqual(result2, expected2) {
t.Errorf("result2 = %v; expected %v", result2, expected2)
}
})

slice3 := []int{}
f3 := func(x int) float32 { return float32(x) / 2 }
expected3 := []float32{}
result3 := Map(slice3, f3)
t.Run("when mapping an empty int slice then return an empty slice", func(t *testing.T) {
if !reflect.DeepEqual(result3, expected3) {
t.Errorf("result3 = %v; expected %v", result3, expected3)
}
})
}

func TestSliceCopy(t *testing.T) {
input1 := []int{1, 2, 3}
expected1 := []int{1, 2, 3}
output1 := SliceCopy(input1)
t.Run("when given slice of integers then return a copy of the input slice", func(t *testing.T) {
if !reflect.DeepEqual(output1, expected1) {
t.Errorf("SliceCopy(%v) = %v; expected %v", input1, output1, expected1)
}
})

input2 := []string{"foo", "bar", "baz"}
expected2 := []string{"foo", "bar", "baz"}
output2 := SliceCopy(input2)
t.Run("when given slice of strings then return a copy of the input slice", func(t *testing.T) {
if !reflect.DeepEqual(output2, expected2) {
t.Errorf("SliceCopy(%v) = %v; expected %v", input2, output2, expected2)
}
})

type person struct {
name string
age int
}
input3 := []person{{"Artem", 65}, {"DD", 18}, {"Charlie", 23}}
expected3 := []person{{"Artem", 65}, {"DD", 18}, {"Charlie", 23}}
output3 := SliceCopy(input3)
t.Run("when given slice of structs then return a copy of the input slice", func(t *testing.T) {
if !reflect.DeepEqual(output3, expected3) {
t.Errorf("SliceCopy(%v) = %v; expected %v", input3, output3, expected3)
}
})

input4 := []int{1, 2, 3}
expected4 := []int{1, 2, 3}
output4 := SliceCopy(input4)
t.Run("when modifying the original input slice then does not affect the returned copy", func(t *testing.T) {
if !reflect.DeepEqual(output4, expected4) {
t.Errorf("SliceCopy(%v) = %v; expected %v", input4, output4, expected4)
}
input4[0] = 4
if reflect.DeepEqual(output4, input4) {
t.Errorf("modifying the original input slice should not change the output slice")
}
})
}

func TestReverseSlice(t *testing.T) {
input1 := []int{1, 2, 3}
expected1 := []int{3, 2, 1}
output1 := ReverseSlice(input1)
t.Run("when given slice of integers then return reversed copy of the input slice", func(t *testing.T) {
if !reflect.DeepEqual(output1, expected1) {
t.Errorf("ReverseSlice(%v) = %v; expected %v", input1, output1, expected1)
}
})

input2 := []string{"foo", "bar", "baz"}
expected2 := []string{"baz", "bar", "foo"}
output2 := ReverseSlice(input2)
t.Run("when given slice of strings then return reversed copy of the input slice", func(t *testing.T) {
if !reflect.DeepEqual(output2, expected2) {
t.Errorf("ReverseSlice(%v) = %v; expected %v", input2, output2, expected2)
}
})

input3 := []int{}
expected3 := []int{}
output3 := ReverseSlice(input3)
t.Run("when given an empty slice then return empty slice", func(t *testing.T) {
if !reflect.DeepEqual(output3, expected3) {
t.Errorf("ReverseSlice(%v) = %v; expected %v", input3, output3, expected3)
}
})
}

func TestMergeMapStringString(t *testing.T) {
testCases := []struct {
name string
existing map[string]string
desired map[string]string
expected bool
expectedState map[string]string
}{
{
name: "when existing and desired are empty then return false and not modify the existing map",
existing: map[string]string{},
desired: map[string]string{},
expected: false,
expectedState: map[string]string{},
},
{
name: "when existing is empty and desired has values then return true and set the values in the existing map",
existing: map[string]string{},
desired: map[string]string{"a": "1", "b": "2"},
expected: true,
expectedState: map[string]string{"a": "1", "b": "2"},
},
{
name: "when existing has some values and desired has different/new values then return true and modify the existing map",
existing: map[string]string{"a": "1", "b": "2"},
desired: map[string]string{"a": "3", "c": "4"},
expected: true,
expectedState: map[string]string{"a": "3", "b": "2", "c": "4"},
},
{
name: "when existing has all the values from desired then return false and not modify the existing map",
existing: map[string]string{"a": "1", "b": "2"},
desired: map[string]string{"a": "1", "b": "2"},
expected: false,
expectedState: map[string]string{"a": "1", "b": "2"},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
existingCopy := make(map[string]string, len(tc.existing))
for k, v := range tc.existing {
existingCopy[k] = v
}
modified := MergeMapStringString(&existingCopy, tc.desired)

if modified != tc.expected {
t.Errorf("MergeMapStringString(%v, %v) returned %v; expected %v", tc.existing, tc.desired, modified, tc.expected)
}

if !reflect.DeepEqual(existingCopy, tc.expectedState) {
t.Errorf("MergeMapStringString(%v, %v) modified the existing map to %v; expected %v", tc.existing, tc.desired, existingCopy, tc.expectedState)
}
})
}
}

0 comments on commit dcad23a

Please sign in to comment.