From 8c2fc884717c3bbe6a3644a7b5442889b59936db Mon Sep 17 00:00:00 2001 From: Jian Lim <85569173+LimJiAn@users.noreply.github.com> Date: Fri, 1 Sep 2023 16:05:27 +0900 Subject: [PATCH] Refactor: func StringInSlice to slices.Contains (#24262) * Refactor: Use generic to change func StringInSlice to Contains * Refactor: Use generic to change func stringNotInSlice to Contains Make utils.go (dir server/public/utils) and func Contains * Refactor: Move func Contains from channels/utils to public/utils Move func Contains from channels/utils to public/utils Fix import declarations line * Docs: Add a description of the Contains function * Test: add TestContains Add a test code for a Contain function --- server/channels/api4/user.go | 4 +- server/channels/api4/user_local.go | 4 +- server/channels/app/channel.go | 7 +- server/channels/app/notification_test.go | 9 +- server/channels/app/plugin_signature.go | 4 +- server/channels/app/role.go | 6 +- server/channels/app/role_test.go | 10 +- server/channels/store/searchtest/testlib.go | 7 +- .../channels/store/storetest/group_store.go | 6 +- server/channels/utils/utils.go | 12 +- server/cmd/mmctl/commands/sampledata.go | 5 +- server/public/model/command_autocomplete.go | 13 +- server/public/utils/utils.go | 14 + server/public/utils/utils_test.go | 388 ++++++++++++++++++ 14 files changed, 443 insertions(+), 46 deletions(-) create mode 100644 server/public/utils/utils.go create mode 100644 server/public/utils/utils_test.go diff --git a/server/channels/api4/user.go b/server/channels/api4/user.go index bfa768d04c..053de727ee 100644 --- a/server/channels/api4/user.go +++ b/server/channels/api4/user.go @@ -14,6 +14,8 @@ import ( "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/shared/mlog" + pUtils "github.com/mattermost/mattermost/server/public/utils" + "github.com/mattermost/mattermost/server/v8/channels/app" "github.com/mattermost/mattermost/server/v8/channels/audit" "github.com/mattermost/mattermost/server/v8/channels/store" @@ -722,7 +724,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { c.SetInvalidParam("role") return } - roleValid := utils.StringInSlice(role, roleNamesAll) + roleValid := pUtils.Contains(roleNamesAll, role) if !roleValid { c.SetInvalidParam("role") return diff --git a/server/channels/api4/user_local.go b/server/channels/api4/user_local.go index f2e5a1fcdb..2171d14f7c 100644 --- a/server/channels/api4/user_local.go +++ b/server/channels/api4/user_local.go @@ -11,6 +11,8 @@ import ( "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/shared/mlog" + pUtils "github.com/mattermost/mattermost/server/public/utils" + "github.com/mattermost/mattermost/server/v8/channels/audit" "github.com/mattermost/mattermost/server/v8/channels/store" "github.com/mattermost/mattermost/server/v8/channels/utils" @@ -85,7 +87,7 @@ func localGetUsers(c *Context, w http.ResponseWriter, r *http.Request) { c.SetInvalidParam("role") return } - roleValid := utils.StringInSlice(role, roleNamesAll) + roleValid := pUtils.Contains(roleNamesAll, role) if !roleValid { c.SetInvalidParam("role") return diff --git a/server/channels/app/channel.go b/server/channels/app/channel.go index 80998a845f..4a0b97a704 100644 --- a/server/channels/app/channel.go +++ b/server/channels/app/channel.go @@ -15,11 +15,12 @@ import ( "github.com/mattermost/mattermost/server/public/plugin" "github.com/mattermost/mattermost/server/public/shared/i18n" "github.com/mattermost/mattermost/server/public/shared/mlog" + pUtils "github.com/mattermost/mattermost/server/public/utils" + "github.com/mattermost/mattermost/server/v8/channels/app/request" "github.com/mattermost/mattermost/server/v8/channels/product" "github.com/mattermost/mattermost/server/v8/channels/store" "github.com/mattermost/mattermost/server/v8/channels/store/sqlstore" - "github.com/mattermost/mattermost/server/v8/channels/utils" ) // channelsWrapper provides an implementation of `product.ChannelService` to be used by products. @@ -1103,7 +1104,7 @@ func (a *App) PatchChannelModerationsForChannel(c request.CTX, channel *model.Ch for _, channelModerationPatch := range channelModerationsPatch { permissionModified := *channelModerationPatch.Name - if channelModerationPatch.Roles.Guests != nil && utils.StringInSlice(permissionModified, model.ChannelModeratedPermissionsChangedByPatch(guestRole, guestRolePatch)) { + if channelModerationPatch.Roles.Guests != nil && pUtils.Contains(model.ChannelModeratedPermissionsChangedByPatch(guestRole, guestRolePatch), permissionModified) { if *channelModerationPatch.Roles.Guests { c.Logger().Info("Permission enabled for guests.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name)) } else { @@ -1111,7 +1112,7 @@ func (a *App) PatchChannelModerationsForChannel(c request.CTX, channel *model.Ch } } - if channelModerationPatch.Roles.Members != nil && utils.StringInSlice(permissionModified, model.ChannelModeratedPermissionsChangedByPatch(memberRole, memberRolePatch)) { + if channelModerationPatch.Roles.Members != nil && pUtils.Contains(model.ChannelModeratedPermissionsChangedByPatch(memberRole, memberRolePatch), permissionModified) { if *channelModerationPatch.Roles.Members { c.Logger().Info("Permission enabled for members.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name)) } else { diff --git a/server/channels/app/notification_test.go b/server/channels/app/notification_test.go index 621fa7703f..9dbf635996 100644 --- a/server/channels/app/notification_test.go +++ b/server/channels/app/notification_test.go @@ -13,8 +13,9 @@ import ( "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/shared/i18n" + pUtils "github.com/mattermost/mattermost/server/public/utils" + "github.com/mattermost/mattermost/server/v8/channels/store" - "github.com/mattermost/mattermost/server/v8/channels/utils" ) func getLicWithSkuShortName(skuShortName string) *model.License { @@ -49,7 +50,7 @@ func TestSendNotifications(t *testing.T) { mentions, err := th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true) require.NoError(t, err) require.NotNil(t, mentions) - require.True(t, utils.StringInSlice(th.BasicUser2.Id, mentions), "mentions", mentions) + require.True(t, pUtils.Contains(mentions, th.BasicUser2.Id), "mentions", mentions) t.Run("license is required for group mention", func(t *testing.T) { group := th.CreateGroup() @@ -145,7 +146,7 @@ func TestSendNotifications(t *testing.T) { } mentions, err = th.App.SendNotifications(th.Context, childPost, th.BasicTeam, th.BasicChannel, th.BasicUser2, &postList, true) require.NoError(t, err) - require.False(t, utils.StringInSlice(user.Id, mentions)) + require.False(t, pUtils.Contains(mentions, user.Id)) } th.BasicUser.NotifyProps[model.CommentsNotifyProp] = model.CommentsNotifyAny @@ -2815,7 +2816,7 @@ func TestReplyPostNotificationsWithCRT(t *testing.T) { } mentions, err := th.App.SendNotifications(th.Context, childPost, th.BasicTeam, th.BasicChannel, th.BasicUser2, &postList, true) require.NoError(t, err) - assert.False(t, utils.StringInSlice(user.Id, mentions)) + assert.False(t, pUtils.Contains(mentions, user.Id)) membership, err := th.App.GetThreadMembershipForUser(user.Id, rootPost.Id) assert.Error(t, err) diff --git a/server/channels/app/plugin_signature.go b/server/channels/app/plugin_signature.go index ad90cf3faa..9fefed3b6b 100644 --- a/server/channels/app/plugin_signature.go +++ b/server/channels/app/plugin_signature.go @@ -15,6 +15,8 @@ import ( "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/shared/mlog" + pUtils "github.com/mattermost/mattermost/server/public/utils" + "github.com/mattermost/mattermost/server/v8/channels/utils" ) @@ -46,7 +48,7 @@ func (a *App) AddPublicKey(name string, key io.Reader) *model.AppError { } a.UpdateConfig(func(cfg *model.Config) { - if !utils.StringInSlice(name, cfg.PluginSettings.SignaturePublicKeyFiles) { + if !pUtils.Contains(cfg.PluginSettings.SignaturePublicKeyFiles, name) { cfg.PluginSettings.SignaturePublicKeyFiles = append(cfg.PluginSettings.SignaturePublicKeyFiles, name) } }) diff --git a/server/channels/app/role.go b/server/channels/app/role.go index 15c95b1595..82a87fbc73 100644 --- a/server/channels/app/role.go +++ b/server/channels/app/role.go @@ -12,6 +12,8 @@ import ( "strings" "github.com/mattermost/mattermost/server/public/model" + pUtils "github.com/mattermost/mattermost/server/public/utils" + "github.com/mattermost/mattermost/server/v8/channels/store" "github.com/mattermost/mattermost/server/v8/channels/utils" ) @@ -187,13 +189,13 @@ func (a *App) UpdateRole(role *model.Role) (*model.Role, *model.AppError) { builtInRolesMinusChannelRoles := append(utils.RemoveStringsFromSlice(model.BuiltInSchemeManagedRoleIDs, builtInChannelRoles...), model.NewSystemRoleIDs...) - if utils.StringInSlice(savedRole.Name, builtInRolesMinusChannelRoles) { + if pUtils.Contains(builtInRolesMinusChannelRoles, savedRole.Name) { return savedRole, nil } var roleRetrievalFunc func() ([]*model.Role, *model.AppError) - if utils.StringInSlice(savedRole.Name, builtInChannelRoles) { + if pUtils.Contains(builtInChannelRoles, savedRole.Name) { roleRetrievalFunc = func() ([]*model.Role, *model.AppError) { roles, nErr := a.Srv().Store().Role().AllChannelSchemeRoles() if nErr != nil { diff --git a/server/channels/app/role_test.go b/server/channels/app/role_test.go index 04f9f9bd88..100de83a4f 100644 --- a/server/channels/app/role_test.go +++ b/server/channels/app/role_test.go @@ -15,7 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/mattermost/mattermost/server/public/model" - "github.com/mattermost/mattermost/server/v8/channels/utils" + pUtils "github.com/mattermost/mattermost/server/public/utils" ) type permissionInheritanceTestData struct { @@ -37,7 +37,7 @@ func TestGetRolesByNames(t *testing.T) { require.NotNil(t, actualRole) require.Equal(t, testData.channelRole.Name, actualRole.Name) - require.Equal(t, testData.shouldHavePermission, utils.StringInSlice(testData.permission.Id, actualRole.Permissions)) + require.Equal(t, testData.shouldHavePermission, pUtils.Contains(actualRole.Permissions, testData.permission.Id)) }) } @@ -47,7 +47,7 @@ func TestGetRoleByName(t *testing.T) { require.Nil(t, err) require.NotNil(t, actualRole) require.Equal(t, testData.channelRole.Name, actualRole.Name) - require.Equal(t, testData.shouldHavePermission, utils.StringInSlice(testData.permission.Id, actualRole.Permissions), "row: %+v", testData.truthTableRow) + require.Equal(t, testData.shouldHavePermission, pUtils.Contains(actualRole.Permissions, testData.permission.Id), "row: %+v", testData.truthTableRow) }) } @@ -57,7 +57,7 @@ func TestGetRoleByID(t *testing.T) { require.Nil(t, err) require.NotNil(t, actualRole) require.Equal(t, testData.channelRole.Id, actualRole.Id) - require.Equal(t, testData.shouldHavePermission, utils.StringInSlice(testData.permission.Id, actualRole.Permissions), "row: %+v", testData.truthTableRow) + require.Equal(t, testData.shouldHavePermission, pUtils.Contains(actualRole.Permissions, testData.permission.Id), "row: %+v", testData.truthTableRow) }) } @@ -69,7 +69,7 @@ func TestGetAllRoles(t *testing.T) { if actualRole.Id == testData.channelRole.Id { require.NotNil(t, actualRole) require.Equal(t, testData.channelRole.Id, actualRole.Id) - require.Equal(t, testData.shouldHavePermission, utils.StringInSlice(testData.permission.Id, actualRole.Permissions), "row: %+v", testData.truthTableRow) + require.Equal(t, testData.shouldHavePermission, pUtils.Contains(actualRole.Permissions, testData.permission.Id), "row: %+v", testData.truthTableRow) } } }) diff --git a/server/channels/store/searchtest/testlib.go b/server/channels/store/searchtest/testlib.go index 3a6c257bba..3777a9544a 100644 --- a/server/channels/store/searchtest/testlib.go +++ b/server/channels/store/searchtest/testlib.go @@ -6,8 +6,9 @@ package searchtest import ( "testing" + pUtils "github.com/mattermost/mattermost/server/public/utils" + "github.com/mattermost/mattermost/server/v8/channels/store" - "github.com/mattermost/mattermost/server/v8/channels/utils" ) const ( @@ -35,12 +36,12 @@ type searchTest struct { func filterTestsByTag(tests []searchTest, tags ...string) []searchTest { filteredTests := []searchTest{} for _, test := range tests { - if utils.StringInSlice(EngineAll, test.Tags) { + if pUtils.Contains(test.Tags, EngineAll) { filteredTests = append(filteredTests, test) continue } for _, tag := range tags { - if utils.StringInSlice(tag, test.Tags) { + if pUtils.Contains(test.Tags, tag) { filteredTests = append(filteredTests, test) break } diff --git a/server/channels/store/storetest/group_store.go b/server/channels/store/storetest/group_store.go index 427600d608..2e51beda2e 100644 --- a/server/channels/store/storetest/group_store.go +++ b/server/channels/store/storetest/group_store.go @@ -16,8 +16,8 @@ import ( "github.com/stretchr/testify/require" "github.com/mattermost/mattermost/server/public/model" + pUtils "github.com/mattermost/mattermost/server/public/utils" "github.com/mattermost/mattermost/server/v8/channels/store" - "github.com/mattermost/mattermost/server/v8/channels/utils" ) func TestGroupStore(t *testing.T, ss store.Store) { @@ -4825,7 +4825,7 @@ func groupTestpUpdateMembersRoleTeam(t *testing.T, ss store.Store) { require.GreaterOrEqual(t, len(members), 4) // sanity check for team membership for _, member := range members { - if utils.StringInSlice(member.UserId, tt.inUserIDs) { + if pUtils.Contains(tt.inUserIDs, member.UserId) { require.True(t, member.SchemeAdmin) } else { require.False(t, member.SchemeAdmin) @@ -4935,7 +4935,7 @@ func groupTestpUpdateMembersRoleChannel(t *testing.T, ss store.Store) { require.GreaterOrEqual(t, len(members), 4) // sanity check for channel membership for _, member := range members { - if utils.StringInSlice(member.UserId, tt.inUserIDs) { + if pUtils.Contains(tt.inUserIDs, member.UserId) { require.True(t, member.SchemeAdmin) } else { require.False(t, member.SchemeAdmin) diff --git a/server/channels/utils/utils.go b/server/channels/utils/utils.go index 4f257536aa..7e0cd20e1c 100644 --- a/server/channels/utils/utils.go +++ b/server/channels/utils/utils.go @@ -14,17 +14,9 @@ import ( "github.com/pkg/errors" "github.com/mattermost/mattermost/server/public/model" + pUtils "github.com/mattermost/mattermost/server/public/utils" ) -func StringInSlice(a string, slice []string) bool { - for _, b := range slice { - if b == a { - return true - } - } - return false -} - // RemoveStringFromSlice removes the first occurrence of a from slice. func RemoveStringFromSlice(a string, slice []string) []string { for i, str := range slice { @@ -40,7 +32,7 @@ func RemoveStringsFromSlice(slice []string, strings ...string) []string { newSlice := []string{} for _, item := range slice { - if !StringInSlice(item, strings) { + if !pUtils.Contains(strings, item) { newSlice = append(newSlice, item) } } diff --git a/server/cmd/mmctl/commands/sampledata.go b/server/cmd/mmctl/commands/sampledata.go index 0b1e0c5315..2d53aca190 100644 --- a/server/cmd/mmctl/commands/sampledata.go +++ b/server/cmd/mmctl/commands/sampledata.go @@ -19,7 +19,6 @@ import ( "github.com/mattermost/mattermost/server/v8/cmd/mmctl/printer" "github.com/mattermost/mattermost/server/v8/channels/app/imports" - "github.com/mattermost/mattermost/server/v8/channels/utils" "github.com/mattermost/mattermost/server/public/model" pUtils "github.com/mattermost/mattermost/server/public/utils" @@ -362,7 +361,7 @@ func sampledataCmdF(c client.Client, command *cobra.Command, args []string) erro totalUsers := 3 + rand.Intn(3) for len(users) < totalUsers { user := allUsers[rand.Intn(len(allUsers))] - if !utils.StringInSlice(user, users) { + if !pUtils.Contains(users, user) { users = append(users, user) } } @@ -377,7 +376,7 @@ func sampledataCmdF(c client.Client, command *cobra.Command, args []string) erro totalUsers := 3 + rand.Intn(3) for len(users) < totalUsers { user := allUsers[rand.Intn(len(allUsers))] - if !utils.StringInSlice(user, users) { + if !pUtils.Contains(users, user) { users = append(users, user) } } diff --git a/server/public/model/command_autocomplete.go b/server/public/model/command_autocomplete.go index 63092a59eb..d1fd08243d 100644 --- a/server/public/model/command_autocomplete.go +++ b/server/public/model/command_autocomplete.go @@ -11,6 +11,8 @@ import ( "strings" "github.com/pkg/errors" + + "github.com/mattermost/mattermost/server/public/utils" ) // AutocompleteArgType describes autocomplete argument type @@ -234,7 +236,7 @@ func (ad *AutocompleteData) IsValid() error { return errors.New("Command should be lowercase") } roles := []string{SystemAdminRoleId, SystemUserRoleId, ""} - if stringNotInSlice(ad.RoleID, roles) { + if !utils.Contains(roles, ad.RoleID) { return errors.New("Wrong role in the autocomplete data") } if len(ad.Arguments) > 0 && len(ad.SubCommands) > 0 { @@ -399,12 +401,3 @@ func (a *AutocompleteArg) UnmarshalJSON(b []byte) error { } return nil } - -func stringNotInSlice(a string, slice []string) bool { - for _, b := range slice { - if b == a { - return false - } - } - return true -} diff --git a/server/public/utils/utils.go b/server/public/utils/utils.go new file mode 100644 index 0000000000..fcadce230e --- /dev/null +++ b/server/public/utils/utils.go @@ -0,0 +1,14 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package utils + +// Contains returns true if the slice contains the item. +func Contains[T comparable](slice []T, item T) bool { + for _, s := range slice { + if s == item { + return true + } + } + return false +} diff --git a/server/public/utils/utils_test.go b/server/public/utils/utils_test.go new file mode 100644 index 0000000000..856f76886c --- /dev/null +++ b/server/public/utils/utils_test.go @@ -0,0 +1,388 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package utils_test + +import ( + "testing" + + "github.com/mattermost/mattermost/server/public/utils" +) + +func TestContains(t *testing.T) { + testCasesStr := []struct { + name string + slice []string + item string + expected bool + }{ + { + name: "empty slice", + slice: []string{}, + item: "foo", + expected: false, + }, + { + name: "slice with item", + slice: []string{"foo"}, + item: "foo", + expected: true, + }, + { + name: "slice without item", + slice: []string{"bar"}, + item: "foo", + expected: false, + }, + { + name: "slice with multiple items", + slice: []string{"foo", "bar"}, + item: "foo", + expected: true, + }, + { + name: "slice with multiple items without item", + slice: []string{"foo", "bar"}, + item: "baz", + expected: false, + }, + } + + for _, tc := range testCasesStr { + t.Run(tc.name, func(t *testing.T) { + actual := utils.Contains(tc.slice, tc.item) + if actual != tc.expected { + t.Errorf("Expected Contains(%v, %v) to be %v, but got %v", tc.slice, tc.item, tc.expected, actual) + } + }) + } + + testCasesInt := []struct { + name string + slice []int + item int + expected bool + }{ + { + name: "empty slice", + slice: []int{}, + item: 1, + expected: false, + }, + { + name: "slice with item", + slice: []int{1}, + item: 1, + expected: true, + }, + { + name: "slice without item", + slice: []int{2}, + item: 1, + expected: false, + }, + { + name: "slice with multiple items", + slice: []int{1, 2}, + item: 1, + expected: true, + }, + { + name: "slice with multiple items without item", + slice: []int{1, 2}, + item: 3, + expected: false, + }, + } + + for _, tc := range testCasesInt { + t.Run(tc.name, func(t *testing.T) { + actual := utils.Contains(tc.slice, tc.item) + if actual != tc.expected { + t.Errorf("Expected Contains(%v, %v) to be %v, but got %v", tc.slice, tc.item, tc.expected, actual) + } + }) + } + + testCasesFloat := []struct { + name string + slice []float64 + item float64 + expected bool + }{ + { + name: "empty slice", + slice: []float64{}, + item: 1.0, + expected: false, + }, + { + name: "slice with item", + slice: []float64{1.0}, + item: 1.0, + expected: true, + }, + { + name: "slice without item", + slice: []float64{2.0}, + item: 1.0, + expected: false, + }, + { + name: "slice with multiple items", + slice: []float64{1.0, 2.0}, + item: 1.0, + expected: true, + }, + { + name: "slice with multiple items without item", + slice: []float64{1.0, 2.0}, + item: 3.0, + expected: false, + }, + } + + for _, tc := range testCasesFloat { + t.Run(tc.name, func(t *testing.T) { + actual := utils.Contains(tc.slice, tc.item) + if actual != tc.expected { + t.Errorf("Expected Contains(%v, %v) to be %v, but got %v", tc.slice, tc.item, tc.expected, actual) + } + }) + } + + testCasesBool := []struct { + name string + slice []bool + item bool + expected bool + }{ + { + name: "empty slice", + slice: []bool{}, + item: true, + expected: false, + }, + { + name: "slice with item", + slice: []bool{true}, + item: true, + expected: true, + }, + { + name: "slice without item", + slice: []bool{false}, + item: true, + expected: false, + }, + { + name: "slice with multiple items", + slice: []bool{true, false}, + item: true, + expected: true, + }, + { + name: "slice with multiple items without item", + slice: []bool{true, false}, + item: false, + expected: true, + }, + } + + for _, tc := range testCasesBool { + t.Run(tc.name, func(t *testing.T) { + actual := utils.Contains(tc.slice, tc.item) + if actual != tc.expected { + t.Errorf("Expected Contains(%v, %v) to be %v, but got %v", tc.slice, tc.item, tc.expected, actual) + } + }) + } + + testCasesByte := []struct { + name string + slice []byte + item byte + expected bool + }{ + { + name: "empty slice", + slice: []byte{}, + item: 1, + expected: false, + }, + { + name: "slice with item", + slice: []byte{1}, + item: 1, + expected: true, + }, + { + name: "slice without item", + slice: []byte{2}, + item: 1, + expected: false, + }, + { + name: "slice with multiple items", + slice: []byte{1, 2}, + item: 1, + expected: true, + }, + { + name: "slice with multiple items without item", + slice: []byte{1, 2}, + item: 3, + expected: false, + }, + } + + for _, tc := range testCasesByte { + t.Run(tc.name, func(t *testing.T) { + actual := utils.Contains(tc.slice, tc.item) + if actual != tc.expected { + t.Errorf("Expected Contains(%v, %v) to be %v, but got %v", tc.slice, tc.item, tc.expected, actual) + } + }) + } + + testCasesRune := []struct { + name string + slice []rune + item rune + expected bool + }{ + { + name: "empty slice", + slice: []rune{}, + item: 1, + expected: false, + }, + { + name: "slice with item", + slice: []rune{1}, + item: 1, + expected: true, + }, + { + name: "slice without item", + slice: []rune{2}, + item: 1, + expected: false, + }, + { + name: "slice with multiple items", + slice: []rune{1, 2}, + item: 1, + expected: true, + }, + { + name: "slice with multiple items without item", + slice: []rune{1, 2}, + item: 3, + expected: false, + }, + } + + for _, tc := range testCasesRune { + t.Run(tc.name, func(t *testing.T) { + actual := utils.Contains(tc.slice, tc.item) + if actual != tc.expected { + t.Errorf("Expected Contains(%v, %v) to be %v, but got %v", tc.slice, tc.item, tc.expected, actual) + } + }) + } + + testCasesComplex := []struct { + name string + slice []complex128 + item complex128 + expected bool + }{ + { + name: "empty slice", + slice: []complex128{}, + item: 1, + expected: false, + }, + { + name: "slice with item", + slice: []complex128{1}, + item: 1, + expected: true, + }, + { + name: "slice without item", + slice: []complex128{2}, + item: 1, + expected: false, + }, + { + name: "slice with multiple items", + slice: []complex128{1, 2}, + item: 1, + expected: true, + }, + { + name: "slice with multiple items without item", + slice: []complex128{1, 2}, + item: 3, + expected: false, + }, + } + + for _, tc := range testCasesComplex { + t.Run(tc.name, func(t *testing.T) { + actual := utils.Contains(tc.slice, tc.item) + if actual != tc.expected { + t.Errorf("Expected Contains(%v, %v) to be %v, but got %v", tc.slice, tc.item, tc.expected, actual) + } + }) + } + + testCasesUint := []struct { + name string + slice []uint + item uint + expected bool + }{ + { + name: "empty slice", + slice: []uint{}, + item: 1, + expected: false, + }, + { + name: "slice with item", + slice: []uint{1}, + item: 1, + expected: true, + }, + { + name: "slice without item", + slice: []uint{2}, + item: 1, + expected: false, + }, + { + name: "slice with multiple items", + slice: []uint{1, 2}, + item: 1, + expected: true, + }, + { + name: "slice with multiple items without item", + slice: []uint{1, 2}, + item: 3, + expected: false, + }, + } + + for _, tc := range testCasesUint { + t.Run(tc.name, func(t *testing.T) { + actual := utils.Contains(tc.slice, tc.item) + if actual != tc.expected { + t.Errorf("Expected Contains(%v, %v) to be %v, but got %v", tc.slice, tc.item, tc.expected, actual) + } + }) + } +}