From bff5d1912129d11cb088a62302507d5b07cf7f1d Mon Sep 17 00:00:00 2001 From: Ruslan Semagin Date: Tue, 27 May 2025 15:17:21 +0300 Subject: [PATCH] common/collections: Increase test coverage --- common/collections/append_test.go | 65 ++++++++++++++++++++++++++ common/collections/slice_test.go | 34 ++++++++++++++ common/collections/stack_test.go | 77 +++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 common/collections/stack_test.go diff --git a/common/collections/append_test.go b/common/collections/append_test.go index f791b731a..62d9015ce 100644 --- a/common/collections/append_test.go +++ b/common/collections/append_test.go @@ -15,6 +15,7 @@ package collections import ( "html/template" + "reflect" "testing" qt "github.com/frankban/quicktest" @@ -77,6 +78,7 @@ func TestAppend(t *testing.T) { {[]string{"a", "b"}, []any{nil}, []any{"a", "b", nil}}, {[]string{"a", "b"}, []any{nil, "d", nil}, []any{"a", "b", nil, "d", nil}}, {[]any{"a", nil, "c"}, []any{"d", nil, "f"}, []any{"a", nil, "c", "d", nil, "f"}}, + {[]string{"a", "b"}, []any{}, []string{"a", "b"}}, } { result, err := Append(test.start, test.addend...) @@ -146,3 +148,66 @@ func TestAppendShouldMakeACopyOfTheInputSlice(t *testing.T) { c.Assert(result, qt.DeepEquals, []string{"a", "b", "c"}) c.Assert(slice, qt.DeepEquals, []string{"d", "b"}) } + +func TestIndirect(t *testing.T) { + t.Parallel() + c := qt.New(t) + + type testStruct struct { + Field string + } + + var ( + nilPtr *testStruct + nilIface interface{} = nil + nonNilIface interface{} = &testStruct{Field: "hello"} + ) + + tests := []struct { + name string + input any + wantKind reflect.Kind + wantNil bool + }{ + { + name: "nil pointer", + input: nilPtr, + wantKind: reflect.Ptr, + wantNil: true, + }, + { + name: "nil interface", + input: nilIface, + wantKind: reflect.Invalid, + wantNil: false, + }, + { + name: "non-nil pointer to struct", + input: &testStruct{Field: "abc"}, + wantKind: reflect.Struct, + wantNil: false, + }, + { + name: "non-nil interface holding pointer", + input: nonNilIface, + wantKind: reflect.Struct, + wantNil: false, + }, + { + name: "plain value", + input: testStruct{Field: "xyz"}, + wantKind: reflect.Struct, + wantNil: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + v := reflect.ValueOf(tt.input) + got, isNil := indirect(v) + + c.Assert(got.Kind(), qt.Equals, tt.wantKind) + c.Assert(isNil, qt.Equals, tt.wantNil) + }) + } +} diff --git a/common/collections/slice_test.go b/common/collections/slice_test.go index 20961aac0..4008a5e6c 100644 --- a/common/collections/slice_test.go +++ b/common/collections/slice_test.go @@ -136,3 +136,37 @@ func TestSortedStringSlice(t *testing.T) { c.Assert(s.Count("z"), qt.Equals, 0) c.Assert(s.Count("a"), qt.Equals, 1) } + +func TestStringSliceToInterfaceSlice(t *testing.T) { + t.Parallel() + c := qt.New(t) + + tests := []struct { + name string + in []string + want []any + }{ + { + name: "empty slice", + in: []string{}, + want: []any{}, + }, + { + name: "single element", + in: []string{"hello"}, + want: []any{"hello"}, + }, + { + name: "multiple elements", + in: []string{"a", "b", "c"}, + want: []any{"a", "b", "c"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := StringSliceToInterfaceSlice(tt.in) + c.Assert(got, qt.DeepEquals, tt.want) + }) + } +} diff --git a/common/collections/stack_test.go b/common/collections/stack_test.go new file mode 100644 index 000000000..965d4dbc8 --- /dev/null +++ b/common/collections/stack_test.go @@ -0,0 +1,77 @@ +package collections + +import ( + "testing" + + qt "github.com/frankban/quicktest" +) + +func TestNewStack(t *testing.T) { + t.Parallel() + c := qt.New(t) + + s := NewStack[int]() + + c.Assert(s, qt.IsNotNil) +} + +func TestStackBasic(t *testing.T) { + t.Parallel() + c := qt.New(t) + + s := NewStack[int]() + + c.Assert(s.Len(), qt.Equals, 0) + + s.Push(1) + s.Push(2) + s.Push(3) + + c.Assert(s.Len(), qt.Equals, 3) + + top, ok := s.Peek() + c.Assert(ok, qt.Equals, true) + c.Assert(top, qt.Equals, 3) + + popped, ok := s.Pop() + c.Assert(ok, qt.Equals, true) + c.Assert(popped, qt.Equals, 3) + + c.Assert(s.Len(), qt.Equals, 2) + + _, _ = s.Pop() + _, _ = s.Pop() + _, ok = s.Pop() + + c.Assert(ok, qt.Equals, false) +} + +func TestStackDrain(t *testing.T) { + t.Parallel() + c := qt.New(t) + + s := NewStack[string]() + s.Push("a") + s.Push("b") + + got := s.Drain() + + c.Assert(got, qt.DeepEquals, []string{"a", "b"}) + c.Assert(s.Len(), qt.Equals, 0) +} + +func TestStackDrainMatching(t *testing.T) { + t.Parallel() + c := qt.New(t) + + s := NewStack[int]() + s.Push(1) + s.Push(2) + s.Push(3) + s.Push(4) + + got := s.DrainMatching(func(v int) bool { return v%2 == 0 }) + + c.Assert(got, qt.DeepEquals, []int{4, 2}) + c.Assert(s.Drain(), qt.DeepEquals, []int{1, 3}) +}